1 /*=========================================================================*\
2 * Internet domain functions
4 \*=========================================================================*/
13 #if defined(__MINGW32__)
14 const char *inet_ntop(int af
, const void *src
, char *dst
, socklen_t cnt
)
18 struct sockaddr_in in
;
19 memset(&in
, 0, sizeof(in
));
20 in
.sin_family
= AF_INET
;
21 memcpy(&in
.sin_addr
, src
, sizeof(struct in_addr
));
22 getnameinfo((struct sockaddr
*)&in
, sizeof(struct
23 sockaddr_in
), dst
, cnt
, NULL
, 0, NI_NUMERICHOST
);
26 else if (af
== AF_INET6
)
28 struct sockaddr_in6 in
;
29 memset(&in
, 0, sizeof(in
));
30 in
.sin6_family
= AF_INET6
;
31 memcpy(&in
.sin6_addr
, src
, sizeof(struct in_addr6
));
32 getnameinfo((struct sockaddr
*)&in
, sizeof(struct
33 sockaddr_in6
), dst
, cnt
, NULL
, 0, NI_NUMERICHOST
);
39 int inet_pton(int af
, const char *src
, void *dst
)
41 struct addrinfo hints
, *res
, *ressave
;
43 memset(&hints
, 0, sizeof(struct addrinfo
));
46 if (getaddrinfo(src
, NULL
, &hints
, &res
) != 0)
55 memcpy(dst
, res
->ai_addr
, res
->ai_addrlen
);
59 freeaddrinfo(ressave
);
66 /*=========================================================================*\
67 * Internal function prototypes.
68 \*=========================================================================*/
69 static int inet_global_toip(lua_State
*L
);
70 static int inet_global_getaddrinfo(lua_State
*L
);
71 static int inet_global_tohostname(lua_State
*L
);
72 static int inet_global_getnameinfo(lua_State
*L
);
73 static void inet_pushresolved(lua_State
*L
, struct hostent
*hp
);
74 static int inet_global_gethostname(lua_State
*L
);
77 static luaL_Reg func
[] = {
78 { "toip", inet_global_toip
},
79 { "getaddrinfo", inet_global_getaddrinfo
},
80 { "tohostname", inet_global_tohostname
},
81 { "getnameinfo", inet_global_getnameinfo
},
82 { "gethostname", inet_global_gethostname
},
86 /*=========================================================================*\
88 \*=========================================================================*/
89 /*-------------------------------------------------------------------------*\
91 \*-------------------------------------------------------------------------*/
92 int inet_open(lua_State
*L
)
94 lua_pushstring(L
, "dns");
96 luaL_openlib(L
, NULL
, func
, 0);
101 /*=========================================================================*\
102 * Global Lua functions
103 \*=========================================================================*/
104 /*-------------------------------------------------------------------------*\
105 * Returns all information provided by the resolver given a host name
107 \*-------------------------------------------------------------------------*/
108 static int inet_gethost(const char *address
, struct hostent
**hp
) {
110 if (inet_aton(address
, &addr
))
111 return socket_gethostbyaddr((char *) &addr
, sizeof(addr
), hp
);
113 return socket_gethostbyname(address
, hp
);
116 /*-------------------------------------------------------------------------*\
117 * Returns all information provided by the resolver given a host name
119 \*-------------------------------------------------------------------------*/
120 static int inet_global_tohostname(lua_State
*L
) {
121 const char *address
= luaL_checkstring(L
, 1);
122 struct hostent
*hp
= NULL
;
123 int err
= inet_gethost(address
, &hp
);
124 if (err
!= IO_DONE
) {
126 lua_pushstring(L
, socket_hoststrerror(err
));
129 lua_pushstring(L
, hp
->h_name
);
130 inet_pushresolved(L
, hp
);
134 static int inet_global_getnameinfo(lua_State
*L
) {
138 struct addrinfo hints
;
139 struct addrinfo
*resolved
, *iter
;
140 const char *node
= luaL_optstring(L
, 1, NULL
);
141 const char *service
= luaL_optstring(L
, 2, NULL
);
143 if (!(node
|| service
))
144 luaL_error(L
, "You have to specify a hostname, a service, or both");
146 memset(&hints
, 0, sizeof(hints
));
147 hints
.ai_socktype
= SOCK_STREAM
;
148 hints
.ai_family
= PF_UNSPEC
;
150 /* getaddrinfo must get a node and a service argument */
151 ret
= getaddrinfo(node
? node
: "127.0.0.1", service
? service
: "7",
155 lua_pushstring(L
, socket_gaistrerror(ret
));
160 for (i
= 1, iter
= resolved
; iter
; i
++, iter
= iter
->ai_next
) {
161 getnameinfo(iter
->ai_addr
, (socklen_t
) iter
->ai_addrlen
, host
,
162 node
? (socklen_t
) sizeof(host
) : 0, serv
, service
? (socklen_t
) sizeof(serv
) : 0, 0);
165 lua_pushnumber(L
, i
);
166 lua_pushstring(L
, host
);
170 freeaddrinfo(resolved
);
173 lua_pushstring(L
, serv
);
180 /*-------------------------------------------------------------------------*\
181 * Returns all information provided by the resolver given a host name
183 \*-------------------------------------------------------------------------*/
184 static int inet_global_toip(lua_State
*L
)
186 const char *address
= luaL_checkstring(L
, 1);
187 struct hostent
*hp
= NULL
;
188 int err
= inet_gethost(address
, &hp
);
189 if (err
!= IO_DONE
) {
191 lua_pushstring(L
, socket_hoststrerror(err
));
194 lua_pushstring(L
, inet_ntoa(*((struct in_addr
*) hp
->h_addr
)));
195 inet_pushresolved(L
, hp
);
199 int inet_optfamily(lua_State
* L
, int narg
, const char* def
)
201 static const char* optname
[] = { "unspec", "inet", "inet6", NULL
};
202 static int optvalue
[] = { PF_UNSPEC
, PF_INET
, PF_INET6
, 0 };
204 return optvalue
[luaL_checkoption(L
, narg
, def
, optname
)];
207 int inet_optsocktype(lua_State
* L
, int narg
, const char* def
)
209 static const char* optname
[] = { "stream", "dgram", NULL
};
210 static int optvalue
[] = { SOCK_STREAM
, SOCK_DGRAM
, 0 };
212 return optvalue
[luaL_checkoption(L
, narg
, def
, optname
)];
215 static int inet_global_getaddrinfo(lua_State
*L
)
217 const char *hostname
= luaL_checkstring(L
, 1);
218 struct addrinfo
*iterator
= NULL
, *resolved
= NULL
;
219 struct addrinfo hints
;
221 memset(&hints
, 0, sizeof(hints
));
222 hints
.ai_socktype
= SOCK_STREAM
;
223 hints
.ai_family
= PF_UNSPEC
;
224 ret
= getaddrinfo(hostname
, NULL
, &hints
, &resolved
);
227 lua_pushstring(L
, socket_gaistrerror(ret
));
231 for (iterator
= resolved
; iterator
; iterator
= iterator
->ai_next
) {
232 char hbuf
[NI_MAXHOST
], sbuf
[NI_MAXSERV
];
233 getnameinfo(iterator
->ai_addr
, (socklen_t
) iterator
->ai_addrlen
, hbuf
,
234 (socklen_t
) sizeof(hbuf
), sbuf
, 0, NI_NUMERICHOST
);
235 lua_pushnumber(L
, i
);
237 switch (iterator
->ai_family
) {
239 lua_pushliteral(L
, "family");
240 lua_pushliteral(L
, "inet");
244 lua_pushliteral(L
, "family");
245 lua_pushliteral(L
, "inet6");
249 lua_pushliteral(L
, "addr");
250 lua_pushstring(L
, hbuf
);
255 freeaddrinfo(resolved
);
260 /*-------------------------------------------------------------------------*\
262 \*-------------------------------------------------------------------------*/
263 static int inet_global_gethostname(lua_State
*L
)
267 if (gethostname(name
, 256) < 0) {
269 lua_pushstring(L
, socket_strerror(errno
));
272 lua_pushstring(L
, name
);
279 /*=========================================================================*\
281 \*=========================================================================*/
282 /*-------------------------------------------------------------------------*\
283 * Retrieves socket peer name
284 \*-------------------------------------------------------------------------*/
285 int inet_meth_getpeername(lua_State
*L
, p_socket ps
, int family
)
289 struct sockaddr_in peer
;
290 socklen_t peer_len
= sizeof(peer
);
291 char name
[INET_ADDRSTRLEN
];
292 if (getpeername(*ps
, (SA
*) &peer
, &peer_len
) < 0) {
294 lua_pushstring(L
, socket_strerror(errno
));
297 inet_ntop(family
, &peer
.sin_addr
, name
, sizeof(name
));
298 lua_pushstring(L
, name
);
299 lua_pushnumber(L
, ntohs(peer
.sin_port
));
300 lua_pushliteral(L
, "inet");
305 struct sockaddr_in6 peer
;
306 socklen_t peer_len
= sizeof(peer
);
307 char name
[INET6_ADDRSTRLEN
];
308 if (getpeername(*ps
, (SA
*) &peer
, &peer_len
) < 0) {
310 lua_pushstring(L
, socket_strerror(errno
));
313 inet_ntop(family
, &peer
.sin6_addr
, name
, sizeof(name
));
314 lua_pushstring(L
, name
);
315 lua_pushnumber(L
, ntohs(peer
.sin6_port
));
316 lua_pushliteral(L
, "inet6");
322 lua_pushfstring(L
, "unknown family %d", family
);
327 /*-------------------------------------------------------------------------*\
328 * Retrieves socket local name
329 \*-------------------------------------------------------------------------*/
330 int inet_meth_getsockname(lua_State
*L
, p_socket ps
, int family
)
334 struct sockaddr_in local
;
335 socklen_t local_len
= sizeof(local
);
336 char name
[INET_ADDRSTRLEN
];
337 if (getsockname(*ps
, (SA
*) &local
, &local_len
) < 0) {
339 lua_pushstring(L
, socket_strerror(errno
));
342 inet_ntop(family
, &local
.sin_addr
, name
, sizeof(name
));
343 lua_pushstring(L
, name
);
344 lua_pushnumber(L
, ntohs(local
.sin_port
));
345 lua_pushliteral(L
, "inet");
350 struct sockaddr_in6 local
;
351 socklen_t local_len
= sizeof(local
);
352 char name
[INET6_ADDRSTRLEN
];
353 if (getsockname(*ps
, (SA
*) &local
, &local_len
) < 0) {
355 lua_pushstring(L
, socket_strerror(errno
));
358 inet_ntop(family
, &local
.sin6_addr
, name
, sizeof(name
));
359 lua_pushstring(L
, name
);
360 lua_pushnumber(L
, ntohs(local
.sin6_port
));
361 lua_pushliteral(L
, "inet6");
367 lua_pushfstring(L
, "unknown family %d", family
);
372 /*=========================================================================*\
374 \*=========================================================================*/
375 /*-------------------------------------------------------------------------*\
376 * Passes all resolver information to Lua as a table
377 \*-------------------------------------------------------------------------*/
378 static void inet_pushresolved(lua_State
*L
, struct hostent
*hp
)
381 struct in_addr
**addr
;
383 lua_newtable(L
); resolved
= lua_gettop(L
);
384 lua_pushstring(L
, "name");
385 lua_pushstring(L
, hp
->h_name
);
386 lua_settable(L
, resolved
);
387 lua_pushstring(L
, "ip");
388 lua_pushstring(L
, "alias");
390 alias
= hp
->h_aliases
;
394 lua_pushnumber(L
, i
);
395 lua_pushstring(L
, *alias
);
400 lua_settable(L
, resolved
);
403 addr
= (struct in_addr
**) hp
->h_addr_list
;
406 lua_pushnumber(L
, i
);
407 lua_pushstring(L
, inet_ntoa(**addr
));
412 lua_settable(L
, resolved
);
415 /*-------------------------------------------------------------------------*\
416 * Tries to create a new inet socket
417 \*-------------------------------------------------------------------------*/
418 const char *inet_trycreate(p_socket ps
, int family
, int type
) {
419 return socket_strerror(socket_create(ps
, family
, type
, 0));
422 /*-------------------------------------------------------------------------*\
423 * "Disconnects" a DGRAM socket
424 \*-------------------------------------------------------------------------*/
425 const char *inet_trydisconnect(p_socket ps
, int family
, p_timeout tm
)
429 struct sockaddr_in sin
;
430 memset((char *) &sin
, 0, sizeof(sin
));
431 sin
.sin_family
= AF_UNSPEC
;
432 sin
.sin_addr
.s_addr
= INADDR_ANY
;
433 return socket_strerror(socket_connect(ps
, (SA
*) &sin
,
437 struct sockaddr_in6 sin6
;
438 struct in6_addr addrany
= IN6ADDR_ANY_INIT
;
439 memset((char *) &sin6
, 0, sizeof(sin6
));
440 sin6
.sin6_family
= AF_UNSPEC
;
441 fprintf(stderr
, "disconnecting\n");
442 sin6
.sin6_addr
= addrany
;
443 return socket_strerror(socket_connect(ps
, (SA
*) &sin6
,
450 /*-------------------------------------------------------------------------*\
451 * Tries to connect to remote address (address, port)
452 \*-------------------------------------------------------------------------*/
453 const char *inet_tryconnect(p_socket ps
, const char *address
,
454 const char *serv
, p_timeout tm
, struct addrinfo
*connecthints
)
456 struct addrinfo
*iterator
= NULL
, *resolved
= NULL
;
457 const char *err
= NULL
;
459 err
= socket_gaistrerror(getaddrinfo(address
, serv
,
460 connecthints
, &resolved
));
462 if (resolved
) freeaddrinfo(resolved
);
465 for (iterator
= resolved
; iterator
; iterator
= iterator
->ai_next
) {
466 timeout_markstart(tm
);
467 /* try connecting to remote address */
468 err
= socket_strerror(socket_connect(ps
, (SA
*) iterator
->ai_addr
,
469 (socklen_t
) iterator
->ai_addrlen
, tm
));
470 /* if success, break out of loop */
471 if (err
== NULL
) break;
473 freeaddrinfo(resolved
);
474 /* here, if err is set, we failed */
478 /*-------------------------------------------------------------------------*\
479 * Tries to accept a socket
480 \*-------------------------------------------------------------------------*/
481 const char *inet_tryaccept(p_socket server
, int family
, p_socket client
, p_timeout tm
)
484 t_sockaddr_storage addr
;
485 if (family
== PF_INET6
) {
486 len
= sizeof(struct sockaddr_in6
);
488 len
= sizeof(struct sockaddr_in
);
490 return socket_strerror(socket_accept(server
, client
, (SA
*) &addr
, &len
, tm
));
493 /*-------------------------------------------------------------------------*\
494 * Tries to bind socket to (address, port)
495 \*-------------------------------------------------------------------------*/
496 const char *inet_trybind(p_socket ps
, const char *address
, const char *serv
,
497 struct addrinfo
*bindhints
)
499 struct addrinfo
*iterator
= NULL
, *resolved
= NULL
;
500 const char *err
= NULL
;
503 err
= socket_gaistrerror(getaddrinfo(address
, serv
, bindhints
, &resolved
));
505 if (resolved
) freeaddrinfo(resolved
);
508 /* iterate over resolved addresses until one is good */
509 for (iterator
= resolved
; iterator
; iterator
= iterator
->ai_next
) {
510 if(sock
== SOCKET_INVALID
) {
511 err
= socket_strerror(socket_create(&sock
, iterator
->ai_family
,
512 iterator
->ai_socktype
, iterator
->ai_protocol
));
516 /* try binding to local address */
517 err
= socket_strerror(socket_bind(&sock
,
518 (SA
*) iterator
->ai_addr
,
519 (socklen_t
) iterator
->ai_addrlen
));
521 /* keep trying unless bind succeeded */
524 socket_destroy(&sock
);
526 /* remember what we connected to, particularly the family */
527 *bindhints
= *iterator
;
531 /* cleanup and return error */
532 freeaddrinfo(resolved
);
537 /*-------------------------------------------------------------------------*\
538 * Some systems do not provide this so that we provide our own. It's not
539 * marvelously fast, but it works just fine.
540 \*-------------------------------------------------------------------------*/
542 int inet_aton(const char *cp
, struct in_addr
*inp
)
544 unsigned int a
= 0, b
= 0, c
= 0, d
= 0;
546 unsigned long int addr
= 0;
547 r
= sscanf(cp
, "%u.%u.%u.%u%n", &a
, &b
, &c
, &d
, &n
);
548 if (r
== 0 || n
== 0) return 0;
551 if (a
> 255 || b
> 255 || c
> 255 || d
> 255) return 0;
553 addr
+= a
; addr
<<= 8;
554 addr
+= b
; addr
<<= 8;
555 addr
+= c
; addr
<<= 8;
557 inp
->s_addr
= htonl(addr
);