/*
 * Copyright (C) 1997-2005 by Objective Systems, Inc.
 *
 * This software is furnished under an open source license and may be 
 * used and copied only in accordance with the terms of this license. 
 * The text of the license may generally be found in the root 
 * directory of this installation in the COPYING file.  It 
 * can also be viewed online at the following URL:
 *
 *   http://www.obj-sys.com/open/license.html
 *
 * Any redistributions of this file including modified versions must 
 * maintain this copyright notice.
 *
 *****************************************************************************/
#include "asterisk.h"

ASTERISK_REGISTER_FILE()

#include "asterisk/io.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/network.h"
#include "asterisk/netsock2.h"
#include "asterisk/config.h"

#include "ooSocket.h"
#include "ootrace.h"
#include "ooh323ep.h"

/** Global endpoint structure */
extern OOH323EndPoint gH323ep;

#if defined(_WIN32_WCE)
static int inited = 0;
#define SEND_FLAGS     0
#define SHUTDOWN_FLAGS 0
#elif defined (_WIN32)
static LPFN_SEND send;
static LPFN_SOCKET socket;
static LPFN_SETSOCKOPT setsockopt;
static LPFN_BIND bind;
static LPFN_HTONL htonl;
static LPFN_HTONS htons;
static LPFN_CONNECT connect;
static LPFN_INET_ADDR inet_addr;
static LPFN_LISTEN listen;
static LPFN_ACCEPT accept;
static LPFN_NTOHL ntohl;
static LPFN_NTOHS ntohs;
static LPFN_RECV recv;
static LPFN_SHUTDOWN shutdown;


static LPFN_IOCTLSOCKET ioctlsocket;
static LPFN_SENDTO sendto;
static LPFN_INET_NTOA inet_ntoa;
static LPFN_RECVFROM recvfrom;
static LPFN_SELECT select;
static LPFN_GETHOSTNAME gethostname;
static LPFN_GETHOSTBYNAME gethostbyname;
static LPFN_WSAGETLASTERROR  WSAGetLastError;
static LPFN_WSACLEANUP WSACleanup;
static LPFN_CLOSESOCKET closesocket;
static LPFN_GETSOCKNAME getsockname;
static HMODULE ws32 = 0;
#define SEND_FLAGS     0
#define SHUTDOWN_FLAGS SD_BOTH
#else
#define SEND_FLAGS     0
#define SHUTDOWN_FLAGS SHUT_RDWR
#define closesocket close
#endif



int ooSocketsInit ()
{
#if defined(_WIN32_WCE)
   WORD wVersionRequested;
   WSADATA wsaData;
   int err;

   if (inited) return ASN_OK; 

   wVersionRequested = MAKEWORD( 1, 1 );
    
   err = WSAStartup (wVersionRequested, &wsaData);
   if ( err != 0 ) {
      /* Tell the user that we could not find a usable */
      /* WinSock DLL.   */
      return ASN_E_NOTINIT;
   }
   inited = 1;

#elif defined (_WIN32)
   LPFN_WSASTARTUP wsaStartup = NULL;
   WSADATA wsaData;

   if (ws32 != 0) return ASN_OK;

//   ws32 = LoadLibrary ("WSOCK32.DLL");
  ws32 = LoadLibrary ("WS2_32.DLL");
   if (ws32 == NULL) return ASN_E_NOTINIT;
   
   wsaStartup = (LPFN_WSASTARTUP) GetProcAddress (ws32, "WSAStartup");
   if (wsaStartup == NULL) return ASN_E_NOTINIT;
   
   send = (LPFN_SEND) GetProcAddress (ws32, "send");
   if (send == NULL) return ASN_E_NOTINIT;
   
   socket = (LPFN_SOCKET) GetProcAddress (ws32, "socket");
   if (socket == NULL) return ASN_E_NOTINIT;
   
   setsockopt = (LPFN_SETSOCKOPT) GetProcAddress (ws32, "setsockopt");
   if (setsockopt == NULL) return ASN_E_NOTINIT;
   
   bind = (LPFN_BIND) GetProcAddress (ws32, "bind");
   if (bind == NULL) return ASN_E_NOTINIT;
   
   htonl = (LPFN_HTONL) GetProcAddress (ws32, "htonl");
   if (htonl == NULL) return ASN_E_NOTINIT;
   
   htons = (LPFN_HTONS) GetProcAddress (ws32, "htons");
   if (htons == NULL) return ASN_E_NOTINIT;
   
   connect = (LPFN_CONNECT) GetProcAddress (ws32, "connect");
   if (connect == NULL) return ASN_E_NOTINIT;
   
   listen = (LPFN_LISTEN) GetProcAddress (ws32, "listen");
   if (listen == NULL) return ASN_E_NOTINIT;
   
   accept = (LPFN_ACCEPT) GetProcAddress (ws32, "accept");
   if (accept == NULL) return ASN_E_NOTINIT;
   
   inet_addr = (LPFN_INET_ADDR) GetProcAddress (ws32, "inet_addr");
   if (inet_addr == NULL) return ASN_E_NOTINIT;
   
   ntohl = (LPFN_NTOHL) GetProcAddress (ws32, "ntohl");
   if (ntohl == NULL) return ASN_E_NOTINIT;
   
   ntohs = (LPFN_NTOHS) GetProcAddress (ws32, "ntohs");
   if (ntohs == NULL) return ASN_E_NOTINIT;
   
   recv = (LPFN_RECV) GetProcAddress (ws32, "recv");
   if (recv == NULL) return ASN_E_NOTINIT;
   
   shutdown = (LPFN_SHUTDOWN) GetProcAddress (ws32, "shutdown");
   if (shutdown == NULL) return ASN_E_NOTINIT;
   
   closesocket = (LPFN_CLOSESOCKET) GetProcAddress (ws32, "closesocket");
   if (closesocket == NULL) return ASN_E_NOTINIT;

   getsockname = (LPFN_GETSOCKNAME) GetProcAddress (ws32, "getsockname");
   if (getsockname == NULL) return ASN_E_NOTINIT;
   
   ioctlsocket = (LPFN_IOCTLSOCKET) GetProcAddress(ws32, "ioctlsocket");
   if(ioctlsocket == NULL) return ASN_E_NOTINIT;

   sendto = (LPFN_SENDTO) GetProcAddress (ws32, "sendto");
   if (sendto == NULL) return ASN_E_NOTINIT;

   inet_ntoa = (LPFN_INET_NTOA) GetProcAddress (ws32, "inet_ntoa");
   if (inet_ntoa == NULL) return ASN_E_NOTINIT;

   recvfrom = (LPFN_RECVFROM) GetProcAddress (ws32, "recvfrom");
   if (recvfrom == NULL) return ASN_E_NOTINIT;

   select = (LPFN_SELECT) GetProcAddress (ws32, "select");
   if (select == NULL) return ASN_E_NOTINIT;

   gethostname = (LPFN_GETHOSTNAME) GetProcAddress (ws32, "gethostname");
   if (gethostname == NULL) return ASN_E_NOTINIT;

   gethostbyname = (LPFN_GETHOSTBYNAME) GetProcAddress (ws32, "gethostbyname");
   if (gethostbyname == NULL) return ASN_E_NOTINIT;
   
   WSAGetLastError = (LPFN_WSAGETLASTERROR) GetProcAddress (ws32, 
                                                           "WSAGetLastError");
   if (WSAGetLastError == NULL) return ASN_E_NOTINIT;

   WSACleanup = (LPFN_WSACLEANUP) GetProcAddress (ws32, "WSACleanup");
   if (WSACleanup == NULL) return ASN_E_NOTINIT;
   
      
   if (wsaStartup (MAKEWORD(1, 1), &wsaData) == -1) return ASN_E_NOTINIT;
#endif
   return ASN_OK;
}

#if defined (_WIN32) || \
defined(_HP_UX) || defined(__hpux) || defined(_HPUX_SOURCE)
typedef int OOSOCKLEN;
#else
typedef socklen_t OOSOCKLEN;
#endif

int ooSocketCreate (OOSOCKET* psocket, int family) 
{
   int on;
   OOSOCKET sock;
   int keepalive = 1;
#ifdef __linux__
   int keepcnt = 24, keepidle = 120, keepintvl = 30;
#endif
   struct linger linger;

   if (family == 6) {
   	sock = socket (AF_INET6,
                             	SOCK_STREAM,
                             	0);
   } else {
   	sock = socket (AF_INET,
                            	SOCK_STREAM,
                             	0);
   }
  
   if (sock == OOSOCKET_INVALID){
      OOTRACEERR1("Error:Failed to create TCP socket\n");
      return ASN_E_INVSOCKET;
   }

   on = 1;
   if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, 
                   (const char* ) &on, sizeof (on)) == -1)
   {
      OOTRACEERR1("Error:Failed to set socket option SO_REUSEADDR\n");
      return ASN_E_INVSOCKET;
   }
   linger.l_onoff = 1;
   linger.l_linger = 0;
   if (setsockopt (sock, SOL_SOCKET, SO_LINGER, 
                   (const char* ) &linger, sizeof (linger)) == -1)
   {
      OOTRACEERR1("Error:Failed to set socket option linger\n");
      return ASN_E_INVSOCKET;
   }
   setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, (const char *)&keepalive,
			sizeof(keepalive));
#ifdef __linux__
   setsockopt (sock, SOL_TCP, TCP_KEEPCNT, &keepcnt, sizeof(keepcnt));
   setsockopt (sock, SOL_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle));
   setsockopt (sock, SOL_TCP, TCP_KEEPINTVL, &keepintvl, sizeof(keepintvl));
#endif
   *psocket = sock;
   return ASN_OK;
}

int ooSocketCreateUDP (OOSOCKET* psocket, int family) 
{
   int on;
   OOSOCKET sock;

   if (family == 6)
   	sock = socket (AF_INET6,
                             SOCK_DGRAM,
                             0);
   else
   	sock = socket (AF_INET,
                             SOCK_DGRAM,
                             0);

   if (sock == OOSOCKET_INVALID){
      OOTRACEERR1("Error:Failed to create UDP socket\n");
      return ASN_E_INVSOCKET;
   }

   on = 1;
   if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, 
                   (const char* ) &on, sizeof (on)) == -1)
   {
      OOTRACEERR1("Error:Failed to set socket option SO_REUSEADDR\n");
      return ASN_E_INVSOCKET;
   }
   // may be will use later
   /*
   linger.l_onoff = 1;
   linger.l_linger = 0;
   if (setsockopt (sock, SOL_SOCKET, SO_LINGER, 
                 (const char* ) &linger, sizeof (linger)) == -1)
      return ASN_E_INVSOCKET;
   */
   *psocket = sock;
   return ASN_OK;
}

int ooSocketClose (OOSOCKET socket)
{
   shutdown (socket, SHUTDOWN_FLAGS);
   if (closesocket (socket) == -1)
      return ASN_E_INVSOCKET;
   return ASN_OK;
}

int ooSocketBind (OOSOCKET socket, OOIPADDR addr, int port) 
{
   struct ast_sockaddr m_addr;

   memset(&m_addr, 0, sizeof(m_addr));


   if (socket == OOSOCKET_INVALID)
   { 
      OOTRACEERR1("Error:Invalid socket passed to bind\n");
      return ASN_E_INVSOCKET;
   }

   ast_sockaddr_copy(&m_addr, &addr);
   ast_sockaddr_set_port(&m_addr, port);

   if (ast_bind(socket, &m_addr) < 0) {
      if (errno != EADDRINUSE) {
      	perror ("bind");
      	OOTRACEERR2("Error:Bind failed, error: %d\n", errno);
      }
      return ASN_E_INVSOCKET;
   }

   return ASN_OK;
}


int ooSocketGetSockName(OOSOCKET socket, struct sockaddr_in *name, socklen_t *size)
{
   int ret;
   ret = getsockname(socket, (struct sockaddr*)name, size);
   if(ret == 0)
      return ASN_OK;
   else{
      OOTRACEERR1("Error:ooSocketGetSockName - getsockname\n");
      return ASN_E_INVSOCKET;
   }
}

int ooSocketGetIpAndPort(OOSOCKET socket, char *ip, int len, int *port, int *family)
{
   int ret=ASN_OK;
   struct ast_sockaddr addr;
   const char *host=NULL;

   ret = ast_getsockname(socket, &addr);
   if(ret != 0)
      return ASN_E_INVSOCKET;

   host = ast_sockaddr_stringify_addr(&addr);

   if(host && strlen(host) < (unsigned)len)
      strcpy(ip, host);   
   else{
     OOTRACEERR1("Error:Insufficient buffer for ip address - "
                 "ooSocketGetIpAndPort\n");
      return -1;
   }
   *port = ast_sockaddr_port(&addr);

   if (family) {
	if (ast_sockaddr_is_ipv6(&addr) && !ast_sockaddr_is_ipv4_mapped(&addr))
		*family = 6;
	else
		*family = 4;
   }

   return ASN_OK;
}

int ooSocketListen (OOSOCKET socket, int maxConnection) 
{
   if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;

   if (listen (socket, maxConnection) == -1)
      return ASN_E_INVSOCKET;

   return ASN_OK;
}

int ooSocketAccept (OOSOCKET socket, OOSOCKET *pNewSocket, 
                    char* destAddr, int* destPort) 
{
   struct ast_sockaddr addr;
   char* host = NULL;

   if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;
   if (pNewSocket == 0) return ASN_E_INVPARAM;

   *pNewSocket = ast_accept (socket, &addr);
   if (*pNewSocket <= 0) return ASN_E_INVSOCKET;

   if (destAddr != 0) {
      if ((host = ast_sockaddr_stringify_addr(&addr)) != NULL);
      	strncpy(destAddr, host, strlen(host));
   }
   if (destPort != 0)
      *destPort =  ast_sockaddr_port(&addr);

   return ASN_OK;
}

int ooSocketConnect (OOSOCKET socket, const char* host, int port) 
{
   struct ast_sockaddr m_addr;

   if (socket == OOSOCKET_INVALID)
   { 
      return ASN_E_INVSOCKET;
   }
   
   memset (&m_addr, 0, sizeof (m_addr));
   ast_parse_arg(host, PARSE_ADDR, &m_addr);
   ast_sockaddr_set_port(&m_addr, port);

   if (ast_connect(socket, &m_addr))
   {
      return ASN_E_INVSOCKET;
   }
   return ASN_OK;
}
/*
// **Need to add check whether complete data was sent by checking the return
// **value of send and if complete data is not sent then add mechanism to 
// **send remaining bytes. This will make ooSocketSend call atomic.
*/
int ooSocketSend (OOSOCKET socket, const ASN1OCTET* pdata, ASN1UINT size)
{
   if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;
   
   if (send (socket, (const char*) pdata, size, SEND_FLAGS) == -1)
      return ASN_E_INVSOCKET;
   return ASN_OK;
}

int ooSocketSendTo(OOSOCKET socket, const ASN1OCTET* pdata, ASN1UINT size,
                     const char* host, int port)
{
   struct sockaddr_in m_addr;
   if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;
   
   memset (&m_addr, 0, sizeof (m_addr));

   m_addr.sin_family = AF_INET;
   m_addr.sin_port = htons ((unsigned short)port);
   m_addr.sin_addr.s_addr = inet_addr (host);
   if (sendto (socket, (const char*) pdata, size, SEND_FLAGS, 
                                    (const struct sockaddr*)&m_addr, 
                                    sizeof(m_addr)) == -1)
      return ASN_E_INVSOCKET;
   return ASN_OK;
}

int ooSocketRecvPeek(OOSOCKET socket, ASN1OCTET* pbuf, ASN1UINT bufsize)
{
   int len;
   int flags = MSG_PEEK;

   if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;

   if ((len = recv (socket, (char*) pbuf, bufsize, flags)) == -1)
      return ASN_E_INVSOCKET;
   return len;
}

int ooSocketRecv (OOSOCKET socket, ASN1OCTET* pbuf, ASN1UINT bufsize)
{
   int len;
   if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;

   if ((len = recv (socket, (char*) pbuf, bufsize, 0)) == -1)
      return ASN_E_INVSOCKET;
   return len;
}

int ooSocketRecvFrom (OOSOCKET socket, ASN1OCTET* pbuf, ASN1UINT bufsize,
                      char* remotehost, ASN1UINT hostBufLen, int * remoteport)
{
   struct sockaddr_in m_addr;
   int len, addrlen;
   const char * host=NULL;
   if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;
   addrlen = sizeof(m_addr);

   memset (&m_addr, 0, sizeof (m_addr));
      
   if ((len = recvfrom (socket, (char*) pbuf, bufsize, 0, 
                        (struct sockaddr*)&m_addr, (socklen_t *) &addrlen)) == -1)
      return ASN_E_INVSOCKET;

   if(remoteport)
      *remoteport = ntohs(m_addr.sin_port);
   if(remotehost)
   {
      host = ast_inet_ntoa(m_addr.sin_addr);
      if(strlen(host) < (hostBufLen-1))
         strcpy(remotehost, host);
      else
         return -1;
   }
   return len;
}

int ooSocketSelect(int nfds, fd_set *readfds, fd_set *writefds, 
                     fd_set *exceptfds, struct timeval * timeout)
{
   int ret;   
#if defined (_WIN32)
  ret = select(nfds, readfds, writefds, exceptfds, 
             (const struct timeval *) timeout);
#else
   ret = select(nfds, readfds, writefds, exceptfds, timeout);
#endif
   return ret;
}

int ooSocketPoll(struct pollfd *pfds, int nfds, int timeout)
{
 return ast_poll(pfds, nfds, timeout);
}

int ooPDRead(struct pollfd *pfds, int nfds, int fd)
{
 int i;
 for (i=0;i<nfds;i++) 
  if (pfds[i].fd == fd && (pfds[i].revents & POLLIN))
   return 1;
 return 0;
}

int ooPDWrite(struct pollfd *pfds, int nfds, int fd)
{
 int i;
 for (i=0;i<nfds;i++)
  if (pfds[i].fd == fd && (pfds[i].revents & POLLOUT))
   return 1;
 return 0;
}

int ooGetLocalIPAddress(char * pIPAddrs)
{
   int ret;
   struct hostent *hp;
   struct ast_hostent phost;
   char hostname[100];

   if(pIPAddrs == NULL)
      return -1; /* Need to find suitable return value */
   ret = gethostname(hostname, 100);
   if(ret == 0)
   {
      if ((hp = ast_gethostbyname(hostname, &phost))) {
			if (hp->h_addrtype == AF_INET6) {
				struct in6_addr i;
				memcpy(&i, hp->h_addr, sizeof(i));
				strcpy(pIPAddrs, (inet_ntop(AF_INET6, &i, 
				hostname, sizeof(hostname))) == NULL ? "::1" : 
				inet_ntop(AF_INET6, &i, hostname, sizeof(hostname)));
			} else {
	  			struct in_addr i;
				memcpy(&i, hp->h_addr, sizeof(i));
			  	strcpy(pIPAddrs, (ast_inet_ntoa(i) == NULL) ? "127.0.0.1" : ast_inet_ntoa(i));
			}
      } else {
         return -1;
      }
   }
   else{
      return -1;
   }
   return ASN_OK;
}

/* int ooSocketStrToAddr (const char* pIPAddrStr, OOIPADDR* pIPAddr) 
{
   int b1, b2, b3, b4;
   int rv = sscanf (pIPAddrStr, "%d.%d.%d.%d", &b1, &b2, &b3, &b4);
   if (rv != 4 ||
      (b1 < 0 || b1 > 256) || (b2 < 0 || b2 > 256) ||
      (b3 < 0 || b3 > 256) || (b4 < 0 || b4 > 256))
      return ASN_E_INVPARAM;
   *pIPAddr = ((b1 & 0xFF) << 24) | ((b2 & 0xFF) << 16) | 
              ((b3 & 0xFF) << 8) | (b4 & 0xFF);
   return ASN_OK;
}

int ooSocketConvertIpToNwAddr(char *inetIp, unsigned char *netIp)
{

   struct sockaddr_in sin = {0};
#ifdef _WIN32
   sin.sin_addr.s_addr = inet_addr(inetIp);
   if(sin.sin_addr.s_addr == INADDR_NONE)
   {
      OOTRACEERR1("Error:Failed to convert address\n");
      return -1;
   }
#else
   if(!inet_aton(inetIp, &sin.sin_addr))
   {
      OOTRACEERR1("Error:Failed to convert address\n");
      return -1;
   }
  
#endif
   
   memcpy(netIp, (char*)&sin.sin_addr.s_addr, sizeof(unsigned long));
   return ASN_OK;
}

int ooSocketAddrToStr (OOIPADDR ipAddr, char* pbuf, int bufsize)
{
   char buf1[5], buf2[5], buf3[5], buf4[5];
   int cnt = 0;

   if (bufsize < 8) 
      return ASN_E_BUFOVFLW;

   cnt += sprintf (buf1, "%lu", (ipAddr >> 24) & 0xFF);
   cnt += sprintf (buf2, "%lu", (ipAddr >> 16) & 0xFF);
   cnt += sprintf (buf3, "%lu", (ipAddr >> 8) & 0xFF);
   cnt += sprintf (buf4, "%lu", ipAddr & 0xFF);
   if (bufsize < cnt + 4)
      return ASN_E_BUFOVFLW;
   sprintf (pbuf, "%s.%s.%s.%s", buf1, buf2, buf3, buf4);
   return ASN_OK;
} */

int ooSocketsCleanup (void)
{
#ifdef _WIN32
   int ret = WSACleanup();
   if(ret == 0)
      return ASN_OK;
   else
      return ret;
#endif
   return ASN_OK;
}

long ooSocketHTONL(long val)
{
   return htonl(val);
}

short ooSocketHTONS(short val)
{
   return htons(val);
}

#ifndef _WIN32
int ooSocketGetInterfaceList(OOCTXT *pctxt, OOInterface **ifList)
{
   OOSOCKET sock;
   struct ifconf ifc;
   int ifNum;
   OOInterface *pIf=NULL;
   struct sockaddr_in sin;

   OOTRACEDBGA1("Retrieving local interfaces\n");
   if(ooSocketCreateUDP(&sock, 4)!= ASN_OK)
   {
      OOTRACEERR1("Error:Failed to create udp socket - "
                  "ooSocketGetInterfaceList\n");   
      return -1;
   }
#ifdef SIOCGIFNUM
   if(ioctl(sock, SIOCGIFNUM, &ifNum) >= 0)
   {
      OOTRACEERR1("Error: ioctl for ifNum failed\n");
      return -1;
   }
#else
   ifNum = 50;
#endif
 
   ifc.ifc_len = ifNum * sizeof(struct ifreq);
   ifc.ifc_req = (struct ifreq *)memAlloc(pctxt, ifNum *sizeof(struct ifreq));
   if(!ifc.ifc_req)
   {
      OOTRACEERR1("Error:Memory - ooSocketGetInterfaceList - ifc.ifc_req\n");
      return -1;
   }

   if (ioctl(sock, SIOCGIFCONF, &ifc) >= 0) {
      void * ifEndList = (char *)ifc.ifc_req + ifc.ifc_len;
      struct ifreq *ifName;
      struct ifreq ifReq;
      int flags;
      for (ifName = ifc.ifc_req; (void*)ifName < ifEndList; ifName++) {
         char *pName=NULL;
         char addr[50];
#ifdef ifr_netmask
	char mask[50];
#endif
         
         pIf = (struct OOInterface*)memAlloc(pctxt, sizeof(struct OOInterface));
         pName = (char*)memAlloc(pctxt, strlen(ifName->ifr_name)+1);
         if(!pIf)
         {
            OOTRACEERR1("Error:Memory - ooSocketGetInterfaceList - "
                        "pIf/pName\n");
            return -1;
         }
         OOTRACEDBGA2("\tInterface name: %s\n", ifName->ifr_name);
         
         
         strcpy(ifReq.ifr_name, ifName->ifr_name);
         strcpy(pName, ifName->ifr_name);
         pIf->name = pName;

         /* Check whether the interface is up*/
         if (ioctl(sock, SIOCGIFFLAGS, &ifReq) < 0) {
            OOTRACEERR2("Error:Unable to determine status of interface %s\n", 
                        pName);
            memFreePtr(pctxt, pIf->name);
            memFreePtr(pctxt, pIf);
            continue;
         }
         flags = ifReq.ifr_flags;
         if (!(flags & IFF_UP)) {
            OOTRACEWARN2("Warn:Interface %s is not up\n", pName);
            memFreePtr(pctxt, pIf->name);
            memFreePtr(pctxt, pIf);
            continue;
         }

         /* Retrieve interface address */
         if (ioctl(sock, SIOCGIFADDR, &ifReq) < 0) 
         {
            OOTRACEWARN2("Warn:Unable to determine address of interface %s\n", 
                          pName);
            memFreePtr(pctxt, pIf->name);
            memFreePtr(pctxt, pIf);
            continue;
         }
	 memcpy(&sin, &ifReq.ifr_addr, sizeof(struct sockaddr_in));
	 strcpy(addr, ast_inet_ntoa(sin.sin_addr));
         OOTRACEDBGA2("\tIP address is %s\n", addr);
         pIf->addr = (char*)memAlloc(pctxt, strlen(addr)+1);
         if(!pIf->addr)
         {
            OOTRACEERR1("Error:Memory - ooSocketGetInterfaceList - "
                        "pIf->addr\n");
            memFreePtr(pctxt, pIf->name);
            memFreePtr(pctxt, pIf);
            return -1;
         }
         strcpy(pIf->addr, addr);
         
#ifdef ifr_netmask
         if (ioctl(sock, SIOCGIFNETMASK, &ifReq) < 0) 
         {
            OOTRACEWARN2("Warn:Unable to determine mask for interface %s\n", 
                          pName);
            memFreePtr(pctxt, pIf->name);
            memFreePtr(pctxt, pIf->addr);
            memFreePtr(pctxt, pIf);
            continue;
         }
	 memcpy(&sin, &ifReq.ifr_netmask, sizeof(struct sockaddr_in));
	 strcpy(mask, ast_inet_ntoa(sin.sin_addr));
         OOTRACEDBGA2("\tMask is %s\n", mask);
         pIf->mask = (char*)memAlloc(pctxt, strlen(mask)+1);
         if(!pIf->mask)
         {
            OOTRACEERR1("Error:Memory - ooSocketGetInterfaceList - "
                        "pIf->mask\n");
            memFreePtr(pctxt, pIf->name);
            memFreePtr(pctxt, pIf->addr);
            memFreePtr(pctxt, pIf);
            return -1;
         }
         strcpy(pIf->mask, mask);
#endif
         pIf->next = NULL;

         /* Add to the list */
         if(!*ifList)
         {
            *ifList = pIf;
            pIf = NULL;
         }
         else{
            pIf->next = *ifList;
            *ifList = pIf;
            pIf=NULL;
         }
/*
#if defined(OO_FREEBSD) || defined(OO_OPENBSD) || defined(OO_NETBSD) || defined(OO_MACOSX) || defined(OO_VXWORKS) || defined(OO_RTEMS) || defined(OO_QNX)
#ifndef _SIZEOF_ADDR_IFREQ
#define _SIZEOF_ADDR_IFREQ(ifr) \
        ((ifr).ifr_addr.sa_len > sizeof(struct sockaddr) ? \
         (sizeof(struct ifreq) - sizeof(struct sockaddr) + \
          (ifr).ifr_addr.sa_len) : sizeof(struct ifreq))
#endif
      ifName = (struct ifreq *)((char *)ifName + _SIZEOF_ADDR_IFREQ(*ifName));
#else
      ifName++;
*/
      }

   }  
   return ASN_OK;
}
#endif
