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