git migration: Refactor the ASTERISK_FILE_VERSION macro
[asterisk/asterisk.git] / addons / ooh323c / src / ooSocket.c
1 /*
2  * Copyright (C) 1997-2005 by Objective Systems, Inc.
3  *
4  * This software is furnished under an open source license and may be 
5  * used and copied only in accordance with the terms of this license. 
6  * The text of the license may generally be found in the root 
7  * directory of this installation in the COPYING file.  It 
8  * can also be viewed online at the following URL:
9  *
10  *   http://www.obj-sys.com/open/license.html
11  *
12  * Any redistributions of this file including modified versions must 
13  * maintain this copyright notice.
14  *
15  *****************************************************************************/
16 #include "asterisk.h"
17
18 ASTERISK_REGISTER_FILE()
19
20 #include "asterisk/io.h"
21 #include "asterisk/lock.h"
22 #include "asterisk/utils.h"
23 #include "asterisk/network.h"
24 #include "asterisk/netsock2.h"
25 #include "asterisk/config.h"
26
27 #include "ooSocket.h"
28 #include "ootrace.h"
29 #include "ooh323ep.h"
30
31 /** Global endpoint structure */
32 extern OOH323EndPoint gH323ep;
33
34 #if defined(_WIN32_WCE)
35 static int inited = 0;
36 #define SEND_FLAGS     0
37 #define SHUTDOWN_FLAGS 0
38 #elif defined (_WIN32)
39 static LPFN_SEND send;
40 static LPFN_SOCKET socket;
41 static LPFN_SETSOCKOPT setsockopt;
42 static LPFN_BIND bind;
43 static LPFN_HTONL htonl;
44 static LPFN_HTONS htons;
45 static LPFN_CONNECT connect;
46 static LPFN_INET_ADDR inet_addr;
47 static LPFN_LISTEN listen;
48 static LPFN_ACCEPT accept;
49 static LPFN_NTOHL ntohl;
50 static LPFN_NTOHS ntohs;
51 static LPFN_RECV recv;
52 static LPFN_SHUTDOWN shutdown;
53
54
55 static LPFN_IOCTLSOCKET ioctlsocket;
56 static LPFN_SENDTO sendto;
57 static LPFN_INET_NTOA inet_ntoa;
58 static LPFN_RECVFROM recvfrom;
59 static LPFN_SELECT select;
60 static LPFN_GETHOSTNAME gethostname;
61 static LPFN_GETHOSTBYNAME gethostbyname;
62 static LPFN_WSAGETLASTERROR  WSAGetLastError;
63 static LPFN_WSACLEANUP WSACleanup;
64 static LPFN_CLOSESOCKET closesocket;
65 static LPFN_GETSOCKNAME getsockname;
66 static HMODULE ws32 = 0;
67 #define SEND_FLAGS     0
68 #define SHUTDOWN_FLAGS SD_BOTH
69 #else
70 #define SEND_FLAGS     0
71 #define SHUTDOWN_FLAGS SHUT_RDWR
72 #define closesocket close
73 #endif
74
75
76
77 int ooSocketsInit ()
78 {
79 #if defined(_WIN32_WCE)
80    WORD wVersionRequested;
81    WSADATA wsaData;
82    int err;
83
84    if (inited) return ASN_OK; 
85
86    wVersionRequested = MAKEWORD( 1, 1 );
87     
88    err = WSAStartup (wVersionRequested, &wsaData);
89    if ( err != 0 ) {
90       /* Tell the user that we could not find a usable */
91       /* WinSock DLL.   */
92       return ASN_E_NOTINIT;
93    }
94    inited = 1;
95
96 #elif defined (_WIN32)
97    LPFN_WSASTARTUP wsaStartup = NULL;
98    WSADATA wsaData;
99
100    if (ws32 != 0) return ASN_OK;
101
102 //   ws32 = LoadLibrary ("WSOCK32.DLL");
103   ws32 = LoadLibrary ("WS2_32.DLL");
104    if (ws32 == NULL) return ASN_E_NOTINIT;
105    
106    wsaStartup = (LPFN_WSASTARTUP) GetProcAddress (ws32, "WSAStartup");
107    if (wsaStartup == NULL) return ASN_E_NOTINIT;
108    
109    send = (LPFN_SEND) GetProcAddress (ws32, "send");
110    if (send == NULL) return ASN_E_NOTINIT;
111    
112    socket = (LPFN_SOCKET) GetProcAddress (ws32, "socket");
113    if (socket == NULL) return ASN_E_NOTINIT;
114    
115    setsockopt = (LPFN_SETSOCKOPT) GetProcAddress (ws32, "setsockopt");
116    if (setsockopt == NULL) return ASN_E_NOTINIT;
117    
118    bind = (LPFN_BIND) GetProcAddress (ws32, "bind");
119    if (bind == NULL) return ASN_E_NOTINIT;
120    
121    htonl = (LPFN_HTONL) GetProcAddress (ws32, "htonl");
122    if (htonl == NULL) return ASN_E_NOTINIT;
123    
124    htons = (LPFN_HTONS) GetProcAddress (ws32, "htons");
125    if (htons == NULL) return ASN_E_NOTINIT;
126    
127    connect = (LPFN_CONNECT) GetProcAddress (ws32, "connect");
128    if (connect == NULL) return ASN_E_NOTINIT;
129    
130    listen = (LPFN_LISTEN) GetProcAddress (ws32, "listen");
131    if (listen == NULL) return ASN_E_NOTINIT;
132    
133    accept = (LPFN_ACCEPT) GetProcAddress (ws32, "accept");
134    if (accept == NULL) return ASN_E_NOTINIT;
135    
136    inet_addr = (LPFN_INET_ADDR) GetProcAddress (ws32, "inet_addr");
137    if (inet_addr == NULL) return ASN_E_NOTINIT;
138    
139    ntohl = (LPFN_NTOHL) GetProcAddress (ws32, "ntohl");
140    if (ntohl == NULL) return ASN_E_NOTINIT;
141    
142    ntohs = (LPFN_NTOHS) GetProcAddress (ws32, "ntohs");
143    if (ntohs == NULL) return ASN_E_NOTINIT;
144    
145    recv = (LPFN_RECV) GetProcAddress (ws32, "recv");
146    if (recv == NULL) return ASN_E_NOTINIT;
147    
148    shutdown = (LPFN_SHUTDOWN) GetProcAddress (ws32, "shutdown");
149    if (shutdown == NULL) return ASN_E_NOTINIT;
150    
151    closesocket = (LPFN_CLOSESOCKET) GetProcAddress (ws32, "closesocket");
152    if (closesocket == NULL) return ASN_E_NOTINIT;
153
154    getsockname = (LPFN_GETSOCKNAME) GetProcAddress (ws32, "getsockname");
155    if (getsockname == NULL) return ASN_E_NOTINIT;
156    
157    ioctlsocket = (LPFN_IOCTLSOCKET) GetProcAddress(ws32, "ioctlsocket");
158    if(ioctlsocket == NULL) return ASN_E_NOTINIT;
159
160    sendto = (LPFN_SENDTO) GetProcAddress (ws32, "sendto");
161    if (sendto == NULL) return ASN_E_NOTINIT;
162
163    inet_ntoa = (LPFN_INET_NTOA) GetProcAddress (ws32, "inet_ntoa");
164    if (inet_ntoa == NULL) return ASN_E_NOTINIT;
165
166    recvfrom = (LPFN_RECVFROM) GetProcAddress (ws32, "recvfrom");
167    if (recvfrom == NULL) return ASN_E_NOTINIT;
168
169    select = (LPFN_SELECT) GetProcAddress (ws32, "select");
170    if (select == NULL) return ASN_E_NOTINIT;
171
172    gethostname = (LPFN_GETHOSTNAME) GetProcAddress (ws32, "gethostname");
173    if (gethostname == NULL) return ASN_E_NOTINIT;
174
175    gethostbyname = (LPFN_GETHOSTBYNAME) GetProcAddress (ws32, "gethostbyname");
176    if (gethostbyname == NULL) return ASN_E_NOTINIT;
177    
178    WSAGetLastError = (LPFN_WSAGETLASTERROR) GetProcAddress (ws32, 
179                                                            "WSAGetLastError");
180    if (WSAGetLastError == NULL) return ASN_E_NOTINIT;
181
182    WSACleanup = (LPFN_WSACLEANUP) GetProcAddress (ws32, "WSACleanup");
183    if (WSACleanup == NULL) return ASN_E_NOTINIT;
184    
185       
186    if (wsaStartup (MAKEWORD(1, 1), &wsaData) == -1) return ASN_E_NOTINIT;
187 #endif
188    return ASN_OK;
189 }
190
191 #if defined (_WIN32) || \
192 defined(_HP_UX) || defined(__hpux) || defined(_HPUX_SOURCE)
193 typedef int OOSOCKLEN;
194 #else
195 typedef socklen_t OOSOCKLEN;
196 #endif
197
198 int ooSocketCreate (OOSOCKET* psocket, int family) 
199 {
200    int on;
201    OOSOCKET sock;
202    int keepalive = 1;
203 #ifdef __linux__
204    int keepcnt = 24, keepidle = 120, keepintvl = 30;
205 #endif
206    struct linger linger;
207
208    if (family == 6) {
209         sock = socket (AF_INET6,
210                                 SOCK_STREAM,
211                                 0);
212    } else {
213         sock = socket (AF_INET,
214                                 SOCK_STREAM,
215                                 0);
216    }
217   
218    if (sock == OOSOCKET_INVALID){
219       OOTRACEERR1("Error:Failed to create TCP socket\n");
220       return ASN_E_INVSOCKET;
221    }
222
223    on = 1;
224    if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, 
225                    (const char* ) &on, sizeof (on)) == -1)
226    {
227       OOTRACEERR1("Error:Failed to set socket option SO_REUSEADDR\n");
228       return ASN_E_INVSOCKET;
229    }
230    linger.l_onoff = 1;
231    linger.l_linger = 0;
232    if (setsockopt (sock, SOL_SOCKET, SO_LINGER, 
233                    (const char* ) &linger, sizeof (linger)) == -1)
234    {
235       OOTRACEERR1("Error:Failed to set socket option linger\n");
236       return ASN_E_INVSOCKET;
237    }
238    setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, (const char *)&keepalive,
239                         sizeof(keepalive));
240 #ifdef __linux__
241    setsockopt (sock, SOL_TCP, TCP_KEEPCNT, &keepcnt, sizeof(keepcnt));
242    setsockopt (sock, SOL_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle));
243    setsockopt (sock, SOL_TCP, TCP_KEEPINTVL, &keepintvl, sizeof(keepintvl));
244 #endif
245    *psocket = sock;
246    return ASN_OK;
247 }
248
249 int ooSocketCreateUDP (OOSOCKET* psocket, int family) 
250 {
251    int on;
252    OOSOCKET sock;
253
254    if (family == 6)
255         sock = socket (AF_INET6,
256                              SOCK_DGRAM,
257                              0);
258    else
259         sock = socket (AF_INET,
260                              SOCK_DGRAM,
261                              0);
262
263    if (sock == OOSOCKET_INVALID){
264       OOTRACEERR1("Error:Failed to create UDP socket\n");
265       return ASN_E_INVSOCKET;
266    }
267
268    on = 1;
269    if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, 
270                    (const char* ) &on, sizeof (on)) == -1)
271    {
272       OOTRACEERR1("Error:Failed to set socket option SO_REUSEADDR\n");
273       return ASN_E_INVSOCKET;
274    }
275    // may be will use later
276    /*
277    linger.l_onoff = 1;
278    linger.l_linger = 0;
279    if (setsockopt (sock, SOL_SOCKET, SO_LINGER, 
280                  (const char* ) &linger, sizeof (linger)) == -1)
281       return ASN_E_INVSOCKET;
282    */
283    *psocket = sock;
284    return ASN_OK;
285 }
286
287 int ooSocketClose (OOSOCKET socket)
288 {
289    shutdown (socket, SHUTDOWN_FLAGS);
290    if (closesocket (socket) == -1)
291       return ASN_E_INVSOCKET;
292    return ASN_OK;
293 }
294
295 int ooSocketBind (OOSOCKET socket, OOIPADDR addr, int port) 
296 {
297    struct ast_sockaddr m_addr;
298
299    memset(&m_addr, 0, sizeof(m_addr));
300
301
302    if (socket == OOSOCKET_INVALID)
303    { 
304       OOTRACEERR1("Error:Invalid socket passed to bind\n");
305       return ASN_E_INVSOCKET;
306    }
307
308    ast_sockaddr_copy(&m_addr, &addr);
309    ast_sockaddr_set_port(&m_addr, port);
310
311    if (ast_bind(socket, &m_addr) < 0) {
312       if (errno != EADDRINUSE) {
313         perror ("bind");
314         OOTRACEERR2("Error:Bind failed, error: %d\n", errno);
315       }
316       return ASN_E_INVSOCKET;
317    }
318
319    return ASN_OK;
320 }
321
322
323 int ooSocketGetSockName(OOSOCKET socket, struct sockaddr_in *name, socklen_t *size)
324 {
325    int ret;
326    ret = getsockname(socket, (struct sockaddr*)name, size);
327    if(ret == 0)
328       return ASN_OK;
329    else{
330       OOTRACEERR1("Error:ooSocketGetSockName - getsockname\n");
331       return ASN_E_INVSOCKET;
332    }
333 }
334
335 int ooSocketGetIpAndPort(OOSOCKET socket, char *ip, int len, int *port, int *family)
336 {
337    int ret=ASN_OK;
338    struct ast_sockaddr addr;
339    const char *host=NULL;
340
341    ret = ast_getsockname(socket, &addr);
342    if(ret != 0)
343       return ASN_E_INVSOCKET;
344
345    host = ast_sockaddr_stringify_addr(&addr);
346
347    if(host && strlen(host) < (unsigned)len)
348       strcpy(ip, host);   
349    else{
350      OOTRACEERR1("Error:Insufficient buffer for ip address - "
351                  "ooSocketGetIpAndPort\n");
352       return -1;
353    }
354    *port = ast_sockaddr_port(&addr);
355
356    if (family) {
357         if (ast_sockaddr_is_ipv6(&addr) && !ast_sockaddr_is_ipv4_mapped(&addr))
358                 *family = 6;
359         else
360                 *family = 4;
361    }
362
363    return ASN_OK;
364 }
365
366 int ooSocketListen (OOSOCKET socket, int maxConnection) 
367 {
368    if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;
369
370    if (listen (socket, maxConnection) == -1)
371       return ASN_E_INVSOCKET;
372
373    return ASN_OK;
374 }
375
376 int ooSocketAccept (OOSOCKET socket, OOSOCKET *pNewSocket, 
377                     char* destAddr, int* destPort) 
378 {
379    struct ast_sockaddr addr;
380    char* host = NULL;
381
382    if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;
383    if (pNewSocket == 0) return ASN_E_INVPARAM;
384
385    *pNewSocket = ast_accept (socket, &addr);
386    if (*pNewSocket <= 0) return ASN_E_INVSOCKET;
387
388    if (destAddr != 0) {
389       if ((host = ast_sockaddr_stringify_addr(&addr)) != NULL);
390         strncpy(destAddr, host, strlen(host));
391    }
392    if (destPort != 0)
393       *destPort =  ast_sockaddr_port(&addr);
394
395    return ASN_OK;
396 }
397
398 int ooSocketConnect (OOSOCKET socket, const char* host, int port) 
399 {
400    struct ast_sockaddr m_addr;
401
402    if (socket == OOSOCKET_INVALID)
403    { 
404       return ASN_E_INVSOCKET;
405    }
406    
407    memset (&m_addr, 0, sizeof (m_addr));
408    ast_parse_arg(host, PARSE_ADDR, &m_addr);
409    ast_sockaddr_set_port(&m_addr, port);
410
411    if (ast_connect(socket, &m_addr))
412    {
413       return ASN_E_INVSOCKET;
414    }
415    return ASN_OK;
416 }
417 /*
418 // **Need to add check whether complete data was sent by checking the return
419 // **value of send and if complete data is not sent then add mechanism to 
420 // **send remaining bytes. This will make ooSocketSend call atomic.
421 */
422 int ooSocketSend (OOSOCKET socket, const ASN1OCTET* pdata, ASN1UINT size)
423 {
424    if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;
425    
426    if (send (socket, (const char*) pdata, size, SEND_FLAGS) == -1)
427       return ASN_E_INVSOCKET;
428    return ASN_OK;
429 }
430
431 int ooSocketSendTo(OOSOCKET socket, const ASN1OCTET* pdata, ASN1UINT size,
432                      const char* host, int port)
433 {
434    struct sockaddr_in m_addr;
435    if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;
436    
437    memset (&m_addr, 0, sizeof (m_addr));
438
439    m_addr.sin_family = AF_INET;
440    m_addr.sin_port = htons ((unsigned short)port);
441    m_addr.sin_addr.s_addr = inet_addr (host);
442    if (sendto (socket, (const char*) pdata, size, SEND_FLAGS, 
443                                     (const struct sockaddr*)&m_addr, 
444                                     sizeof(m_addr)) == -1)
445       return ASN_E_INVSOCKET;
446    return ASN_OK;
447 }
448
449 int ooSocketRecvPeek(OOSOCKET socket, ASN1OCTET* pbuf, ASN1UINT bufsize)
450 {
451    int len;
452    int flags = MSG_PEEK;
453
454    if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;
455
456    if ((len = recv (socket, (char*) pbuf, bufsize, flags)) == -1)
457       return ASN_E_INVSOCKET;
458    return len;
459 }
460
461 int ooSocketRecv (OOSOCKET socket, ASN1OCTET* pbuf, ASN1UINT bufsize)
462 {
463    int len;
464    if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;
465
466    if ((len = recv (socket, (char*) pbuf, bufsize, 0)) == -1)
467       return ASN_E_INVSOCKET;
468    return len;
469 }
470
471 int ooSocketRecvFrom (OOSOCKET socket, ASN1OCTET* pbuf, ASN1UINT bufsize,
472                       char* remotehost, ASN1UINT hostBufLen, int * remoteport)
473 {
474    struct sockaddr_in m_addr;
475    int len, addrlen;
476    const char * host=NULL;
477    if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;
478    addrlen = sizeof(m_addr);
479
480    memset (&m_addr, 0, sizeof (m_addr));
481       
482    if ((len = recvfrom (socket, (char*) pbuf, bufsize, 0, 
483                         (struct sockaddr*)&m_addr, (socklen_t *) &addrlen)) == -1)
484       return ASN_E_INVSOCKET;
485
486    if(remoteport)
487       *remoteport = ntohs(m_addr.sin_port);
488    if(remotehost)
489    {
490       host = ast_inet_ntoa(m_addr.sin_addr);
491       if(strlen(host) < (hostBufLen-1))
492          strcpy(remotehost, host);
493       else
494          return -1;
495    }
496    return len;
497 }
498
499 int ooSocketSelect(int nfds, fd_set *readfds, fd_set *writefds, 
500                      fd_set *exceptfds, struct timeval * timeout)
501 {
502    int ret;   
503 #if defined (_WIN32)
504   ret = select(nfds, readfds, writefds, exceptfds, 
505              (const struct timeval *) timeout);
506 #else
507    ret = select(nfds, readfds, writefds, exceptfds, timeout);
508 #endif
509    return ret;
510 }
511
512 int ooSocketPoll(struct pollfd *pfds, int nfds, int timeout)
513 {
514  return ast_poll(pfds, nfds, timeout);
515 }
516
517 int ooPDRead(struct pollfd *pfds, int nfds, int fd)
518 {
519  int i;
520  for (i=0;i<nfds;i++) 
521   if (pfds[i].fd == fd && (pfds[i].revents & POLLIN))
522    return 1;
523  return 0;
524 }
525
526 int ooPDWrite(struct pollfd *pfds, int nfds, int fd)
527 {
528  int i;
529  for (i=0;i<nfds;i++)
530   if (pfds[i].fd == fd && (pfds[i].revents & POLLOUT))
531    return 1;
532  return 0;
533 }
534
535 int ooGetLocalIPAddress(char * pIPAddrs)
536 {
537    int ret;
538    struct hostent *hp;
539    struct ast_hostent phost;
540    char hostname[100];
541
542    if(pIPAddrs == NULL)
543       return -1; /* Need to find suitable return value */
544    ret = gethostname(hostname, 100);
545    if(ret == 0)
546    {
547       if ((hp = ast_gethostbyname(hostname, &phost))) {
548                         if (hp->h_addrtype == AF_INET6) {
549                                 struct in6_addr i;
550                                 memcpy(&i, hp->h_addr, sizeof(i));
551                                 strcpy(pIPAddrs, (inet_ntop(AF_INET6, &i, 
552                                 hostname, sizeof(hostname))) == NULL ? "::1" : 
553                                 inet_ntop(AF_INET6, &i, hostname, sizeof(hostname)));
554                         } else {
555                                 struct in_addr i;
556                                 memcpy(&i, hp->h_addr, sizeof(i));
557                                 strcpy(pIPAddrs, (ast_inet_ntoa(i) == NULL) ? "127.0.0.1" : ast_inet_ntoa(i));
558                         }
559       } else {
560          return -1;
561       }
562    }
563    else{
564       return -1;
565    }
566    return ASN_OK;
567 }
568
569 /* int ooSocketStrToAddr (const char* pIPAddrStr, OOIPADDR* pIPAddr) 
570 {
571    int b1, b2, b3, b4;
572    int rv = sscanf (pIPAddrStr, "%d.%d.%d.%d", &b1, &b2, &b3, &b4);
573    if (rv != 4 ||
574       (b1 < 0 || b1 > 256) || (b2 < 0 || b2 > 256) ||
575       (b3 < 0 || b3 > 256) || (b4 < 0 || b4 > 256))
576       return ASN_E_INVPARAM;
577    *pIPAddr = ((b1 & 0xFF) << 24) | ((b2 & 0xFF) << 16) | 
578               ((b3 & 0xFF) << 8) | (b4 & 0xFF);
579    return ASN_OK;
580 }
581
582 int ooSocketConvertIpToNwAddr(char *inetIp, unsigned char *netIp)
583 {
584
585    struct sockaddr_in sin = {0};
586 #ifdef _WIN32
587    sin.sin_addr.s_addr = inet_addr(inetIp);
588    if(sin.sin_addr.s_addr == INADDR_NONE)
589    {
590       OOTRACEERR1("Error:Failed to convert address\n");
591       return -1;
592    }
593 #else
594    if(!inet_aton(inetIp, &sin.sin_addr))
595    {
596       OOTRACEERR1("Error:Failed to convert address\n");
597       return -1;
598    }
599   
600 #endif
601    
602    memcpy(netIp, (char*)&sin.sin_addr.s_addr, sizeof(unsigned long));
603    return ASN_OK;
604 }
605
606 int ooSocketAddrToStr (OOIPADDR ipAddr, char* pbuf, int bufsize)
607 {
608    char buf1[5], buf2[5], buf3[5], buf4[5];
609    int cnt = 0;
610
611    if (bufsize < 8) 
612       return ASN_E_BUFOVFLW;
613
614    cnt += sprintf (buf1, "%lu", (ipAddr >> 24) & 0xFF);
615    cnt += sprintf (buf2, "%lu", (ipAddr >> 16) & 0xFF);
616    cnt += sprintf (buf3, "%lu", (ipAddr >> 8) & 0xFF);
617    cnt += sprintf (buf4, "%lu", ipAddr & 0xFF);
618    if (bufsize < cnt + 4)
619       return ASN_E_BUFOVFLW;
620    sprintf (pbuf, "%s.%s.%s.%s", buf1, buf2, buf3, buf4);
621    return ASN_OK;
622 } */
623
624 int ooSocketsCleanup (void)
625 {
626 #ifdef _WIN32
627    int ret = WSACleanup();
628    if(ret == 0)
629       return ASN_OK;
630    else
631       return ret;
632 #endif
633    return ASN_OK;
634 }
635
636 long ooSocketHTONL(long val)
637 {
638    return htonl(val);
639 }
640
641 short ooSocketHTONS(short val)
642 {
643    return htons(val);
644 }
645
646 #ifndef _WIN32
647 int ooSocketGetInterfaceList(OOCTXT *pctxt, OOInterface **ifList)
648 {
649    OOSOCKET sock;
650    struct ifconf ifc;
651    int ifNum;
652    OOInterface *pIf=NULL;
653    struct sockaddr_in sin;
654
655    OOTRACEDBGA1("Retrieving local interfaces\n");
656    if(ooSocketCreateUDP(&sock, 4)!= ASN_OK)
657    {
658       OOTRACEERR1("Error:Failed to create udp socket - "
659                   "ooSocketGetInterfaceList\n");   
660       return -1;
661    }
662 #ifdef SIOCGIFNUM
663    if(ioctl(sock, SIOCGIFNUM, &ifNum) >= 0)
664    {
665       OOTRACEERR1("Error: ioctl for ifNum failed\n");
666       return -1;
667    }
668 #else
669    ifNum = 50;
670 #endif
671  
672    ifc.ifc_len = ifNum * sizeof(struct ifreq);
673    ifc.ifc_req = (struct ifreq *)memAlloc(pctxt, ifNum *sizeof(struct ifreq));
674    if(!ifc.ifc_req)
675    {
676       OOTRACEERR1("Error:Memory - ooSocketGetInterfaceList - ifc.ifc_req\n");
677       return -1;
678    }
679
680    if (ioctl(sock, SIOCGIFCONF, &ifc) >= 0) {
681       void * ifEndList = (char *)ifc.ifc_req + ifc.ifc_len;
682       struct ifreq *ifName;
683       struct ifreq ifReq;
684       int flags;
685       for (ifName = ifc.ifc_req; (void*)ifName < ifEndList; ifName++) {
686          char *pName=NULL;
687          char addr[50];
688 #ifdef ifr_netmask
689         char mask[50];
690 #endif
691          
692          pIf = (struct OOInterface*)memAlloc(pctxt, sizeof(struct OOInterface));
693          pName = (char*)memAlloc(pctxt, strlen(ifName->ifr_name)+1);
694          if(!pIf)
695          {
696             OOTRACEERR1("Error:Memory - ooSocketGetInterfaceList - "
697                         "pIf/pName\n");
698             return -1;
699          }
700          OOTRACEDBGA2("\tInterface name: %s\n", ifName->ifr_name);
701          
702          
703          strcpy(ifReq.ifr_name, ifName->ifr_name);
704          strcpy(pName, ifName->ifr_name);
705          pIf->name = pName;
706
707          /* Check whether the interface is up*/
708          if (ioctl(sock, SIOCGIFFLAGS, &ifReq) < 0) {
709             OOTRACEERR2("Error:Unable to determine status of interface %s\n", 
710                         pName);
711             memFreePtr(pctxt, pIf->name);
712             memFreePtr(pctxt, pIf);
713             continue;
714          }
715          flags = ifReq.ifr_flags;
716          if (!(flags & IFF_UP)) {
717             OOTRACEWARN2("Warn:Interface %s is not up\n", pName);
718             memFreePtr(pctxt, pIf->name);
719             memFreePtr(pctxt, pIf);
720             continue;
721          }
722
723          /* Retrieve interface address */
724          if (ioctl(sock, SIOCGIFADDR, &ifReq) < 0) 
725          {
726             OOTRACEWARN2("Warn:Unable to determine address of interface %s\n", 
727                           pName);
728             memFreePtr(pctxt, pIf->name);
729             memFreePtr(pctxt, pIf);
730             continue;
731          }
732          memcpy(&sin, &ifReq.ifr_addr, sizeof(struct sockaddr_in));
733          strcpy(addr, ast_inet_ntoa(sin.sin_addr));
734          OOTRACEDBGA2("\tIP address is %s\n", addr);
735          pIf->addr = (char*)memAlloc(pctxt, strlen(addr)+1);
736          if(!pIf->addr)
737          {
738             OOTRACEERR1("Error:Memory - ooSocketGetInterfaceList - "
739                         "pIf->addr\n");
740             memFreePtr(pctxt, pIf->name);
741             memFreePtr(pctxt, pIf);
742             return -1;
743          }
744          strcpy(pIf->addr, addr);
745          
746 #ifdef ifr_netmask
747          if (ioctl(sock, SIOCGIFNETMASK, &ifReq) < 0) 
748          {
749             OOTRACEWARN2("Warn:Unable to determine mask for interface %s\n", 
750                           pName);
751             memFreePtr(pctxt, pIf->name);
752             memFreePtr(pctxt, pIf->addr);
753             memFreePtr(pctxt, pIf);
754             continue;
755          }
756          memcpy(&sin, &ifReq.ifr_netmask, sizeof(struct sockaddr_in));
757          strcpy(mask, ast_inet_ntoa(sin.sin_addr));
758          OOTRACEDBGA2("\tMask is %s\n", mask);
759          pIf->mask = (char*)memAlloc(pctxt, strlen(mask)+1);
760          if(!pIf->mask)
761          {
762             OOTRACEERR1("Error:Memory - ooSocketGetInterfaceList - "
763                         "pIf->mask\n");
764             memFreePtr(pctxt, pIf->name);
765             memFreePtr(pctxt, pIf->addr);
766             memFreePtr(pctxt, pIf);
767             return -1;
768          }
769          strcpy(pIf->mask, mask);
770 #endif
771          pIf->next = NULL;
772
773          /* Add to the list */
774          if(!*ifList)
775          {
776             *ifList = pIf;
777             pIf = NULL;
778          }
779          else{
780             pIf->next = *ifList;
781             *ifList = pIf;
782             pIf=NULL;
783          }
784 /*
785 #if defined(OO_FREEBSD) || defined(OO_OPENBSD) || defined(OO_NETBSD) || defined(OO_MACOSX) || defined(OO_VXWORKS) || defined(OO_RTEMS) || defined(OO_QNX)
786 #ifndef _SIZEOF_ADDR_IFREQ
787 #define _SIZEOF_ADDR_IFREQ(ifr) \
788         ((ifr).ifr_addr.sa_len > sizeof(struct sockaddr) ? \
789          (sizeof(struct ifreq) - sizeof(struct sockaddr) + \
790           (ifr).ifr_addr.sa_len) : sizeof(struct ifreq))
791 #endif
792       ifName = (struct ifreq *)((char *)ifName + _SIZEOF_ADDR_IFREQ(*ifName));
793 #else
794       ifName++;
795 */
796       }
797
798    }  
799    return ASN_OK;
800 }
801 #endif