aboutsummaryrefslogtreecommitdiff
path: root/src/inet.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/inet.c')
-rw-r--r--src/inet.c116
1 files changed, 91 insertions, 25 deletions
diff --git a/src/inet.c b/src/inet.c
index 69d32e6..fe9769b 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -79,24 +79,22 @@ static int inet_global_tohostname(lua_State *L) {
79} 79}
80 80
81static int inet_global_getnameinfo(lua_State *L) { 81static int inet_global_getnameinfo(lua_State *L) {
82 char hbuf[NI_MAXHOST];
83 char sbuf[NI_MAXSERV];
82 int i, ret; 84 int i, ret;
83 char host[1024];
84 char serv[32];
85 struct addrinfo hints; 85 struct addrinfo hints;
86 struct addrinfo *resolved, *iter; 86 struct addrinfo *resolved, *iter;
87 const char *node = luaL_optstring(L, 1, NULL); 87 const char *host = luaL_optstring(L, 1, NULL);
88 const char *service = luaL_optstring(L, 2, NULL); 88 const char *serv = luaL_optstring(L, 2, NULL);
89 89
90 if (!(node || service)) 90 if (!(host || serv))
91 luaL_error(L, "You have to specify a hostname, a service, or both"); 91 luaL_error(L, "host and serv cannot be both nil");
92 92
93 memset(&hints, 0, sizeof(hints)); 93 memset(&hints, 0, sizeof(hints));
94 hints.ai_socktype = SOCK_STREAM; 94 hints.ai_socktype = SOCK_STREAM;
95 hints.ai_family = PF_UNSPEC; 95 hints.ai_family = PF_UNSPEC;
96 96
97 /* getaddrinfo must get a node and a service argument */ 97 ret = getaddrinfo(host, serv, &hints, &resolved);
98 ret = getaddrinfo(node ? node : "127.0.0.1", service ? service : "7",
99 &hints, &resolved);
100 if (ret != 0) { 98 if (ret != 0) {
101 lua_pushnil(L); 99 lua_pushnil(L);
102 lua_pushstring(L, socket_gaistrerror(ret)); 100 lua_pushstring(L, socket_gaistrerror(ret));
@@ -105,19 +103,19 @@ static int inet_global_getnameinfo(lua_State *L) {
105 103
106 lua_newtable(L); 104 lua_newtable(L);
107 for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) { 105 for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) {
108 getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen, host, 106 getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen,
109 node ? (socklen_t) sizeof(host) : 0, serv, service ? (socklen_t) sizeof(serv) : 0, 0); 107 hbuf, host? (socklen_t) sizeof(hbuf): 0,
110 108 sbuf, serv? (socklen_t) sizeof(sbuf): 0, 0);
111 if (node) { 109 if (host) {
112 lua_pushnumber(L, i); 110 lua_pushnumber(L, i);
113 lua_pushstring(L, host); 111 lua_pushstring(L, hbuf);
114 lua_settable(L, -3); 112 lua_settable(L, -3);
115 } 113 }
116 } 114 }
117 freeaddrinfo(resolved); 115 freeaddrinfo(resolved);
118 116
119 if (service) { 117 if (serv) {
120 lua_pushstring(L, serv); 118 lua_pushstring(L, sbuf);
121 return 2; 119 return 2;
122 } else { 120 } else {
123 return 1; 121 return 1;
@@ -176,9 +174,14 @@ static int inet_global_getaddrinfo(lua_State *L)
176 } 174 }
177 lua_newtable(L); 175 lua_newtable(L);
178 for (iterator = resolved; iterator; iterator = iterator->ai_next) { 176 for (iterator = resolved; iterator; iterator = iterator->ai_next) {
179 char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; 177 char hbuf[NI_MAXHOST];
180 getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen, hbuf, 178 ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen,
181 (socklen_t) sizeof(hbuf), sbuf, 0, NI_NUMERICHOST); 179 hbuf, (socklen_t) sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
180 if (ret){
181 lua_pushnil(L);
182 lua_pushstring(L, socket_gaistrerror(ret));
183 return 2;
184 }
182 lua_pushnumber(L, i); 185 lua_pushnumber(L, i);
183 lua_newtable(L); 186 lua_newtable(L);
184 switch (iterator->ai_family) { 187 switch (iterator->ai_family) {
@@ -203,7 +206,6 @@ static int inet_global_getaddrinfo(lua_State *L)
203 return 1; 206 return 1;
204} 207}
205 208
206
207/*-------------------------------------------------------------------------*\ 209/*-------------------------------------------------------------------------*\
208* Gets the host name 210* Gets the host name
209\*-------------------------------------------------------------------------*/ 211\*-------------------------------------------------------------------------*/
@@ -222,7 +224,6 @@ static int inet_global_gethostname(lua_State *L)
222} 224}
223 225
224 226
225
226/*=========================================================================*\ 227/*=========================================================================*\
227* Lua methods 228* Lua methods
228\*=========================================================================*/ 229\*=========================================================================*/
@@ -385,7 +386,6 @@ const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm)
385 struct in6_addr addrany = IN6ADDR_ANY_INIT; 386 struct in6_addr addrany = IN6ADDR_ANY_INIT;
386 memset((char *) &sin6, 0, sizeof(sin6)); 387 memset((char *) &sin6, 0, sizeof(sin6));
387 sin6.sin6_family = AF_UNSPEC; 388 sin6.sin6_family = AF_UNSPEC;
388fprintf(stderr, "disconnecting\n");
389 sin6.sin6_addr = addrany; 389 sin6.sin6_addr = addrany;
390 return socket_strerror(socket_connect(ps, (SA *) &sin6, 390 return socket_strerror(socket_connect(ps, (SA *) &sin6,
391 sizeof(sin6), tm)); 391 sizeof(sin6), tm));
@@ -397,7 +397,7 @@ fprintf(stderr, "disconnecting\n");
397/*-------------------------------------------------------------------------*\ 397/*-------------------------------------------------------------------------*\
398* Tries to connect to remote address (address, port) 398* Tries to connect to remote address (address, port)
399\*-------------------------------------------------------------------------*/ 399\*-------------------------------------------------------------------------*/
400const char *inet_tryconnect(p_socket ps, const char *address, 400const char *inet_tryconnect(p_socket ps, int *family, const char *address,
401 const char *serv, p_timeout tm, struct addrinfo *connecthints) 401 const char *serv, p_timeout tm, struct addrinfo *connecthints)
402{ 402{
403 struct addrinfo *iterator = NULL, *resolved = NULL; 403 struct addrinfo *iterator = NULL, *resolved = NULL;
@@ -411,6 +411,23 @@ const char *inet_tryconnect(p_socket ps, const char *address,
411 } 411 }
412 for (iterator = resolved; iterator; iterator = iterator->ai_next) { 412 for (iterator = resolved; iterator; iterator = iterator->ai_next) {
413 timeout_markstart(tm); 413 timeout_markstart(tm);
414 /* create new socket if necessary. if there was no
415 * bind, we need to create one for every new family
416 * that shows up while iterating. if there was a
417 * bind, all families will be the same and we will
418 * not enter this branch. */
419 if (*family != iterator->ai_family) {
420 socket_destroy(ps);
421 err = socket_strerror(socket_create(ps, iterator->ai_family,
422 iterator->ai_socktype, iterator->ai_protocol));
423 if (err != NULL) {
424 freeaddrinfo(resolved);
425 return err;
426 }
427 *family = iterator->ai_family;
428 /* all sockets initially non-blocking */
429 socket_setnonblocking(ps);
430 }
414 /* try connecting to remote address */ 431 /* try connecting to remote address */
415 err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr, 432 err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr,
416 (socklen_t) iterator->ai_addrlen, tm)); 433 (socklen_t) iterator->ai_addrlen, tm));
@@ -425,7 +442,8 @@ const char *inet_tryconnect(p_socket ps, const char *address,
425/*-------------------------------------------------------------------------*\ 442/*-------------------------------------------------------------------------*\
426* Tries to accept a socket 443* Tries to accept a socket
427\*-------------------------------------------------------------------------*/ 444\*-------------------------------------------------------------------------*/
428const char *inet_tryaccept(p_socket server, int family, p_socket client, p_timeout tm) 445const char *inet_tryaccept(p_socket server, int family, p_socket client,
446 p_timeout tm)
429{ 447{
430 socklen_t len; 448 socklen_t len;
431 t_sockaddr_storage addr; 449 t_sockaddr_storage addr;
@@ -446,6 +464,9 @@ const char *inet_trybind(p_socket ps, const char *address, const char *serv,
446 struct addrinfo *iterator = NULL, *resolved = NULL; 464 struct addrinfo *iterator = NULL, *resolved = NULL;
447 const char *err = NULL; 465 const char *err = NULL;
448 t_socket sock = *ps; 466 t_socket sock = *ps;
467 /* translate luasocket special values to C */
468 if (strcmp(address, "*") == 0) address = NULL;
469 if (!serv) serv = "0";
449 /* try resolving */ 470 /* try resolving */
450 err = socket_gaistrerror(getaddrinfo(address, serv, bindhints, &resolved)); 471 err = socket_gaistrerror(getaddrinfo(address, serv, bindhints, &resolved));
451 if (err) { 472 if (err) {
@@ -485,7 +506,7 @@ const char *inet_trybind(p_socket ps, const char *address, const char *serv,
485* Some systems do not provide this so that we provide our own. It's not 506* Some systems do not provide this so that we provide our own. It's not
486* marvelously fast, but it works just fine. 507* marvelously fast, but it works just fine.
487\*-------------------------------------------------------------------------*/ 508\*-------------------------------------------------------------------------*/
488#ifdef INET_ATON 509#ifdef LUASOCKET_INET_ATON
489int inet_aton(const char *cp, struct in_addr *inp) 510int inet_aton(const char *cp, struct in_addr *inp)
490{ 511{
491 unsigned int a = 0, b = 0, c = 0, d = 0; 512 unsigned int a = 0, b = 0, c = 0, d = 0;
@@ -507,4 +528,49 @@ int inet_aton(const char *cp, struct in_addr *inp)
507} 528}
508#endif 529#endif
509 530
531/*-------------------------------------------------------------------------*\
532* inet_ntop/inet_pton for MinGW from
533* http://mingw-users.1079350.n2.nabble.com/IPv6-getaddrinfo-amp-inet-ntop-td5891996.html
534\*-------------------------------------------------------------------------*/
535
536#ifdef LUASOCKET_INET_PTON
537const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
538{
539 if (af == AF_INET) {
540 struct sockaddr_in in;
541 memset(&in, 0, sizeof(in));
542 in.sin_family = AF_INET;
543 memcpy(&in.sin_addr, src, sizeof(struct in_addr));
544 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in),
545 dst, cnt, NULL, 0, NI_NUMERICHOST);
546 return dst;
547 } else if (af == AF_INET6) {
548 struct sockaddr_in6 in;
549 memset(&in, 0, sizeof(in));
550 in.sin6_family = AF_INET6;
551 memcpy(&in.sin6_addr, src, sizeof(struct in_addr6));
552 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6),
553 dst, cnt, NULL, 0, NI_NUMERICHOST);
554 return dst;
555 }
556 return NULL;
557}
558
559int inet_pton(int af, const char *src, void *dst)
560{
561 struct addrinfo hints, *res, *ressave;
562 memset(&hints, 0, sizeof(struct addrinfo));
563 hints.ai_family = af;
564 if (getaddrinfo(src, NULL, &hints, &res) != 0) {
565 return -1;
566 }
567 ressave = res;
568 while (res) {
569 memcpy(dst, res->ai_addr, res->ai_addrlen);
570 res = res->ai_next;
571 }
572 freeaddrinfo(ressave);
573 return 0;
574}
510 575
576#endif