aboutsummaryrefslogtreecommitdiff
path: root/src/inet.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/inet.c')
-rw-r--r--src/inet.c132
1 files changed, 68 insertions, 64 deletions
diff --git a/src/inet.c b/src/inet.c
index 68087db..8f0fac2 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}
@@ -354,21 +362,21 @@ const char *inet_trycreate(p_socket ps, int family, int type) {
354const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm) 362const 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\*-------------------------------------------------------------------------*/
426const char *inet_tryaccept(p_socket server, int family, p_socket client, 435const 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\*-------------------------------------------------------------------------*/
443const char *inet_trybind(p_socket ps, const char *address, const char *serv, 451const 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
491int inet_aton(const char *cp, struct in_addr *inp) 495int 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
513int inet_pton(int af, const char *src, void *dst) 517int 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