aboutsummaryrefslogtreecommitdiff
path: root/vendor/luasocket/src/inet.c
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/luasocket/src/inet.c')
-rwxr-xr-xvendor/luasocket/src/inet.c537
1 files changed, 537 insertions, 0 deletions
diff --git a/vendor/luasocket/src/inet.c b/vendor/luasocket/src/inet.c
new file mode 100755
index 00000000..138c9abe
--- /dev/null
+++ b/vendor/luasocket/src/inet.c
@@ -0,0 +1,537 @@
1/*=========================================================================*\
2* Internet domain functions
3* LuaSocket toolkit
4\*=========================================================================*/
5#include "luasocket.h"
6#include "inet.h"
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12/*=========================================================================*\
13* Internal function prototypes.
14\*=========================================================================*/
15static int inet_global_toip(lua_State *L);
16static int inet_global_getaddrinfo(lua_State *L);
17static int inet_global_tohostname(lua_State *L);
18static int inet_global_getnameinfo(lua_State *L);
19static void inet_pushresolved(lua_State *L, struct hostent *hp);
20static int inet_global_gethostname(lua_State *L);
21
22/* DNS functions */
23static luaL_Reg func[] = {
24 { "toip", inet_global_toip},
25 { "getaddrinfo", inet_global_getaddrinfo},
26 { "tohostname", inet_global_tohostname},
27 { "getnameinfo", inet_global_getnameinfo},
28 { "gethostname", inet_global_gethostname},
29 { NULL, NULL}
30};
31
32/*-------------------------------------------------------------------------*\
33* Initializes module
34\*-------------------------------------------------------------------------*/
35int inet_open(lua_State *L)
36{
37 lua_pushstring(L, "dns");
38 lua_newtable(L);
39 luaL_setfuncs(L, func, 0);
40 lua_settable(L, -3);
41 return 0;
42}
43
44/*=========================================================================*\
45* Global Lua functions
46\*=========================================================================*/
47/*-------------------------------------------------------------------------*\
48* Returns all information provided by the resolver given a host name
49* or ip address
50\*-------------------------------------------------------------------------*/
51static int inet_gethost(const char *address, struct hostent **hp) {
52 struct in_addr addr;
53 if (inet_aton(address, &addr))
54 return socket_gethostbyaddr((char *) &addr, sizeof(addr), hp);
55 else
56 return socket_gethostbyname(address, hp);
57}
58
59/*-------------------------------------------------------------------------*\
60* Returns all information provided by the resolver given a host name
61* or ip address
62\*-------------------------------------------------------------------------*/
63static int inet_global_tohostname(lua_State *L) {
64 const char *address = luaL_checkstring(L, 1);
65 struct hostent *hp = NULL;
66 int err = inet_gethost(address, &hp);
67 if (err != IO_DONE) {
68 lua_pushnil(L);
69 lua_pushstring(L, socket_hoststrerror(err));
70 return 2;
71 }
72 lua_pushstring(L, hp->h_name);
73 inet_pushresolved(L, hp);
74 return 2;
75}
76
77static int inet_global_getnameinfo(lua_State *L) {
78 char hbuf[NI_MAXHOST];
79 char sbuf[NI_MAXSERV];
80 int i, ret;
81 struct addrinfo hints;
82 struct addrinfo *resolved, *iter;
83 const char *host = luaL_optstring(L, 1, NULL);
84 const char *serv = luaL_optstring(L, 2, NULL);
85
86 if (!(host || serv))
87 luaL_error(L, "host and serv cannot be both nil");
88
89 memset(&hints, 0, sizeof(hints));
90 hints.ai_socktype = SOCK_STREAM;
91 hints.ai_family = AF_UNSPEC;
92
93 ret = getaddrinfo(host, serv, &hints, &resolved);
94 if (ret != 0) {
95 lua_pushnil(L);
96 lua_pushstring(L, socket_gaistrerror(ret));
97 return 2;
98 }
99
100 lua_newtable(L);
101 for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) {
102 getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen,
103 hbuf, host? (socklen_t) sizeof(hbuf): 0,
104 sbuf, serv? (socklen_t) sizeof(sbuf): 0, 0);
105 if (host) {
106 lua_pushnumber(L, i);
107 lua_pushstring(L, hbuf);
108 lua_settable(L, -3);
109 }
110 }
111 freeaddrinfo(resolved);
112
113 if (serv) {
114 lua_pushstring(L, sbuf);
115 return 2;
116 } else {
117 return 1;
118 }
119}
120
121/*-------------------------------------------------------------------------*\
122* Returns all information provided by the resolver given a host name
123* or ip address
124\*-------------------------------------------------------------------------*/
125static int inet_global_toip(lua_State *L)
126{
127 const char *address = luaL_checkstring(L, 1);
128 struct hostent *hp = NULL;
129 int err = inet_gethost(address, &hp);
130 if (err != IO_DONE) {
131 lua_pushnil(L);
132 lua_pushstring(L, socket_hoststrerror(err));
133 return 2;
134 }
135 lua_pushstring(L, inet_ntoa(*((struct in_addr *) hp->h_addr)));
136 inet_pushresolved(L, hp);
137 return 2;
138}
139
140int inet_optfamily(lua_State* L, int narg, const char* def)
141{
142 static const char* optname[] = { "unspec", "inet", "inet6", NULL };
143 static int optvalue[] = { AF_UNSPEC, AF_INET, AF_INET6, 0 };
144
145 return optvalue[luaL_checkoption(L, narg, def, optname)];
146}
147
148int inet_optsocktype(lua_State* L, int narg, const char* def)
149{
150 static const char* optname[] = { "stream", "dgram", NULL };
151 static int optvalue[] = { SOCK_STREAM, SOCK_DGRAM, 0 };
152
153 return optvalue[luaL_checkoption(L, narg, def, optname)];
154}
155
156static int inet_global_getaddrinfo(lua_State *L)
157{
158 const char *hostname = luaL_checkstring(L, 1);
159 struct addrinfo *iterator = NULL, *resolved = NULL;
160 struct addrinfo hints;
161 int i = 1, ret = 0;
162 memset(&hints, 0, sizeof(hints));
163 hints.ai_socktype = SOCK_STREAM;
164 hints.ai_family = AF_UNSPEC;
165 ret = getaddrinfo(hostname, NULL, &hints, &resolved);
166 if (ret != 0) {
167 lua_pushnil(L);
168 lua_pushstring(L, socket_gaistrerror(ret));
169 return 2;
170 }
171 lua_newtable(L);
172 for (iterator = resolved; iterator; iterator = iterator->ai_next) {
173 char hbuf[NI_MAXHOST];
174 ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen,
175 hbuf, (socklen_t) sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
176 if (ret){
177 freeaddrinfo(resolved);
178 lua_pushnil(L);
179 lua_pushstring(L, socket_gaistrerror(ret));
180 return 2;
181 }
182 lua_pushnumber(L, i);
183 lua_newtable(L);
184 switch (iterator->ai_family) {
185 case AF_INET:
186 lua_pushliteral(L, "family");
187 lua_pushliteral(L, "inet");
188 lua_settable(L, -3);
189 break;
190 case AF_INET6:
191 lua_pushliteral(L, "family");
192 lua_pushliteral(L, "inet6");
193 lua_settable(L, -3);
194 break;
195 case AF_UNSPEC:
196 lua_pushliteral(L, "family");
197 lua_pushliteral(L, "unspec");
198 lua_settable(L, -3);
199 break;
200 default:
201 lua_pushliteral(L, "family");
202 lua_pushliteral(L, "unknown");
203 lua_settable(L, -3);
204 break;
205 }
206 lua_pushliteral(L, "addr");
207 lua_pushstring(L, hbuf);
208 lua_settable(L, -3);
209 lua_settable(L, -3);
210 i++;
211 }
212 freeaddrinfo(resolved);
213 return 1;
214}
215
216/*-------------------------------------------------------------------------*\
217* Gets the host name
218\*-------------------------------------------------------------------------*/
219static int inet_global_gethostname(lua_State *L)
220{
221 char name[257];
222 name[256] = '\0';
223 if (gethostname(name, 256) < 0) {
224 lua_pushnil(L);
225 lua_pushstring(L, socket_strerror(errno));
226 return 2;
227 } else {
228 lua_pushstring(L, name);
229 return 1;
230 }
231}
232
233/*=========================================================================*\
234* Lua methods
235\*=========================================================================*/
236/*-------------------------------------------------------------------------*\
237* Retrieves socket peer name
238\*-------------------------------------------------------------------------*/
239int inet_meth_getpeername(lua_State *L, p_socket ps, int family)
240{
241 int err;
242 struct sockaddr_storage peer;
243 socklen_t peer_len = sizeof(peer);
244 char name[INET6_ADDRSTRLEN];
245 char port[6]; /* 65535 = 5 bytes + 0 to terminate it */
246 if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) {
247 lua_pushnil(L);
248 lua_pushstring(L, socket_strerror(errno));
249 return 2;
250 }
251 err = getnameinfo((struct sockaddr *) &peer, peer_len,
252 name, INET6_ADDRSTRLEN,
253 port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
254 if (err) {
255 lua_pushnil(L);
256 lua_pushstring(L, LUA_GAI_STRERROR(err));
257 return 2;
258 }
259 lua_pushstring(L, name);
260 lua_pushinteger(L, (int) strtol(port, (char **) NULL, 10));
261 switch (family) {
262 case AF_INET: lua_pushliteral(L, "inet"); break;
263 case AF_INET6: lua_pushliteral(L, "inet6"); break;
264 case AF_UNSPEC: lua_pushliteral(L, "unspec"); break;
265 default: lua_pushliteral(L, "unknown"); break;
266 }
267 return 3;
268}
269
270/*-------------------------------------------------------------------------*\
271* Retrieves socket local name
272\*-------------------------------------------------------------------------*/
273int inet_meth_getsockname(lua_State *L, p_socket ps, int family)
274{
275 int err;
276 struct sockaddr_storage peer;
277 socklen_t peer_len = sizeof(peer);
278 char name[INET6_ADDRSTRLEN];
279 char port[6]; /* 65535 = 5 bytes + 0 to terminate it */
280 if (getsockname(*ps, (SA *) &peer, &peer_len) < 0) {
281 lua_pushnil(L);
282 lua_pushstring(L, socket_strerror(errno));
283 return 2;
284 }
285 err=getnameinfo((struct sockaddr *)&peer, peer_len,
286 name, INET6_ADDRSTRLEN, port, 6, NI_NUMERICHOST | NI_NUMERICSERV);
287 if (err) {
288 lua_pushnil(L);
289 lua_pushstring(L, LUA_GAI_STRERROR(err));
290 return 2;
291 }
292 lua_pushstring(L, name);
293 lua_pushstring(L, port);
294 switch (family) {
295 case AF_INET: lua_pushliteral(L, "inet"); break;
296 case AF_INET6: lua_pushliteral(L, "inet6"); break;
297 case AF_UNSPEC: lua_pushliteral(L, "unspec"); break;
298 default: lua_pushliteral(L, "unknown"); break;
299 }
300 return 3;
301}
302
303/*=========================================================================*\
304* Internal functions
305\*=========================================================================*/
306/*-------------------------------------------------------------------------*\
307* Passes all resolver information to Lua as a table
308\*-------------------------------------------------------------------------*/
309static void inet_pushresolved(lua_State *L, struct hostent *hp)
310{
311 char **alias;
312 struct in_addr **addr;
313 int i, resolved;
314 lua_newtable(L); resolved = lua_gettop(L);
315 lua_pushstring(L, "name");
316 lua_pushstring(L, hp->h_name);
317 lua_settable(L, resolved);
318 lua_pushstring(L, "ip");
319 lua_pushstring(L, "alias");
320 i = 1;
321 alias = hp->h_aliases;
322 lua_newtable(L);
323 if (alias) {
324 while (*alias) {
325 lua_pushnumber(L, i);
326 lua_pushstring(L, *alias);
327 lua_settable(L, -3);
328 i++; alias++;
329 }
330 }
331 lua_settable(L, resolved);
332 i = 1;
333 lua_newtable(L);
334 addr = (struct in_addr **) hp->h_addr_list;
335 if (addr) {
336 while (*addr) {
337 lua_pushnumber(L, i);
338 lua_pushstring(L, inet_ntoa(**addr));
339 lua_settable(L, -3);
340 i++; addr++;
341 }
342 }
343 lua_settable(L, resolved);
344}
345
346/*-------------------------------------------------------------------------*\
347* Tries to create a new inet socket
348\*-------------------------------------------------------------------------*/
349const char *inet_trycreate(p_socket ps, int family, int type, int protocol) {
350 const char *err = socket_strerror(socket_create(ps, family, type, protocol));
351 if (err == NULL && family == AF_INET6) {
352 int yes = 1;
353 setsockopt(*ps, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&yes, sizeof(yes));
354 }
355 return err;
356}
357
358/*-------------------------------------------------------------------------*\
359* "Disconnects" a DGRAM socket
360\*-------------------------------------------------------------------------*/
361const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm)
362{
363 switch (family) {
364 case AF_INET: {
365 struct sockaddr_in sin;
366 memset((char *) &sin, 0, sizeof(sin));
367 sin.sin_family = AF_UNSPEC;
368 sin.sin_addr.s_addr = INADDR_ANY;
369 return socket_strerror(socket_connect(ps, (SA *) &sin,
370 sizeof(sin), tm));
371 }
372 case AF_INET6: {
373 struct sockaddr_in6 sin6;
374 struct in6_addr addrany = IN6ADDR_ANY_INIT;
375 memset((char *) &sin6, 0, sizeof(sin6));
376 sin6.sin6_family = AF_UNSPEC;
377 sin6.sin6_addr = addrany;
378 return socket_strerror(socket_connect(ps, (SA *) &sin6,
379 sizeof(sin6), tm));
380 }
381 }
382 return NULL;
383}
384
385/*-------------------------------------------------------------------------*\
386* Tries to connect to remote address (address, port)
387\*-------------------------------------------------------------------------*/
388const char *inet_tryconnect(p_socket ps, int *family, const char *address,
389 const char *serv, p_timeout tm, struct addrinfo *connecthints)
390{
391 struct addrinfo *iterator = NULL, *resolved = NULL;
392 const char *err = NULL;
393 int current_family = *family;
394 /* try resolving */
395 err = socket_gaistrerror(getaddrinfo(address, serv,
396 connecthints, &resolved));
397 if (err != NULL) {
398 if (resolved) freeaddrinfo(resolved);
399 return err;
400 }
401 for (iterator = resolved; iterator; iterator = iterator->ai_next) {
402 timeout_markstart(tm);
403 /* create new socket if necessary. if there was no
404 * bind, we need to create one for every new family
405 * that shows up while iterating. if there was a
406 * bind, all families will be the same and we will
407 * not enter this branch. */
408 if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
409 socket_destroy(ps);
410 err = inet_trycreate(ps, iterator->ai_family,
411 iterator->ai_socktype, iterator->ai_protocol);
412 if (err) continue;
413 current_family = iterator->ai_family;
414 /* set non-blocking before connect */
415 socket_setnonblocking(ps);
416 }
417 /* try connecting to remote address */
418 err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr,
419 (socklen_t) iterator->ai_addrlen, tm));
420 /* if success or timeout is zero, break out of loop */
421 if (err == NULL || timeout_iszero(tm)) {
422 *family = current_family;
423 break;
424 }
425 }
426 freeaddrinfo(resolved);
427 /* here, if err is set, we failed */
428 return err;
429}
430
431/*-------------------------------------------------------------------------*\
432* Tries to accept a socket
433\*-------------------------------------------------------------------------*/
434const char *inet_tryaccept(p_socket server, int family, p_socket client,
435 p_timeout tm) {
436 socklen_t len;
437 t_sockaddr_storage addr;
438 switch (family) {
439 case AF_INET6: len = sizeof(struct sockaddr_in6); break;
440 case AF_INET: len = sizeof(struct sockaddr_in); break;
441 default: len = sizeof(addr); break;
442 }
443 return socket_strerror(socket_accept(server, client, (SA *) &addr,
444 &len, tm));
445}
446
447/*-------------------------------------------------------------------------*\
448* Tries to bind socket to (address, port)
449\*-------------------------------------------------------------------------*/
450const char *inet_trybind(p_socket ps, int *family, const char *address,
451 const char *serv, struct addrinfo *bindhints) {
452 struct addrinfo *iterator = NULL, *resolved = NULL;
453 const char *err = NULL;
454 int current_family = *family;
455 /* translate luasocket special values to C */
456 if (strcmp(address, "*") == 0) address = NULL;
457 if (!serv) serv = "0";
458 /* try resolving */
459 err = socket_gaistrerror(getaddrinfo(address, serv, bindhints, &resolved));
460 if (err) {
461 if (resolved) freeaddrinfo(resolved);
462 return err;
463 }
464 /* iterate over resolved addresses until one is good */
465 for (iterator = resolved; iterator; iterator = iterator->ai_next) {
466 if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
467 socket_destroy(ps);
468 err = inet_trycreate(ps, iterator->ai_family,
469 iterator->ai_socktype, iterator->ai_protocol);
470 if (err) continue;
471 current_family = iterator->ai_family;
472 }
473 /* try binding to local address */
474 err = socket_strerror(socket_bind(ps, (SA *) iterator->ai_addr,
475 (socklen_t) iterator->ai_addrlen));
476 /* keep trying unless bind succeeded */
477 if (err == NULL) {
478 *family = current_family;
479 /* set to non-blocking after bind */
480 socket_setnonblocking(ps);
481 break;
482 }
483 }
484 /* cleanup and return error */
485 freeaddrinfo(resolved);
486 /* here, if err is set, we failed */
487 return err;
488}
489
490/*-------------------------------------------------------------------------*\
491* Some systems do not provide these so that we provide our own.
492\*-------------------------------------------------------------------------*/
493#ifdef LUASOCKET_INET_ATON
494int inet_aton(const char *cp, struct in_addr *inp)
495{
496 unsigned int a = 0, b = 0, c = 0, d = 0;
497 int n = 0, r;
498 unsigned long int addr = 0;
499 r = sscanf(cp, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n);
500 if (r == 0 || n == 0) return 0;
501 cp += n;
502 if (*cp) return 0;
503 if (a > 255 || b > 255 || c > 255 || d > 255) return 0;
504 if (inp) {
505 addr += a; addr <<= 8;
506 addr += b; addr <<= 8;
507 addr += c; addr <<= 8;
508 addr += d;
509 inp->s_addr = htonl(addr);
510 }
511 return 1;
512}
513#endif
514
515#ifdef LUASOCKET_INET_PTON
516int inet_pton(int af, const char *src, void *dst)
517{
518 struct addrinfo hints, *res;
519 int ret = 1;
520 memset(&hints, 0, sizeof(struct addrinfo));
521 hints.ai_family = af;
522 hints.ai_flags = AI_NUMERICHOST;
523 if (getaddrinfo(src, NULL, &hints, &res) != 0) return -1;
524 if (af == AF_INET) {
525 struct sockaddr_in *in = (struct sockaddr_in *) res->ai_addr;
526 memcpy(dst, &in->sin_addr, sizeof(in->sin_addr));
527 } else if (af == AF_INET6) {
528 struct sockaddr_in6 *in = (struct sockaddr_in6 *) res->ai_addr;
529 memcpy(dst, &in->sin6_addr, sizeof(in->sin6_addr));
530 } else {
531 ret = -1;
532 }
533 freeaddrinfo(res);
534 return ret;
535}
536
537#endif