X-Git-Url: http://ftp.carnet.hr/carnet-debian/scm?p=ossec-hids.git;a=blobdiff_plain;f=src%2Fos_net%2Fos_net.c;fp=src%2Fos_net%2Fos_net.c;h=23f80fe7934736368c8833249c73b6e7c75362c1;hp=08e1352ee72721e412a2c3f2053eba13bad36718;hb=3f728675941dc69d4e544d3a880a56240a6e394a;hpb=927951d1c1ad45ba9e7325f07d996154a91c911b diff --git a/src/os_net/os_net.c b/src/os_net/os_net.c old mode 100755 new mode 100644 index 08e1352..23f80fe --- a/src/os_net/os_net.c +++ b/src/os_net/os_net.c @@ -1,6 +1,3 @@ -/* @(#) $Id: ./src/os_net/os_net.c, 2011/09/08 dcid Exp $ - */ - /* Copyright (C) 2009 Trend Micro Inc. * All rights reserved. * @@ -8,218 +5,273 @@ * and/or modify it under the terms of the GNU General Public * License (version 2) as published by the FSF - Free Software * Foundation - * - * License details at the LICENSE file included with OSSEC or - * online at: http://www.ossec.net/en/licensing.html */ -/* OS_net Library. - * APIs for many network operations. +/* OS_net Library + * APIs for many network operations */ - - #include #include "shared.h" #include "os_net.h" +agent *agt; - - +/* Prototypes */ +static OSNetInfo *OS_Bindport(char *_port, unsigned int _proto, const char *_ip); +static int OS_Connect(char *_port, unsigned int protocol, const char *_ip); +static int OS_DecodeAddrinfo (struct addrinfo *res); +static char *OS_DecodeSockaddr (struct sockaddr *sa); +static char *DecodeFamily (int val); +static char *DecodeSocktype (int val); +static char *DecodeProtocol (int val); /* Unix socket -- not for windows */ #ifndef WIN32 -struct sockaddr_un n_us; -socklen_t us_l = sizeof(n_us); +static struct sockaddr_un n_us; +static socklen_t us_l = sizeof(n_us); /* UNIX SOCKET */ #ifndef SUN_LEN #define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \ - + strlen ((ptr)->sun_path)) + + strlen ((ptr)->sun_path)) #endif /* Sun_LEN */ #else /* WIN32 */ /*int ENOBUFS = 0;*/ -# ifndef ENOBUFS -# define ENOBUFS 0 -# endif +#ifndef ENOBUFS +#define ENOBUFS 0 +#endif #endif /* WIN32*/ -/* OS_Bindport v 0.2, 2005/02/11 - * Bind a specific port - * v0.2: Added REUSEADDR. - */ -int OS_Bindport(unsigned int _port, unsigned int _proto, char *_ip, int ipv6) +/* Bind all relevant ports */ +OSNetInfo *OS_Bindport(char *_port, unsigned int _proto, const char *_ip) { - int ossock; - struct sockaddr_in server; + int ossock = 0, s; + struct addrinfo hints, *result, *rp; + OSNetInfo *ni; /* return data */ + + /* Allocate the return data structure and initialize it. */ + ni = malloc (sizeof (OSNetInfo)); + memset(ni, 0, sizeof (OSNetInfo)); + FD_ZERO (&(ni->fdset)); + ni->fdmax = 0; + ni->fdcnt = 0; + ni->status = 0; + ni->retval = 0; + + /* init hints for getaddrinfo() */ + memset(&hints, 0, sizeof(struct addrinfo)); + + /* + * If you cannot bind both IPv4 and IPv6, the problem is likely due to the + * AF_INET6 family with the AI_V4MAPPED flag. Alter your Makefile to use the + * NOV4MAP define and it should work like a breeze. All of the *BSDs fall + * into this category even though AI_V4MAPPED exists in netdb.h (true for + * all modern OS's). This should work with all Linux versions too, but the + * original code for AF_INET6 was left for Linux because it works. + * + * d. stoddard - 4/19/2018 + */ + +#if defined(__linux__) && !defined(NOV4MAP) +#if defined (AI_V4MAPPED) + hints.ai_family = AF_INET6; /* Allow IPv4 and IPv6 */ + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG | AI_V4MAPPED; +#else + /* handle as normal IPv4 and IPv6 multi request */ + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; +#endif /* AI_V4MAPPED */ +#else + /* FreeBSD, OpenBSD, NetBSD, and others */ + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; +#endif - #ifndef WIN32 - struct sockaddr_in6 server6; - #else - ipv6 = 0; - #endif + hints.ai_protocol = _proto; + if (_proto == IPPROTO_UDP) { + hints.ai_socktype = SOCK_DGRAM; + } else if (_proto == IPPROTO_TCP) { + hints.ai_socktype = SOCK_STREAM; + } else { + ni->status = -1; + ni->retval = OS_INVALID; + return(ni); + } + /* get linked list of adresses */ + s = getaddrinfo(_ip, _port, &hints, &result); - if(_proto == IPPROTO_UDP) - { - if((ossock = socket(ipv6 == 1?PF_INET6:PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) - { - return OS_SOCKTERR; - } + /* Try to support legacy ipv4 only hosts */ + if((s == EAI_FAMILY) || (s == EAI_NONAME)) { + hints.ai_family = AF_INET; + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; + s = getaddrinfo(_ip, _port, &hints, &result); } - else if(_proto == IPPROTO_TCP) - { - int flag = 1; - if((ossock = socket(ipv6 == 1?PF_INET6:PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) - { - return(int)(OS_SOCKTERR); - } - if(setsockopt(ossock, SOL_SOCKET, SO_REUSEADDR, - (char *)&flag, sizeof(flag)) < 0) - { - OS_CloseSocket(ossock); - return(OS_SOCKTERR); - } - } - else - { - return(OS_INVALID); + if (s != 0) { + verbose("getaddrinfo: %s", gai_strerror(s)); + ni->status = -1; + ni->retval = OS_INVALID; + return(ni); } - if(ipv6) - { - #ifndef WIN32 - memset(&server6, 0, sizeof(server6)); - server6.sin6_family = AF_INET6; - server6.sin6_port = htons( _port ); - server6.sin6_addr = in6addr_any; - + /* log the list of connections available */ + OS_DecodeAddrinfo (result); + + /* + * getaddrinfo() returns a list of address structures. We try each + * address and attempt to connect to it. If a socket(2) or bind(2) fails, + * we close the socket and try the next address. We repeat this for every + * address getaddrinfo() returns in the addrinfo linked list. + */ + + for (rp = result; rp != NULL; rp = rp->ai_next) { + ossock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (ossock == -1) { + verbose ("socket error: family %s type %s protocol %s: %s", + DecodeFamily (rp->ai_family), + DecodeSocktype (rp->ai_socktype), + DecodeProtocol (rp->ai_protocol), + strerror(errno)); + continue; + } - if(bind(ossock, (struct sockaddr *) &server6, sizeof(server6)) < 0) - { - OS_CloseSocket(ossock); - return(OS_SOCKTERR); + if (_proto == IPPROTO_TCP) { + int flag = 1; + if (setsockopt(ossock, SOL_SOCKET, SO_REUSEADDR, + (char *)&flag, sizeof(flag)) < 0) { + verbose ("setsockopt error: SO_REUSEADDR %d: %s", + errno, strerror(errno)); + if(ossock > 0) { + OS_CloseSocket(ossock); + } + continue; + } } - #endif - } - else - { - memset(&server, 0, sizeof(server)); - server.sin_family = AF_INET; - server.sin_port = htons( _port ); + if (bind(ossock, rp->ai_addr, rp->ai_addrlen) == -1) { + /* + * Don't issue an error message if the address and port is already + * bound. This can happen when 0.0.0.0 or :: are bound in a + * previous iteration of this loop. + */ + if (errno == EADDRINUSE) { + close (ossock); + continue; + } + + /* tell them why this address failed */ + verbose ("Bind failed on socket for %s: %s", + OS_DecodeSockaddr (rp->ai_addr), strerror (errno)); + close (ossock); + continue; + } - if((_ip == NULL)||(_ip[0] == '\0')) - server.sin_addr.s_addr = htonl(INADDR_ANY); - else - server.sin_addr.s_addr = inet_addr(_ip); + if (_proto == IPPROTO_TCP) { + if (listen(ossock, 32) < 0) { + verbose ("Request to listen() failed on socket for %s: %s", + OS_DecodeSockaddr (rp->ai_addr), strerror (errno)); + close (ossock); + continue; + } + verbose ("Request for TCP listen() succeeded."); + } + /* success - accumulate data for select call */ + verbose ("Socket bound for %s", OS_DecodeSockaddr (rp->ai_addr)); - if(bind(ossock, (struct sockaddr *) &server, sizeof(server)) < 0) - { - OS_CloseSocket(ossock); - return(OS_SOCKTERR); + /* save bound socket info for select() */ + ni->fds[ni->fdcnt++] = ossock; /* increment after use! */ + FD_SET (ossock, &(ni->fdset)); + if (ossock > ni->fdmax) { + ni->fdmax = ossock; } } - - - if(_proto == IPPROTO_TCP) - { - if(listen(ossock, 32) < 0) - { - OS_CloseSocket(ossock); - return(OS_SOCKTERR); + /* check to see if at least one address succeeded */ + if (ni->fdcnt == 0) { + verbose ("Request to allocate and bind sockets failed."); + ni->status = -1; + ni->retval = OS_SOCKTERR; + if(result) { + freeaddrinfo(result); } + return(ni); } - - return(ossock); + freeaddrinfo(result); /* No longer needed */ + ni->fdmax += 1; /* prep for use with select() */ + return (ni); } -/* OS_Bindporttcp v 0.1 - * Bind a TCP port, using the OS_Bindport - */ -int OS_Bindporttcp(unsigned int _port, char *_ip, int ipv6) +/* Bind a TCP port, using the OS_Bindport */ +OSNetInfo *OS_Bindporttcp(char *_port, const char *_ip) { - return(OS_Bindport(_port, IPPROTO_TCP, _ip, ipv6)); + return (OS_Bindport(_port, IPPROTO_TCP, _ip)); } - -/* OS_Bindportudp v 0.1 - * Bind a UDP port, using the OS_Bindport - */ -int OS_Bindportudp(unsigned int _port, char *_ip, int ipv6) +/* Bind a UDP port, using the OS_Bindport */ +OSNetInfo *OS_Bindportudp(char *_port, const char *_ip) { - return(OS_Bindport(_port, IPPROTO_UDP, _ip, ipv6)); + return (OS_Bindport(_port, IPPROTO_UDP, _ip)); } #ifndef WIN32 -/* OS_BindUnixDomain v0.1, 2004/07/29 - * Bind to a Unix domain, using DGRAM sockets - */ -int OS_BindUnixDomain(char * path, int mode, int max_msg_size) +/* Bind to a Unix domain, using DGRAM sockets */ +int OS_BindUnixDomain(const char *path, mode_t mode, int max_msg_size) { int len; int ossock = 0; socklen_t optlen = sizeof(len); - /* Making sure the path isn't there */ + /* Make sure the path isn't there */ unlink(path); memset(&n_us, 0, sizeof(n_us)); n_us.sun_family = AF_UNIX; - strncpy(n_us.sun_path, path, sizeof(n_us.sun_path)-1); + strncpy(n_us.sun_path, path, sizeof(n_us.sun_path) - 1); - if((ossock = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) - return(OS_SOCKTERR); + if ((ossock = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) { + return (OS_SOCKTERR); + } - if(bind(ossock, (struct sockaddr *)&n_us, SUN_LEN(&n_us)) < 0) - { + if (bind(ossock, (struct sockaddr *)&n_us, SUN_LEN(&n_us)) < 0) { OS_CloseSocket(ossock); - return(OS_SOCKTERR); + return (OS_SOCKTERR); } - /* Changing permissions */ - if(chmod(path,mode) < 0) - { + /* Change permissions */ + if (chmod(path, mode) < 0) { OS_CloseSocket(ossock); - return(OS_SOCKTERR); + return (OS_SOCKTERR); } - - /* Getting current maximum size */ - if(getsockopt(ossock, SOL_SOCKET, SO_RCVBUF, &len, &optlen) == -1) - { + /* Get current maximum size */ + if (getsockopt(ossock, SOL_SOCKET, SO_RCVBUF, &len, &optlen) == -1) { OS_CloseSocket(ossock); - return(OS_SOCKTERR); + return (OS_SOCKTERR); } - - /* Setting socket opt */ - if(len < max_msg_size) - { + /* Set socket opt */ + if (len < max_msg_size) { len = max_msg_size; - if(setsockopt(ossock, SOL_SOCKET, SO_RCVBUF, &len, optlen) < 0) - { + if (setsockopt(ossock, SOL_SOCKET, SO_RCVBUF, &len, optlen) < 0) { OS_CloseSocket(ossock); - return(OS_SOCKTERR); + return (OS_SOCKTERR); } } - return(ossock); + return (ossock); } -/* OS_ConnectUnixDomain v0.1, 2004/07/29 - * Open a client Unix domain socket +/* Open a client Unix domain socket * ("/tmp/lala-socket",0666)); - * */ -int OS_ConnectUnixDomain(char * path, int max_msg_size) +int OS_ConnectUnixDomain(const char *path, int max_msg_size) { int len; int ossock = 0; @@ -229,196 +281,199 @@ int OS_ConnectUnixDomain(char * path, int max_msg_size) n_us.sun_family = AF_UNIX; - /* Setting up path */ - strncpy(n_us.sun_path,path,sizeof(n_us.sun_path)-1); - - if((ossock = socket(PF_UNIX, SOCK_DGRAM,0)) < 0) - return(OS_SOCKTERR); + /* Set up path */ + strncpy(n_us.sun_path, path, sizeof(n_us.sun_path) - 1); + if ((ossock = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) { + return (OS_SOCKTERR); + } - /* Connecting to the UNIX domain. - * We can use "send" after that - */ - if(connect(ossock,(struct sockaddr *)&n_us,SUN_LEN(&n_us)) < 0) - { + /* Connect to the UNIX domain */ + if (connect(ossock, (struct sockaddr *)&n_us, SUN_LEN(&n_us)) < 0) { OS_CloseSocket(ossock); - return(OS_SOCKTERR); + return (OS_SOCKTERR); } - - /* Getting current maximum size */ - if(getsockopt(ossock, SOL_SOCKET, SO_SNDBUF, &len, &optlen) == -1) - { + /* Get current maximum size */ + if (getsockopt(ossock, SOL_SOCKET, SO_SNDBUF, &len, &optlen) == -1) { OS_CloseSocket(ossock); - return(OS_SOCKTERR); + return (OS_SOCKTERR); } - - /* Setting maximum message size */ - if(len < max_msg_size) - { + /* Set maximum message size */ + if (len < max_msg_size) { len = max_msg_size; - if(setsockopt(ossock, SOL_SOCKET, SO_SNDBUF, &len, optlen) < 0) - { + if (setsockopt(ossock, SOL_SOCKET, SO_SNDBUF, &len, optlen) < 0) { OS_CloseSocket(ossock); - return(OS_SOCKTERR); + return (OS_SOCKTERR); } } - - /* Returning the socket */ - return(ossock); + return (ossock); } - int OS_getsocketsize(int ossock) { int len = 0; socklen_t optlen = sizeof(len); - /* Getting current maximum size */ - if(getsockopt(ossock, SOL_SOCKET, SO_SNDBUF, &len, &optlen) == -1) + /* Get current maximum size */ + if (getsockopt(ossock, SOL_SOCKET, SO_SNDBUF, &len, &optlen) == -1) { + OS_CloseSocket(ossock); return(OS_SOCKTERR); + } - return(len); + return (len); } #endif -/* OS_Connect v 0.1, 2004/07/21 - * Open a TCP/UDP client socket - */ -int OS_Connect(unsigned int _port, unsigned int protocol, char *_ip, int ipv6) +/* Open a TCP/UDP client socket */ +int OS_Connect(char *_port, unsigned int protocol, const char *_ip) { - int ossock; - struct sockaddr_in server; + int ossock = 0, s; + struct addrinfo hints, *result, *rp, *local_ai = NULL; + char tempaddr[INET6_ADDRSTRLEN]; - #ifndef WIN32 - struct sockaddr_in6 server6; - #else - ipv6 = 0; - #endif + if ((_ip == NULL)||(_ip[0] == '\0')) { + OS_CloseSocket(ossock); + return(OS_INVALID); + } - if(protocol == IPPROTO_TCP) - { - if((ossock = socket(ipv6 == 1?PF_INET6:PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0) - return(OS_SOCKTERR); + if (agt) { + if (agt->lip) { + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_flags = AI_NUMERICHOST; + s = getaddrinfo(agt->lip, NULL, &hints, &result); + if (s != 0) { + verbose("getaddrinfo: %s", gai_strerror(s)); + } + else { + local_ai = result; + } + } } - else if(protocol == IPPROTO_UDP) - { - if((ossock = socket(ipv6 == 1?PF_INET6:PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0) - return(OS_SOCKTERR); + + memset(&hints, 0, sizeof(struct addrinfo)); + /* Allow IPv4 or IPv6 if local_ip isn't specified */ + hints.ai_family = AF_UNSPEC; + if (agt) { + if (agt->lip) { + hints.ai_family = local_ai->ai_family; + } } - else + hints.ai_protocol = protocol; + if (protocol == IPPROTO_TCP) { + hints.ai_socktype = SOCK_STREAM; + } else if (protocol == IPPROTO_UDP) { + hints.ai_socktype = SOCK_DGRAM; + } else { return(OS_INVALID); - - - - #ifdef HPUX - { - int flags; - flags = fcntl(ossock,F_GETFL,0); - fcntl(ossock, F_SETFL, flags | O_NONBLOCK); } - #endif - + hints.ai_flags = 0; - - if((_ip == NULL)||(_ip[0] == '\0')) - { - OS_CloseSocket(ossock); + s = getaddrinfo(_ip, _port, &hints, &result); + if (s != 0) { + verbose("getaddrinfo: %s", gai_strerror(s)); + if(result) { + freeaddrinfo(result); + } return(OS_INVALID); } + /* getaddrinfo() returns a list of address structures. + Try each address until we successfully connect(2). + If socket(2) (or connect(2)) fails, we (close the socket + and) try the next address. */ - if(ipv6 == 1) - { - #ifndef WIN32 - memset(&server6, 0, sizeof(server6)); - server6.sin6_family = AF_INET6; - server6.sin6_port = htons( _port ); - inet_pton(AF_INET6, _ip, &server6.sin6_addr.s6_addr); - - if(connect(ossock,(struct sockaddr *)&server6, sizeof(server6)) < 0) - { - OS_CloseSocket(ossock); - return(OS_SOCKTERR); + for (rp = result; rp != NULL; rp = rp->ai_next) { + ossock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (ossock == -1) { + continue; } - #endif - } - else - { - memset(&server, 0, sizeof(server)); - server.sin_family = AF_INET; - server.sin_port = htons( _port ); - server.sin_addr.s_addr = inet_addr(_ip); + if (agt) { + if (agt->lip) { + if (bind(ossock, local_ai->ai_addr, local_ai->ai_addrlen)) { + verbose("Unable to bind to local address %s. Ignoring. (%s)", + agt->lip, strerror(errno)); + } + else verbose("Connecting from local address %s", agt->lip); + } + } - if(connect(ossock,(struct sockaddr *)&server, sizeof(server)) < 0) - { + if (connect(ossock, rp->ai_addr, rp->ai_addrlen) != -1) { + break; /* Success */ + } + } + if (rp == NULL) { /* No address succeeded */ + if (ossock > 0) { OS_CloseSocket(ossock); - return(OS_SOCKTERR); } + if(result) { + freeaddrinfo(result); + } + return(OS_SOCKTERR); } + satop(rp->ai_addr, tempaddr, sizeof tempaddr); + verbose("INFO: Connected to %s at address %s, port %s", _ip, + tempaddr, _port); + + freeaddrinfo(result); /* No longer needed */ + #ifdef HPUX + { + int flags; + flags = fcntl(ossock,F_GETFL,0); + fcntl(ossock, F_SETFL, flags | O_NONBLOCK); + } + #endif return(ossock); } -/* OS_ConnectTCP, v0.1 - * Open a TCP socket - */ -int OS_ConnectTCP(unsigned int _port, char *_ip, int ipv6) +/* Open a TCP socket */ +int OS_ConnectTCP(char *_port, const char *_ip) { - return(OS_Connect(_port, IPPROTO_TCP, _ip, ipv6)); + return (OS_Connect(_port, IPPROTO_TCP, _ip)); } - -/* OS_ConnectUDP, v0.1 - * Open a UDP socket - */ -int OS_ConnectUDP(unsigned int _port, char *_ip, int ipv6) +/* Open a UDP socket */ +int OS_ConnectUDP(char *_port, const char *_ip) { - return(OS_Connect(_port, IPPROTO_UDP, _ip, ipv6)); + return (OS_Connect(_port, IPPROTO_UDP, _ip)); } -/* OS_SendTCP v0.1, 2004/07/21 - * Send a TCP packet (in a open socket) - */ -int OS_SendTCP(int socket, char *msg) +/* Send a TCP packet (through an open socket) */ +int OS_SendTCP(int socket, const char *msg) { - if((send(socket, msg, strlen(msg),0)) <= 0) + if ((send(socket, msg, strlen(msg), 0)) <= 0) { return (OS_SOCKTERR); + } - return(0); + return (0); } -/* OS_SendTCPbySize v0.1, 2004/07/21 - * Send a TCP packet (in a open socket) of a specific size - */ -int OS_SendTCPbySize(int socket, int size, char *msg) +/* Send a TCP packet of a specific size (through a open socket) */ +int OS_SendTCPbySize(int socket, int size, const char *msg) { - if((send(socket, msg, size, 0)) < size) + if ((send(socket, msg, size, 0)) < size) { return (OS_SOCKTERR); + } - return(0); + return (0); } - -/* OS_SendUDPbySize v0.1, 2004/07/21 - * Send a UDP packet (in a open socket) of a specific size - */ -int OS_SendUDPbySize(int socket, int size, char *msg) +/* Send a UDP packet of a specific size (through an open socket) */ +int OS_SendUDPbySize(int socket, int size, const char *msg) { - int i = 0; + unsigned int i = 0; /* Maximum attempts is 5 */ - while((send(socket,msg,size,0)) < 0) - { - if((errno != ENOBUFS) || (i >= 5)) - { - return(OS_SOCKTERR); + while ((send(socket, msg, size, 0)) < 0) { + if ((errno != ENOBUFS) || (i >= 5)) { + return (OS_SOCKTERR); } i++; @@ -426,188 +481,358 @@ int OS_SendUDPbySize(int socket, int size, char *msg) sleep(i); } - return(0); + return (0); } - - -/* OS_AcceptTCP v0.1, 2005/01/28 - * Accept a TCP connection - */ -int OS_AcceptTCP(int socket, char *srcip, int addrsize) +/* Accept a TCP connection */ +int OS_AcceptTCP(int socket, char *srcip, size_t addrsize) { int clientsocket; - struct sockaddr_in _nc; + struct sockaddr_storage _nc; socklen_t _ncl; memset(&_nc, 0, sizeof(_nc)); _ncl = sizeof(_nc); - if((clientsocket = accept(socket, (struct sockaddr *) &_nc, - &_ncl)) < 0) - return(-1); + if ((clientsocket = accept(socket, (struct sockaddr *) &_nc, + &_ncl)) < 0) { + return (-1); + } - strncpy(srcip, inet_ntoa(_nc.sin_addr),addrsize -1); - srcip[addrsize -1]='\0'; + satop((struct sockaddr *) &_nc, srcip, addrsize -1); + srcip[addrsize -1] = '\0'; - return(clientsocket); + return (clientsocket); } - -/* OS_RecvTCP v0.1, 2004/07/21 - * Receive a TCP packet (in a open socket) - */ +/* Receive a TCP packet (from an open socket) */ char *OS_RecvTCP(int socket, int sizet) { char *ret; ret = (char *) calloc((sizet), sizeof(char)); - if(ret == NULL) - return(NULL); + if (ret == NULL) { + return (NULL); + } - if(recv(socket, ret, sizet-1,0) <= 0) - { + if (recv(socket, ret, sizet - 1, 0) <= 0) { free(ret); - return(NULL); + return (NULL); } - return(ret); + return (ret); } - -/* OS_RecvTCPBuffer v0.1, 2004/07/21 - * Receive a TCP packet (in a open socket) - */ +/* Receive a TCP packet (from an open socket) */ int OS_RecvTCPBuffer(int socket, char *buffer, int sizet) { int retsize; - if((retsize = recv(socket, buffer, sizet -1, 0)) > 0) - { + if ((retsize = recv(socket, buffer, sizet - 1, 0)) > 0) { buffer[retsize] = '\0'; - return(0); + return (retsize); } - return(-1); + return (-1); } - - - -/* OS_RecvUDP v 0.1, 2004/07/20 - * Receive a UDP packet - */ +/* Receive a UDP packet */ char *OS_RecvUDP(int socket, int sizet) { char *ret; ret = (char *) calloc((sizet), sizeof(char)); - if(ret == NULL) - return(NULL); + if (ret == NULL) { + return (NULL); + } - if((recv(socket,ret,sizet-1,0))<0) - { + if ((recv(socket, ret, sizet - 1, 0)) < 0) { free(ret); - return(NULL); + return (NULL); } - return(ret); + return (ret); } - -/* OS_RecvConnUDP v0.1 - * Receives a message from a connected UDP socket - */ +/* Receives a message from a connected UDP socket */ int OS_RecvConnUDP(int socket, char *buffer, int buffer_size) { int recv_b; recv_b = recv(socket, buffer, buffer_size, 0); - if(recv_b < 0) - return(0); + if (recv_b < 0) { + return (0); + } - return(recv_b); -} + buffer[recv_b] = '\0'; + return (recv_b); +} #ifndef WIN32 -/* OS_RecvUnix, v0.1, 2004/07/29 - * Receive a message using a Unix socket - */ +/* Receive a message from a Unix socket */ int OS_RecvUnix(int socket, int sizet, char *ret) { ssize_t recvd; - if((recvd = recvfrom(socket, ret, sizet -1, 0, - (struct sockaddr*)&n_us,&us_l)) < 0) - return(0); + if ((recvd = recvfrom(socket, ret, sizet - 1, 0, + (struct sockaddr *)&n_us, &us_l)) < 0) { + return (0); + } ret[recvd] = '\0'; - return((int)recvd); + return ((int)recvd); } - -/* OS_SendUnix, v0.1, 2004/07/29 - * Send a message using a Unix socket. - * Returns the OS_SOCKETERR if it +/* Send a message using a Unix socket + * Returns the OS_SOCKETERR if it fails */ -int OS_SendUnix(int socket, char * msg, int size) +int OS_SendUnix(int socket, const char *msg, int size) { - if(size == 0) - size = strlen(msg)+1; + if (size == 0) { + size = strlen(msg) + 1; + } - if(send(socket, msg, size,0) < size) - { - if(errno == ENOBUFS) - return(OS_SOCKBUSY); + if (send(socket, msg, size, 0) < size) { + if (errno == ENOBUFS) { + return (OS_SOCKBUSY); + } - return(OS_SOCKTERR); + return (OS_SOCKTERR); } - return(OS_SUCCESS); + return (OS_SUCCESS); } #endif - -/* OS_GetHost, v0.1, 2005/01/181 - * Calls gethostbyname (tries x attempts) - */ -char *OS_GetHost(char *host, int attempts) +/* Calls getaddrinfo (tries x attempts) */ +char *OS_GetHost(const char *host, unsigned int attempts) { - int i = 0; - int sz; + unsigned int i = 0; + int error; char *ip; - struct hostent *h; + struct addrinfo *hai, *result; - if(host == NULL) - return(NULL); + if (host == NULL) { + return (NULL); + } - while(i <= attempts) - { - if((h = gethostbyname(host)) == NULL) - { + while (i <= attempts) { + if ((error = getaddrinfo(host, NULL, NULL, &result)) != 0) { sleep(i++); continue; } - sz = strlen(inet_ntoa(*((struct in_addr *)h->h_addr)))+1; - if((ip = (char *) calloc(sz, sizeof(char))) == NULL) - return(NULL); + if ((ip = (char *) calloc(IPSIZE, sizeof(char))) == NULL) { + if (result) { + freeaddrinfo(result); + } + return (NULL); + } - strncpy(ip,inet_ntoa(*((struct in_addr *)h->h_addr)), sz-1); + hai = result; + satop(hai->ai_addr, ip, IPSIZE); - return(ip); + freeaddrinfo(result); + return (ip); } - return(NULL); + return (NULL); +} + +/* satop(struct sockaddr *sa, char *dst, socklen_t size) + * Convert a sockaddr to a printable address. + */ +int satop(struct sockaddr *sa, char *dst, socklen_t size) +{ + sa_family_t af; + struct sockaddr_in *sa4; + struct sockaddr_in6 *sa6; +#ifdef WIN32 + int newlength; +#endif + + af = sa->sa_family; + + switch (af) + { + case AF_INET: + sa4 = (struct sockaddr_in *) sa; +#ifdef WIN32 + newlength = size; + WSAAddressToString((LPSOCKADDR) sa4, sizeof(struct sockaddr_in), + NULL, dst, (LPDWORD) &newlength); +#else + inet_ntop(af, (const void *) &(sa4->sin_addr), dst, size); +#endif + return(0); + case AF_INET6: + sa6 = (struct sockaddr_in6 *) sa; +#ifdef WIN32 + newlength = size; + WSAAddressToString((LPSOCKADDR) sa6, sizeof(struct sockaddr_in6), + NULL, dst, (LPDWORD) &newlength); +#else + inet_ntop(af, (const void *) &(sa6->sin6_addr), dst, size); +#endif + if (IN6_IS_ADDR_V4MAPPED(&(sa6->sin6_addr))) + { /* extract the embedded IPv4 address */ + memmove(dst, dst+7, size-7); + } + return(0); + default: + *dst = '\0'; + return(-1); + } } int OS_CloseSocket(int socket) { - #ifdef WIN32 +#ifdef WIN32 return (closesocket(socket)); - #else +#else return (close(socket)); - #endif /* WIN32 */ +#endif /* WIN32 */ +} + + +/* + * OS_DecodeAddrinfo() will decode the contents of an addrinfo structure and + * log the IP version, address, and port number for each item in the + * linked list of addrinfo structs. + */ + +int OS_DecodeAddrinfo (struct addrinfo *res) { + struct addrinfo *p; /* pointer to addrinfo structs */ + + for (p = res; p != NULL; p = p->ai_next) + verbose ("%s",OS_DecodeSockaddr (p->ai_addr)); + return 0; +} + + +/* + * OS_DecodeSockaddr() will decode a socket address and return a string with + * the IP version, address, and port number. + */ + +char *OS_DecodeSockaddr (struct sockaddr *sa) { + int rc; /* return code */ + char ipaddr[INET6_ADDRSTRLEN]; /* printed address */ + char ipport[NI_MAXSERV]; /* printed port */ + static char buf[256]; /* message buffer */ + +#if defined(__linux__) || defined (WIN32) + /* most Linux systems do not have sa_len in the sockaddr struct */ + socklen_t slen = 0; + switch(sa->sa_family) { + case AF_INET: + slen = sizeof(struct sockaddr_in); + break; + case AF_INET6: + slen = sizeof(struct sockaddr_in6); + break; + default: + // XXX WTF + break; + } + rc = getnameinfo ((struct sockaddr *) sa, slen, ipaddr, + sizeof (ipaddr), ipport, sizeof (ipport), + NI_NUMERICHOST | NI_NUMERICSERV); +#else + /* BSD systems require the value in sa->sa_len or error 4 occurs */ + rc = getnameinfo ((struct sockaddr *) sa, sa->sa_len, ipaddr, + sizeof (ipaddr), ipport, sizeof (ipport), + NI_NUMERICHOST | NI_NUMERICSERV); +#endif + + if (rc) { + sprintf (buf, "Error %d on getnameinfo: %s", rc, gai_strerror (rc)); + return (buf); + } + + sprintf (buf, "%s: %s on port %s", + DecodeFamily (sa->sa_family), ipaddr, ipport); + return buf; +} + + +/* + * DecodeFamily() is used to convert the IP family into a string for info + * and debugging purposes. + */ + +char *DecodeFamily (int val) { + static char buf[32]; /* response */ + + switch (val) { + case AF_INET: + strcpy (buf,"IPv4"); + break; + case AF_INET6: + strcpy (buf,"IPv6"); + break; + default: + sprintf (buf, "Unknown Family %d", val); + break; + } + + return (buf); +} + + +/* + * DecodeSocktype() is used to convert the IP socket type into a string for + * info and debugging purposes. + */ + +char *DecodeSocktype (int val) { + static char buf[32]; /* response */ + + switch (val) { + case SOCK_STREAM: + strcpy (buf,"STREAM"); + break; + case SOCK_DGRAM: + strcpy (buf,"DGRAM"); + break; + case SOCK_RAW: + strcpy (buf,"RAW"); + break; + default: + sprintf (buf, "Unknown Sock Type %d", val); + break; + } + + return (buf); +} + + +/* + * DecodeProtocol() is used to convert the IP protocol into a string for info + * and debugging purposes. + */ + +char *DecodeProtocol (int val) { + static char buf[32]; /* response */ + + switch (val) { + case IPPROTO_IP: + strcpy (buf,"IP"); + break; + case IPPROTO_ICMP: + strcpy (buf,"ICMP"); + break; + case IPPROTO_TCP: + strcpy (buf,"TCP"); + break; + case IPPROTO_UDP: + strcpy (buf,"UDP"); + break; + default: + sprintf (buf, "Unknown Protocol %d", val); + break; + } + + return (buf); } -/* EOF */