📄 su_localinfo.c
字号:
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 + -