| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
#ifdef HAVE_CONFIG_H |
|---|
| 26 |
# include "config.h" |
|---|
| 27 |
#endif |
|---|
| 28 |
|
|---|
| 29 |
#include <vlc_common.h> |
|---|
| 30 |
|
|---|
| 31 |
#include <stddef.h> |
|---|
| 32 |
#include <string.h> |
|---|
| 33 |
#include <stdlib.h> |
|---|
| 34 |
#include <errno.h> |
|---|
| 35 |
|
|---|
| 36 |
#ifdef HAVE_SYS_TYPES_H |
|---|
| 37 |
# include <sys/types.h> |
|---|
| 38 |
#endif |
|---|
| 39 |
#ifdef HAVE_ARPA_INET_H |
|---|
| 40 |
# include <arpa/inet.h> |
|---|
| 41 |
#endif |
|---|
| 42 |
#ifdef HAVE_NETINET_IN_H |
|---|
| 43 |
# include <netinet/in.h> |
|---|
| 44 |
#endif |
|---|
| 45 |
#ifdef HAVE_UNISTD_H |
|---|
| 46 |
# include <unistd.h> |
|---|
| 47 |
#endif |
|---|
| 48 |
|
|---|
| 49 |
#include <vlc_network.h> |
|---|
| 50 |
|
|---|
| 51 |
#ifndef NO_ADDRESS |
|---|
| 52 |
# define NO_ADDRESS NO_DATA |
|---|
| 53 |
#endif |
|---|
| 54 |
#ifndef INADDR_NONE |
|---|
| 55 |
# define INADDR_NONE 0xFFFFFFFF |
|---|
| 56 |
#endif |
|---|
| 57 |
#ifndef AF_UNSPEC |
|---|
| 58 |
# define AF_UNSPEC 0 |
|---|
| 59 |
#endif |
|---|
| 60 |
|
|---|
| 61 |
|
|---|
| 62 |
#ifndef HAVE_GAI_STRERROR |
|---|
| 63 |
static const struct |
|---|
| 64 |
{ |
|---|
| 65 |
int code; |
|---|
| 66 |
const char msg[41]; |
|---|
| 67 |
} gai_errlist[] = |
|---|
| 68 |
{ |
|---|
| 69 |
{ 0, "Error 0" }, |
|---|
| 70 |
{ EAI_BADFLAGS, "Invalid flag used" }, |
|---|
| 71 |
{ EAI_NONAME, "Host or service not found" }, |
|---|
| 72 |
{ EAI_AGAIN, "Temporary name service failure" }, |
|---|
| 73 |
{ EAI_FAIL, "Non-recoverable name service failure" }, |
|---|
| 74 |
{ EAI_NODATA, "No data for host name" }, |
|---|
| 75 |
{ EAI_FAMILY, "Unsupported address family" }, |
|---|
| 76 |
{ EAI_SOCKTYPE, "Unsupported socket type" }, |
|---|
| 77 |
{ EAI_SERVICE, "Incompatible service for socket type" }, |
|---|
| 78 |
{ EAI_ADDRFAMILY, "Unavailable address family for host name" }, |
|---|
| 79 |
{ EAI_MEMORY, "Memory allocation failure" }, |
|---|
| 80 |
{ EAI_OVERFLOW, "Buffer overflow" }, |
|---|
| 81 |
{ EAI_SYSTEM, "System error" }, |
|---|
| 82 |
{ 0, "" }, |
|---|
| 83 |
}; |
|---|
| 84 |
|
|---|
| 85 |
static const char gai_unknownerr[] = "Unrecognized error number"; |
|---|
| 86 |
|
|---|
| 87 |
|
|---|
| 88 |
|
|---|
| 89 |
|
|---|
| 90 |
const char *vlc_gai_strerror (int errnum) |
|---|
| 91 |
{ |
|---|
| 92 |
for (unsigned i = 0; *gai_errlist[i].msg; i++) |
|---|
| 93 |
if (errnum == gai_errlist[i].code) |
|---|
| 94 |
return gai_errlist[i].msg; |
|---|
| 95 |
|
|---|
| 96 |
return gai_unknownerr; |
|---|
| 97 |
} |
|---|
| 98 |
#else |
|---|
| 99 |
const char *vlc_gai_strerror (int errnum) |
|---|
| 100 |
{ |
|---|
| 101 |
return gai_strerror (errnum); |
|---|
| 102 |
} |
|---|
| 103 |
#endif |
|---|
| 104 |
|
|---|
| 105 |
#ifndef HAVE_GETNAMEINFO |
|---|
| 106 |
#define _NI_MASK (NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|\ |
|---|
| 107 |
NI_DGRAM) |
|---|
| 108 |
|
|---|
| 109 |
|
|---|
| 110 |
|
|---|
| 111 |
|
|---|
| 112 |
|
|---|
| 113 |
|
|---|
| 114 |
|
|---|
| 115 |
|
|---|
| 116 |
|
|---|
| 117 |
|
|---|
| 118 |
|
|---|
| 119 |
|
|---|
| 120 |
#ifdef WIN32 |
|---|
| 121 |
static int WSAAPI |
|---|
| 122 |
stub_getnameinfo (const struct sockaddr *sa, socklen_t salen, |
|---|
| 123 |
char *host, DWORD hostlen, char *serv, DWORD servlen, int flags) |
|---|
| 124 |
#else |
|---|
| 125 |
static int |
|---|
| 126 |
stub_getnameinfo (const struct sockaddr *sa, socklen_t salen, |
|---|
| 127 |
char *host, int hostlen, char *serv, int servlen, int flags) |
|---|
| 128 |
#endif |
|---|
| 129 |
{ |
|---|
| 130 |
if (((size_t)salen < sizeof (struct sockaddr_in)) |
|---|
| 131 |
|| (sa->sa_family != AF_INET)) |
|---|
| 132 |
return EAI_FAMILY; |
|---|
| 133 |
else if (flags & (~_NI_MASK)) |
|---|
| 134 |
return EAI_BADFLAGS; |
|---|
| 135 |
else |
|---|
| 136 |
{ |
|---|
| 137 |
const struct sockaddr_in *addr; |
|---|
| 138 |
|
|---|
| 139 |
addr = (const struct sockaddr_in *)sa; |
|---|
| 140 |
|
|---|
| 141 |
if (host != NULL) |
|---|
| 142 |
{ |
|---|
| 143 |
|
|---|
| 144 |
if (!(flags & NI_NUMERICHOST)) |
|---|
| 145 |
{ |
|---|
| 146 |
if (flags & NI_NAMEREQD) |
|---|
| 147 |
return EAI_NONAME; |
|---|
| 148 |
} |
|---|
| 149 |
|
|---|
| 150 |
|
|---|
| 151 |
uint32_t ipv4 = ntohl (addr->sin_addr.s_addr); |
|---|
| 152 |
|
|---|
| 153 |
if (snprintf (host, hostlen, "%u.%u.%u.%u", ipv4 >> 24, |
|---|
| 154 |
(ipv4 >> 16) & 0xff, (ipv4 >> 8) & 0xff, |
|---|
| 155 |
ipv4 & 0xff) >= (int)hostlen) |
|---|
| 156 |
return EAI_OVERFLOW; |
|---|
| 157 |
} |
|---|
| 158 |
|
|---|
| 159 |
if (serv != NULL) |
|---|
| 160 |
{ |
|---|
| 161 |
if (snprintf (serv, servlen, "%u", |
|---|
| 162 |
(unsigned int)ntohs (addr->sin_port)) >= (int)servlen) |
|---|
| 163 |
return EAI_OVERFLOW; |
|---|
| 164 |
} |
|---|
| 165 |
} |
|---|
| 166 |
return 0; |
|---|
| 167 |
} |
|---|
| 168 |
#undef getnameinfo |
|---|
| 169 |
#define getnameifo stub_getnameinfo |
|---|
| 170 |
#endif |
|---|
| 171 |
|
|---|
| 172 |
#ifndef HAVE_GETADDRINFO |
|---|
| 173 |
#define _AI_MASK (AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST) |
|---|
| 174 |
|
|---|
| 175 |
|
|---|
| 176 |
|
|---|
| 177 |
|
|---|
| 178 |
static int |
|---|
| 179 |
gai_error_from_herrno (void) |
|---|
| 180 |
{ |
|---|
| 181 |
switch (h_errno) |
|---|
| 182 |
{ |
|---|
| 183 |
case HOST_NOT_FOUND: |
|---|
| 184 |
return EAI_NONAME; |
|---|
| 185 |
|
|---|
| 186 |
case NO_ADDRESS: |
|---|
| 187 |
# if (NO_ADDRESS != NO_DATA) |
|---|
| 188 |
case NO_DATA: |
|---|
| 189 |
# endif |
|---|
| 190 |
return EAI_NODATA; |
|---|
| 191 |
|
|---|
| 192 |
case NO_RECOVERY: |
|---|
| 193 |
return EAI_FAIL; |
|---|
| 194 |
|
|---|
| 195 |
case TRY_AGAIN: |
|---|
| 196 |
return EAI_AGAIN; |
|---|
| 197 |
} |
|---|
| 198 |
return EAI_SYSTEM; |
|---|
| 199 |
} |
|---|
| 200 |
|
|---|
| 201 |
|
|---|
| 202 |
|
|---|
| 203 |
|
|---|
| 204 |
#ifdef WIN32 |
|---|
| 205 |
static void WSAAPI stub_freeaddrinfo (struct addrinfo *res) |
|---|
| 206 |
#else |
|---|
| 207 |
static void stub_freeaddrinfo (struct addrinfo *res) |
|---|
| 208 |
#endif |
|---|
| 209 |
{ |
|---|
| 210 |
if (res == NULL) |
|---|
| 211 |
return; |
|---|
| 212 |
free (res->ai_canonname); |
|---|
| 213 |
free (res->ai_addr); |
|---|
| 214 |
free (res->ai_next); |
|---|
| 215 |
free (res); |
|---|
| 216 |
} |
|---|
| 217 |
|
|---|
| 218 |
|
|---|
| 219 |
|
|---|
| 220 |
|
|---|
| 221 |
|
|---|
| 222 |
static struct addrinfo * |
|---|
| 223 |
makeaddrinfo (int af, int type, int proto, |
|---|
| 224 |
const struct sockaddr *addr, size_t addrlen, |
|---|
| 225 |
const char *canonname) |
|---|
| 226 |
{ |
|---|
| 227 |
struct addrinfo *res; |
|---|
| 228 |
|
|---|
| 229 |
res = (struct addrinfo *)malloc (sizeof (struct addrinfo)); |
|---|
| 230 |
if (res != NULL) |
|---|
| 231 |
{ |
|---|
| 232 |
res->ai_flags = 0; |
|---|
| 233 |
res->ai_family = af; |
|---|
| 234 |
res->ai_socktype = type; |
|---|
| 235 |
res->ai_protocol = proto; |
|---|
| 236 |
res->ai_addrlen = addrlen; |
|---|
| 237 |
res->ai_addr = malloc (addrlen); |
|---|
| 238 |
res->ai_canonname = NULL; |
|---|
| 239 |
res->ai_next = NULL; |
|---|
| 240 |
|
|---|
| 241 |
if (res->ai_addr != NULL) |
|---|
| 242 |
{ |
|---|
| 243 |
memcpy (res->ai_addr, addr, addrlen); |
|---|
| 244 |
|
|---|
| 245 |
if (canonname != NULL) |
|---|
| 246 |
{ |
|---|
| 247 |
res->ai_canonname = strdup (canonname); |
|---|
| 248 |
if (res->ai_canonname != NULL) |
|---|
| 249 |
return res; |
|---|
| 250 |
} |
|---|
| 251 |
else |
|---|
| 252 |
return res; |
|---|
| 253 |
} |
|---|
| 254 |
} |
|---|
| 255 |
|
|---|
| 256 |
vlc_freeaddrinfo (res); |
|---|
| 257 |
return NULL; |
|---|
| 258 |
} |
|---|
| 259 |
|
|---|
| 260 |
|
|---|
| 261 |
static struct addrinfo * |
|---|
| 262 |
makeipv4info (int type, int proto, u_long ip, u_short port, const char *name) |
|---|
| 263 |
{ |
|---|
| 264 |
struct sockaddr_in addr; |
|---|
| 265 |
|
|---|
| 266 |
memset (&addr, 0, sizeof (addr)); |
|---|
| 267 |
addr.sin_family = AF_INET; |
|---|
| 268 |
# ifdef HAVE_SA_LEN |
|---|
| 269 |
addr.sin_len = sizeof (addr); |
|---|
| 270 |
# endif |
|---|
| 271 |
addr.sin_port = port; |
|---|
| 272 |
addr.sin_addr.s_addr = ip; |
|---|
| 273 |
|
|---|
| 274 |
return makeaddrinfo (AF_INET, type, proto, |
|---|
| 275 |
(struct sockaddr*)&addr, sizeof (addr), name); |
|---|
| 276 |
} |
|---|
| 277 |
|
|---|
| 278 |
|
|---|
| 279 |
|
|---|
| 280 |
|
|---|
| 281 |
|
|---|
| 282 |
|
|---|
| 283 |
|
|---|
| 284 |
|
|---|
| 285 |
|
|---|
| 286 |
|
|---|
| 287 |
|
|---|
| 288 |
#ifdef WIN32 |
|---|
| 289 |
static int WSAAPI |
|---|
| 290 |
stub_getaddrinfo (const char *node, const char *service, |
|---|
| 291 |
const struct addrinfo *hints, struct addrinfo **res) |
|---|
| 292 |
#else |
|---|
| 293 |
static int |
|---|
| 294 |
stub_getaddrinfo (const char *node, const char *service, |
|---|
| 295 |
const struct addrinfo *hints, struct addrinfo **res) |
|---|
| 296 |
#endif |
|---|
| 297 |
{ |
|---|
| 298 |
struct addrinfo *info; |
|---|
| 299 |
u_long ip; |
|---|
| 300 |
u_short port; |
|---|
| 301 |
int protocol = 0, flags = 0; |
|---|
| 302 |
const char *name = NULL; |
|---|
| 303 |
|
|---|
| 304 |
#ifdef WIN32 |
|---|
| 305 |
|
|---|
| 306 |
|
|---|
| 307 |
|
|---|
| 308 |
|
|---|
| 309 |
|
|---|
| 310 |
|
|---|
| 311 |
|
|---|
| 312 |
|
|---|
| 313 |
|
|---|
| 314 |
|
|---|
| 315 |
|
|---|
| 316 |
|
|---|
| 317 |
|
|---|
| 318 |
|
|---|
| 319 |
|
|---|
| 320 |
|
|---|
| 321 |
|
|---|
| 322 |
|
|---|
| 323 |
|
|---|
| 324 |
|
|---|
| 325 |
if ((node != NULL) && (strchr (node, ':') != NULL)) |
|---|
| 326 |
return EAI_NONAME; |
|---|
| 327 |
#endif |
|---|
| 328 |
|
|---|
| 329 |
if (hints != NULL) |
|---|
| 330 |
{ |
|---|
| 331 |
flags = hints->ai_flags; |
|---|
| 332 |
|
|---|
| 333 |
if (flags & ~_AI_MASK) |
|---|
| 334 |
return EAI_BADFLAGS; |
|---|
| 335 |
|
|---|
| 336 |
if (hints->ai_family && (hints->ai_family != AF_INET)) |
|---|
| 337 |
return EAI_FAMILY; |
|---|
| 338 |
|
|---|
| 339 |
|
|---|
| 340 |
switch (hints->ai_socktype) |
|---|
| 341 |
{ |
|---|
| 342 |
case SOCK_STREAM: |
|---|
| 343 |
protocol = IPPROTO_TCP; |
|---|
| 344 |
break; |
|---|
| 345 |
|
|---|
| 346 |
case SOCK_DGRAM: |
|---|
| 347 |
protocol = IPPROTO_UDP; |
|---|
| 348 |
break; |
|---|
| 349 |
|
|---|
| 350 |
#ifndef SOCK_RAW |
|---|
| 351 |
case SOCK_RAW: |
|---|
| 352 |
#endif |
|---|
| 353 |
case 0: |
|---|
| 354 |
break; |
|---|
| 355 |
|
|---|
| 356 |
default: |
|---|
| 357 |
return EAI_SOCKTYPE; |
|---|
| 358 |
} |
|---|
| 359 |
if (hints->ai_protocol && protocol |
|---|
| 360 |
&& (protocol != hints->ai_protocol)) |
|---|
| 361 |
return EAI_SERVICE; |
|---|
| 362 |
} |
|---|
| 363 |
|
|---|
| 364 |
*res = NULL; |
|---|
| 365 |
|
|---|
| 366 |
|
|---|
| 367 |
if (node == NULL) |
|---|
| 368 |
{ |
|---|
| 369 |
if (flags & AI_PASSIVE) |
|---|
| 370 |
ip = htonl (INADDR_ANY); |
|---|
| 371 |
else |
|---|
| 372 |
ip = htonl (INADDR_LOOPBACK); |
|---|
| 373 |
} |
|---|
| 374 |
else |
|---|
| 375 |
if ((ip = inet_addr (node)) == INADDR_NONE) |
|---|
| 376 |
{ |
|---|
| 377 |
struct hostent *entry = NULL; |
|---|
| 378 |
|
|---|
| 379 |
|
|---|
| 380 |
if (!(flags & AI_NUMERICHOST)) |
|---|
| 381 |
entry = gethostbyname (node); |
|---|
| 382 |
|
|---|
| 383 |
if (entry == NULL) |
|---|
| 384 |
return gai_error_from_herrno (); |
|---|
| 385 |
|
|---|
| 386 |
if ((entry->h_length != 4) || (entry->h_addrtype != AF_INET)) |
|---|
| 387 |
return EAI_FAMILY; |
|---|
| 388 |
|
|---|
| 389 |
ip = *((u_long *) entry->h_addr); |
|---|
| 390 |
if (flags & AI_CANONNAME) |
|---|
| 391 |
name = entry->h_name; |
|---|
| 392 |
} |
|---|
| 393 |
|
|---|
| 394 |
if ((flags & AI_CANONNAME) && (name == NULL)) |
|---|
| 395 |
name = node; |
|---|
| 396 |
|
|---|
| 397 |
|
|---|
| 398 |
if (service == NULL) |
|---|
| 399 |
port = 0; |
|---|
| 400 |
else |
|---|
| 401 |
{ |
|---|
| 402 |
unsigned long d; |
|---|
| 403 |
char *end; |
|---|
| 404 |
|
|---|
| 405 |
d = strtoul (service, &end, 0); |
|---|
| 406 |
if (end[0] || (d > 65535u)) |
|---|
| 407 |
return EAI_SERVICE; |
|---|
| 408 |
|
|---|
| 409 |
port = htons ((u_short)d); |
|---|
| 410 |
} |
|---|
| 411 |
|
|---|
| 412 |
|
|---|
| 413 |
if ((!protocol) || (protocol == IPPROTO_UDP)) |
|---|
| 414 |
{ |
|---|
| 415 |
info = makeipv4info (SOCK_DGRAM, IPPROTO_UDP, ip, port, name); |
|---|
| 416 |
if (info == NULL) |
|---|
| 417 |
{ |
|---|
| 418 |
errno = ENOMEM; |
|---|
| 419 |
return EAI_SYSTEM; |
|---|
| 420 |
} |
|---|
| 421 |
if (flags & AI_PASSIVE) |
|---|
| 422 |
info->ai_flags |= AI_PASSIVE; |
|---|
| 423 |
*res = info; |
|---|
| 424 |
} |
|---|
| 425 |
if ((!protocol) || (protocol == IPPROTO_TCP)) |
|---|
| 426 |
{ |
|---|
| 427 |
info = makeipv4info (SOCK_STREAM, IPPROTO_TCP, ip, port, name); |
|---|
| 428 |
if (info == NULL) |
|---|
| 429 |
{ |
|---|
| 430 |
errno = ENOMEM; |
|---|
| 431 |
return EAI_SYSTEM; |
|---|
| 432 |
} |
|---|
| 433 |
info->ai_next = *res; |
|---|
| 434 |
if (flags & AI_PASSIVE) |
|---|
| 435 |
info->ai_flags |= AI_PASSIVE; |
|---|
| 436 |
*res = info; |
|---|
| 437 |
} |
|---|
| 438 |
|
|---|
| 439 |
return 0; |
|---|
| 440 |
} |
|---|
| 441 |
#undef getaddrinfo |
|---|
| 442 |
#define getaddrifo stub_getaddrinfo |
|---|
| 443 |
#undef freeaddrinfo |
|---|
| 444 |
#define freeaddrifo stub_freeaddrinfo |
|---|
| 445 |
#endif |
|---|
| 446 |
|
|---|
| 447 |
#if defined( WIN32 ) && !defined( UNDER_CE ) |
|---|
| 448 |
|
|---|
| 449 |
|
|---|
| 450 |
|
|---|
| 451 |
|
|---|
| 452 |
typedef int (WSAAPI * GETNAMEINFO) ( const struct sockaddr FAR *, socklen_t, |
|---|
| 453 |
char FAR *, DWORD, char FAR *, DWORD, int ); |
|---|
| 454 |
typedef int (WSAAPI * GETADDRINFO) (const char FAR *, const char FAR *, |
|---|
| 455 |
const struct addrinfo FAR *, |
|---|
| 456 |
struct addrinfo FAR * FAR *); |
|---|
| 457 |
|
|---|
| 458 |
typedef void (WSAAPI * FREEADDRINFO) ( struct addrinfo FAR * ); |
|---|
| 459 |
|
|---|
| 460 |
static int WSAAPI _ws2_getnameinfo_bind ( const struct sockaddr FAR *, socklen_t, |
|---|
| 461 |
char FAR *, DWORD, char FAR *, DWORD, int ); |
|---|
| 462 |
static int WSAAPI _ws2_getaddrinfo_bind (const char FAR *, const char FAR *, |
|---|
| 463 |
const struct addrinfo FAR *, |
|---|
| 464 |
struct addrinfo FAR * FAR *); |
|---|
| 465 |
|
|---|
| 466 |
static GETNAMEINFO ws2_getnameinfo = _ws2_getnameinfo_bind; |
|---|
| 467 |
static GETADDRINFO ws2_getaddrinfo = _ws2_getaddrinfo_bind; |
|---|
| 468 |
static FREEADDRINFO ws2_freeaddrinfo; |
|---|
| 469 |
|
|---|
| 470 |
static FARPROC ws2_find_api (LPCTSTR name) |
|---|
| 471 |
{ |
|---|
| 472 |
FARPROC f = NULL; |
|---|
| 473 |
|
|---|
| 474 |
HMODULE m = GetModuleHandle (TEXT("WS2_32")); |
|---|
| 475 |
if (m != NULL) |
|---|
| 476 |
f = GetProcAddress (m, name); |
|---|
| 477 |
|
|---|
| 478 |
if (f == NULL) |
|---|
| 479 |
{ |
|---|
| 480 |
|
|---|
| 481 |
m = LoadLibrary (TEXT("WSHIP6")); |
|---|
| 482 |
if (m != NULL) |
|---|
| 483 |
f = GetProcAddress (m, name); |
|---|
| 484 |
} |
|---|
| 485 |
|
|---|
| 486 |
return f; |
|---|
| 487 |
} |
|---|
| 488 |
|
|---|
| 489 |
static WSAAPI int _ws2_getnameinfo_bind( const struct sockaddr FAR * sa, socklen_t salen, |
|---|
| 490 |
char FAR *host, DWORD hostlen, char FAR *serv, DWORD servlen, int flags ) |
|---|
| 491 |
{ |
|---|
| 492 |
GETNAMEINFO entry = (GETNAMEINFO)ws2_find_api (TEXT("getnameinfo")); |
|---|
| 493 |
int result; |
|---|
| 494 |
|
|---|
| 495 |
if (entry == NULL) |
|---|
| 496 |
{ |
|---|
| 497 |
|
|---|
| 498 |
entry = stub_getnameinfo; |
|---|
| 499 |
} |
|---|
| 500 |
|
|---|
| 501 |
result = entry (sa, salen, host, hostlen, serv, servlen, flags); |
|---|
| 502 |
ws2_getnameinfo = entry; |
|---|
| 503 |
return result; |
|---|
| 504 |
} |
|---|
| 505 |
#undef getnameinfo |
|---|
| 506 |
#define getnameinfo ws2_getnameinfo |
|---|
| 507 |
|
|---|
| 508 |
static WSAAPI int _ws2_getaddrinfo_bind(const char FAR *node, const char FAR *service, |
|---|
| 509 |
const struct addrinfo FAR *hints, struct addrinfo FAR * FAR *res) |
|---|
| 510 |
{ |
|---|
| 511 |
GETADDRINFO entry; |
|---|
| 512 |
FREEADDRINFO freentry; |
|---|
| 513 |
int result; |
|---|
| 514 |
|
|---|
| 515 |
entry = (GETADDRINFO)ws2_find_api (TEXT("getaddrinfo")); |
|---|
| 516 |
freentry = (FREEADDRINFO)ws2_find_api (TEXT("freeaddrinfo")); |
|---|
| 517 |
|
|---|
| 518 |
if ((entry == NULL) || (freentry == NULL)) |
|---|
| 519 |
{ |
|---|
| 520 |
|
|---|
| 521 |
entry = stub_getaddrinfo; |
|---|
| 522 |
freentry = stub_freeaddrinfo; |
|---|
| 523 |
} |
|---|
| 524 |
|
|---|
| 525 |
result = entry (node, service, hints, res); |
|---|
| 526 |
ws2_freeaddrinfo = freentry; |
|---|
| 527 |
ws2_getaddrinfo = entry; |
|---|
| 528 |
return result; |
|---|
| 529 |
} |
|---|
| 530 |
#undef getaddrinfo |
|---|
| 531 |
#undef freeaddrinfo |
|---|
| 532 |
#define getaddrinfo ws2_getaddrinfo |
|---|
| 533 |
#define freeaddrinfo ws2_freeaddrinfo |
|---|
| 534 |
#define HAVE_GETADDRINFO |
|---|
| 535 |
#endif |
|---|
| 536 |
|
|---|
| 537 |
|
|---|
| 538 |
int vlc_getnameinfo( const struct sockaddr *sa, int salen, |
|---|
| 539 |
char *host, int hostlen, int *portnum, int flags ) |
|---|
| 540 |
{ |
|---|
| 541 |
char psz_servbuf[6], *psz_serv; |
|---|
| 542 |
int i_servlen, i_val; |
|---|
| 543 |
|
|---|
| 544 |
flags |= NI_NUMERICSERV; |
|---|
| 545 |
if( portnum != NULL ) |
|---|
| 546 |
{ |
|---|
| 547 |
psz_serv = psz_servbuf; |
|---|
| 548 |
i_servlen = sizeof( psz_servbuf ); |
|---|
| 549 |
} |
|---|
| 550 |
else |
|---|
| 551 |
{ |
|---|
| 552 |
psz_serv = NULL; |
|---|
| 553 |
i_servlen = 0; |
|---|
| 554 |
} |
|---|
| 555 |
|
|---|
| 556 |
i_val = getnameinfo(sa, salen, host, hostlen, psz_serv, i_servlen, flags); |
|---|
| 557 |
|
|---|
| 558 |
if( portnum != NULL ) |
|---|
| 559 |
*portnum = atoi( psz_serv ); |
|---|
| 560 |
|
|---|
| 561 |
return i_val; |
|---|
| 562 |
} |
|---|
| 563 |
|
|---|
| 564 |
|
|---|
| 565 |
int vlc_getaddrinfo( vlc_object_t *p_this, const char *node, |
|---|
| 566 |
int i_port, const struct addrinfo *p_hints, |
|---|
| 567 |
struct addrinfo **res ) |
|---|
| 568 |
{ |
|---|
| 569 |
struct addrinfo hints; |
|---|
| 570 |
char psz_buf[NI_MAXHOST], *psz_node, psz_service[6]; |
|---|
| 571 |
|
|---|
| 572 |
|
|---|
| 573 |
|
|---|
| 574 |
|
|---|
| 575 |
|
|---|
| 576 |
if( ( i_port > 65535 ) || ( i_port < 0 ) ) |
|---|
| 577 |
{ |
|---|
| 578 |
msg_Err( p_this, "invalid port number %d specified", i_port ); |
|---|
| 579 |
return EAI_SERVICE; |
|---|
| 580 |
} |
|---|
| 581 |
|
|---|
| 582 |
|
|---|
| 583 |
snprintf( psz_service, 6, "%d", i_port ); |
|---|
| 584 |
|
|---|
| 585 |
|
|---|
| 586 |
memset (&hints, 0, sizeof (hints)); |
|---|
| 587 |
if (p_hints != NULL) |
|---|
| 588 |
{ |
|---|
| 589 |
const int safe_flags = |
|---|
| 590 |
AI_PASSIVE | |
|---|
| 591 |
AI_CANONNAME | |
|---|
| 592 |
AI_NUMERICHOST | |
|---|
| 593 |
AI_NUMERICSERV | |
|---|
| 594 |
#ifdef AI_ALL |
|---|
| 595 |
AI_ALL | |
|---|
| 596 |
#endif |
|---|
| 597 |
#ifdef AI_ADDRCONFIG |
|---|
| 598 |
AI_ADDRCONFIG | |
|---|
| 599 |
#endif |
|---|
| 600 |
#ifdef AI_V4MAPPED |
|---|
| 601 |
AI_V4MAPPED | |
|---|
| 602 |
#endif |
|---|
| 603 |
0; |
|---|
| 604 |
|
|---|
| 605 |
hints.ai_family = p_hints->ai_family; |
|---|
| 606 |
hints.ai_socktype = p_hints->ai_socktype; |
|---|
| 607 |
hints.ai_protocol = p_hints->ai_protocol; |
|---|
| 608 |
|
|---|
| 609 |
|
|---|
| 610 |
|
|---|
| 611 |
|
|---|
| 612 |
hints.ai_flags = p_hints->ai_flags & safe_flags; |
|---|
| 613 |
} |
|---|
| 614 |
|
|---|
| 615 |
|
|---|
| 616 |
hints.ai_flags |= AI_NUMERICSERV; |
|---|
| 617 |
|
|---|
| 618 |
if( hints.ai_family == AF_UNSPEC ) |
|---|
| 619 |
{ |
|---|
| 620 |
#ifdef AF_INET6 |
|---|
| 621 |
if (var_CreateGetBool (p_this, "ipv6")) |
|---|
| 622 |
hints.ai_family = AF_INET6; |
|---|
| 623 |
else |
|---|
| 624 |
#endif |
|---|
| 625 |
if (var_CreateGetBool (p_this, "ipv4")) |
|---|
| 626 |
hints.ai_family = AF_INET; |
|---|
| 627 |
} |
|---|
| 628 |
|
|---|
| 629 |
|
|---|
| 630 |
|
|---|
| 631 |
|
|---|
| 632 |
|
|---|
| 633 |
|
|---|
| 634 |
if( ( node == NULL ) || (node[0] == '\0' ) ) |
|---|
| 635 |
{ |
|---|
| 636 |
psz_node = NULL; |
|---|
| 637 |
} |
|---|
| 638 |
else |
|---|
| 639 |
{ |
|---|
| 640 |
strlcpy( psz_buf, node, NI_MAXHOST ); |
|---|
| 641 |
|
|---|
| 642 |
psz_node = psz_buf; |
|---|
| 643 |
|
|---|
| 644 |
if( psz_buf[0] == '[' ) |
|---|
| 645 |
{ |
|---|
| 646 |
char *ptr; |
|---|
| 647 |
|
|---|
| 648 |
ptr = strrchr( psz_buf, ']' ); |
|---|
| 649 |
if( ( ptr != NULL ) && (ptr[1] == '\0' ) ) |
|---|
| 650 |
{ |
|---|
| 651 |
*ptr = '\0'; |
|---|
| 652 |
psz_node++; |
|---|
| 653 |
} |
|---|
| 654 |
} |
|---|
| 655 |
} |
|---|
| 656 |
|
|---|
| 657 |
#ifdef WIN32 |
|---|
| 658 |
|
|---|
| 659 |
|
|---|
| 660 |
|
|---|
| 661 |
|
|---|
| 662 |
if ((hints.ai_flags & AI_NUMERICHOST) == 0) |
|---|
| 663 |
{ |
|---|
| 664 |
hints.ai_flags |= AI_NUMERICHOST; |
|---|
| 665 |
|
|---|
| 666 |
if (getaddrinfo (psz_node, psz_service, &hints, res) == 0) |
|---|
| 667 |
return 0; |
|---|
| 668 |
|
|---|
| 669 |
hints.ai_flags &= ~AI_NUMERICHOST; |
|---|
| 670 |
} |
|---|
| 671 |
#endif |
|---|
| 672 |
#ifdef AI_IDN |
|---|
| 673 |
|
|---|
| 674 |
hints.ai_flags |= AI_IDN; |
|---|
| 675 |
int ret = getaddrinfo (psz_node, psz_service, &hints, res); |
|---|
| 676 |
if (ret != EAI_BADFLAGS) |
|---|
| 677 |
return ret; |
|---|
| 678 |
|
|---|
| 679 |
|
|---|
| 680 |
hints.ai_flags &= ~AI_IDN; |
|---|
| 681 |
#endif |
|---|
| 682 |
return getaddrinfo (psz_node, psz_service, &hints, res); |
|---|
| 683 |
} |
|---|
| 684 |
|
|---|
| 685 |
|
|---|
| 686 |
void vlc_freeaddrinfo( struct addrinfo *infos ) |
|---|
| 687 |
{ |
|---|
| 688 |
freeaddrinfo (infos); |
|---|
| 689 |
} |
|---|
| 690 |
|
|---|
| 691 |
|
|---|
| 692 |
|
|---|
| 693 |
|
|---|
| 694 |
int vlc_inet_pton (int af, const char *src, void *dst) |
|---|
| 695 |
{ |
|---|
| 696 |
#ifndef HAVE_INET_PTON |
|---|
| 697 |
|
|---|
| 698 |
|
|---|
| 699 |
struct addrinfo hints = { |
|---|
| 700 |
.ai_family = af, |
|---|
| 701 |
.ai_socktype = SOCK_DGRAM, |
|---|
| 702 |
.ai_protocol = IPPROTO_UDP, |
|---|
| 703 |
.ai_flags = AI_NUMERICHOST, |
|---|
| 704 |
}, *res; |
|---|
| 705 |
|
|---|
| 706 |
if (getaddrinfo (src, NULL, &hints, &res)) |
|---|
| 707 |
return 0; |
|---|
| 708 |
|
|---|
| 709 |
const void *data; |
|---|
| 710 |
size_t len; |
|---|
| 711 |
|
|---|
| 712 |
switch (af) |
|---|
| 713 |
{ |
|---|
| 714 |
case AF_INET: |
|---|
| 715 |
data = &((const struct sockaddr_in *)res->ai_addr)->sin_addr; |
|---|
| 716 |
len = sizeof (struct in_addr); |
|---|
| 717 |
break; |
|---|
| 718 |
#ifdef AF_INET6 |
|---|
| 719 |
case AF_INET6: |
|---|
| 720 |
data = &((const struct sockaddr_in6 *)res->ai_addr)->sin6_addr; |
|---|
| 721 |
len = sizeof (struct in6_addr); |
|---|
| 722 |
break; |
|---|
| 723 |
#endif |
|---|
| 724 |
default: |
|---|
| 725 |
freeaddrinfo (res); |
|---|
| 726 |
return -1; |
|---|
| 727 |
} |
|---|
| 728 |
memcpy (dst, data, len); |
|---|
| 729 |
freeaddrinfo (res); |
|---|
| 730 |
return 1; |
|---|
| 731 |
#else |
|---|
| 732 |
return inet_pton( af, src, dst ); |
|---|
| 733 |
#endif |
|---|
| 734 |
} |
|---|
| 735 |
|
|---|
| 736 |
|
|---|
| 737 |
|
|---|
| 738 |
|
|---|
| 739 |
const char *vlc_inet_ntop (int af, const void *src, char *dst, socklen_t cnt) |
|---|
| 740 |
{ |
|---|
| 741 |
#ifndef HAVE_INET_NTOP |
|---|
| 742 |
int ret = EAI_FAMILY; |
|---|
| 743 |
|
|---|
| 744 |
switch (af) |
|---|
| 745 |
{ |
|---|
| 746 |
#ifdef AF_INET6 |
|---|
| 747 |
case AF_INET6: |
|---|
| 748 |
{ |
|---|
| 749 |
struct sockaddr_in6 addr; |
|---|
| 750 |
memset (&addr, 0, sizeof(addr)); |
|---|
| 751 |
addr.sin6_family = AF_INET6; |
|---|
| 752 |
addr.sin6_addr = *(struct in6_addr *)src; |
|---|
| 753 |
ret = getnameinfo ((struct sockaddr *)&addr, sizeof (addr), |
|---|
| 754 |
dst, cnt, NULL, 0, NI_NUMERICHOST); |
|---|
| 755 |
} |
|---|
| 756 |
|
|---|
| 757 |
#endif |
|---|
| 758 |
case AF_INET: |
|---|
| 759 |
{ |
|---|
| 760 |
struct sockaddr_in addr; |
|---|
| 761 |
memset(&addr, 0, sizeof(addr)); |
|---|
| 762 |
addr.sin_family = AF_INET; |
|---|
| 763 |
addr.sin_addr = *(struct in_addr *)src; |
|---|
| 764 |
ret = getnameinfo ((struct sockaddr *)&addr, sizeof (addr), |
|---|
| 765 |
dst, cnt, NULL, 0, NI_NUMERICHOST); |
|---|
| 766 |
} |
|---|
| 767 |
} |
|---|
| 768 |
return (ret == 0) ? dst : NULL; |
|---|
| 769 |
#else |
|---|
| 770 |
return inet_ntop( af, src, dst, cnt ); |
|---|
| 771 |
#endif |
|---|
| 772 |
} |
|---|
| 773 |
|
|---|