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