Imported Upstream version 2.7
[ossec-hids.git] / src / os_net / os_net.c
index 1921609..c282b9f 100755 (executable)
@@ -1,30 +1,29 @@
-/* @(#) $Id$ */
+/* @(#) $Id: ./src/os_net/os_net.c, 2011/09/08 dcid Exp $
+ */
 
 /* Copyright (C) 2009 Trend Micro Inc.
  * All rights reserved.
  *
  * This program is a free software; you can redistribute it
  * and/or modify it under the terms of the GNU General Public
- * License (version 2) as published by the FSF - Free Software 
+ * 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. 
+/* OS_net Library.
  * APIs for many network operations.
  */
+
+
 
 
 #include "shared.h"
 #include "os_net.h"
 
 
-struct sockaddr_in _c;     /* Client socket */
-socklen_t _cl;              /* Client socket length */
 
 
 /* Unix socket -- not for windows */
@@ -47,15 +46,21 @@ int ENOBUFS = 0;
  * Bind a specific port
  * v0.2: Added REUSEADDR.
  */
-int OS_Bindport(unsigned int _port, unsigned int _proto, char *_ip)
+int OS_Bindport(unsigned int _port, unsigned int _proto, char *_ip, int ipv6)
 {
     int ossock;
     struct sockaddr_in server;
 
-    
+    #ifndef WIN32
+    struct sockaddr_in6 server6;
+    #else
+    ipv6 = 0;
+    #endif
+
+
     if(_proto == IPPROTO_UDP)
     {
-        if((ossock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+        if((ossock = socket(ipv6 == 1?PF_INET6:PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
         {
             return OS_SOCKTERR;
         }
@@ -63,12 +68,12 @@ int OS_Bindport(unsigned int _port, unsigned int _proto, char *_ip)
     else if(_proto == IPPROTO_TCP)
     {
         int flag = 1;
-        if((ossock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+        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, 
+
+        if(setsockopt(ossock, SOL_SOCKET, SO_REUSEADDR,
                               (char *)&flag,  sizeof(flag)) < 0)
         {
             return(OS_SOCKTERR);
@@ -79,20 +84,42 @@ int OS_Bindport(unsigned int _port, unsigned int _proto, char *_ip)
         return(OS_INVALID);
     }
 
-    memset(&server, 0, sizeof(server));
-    server.sin_family = AF_INET;
-    server.sin_port = htons( _port );
+    if(ipv6)
+    {
+        #ifndef WIN32
+        memset(&server6, 0, sizeof(server6));
+        server6.sin6_family = AF_INET6;
+        server6.sin6_port = htons( _port );
+        server6.sin6_addr = in6addr_any;
 
-    if((_ip == NULL)||(_ip[0] == '\0'))
-        server.sin_addr.s_addr = htonl(INADDR_ANY);
-    else
-        server.sin_addr.s_addr = inet_addr(_ip);
 
-    if(bind(ossock, (struct sockaddr *) &server, sizeof(server)) < 0)
+        if(bind(ossock, (struct sockaddr *) &server6, sizeof(server6)) < 0)
+        {
+            return(OS_SOCKTERR);
+        }
+        #endif
+    }
+    else
     {
-        return(OS_SOCKTERR);
+        memset(&server, 0, sizeof(server));
+        server.sin_family = AF_INET;
+        server.sin_port = htons( _port );
+
+
+        if((_ip == NULL)||(_ip[0] == '\0'))
+            server.sin_addr.s_addr = htonl(INADDR_ANY);
+        else
+            server.sin_addr.s_addr = inet_addr(_ip);
+
+
+        if(bind(ossock, (struct sockaddr *) &server, sizeof(server)) < 0)
+        {
+            return(OS_SOCKTERR);
+        }
     }
 
+
+
     if(_proto == IPPROTO_TCP)
     {
         if(listen(ossock, 32) < 0)
@@ -100,9 +127,8 @@ int OS_Bindport(unsigned int _port, unsigned int _proto, char *_ip)
             return(OS_SOCKTERR);
         }
     }
-    
-    
-    _cl = sizeof(_c);
+
+
     return(ossock);
 }
 
@@ -110,18 +136,18 @@ int OS_Bindport(unsigned int _port, unsigned int _proto, char *_ip)
 /* OS_Bindporttcp v 0.1
  * Bind a TCP port, using the OS_Bindport
  */
-int OS_Bindporttcp(unsigned int _port, char *_ip)
+int OS_Bindporttcp(unsigned int _port, char *_ip, int ipv6)
 {
-    return(OS_Bindport(_port, IPPROTO_TCP, _ip));
+    return(OS_Bindport(_port, IPPROTO_TCP, _ip, ipv6));
 }
 
 
 /* OS_Bindportudp v 0.1
  * Bind a UDP port, using the OS_Bindport
  */
-int OS_Bindportudp(unsigned int _port, char *_ip)
+int OS_Bindportudp(unsigned int _port, char *_ip, int ipv6)
 {
-    return(OS_Bindport(_port, IPPROTO_UDP, _ip));
+    return(OS_Bindport(_port, IPPROTO_UDP, _ip, ipv6));
 }
 
 #ifndef WIN32
@@ -136,7 +162,7 @@ int OS_BindUnixDomain(char * path, int mode, int max_msg_size)
 
     /* Making 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);
@@ -149,23 +175,23 @@ int OS_BindUnixDomain(char * path, int mode, int max_msg_size)
         close(ossock);
         return(OS_SOCKTERR);
     }
-    
+
     /* Changing permissions */
     chmod(path,mode);
-    
-    
+
+
     /* Getting current maximum size */
     if(getsockopt(ossock, SOL_SOCKET, SO_RCVBUF, &len, &optlen) == -1)
         return(OS_SOCKTERR);
-    
-                    
+
+
     /* Setting socket opt */
     if(len < max_msg_size)
     {
         len = max_msg_size;
         setsockopt(ossock, SOL_SOCKET, SO_RCVBUF, &len, optlen);
     }
-                                            
+
     return(ossock);
 }
 
@@ -209,8 +235,8 @@ int OS_ConnectUnixDomain(char * path, int max_msg_size)
         len = max_msg_size;
         setsockopt(ossock, SOL_SOCKET, SO_SNDBUF, &len, optlen);
     }
-    
-    
+
+
     /* Returning the socket */ 
     return(ossock);
 }
@@ -224,46 +250,79 @@ int OS_getsocketsize(int ossock)
     /* Getting current maximum size */
     if(getsockopt(ossock, SOL_SOCKET, SO_SNDBUF, &len, &optlen) == -1)
         return(OS_SOCKTERR);
-    
-    return(len);    
+
+    return(len);
 }
 
 #endif
 
 /* OS_Connect v 0.1, 2004/07/21
- * Open a TCP/UDP client socket 
+ * Open a TCP/UDP client socket
  */
-int OS_Connect(unsigned int _port, unsigned int protocol, char *_ip)
+int OS_Connect(unsigned int _port, unsigned int protocol, char *_ip, int ipv6)
 {
     int ossock;
     struct sockaddr_in server;
 
+    #ifndef WIN32
+    struct sockaddr_in6 server6;
+    #else
+    ipv6 = 0;
+    #endif
+
     if(protocol == IPPROTO_TCP)
     {
-        if((ossock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0)
+        if((ossock = socket(ipv6 == 1?PF_INET6:PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0)
             return(OS_SOCKTERR);
     }
     else if(protocol == IPPROTO_UDP)
     {
-        if((ossock = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0)
+        if((ossock = socket(ipv6 == 1?PF_INET6:PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0)
             return(OS_SOCKTERR);
     }
     else
         return(OS_INVALID);
 
-    _cl = sizeof(server);      
 
-    memset(&server, 0, _cl);
-    server.sin_family = AF_INET;
-    server.sin_port = htons( _port );
+
+    #ifdef HPUX
+    {
+    int flags;
+    flags = fcntl(ossock,F_GETFL,0);
+    fcntl(ossock, F_SETFL, flags | O_NONBLOCK);
+    }
+    #endif
+
+
 
     if((_ip == NULL)||(_ip[0] == '\0'))
-        return(OS_INVALID);        
+        return(OS_INVALID);
 
-    server.sin_addr.s_addr = inet_addr(_ip);
 
-    if(connect(ossock,(struct sockaddr *)&server, _cl) < 0)
-        return(OS_SOCKTERR);
+    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)
+            return(OS_SOCKTERR);
+        #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(connect(ossock,(struct sockaddr *)&server, sizeof(server)) < 0)
+            return(OS_SOCKTERR);
+    }
+
 
     return(ossock);
 }
@@ -272,18 +331,18 @@ int OS_Connect(unsigned int _port, unsigned int protocol, char *_ip)
 /* OS_ConnectTCP, v0.1
  * Open a TCP socket
  */
-int OS_ConnectTCP(unsigned int _port, char *_ip)
+int OS_ConnectTCP(unsigned int _port, char *_ip, int ipv6)
 {
-    return(OS_Connect(_port, IPPROTO_TCP,_ip));
+    return(OS_Connect(_port, IPPROTO_TCP, _ip, ipv6));
 }
 
 
 /* OS_ConnectUDP, v0.1
- * Open a UDP socket 
+ * Open a UDP socket
  */
-int OS_ConnectUDP(unsigned int _port, char *_ip)
+int OS_ConnectUDP(unsigned int _port, char *_ip, int ipv6)
 {
-    return(OS_Connect(_port, IPPROTO_UDP,_ip));
+    return(OS_Connect(_port, IPPROTO_UDP, _ip, ipv6));
 }
 
 /* OS_SendTCP v0.1, 2004/07/21
@@ -304,7 +363,7 @@ int OS_SendTCPbySize(int socket, int size, char *msg)
 {
     if((send(socket, msg, size, 0)) < size)
         return (OS_SOCKTERR);
-        
+
     return(0);
 }
 
@@ -324,11 +383,11 @@ int OS_SendUDPbySize(int socket, int size, char *msg)
             return(OS_SOCKTERR);
         }
 
-        i++;    
+        i++;
         merror("%s: INFO: Remote socket busy, waiting %d s.", __local_name, i);
-        sleep(i);    
+        sleep(i);
     }
-        
+
     return(0);
 }
 
@@ -342,7 +401,7 @@ int OS_AcceptTCP(int socket, char *srcip, int addrsize)
     int clientsocket;
     struct sockaddr_in _nc;
     socklen_t _ncl;
-    
+
     memset(&_nc, 0, sizeof(_nc));
     _ncl = sizeof(_nc);
 
@@ -369,7 +428,7 @@ char *OS_RecvTCP(int socket, int sizet)
     ret = (char *) calloc((sizet), sizeof(char));
     if(ret == NULL)
         return(NULL);
-        
+
     if((retsize = recv(socket, ret, sizet-1,0)) <= 0)
         return(NULL);
 
@@ -406,12 +465,12 @@ int OS_RecvTCPBuffer(int socket, char *buffer, int sizet)
 char *OS_RecvUDP(int socket, int sizet)
 {
     char *ret;
-    
+
     ret = (char *) calloc((sizet), sizeof(char));
     if(ret == NULL)
         return(NULL);
 
-    if((recvfrom(socket,ret,sizet-1,0,(struct sockaddr *)&_c,&_cl))<0)
+    if((recv(socket,ret,sizet-1,0))<0)
         return(NULL);
 
     return(ret);
@@ -428,8 +487,8 @@ int OS_RecvConnUDP(int socket, char *buffer, int buffer_size)
     recv_b = recv(socket, buffer, buffer_size, 0);
     if(recv_b < 0)
         return(0);
-    
-    return(recv_b);    
+
+    return(recv_b);
 }
 
 
@@ -440,7 +499,7 @@ int OS_RecvConnUDP(int socket, char *buffer, int buffer_size)
 int OS_RecvUnix(int socket, int sizet, char *ret)
 {
     ssize_t recvd;
-    if((recvd = recvfrom(socket, ret, sizet -1, 0, 
+    if((recvd = recvfrom(socket, ret, sizet -1, 0,
                          (struct sockaddr*)&n_us,&us_l)) < 0)
         return(0);
 
@@ -451,13 +510,13 @@ int OS_RecvUnix(int socket, int sizet, char *ret)
 
 /* OS_SendUnix, v0.1, 2004/07/29
  * Send a message using a Unix socket.
- * Returns the OS_SOCKETERR if it 
- */ 
+ * Returns the OS_SOCKETERR if it
+ */
 int OS_SendUnix(int socket, char * msg, int size)
 {
     if(size == 0)
         size = strlen(msg)+1;
-        
+
     if(send(socket, msg, size,0) < size)
     {
         if(errno == ENOBUFS)
@@ -465,7 +524,7 @@ int OS_SendUnix(int socket, char * msg, int size)
 
         return(OS_SOCKTERR);
     }
-    
+
     return(OS_SUCCESS);
 }
 #endif
@@ -478,13 +537,13 @@ char *OS_GetHost(char *host, int attempts)
 {
     int i = 0;
     int sz;
-    
+
     char *ip;
     struct hostent *h;
 
     if(host == NULL)
         return(NULL);
-    
+
     while(i <= attempts)
     {
         if((h = gethostbyname(host)) == NULL)