Initial commit of files
This commit is contained in:
71
src/libnet/CMakeLists.txt
Normal file
71
src/libnet/CMakeLists.txt
Normal file
@ -0,0 +1,71 @@
|
||||
cmake_minimum_required(VERSION 3.7)
|
||||
set(NAME net)
|
||||
set(TARGET lib${NAME})
|
||||
project(Cnomicon-${TARGET})
|
||||
set(CMAKE_INSTALL_PREFIX ..)
|
||||
set(LIBRARY ${TARGET})
|
||||
|
||||
# list of header files
|
||||
set(LIBH
|
||||
memlib.h
|
||||
netlib.h
|
||||
strlib.h
|
||||
)
|
||||
|
||||
# list of source files
|
||||
set(LIBSRC
|
||||
fd_selector.c
|
||||
fd_utils.c
|
||||
io_serial.c
|
||||
ip_hostaddr.c
|
||||
ip_hostname.c
|
||||
ip_servport.c
|
||||
ip_sockname.c
|
||||
log_file.c
|
||||
mac_address.c
|
||||
mem_safe.c
|
||||
msleep.c
|
||||
pid_file.c
|
||||
sig_rt.c
|
||||
strlcat.c
|
||||
strlcpy.c
|
||||
tcp_accept.c
|
||||
tcp_client.c
|
||||
tcp_nagle.c
|
||||
tcp_recv.c
|
||||
tcp_send.c
|
||||
tcp_server.c
|
||||
udp_broadcast.c
|
||||
udp_client.c
|
||||
udp_listener.c
|
||||
udp_multicast.c
|
||||
udp_recvfrom.c
|
||||
# udp_sendmcast.c
|
||||
udp_sendto.c
|
||||
udp_server.c
|
||||
udp_socket.c
|
||||
uds_client.c
|
||||
uds_server.c
|
||||
uri_parse.c
|
||||
)
|
||||
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../lib)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../lib)
|
||||
|
||||
# this is the "object library" target: compiles the sources only once
|
||||
add_library(${LIBRARY} OBJECT ${LIBSRC})
|
||||
|
||||
# shared libraries need PIC
|
||||
set_property(TARGET ${LIBRARY} PROPERTY POSITION_INDEPENDENT_CODE 1)
|
||||
|
||||
# shared and static libraries built from the same object files
|
||||
add_library(${LIBRARY}-shared SHARED $<TARGET_OBJECTS:${LIBRARY}>)
|
||||
add_library(${LIBRARY}-static STATIC $<TARGET_OBJECTS:${LIBRARY}>)
|
||||
|
||||
# output file names
|
||||
set_target_properties(${LIBRARY}-shared PROPERTIES OUTPUT_NAME ${NAME})
|
||||
set_target_properties(${LIBRARY}-static PROPERTIES OUTPUT_NAME ${NAME})
|
||||
|
||||
# installations
|
||||
install (FILES ${LIBH} DESTINATION include)
|
||||
#install (FILES lib${NAME}.a lib${NAME}.so DESTINATION lib)
|
||||
43
src/libnet/fd_selector.c
Normal file
43
src/libnet/fd_selector.c
Normal file
@ -0,0 +1,43 @@
|
||||
#include "netlib.h"
|
||||
|
||||
#define max(A,B) ((A)>=(B)?(A):(B))
|
||||
|
||||
int selector( int *nfds, fd_set *rfds, fd_set *wfds, long usec )
|
||||
{
|
||||
// descriptor count
|
||||
int n = 0;
|
||||
if ( !nfds )
|
||||
{
|
||||
// maximum
|
||||
n = getdtablesize();
|
||||
}
|
||||
else if ( ! *nfds )
|
||||
{
|
||||
n = fd_count(rfds);
|
||||
int m = fd_count(wfds);
|
||||
n = max( n, m );
|
||||
}
|
||||
else
|
||||
n = *nfds;
|
||||
|
||||
if( nfds )
|
||||
*nfds = n;
|
||||
|
||||
// timeout
|
||||
struct timeval timeout;
|
||||
if ( usec )
|
||||
{
|
||||
timeout.tv_sec = usec / 1000000;
|
||||
timeout.tv_usec = usec % 1000000;
|
||||
}
|
||||
|
||||
// do it
|
||||
int rc = select( n, rfds, wfds, NULL, usec ? &timeout:NULL );
|
||||
|
||||
if ( rc < 0 )
|
||||
{
|
||||
// error
|
||||
log_error( "select" );
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
47
src/libnet/fd_utils.c
Normal file
47
src/libnet/fd_utils.c
Normal file
@ -0,0 +1,47 @@
|
||||
#include "netlib.h"
|
||||
|
||||
#define max(A,B) ((A)>=(B)?(A):(B))
|
||||
|
||||
int fd_add( int sock, fd_set *pfds, int nfds )
|
||||
{
|
||||
if ( sock < 0 )
|
||||
return nfds;
|
||||
|
||||
// set it
|
||||
if ( pfds )
|
||||
FD_SET(sock, pfds);
|
||||
|
||||
// fix #
|
||||
if ( nfds < sock + 1 )
|
||||
nfds = sock + 1;
|
||||
|
||||
return nfds;
|
||||
}
|
||||
|
||||
int fd_count( fd_set *pfds )
|
||||
{
|
||||
// optimal number of descriptors
|
||||
int i, n = 0;
|
||||
|
||||
if ( !pfds )
|
||||
return 0;
|
||||
|
||||
for ( i=0 ; i<getdtablesize() ; i++ )
|
||||
{
|
||||
if ( FD_ISSET(i, pfds) )
|
||||
n = i;
|
||||
}
|
||||
return n + 1;
|
||||
}
|
||||
|
||||
int fd_del( int sock, fd_set *pfds, int nfds )
|
||||
{
|
||||
// clear it
|
||||
FD_CLR(sock, pfds);
|
||||
|
||||
if ( !nfds )
|
||||
nfds = fd_count(pfds);
|
||||
|
||||
return nfds;
|
||||
}
|
||||
|
||||
110
src/libnet/io_serial.c
Normal file
110
src/libnet/io_serial.c
Normal file
@ -0,0 +1,110 @@
|
||||
#include "netlib.h"
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
int serial_open( char *tty, int ttybaud, int blocksz, int waittime )
|
||||
{
|
||||
int fd;
|
||||
struct termios termios;
|
||||
|
||||
// open non-blocking, to allow use of select()
|
||||
fd = open(tty, O_RDWR | O_NONBLOCK | O_NOCTTY );
|
||||
if (fd < 0)
|
||||
{
|
||||
log_error("open");
|
||||
return (-1);
|
||||
}
|
||||
if (tcgetattr(fd, &termios) < 0)
|
||||
{
|
||||
// not a serial port
|
||||
log_error("tcgetattr");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* zap special chars */
|
||||
int cnt;
|
||||
|
||||
for (cnt = 0; cnt < NCCS; cnt++)
|
||||
termios.c_cc[cnt] = -1;
|
||||
|
||||
/* default control flags */
|
||||
termios.c_iflag = 0;
|
||||
termios.c_oflag = 0; /* (ONLRET) */
|
||||
termios.c_cflag = CS8 | CLOCAL | CREAD;
|
||||
termios.c_lflag = 0;
|
||||
|
||||
/* canonical or not? */
|
||||
if ( blocksz <= 0 && waittime <= 0 )
|
||||
{
|
||||
/* assume canonical (ascii) */
|
||||
termios.c_lflag = ICANON;
|
||||
termios.c_cc[VEOL] = '\n';
|
||||
|
||||
termios.c_cc[VMIN] = 0;
|
||||
termios.c_cc[VTIME] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* non-canonical (binary) */
|
||||
termios.c_cc[VMIN] = blocksz;
|
||||
termios.c_cc[VTIME] = waittime; // x100 msec
|
||||
}
|
||||
|
||||
/* baud rates */
|
||||
switch (ttybaud)
|
||||
{
|
||||
case 300:
|
||||
ttybaud = B300;
|
||||
break;
|
||||
case 1200:
|
||||
ttybaud = B1200;
|
||||
break;
|
||||
case 2400:
|
||||
ttybaud = B2400;
|
||||
break;
|
||||
case 4800:
|
||||
ttybaud = B4800;
|
||||
break;
|
||||
case 9600:
|
||||
ttybaud = B9600;
|
||||
break;
|
||||
case 19200:
|
||||
ttybaud = B19200;
|
||||
break;
|
||||
case 38400:
|
||||
ttybaud = B38400;
|
||||
break;
|
||||
case 57600:
|
||||
ttybaud = B57600;
|
||||
break;
|
||||
case 115200:
|
||||
ttybaud = B115200;
|
||||
break;
|
||||
case 230400:
|
||||
ttybaud = B230400;
|
||||
break;
|
||||
default:
|
||||
ttybaud = B9600;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cfsetispeed(&termios, ttybaud) != 0) {
|
||||
log_error("cfsetispeed");
|
||||
return (-1);
|
||||
}
|
||||
if (cfsetospeed(&termios, ttybaud) != 0) {
|
||||
log_error("cfsetospeed");
|
||||
return (-1);
|
||||
}
|
||||
if (tcsetattr(fd, TCSANOW, &termios) < 0) {
|
||||
log_error("tcsetattr");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#if WANT_BLOCKING_READ
|
||||
if (fcntl(fd, F_SETFL, 0) == -1) {
|
||||
log_error("fcntl: set nonblock");
|
||||
}
|
||||
#endif
|
||||
return (fd);
|
||||
}
|
||||
57
src/libnet/ip_hostaddr.c
Normal file
57
src/libnet/ip_hostaddr.c
Normal file
@ -0,0 +1,57 @@
|
||||
//
|
||||
// IP gethostname
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
int ip_host2addr( const char *host, const char *service, struct sockaddr_storage *sa, socklen_t *len )
|
||||
{
|
||||
struct hostent *ent;
|
||||
|
||||
/* do host lookup matching family (this is not POSIX) */
|
||||
if ( (ent = gethostbyname2( host, AF_INET6 )) == NULL )
|
||||
{
|
||||
if ( (ent = gethostbyname2( host, AF_INET )) == NULL )
|
||||
{
|
||||
log_error( "gethostbyname" );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
int family = ent->h_addrtype;
|
||||
|
||||
// service
|
||||
int port = ip_service2port( service, atoi(service), NULL );
|
||||
|
||||
/* clear and initialize address structure */
|
||||
if ( sa )
|
||||
bzero(sa, sizeof(struct sockaddr_storage) );
|
||||
|
||||
if ( family == AF_INET6 )
|
||||
{
|
||||
if ( sa )
|
||||
{
|
||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
|
||||
sa6->sin6_family = family;
|
||||
sa6->sin6_port = port;
|
||||
sa6->sin6_addr = *((struct in6_addr *)ent->h_addr);
|
||||
}
|
||||
if ( len )
|
||||
*len = sizeof(struct sockaddr_in6);
|
||||
}
|
||||
else if ( family == AF_INET )
|
||||
{
|
||||
if ( sa )
|
||||
{
|
||||
struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
|
||||
sa4->sin_family = family;
|
||||
sa4->sin_port = port;
|
||||
sa4->sin_addr = *((struct in_addr *)ent->h_addr);
|
||||
}
|
||||
if ( len )
|
||||
*len = sizeof(struct sockaddr_in);
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
return family;
|
||||
}
|
||||
45
src/libnet/ip_hostname.c
Normal file
45
src/libnet/ip_hostname.c
Normal file
@ -0,0 +1,45 @@
|
||||
//
|
||||
// IP gethostname
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
const char *ip_host2name( char *buf, int max, const struct sockaddr_storage *sa )
|
||||
{
|
||||
const char *s = NULL;
|
||||
|
||||
switch (sa->ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
s = inet_ntop(sa->ss_family,
|
||||
&((struct sockaddr_in *)sa)->sin_addr,
|
||||
buf, max);
|
||||
break;
|
||||
case AF_INET6:
|
||||
s = inet_ntop(sa->ss_family,
|
||||
&((struct sockaddr_in6 *)sa)->sin6_addr,
|
||||
buf, max);
|
||||
break;
|
||||
}
|
||||
if ( s )
|
||||
return s;
|
||||
|
||||
return strerror(errno);
|
||||
}
|
||||
|
||||
int ip_name2host( const char *buf, struct sockaddr_storage *sa )
|
||||
{
|
||||
// from string
|
||||
switch (sa->ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
return inet_pton(sa->ss_family, buf,
|
||||
&((struct sockaddr_in *)sa)->sin_addr );
|
||||
break;
|
||||
case AF_INET6:
|
||||
return inet_pton(sa->ss_family, buf,
|
||||
&((struct sockaddr_in6 *)sa)->sin6_addr );
|
||||
break;
|
||||
}
|
||||
return EAFNOSUPPORT;
|
||||
}
|
||||
22
src/libnet/ip_servport.c
Normal file
22
src/libnet/ip_servport.c
Normal file
@ -0,0 +1,22 @@
|
||||
//
|
||||
// IP Service -> Port
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
int ip_service2port( const char *service, int port, const char *proto )
|
||||
{
|
||||
/* socket stuff */
|
||||
struct servent *serv; /* service entry from /etc/services */
|
||||
|
||||
/* check args */
|
||||
if ( port )
|
||||
serv = getservbyport( htons(port), proto );
|
||||
else if ( service )
|
||||
serv = getservbyname( service, proto );
|
||||
|
||||
// return network byte order
|
||||
if ( serv )
|
||||
return serv->s_port;
|
||||
return htons(port);
|
||||
}
|
||||
20
src/libnet/ip_sockname.c
Normal file
20
src/libnet/ip_sockname.c
Normal file
@ -0,0 +1,20 @@
|
||||
//
|
||||
// Socket address
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
int ip_sockname( int sock, struct sockaddr_storage *sa )
|
||||
{
|
||||
if ( !sa )
|
||||
return -1;
|
||||
|
||||
bzero( sa, sizeof(struct sockaddr_storage) );
|
||||
|
||||
/* address info */
|
||||
socklen_t l = sizeof(struct sockaddr_storage);
|
||||
if ( getsockname( sock, (struct sockaddr *)&sa, &l ) < 0 )
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
100
src/libnet/log_file.c
Normal file
100
src/libnet/log_file.c
Normal file
@ -0,0 +1,100 @@
|
||||
//
|
||||
// Logging
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
#include "strlib.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
static char szLogPath[MAXPATHLEN-5] = "/var/log/" VAR_LOG_RUN_NAME "/";
|
||||
static char szLogFile[MAXPATHLEN-5];
|
||||
static FILE *pLog = NULL;
|
||||
static char bLogFlag = 1;
|
||||
|
||||
void log_on(void)
|
||||
{
|
||||
bLogFlag = 1;
|
||||
}
|
||||
|
||||
void log_off(void)
|
||||
{
|
||||
bLogFlag = 0;
|
||||
}
|
||||
|
||||
void log_exit( void )
|
||||
{
|
||||
if ( pLog )
|
||||
{
|
||||
log_printf( "Closed logfile (euid = %d.%d)", geteuid(), getegid() );
|
||||
fclose( pLog );
|
||||
}
|
||||
}
|
||||
|
||||
void log_path( const char *pszPath )
|
||||
{
|
||||
strlcpy( szLogPath, pszPath, sizeof(szLogPath) );
|
||||
}
|
||||
|
||||
FILE *log_open( const char *pszFile )
|
||||
{
|
||||
mkdir(szLogPath, 0776);
|
||||
snprintf(szLogFile, MAXPATHLEN-1, "%s%s.log", szLogPath, pszFile);
|
||||
|
||||
if ( (pLog = fopen( szLogFile, "a" )) )
|
||||
{
|
||||
log_printf( "Opened logfile: %s (uid = %d.%d)", szLogFile, getuid(), getgid() );
|
||||
atexit( log_exit );
|
||||
}
|
||||
else
|
||||
{
|
||||
perror( szLogFile );
|
||||
}
|
||||
return pLog;
|
||||
}
|
||||
|
||||
void log_write( const char *msg )
|
||||
{
|
||||
if ( !pLog || !bLogFlag || !msg || !strlen(msg) )
|
||||
return;
|
||||
|
||||
/* time stamp it */
|
||||
time_t t = time(NULL);
|
||||
struct tm *tm = localtime( &t );
|
||||
char szBuf[30];
|
||||
strftime( szBuf, sizeof(szBuf), "%F %T ", tm );
|
||||
|
||||
fprintf( pLog, "%s %s\n", szBuf, msg );
|
||||
fflush( pLog );
|
||||
}
|
||||
|
||||
void log_printf( const char *fmt, ... )
|
||||
{
|
||||
va_list ap;
|
||||
if ( !pLog || !bLogFlag || !fmt )
|
||||
return;
|
||||
|
||||
/* time stamp it */
|
||||
time_t t = time(NULL);
|
||||
struct tm *tm = localtime( &t );
|
||||
char szBuf[30];
|
||||
strftime( szBuf, sizeof(szBuf), "%F %T ", tm );
|
||||
fprintf( pLog, "%s", szBuf );
|
||||
|
||||
va_start( ap, fmt );
|
||||
vfprintf( pLog, fmt, ap );
|
||||
va_end( ap );
|
||||
fputs( "\n", pLog );
|
||||
fflush( pLog );
|
||||
}
|
||||
|
||||
void log_error( const char *msg )
|
||||
{
|
||||
perror(msg);
|
||||
log_printf( "%s (%s)", msg, strerror(errno) );
|
||||
}
|
||||
75
src/libnet/mac_address.c
Normal file
75
src/libnet/mac_address.c
Normal file
@ -0,0 +1,75 @@
|
||||
//
|
||||
// IP getmacaddr
|
||||
//
|
||||
|
||||
#include "strlib.h"
|
||||
#include "netlib.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/sockios.h>
|
||||
|
||||
int mac_interface2macaddr( const char *name, unsigned char *mac )
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( !name )
|
||||
name = "eth0";
|
||||
|
||||
// MAC address (should be temporary)
|
||||
int fd;
|
||||
|
||||
if ( (fd = socket(AF_INET6, SOCK_DGRAM, 0)) )
|
||||
{
|
||||
struct ifreq ifr;
|
||||
bzero(&ifr, sizeof(ifr));
|
||||
ifr.ifr_addr.sa_family = AF_INET6;
|
||||
strncpy(ifr.ifr_name, name, IFNAMSIZ-1);
|
||||
|
||||
if ( ioctl(fd, SIOCGIFHWADDR, &ifr) == 0 )
|
||||
{
|
||||
for ( i=0 ; i<6 ; i++ )
|
||||
*mac++ = ifr.ifr_hwaddr.sa_data[i];
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mac_string2mac( const char *str, unsigned char *mac )
|
||||
{
|
||||
// exact 00:00:00:00:00:00 string
|
||||
char buf[25];
|
||||
bzero(buf, sizeof(buf));
|
||||
strncpy(buf, str, sizeof(buf)-1);
|
||||
|
||||
char *s, *t;
|
||||
t = strtok_r(buf, ":", &s);
|
||||
int n = 0;
|
||||
|
||||
while ( t )
|
||||
{
|
||||
// decode
|
||||
char *e;
|
||||
*mac++ = (unsigned char) strtol( t, &e, 16 );
|
||||
n++;
|
||||
|
||||
// invalid decode
|
||||
if ( *e )
|
||||
return 0;
|
||||
|
||||
t = strtok_r(NULL, ":", &s);
|
||||
}
|
||||
|
||||
if ( n == 6 )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mac_mac2string( const unsigned char *mac, char *str )
|
||||
{
|
||||
// exact 00:00:00:00:00:00 string
|
||||
return sprintf( str, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
*mac, *(mac+1), *(mac+2), *(mac+3), *(mac+4), *(mac+5) );
|
||||
}
|
||||
16
src/libnet/mem_safe.c
Normal file
16
src/libnet/mem_safe.c
Normal file
@ -0,0 +1,16 @@
|
||||
#include "memlib.h"
|
||||
|
||||
inline void memcpy_s(void *dest, size_t max, const void *src, size_t count)
|
||||
{
|
||||
if (count > max)
|
||||
count = max;
|
||||
memcpy(dest, src, count);
|
||||
}
|
||||
|
||||
inline void memmove_s(void *dest, size_t max, const void *src, size_t count)
|
||||
{
|
||||
if (count > max)
|
||||
count = max;
|
||||
memmove(dest, src, count);
|
||||
}
|
||||
|
||||
39
src/libnet/memlib.h
Normal file
39
src/libnet/memlib.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef __MEMLIB_INCLUDE__
|
||||
#define __MEMLIB_INCLUDE__
|
||||
|
||||
/******************************************************************************
|
||||
* includes
|
||||
*****************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <memory.h>
|
||||
|
||||
//#pragma deprecated (memcpy, memmove)
|
||||
|
||||
/******************************************************************************
|
||||
* defines
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* structs & typedefs
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* function prototypes
|
||||
*****************************************************************************/
|
||||
/* export C functions to C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void memcpy_s(void *dest, size_t max, const void *src, size_t count);
|
||||
void memmove_s(void *dest, size_t max, const void *src, size_t count);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/******************************************************************************
|
||||
* Macros
|
||||
* ***************************************************************************/
|
||||
|
||||
#endif
|
||||
17
src/libnet/msleep.c
Normal file
17
src/libnet/msleep.c
Normal file
@ -0,0 +1,17 @@
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
int msleep(unsigned long msec)
|
||||
{
|
||||
struct timespec req={0};
|
||||
time_t sec=(int)(msec/1000);
|
||||
msec=msec-(sec*1000);
|
||||
req.tv_sec=sec;
|
||||
req.tv_nsec=msec*1000000L;
|
||||
while(nanosleep(&req,&req)==-1)
|
||||
continue;
|
||||
return 1;
|
||||
}
|
||||
|
||||
140
src/libnet/netlib.h
Normal file
140
src/libnet/netlib.h
Normal file
@ -0,0 +1,140 @@
|
||||
#ifndef __NETLIB_INCLUDE__
|
||||
#define __NETLIB_INCLUDE__
|
||||
|
||||
/******************************************************************************
|
||||
* includes
|
||||
*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <netdb.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "strlib.h"
|
||||
|
||||
/******************************************************************************
|
||||
* defines
|
||||
*****************************************************************************/
|
||||
|
||||
#define VAR_LOG_RUN_NAME "cnomicon"
|
||||
|
||||
/******************************************************************************
|
||||
* structs & typedefs
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct _uri_parts {
|
||||
char proto[8];
|
||||
char user[16];
|
||||
char pass[16];
|
||||
char host[256];
|
||||
char port[16];
|
||||
char path[1204];
|
||||
int rate;
|
||||
} uri_parts;
|
||||
|
||||
/******************************************************************************
|
||||
* function prototypes
|
||||
*****************************************************************************/
|
||||
/* export C functions to C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* File */
|
||||
int fd_add( int sock, fd_set *pfds, int nfds );
|
||||
int fd_count( fd_set *pfds );
|
||||
int selector( int *nfds, fd_set *rfds, fd_set *wfds, long usec );
|
||||
|
||||
/* Runtime */
|
||||
void log_path( const char * );
|
||||
FILE *log_open( const char * );
|
||||
void log_write( const char * );
|
||||
void log_printf( const char *, ... );
|
||||
void log_error( const char * );
|
||||
void log_on(void);
|
||||
void log_off(void);
|
||||
void pid_path( const char * );
|
||||
int pid_create( const char * );
|
||||
void pid_delete( void );
|
||||
|
||||
/* Serial I/O */
|
||||
int serial_open( char *tty, int baud, int vmin, int vwait );
|
||||
|
||||
/* Signals */
|
||||
int sigrt_alloc(void);
|
||||
void sigrt_free(int sig);
|
||||
|
||||
/* TCP/IP Basics */
|
||||
int ip_host2addr( const char *host, const char *service, struct sockaddr_storage *ss, socklen_t *len );
|
||||
const char *ip_host2name( char *buf, int max, const struct sockaddr_storage *ss);
|
||||
int ip_name2host( const char *buf, struct sockaddr_storage *ss);
|
||||
int ip_service2port( const char *service, int port, const char *proto );
|
||||
int ip_sockname( int sock, struct sockaddr_storage *ss );
|
||||
|
||||
/* MAC Address */
|
||||
int mac_interface2macaddr( const char *, unsigned char * );
|
||||
int mac_string2mac( const char *str, unsigned char *mac );
|
||||
int mac_mac2string( const unsigned char *mac, char *str );
|
||||
|
||||
/* TCP Server */
|
||||
int tcp_server( const char *host, const char *service );
|
||||
int tcp_accept( int sock, struct sockaddr_storage *ss );
|
||||
|
||||
/* TCP Client */
|
||||
int tcp_client( const char *host, const char *service );
|
||||
int tcp_nagle( int sock, int flag );
|
||||
|
||||
/* TCP I/O */
|
||||
int tcp_recv( int sock, void *buf, int len );
|
||||
int tcp_send( int sock, const char *buf, int len );
|
||||
int tcp_sendstr( int sock, const char *str );
|
||||
|
||||
/* UDP Server */
|
||||
int udp_server( const char *host, const char *service );
|
||||
int udp_client( const char *host, const char *service );
|
||||
int udp_socket( const char *host, const char *service );
|
||||
|
||||
/* UDP Broadcast */
|
||||
int udp_broadcast( const char *host, const char *service, struct sockaddr_storage *, socklen_t *);
|
||||
int udp_multicast( const char *host, const char *service, struct sockaddr_storage *, socklen_t *);
|
||||
int udp_listener( const char *host, const char *service );
|
||||
|
||||
/* UDP I/O */
|
||||
int udp_recvfrom( int sock, void *buf, int n, struct sockaddr_storage *, socklen_t *len );
|
||||
int udp_sendto( int sock, const char *buf, int n, const struct sockaddr_storage *, int len );
|
||||
int udp_sendstr( int sock, const char *buf, const struct sockaddr_storage *, int len );
|
||||
|
||||
/* Unix Domain Socket (UDS) */
|
||||
int uds_client( const char *file );
|
||||
int uds_server( const char *file );
|
||||
|
||||
/* URI */
|
||||
void uri_clear( uri_parts *parsed );
|
||||
void uri_defaults( uri_parts *parsed );
|
||||
int uri_parse( const char *uri, uri_parts *parsed );
|
||||
|
||||
/* misc */
|
||||
int msleep(unsigned long msec);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/******************************************************************************
|
||||
* Macros
|
||||
* ***************************************************************************/
|
||||
|
||||
// connected udp socket
|
||||
#define udp_send(S,B,L) tcp_send(S,B,L)
|
||||
#define uds_recv(S,B,L) tcp_recv(S,B,L)
|
||||
#define uds_send(S,B,L) tcp_send(S,B,L)
|
||||
|
||||
#endif
|
||||
43
src/libnet/pid_file.c
Normal file
43
src/libnet/pid_file.c
Normal file
@ -0,0 +1,43 @@
|
||||
//
|
||||
// Pid file
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
#include "strlib.h"
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
static char szPidPath[MAXPATHLEN-5] = "/var/run/" VAR_LOG_RUN_NAME "/";
|
||||
static char szPidFile[MAXPATHLEN-5] = "/tmp/not-a-file";
|
||||
|
||||
void pid_path( const char *pszPath )
|
||||
{
|
||||
strlcpy( szPidPath, pszPath, sizeof(szPidPath) );
|
||||
}
|
||||
|
||||
void pid_delete( void )
|
||||
{
|
||||
unlink( szPidFile );
|
||||
}
|
||||
|
||||
int pid_create( const char *pszFile )
|
||||
{
|
||||
FILE *pPid;
|
||||
|
||||
mkdir(szPidPath, 0776);
|
||||
snprintf(szPidFile, MAXPATHLEN-1, "%s%s.pid", szPidPath, pszFile);
|
||||
|
||||
if ( (pPid = fopen( szPidFile, "w" )) )
|
||||
{
|
||||
fprintf( pPid, "%d", getpid() );
|
||||
fclose( pPid );
|
||||
|
||||
atexit( pid_delete );
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
perror( szPidFile );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
51
src/libnet/sig_rt.c
Normal file
51
src/libnet/sig_rt.c
Normal file
@ -0,0 +1,51 @@
|
||||
//
|
||||
// signal table
|
||||
//
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
static unsigned char s_init = 0;
|
||||
static unsigned char signal_list[32] = {0};
|
||||
|
||||
static void sigrt_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for ( i=0 ; i<sizeof(signal_list) ; i++ )
|
||||
{
|
||||
int sig = SIGRTMIN + i + 1;
|
||||
if ( sig <= SIGRTMAX )
|
||||
signal_list[i] = sig;
|
||||
else
|
||||
break;
|
||||
}
|
||||
s_init = 1;
|
||||
}
|
||||
|
||||
int sigrt_alloc(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( !s_init )
|
||||
sigrt_init();
|
||||
|
||||
for ( i=0 ; i<sizeof(signal_list) ; i++ )
|
||||
{
|
||||
if ( signal_list[i] )
|
||||
{
|
||||
int sig = signal_list[i];
|
||||
signal_list[i] = 0;
|
||||
return sig;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sigrt_free(int sig)
|
||||
{
|
||||
if ( sig <= SIGRTMIN || sig > SIGRTMAX )
|
||||
return;
|
||||
|
||||
if ( signal_list[sig-SIGRTMIN-1] == 0 )
|
||||
signal_list[sig-SIGRTMIN-1] = sig;
|
||||
}
|
||||
40
src/libnet/strlcat.c
Normal file
40
src/libnet/strlcat.c
Normal file
@ -0,0 +1,40 @@
|
||||
#include "strlib.h"
|
||||
|
||||
/*
|
||||
* * Appends src to string dst of size siz (unlike strncat, siz is the
|
||||
* * full size of dst, not space left). At most siz-1 characters
|
||||
* * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
||||
* * Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||
* * If retval >= siz, truncation occurred.
|
||||
* */
|
||||
size_t
|
||||
strlcat(dst, src, siz)
|
||||
char *dst;
|
||||
const char *src;
|
||||
size_t siz;
|
||||
{
|
||||
register char *d = dst;
|
||||
register const char *s = src;
|
||||
register size_t n = siz;
|
||||
size_t dlen;
|
||||
|
||||
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||
while (n-- != 0 && *d != '\0')
|
||||
d++;
|
||||
dlen = d - dst;
|
||||
n = siz - dlen;
|
||||
|
||||
if (n == 0)
|
||||
return(dlen + strlen(s));
|
||||
while (*s != '\0') {
|
||||
if (n != 1) {
|
||||
*d++ = *s;
|
||||
n--;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
*d = '\0';
|
||||
|
||||
return(dlen + (s - src)); /* count does not include NUL */
|
||||
}
|
||||
|
||||
33
src/libnet/strlcpy.c
Normal file
33
src/libnet/strlcpy.c
Normal file
@ -0,0 +1,33 @@
|
||||
#include "strlib.h"
|
||||
|
||||
/*
|
||||
* * Copy src to string dst of size siz. At most siz-1 characters
|
||||
* * will be copied. Always NUL terminates (unless siz == 0).
|
||||
* * Returns strlen(src); if retval >= siz, truncation occurred.
|
||||
* */
|
||||
size_t
|
||||
strlcpy(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = siz;
|
||||
|
||||
/* Copy as many bytes as will fit */
|
||||
if (n != 0) {
|
||||
while (--n != 0) {
|
||||
if ((*d++ = *s++) == '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not enough room in dst, add NUL and traverse rest of src */
|
||||
if (n == 0) {
|
||||
if (siz != 0)
|
||||
*d = '\0'; /* NUL-terminate dst */
|
||||
while (*s++)
|
||||
;
|
||||
}
|
||||
|
||||
return(s - src - 1); /* count does not include NUL */
|
||||
}
|
||||
|
||||
40
src/libnet/strlib.h
Normal file
40
src/libnet/strlib.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef __STRLIB_INCLUDE__
|
||||
#define __STRLIB_INCLUDE__
|
||||
|
||||
/******************************************************************************
|
||||
* includes
|
||||
*****************************************************************************/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
//#pragma deprecated (strcpy, strcat)
|
||||
|
||||
/******************************************************************************
|
||||
* defines
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* structs & typedefs
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* function prototypes
|
||||
*****************************************************************************/
|
||||
/* export C functions to C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
size_t strlcat(char *dst, const char *src, size_t siz);
|
||||
size_t strlcpy(char *dst, const char *src, size_t siz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/******************************************************************************
|
||||
* Macros
|
||||
* ***************************************************************************/
|
||||
|
||||
#endif
|
||||
46
src/libnet/tcp_accept.c
Normal file
46
src/libnet/tcp_accept.c
Normal file
@ -0,0 +1,46 @@
|
||||
//
|
||||
// TCP Accept
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
#include "strlib.h"
|
||||
|
||||
int tcp_accept( int sock, struct sockaddr_storage *sa )
|
||||
{
|
||||
/* storage? */
|
||||
struct sockaddr_storage ss;
|
||||
if ( !sa )
|
||||
sa = &ss;
|
||||
|
||||
/* tcp request */
|
||||
socklen_t len = sizeof(struct sockaddr_storage);
|
||||
|
||||
/* accept the incoming connection */
|
||||
int cs = accept(sock, (struct sockaddr *)sa, &len );
|
||||
|
||||
/* check for errors. if any, ignore new connection */
|
||||
if (cs < 0 )
|
||||
{
|
||||
log_error("tcp_accept");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* turn off nagle, writes are shipped immediately */
|
||||
int flag = 1;
|
||||
setsockopt( cs, /* socket affected */
|
||||
IPPROTO_TCP, /* set option at TCP level */
|
||||
TCP_NODELAY, /* name of option */
|
||||
(char *) &flag, /* the cast is historical cruft */
|
||||
sizeof(int)); /* length of option value */
|
||||
|
||||
/* log new client */
|
||||
if ( cs > 0 )
|
||||
{
|
||||
char szBuf[256];
|
||||
ip_host2name( szBuf, sizeof(szBuf), sa );
|
||||
strlcat( szBuf, " client connected", sizeof(szBuf) );
|
||||
log_write( szBuf );
|
||||
}
|
||||
|
||||
return cs;
|
||||
}
|
||||
36
src/libnet/tcp_client.c
Normal file
36
src/libnet/tcp_client.c
Normal file
@ -0,0 +1,36 @@
|
||||
//
|
||||
// TCP Client Connect
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
int tcp_client( const char *host, const char *service )
|
||||
{
|
||||
int sock, family;
|
||||
struct sockaddr_storage sa;
|
||||
socklen_t len = sizeof(sa);
|
||||
|
||||
/* default IPv6 localhost */
|
||||
if ( !host || !strlen(host) )
|
||||
host = "ip6-localhost";
|
||||
|
||||
/* lookup */
|
||||
family = ip_host2addr( host, service, &sa, &len );
|
||||
|
||||
/* socket */
|
||||
sock = socket(family, SOCK_STREAM, 0);
|
||||
if (sock < 0)
|
||||
{
|
||||
log_error( "socket" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* connect */
|
||||
if ( connect(sock, (struct sockaddr *)&sa, len) != 0 )
|
||||
{
|
||||
close(sock);
|
||||
log_error( "connect" );
|
||||
return -1;
|
||||
}
|
||||
return sock;
|
||||
}
|
||||
16
src/libnet/tcp_nagle.c
Normal file
16
src/libnet/tcp_nagle.c
Normal file
@ -0,0 +1,16 @@
|
||||
//
|
||||
// TCP Nagle'ing
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
int tcp_nagle( int sock, int flag )
|
||||
{
|
||||
/* turn off nagle, writes are shipped immediately */
|
||||
flag = flag ? 0 : 1;
|
||||
return setsockopt( sock, /* socket affected */
|
||||
IPPROTO_TCP, /* set option at TCP level */
|
||||
TCP_NODELAY, /* name of option */
|
||||
(char *) &flag, /* the cast is historical cruft */
|
||||
sizeof(int)); /* length of option value */
|
||||
}
|
||||
25
src/libnet/tcp_recv.c
Normal file
25
src/libnet/tcp_recv.c
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// TCP recv
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
int tcp_recv( int sock, void *buf, int len )
|
||||
{
|
||||
char *s = (char *)buf;
|
||||
size_t n;
|
||||
|
||||
/* check! */
|
||||
if ( sock < 0 )
|
||||
return -1;
|
||||
if ( !buf || len <= 0 )
|
||||
return -1;
|
||||
|
||||
/* read */
|
||||
n = recv( sock, buf, len, 0 );
|
||||
|
||||
if ( n > 0 )
|
||||
*(s+n) = '\0';
|
||||
|
||||
return n;
|
||||
}
|
||||
35
src/libnet/tcp_send.c
Normal file
35
src/libnet/tcp_send.c
Normal file
@ -0,0 +1,35 @@
|
||||
//
|
||||
// TCP send
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
int tcp_send( int sock, const char *buf, int len )
|
||||
{
|
||||
int total = 0;
|
||||
int n = 0;
|
||||
|
||||
/* check! */
|
||||
if ( sock < 0 )
|
||||
return -1;
|
||||
if ( !buf || len <= 0 )
|
||||
return -1;
|
||||
|
||||
/* send it all */
|
||||
while ( total < len )
|
||||
{
|
||||
int n = send( sock, buf, len, 0 );
|
||||
if ( n == -1 )
|
||||
break;
|
||||
buf += n;
|
||||
total += n;
|
||||
len -= n;
|
||||
}
|
||||
|
||||
return n==-1 ? -1 : total;
|
||||
}
|
||||
|
||||
int tcp_sendstr( int sock, const char *str )
|
||||
{
|
||||
return tcp_send( sock, str, strlen(str) );
|
||||
}
|
||||
72
src/libnet/tcp_server.c
Normal file
72
src/libnet/tcp_server.c
Normal file
@ -0,0 +1,72 @@
|
||||
//
|
||||
// TCP Server
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
int tcp_server( const char *host, const char *service )
|
||||
{
|
||||
int i;
|
||||
|
||||
/* socket stuff */
|
||||
int sock; /* tcp socket */
|
||||
|
||||
/* dual stack listener */
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *res, *ressave;
|
||||
|
||||
/* set-up hints structure */
|
||||
bzero(&hints, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
if ( getaddrinfo(host, service, &hints, &res) )
|
||||
{
|
||||
log_error("getaddrinfo");
|
||||
return -1;
|
||||
}
|
||||
ressave = res;
|
||||
|
||||
/*
|
||||
* "res" has a chain of addrinfo structure filled with
|
||||
* 0.0.0.0 (for IPv4), 0:0:0:0:0:0:0:0 (for IPv6) and alike,
|
||||
* with port filled for "myservice".
|
||||
*/
|
||||
while (res)
|
||||
{
|
||||
/* bind() and listen() to res->ai_addr */
|
||||
sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol );
|
||||
if ( sock < 0 )
|
||||
continue;
|
||||
|
||||
/* reuse socket */
|
||||
i = 1;
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i) );
|
||||
|
||||
/* bind */
|
||||
if ( bind(sock, res->ai_addr, res->ai_addrlen) == 0 )
|
||||
break; // success
|
||||
|
||||
/* error, try again */
|
||||
close( sock );
|
||||
res = res->ai_next;
|
||||
}
|
||||
|
||||
freeaddrinfo( ressave );
|
||||
|
||||
/* able to bind? */
|
||||
if ( !res )
|
||||
{
|
||||
log_error("tcp_server");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* listen, queue up to 10 pending connections */
|
||||
if ( listen(sock, 10) )
|
||||
{
|
||||
log_error("tcp_listen");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
40
src/libnet/udp_broadcast.c
Normal file
40
src/libnet/udp_broadcast.c
Normal file
@ -0,0 +1,40 @@
|
||||
//
|
||||
// Neal Probert
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
int udp_broadcast( const char *host, const char *service, struct sockaddr_storage *sa, socklen_t *len )
|
||||
{
|
||||
/* socket stuff */
|
||||
int sock, family; /* tcp socket */
|
||||
|
||||
if ( !host )
|
||||
host = "255.255.255.255";
|
||||
|
||||
// host
|
||||
family = ip_host2addr( host, service, sa, len );
|
||||
|
||||
if ( family != AF_INET )
|
||||
{
|
||||
log_error(host);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* plug me into a socket */
|
||||
if ( (sock = socket( family, SOCK_DGRAM, 0)) < 0 )
|
||||
{
|
||||
log_error("dgram_socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ipv4 uses classic broadcast
|
||||
u_int i = 1;
|
||||
if ( setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i)) != 0 )
|
||||
{
|
||||
log_error("so_broadcast");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
51
src/libnet/udp_client.c
Normal file
51
src/libnet/udp_client.c
Normal file
@ -0,0 +1,51 @@
|
||||
//
|
||||
// UDP Client Connect
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
int udp_client( const char *host, const char *service )
|
||||
{
|
||||
int sock; /* tcp socket */
|
||||
struct addrinfo hints, *res, *ressave;
|
||||
|
||||
/* default IPv6 localhost */
|
||||
if ( !host || !strlen(host) )
|
||||
host = "ip6-localhost";
|
||||
|
||||
/* get address information */
|
||||
bzero(&hints, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
if ( getaddrinfo(host, service, &hints, &res) )
|
||||
{
|
||||
log_error("getaddrinfo");
|
||||
return -1;
|
||||
}
|
||||
ressave = res;
|
||||
|
||||
while (res)
|
||||
{
|
||||
sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
if (sock < 0)
|
||||
continue; // ignore
|
||||
|
||||
// connected (allows send()/write() to be used)
|
||||
if ( connect(sock, res->ai_addr, res->ai_addrlen) == 0 )
|
||||
break; // success
|
||||
|
||||
// next
|
||||
close(sock);
|
||||
res = res->ai_next;
|
||||
}
|
||||
|
||||
if ( !res )
|
||||
{
|
||||
log_error("udp_client");
|
||||
return -1;
|
||||
}
|
||||
|
||||
freeaddrinfo(ressave);
|
||||
|
||||
return sock;
|
||||
}
|
||||
105
src/libnet/udp_listener.c
Normal file
105
src/libnet/udp_listener.c
Normal file
@ -0,0 +1,105 @@
|
||||
//
|
||||
// UDP Client Connect
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
int udp_listener( const char *host, const char *service )
|
||||
{
|
||||
int sock; /* tcp socket */
|
||||
struct sockaddr_storage ss;
|
||||
int bcast = 0;
|
||||
|
||||
// default host?
|
||||
if ( !host )
|
||||
host = "0.0.0.0"; // INADDR_ANY
|
||||
|
||||
/* clear and initialize address structure */
|
||||
socklen_t sa_len;
|
||||
int family = ip_host2addr( host, service, (struct sockaddr_storage *)&ss, &sa_len );
|
||||
|
||||
if ( family < 0 )
|
||||
return -1;
|
||||
|
||||
// check if multicast
|
||||
if ( family == AF_INET6 )
|
||||
{
|
||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&ss;
|
||||
|
||||
if ( !IN6_IS_ADDR_MULTICAST( sa6->sin6_addr.s6_addr ) )
|
||||
{
|
||||
log_error(host);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// bind to any
|
||||
sa6->sin6_addr = in6addr_any;
|
||||
}
|
||||
else if ( family == AF_INET )
|
||||
{
|
||||
struct sockaddr_in *sa = (struct sockaddr_in *)&ss;
|
||||
|
||||
// broadcast listener?
|
||||
if ( sa->sin_addr.s_addr == INADDR_ANY ||
|
||||
sa->sin_addr.s_addr == INADDR_LOOPBACK )
|
||||
{
|
||||
bcast = 1;
|
||||
}
|
||||
else if ( IN_MULTICAST( sa->sin_addr.s_addr ) )
|
||||
{
|
||||
log_error("multicast");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// bind to any
|
||||
sa->sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
|
||||
/* plug me into a socket */
|
||||
if ( (sock = socket(family, SOCK_DGRAM, 0)) < 0 )
|
||||
{
|
||||
log_error("dgram_socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* reuse socket */
|
||||
int i = 1;
|
||||
if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) == 1 )
|
||||
{
|
||||
log_error("so_reuseaddr");
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* bind (any) */
|
||||
if ( bind(sock, (struct sockaddr *)&ss, sa_len ) < 0 )
|
||||
{
|
||||
log_error( "udp_bind" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// IPv4 broadcast
|
||||
if ( bcast )
|
||||
return sock;
|
||||
|
||||
// Multicast
|
||||
int level = (family == AF_INET6) ? IPPROTO_IPV6 : IPPROTO_IP;
|
||||
|
||||
// join multi-cast group
|
||||
struct group_req req;
|
||||
req.gr_interface = 0; // kernel selects interface
|
||||
req.gr_group = ss;
|
||||
|
||||
// join
|
||||
if ( family == AF_INET6 )
|
||||
{
|
||||
if ( setsockopt(sock, level, MCAST_JOIN_GROUP, &req, sizeof(req) ) != 0 )
|
||||
{
|
||||
log_error( "ipv6_join_group" );
|
||||
close( sock );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
67
src/libnet/udp_multicast.c
Normal file
67
src/libnet/udp_multicast.c
Normal file
@ -0,0 +1,67 @@
|
||||
//
|
||||
// Neal Probert
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
int udp_multicast( const char *host, const char *service, struct sockaddr_storage *sa, socklen_t *len )
|
||||
{
|
||||
// socket stuff
|
||||
int sock; /* tcp socket */
|
||||
|
||||
// address for link-local multi-cast
|
||||
int family = ip_host2addr( host, service, sa, len );
|
||||
if ( family < 0 )
|
||||
return -1;
|
||||
|
||||
// plug me into a socket
|
||||
if ( (sock = socket( family, SOCK_DGRAM, 0)) < 0 )
|
||||
{
|
||||
log_error("dgram_socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int level = (family == AF_INET6) ? IPPROTO_IPV6 : IPPROTO_IP;
|
||||
|
||||
// The Stevens book doesn't do the join source group
|
||||
|
||||
// broadcast on this socket
|
||||
if ( family == AF_INET6 )
|
||||
{
|
||||
// no local echo
|
||||
u_int flag = 0;
|
||||
if ( setsockopt(sock, level, IPV6_MULTICAST_LOOP, &flag, sizeof(flag) ) != 0 )
|
||||
{
|
||||
log_error( "mcast_multicast_loop" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 1 hop
|
||||
flag = 1;
|
||||
if ( setsockopt(sock, level, IPV6_MULTICAST_HOPS, &flag, sizeof(flag) ) != 0 )
|
||||
{
|
||||
log_error( "mcast_multicast_hops" );
|
||||
// return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no local echo
|
||||
u_char flag = 0;
|
||||
if ( setsockopt(sock, level, IP_MULTICAST_LOOP, &flag, sizeof(flag) ) != 0 )
|
||||
{
|
||||
log_error( "mcast_multicast_loop" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 1 hop
|
||||
flag = 1;
|
||||
if ( setsockopt(sock, level, IP_MULTICAST_TTL, &flag, sizeof(flag) ) != 0 )
|
||||
{
|
||||
log_error( "mcast_multicast_hops" );
|
||||
// return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
35
src/libnet/udp_recvfrom.c
Normal file
35
src/libnet/udp_recvfrom.c
Normal file
@ -0,0 +1,35 @@
|
||||
//
|
||||
// UDP recvfrom
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
int udp_recvfrom( int sock, void *buf, int max, struct sockaddr_storage *sa, socklen_t *len )
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t num;
|
||||
char *s = (char *)buf;
|
||||
int n;
|
||||
|
||||
/* check! */
|
||||
if ( sock < 0 )
|
||||
return -1;
|
||||
if ( !buf || max <= 0 )
|
||||
return -1;
|
||||
|
||||
/* sender */
|
||||
if ( !sa )
|
||||
sa = &ss;
|
||||
if ( !len ) {
|
||||
len = #
|
||||
num = sizeof(ss);
|
||||
}
|
||||
|
||||
/* read */
|
||||
n = recvfrom( sock, buf, max, 0, (struct sockaddr *)sa, len );
|
||||
|
||||
if ( n > 0 && n<(max-1) )
|
||||
*(s+n) = '\0';
|
||||
|
||||
return n;
|
||||
}
|
||||
41
src/libnet/udp_sendmcast.c
Normal file
41
src/libnet/udp_sendmcast.c
Normal file
@ -0,0 +1,41 @@
|
||||
//
|
||||
// Neal Probert
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
int udp_sendbcast( int sock, int port, char *buf, int len, const struct sockaddr_storage *sa )
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
|
||||
if ( !sa )
|
||||
{
|
||||
bzero( &ss, sizeof(ss) );
|
||||
sa = &ss;
|
||||
}
|
||||
|
||||
if ( !sa->ss_family )
|
||||
{
|
||||
socklen_t l = sizeof(struct sockaddr_storage);
|
||||
|
||||
/* address info */
|
||||
if ( getsockname( sock, (struct sockaddr *)&ss, &l ) < 0 )
|
||||
return -1;
|
||||
|
||||
// bcast address
|
||||
if ( ss.ss_family == AF_INET6 )
|
||||
{
|
||||
// ipv6 link local multicast (all-hosts with hop count of 1)
|
||||
}
|
||||
else
|
||||
{
|
||||
struct sockaddr_in *sa4 = (struct sockaddr_in *)&ss;
|
||||
sa4->sin_port = port;
|
||||
|
||||
// TBD address and netmask
|
||||
sa4->sin_addr.s_addr = htonl( 0xC0A8FFFF ); // 192.168.255.255
|
||||
}
|
||||
}
|
||||
|
||||
return sendto( sock, buf, len, MSG_DONTROUTE, (const struct sockaddr *)sa, (socklen_t)sizeof(sockaddr_storage) );
|
||||
}
|
||||
16
src/libnet/udp_sendto.c
Normal file
16
src/libnet/udp_sendto.c
Normal file
@ -0,0 +1,16 @@
|
||||
//
|
||||
// UDP send
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
int udp_sendto( int sock, const char *buf, int len, const struct sockaddr_storage *sa, int salen )
|
||||
{
|
||||
/* check! */
|
||||
if ( sock < 0 )
|
||||
return -1;
|
||||
if ( !buf || len <= 0 )
|
||||
return -1;
|
||||
|
||||
return sendto( sock, buf, len, MSG_DONTROUTE, (struct sockaddr *)sa, salen );
|
||||
}
|
||||
59
src/libnet/udp_server.c
Normal file
59
src/libnet/udp_server.c
Normal file
@ -0,0 +1,59 @@
|
||||
//
|
||||
// UDP Server
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
int udp_server( const char *host, const char *service )
|
||||
{
|
||||
/* socket stuff */
|
||||
int sock; /* tcp socket */
|
||||
|
||||
/* dual stack listener */
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *res, *ressave;
|
||||
|
||||
/* set-up hints structure */
|
||||
bzero(&hints, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
if ( getaddrinfo(host, service, &hints, &res) )
|
||||
{
|
||||
log_error( "getaddrinfo" );
|
||||
return -1;
|
||||
}
|
||||
ressave = res;
|
||||
|
||||
/*
|
||||
* "res" has a chain of addrinfo structure filled with
|
||||
* 0.0.0.0 (for IPv4), 0:0:0:0:0:0:0:0 (for IPv6) and alike,
|
||||
* with port filled for "myservice".
|
||||
*/
|
||||
while (res)
|
||||
{
|
||||
/* bind() and listen() to res->ai_addr */
|
||||
sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol );
|
||||
if ( sock < 0 )
|
||||
continue;
|
||||
|
||||
/* bind */
|
||||
if ( bind(sock, res->ai_addr, res->ai_addrlen) == 0 )
|
||||
break; // success
|
||||
|
||||
/* error, try again */
|
||||
close( sock );
|
||||
res = res->ai_next;
|
||||
}
|
||||
|
||||
freeaddrinfo( ressave );
|
||||
|
||||
/* able to bind? */
|
||||
if ( !res )
|
||||
{
|
||||
log_error( "server" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
47
src/libnet/udp_socket.c
Normal file
47
src/libnet/udp_socket.c
Normal file
@ -0,0 +1,47 @@
|
||||
//
|
||||
// UDP Client Socket
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
int udp_socket(const char *host, const char *service)
|
||||
{
|
||||
int sock; /* tcp socket */
|
||||
struct addrinfo hints, *res, *ressave;
|
||||
|
||||
/* default IPv6 localhost */
|
||||
if ( !host || !strlen(host) )
|
||||
host = "ip6-localhost";
|
||||
|
||||
/* get address information */
|
||||
bzero(&hints, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
if ( getaddrinfo(NULL, service, &hints, &res) )
|
||||
{
|
||||
log_error("getaddrinfo");
|
||||
return -1;
|
||||
}
|
||||
ressave = res;
|
||||
|
||||
while (res)
|
||||
{
|
||||
sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
if (sock >= 0)
|
||||
break;
|
||||
|
||||
// next
|
||||
close(sock);
|
||||
res = res->ai_next;
|
||||
}
|
||||
|
||||
if ( !res )
|
||||
{
|
||||
log_error("udp_socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
freeaddrinfo(ressave);
|
||||
|
||||
return sock;
|
||||
}
|
||||
26
src/libnet/uds_client.c
Normal file
26
src/libnet/uds_client.c
Normal file
@ -0,0 +1,26 @@
|
||||
//
|
||||
// TCP Client Connect
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
#include <sys/un.h>
|
||||
|
||||
int uds_client( const char *file )
|
||||
{
|
||||
int s, len;
|
||||
struct sockaddr_un remote;
|
||||
|
||||
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
||||
log_error("uds_client");
|
||||
return -1;
|
||||
}
|
||||
|
||||
remote.sun_family = AF_UNIX;
|
||||
strcpy(remote.sun_path, file);
|
||||
len = strlen(remote.sun_path) + sizeof(remote.sun_family);
|
||||
if (connect(s, (struct sockaddr *)&remote, len) == -1) {
|
||||
log_error("uds_client");
|
||||
return -1;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
48
src/libnet/uds_server.c
Normal file
48
src/libnet/uds_server.c
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// Unix Domain Socket (UDS) Server
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
#include <sys/un.h>
|
||||
|
||||
int uds_server( const char *file )
|
||||
{
|
||||
unsigned int s;
|
||||
struct sockaddr_un local;
|
||||
int len;
|
||||
|
||||
// socket
|
||||
s = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (s < 0)
|
||||
{
|
||||
log_error("uds_server");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// bind
|
||||
local.sun_family = AF_UNIX; /* local is declared before socket() ^ */
|
||||
strcpy(local.sun_path, file);
|
||||
unlink(local.sun_path);
|
||||
len = strlen(local.sun_path) + sizeof(local.sun_family);
|
||||
if (bind(s, (struct sockaddr *)&local, len) < 0) {
|
||||
close(s);
|
||||
log_error("uds_server");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// listen
|
||||
if (listen(s, 10) < 0) {
|
||||
close(s);
|
||||
log_error("uds_server");
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int uds_accept( const int s )
|
||||
{
|
||||
struct sockaddr_un remote;
|
||||
socklen_t len = sizeof(struct sockaddr_un);
|
||||
int s2 = accept(s, (struct sockaddr *)&remote, &len);
|
||||
return s2;
|
||||
}
|
||||
160
src/libnet/uri_parse.c
Normal file
160
src/libnet/uri_parse.c
Normal file
@ -0,0 +1,160 @@
|
||||
//
|
||||
// IP gethostname
|
||||
//
|
||||
|
||||
#include "netlib.h"
|
||||
#include "strlib.h"
|
||||
|
||||
void uri_clear( uri_parts *parsed )
|
||||
{
|
||||
bzero( parsed, sizeof(uri_parts) );
|
||||
}
|
||||
|
||||
void uri_defaults( uri_parts *parsed )
|
||||
{
|
||||
bzero( parsed, sizeof(uri_parts) );
|
||||
strcpy( parsed->proto, "http" );
|
||||
strcpy( parsed->host, "localhost" );
|
||||
strcpy( parsed->port, "80" );
|
||||
strcpy( parsed->path, "/" );
|
||||
}
|
||||
|
||||
int uri_parse( const char *uri, uri_parts *parsed )
|
||||
{
|
||||
char buf[4096];
|
||||
char *proto = NULL, *host = NULL, *port = NULL;
|
||||
char *user = NULL, *pass = NULL, *path = NULL;
|
||||
char *s;
|
||||
int ret = 0;
|
||||
|
||||
// output
|
||||
if ( !parsed )
|
||||
return 0;
|
||||
|
||||
// buffer
|
||||
strlcpy( buf, uri, sizeof(buf) );
|
||||
|
||||
// proto://user:pass@host:port/path
|
||||
s = buf;
|
||||
|
||||
// proto
|
||||
if ( isalpha(*s) )
|
||||
{
|
||||
s = strchr( buf, ':' );
|
||||
|
||||
if ( s )
|
||||
{
|
||||
proto = buf;
|
||||
*s++ = '\0';
|
||||
ret++;
|
||||
}
|
||||
else
|
||||
s = buf;
|
||||
}
|
||||
|
||||
// absolute path
|
||||
if ( strncmp( s, "///", 3 ) == 0 )
|
||||
{
|
||||
// skip over
|
||||
s += 2;
|
||||
|
||||
// file path
|
||||
path = s++;
|
||||
|
||||
ret++;
|
||||
}
|
||||
else if ( strncmp( s, "//", 2 ) == 0 )
|
||||
{
|
||||
// skip over
|
||||
s += 2;
|
||||
|
||||
// path
|
||||
if ( (path = strchr( s, '/' )) )
|
||||
{
|
||||
*path++ = '\0';
|
||||
strlcpy( parsed->path, "/", sizeof(parsed->path) );
|
||||
ret++;
|
||||
}
|
||||
|
||||
// user:pass, host
|
||||
if ( (host = strchr( s, '@' )) )
|
||||
{
|
||||
// user
|
||||
user = s;
|
||||
*host++ = '\0';
|
||||
ret++;
|
||||
|
||||
// pass
|
||||
pass = strchr( user, ':' );
|
||||
if ( pass )
|
||||
{
|
||||
*pass++ = '\0';
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
else
|
||||
host = s;
|
||||
|
||||
// host:port
|
||||
if ( strlen( host ) )
|
||||
{
|
||||
ret++;
|
||||
port = strchr( host, ':' );
|
||||
if ( port )
|
||||
{
|
||||
*port++ = '\0';
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
parsed->rate = 0;
|
||||
}
|
||||
else if ( *s == '/' )
|
||||
{
|
||||
// file path
|
||||
path = s;
|
||||
|
||||
// the case of /dev/ttyS0:baud
|
||||
if ( (s = strchr( path, ':' )) )
|
||||
{
|
||||
*s++ = '\0';
|
||||
parsed->rate = atoi( s );
|
||||
ret++;
|
||||
}
|
||||
ret++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// hostname
|
||||
host = s;
|
||||
|
||||
if ( (s = strchr( host, ':' )) )
|
||||
{
|
||||
*s++ = '\0';
|
||||
port = s;
|
||||
ret++;
|
||||
}
|
||||
ret++;
|
||||
}
|
||||
|
||||
// copy
|
||||
if ( proto )
|
||||
{
|
||||
strncpy( parsed->proto, proto, sizeof(parsed->proto) );
|
||||
}
|
||||
if ( user )
|
||||
{
|
||||
strncpy( parsed->user, user, sizeof(parsed->user) );
|
||||
if ( pass )
|
||||
strncpy( parsed->pass, pass, sizeof(parsed->pass) );
|
||||
}
|
||||
if ( host )
|
||||
{
|
||||
strncpy( parsed->host, host, sizeof(parsed->host) );
|
||||
if ( port )
|
||||
strncpy( parsed->port, port, sizeof(parsed->port) );
|
||||
}
|
||||
if ( path )
|
||||
strncat( parsed->path, path, sizeof(parsed->path) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
27
src/libnet/uritest.c
Normal file
27
src/libnet/uritest.c
Normal file
@ -0,0 +1,27 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
struct uri_parse parsed;
|
||||
|
||||
int i, n;
|
||||
|
||||
for ( i=1 ; i<argc ; i++ )
|
||||
{
|
||||
uri_clear( &parsed );
|
||||
|
||||
n = uri_parse( argv[i] , &parsed );
|
||||
printf( "parsed out %d fields\n", n );
|
||||
|
||||
printf( "proto: %s\n", parsed.proto );
|
||||
printf( "user: %s\n", parsed.user );
|
||||
printf( "pass: %s\n", parsed.pass );
|
||||
printf( "host: %s\n", parsed.host );
|
||||
printf( "port: %s\n", parsed.port );
|
||||
printf( "path: %s\n", parsed.path );
|
||||
printf( "rate: %d\n", parsed.rate );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user