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 + -
显示快捷键?