diff options
Diffstat (limited to 'src/inet.c')
-rw-r--r-- | src/inet.c | 132 |
1 files changed, 68 insertions, 64 deletions
@@ -94,7 +94,7 @@ static int inet_global_getnameinfo(lua_State *L) { | |||
94 | 94 | ||
95 | memset(&hints, 0, sizeof(hints)); | 95 | memset(&hints, 0, sizeof(hints)); |
96 | hints.ai_socktype = SOCK_STREAM; | 96 | hints.ai_socktype = SOCK_STREAM; |
97 | hints.ai_family = PF_UNSPEC; | 97 | hints.ai_family = AF_UNSPEC; |
98 | 98 | ||
99 | ret = getaddrinfo(host, serv, &hints, &resolved); | 99 | ret = getaddrinfo(host, serv, &hints, &resolved); |
100 | if (ret != 0) { | 100 | if (ret != 0) { |
@@ -105,8 +105,8 @@ static int inet_global_getnameinfo(lua_State *L) { | |||
105 | 105 | ||
106 | lua_newtable(L); | 106 | lua_newtable(L); |
107 | for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) { | 107 | for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) { |
108 | getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen, | 108 | getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen, |
109 | hbuf, host? (socklen_t) sizeof(hbuf): 0, | 109 | hbuf, host? (socklen_t) sizeof(hbuf): 0, |
110 | sbuf, serv? (socklen_t) sizeof(sbuf): 0, 0); | 110 | sbuf, serv? (socklen_t) sizeof(sbuf): 0, 0); |
111 | if (host) { | 111 | if (host) { |
112 | lua_pushnumber(L, i); | 112 | lua_pushnumber(L, i); |
@@ -146,7 +146,7 @@ static int inet_global_toip(lua_State *L) | |||
146 | int inet_optfamily(lua_State* L, int narg, const char* def) | 146 | int inet_optfamily(lua_State* L, int narg, const char* def) |
147 | { | 147 | { |
148 | static const char* optname[] = { "unspec", "inet", "inet6", NULL }; | 148 | static const char* optname[] = { "unspec", "inet", "inet6", NULL }; |
149 | static int optvalue[] = { PF_UNSPEC, PF_INET, PF_INET6, 0 }; | 149 | static int optvalue[] = { AF_UNSPEC, AF_INET, AF_INET6, 0 }; |
150 | 150 | ||
151 | return optvalue[luaL_checkoption(L, narg, def, optname)]; | 151 | return optvalue[luaL_checkoption(L, narg, def, optname)]; |
152 | } | 152 | } |
@@ -167,7 +167,7 @@ static int inet_global_getaddrinfo(lua_State *L) | |||
167 | int i = 1, ret = 0; | 167 | int i = 1, ret = 0; |
168 | memset(&hints, 0, sizeof(hints)); | 168 | memset(&hints, 0, sizeof(hints)); |
169 | hints.ai_socktype = SOCK_STREAM; | 169 | hints.ai_socktype = SOCK_STREAM; |
170 | hints.ai_family = PF_UNSPEC; | 170 | hints.ai_family = AF_UNSPEC; |
171 | ret = getaddrinfo(hostname, NULL, &hints, &resolved); | 171 | ret = getaddrinfo(hostname, NULL, &hints, &resolved); |
172 | if (ret != 0) { | 172 | if (ret != 0) { |
173 | lua_pushnil(L); | 173 | lua_pushnil(L); |
@@ -177,7 +177,7 @@ static int inet_global_getaddrinfo(lua_State *L) | |||
177 | lua_newtable(L); | 177 | lua_newtable(L); |
178 | for (iterator = resolved; iterator; iterator = iterator->ai_next) { | 178 | for (iterator = resolved; iterator; iterator = iterator->ai_next) { |
179 | char hbuf[NI_MAXHOST]; | 179 | char hbuf[NI_MAXHOST]; |
180 | ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen, | 180 | ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen, |
181 | hbuf, (socklen_t) sizeof(hbuf), NULL, 0, NI_NUMERICHOST); | 181 | hbuf, (socklen_t) sizeof(hbuf), NULL, 0, NI_NUMERICHOST); |
182 | if (ret){ | 182 | if (ret){ |
183 | freeaddrinfo(resolved); | 183 | freeaddrinfo(resolved); |
@@ -198,6 +198,16 @@ static int inet_global_getaddrinfo(lua_State *L) | |||
198 | lua_pushliteral(L, "inet6"); | 198 | lua_pushliteral(L, "inet6"); |
199 | lua_settable(L, -3); | 199 | lua_settable(L, -3); |
200 | break; | 200 | break; |
201 | case AF_UNSPEC: | ||
202 | lua_pushliteral(L, "family"); | ||
203 | lua_pushliteral(L, "unspec"); | ||
204 | lua_settable(L, -3); | ||
205 | break; | ||
206 | default: | ||
207 | lua_pushliteral(L, "family"); | ||
208 | lua_pushliteral(L, "unknown"); | ||
209 | lua_settable(L, -3); | ||
210 | break; | ||
201 | } | 211 | } |
202 | lua_pushliteral(L, "addr"); | 212 | lua_pushliteral(L, "addr"); |
203 | lua_pushstring(L, hbuf); | 213 | lua_pushstring(L, hbuf); |
@@ -254,12 +264,11 @@ int inet_meth_getpeername(lua_State *L, p_socket ps, int family) | |||
254 | } | 264 | } |
255 | lua_pushstring(L, name); | 265 | lua_pushstring(L, name); |
256 | lua_pushinteger(L, (int) strtol(port, (char **) NULL, 10)); | 266 | lua_pushinteger(L, (int) strtol(port, (char **) NULL, 10)); |
257 | if (family == PF_INET) { | 267 | switch (family) { |
258 | lua_pushliteral(L, "inet"); | 268 | case AF_INET: lua_pushliteral(L, "inet"); break; |
259 | } else if (family == PF_INET6) { | 269 | case AF_INET6: lua_pushliteral(L, "inet6"); break; |
260 | lua_pushliteral(L, "inet6"); | 270 | case AF_UNSPEC: lua_pushliteral(L, "unspec"); break; |
261 | } else { | 271 | default: lua_pushliteral(L, "unknown"); break; |
262 | lua_pushliteral(L, "uknown family"); | ||
263 | } | 272 | } |
264 | return 3; | 273 | return 3; |
265 | } | 274 | } |
@@ -279,7 +288,7 @@ int inet_meth_getsockname(lua_State *L, p_socket ps, int family) | |||
279 | lua_pushstring(L, socket_strerror(errno)); | 288 | lua_pushstring(L, socket_strerror(errno)); |
280 | return 2; | 289 | return 2; |
281 | } | 290 | } |
282 | err=getnameinfo((struct sockaddr *)&peer, peer_len, | 291 | err=getnameinfo((struct sockaddr *)&peer, peer_len, |
283 | name, INET6_ADDRSTRLEN, port, 6, NI_NUMERICHOST | NI_NUMERICSERV); | 292 | name, INET6_ADDRSTRLEN, port, 6, NI_NUMERICHOST | NI_NUMERICSERV); |
284 | if (err) { | 293 | if (err) { |
285 | lua_pushnil(L); | 294 | lua_pushnil(L); |
@@ -288,12 +297,11 @@ int inet_meth_getsockname(lua_State *L, p_socket ps, int family) | |||
288 | } | 297 | } |
289 | lua_pushstring(L, name); | 298 | lua_pushstring(L, name); |
290 | lua_pushstring(L, port); | 299 | lua_pushstring(L, port); |
291 | if (family == PF_INET) { | 300 | switch (family) { |
292 | lua_pushliteral(L, "inet"); | 301 | case AF_INET: lua_pushliteral(L, "inet"); break; |
293 | } else if (family == PF_INET6) { | 302 | case AF_INET6: lua_pushliteral(L, "inet6"); break; |
294 | lua_pushliteral(L, "inet6"); | 303 | case AF_UNSPEC: lua_pushliteral(L, "unspec"); break; |
295 | } else { | 304 | default: lua_pushliteral(L, "unknown"); break; |
296 | lua_pushliteral(L, "uknown family"); | ||
297 | } | 305 | } |
298 | return 3; | 306 | return 3; |
299 | } | 307 | } |
@@ -354,21 +362,21 @@ const char *inet_trycreate(p_socket ps, int family, int type) { | |||
354 | const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm) | 362 | const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm) |
355 | { | 363 | { |
356 | switch (family) { | 364 | switch (family) { |
357 | case PF_INET: { | 365 | case AF_INET: { |
358 | struct sockaddr_in sin; | 366 | struct sockaddr_in sin; |
359 | memset((char *) &sin, 0, sizeof(sin)); | 367 | memset((char *) &sin, 0, sizeof(sin)); |
360 | sin.sin_family = AF_UNSPEC; | 368 | sin.sin_family = AF_UNSPEC; |
361 | sin.sin_addr.s_addr = INADDR_ANY; | 369 | sin.sin_addr.s_addr = INADDR_ANY; |
362 | return socket_strerror(socket_connect(ps, (SA *) &sin, | 370 | return socket_strerror(socket_connect(ps, (SA *) &sin, |
363 | sizeof(sin), tm)); | 371 | sizeof(sin), tm)); |
364 | } | 372 | } |
365 | case PF_INET6: { | 373 | case AF_INET6: { |
366 | struct sockaddr_in6 sin6; | 374 | struct sockaddr_in6 sin6; |
367 | struct in6_addr addrany = IN6ADDR_ANY_INIT; | 375 | struct in6_addr addrany = IN6ADDR_ANY_INIT; |
368 | memset((char *) &sin6, 0, sizeof(sin6)); | 376 | memset((char *) &sin6, 0, sizeof(sin6)); |
369 | sin6.sin6_family = AF_UNSPEC; | 377 | sin6.sin6_family = AF_UNSPEC; |
370 | sin6.sin6_addr = addrany; | 378 | sin6.sin6_addr = addrany; |
371 | return socket_strerror(socket_connect(ps, (SA *) &sin6, | 379 | return socket_strerror(socket_connect(ps, (SA *) &sin6, |
372 | sizeof(sin6), tm)); | 380 | sizeof(sin6), tm)); |
373 | } | 381 | } |
374 | } | 382 | } |
@@ -383,6 +391,7 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address, | |||
383 | { | 391 | { |
384 | struct addrinfo *iterator = NULL, *resolved = NULL; | 392 | struct addrinfo *iterator = NULL, *resolved = NULL; |
385 | const char *err = NULL; | 393 | const char *err = NULL; |
394 | int current_family = *family; | ||
386 | /* try resolving */ | 395 | /* try resolving */ |
387 | err = socket_gaistrerror(getaddrinfo(address, serv, | 396 | err = socket_gaistrerror(getaddrinfo(address, serv, |
388 | connecthints, &resolved)); | 397 | connecthints, &resolved)); |
@@ -397,23 +406,23 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address, | |||
397 | * that shows up while iterating. if there was a | 406 | * that shows up while iterating. if there was a |
398 | * bind, all families will be the same and we will | 407 | * bind, all families will be the same and we will |
399 | * not enter this branch. */ | 408 | * not enter this branch. */ |
400 | if (*family != iterator->ai_family) { | 409 | if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) { |
401 | socket_destroy(ps); | 410 | socket_destroy(ps); |
402 | err = socket_strerror(socket_create(ps, iterator->ai_family, | 411 | err = socket_strerror(socket_create(ps, iterator->ai_family, |
403 | iterator->ai_socktype, iterator->ai_protocol)); | 412 | iterator->ai_socktype, iterator->ai_protocol)); |
404 | if (err != NULL) { | 413 | if (err) continue; |
405 | freeaddrinfo(resolved); | 414 | current_family = iterator->ai_family; |
406 | return err; | 415 | /* set non-blocking before connect */ |
407 | } | ||
408 | *family = iterator->ai_family; | ||
409 | /* all sockets initially non-blocking */ | ||
410 | socket_setnonblocking(ps); | 416 | socket_setnonblocking(ps); |
411 | } | 417 | } |
412 | /* try connecting to remote address */ | 418 | /* try connecting to remote address */ |
413 | err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr, | 419 | err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr, |
414 | (socklen_t) iterator->ai_addrlen, tm)); | 420 | (socklen_t) iterator->ai_addrlen, tm)); |
415 | /* if success, break out of loop */ | 421 | /* if success, break out of loop */ |
416 | if (err == NULL) break; | 422 | if (err == NULL) { |
423 | *family = current_family; | ||
424 | break; | ||
425 | } | ||
417 | } | 426 | } |
418 | freeaddrinfo(resolved); | 427 | freeaddrinfo(resolved); |
419 | /* here, if err is set, we failed */ | 428 | /* here, if err is set, we failed */ |
@@ -423,29 +432,27 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address, | |||
423 | /*-------------------------------------------------------------------------*\ | 432 | /*-------------------------------------------------------------------------*\ |
424 | * Tries to accept a socket | 433 | * Tries to accept a socket |
425 | \*-------------------------------------------------------------------------*/ | 434 | \*-------------------------------------------------------------------------*/ |
426 | const char *inet_tryaccept(p_socket server, int family, p_socket client, | 435 | const char *inet_tryaccept(p_socket server, int family, p_socket client, |
427 | p_timeout tm) | 436 | p_timeout tm) { |
428 | { | ||
429 | socklen_t len; | 437 | socklen_t len; |
430 | t_sockaddr_storage addr; | 438 | t_sockaddr_storage addr; |
431 | if (family == PF_INET6) { | 439 | switch (family) { |
432 | len = sizeof(struct sockaddr_in6); | 440 | case AF_INET6: len = sizeof(struct sockaddr_in6); break; |
433 | } else { | 441 | case AF_INET: len = sizeof(struct sockaddr_in); break; |
434 | len = sizeof(struct sockaddr_in); | 442 | default: len = sizeof(addr); break; |
435 | } | 443 | } |
436 | return socket_strerror(socket_accept(server, client, (SA *) &addr, | 444 | return socket_strerror(socket_accept(server, client, (SA *) &addr, |
437 | &len, tm)); | 445 | &len, tm)); |
438 | } | 446 | } |
439 | 447 | ||
440 | /*-------------------------------------------------------------------------*\ | 448 | /*-------------------------------------------------------------------------*\ |
441 | * Tries to bind socket to (address, port) | 449 | * Tries to bind socket to (address, port) |
442 | \*-------------------------------------------------------------------------*/ | 450 | \*-------------------------------------------------------------------------*/ |
443 | const char *inet_trybind(p_socket ps, const char *address, const char *serv, | 451 | const char *inet_trybind(p_socket ps, int *family, const char *address, |
444 | struct addrinfo *bindhints) | 452 | const char *serv, struct addrinfo *bindhints) { |
445 | { | ||
446 | struct addrinfo *iterator = NULL, *resolved = NULL; | 453 | struct addrinfo *iterator = NULL, *resolved = NULL; |
447 | const char *err = NULL; | 454 | const char *err = NULL; |
448 | t_socket sock = *ps; | 455 | int current_family = *family; |
449 | /* translate luasocket special values to C */ | 456 | /* translate luasocket special values to C */ |
450 | if (strcmp(address, "*") == 0) address = NULL; | 457 | if (strcmp(address, "*") == 0) address = NULL; |
451 | if (!serv) serv = "0"; | 458 | if (!serv) serv = "0"; |
@@ -457,35 +464,32 @@ const char *inet_trybind(p_socket ps, const char *address, const char *serv, | |||
457 | } | 464 | } |
458 | /* iterate over resolved addresses until one is good */ | 465 | /* iterate over resolved addresses until one is good */ |
459 | for (iterator = resolved; iterator; iterator = iterator->ai_next) { | 466 | for (iterator = resolved; iterator; iterator = iterator->ai_next) { |
460 | if(sock == SOCKET_INVALID) { | 467 | if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) { |
461 | err = socket_strerror(socket_create(&sock, iterator->ai_family, | 468 | socket_destroy(ps); |
469 | err = socket_strerror(socket_create(ps, iterator->ai_family, | ||
462 | iterator->ai_socktype, iterator->ai_protocol)); | 470 | iterator->ai_socktype, iterator->ai_protocol)); |
463 | if(err) | 471 | if (err) continue; |
464 | continue; | 472 | current_family = iterator->ai_family; |
465 | } | 473 | } |
466 | /* try binding to local address */ | 474 | /* try binding to local address */ |
467 | err = socket_strerror(socket_bind(&sock, | 475 | err = socket_strerror(socket_bind(ps, (SA *) iterator->ai_addr, |
468 | (SA *) iterator->ai_addr, | ||
469 | (socklen_t) iterator->ai_addrlen)); | 476 | (socklen_t) iterator->ai_addrlen)); |
470 | |||
471 | /* keep trying unless bind succeeded */ | 477 | /* keep trying unless bind succeeded */ |
472 | if (err) { | 478 | if (err == NULL) { |
473 | if(sock != *ps) | 479 | *family = current_family; |
474 | socket_destroy(&sock); | 480 | /* set to non-blocking after bind */ |
475 | } else { | 481 | socket_setnonblocking(ps); |
476 | /* remember what we connected to, particularly the family */ | ||
477 | *bindhints = *iterator; | ||
478 | break; | 482 | break; |
479 | } | 483 | } |
480 | } | 484 | } |
481 | /* cleanup and return error */ | 485 | /* cleanup and return error */ |
482 | freeaddrinfo(resolved); | 486 | freeaddrinfo(resolved); |
483 | *ps = sock; | 487 | /* here, if err is set, we failed */ |
484 | return err; | 488 | return err; |
485 | } | 489 | } |
486 | 490 | ||
487 | /*-------------------------------------------------------------------------*\ | 491 | /*-------------------------------------------------------------------------*\ |
488 | * Some systems do not provide these so that we provide our own. | 492 | * Some systems do not provide these so that we provide our own. |
489 | \*-------------------------------------------------------------------------*/ | 493 | \*-------------------------------------------------------------------------*/ |
490 | #ifdef LUASOCKET_INET_ATON | 494 | #ifdef LUASOCKET_INET_ATON |
491 | int inet_aton(const char *cp, struct in_addr *inp) | 495 | int inet_aton(const char *cp, struct in_addr *inp) |
@@ -510,7 +514,7 @@ int inet_aton(const char *cp, struct in_addr *inp) | |||
510 | #endif | 514 | #endif |
511 | 515 | ||
512 | #ifdef LUASOCKET_INET_PTON | 516 | #ifdef LUASOCKET_INET_PTON |
513 | int inet_pton(int af, const char *src, void *dst) | 517 | int inet_pton(int af, const char *src, void *dst) |
514 | { | 518 | { |
515 | struct addrinfo hints, *res; | 519 | struct addrinfo hints, *res; |
516 | int ret = 1; | 520 | int ret = 1; |
@@ -527,7 +531,7 @@ int inet_pton(int af, const char *src, void *dst) | |||
527 | } else { | 531 | } else { |
528 | ret = -1; | 532 | ret = -1; |
529 | } | 533 | } |
530 | freeaddrinfo(res); | 534 | freeaddrinfo(res); |
531 | return ret; | 535 | return ret; |
532 | } | 536 | } |
533 | 537 | ||