Initial commit of files

This commit is contained in:
2021-01-22 10:16:20 -05:00
parent 32d165ec8f
commit ed92211680
534 changed files with 68563 additions and 19 deletions

71
src/libnet/CMakeLists.txt Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}

View 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
View 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
View 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;
}

View 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
View 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;
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;
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}