📄 getaddrinfo.c
字号:
ip = *((u_long *) entry->h_addr); if (flags & AI_CANONNAME) name = entry->h_name; } if ((flags & AI_CANONNAME) && (name == NULL)) name = node; /* service resolution */ if (service == NULL) port = 0; else { unsigned long d; char *end; d = strtoul (service, &end, 0); if (end[0] || (d > 65535u)) return EAI_SERVICE; port = htons ((u_short)d); } /* building results... */ if ((!protocol) || (protocol == IPPROTO_UDP)) { info = makeipv4info (SOCK_DGRAM, IPPROTO_UDP, ip, port, name); if (info == NULL) { errno = ENOMEM; return EAI_SYSTEM; } if (flags & AI_PASSIVE) info->ai_flags |= AI_PASSIVE; *res = info; } if ((!protocol) || (protocol == IPPROTO_TCP)) { info = makeipv4info (SOCK_STREAM, IPPROTO_TCP, ip, port, name); if (info == NULL) { errno = ENOMEM; return EAI_SYSTEM; } info->ai_next = *res; if (flags & AI_PASSIVE) info->ai_flags |= AI_PASSIVE; *res = info; } return 0;}#undef getaddrinfo#define getaddrifo stub_getaddrinfo#undef freeaddrinfo#define freeaddrifo stub_freeaddrinfo#endif /* if !HAVE_GETADDRINFO */#if defined( WIN32 ) && !defined( UNDER_CE ) /* * Here is the kind of kludge you need to keep binary compatibility among * varying OS versions... */typedef int (WSAAPI * GETNAMEINFO) ( const struct sockaddr FAR *, socklen_t, char FAR *, DWORD, char FAR *, DWORD, int );typedef int (WSAAPI * GETADDRINFO) (const char FAR *, const char FAR *, const struct addrinfo FAR *, struct addrinfo FAR * FAR *);typedef void (WSAAPI * FREEADDRINFO) ( struct addrinfo FAR * );static int WSAAPI _ws2_getnameinfo_bind ( const struct sockaddr FAR *, socklen_t, char FAR *, DWORD, char FAR *, DWORD, int );static int WSAAPI _ws2_getaddrinfo_bind (const char FAR *, const char FAR *, const struct addrinfo FAR *, struct addrinfo FAR * FAR *);static GETNAMEINFO ws2_getnameinfo = _ws2_getnameinfo_bind;static GETADDRINFO ws2_getaddrinfo = _ws2_getaddrinfo_bind;static FREEADDRINFO ws2_freeaddrinfo;static FARPROC ws2_find_api (LPCTSTR name){ FARPROC f = NULL; HMODULE m = GetModuleHandle (TEXT("WS2_32")); if (m != NULL) f = GetProcAddress (m, name); if (f == NULL) { /* Windows 2K IPv6 preview */ m = LoadLibrary (TEXT("WSHIP6")); if (m != NULL) f = GetProcAddress (m, name); } return f;}static WSAAPI int _ws2_getnameinfo_bind( const struct sockaddr FAR * sa, socklen_t salen, char FAR *host, DWORD hostlen, char FAR *serv, DWORD servlen, int flags ){ GETNAMEINFO entry = (GETNAMEINFO)ws2_find_api (TEXT("getnameinfo")); int result; if (entry == NULL) { /* not found, use replacement API instead */ entry = stub_getnameinfo; } /* call API before replacing function pointer to avoid crash */ result = entry (sa, salen, host, hostlen, serv, servlen, flags); ws2_getnameinfo = entry; return result;}#undef getnameinfo#define getnameinfo ws2_getnameinfostatic WSAAPI int _ws2_getaddrinfo_bind(const char FAR *node, const char FAR *service, const struct addrinfo FAR *hints, struct addrinfo FAR * FAR *res){ GETADDRINFO entry; FREEADDRINFO freentry; int result; entry = (GETADDRINFO)ws2_find_api (TEXT("getaddrinfo")); freentry = (FREEADDRINFO)ws2_find_api (TEXT("freeaddrinfo")); if ((entry == NULL) || (freentry == NULL)) { /* not found, use replacement API instead */ entry = stub_getaddrinfo; freentry = stub_freeaddrinfo; } /* call API before replacing function pointer to avoid crash */ result = entry (node, service, hints, res); ws2_freeaddrinfo = freentry; ws2_getaddrinfo = entry; return result;}#undef getaddrinfo#undef freeaddrinfo#define getaddrinfo ws2_getaddrinfo#define freeaddrinfo ws2_freeaddrinfo#define HAVE_GETADDRINFO#endifint vlc_getnameinfo( const struct sockaddr *sa, int salen, char *host, int hostlen, int *portnum, int flags ){ char psz_servbuf[6], *psz_serv; int i_servlen, i_val; flags |= NI_NUMERICSERV; if( portnum != NULL ) { psz_serv = psz_servbuf; i_servlen = sizeof( psz_servbuf ); } else { psz_serv = NULL; i_servlen = 0; } i_val = getnameinfo(sa, salen, host, hostlen, psz_serv, i_servlen, flags); if( portnum != NULL ) *portnum = atoi( psz_serv ); return i_val;}int vlc_getaddrinfo( vlc_object_t *p_this, const char *node, int i_port, const struct addrinfo *p_hints, struct addrinfo **res ){ struct addrinfo hints; char psz_buf[NI_MAXHOST], *psz_node, psz_service[6]; /* * In VLC, we always use port number as integer rather than strings * for historical reasons (and portability). */ if( ( i_port > 65535 ) || ( i_port < 0 ) ) { msg_Err( p_this, "invalid port number %d specified", i_port ); return EAI_SERVICE; } /* cannot overflow */ snprintf( psz_service, 6, "%d", i_port ); /* Check if we have to force ipv4 or ipv6 */ memset (&hints, 0, sizeof (hints)); if (p_hints != NULL) { const int safe_flags = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV |#ifdef AI_ALL AI_ALL |#endif#ifdef AI_ADDRCONFIG AI_ADDRCONFIG |#endif#ifdef AI_V4MAPPED AI_V4MAPPED |#endif 0; hints.ai_family = p_hints->ai_family; hints.ai_socktype = p_hints->ai_socktype; hints.ai_protocol = p_hints->ai_protocol; /* Unfortunately, some flags chang the layout of struct addrinfo, so * they cannot be copied blindly from p_hints to &hints. Therefore, we * only copy flags that we know for sure are "safe". */ hints.ai_flags = p_hints->ai_flags & safe_flags; } /* We only ever use port *numbers* */ hints.ai_flags |= AI_NUMERICSERV; if( hints.ai_family == AF_UNSPEC ) {#ifdef AF_INET6 if (var_CreateGetBool (p_this, "ipv6")) hints.ai_family = AF_INET6; else#endif if (var_CreateGetBool (p_this, "ipv4")) hints.ai_family = AF_INET; } /* * VLC extensions : * - accept "" as NULL * - ignore square brackets */ if( ( node == NULL ) || (node[0] == '\0' ) ) { psz_node = NULL; } else { strlcpy( psz_buf, node, NI_MAXHOST ); psz_node = psz_buf; if( psz_buf[0] == '[' ) { char *ptr; ptr = strrchr( psz_buf, ']' ); if( ( ptr != NULL ) && (ptr[1] == '\0' ) ) { *ptr = '\0'; psz_node++; } } }#ifdef WIN32 /* * Winsock tries to resolve numerical IPv4 addresses as AAAA * and IPv6 addresses as A... There comes the bug-to-bug fix. */ if ((hints.ai_flags & AI_NUMERICHOST) == 0) { hints.ai_flags |= AI_NUMERICHOST; if (getaddrinfo (psz_node, psz_service, &hints, res) == 0) return 0; hints.ai_flags &= ~AI_NUMERICHOST; }#endif#ifdef AI_IDN /* Run-time I18n Domain Names support */ hints.ai_flags |= AI_IDN; int ret = getaddrinfo (psz_node, psz_service, &hints, res); if (ret != EAI_BADFLAGS) return ret; /* IDN not available: disable and retry without it */ hints.ai_flags &= ~AI_IDN;#endif return getaddrinfo (psz_node, psz_service, &hints, res);}void vlc_freeaddrinfo( struct addrinfo *infos ){ freeaddrinfo (infos);}/** * inet_pton() replacement */int vlc_inet_pton (int af, const char *src, void *dst){#ifndef HAVE_INET_PTON /* Windows Vista has inet_pton(), but not XP. */ /* We have a pretty good example of abstraction inversion here... */ struct addrinfo hints = { .ai_family = af, .ai_socktype = SOCK_DGRAM, /* make sure we have... */ .ai_protocol = IPPROTO_UDP, /* ...only one response */ .ai_flags = AI_NUMERICHOST, }, *res; if (getaddrinfo (src, NULL, &hints, &res)) return 0; const void *data; size_t len; switch (af) { case AF_INET: data = &((const struct sockaddr_in *)res->ai_addr)->sin_addr; len = sizeof (struct in_addr); break;#ifdef AF_INET6 case AF_INET6: data = &((const struct sockaddr_in6 *)res->ai_addr)->sin6_addr; len = sizeof (struct in6_addr); break;#endif default: freeaddrinfo (res); return -1; } memcpy (dst, data, len); freeaddrinfo (res); return 1;#else /* HAVE_INET_PTON */ return inet_pton( af, src, dst );#endif /* HAVE_INET_PTON */}/** * inet_ntop() replacement */const char *vlc_inet_ntop (int af, const void *src, char *dst, socklen_t cnt){#ifndef HAVE_INET_NTOP int ret = EAI_FAMILY; switch (af) {#ifdef AF_INET6 case AF_INET6: { struct sockaddr_in6 addr; memset (&addr, 0, sizeof(addr)); addr.sin6_family = AF_INET6; addr.sin6_addr = *(struct in6_addr *)src; ret = getnameinfo ((struct sockaddr *)&addr, sizeof (addr), dst, cnt, NULL, 0, NI_NUMERICHOST); }#endif case AF_INET: { struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr = *(struct in_addr *)src; ret = getnameinfo ((struct sockaddr *)&addr, sizeof (addr), dst, cnt, NULL, 0, NI_NUMERICHOST); } } return (ret == 0) ? dst : NULL;#else /* HAVE_INET_NTOP */ return inet_ntop( af, src, dst, cnt );#endif /* HAVE_INET_NTOP */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -