aboutsummaryrefslogtreecommitdiff
path: root/src/inet.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/inet.c')
-rw-r--r--src/inet.c145
1 files changed, 77 insertions, 68 deletions
diff --git a/src/inet.c b/src/inet.c
index 68087db..331b800 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -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)
146int inet_optfamily(lua_State* L, int narg, const char* def) 146int 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}
@@ -344,8 +352,13 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp)
344/*-------------------------------------------------------------------------*\ 352/*-------------------------------------------------------------------------*\
345* Tries to create a new inet socket 353* Tries to create a new inet socket
346\*-------------------------------------------------------------------------*/ 354\*-------------------------------------------------------------------------*/
347const char *inet_trycreate(p_socket ps, int family, int type) { 355const char *inet_trycreate(p_socket ps, int family, int type, int protocol) {
348 return socket_strerror(socket_create(ps, family, type, 0)); 356 const char *err = socket_strerror(socket_create(ps, family, type, protocol));
357 if (err == NULL && family == AF_INET6) {
358 int yes = 1;
359 setsockopt(*ps, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&yes, sizeof(yes));
360 }
361 return err;
349} 362}
350 363
351/*-------------------------------------------------------------------------*\ 364/*-------------------------------------------------------------------------*\
@@ -354,21 +367,21 @@ const char *inet_trycreate(p_socket ps, int family, int type) {
354const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm) 367const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm)
355{ 368{
356 switch (family) { 369 switch (family) {
357 case PF_INET: { 370 case AF_INET: {
358 struct sockaddr_in sin; 371 struct sockaddr_in sin;
359 memset((char *) &sin, 0, sizeof(sin)); 372 memset((char *) &sin, 0, sizeof(sin));
360 sin.sin_family = AF_UNSPEC; 373 sin.sin_family = AF_UNSPEC;
361 sin.sin_addr.s_addr = INADDR_ANY; 374 sin.sin_addr.s_addr = INADDR_ANY;
362 return socket_strerror(socket_connect(ps, (SA *) &sin, 375 return socket_strerror(socket_connect(ps, (SA *) &sin,
363 sizeof(sin), tm)); 376 sizeof(sin), tm));
364 } 377 }
365 case PF_INET6: { 378 case AF_INET6: {
366 struct sockaddr_in6 sin6; 379 struct sockaddr_in6 sin6;
367 struct in6_addr addrany = IN6ADDR_ANY_INIT; 380 struct in6_addr addrany = IN6ADDR_ANY_INIT;
368 memset((char *) &sin6, 0, sizeof(sin6)); 381 memset((char *) &sin6, 0, sizeof(sin6));
369 sin6.sin6_family = AF_UNSPEC; 382 sin6.sin6_family = AF_UNSPEC;
370 sin6.sin6_addr = addrany; 383 sin6.sin6_addr = addrany;
371 return socket_strerror(socket_connect(ps, (SA *) &sin6, 384 return socket_strerror(socket_connect(ps, (SA *) &sin6,
372 sizeof(sin6), tm)); 385 sizeof(sin6), tm));
373 } 386 }
374 } 387 }
@@ -383,6 +396,7 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address,
383{ 396{
384 struct addrinfo *iterator = NULL, *resolved = NULL; 397 struct addrinfo *iterator = NULL, *resolved = NULL;
385 const char *err = NULL; 398 const char *err = NULL;
399 int current_family = *family;
386 /* try resolving */ 400 /* try resolving */
387 err = socket_gaistrerror(getaddrinfo(address, serv, 401 err = socket_gaistrerror(getaddrinfo(address, serv,
388 connecthints, &resolved)); 402 connecthints, &resolved));
@@ -397,23 +411,23 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address,
397 * that shows up while iterating. if there was a 411 * that shows up while iterating. if there was a
398 * bind, all families will be the same and we will 412 * bind, all families will be the same and we will
399 * not enter this branch. */ 413 * not enter this branch. */
400 if (*family != iterator->ai_family) { 414 if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
401 socket_destroy(ps); 415 socket_destroy(ps);
402 err = socket_strerror(socket_create(ps, iterator->ai_family, 416 err = inet_trycreate(ps, iterator->ai_family,
403 iterator->ai_socktype, iterator->ai_protocol)); 417 iterator->ai_socktype, iterator->ai_protocol);
404 if (err != NULL) { 418 if (err) continue;
405 freeaddrinfo(resolved); 419 current_family = iterator->ai_family;
406 return err; 420 /* set non-blocking before connect */
407 }
408 *family = iterator->ai_family;
409 /* all sockets initially non-blocking */
410 socket_setnonblocking(ps); 421 socket_setnonblocking(ps);
411 } 422 }
412 /* try connecting to remote address */ 423 /* try connecting to remote address */
413 err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr, 424 err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr,
414 (socklen_t) iterator->ai_addrlen, tm)); 425 (socklen_t) iterator->ai_addrlen, tm));
415 /* if success, break out of loop */ 426 /* if success, break out of loop */
416 if (err == NULL) break; 427 if (err == NULL) {
428 *family = current_family;
429 break;
430 }
417 } 431 }
418 freeaddrinfo(resolved); 432 freeaddrinfo(resolved);
419 /* here, if err is set, we failed */ 433 /* here, if err is set, we failed */
@@ -423,29 +437,27 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address,
423/*-------------------------------------------------------------------------*\ 437/*-------------------------------------------------------------------------*\
424* Tries to accept a socket 438* Tries to accept a socket
425\*-------------------------------------------------------------------------*/ 439\*-------------------------------------------------------------------------*/
426const char *inet_tryaccept(p_socket server, int family, p_socket client, 440const char *inet_tryaccept(p_socket server, int family, p_socket client,
427 p_timeout tm) 441 p_timeout tm) {
428{
429 socklen_t len; 442 socklen_t len;
430 t_sockaddr_storage addr; 443 t_sockaddr_storage addr;
431 if (family == PF_INET6) { 444 switch (family) {
432 len = sizeof(struct sockaddr_in6); 445 case AF_INET6: len = sizeof(struct sockaddr_in6); break;
433 } else { 446 case AF_INET: len = sizeof(struct sockaddr_in); break;
434 len = sizeof(struct sockaddr_in); 447 default: len = sizeof(addr); break;
435 } 448 }
436 return socket_strerror(socket_accept(server, client, (SA *) &addr, 449 return socket_strerror(socket_accept(server, client, (SA *) &addr,
437 &len, tm)); 450 &len, tm));
438} 451}
439 452
440/*-------------------------------------------------------------------------*\ 453/*-------------------------------------------------------------------------*\
441* Tries to bind socket to (address, port) 454* Tries to bind socket to (address, port)
442\*-------------------------------------------------------------------------*/ 455\*-------------------------------------------------------------------------*/
443const char *inet_trybind(p_socket ps, const char *address, const char *serv, 456const char *inet_trybind(p_socket ps, int *family, const char *address,
444 struct addrinfo *bindhints) 457 const char *serv, struct addrinfo *bindhints) {
445{
446 struct addrinfo *iterator = NULL, *resolved = NULL; 458 struct addrinfo *iterator = NULL, *resolved = NULL;
447 const char *err = NULL; 459 const char *err = NULL;
448 t_socket sock = *ps; 460 int current_family = *family;
449 /* translate luasocket special values to C */ 461 /* translate luasocket special values to C */
450 if (strcmp(address, "*") == 0) address = NULL; 462 if (strcmp(address, "*") == 0) address = NULL;
451 if (!serv) serv = "0"; 463 if (!serv) serv = "0";
@@ -457,35 +469,32 @@ const char *inet_trybind(p_socket ps, const char *address, const char *serv,
457 } 469 }
458 /* iterate over resolved addresses until one is good */ 470 /* iterate over resolved addresses until one is good */
459 for (iterator = resolved; iterator; iterator = iterator->ai_next) { 471 for (iterator = resolved; iterator; iterator = iterator->ai_next) {
460 if(sock == SOCKET_INVALID) { 472 if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
461 err = socket_strerror(socket_create(&sock, iterator->ai_family, 473 socket_destroy(ps);
462 iterator->ai_socktype, iterator->ai_protocol)); 474 err = inet_trycreate(ps, iterator->ai_family,
463 if(err) 475 iterator->ai_socktype, iterator->ai_protocol);
464 continue; 476 if (err) continue;
477 current_family = iterator->ai_family;
465 } 478 }
466 /* try binding to local address */ 479 /* try binding to local address */
467 err = socket_strerror(socket_bind(&sock, 480 err = socket_strerror(socket_bind(ps, (SA *) iterator->ai_addr,
468 (SA *) iterator->ai_addr,
469 (socklen_t) iterator->ai_addrlen)); 481 (socklen_t) iterator->ai_addrlen));
470
471 /* keep trying unless bind succeeded */ 482 /* keep trying unless bind succeeded */
472 if (err) { 483 if (err == NULL) {
473 if(sock != *ps) 484 *family = current_family;
474 socket_destroy(&sock); 485 /* set to non-blocking after bind */
475 } else { 486 socket_setnonblocking(ps);
476 /* remember what we connected to, particularly the family */
477 *bindhints = *iterator;
478 break; 487 break;
479 } 488 }
480 } 489 }
481 /* cleanup and return error */ 490 /* cleanup and return error */
482 freeaddrinfo(resolved); 491 freeaddrinfo(resolved);
483 *ps = sock; 492 /* here, if err is set, we failed */
484 return err; 493 return err;
485} 494}
486 495
487/*-------------------------------------------------------------------------*\ 496/*-------------------------------------------------------------------------*\
488* Some systems do not provide these so that we provide our own. 497* Some systems do not provide these so that we provide our own.
489\*-------------------------------------------------------------------------*/ 498\*-------------------------------------------------------------------------*/
490#ifdef LUASOCKET_INET_ATON 499#ifdef LUASOCKET_INET_ATON
491int inet_aton(const char *cp, struct in_addr *inp) 500int inet_aton(const char *cp, struct in_addr *inp)
@@ -510,7 +519,7 @@ int inet_aton(const char *cp, struct in_addr *inp)
510#endif 519#endif
511 520
512#ifdef LUASOCKET_INET_PTON 521#ifdef LUASOCKET_INET_PTON
513int inet_pton(int af, const char *src, void *dst) 522int inet_pton(int af, const char *src, void *dst)
514{ 523{
515 struct addrinfo hints, *res; 524 struct addrinfo hints, *res;
516 int ret = 1; 525 int ret = 1;
@@ -527,7 +536,7 @@ int inet_pton(int af, const char *src, void *dst)
527 } else { 536 } else {
528 ret = -1; 537 ret = -1;
529 } 538 }
530 freeaddrinfo(res); 539 freeaddrinfo(res);
531 return ret; 540 return ret;
532} 541}
533 542