exutils.c

来自「libosip2-3版本的osip源代码」· C语言 代码 · 共 1,103 行 · 第 1/2 页

C
1,103
字号
/*  eXosip - This is the eXtended osip library.  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org    eXosip is free software; you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the Free Software Foundation; either version 2 of the License, or  (at your option) any later version.    eXosip is distributed in the hope that it will be useful,  but WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License for more details.    You should have received a copy of the GNU General Public License  along with this program; if not, write to the Free Software  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*/#ifdef ENABLE_MPATROL#include <mpatrol.h>#endif#include <osipparser2/osip_port.h>#include "eXosip2.h"#if defined(_WIN32_WCE)#elif defined(WIN32)#include <WinDNS.h>#else#include <netinet/in.h>#include <sys/socket.h>#include <arpa/inet.h>#ifdef HAVE_ARPA_NAMESER_H#include <arpa/nameser.h>#endif#ifdef HAVE_RESOLV8_COMPAT_H#include <nameser8_compat.h>#include <resolv8_compat.h>#elif defined(HAVE_RESOLV_H) || defined(OpenBSD) || defined(FreeBSD) || defined(NetBSD)#include <resolv.h>#endif#ifdef HAVE_NETDB_H#include <netdb.h>#endif#endifextern eXosip_t eXosip;extern int ipv6_enable;#if defined(WIN32) || defined(_WIN32_WCE)/* You need the Platform SDK to compile this. */#include <Windows.h>#include <Iphlpapi.h>inteXosip_dns_get_local_fqdn (char **servername, char **serverip,                        char **netmask, unsigned int WIN32_interface){  unsigned int pos;  *servername = NULL;           /* no name on win32? */  *serverip = NULL;  *netmask = NULL;  /* First, try to get the interface where we should listen */  {    DWORD size_of_iptable = 0;    PMIB_IPADDRTABLE ipt;    PMIB_IFROW ifrow;    if (GetIpAddrTable (NULL, &size_of_iptable, TRUE) == ERROR_INSUFFICIENT_BUFFER)      {        ifrow = (PMIB_IFROW) _alloca (sizeof (MIB_IFROW));        ipt = (PMIB_IPADDRTABLE) _alloca (size_of_iptable);        if (ifrow == NULL || ipt == NULL)          {            /* not very usefull to continue */            OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL,                                    "ERROR alloca failed\r\n"));            return -1;          }        if (!GetIpAddrTable (ipt, &size_of_iptable, TRUE))          {            /* look for the best public interface */            for (pos = 0; pos < ipt->dwNumEntries && *netmask == NULL; ++pos)              {                /* index is */                struct in_addr addr;                struct in_addr mask;                ifrow->dwIndex = ipt->table[pos].dwIndex;                if (GetIfEntry (ifrow) == NO_ERROR)                  {                    switch (ifrow->dwType)                      {                        case MIB_IF_TYPE_LOOPBACK:                          /*    break; */                        case MIB_IF_TYPE_ETHERNET:                        default:                          addr.s_addr = ipt->table[pos].dwAddr;                          mask.s_addr = ipt->table[pos].dwMask;                          if (ipt->table[pos].dwIndex == WIN32_interface)                            {                              *servername = NULL;       /* no name on win32? */                              *serverip = osip_strdup (inet_ntoa (addr));                              *netmask = osip_strdup (inet_ntoa (mask));                              OSIP_TRACE (osip_trace                                          (__FILE__, __LINE__, OSIP_INFO4, NULL,                                           "Interface ethernet: %s/%s\r\n",                                           *serverip, *netmask));                              break;                            }                      }                  }              }          }      }  }  if (*serverip == NULL || *netmask == NULL)    {      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL,                              "ERROR No network interface found\r\n"));      return -1;    }  return 0;}#if 1inteXosip_guess_ip_for_via (int family, char *address, int size){  SOCKET sock;  SOCKADDR_STORAGE local_addr;  int local_addr_len;  struct addrinfo *addrf;    address[0] = '\0';  sock = socket(family, SOCK_DGRAM, 0);    if(family == AF_INET)    {      getaddrinfo(eXosip.ipv4_for_gateway,NULL,NULL,&addrf);    }  else if(family == AF_INET6)    {      getaddrinfo("2001:238:202::1",NULL,NULL,&addrf);    }    if (addrf==NULL)  {      closesocket(sock);      snprintf(address, size, (family == AF_INET) ? "127.0.0.1" : "::1" );      return -1;  }  if(WSAIoctl(sock,SIO_ROUTING_INTERFACE_QUERY, addrf->ai_addr, addrf->ai_addrlen,	      &local_addr, sizeof(local_addr), &local_addr_len, NULL, NULL) != 0)    {      closesocket(sock);      freeaddrinfo(addrf);      snprintf(address, size, (family == AF_INET) ? "127.0.0.1" : "::1" );      return -1;    }    closesocket(sock);  freeaddrinfo(addrf);    if(getnameinfo((const struct sockaddr*)&local_addr,		 local_addr_len,address, size, NULL, 0, NI_NUMERICHOST))    {      snprintf(address, size, (family == AF_INET) ? "127.0.0.1" : "::1" );      return -1;    }    return 0;}#elseinteXosip_guess_ip_for_via (int family, char *address, int size){  /* w2000 and W95/98 */  unsigned long best_interface_index;  DWORD hr;  /* NT4 (sp4 only?) */  PMIB_IPFORWARDTABLE ipfwdt;  DWORD siz_ipfwd_table = 0;  unsigned int ipf_cnt;  address[0] = '\0';  best_interface_index = -1;  /* w2000 and W95/98 only */  hr = GetBestInterface (inet_addr (eXosip.ipv4_for_gateway), &best_interface_index);  if (hr)    {      LPVOID lpMsgBuf;      FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |                     FORMAT_MESSAGE_FROM_SYSTEM |                     FORMAT_MESSAGE_IGNORE_INSERTS,                     NULL,                     hr,                     MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),                     (LPSTR) & lpMsgBuf, 0, NULL);      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL,                              "GetBestInterface: %s\r\n", lpMsgBuf));      best_interface_index = -1;    }  if (best_interface_index != -1)    {                           /* probably W2000 or W95/W98 */      char *servername;      char *serverip;      char *netmask;      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL,                              "Default Interface found %i\r\n",                              best_interface_index));      if (0 == eXosip_dns_get_local_fqdn (&servername, &serverip, &netmask,                                       best_interface_index))        {          osip_strncpy (address, serverip, size - 1);          osip_free (servername);          osip_free (serverip);          osip_free (netmask);          return 0;        }      return -1;    }  if (!GetIpForwardTable (NULL, &siz_ipfwd_table, FALSE) ==      ERROR_INSUFFICIENT_BUFFER      || !(ipfwdt = (PMIB_IPFORWARDTABLE) alloca (siz_ipfwd_table)))    {      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL,                              "Allocation error\r\n"));      return -1;    }  /* NT4 (sp4 support only?) */  if (!GetIpForwardTable (ipfwdt, &siz_ipfwd_table, FALSE))    {      for (ipf_cnt = 0; ipf_cnt < ipfwdt->dwNumEntries; ++ipf_cnt)        {          if (ipfwdt->table[ipf_cnt].dwForwardDest == 0)            {                   /* default gateway found */              char *servername;              char *serverip;              char *netmask;              OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL,                                      "Default Interface found %i\r\n",                                      ipfwdt->table[ipf_cnt].dwForwardIfIndex));              if (0 == eXosip_dns_get_local_fqdn (&servername,                                               &serverip,                                               &netmask,                                               ipfwdt->table[ipf_cnt].                                               dwForwardIfIndex))                {                  osip_strncpy (address, serverip, size);                  osip_free (servername);                  osip_free (serverip);                  osip_free (netmask);                  return 0;                }              return -1;            }        }    }  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL,                          "Please define a default network interface.\r\n"));#ifdef WANT_INTERFACE_ANYWAY  /* NT4 (sp4 support only?) */  if (!GetIpForwardTable (ipfwdt, &siz_ipfwd_table, FALSE))    {      for (ipf_cnt = 0; ipf_cnt < ipfwdt->dwNumEntries; ++ipf_cnt)        {          char *servername;          char *serverip;          char *netmask;          OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL,                                  "Default Interface found %i\r\n",                                  ipfwdt->table[ipf_cnt].dwForwardIfIndex));          if (0 == eXosip_dns_get_local_fqdn (&servername,                                           &serverip,                                           &netmask,                                           ipfwdt->table[ipf_cnt].                                           dwForwardIfIndex))            {              /* search for public */              if (eXosip_is_public_address (serverip) == 0)                {                  osip_strncpy (address, serverip, size);                  osip_free (servername);                  osip_free (serverip);                  osip_free (netmask);                  return 0;                }              osip_free (servername);              osip_free (serverip);              osip_free (netmask);            }        }    }  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,                          "No public interface found. searching private\r\n"));  /* NT4 (sp4 support only?) */  if (!GetIpForwardTable (ipfwdt, &siz_ipfwd_table, FALSE))    {      for (ipf_cnt = 0; ipf_cnt < ipfwdt->dwNumEntries; ++ipf_cnt)        {          char *servername;          char *serverip;          char *netmask;          OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL,                                  "Default Interface found %i\r\n",                                  ipfwdt->table[ipf_cnt].dwForwardIfIndex));          if (0 == eXosip_dns_get_local_fqdn (&servername,                                           &serverip,                                           &netmask,                                           ipfwdt->table[ipf_cnt].                                           dwForwardIfIndex))            {              osip_strncpy (address, serverip, size);              osip_free (servername);              osip_free (serverip);              osip_free (netmask);              return 0;            }        }    }  {    char *lo = osip_strdup ("127.0.0.1");    osip_strncpy (address, lo, size);    osip_free (lo);    return 0;  }  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,                          "No interface found. returning 127.0.0.1\r\n"));  /* no default gateway interface found */  return 0;#else  return -1;#endif /* WANT_INTERFACE_ANYWAY */}#endif#else /* sun, *BSD, linux, and other? */#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <sys/ioctl.h>#include <net/if.h>#include <unistd.h>#include <sys/param.h>#include <stdio.h>static int ppl_dns_default_gateway_ipv4 (char *address, int size);static int ppl_dns_default_gateway_ipv6 (char *address, int size);inteXosip_guess_ip_for_via (int family, char *address, int size){  if (family == AF_INET6)    {      return ppl_dns_default_gateway_ipv6 (address, size);  } else    {      return ppl_dns_default_gateway_ipv4 (address, size);    }}/* This is a portable way to find the default gateway. * The ip of the default interface is returned. */static intppl_dns_default_gateway_ipv4 (char *address, int size){#ifdef __APPLE_CC__  int len;#else  unsigned int len;#endif  int sock_rt, on = 1;  struct sockaddr_in iface_out;  struct sockaddr_in remote;  memset (&remote, 0, sizeof (struct sockaddr_in));  remote.sin_family = AF_INET;  remote.sin_addr.s_addr = inet_addr (eXosip.ipv4_for_gateway);  remote.sin_port = htons (11111);  memset (&iface_out, 0, sizeof (iface_out));  sock_rt = socket (AF_INET, SOCK_DGRAM, 0);  if (setsockopt (sock_rt, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) == -1)    {      perror ("DEBUG: [get_output_if] setsockopt(SOL_SOCKET, SO_BROADCAST");      close (sock_rt);      snprintf(address, size, "127.0.0.1");      return -1;    }  if (connect      (sock_rt, (struct sockaddr *) &remote, sizeof (struct sockaddr_in)) == -1)    {      perror ("DEBUG: [get_output_if] connect");      close (sock_rt);      snprintf(address, size, "127.0.0.1");      return -1;    }  len = sizeof (iface_out);  if (getsockname (sock_rt, (struct sockaddr *) &iface_out, &len) == -1)    {      perror ("DEBUG: [get_output_if] getsockname");      close (sock_rt);      snprintf(address, size, "127.0.0.1");      return -1;    }  close (sock_rt);  if (iface_out.sin_addr.s_addr == 0)    {                           /* what is this case?? */      snprintf(address, size, "127.0.0.1");      return -1;    }  osip_strncpy (address, inet_ntoa (iface_out.sin_addr), size - 1);  return 0;}/* This is a portable way to find the default gateway. * The ip of the default interface is returned. */static intppl_dns_default_gateway_ipv6 (char *address, int size){#ifdef __APPLE_CC__  int len;#else  unsigned int len;#endif  int sock_rt, on = 1;  struct sockaddr_in6 iface_out;  struct sockaddr_in6 remote;  memset (&remote, 0, sizeof (struct sockaddr_in6));  remote.sin6_family = AF_INET6;  inet_pton (AF_INET6, "2001:638:500:101:2e0:81ff:fe24:37c6", &remote.sin6_addr);  remote.sin6_port = htons (11111);  memset (&iface_out, 0, sizeof (iface_out));  sock_rt = socket (AF_INET6, SOCK_DGRAM, 0);  if (setsockopt (sock_rt, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) == -1)    {      perror ("DEBUG: [get_output_if] setsockopt(SOL_SOCKET, SO_BROADCAST");      close (sock_rt);      return -1;    }  if (connect      (sock_rt, (struct sockaddr *) &remote, sizeof (struct sockaddr_in6)) == -1)    {      perror ("DEBUG: [get_output_if] connect");      close (sock_rt);      return -1;    }  len = sizeof (iface_out);  if (getsockname (sock_rt, (struct sockaddr *) &iface_out, &len) == -1)    {      perror ("DEBUG: [get_output_if] getsockname");      close (sock_rt);      return -1;    }  close (sock_rt);  if (iface_out.sin6_addr.s6_addr == 0)    {                           /* what is this case?? */      return -1;    }  inet_ntop (AF_INET6, (const void *) &iface_out.sin6_addr, address, size - 1);  return 0;}#endif#ifdef SMinteXosip_get_localip_for (const char *address_to_reach, char *loc, int size){  int err, tmp;  struct addrinfo hints;  struct addrinfo *res = NULL;  struct sockaddr_storage addr;  int sock;#ifdef __APPLE_CC__  int s;#else  socklen_t s;#endif#ifdef MAXHOSTNAMELEN  if (size > MAXHOSTNAMELEN)    size = MAXHOSTNAMELEN;#else

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?