Imported Upstream version 2.5.1
[ossec-hids.git] / src / os_net / os_net.c
1 /* @(#) $Id$ */
2
3 /* Copyright (C) 2009 Trend Micro Inc.
4  * All rights reserved.
5  *
6  * This program is a free software; you can redistribute it
7  * and/or modify it under the terms of the GNU General Public
8  * License (version 2) as published by the FSF - Free Software 
9  * Foundation
10  *
11  * License details at the LICENSE file included with OSSEC or
12  * online at: http://www.ossec.net/en/licensing.html
13  */
14
15 /* OS_net Library. 
16  * APIs for many network operations.
17  */
18  
19  
20
21
22 #include "shared.h"
23 #include "os_net.h"
24
25
26 struct sockaddr_in _c;      /* Client socket */
27 socklen_t _cl;              /* Client socket length */
28
29
30 /* Unix socket -- not for windows */
31 #ifndef WIN32
32 struct sockaddr_un n_us;
33 socklen_t us_l = sizeof(n_us);
34
35 /* UNIX SOCKET */
36 #ifndef SUN_LEN
37 #define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path)        \
38                                       + strlen ((ptr)->sun_path))
39 #endif /* Sun_LEN */
40
41 #else
42 int ENOBUFS = 0;
43 #endif /* WIN32*/
44
45
46 /* OS_Bindport v 0.2, 2005/02/11
47  * Bind a specific port
48  * v0.2: Added REUSEADDR.
49  */
50 int OS_Bindport(unsigned int _port, unsigned int _proto, char *_ip)
51 {
52     int ossock;
53     struct sockaddr_in server;
54
55     
56     if(_proto == IPPROTO_UDP)
57     {
58         if((ossock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
59         {
60             return OS_SOCKTERR;
61         }
62     }
63     else if(_proto == IPPROTO_TCP)
64     {
65         int flag = 1;
66         if((ossock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
67         {
68             return(int)(OS_SOCKTERR);
69         }
70             
71         if(setsockopt(ossock, SOL_SOCKET, SO_REUSEADDR, 
72                               (char *)&flag,  sizeof(flag)) < 0)
73         {
74             return(OS_SOCKTERR);
75         }
76     }
77     else
78     {
79         return(OS_INVALID);
80     }
81
82     memset(&server, 0, sizeof(server));
83     server.sin_family = AF_INET;
84     server.sin_port = htons( _port );
85
86     if((_ip == NULL)||(_ip[0] == '\0'))
87         server.sin_addr.s_addr = htonl(INADDR_ANY);
88     else
89         server.sin_addr.s_addr = inet_addr(_ip);
90
91     if(bind(ossock, (struct sockaddr *) &server, sizeof(server)) < 0)
92     {
93         return(OS_SOCKTERR);
94     }
95
96     if(_proto == IPPROTO_TCP)
97     {
98         if(listen(ossock, 32) < 0)
99         {
100             return(OS_SOCKTERR);
101         }
102     }
103     
104     
105     _cl = sizeof(_c);
106     return(ossock);
107 }
108
109
110 /* OS_Bindporttcp v 0.1
111  * Bind a TCP port, using the OS_Bindport
112  */
113 int OS_Bindporttcp(unsigned int _port, char *_ip)
114 {
115     return(OS_Bindport(_port, IPPROTO_TCP, _ip));
116 }
117
118
119 /* OS_Bindportudp v 0.1
120  * Bind a UDP port, using the OS_Bindport
121  */
122 int OS_Bindportudp(unsigned int _port, char *_ip)
123 {
124     return(OS_Bindport(_port, IPPROTO_UDP, _ip));
125 }
126
127 #ifndef WIN32
128 /* OS_BindUnixDomain v0.1, 2004/07/29
129  * Bind to a Unix domain, using DGRAM sockets
130  */
131 int OS_BindUnixDomain(char * path, int mode, int max_msg_size)
132 {
133     int len;
134     int ossock = 0;
135     socklen_t optlen = sizeof(len);
136
137     /* Making sure the path isn't there */
138     unlink(path);
139     
140     memset(&n_us, 0, sizeof(n_us));
141     n_us.sun_family = AF_UNIX;
142     strncpy(n_us.sun_path, path, sizeof(n_us.sun_path)-1);
143
144     if((ossock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
145         return(OS_SOCKTERR);
146
147     if(bind(ossock, (struct sockaddr *)&n_us, SUN_LEN(&n_us)) < 0)
148     {
149         close(ossock);
150         return(OS_SOCKTERR);
151     }
152     
153     /* Changing permissions */
154     chmod(path,mode);
155     
156     
157     /* Getting current maximum size */
158     if(getsockopt(ossock, SOL_SOCKET, SO_RCVBUF, &len, &optlen) == -1)
159         return(OS_SOCKTERR);
160     
161                     
162     /* Setting socket opt */
163     if(len < max_msg_size)
164     {
165         len = max_msg_size;
166         setsockopt(ossock, SOL_SOCKET, SO_RCVBUF, &len, optlen);
167     }
168                                             
169     return(ossock);
170 }
171
172 /* OS_ConnectUnixDomain v0.1, 2004/07/29
173  * Open a client Unix domain socket
174  * ("/tmp/lala-socket",0666));
175  *
176  */
177 int OS_ConnectUnixDomain(char * path, int max_msg_size)
178 {
179     int len;
180     int ossock = 0;
181     socklen_t optlen = sizeof(len);
182
183     memset(&n_us, 0, sizeof(n_us));
184
185     n_us.sun_family = AF_UNIX;
186
187     /* Setting up path */
188     strncpy(n_us.sun_path,path,sizeof(n_us.sun_path)-1);        
189
190     if((ossock = socket(AF_UNIX, SOCK_DGRAM,0)) < 0)
191         return(OS_SOCKTERR);
192
193
194     /* Connecting to the UNIX domain.
195      * We can use "send" after that
196      */
197     if(connect(ossock,(struct sockaddr *)&n_us,SUN_LEN(&n_us)) < 0)
198         return(OS_SOCKTERR);
199
200
201     /* Getting current maximum size */
202     if(getsockopt(ossock, SOL_SOCKET, SO_SNDBUF, &len, &optlen) == -1)
203         return(OS_SOCKTERR);
204
205
206     /* Setting maximum message size */
207     if(len < max_msg_size)
208     {
209         len = max_msg_size;
210         setsockopt(ossock, SOL_SOCKET, SO_SNDBUF, &len, optlen);
211     }
212     
213     
214     /* Returning the socket */  
215     return(ossock);
216 }
217
218
219 int OS_getsocketsize(int ossock)
220 {
221     int len = 0;
222     socklen_t optlen = sizeof(len);
223
224     /* Getting current maximum size */
225     if(getsockopt(ossock, SOL_SOCKET, SO_SNDBUF, &len, &optlen) == -1)
226         return(OS_SOCKTERR);
227     
228     return(len);    
229 }
230
231 #endif
232
233 /* OS_Connect v 0.1, 2004/07/21
234  * Open a TCP/UDP client socket 
235  */
236 int OS_Connect(unsigned int _port, unsigned int protocol, char *_ip)
237 {
238     int ossock;
239     struct sockaddr_in server;
240
241     if(protocol == IPPROTO_TCP)
242     {
243         if((ossock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0)
244             return(OS_SOCKTERR);
245     }
246     else if(protocol == IPPROTO_UDP)
247     {
248         if((ossock = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0)
249             return(OS_SOCKTERR);
250     }
251     else
252         return(OS_INVALID);
253
254     _cl = sizeof(server);       
255
256     memset(&server, 0, _cl);
257     server.sin_family = AF_INET;
258     server.sin_port = htons( _port );
259
260     if((_ip == NULL)||(_ip[0] == '\0'))
261         return(OS_INVALID);        
262
263     server.sin_addr.s_addr = inet_addr(_ip);
264
265     if(connect(ossock,(struct sockaddr *)&server, _cl) < 0)
266         return(OS_SOCKTERR);
267
268     return(ossock);
269 }
270
271
272 /* OS_ConnectTCP, v0.1
273  * Open a TCP socket
274  */
275 int OS_ConnectTCP(unsigned int _port, char *_ip)
276 {
277     return(OS_Connect(_port, IPPROTO_TCP,_ip));
278 }
279
280
281 /* OS_ConnectUDP, v0.1
282  * Open a UDP socket 
283  */
284 int OS_ConnectUDP(unsigned int _port, char *_ip)
285 {
286     return(OS_Connect(_port, IPPROTO_UDP,_ip));
287 }
288
289 /* OS_SendTCP v0.1, 2004/07/21
290  * Send a TCP packet (in a open socket)
291  */
292 int OS_SendTCP(int socket, char *msg)
293 {
294     if((send(socket, msg, strlen(msg),0)) <= 0)
295         return (OS_SOCKTERR);
296
297     return(0);
298 }
299
300 /* OS_SendTCPbySize v0.1, 2004/07/21
301  * Send a TCP packet (in a open socket) of a specific size
302  */
303 int OS_SendTCPbySize(int socket, int size, char *msg)
304 {
305     if((send(socket, msg, size, 0)) < size)
306         return (OS_SOCKTERR);
307         
308     return(0);
309 }
310
311
312 /* OS_SendUDPbySize v0.1, 2004/07/21
313  * Send a UDP packet (in a open socket) of a specific size
314  */
315 int OS_SendUDPbySize(int socket, int size, char *msg)
316 {
317     int i = 0;
318
319     /* Maximum attempts is 5 */
320     while((send(socket,msg,size,0)) < 0)
321     {
322         if((errno != ENOBUFS) || (i >= 5))
323         {
324             return(OS_SOCKTERR);
325         }
326
327         i++;    
328         merror("%s: INFO: Remote socket busy, waiting %d s.", __local_name, i);
329         sleep(i);    
330     }
331         
332     return(0);
333 }
334
335
336
337 /* OS_AcceptTCP v0.1, 2005/01/28
338  * Accept a TCP connection
339  */
340 int OS_AcceptTCP(int socket, char *srcip, int addrsize)
341 {
342     int clientsocket;
343     struct sockaddr_in _nc;
344     socklen_t _ncl;
345     
346     memset(&_nc, 0, sizeof(_nc));
347     _ncl = sizeof(_nc);
348
349     if((clientsocket = accept(socket, (struct sockaddr *) &_nc,
350                     &_ncl)) < 0)
351         return(-1);     
352
353     strncpy(srcip, inet_ntoa(_nc.sin_addr),addrsize -1);
354     srcip[addrsize -1]='\0';
355
356     return(clientsocket);
357 }
358
359
360 /* OS_RecvTCP v0.1, 2004/07/21
361  * Receive a TCP packet (in a open socket)
362  */
363 char *OS_RecvTCP(int socket, int sizet)
364 {
365     char *ret;
366
367     int retsize=0;
368
369     ret = (char *) calloc((sizet), sizeof(char));
370     if(ret == NULL)
371         return(NULL);
372         
373     if((retsize = recv(socket, ret, sizet-1,0)) <= 0)
374         return(NULL);
375
376     return(ret);
377 }
378
379
380 /* OS_RecvTCPBuffer v0.1, 2004/07/21
381  * Receive a TCP packet (in a open socket)
382  */
383 int OS_RecvTCPBuffer(int socket, char *buffer, int sizet)
384 {
385     int retsize = 0;
386
387     while(!retsize)
388     {
389         retsize = recv(socket, buffer, sizet -1, 0);
390         if(retsize > 0)
391         {
392             buffer[retsize] = '\0';
393             return(0);
394         }
395         return(-1);
396     }
397     return(-1);
398 }
399
400
401
402
403 /* OS_RecvUDP v 0.1, 2004/07/20
404  * Receive a UDP packet
405  */
406 char *OS_RecvUDP(int socket, int sizet)
407 {
408     char *ret;
409     
410     ret = (char *) calloc((sizet), sizeof(char));
411     if(ret == NULL)
412         return(NULL);
413
414     if((recvfrom(socket,ret,sizet-1,0,(struct sockaddr *)&_c,&_cl))<0)
415         return(NULL);
416
417     return(ret);
418 }
419
420
421 /* OS_RecvConnUDP v0.1
422  * Receives a message from a connected UDP socket
423  */
424 int OS_RecvConnUDP(int socket, char *buffer, int buffer_size)
425 {
426     int recv_b;
427
428     recv_b = recv(socket, buffer, buffer_size, 0);
429     if(recv_b < 0)
430         return(0);
431     
432     return(recv_b);    
433 }
434
435
436 #ifndef WIN32
437 /* OS_RecvUnix, v0.1, 2004/07/29
438  * Receive a message using a Unix socket
439  */
440 int OS_RecvUnix(int socket, int sizet, char *ret)
441 {
442     ssize_t recvd;
443     if((recvd = recvfrom(socket, ret, sizet -1, 0, 
444                          (struct sockaddr*)&n_us,&us_l)) < 0)
445         return(0);
446
447     ret[recvd] = '\0';
448     return((int)recvd);
449 }
450
451
452 /* OS_SendUnix, v0.1, 2004/07/29
453  * Send a message using a Unix socket.
454  * Returns the OS_SOCKETERR if it 
455  */ 
456 int OS_SendUnix(int socket, char * msg, int size)
457 {
458     if(size == 0)
459         size = strlen(msg)+1;
460         
461     if(send(socket, msg, size,0) < size)
462     {
463         if(errno == ENOBUFS)
464             return(OS_SOCKBUSY);
465
466         return(OS_SOCKTERR);
467     }
468     
469     return(OS_SUCCESS);
470 }
471 #endif
472
473
474 /* OS_GetHost, v0.1, 2005/01/181
475  * Calls gethostbyname (tries x attempts)
476  */
477 char *OS_GetHost(char *host, int attempts)
478 {
479     int i = 0;
480     int sz;
481     
482     char *ip;
483     struct hostent *h;
484
485     if(host == NULL)
486         return(NULL);
487     
488     while(i <= attempts)
489     {
490         if((h = gethostbyname(host)) == NULL)
491         {
492             sleep(i++);
493             continue;
494         }
495
496         sz = strlen(inet_ntoa(*((struct in_addr *)h->h_addr)))+1;
497         if((ip = (char *) calloc(sz, sizeof(char))) == NULL)
498             return(NULL);
499
500         strncpy(ip,inet_ntoa(*((struct in_addr *)h->h_addr)), sz-1);
501
502         return(ip);
503     }
504
505     return(NULL);
506 }
507
508 /* EOF */