⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 su_localinfo.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 3 页
字号:
	goto err;      if (li->li_flags & LI_IFNAME) 	li->li_ifname = ifname;      if ((error = li_name(hints, NI_NUMERICHOST, su, &li->li_canonname)) < 0)	goto err;      else if (error > 0) {	free(li); li = NULL;       }    }  }  *rresult = li;  return 0;err:  if (li) su_freelocalinfo(li);  return error;}#endif#if HAVE_GETIFADDRS#include <ifaddrs.h>staticint bsd_localinfo(su_localinfo_t const hints[1], 		  su_localinfo_t **return_result){  struct ifaddrs *ifa, *results;  int error = 0;#if SU_HAVE_IN6  int v4_mapped = (hints->li_flags & LI_V4MAPPED) != 0;#endif  char *canonname = NULL;  if (getifaddrs(&results) < 0) {    if (errno == ENOMEM)      return ELI_MEMORY;    else      return ELI_SYSTEM;  }  for (ifa = results; ifa; ifa = ifa->ifa_next) {    su_localinfo_t *li;    su_sockaddr_t *su;#if SU_HAVE_IN6    su_sockaddr_t su2[1];#endif    socklen_t sulen;    int scope, flags = 0, gni_flags = 0, if_index = 0;    char const *ifname = 0;    size_t ifnamelen = 0;    /* no ip address from if that is down */    if ((ifa->ifa_flags & IFF_UP) == 0 && (hints->li_flags & LI_DOWN) == 0)      continue;    su = (su_sockaddr_t *)ifa->ifa_addr;    if (!su)      continue;    if (su->su_family == AF_INET) {      sulen = sizeof(su->su_sin);      scope = li_scope4(su->su_sin.sin_addr.s_addr);#if SU_HAVE_IN6      if (v4_mapped)	sulen = sizeof(su->su_sin6);#endif    }#if SU_HAVE_IN6    else if (su->su_family == AF_INET6) {      if (IN6_IS_ADDR_MULTICAST(&su->su_sin6.sin6_addr))	continue;      sulen = sizeof(su->su_sin6);      scope = li_scope6(&su->su_sin6.sin6_addr);    }#endif    else       continue;    if (hints->li_flags & LI_IFNAME) {      ifname = ifa->ifa_name;      if (ifname)	ifnamelen = strlen(ifname) + 1;    }    if ((hints->li_scope && (hints->li_scope & scope) == 0) ||	(hints->li_family && hints->li_family != su->su_family) ||	(hints->li_ifname && (!ifname || strcmp(hints->li_ifname, ifname))) ||	(hints->li_index && hints->li_index != if_index))      continue;        if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK)      gni_flags = NI_NUMERICHOST;#if SU_HAVE_IN6    if (v4_mapped && su->su_family == AF_INET) {      /* Map IPv4 address to IPv6 address */      memset(su2, 0, sizeof(*su2));      su2->su_family = AF_INET6;      ((int32_t*)&su2->su_sin6.sin6_addr)[2] = htonl(0xffff);      ((int32_t*)&su2->su_sin6.sin6_addr)[3] = su->su_sin.sin_addr.s_addr;      su = su2;    }#endif    if ((error = li_name(hints, gni_flags, su, &canonname)) < 0)      break;    if (error > 0) {      error = 0;      continue;    }        if (canonname)      if (strchr(canonname, ':') ||	  canonname[strspn(canonname, "0123456789.")] == '\0')	flags |= LI_NUMERIC;    if (!(li = calloc(1, sizeof(*li) + sulen + ifnamelen))) {      SU_DEBUG_1(("su_getlocalinfo: memory exhausted\n"));      error = ELI_MEMORY;      break;    }     *return_result = li, return_result = &li->li_next;    li->li_flags = flags;    li->li_family = su->su_family;    li->li_scope = scope;    li->li_index = if_index;    li->li_addrlen = sulen;    li->li_addr = memcpy(li + 1, su, sulen);    li->li_canonname = canonname;    if (ifnamelen) {      li->li_ifname = strcpy((char *)(li + 1) + sulen, ifname);    }    canonname = NULL;  }  if (canonname)    free(canonname);  freeifaddrs(results);  return error;}#elif USE_LOCALINFO0 && HAVE_IPHLPAPI_H && SU_HAVE_IN6static char const *ws2ifname(DWORD iftype){  switch (iftype) {  case IF_TYPE_ETHERNET_CSMACD:         return "eth";  case IF_TYPE_IEEE80212:               return "eth";  case IF_TYPE_FASTETHER:               return "eth";  case IF_TYPE_GIGABITETHERNET:         return "eth";  case IF_TYPE_ISO88025_TOKENRING:      return "token";  case IF_TYPE_FDDI:                    return "fddi";  case IF_TYPE_PPP:                     return "ppp";  case IF_TYPE_SOFTWARE_LOOPBACK:       return "lo";  case IF_TYPE_SLIP:                    return "sl";  case IF_TYPE_FRAMERELAY:              return "fr";  case IF_TYPE_ATM:                     return "atm";  case IF_TYPE_HIPPI:                   return "hippi";  case IF_TYPE_ISDN:                    return "isdn";  case IF_TYPE_IEEE80211:               return "wlan";  case IF_TYPE_ADSL:                    return "adsl";  case IF_TYPE_RADSL:                   return "radsl";  case IF_TYPE_SDSL:                    return "sdsl";  case IF_TYPE_VDSL:                    return "vdsl";  case IF_TYPE_TUNNEL:                  return "tunnel";  case IF_TYPE_IEEE1394:                return "fw";  case IF_TYPE_OTHER:  default:                              return "other";  }}staticint win_localinfo(su_localinfo_t const hints[1], su_localinfo_t **rresult){  /* This is Windows XP code, for both IPv6 and IPv4. */  ULONG iaa_size = 2048;  IP_ADAPTER_ADDRESSES *iaa0, *iaa;  int error, loopback_seen = 0;  int v4_mapped = (hints->li_flags & LI_V4MAPPED) != 0;  char *canonname = NULL;  su_localinfo_t *li, **next;  int flags = GAA_FLAG_SKIP_MULTICAST;  *rresult = NULL; next = rresult;  iaa0 = malloc((size_t)iaa_size);  if (!iaa0) {    SU_DEBUG_1(("su_localinfo: memory exhausted\n"));    error = ELI_MEMORY;    goto err;  }  error = GetAdaptersAddresses(hints->li_family, flags, NULL, iaa0, &iaa_size);  if (error == ERROR_BUFFER_OVERFLOW) {    if ((iaa0 = realloc(iaa0, iaa_size)))      error = GetAdaptersAddresses(hints->li_family, flags, NULL, iaa0, &iaa_size);  }  if (error) {    char const *empty = "";    LPTSTR msg = empty;    if (error == ERROR_NO_DATA) {      error = ELI_NOADDRESS;      goto err;    }    if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 	               FORMAT_MESSAGE_FROM_SYSTEM | 	               FORMAT_MESSAGE_IGNORE_INSERTS,	  	       NULL,	  	       error,		       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),		       msg, 0, NULL))      msg = empty;     SU_DEBUG_1(("su_localinfo: GetAdaptersAddresses: %s (%d)\n", msg, error));    if (msg != empty) LocalFree((LPVOID)msg);    error = ELI_SYSTEM;    goto err;  }    for (iaa = iaa0; iaa; iaa = iaa->Next) {    IP_ADAPTER_UNICAST_ADDRESS *ua;    IP_ADAPTER_UNICAST_ADDRESS lua[1];    int if_index = iaa->IfIndex;    size_t ifnamelen = 0;    char ifname[16];    for (ua = iaa->FirstUnicastAddress; ;ua = ua->Next) {      su_sockaddr_t *su;      socklen_t sulen;      su_sockaddr_t su2[1];      int scope, flags = 0, gni_flags = 0;      if (ua == NULL) {	/* There is no loopback interface in windows */	if (!loopback_seen && iaa->Next == NULL) {	  struct sockaddr_in loopback_sin = { AF_INET, 0, {{ 127, 0, 0, 1 }}};	  lua->Address.lpSockaddr = (struct sockaddr *)&loopback_sin;	  lua->Address.iSockaddrLength = sizeof(loopback_sin);	  lua->Next = NULL;	  iaa->IfType = IF_TYPE_SOFTWARE_LOOPBACK;	  if_index = 1;	  ua = lua;	}	else	  break;      }      su = (su_sockaddr_t *)ua->Address.lpSockaddr;      sulen = ua->Address.iSockaddrLength;      if (su->su_family == AF_INET) {	scope = li_scope4(su->su_sin.sin_addr.s_addr);	if (v4_mapped)	  sulen = sizeof(su->su_sin6);	if (scope == LI_SCOPE_HOST)	  loopback_seen = 1;      }      else if (su->su_family == AF_INET6) {	if (IN6_IS_ADDR_MULTICAST(&su->su_sin6.sin6_addr))	  continue;	scope = li_scope6(&su->su_sin6.sin6_addr);      }      else 	continue;      if (hints->li_flags & LI_IFNAME) {	snprintf(ifname, sizeof(ifname), "%s%u", 		 ws2ifname(iaa->IfType), if_index);	ifnamelen = strlen(ifname) + 1;      }      if ((hints->li_scope && (hints->li_scope & scope) == 0) ||	  (hints->li_family && hints->li_family != su->su_family) ||	  /* (hints->li_ifname && strcmp(hints->li_ifname, ifname) != 0) || */	  (hints->li_index && hints->li_index != if_index))	continue;          if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK)	gni_flags = NI_NUMERICHOST;      if (v4_mapped && su->su_family == AF_INET) {	/* Map IPv4 address to IPv6 address */	memset(su2, 0, sizeof(*su2));	su2->su_family = AF_INET6;	((int32_t*)&su2->su_sin6.sin6_addr)[2] = htonl(0xffff);	((int32_t*)&su2->su_sin6.sin6_addr)[3] = su->su_sin.sin_addr.s_addr;	su = su2;      }      if ((error = li_name(hints, gni_flags, su, &canonname)) < 0)	goto err;      else if (error > 0)	continue;          if (canonname)	if (strchr(canonname, ':') ||	    strspn(canonname, "0123456789.") == strlen(canonname))	  flags |= LI_NUMERIC;      if (!(li = calloc(1, sizeof(*li) + sulen + ifnamelen))) {	SU_DEBUG_1(("su_getlocalinfo: memory exhausted\n"));	error = ELI_MEMORY; goto err;      }       *next = li, next = &li->li_next;      li->li_flags = flags;      li->li_family = su->su_family;      li->li_scope = scope;      li->li_index = if_index;      li->li_addrlen = sulen;      li->li_addr = memcpy(li + 1, su, sulen);      li->li_canonname = canonname;      if (ifnamelen) {	li->li_ifname = strcpy((char *)(li + 1) + sulen, ifname);	/* WideCharToMultiByte(CP_ACP, 0,			    ifname, -1, (char *)(li + 1) + sulen, ifnamelen,			    NULL, NULL); */      }      canonname = NULL;    }  }  if (iaa0) free(iaa0);  return 0;err:  if (iaa0) free(iaa0);  if (canonname) free(canonname);  su_freelocalinfo(*rresult), *rresult = NULL;  return error;}#elif HAVE_SIO_ADDRESS_LIST_QUERYstaticint localinfo0(su_localinfo_t const *hints, su_localinfo_t **rresult){  /* This is Windows IPv4 code */  short family = AF_INET;  su_socket_t s;  union {    SOCKET_ADDRESS_LIST sal[1];#if HAVE_INTERFACE_INFO_EX    INTERFACE_INFO_EX   ii[1];    #else    INTERFACE_INFO      ii[1];#endif    char buffer[2048];  } b = {{ 1 }};  DWORD salen = sizeof(b);  int i, error = -1;#if SU_HAVE_IN6  int v4_mapped = (hints->li_flags & LI_V4MAPPED) != 0;#endif  su_localinfo_t *li, *head = NULL, **next = &head;  char *canonname = NULL, *if_name = NULL;  *rresult = NULL;  s = su_socket(family, SOCK_DGRAM, 0);  if (s == INVALID_SOCKET) {    SU_DEBUG_1(("su_getlocalinfo: %s: %s\n", "su_socket",		            su_strerror(su_errno())));    return -1;  }  /* get the list of known IP address (NT5 and up) */  if (WSAIoctl(s, SIO_ADDRESS_LIST_QUERY, NULL, 0,               &b, sizeof(b), &salen, NULL, NULL) == SOCKET_ERROR) {    SU_DEBUG_1(("su_getlocalinfo: %s: %s\n", "SIO_ADDRESS_LIST_QUERY",		su_strerror(su_errno())));    error = -1; goto err;  }  if (b.sal->iAddressCount < 1) {    SU_DEBUG_1(("su_getlocalinfo: no local addresses\n"));    error = -1; goto err;  }    for (i = 0; i < b.sal->iAddressCount; i++) {    su_sockaddr_t *su = (su_sockaddr_t *)b.sal->Address[i].lpSockaddr;#if SU_HAVE_IN6    socklen_t sulen = v4_mapped ? sizeof(*su) : b.sal->Address[i].iSockaddrLength;    su_sockaddr_t su2[1];#else    socklen_t sulen = b.sal->Address[i].iSockaddrLength;#endif    int scope, flags = 0, gni_flags = 0;    scope = li_scope4(su->su_sin.sin_addr.s_addr);    if (hints->li_scope && (hints->li_scope & scope) == 0)      continue;        if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK)      gni_flags = NI_NUMERICHOST;    if (!(li = calloc(1, sizeof(*li) + sulen))) {      SU_DEBUG_1(("su_getlocalinfo: memory exhausted\n"));      error = -1; goto err;    }    *next = li, next = &li->li_next;#if SU_HAVE_IN6    if (v4_mapped) {      /* Map IPv4 address to IPv6 address */      memset(su2, 0, sizeof(*su2));      su2->su_family = AF_INET6;      ((int32_t*)&su2->su_sin6.sin6_addr)[2] = htonl(0xffff);      ((int32_t*)&su2->su_sin6.sin6_addr)[3] = su->su_sin.sin_addr.s_addr;      su = su2;    }#endif    if ((error = li_name(hints, gni_flags, su, &canonname)) < 0)      goto err;    else if (error > 0)      continue;        if (canonname)      if (strchr(canonname, ':') ||	  strspn(canonname, "0123456789.") == strlen(canonname))	flags |= LI_NUMERIC;       li->li_flags = flags;    li->li_family = su->su_family;    li->li_scope = scope;    li->li_index = i;    li->li_addrlen = su_sockaddr_size(su);    li->li_addr = su;    li->li_canonname = canonname, canonname = NULL;    if (hints->li_flags & LI_IFNAME)      li->li_ifname = if_name;    li->li_addr = (su_sockaddr_t *)(li + 1);     li->li_addrlen = sulen;    memcpy(li->li_addr, su, sulen);  }  *rresult = head;  su_close(s);  return 0;err:  if (canonname) free(canonname);  su_freelocalinfo(head);  su_close(s);  return error;}#endifstatic int li_name(su_localinfo_t const *hints, 	    int gni_flags,	    su_sockaddr_t const *su, 	    char **ccanonname){  char name[SU_MAXHOST];  int error;  int flags = hints->li_flags;  *ccanonname = NULL;  if ((flags & LI_CANONNAME) || hints->li_canonname) {    if ((flags & LI_NAMEREQD) == LI_NAMEREQD)      gni_flags |= NI_NAMEREQD;          if (flags & LI_NUMERIC)      gni_flags |= NI_NUMERICHOST;    error = su_getnameinfo(su, su_sockaddr_size(su), 			   name, sizeof(name), NULL, 0,			   gni_flags);    if (error) {      if ((flags & LI_NAMEREQD) == LI_NAMEREQD)	return 1;      SU_DEBUG_7(("li_name: getnameinfo() failed\n"));      if (!su_inet_ntop(su->su_family, SU_ADDR(su), name, sizeof name))	return ELI_RESOLVER;    }    if (hints->li_canonname && strcasecmp(name, hints->li_canonname))      return 1;    if (!(flags & LI_CANONNAME))      return 0;    if (!(*ccanonname = strdup(name)))      return ELI_MEMORY;  }  return 0;}staticvoid li_sort(su_localinfo_t *i, su_localinfo_t **rresult){  su_localinfo_t *li, **lli;#define LI_MAPPED(li) \  ((li)->li_family == AF_INET6 &&					\   (IN6_IS_ADDR_V4MAPPED(&(li)->li_addr->su_sin6.sin6_addr) ||		\    IN6_IS_ADDR_V4COMPAT(&(li)->li_addr->su_sin6.sin6_addr)))  /* Sort addresses according to scope (and mappedness) */  for (li = i; li; li = i) {    i = li->li_next;    for (lli = rresult; *lli; lli = &(*lli)->li_next) {      if ((*lli)->li_scope < li->li_scope)	break;#if SU_HAVE_IN6      if (LI_MAPPED(*lli) > LI_MAPPED(li))	break;#endif    }    li->li_next = *lli;    *lli = li;  }}/**Get local IP address. * * @deprecated * Use su_getlocalinfo() instead. */int su_getlocalip(su_sockaddr_t *sa){  su_localinfo_t *li = NULL, hints[1] = {{ 0 }};  hints->li_family = sa->su_sa.sa_family ? sa->su_sa.sa_family : AF_INET;  if (su_getlocalinfo(hints, &li) == 0) {    memcpy(sa, li->li_addr, li->li_addrlen);    su_freelocalinfo(li);    return 0;  }  else     return -1;}

⌨️ 快捷键说明

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