1 /* @(#) $Id: ./src/os_net/os_net.c, 2011/09/08 dcid Exp $
4 /* Copyright (C) 2009 Trend Micro Inc.
7 * This program is a free software; you can redistribute it
8 * and/or modify it under the terms of the GNU General Public
9 * License (version 2) as published by the FSF - Free Software
12 * License details at the LICENSE file included with OSSEC or
13 * online at: http://www.ossec.net/en/licensing.html
17 * APIs for many network operations.
29 /* Unix socket -- not for windows */
31 struct sockaddr_un n_us;
32 socklen_t us_l = sizeof(n_us);
36 #define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
37 + strlen ((ptr)->sun_path))
45 /* OS_Bindport v 0.2, 2005/02/11
46 * Bind a specific port
47 * v0.2: Added REUSEADDR.
49 int OS_Bindport(unsigned int _port, unsigned int _proto, char *_ip, int ipv6)
52 struct sockaddr_in server;
55 struct sockaddr_in6 server6;
61 if(_proto == IPPROTO_UDP)
63 if((ossock = socket(ipv6 == 1?PF_INET6:PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
68 else if(_proto == IPPROTO_TCP)
71 if((ossock = socket(ipv6 == 1?PF_INET6:PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
73 return(int)(OS_SOCKTERR);
76 if(setsockopt(ossock, SOL_SOCKET, SO_REUSEADDR,
77 (char *)&flag, sizeof(flag)) < 0)
90 memset(&server6, 0, sizeof(server6));
91 server6.sin6_family = AF_INET6;
92 server6.sin6_port = htons( _port );
93 server6.sin6_addr = in6addr_any;
96 if(bind(ossock, (struct sockaddr *) &server6, sizeof(server6)) < 0)
104 memset(&server, 0, sizeof(server));
105 server.sin_family = AF_INET;
106 server.sin_port = htons( _port );
109 if((_ip == NULL)||(_ip[0] == '\0'))
110 server.sin_addr.s_addr = htonl(INADDR_ANY);
112 server.sin_addr.s_addr = inet_addr(_ip);
115 if(bind(ossock, (struct sockaddr *) &server, sizeof(server)) < 0)
123 if(_proto == IPPROTO_TCP)
125 if(listen(ossock, 32) < 0)
136 /* OS_Bindporttcp v 0.1
137 * Bind a TCP port, using the OS_Bindport
139 int OS_Bindporttcp(unsigned int _port, char *_ip, int ipv6)
141 return(OS_Bindport(_port, IPPROTO_TCP, _ip, ipv6));
145 /* OS_Bindportudp v 0.1
146 * Bind a UDP port, using the OS_Bindport
148 int OS_Bindportudp(unsigned int _port, char *_ip, int ipv6)
150 return(OS_Bindport(_port, IPPROTO_UDP, _ip, ipv6));
154 /* OS_BindUnixDomain v0.1, 2004/07/29
155 * Bind to a Unix domain, using DGRAM sockets
157 int OS_BindUnixDomain(char * path, int mode, int max_msg_size)
161 socklen_t optlen = sizeof(len);
163 /* Making sure the path isn't there */
166 memset(&n_us, 0, sizeof(n_us));
167 n_us.sun_family = AF_UNIX;
168 strncpy(n_us.sun_path, path, sizeof(n_us.sun_path)-1);
170 if((ossock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
173 if(bind(ossock, (struct sockaddr *)&n_us, SUN_LEN(&n_us)) < 0)
179 /* Changing permissions */
183 /* Getting current maximum size */
184 if(getsockopt(ossock, SOL_SOCKET, SO_RCVBUF, &len, &optlen) == -1)
188 /* Setting socket opt */
189 if(len < max_msg_size)
192 setsockopt(ossock, SOL_SOCKET, SO_RCVBUF, &len, optlen);
198 /* OS_ConnectUnixDomain v0.1, 2004/07/29
199 * Open a client Unix domain socket
200 * ("/tmp/lala-socket",0666));
203 int OS_ConnectUnixDomain(char * path, int max_msg_size)
207 socklen_t optlen = sizeof(len);
209 memset(&n_us, 0, sizeof(n_us));
211 n_us.sun_family = AF_UNIX;
213 /* Setting up path */
214 strncpy(n_us.sun_path,path,sizeof(n_us.sun_path)-1);
216 if((ossock = socket(AF_UNIX, SOCK_DGRAM,0)) < 0)
220 /* Connecting to the UNIX domain.
221 * We can use "send" after that
223 if(connect(ossock,(struct sockaddr *)&n_us,SUN_LEN(&n_us)) < 0)
227 /* Getting current maximum size */
228 if(getsockopt(ossock, SOL_SOCKET, SO_SNDBUF, &len, &optlen) == -1)
232 /* Setting maximum message size */
233 if(len < max_msg_size)
236 setsockopt(ossock, SOL_SOCKET, SO_SNDBUF, &len, optlen);
240 /* Returning the socket */
245 int OS_getsocketsize(int ossock)
248 socklen_t optlen = sizeof(len);
250 /* Getting current maximum size */
251 if(getsockopt(ossock, SOL_SOCKET, SO_SNDBUF, &len, &optlen) == -1)
259 /* OS_Connect v 0.1, 2004/07/21
260 * Open a TCP/UDP client socket
262 int OS_Connect(unsigned int _port, unsigned int protocol, char *_ip, int ipv6)
265 struct sockaddr_in server;
268 struct sockaddr_in6 server6;
273 if(protocol == IPPROTO_TCP)
275 if((ossock = socket(ipv6 == 1?PF_INET6:PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0)
278 else if(protocol == IPPROTO_UDP)
280 if((ossock = socket(ipv6 == 1?PF_INET6:PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0)
291 flags = fcntl(ossock,F_GETFL,0);
292 fcntl(ossock, F_SETFL, flags | O_NONBLOCK);
298 if((_ip == NULL)||(_ip[0] == '\0'))
305 memset(&server6, 0, sizeof(server6));
306 server6.sin6_family = AF_INET6;
307 server6.sin6_port = htons( _port );
308 inet_pton(AF_INET6, _ip, &server6.sin6_addr.s6_addr);
310 if(connect(ossock,(struct sockaddr *)&server6, sizeof(server6)) < 0)
316 memset(&server, 0, sizeof(server));
317 server.sin_family = AF_INET;
318 server.sin_port = htons( _port );
319 server.sin_addr.s_addr = inet_addr(_ip);
322 if(connect(ossock,(struct sockaddr *)&server, sizeof(server)) < 0)
331 /* OS_ConnectTCP, v0.1
334 int OS_ConnectTCP(unsigned int _port, char *_ip, int ipv6)
336 return(OS_Connect(_port, IPPROTO_TCP, _ip, ipv6));
340 /* OS_ConnectUDP, v0.1
343 int OS_ConnectUDP(unsigned int _port, char *_ip, int ipv6)
345 return(OS_Connect(_port, IPPROTO_UDP, _ip, ipv6));
348 /* OS_SendTCP v0.1, 2004/07/21
349 * Send a TCP packet (in a open socket)
351 int OS_SendTCP(int socket, char *msg)
353 if((send(socket, msg, strlen(msg),0)) <= 0)
354 return (OS_SOCKTERR);
359 /* OS_SendTCPbySize v0.1, 2004/07/21
360 * Send a TCP packet (in a open socket) of a specific size
362 int OS_SendTCPbySize(int socket, int size, char *msg)
364 if((send(socket, msg, size, 0)) < size)
365 return (OS_SOCKTERR);
371 /* OS_SendUDPbySize v0.1, 2004/07/21
372 * Send a UDP packet (in a open socket) of a specific size
374 int OS_SendUDPbySize(int socket, int size, char *msg)
378 /* Maximum attempts is 5 */
379 while((send(socket,msg,size,0)) < 0)
381 if((errno != ENOBUFS) || (i >= 5))
387 merror("%s: INFO: Remote socket busy, waiting %d s.", __local_name, i);
396 /* OS_AcceptTCP v0.1, 2005/01/28
397 * Accept a TCP connection
399 int OS_AcceptTCP(int socket, char *srcip, int addrsize)
402 struct sockaddr_in _nc;
405 memset(&_nc, 0, sizeof(_nc));
408 if((clientsocket = accept(socket, (struct sockaddr *) &_nc,
412 strncpy(srcip, inet_ntoa(_nc.sin_addr),addrsize -1);
413 srcip[addrsize -1]='\0';
415 return(clientsocket);
419 /* OS_RecvTCP v0.1, 2004/07/21
420 * Receive a TCP packet (in a open socket)
422 char *OS_RecvTCP(int socket, int sizet)
428 ret = (char *) calloc((sizet), sizeof(char));
432 if((retsize = recv(socket, ret, sizet-1,0)) <= 0)
439 /* OS_RecvTCPBuffer v0.1, 2004/07/21
440 * Receive a TCP packet (in a open socket)
442 int OS_RecvTCPBuffer(int socket, char *buffer, int sizet)
448 retsize = recv(socket, buffer, sizet -1, 0);
451 buffer[retsize] = '\0';
462 /* OS_RecvUDP v 0.1, 2004/07/20
463 * Receive a UDP packet
465 char *OS_RecvUDP(int socket, int sizet)
469 ret = (char *) calloc((sizet), sizeof(char));
473 if((recv(socket,ret,sizet-1,0))<0)
480 /* OS_RecvConnUDP v0.1
481 * Receives a message from a connected UDP socket
483 int OS_RecvConnUDP(int socket, char *buffer, int buffer_size)
487 recv_b = recv(socket, buffer, buffer_size, 0);
496 /* OS_RecvUnix, v0.1, 2004/07/29
497 * Receive a message using a Unix socket
499 int OS_RecvUnix(int socket, int sizet, char *ret)
502 if((recvd = recvfrom(socket, ret, sizet -1, 0,
503 (struct sockaddr*)&n_us,&us_l)) < 0)
511 /* OS_SendUnix, v0.1, 2004/07/29
512 * Send a message using a Unix socket.
513 * Returns the OS_SOCKETERR if it
515 int OS_SendUnix(int socket, char * msg, int size)
518 size = strlen(msg)+1;
520 if(send(socket, msg, size,0) < size)
533 /* OS_GetHost, v0.1, 2005/01/181
534 * Calls gethostbyname (tries x attempts)
536 char *OS_GetHost(char *host, int attempts)
549 if((h = gethostbyname(host)) == NULL)
555 sz = strlen(inet_ntoa(*((struct in_addr *)h->h_addr)))+1;
556 if((ip = (char *) calloc(sz, sizeof(char))) == NULL)
559 strncpy(ip,inet_ntoa(*((struct in_addr *)h->h_addr)), sz-1);