2002-03-21 14:52:38 +01:00
|
|
|
/*=========================================================================*\
|
2003-05-25 03:54:13 +02:00
|
|
|
* Internet domain functions
|
2003-03-28 22:08:50 +01:00
|
|
|
*
|
|
|
|
* RCS ID: $Id$
|
2002-03-21 14:52:38 +01:00
|
|
|
\*=========================================================================*/
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <lua.h>
|
|
|
|
#include <lauxlib.h>
|
|
|
|
|
2003-05-25 03:54:13 +02:00
|
|
|
#include "luasocket.h"
|
|
|
|
#include "inet.h"
|
2002-03-21 14:52:38 +01:00
|
|
|
|
|
|
|
/*=========================================================================*\
|
|
|
|
* Internal function prototypes.
|
|
|
|
\*=========================================================================*/
|
2003-05-25 03:54:13 +02:00
|
|
|
static int inet_global_toip(lua_State *L);
|
|
|
|
static int inet_global_tohostname(lua_State *L);
|
|
|
|
|
2002-03-21 14:52:38 +01:00
|
|
|
static void inet_pushresolved(lua_State *L, struct hostent *hp);
|
|
|
|
|
2003-05-25 03:54:13 +02:00
|
|
|
#ifdef INET_ATON
|
|
|
|
static int inet_aton(const char *cp, struct in_addr *inp);
|
2002-03-21 14:52:38 +01:00
|
|
|
#endif
|
|
|
|
|
2003-05-25 03:54:13 +02:00
|
|
|
static luaL_reg func[] = {
|
|
|
|
{ "toip", inet_global_toip },
|
|
|
|
{ "tohostname", inet_global_tohostname },
|
|
|
|
{ NULL, NULL}
|
|
|
|
};
|
|
|
|
|
2002-03-21 14:52:38 +01:00
|
|
|
/*=========================================================================*\
|
|
|
|
* Exported functions
|
|
|
|
\*=========================================================================*/
|
|
|
|
/*-------------------------------------------------------------------------*\
|
|
|
|
* Initializes module
|
|
|
|
\*-------------------------------------------------------------------------*/
|
|
|
|
void inet_open(lua_State *L)
|
|
|
|
{
|
2003-05-25 03:54:13 +02:00
|
|
|
luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
|
2002-03-21 14:52:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*=========================================================================*\
|
|
|
|
* Global Lua functions
|
|
|
|
\*=========================================================================*/
|
|
|
|
/*-------------------------------------------------------------------------*\
|
2002-07-03 21:06:55 +02:00
|
|
|
* Returns all information provided by the resolver given a host name
|
|
|
|
* or ip address
|
2002-03-21 14:52:38 +01:00
|
|
|
* Lua Input: address
|
|
|
|
* address: ip address or hostname to dns lookup
|
|
|
|
* Lua Returns
|
|
|
|
* On success: first IP address followed by a resolved table
|
|
|
|
* On error: nil, followed by an error message
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2003-05-25 03:54:13 +02:00
|
|
|
static int inet_global_toip(lua_State *L)
|
2002-03-21 14:52:38 +01:00
|
|
|
{
|
2003-05-25 03:54:13 +02:00
|
|
|
const char *address = luaL_checkstring(L, 1);
|
2002-03-21 14:52:38 +01:00
|
|
|
struct in_addr addr;
|
|
|
|
struct hostent *hp;
|
|
|
|
if (inet_aton(address, &addr))
|
|
|
|
hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
|
2003-05-25 03:54:13 +02:00
|
|
|
else
|
|
|
|
hp = gethostbyname(address);
|
2002-03-21 14:52:38 +01:00
|
|
|
if (!hp) {
|
|
|
|
lua_pushnil(L);
|
2003-05-25 03:54:13 +02:00
|
|
|
lua_pushstring(L, sock_hoststrerror());
|
2002-03-21 14:52:38 +01:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
addr = *((struct in_addr *) hp->h_addr);
|
|
|
|
lua_pushstring(L, inet_ntoa(addr));
|
|
|
|
inet_pushresolved(L, hp);
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
2002-07-03 21:06:55 +02:00
|
|
|
* Returns all information provided by the resolver given a host name
|
|
|
|
* or ip address
|
2002-03-21 14:52:38 +01:00
|
|
|
* Lua Input: address
|
|
|
|
* address: ip address or host name to reverse dns lookup
|
|
|
|
* Lua Returns
|
|
|
|
* On success: canonic name followed by a resolved table
|
|
|
|
* On error: nil, followed by an error message
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2003-05-25 03:54:13 +02:00
|
|
|
static int inet_global_tohostname(lua_State *L)
|
2002-03-21 14:52:38 +01:00
|
|
|
{
|
2003-05-25 03:54:13 +02:00
|
|
|
const char *address = luaL_checkstring(L, 1);
|
2002-03-21 14:52:38 +01:00
|
|
|
struct in_addr addr;
|
|
|
|
struct hostent *hp;
|
|
|
|
if (inet_aton(address, &addr))
|
|
|
|
hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
|
2003-05-25 03:54:13 +02:00
|
|
|
else
|
|
|
|
hp = gethostbyname(address);
|
2002-03-21 14:52:38 +01:00
|
|
|
if (!hp) {
|
|
|
|
lua_pushnil(L);
|
2003-05-25 03:54:13 +02:00
|
|
|
lua_pushstring(L, sock_hoststrerror());
|
2002-03-21 14:52:38 +01:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
lua_pushstring(L, hp->h_name);
|
|
|
|
inet_pushresolved(L, hp);
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*=========================================================================*\
|
2002-07-03 21:06:55 +02:00
|
|
|
* Lua methods
|
2002-03-21 14:52:38 +01:00
|
|
|
\*=========================================================================*/
|
|
|
|
/*-------------------------------------------------------------------------*\
|
|
|
|
* Retrieves socket peer name
|
2003-05-25 03:54:13 +02:00
|
|
|
* Input:
|
2002-03-21 14:52:38 +01:00
|
|
|
* sock: socket
|
|
|
|
* Lua Returns
|
|
|
|
* On success: ip address and port of peer
|
|
|
|
* On error: nil
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2003-05-25 03:54:13 +02:00
|
|
|
int inet_meth_getpeername(lua_State *L, p_sock ps)
|
2002-03-21 14:52:38 +01:00
|
|
|
{
|
|
|
|
struct sockaddr_in peer;
|
2003-03-28 22:08:50 +01:00
|
|
|
size_t peer_len = sizeof(peer);
|
2003-05-25 03:54:13 +02:00
|
|
|
if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) {
|
2002-03-21 14:52:38 +01:00
|
|
|
lua_pushnil(L);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
lua_pushstring(L, inet_ntoa(peer.sin_addr));
|
|
|
|
lua_pushnumber(L, ntohs(peer.sin_port));
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
|
|
|
* Retrieves socket local name
|
2003-05-25 03:54:13 +02:00
|
|
|
* Input:
|
2002-03-21 14:52:38 +01:00
|
|
|
* sock: socket
|
|
|
|
* Lua Returns
|
|
|
|
* On success: local ip address and port
|
|
|
|
* On error: nil
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2003-05-25 03:54:13 +02:00
|
|
|
int inet_meth_getsockname(lua_State *L, p_sock ps)
|
2002-03-21 14:52:38 +01:00
|
|
|
{
|
|
|
|
struct sockaddr_in local;
|
2003-03-28 22:08:50 +01:00
|
|
|
size_t local_len = sizeof(local);
|
2003-05-25 03:54:13 +02:00
|
|
|
if (getsockname(*ps, (SA *) &local, &local_len) < 0) {
|
2002-03-21 14:52:38 +01:00
|
|
|
lua_pushnil(L);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
lua_pushstring(L, inet_ntoa(local.sin_addr));
|
|
|
|
lua_pushnumber(L, ntohs(local.sin_port));
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*=========================================================================*\
|
|
|
|
* Internal functions
|
|
|
|
\*=========================================================================*/
|
|
|
|
/*-------------------------------------------------------------------------*\
|
|
|
|
* Passes all resolver information to Lua as a table
|
|
|
|
* Input
|
|
|
|
* hp: hostent structure returned by resolver
|
|
|
|
\*-------------------------------------------------------------------------*/
|
|
|
|
static void inet_pushresolved(lua_State *L, struct hostent *hp)
|
|
|
|
{
|
|
|
|
char **alias;
|
|
|
|
struct in_addr **addr;
|
|
|
|
int i, resolved;
|
|
|
|
lua_newtable(L); resolved = lua_gettop(L);
|
|
|
|
lua_pushstring(L, "name");
|
|
|
|
lua_pushstring(L, hp->h_name);
|
|
|
|
lua_settable(L, resolved);
|
|
|
|
lua_pushstring(L, "ip");
|
|
|
|
lua_pushstring(L, "alias");
|
|
|
|
i = 1;
|
|
|
|
alias = hp->h_aliases;
|
|
|
|
lua_newtable(L);
|
|
|
|
while (*alias) {
|
|
|
|
lua_pushnumber(L, i);
|
|
|
|
lua_pushstring(L, *alias);
|
|
|
|
lua_settable(L, -3);
|
|
|
|
i++; alias++;
|
|
|
|
}
|
|
|
|
lua_settable(L, resolved);
|
|
|
|
i = 1;
|
|
|
|
lua_newtable(L);
|
|
|
|
addr = (struct in_addr **) hp->h_addr_list;
|
|
|
|
while (*addr) {
|
|
|
|
lua_pushnumber(L, i);
|
|
|
|
lua_pushstring(L, inet_ntoa(**addr));
|
|
|
|
lua_settable(L, -3);
|
|
|
|
i++; addr++;
|
|
|
|
}
|
|
|
|
lua_settable(L, resolved);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
2003-05-25 03:54:13 +02:00
|
|
|
* Tries to connect to remote address (address, port)
|
2002-03-21 14:52:38 +01:00
|
|
|
* Input
|
2003-05-25 03:54:13 +02:00
|
|
|
* ps: pointer to socket
|
2002-03-21 14:52:38 +01:00
|
|
|
* address: host name or ip address
|
|
|
|
* port: port number to bind to
|
|
|
|
* Returns
|
|
|
|
* NULL in case of success, error message otherwise
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2003-05-25 03:54:13 +02:00
|
|
|
const char *inet_tryconnect(p_sock ps, const char *address, ushort port)
|
2002-03-21 14:52:38 +01:00
|
|
|
{
|
|
|
|
struct sockaddr_in remote;
|
|
|
|
memset(&remote, 0, sizeof(remote));
|
2002-07-03 21:06:55 +02:00
|
|
|
remote.sin_family = AF_INET;
|
|
|
|
remote.sin_port = htons(port);
|
2003-05-25 03:54:13 +02:00
|
|
|
if (strcmp(address, "*")) {
|
|
|
|
if (!strlen(address) || !inet_aton(address, &remote.sin_addr)) {
|
|
|
|
struct hostent *hp = gethostbyname(address);
|
|
|
|
struct in_addr **addr;
|
|
|
|
remote.sin_family = AF_INET;
|
|
|
|
if (!hp) return sock_hoststrerror();
|
|
|
|
addr = (struct in_addr **) hp->h_addr_list;
|
|
|
|
memcpy(&remote.sin_addr, *addr, sizeof(struct in_addr));
|
|
|
|
}
|
|
|
|
} else remote.sin_family = AF_UNSPEC;
|
|
|
|
sock_setblocking(ps);
|
|
|
|
const char *err = sock_connect(ps, (SA *) &remote, sizeof(remote));
|
|
|
|
if (err) {
|
|
|
|
sock_destroy(ps);
|
|
|
|
*ps = SOCK_INVALID;
|
2002-07-03 21:06:55 +02:00
|
|
|
return err;
|
2003-05-25 03:54:13 +02:00
|
|
|
} else {
|
|
|
|
sock_setnonblocking(ps);
|
|
|
|
return NULL;
|
|
|
|
}
|
2002-03-21 14:52:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
2003-05-25 03:54:13 +02:00
|
|
|
* Tries to bind socket to (address, port)
|
2002-03-21 14:52:38 +01:00
|
|
|
* Input
|
2003-05-25 03:54:13 +02:00
|
|
|
* sock: pointer to socket
|
2002-03-21 14:52:38 +01:00
|
|
|
* address: host name or ip address
|
|
|
|
* port: port number to bind to
|
|
|
|
* Returns
|
|
|
|
* NULL in case of success, error message otherwise
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2003-05-25 03:54:13 +02:00
|
|
|
const char *inet_trybind(p_sock ps, const char *address, ushort port,
|
|
|
|
int backlog)
|
2002-03-21 14:52:38 +01:00
|
|
|
{
|
|
|
|
struct sockaddr_in local;
|
|
|
|
memset(&local, 0, sizeof(local));
|
|
|
|
/* address is either wildcard or a valid ip address */
|
|
|
|
local.sin_addr.s_addr = htonl(INADDR_ANY);
|
2002-07-03 21:06:55 +02:00
|
|
|
local.sin_port = htons(port);
|
|
|
|
local.sin_family = AF_INET;
|
|
|
|
if (strcmp(address, "*") &&
|
|
|
|
(!strlen(address) || !inet_aton(address, &local.sin_addr))) {
|
2002-03-21 14:52:38 +01:00
|
|
|
struct hostent *hp = gethostbyname(address);
|
|
|
|
struct in_addr **addr;
|
2003-05-25 03:54:13 +02:00
|
|
|
if (!hp) return sock_hoststrerror();
|
2002-03-21 14:52:38 +01:00
|
|
|
addr = (struct in_addr **) hp->h_addr_list;
|
2002-07-03 21:06:55 +02:00
|
|
|
memcpy(&local.sin_addr, *addr, sizeof(struct in_addr));
|
|
|
|
}
|
2003-05-25 03:54:13 +02:00
|
|
|
sock_setblocking(ps);
|
|
|
|
const char *err = sock_bind(ps, (SA *) &local, sizeof(local));
|
|
|
|
if (err) {
|
|
|
|
sock_destroy(ps);
|
|
|
|
*ps = SOCK_INVALID;
|
2002-07-03 21:06:55 +02:00
|
|
|
return err;
|
2003-05-25 03:54:13 +02:00
|
|
|
} else {
|
|
|
|
sock_setnonblocking(ps);
|
|
|
|
if (backlog > 0) sock_listen(ps, backlog);
|
|
|
|
return NULL;
|
2002-03-21 14:52:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
|
|
|
* Tries to create a new inet socket
|
|
|
|
* Input
|
2003-05-25 03:54:13 +02:00
|
|
|
* sock: pointer to socket
|
2002-03-21 14:52:38 +01:00
|
|
|
* Returns
|
|
|
|
* NULL if successfull, error message on error
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2003-05-25 03:54:13 +02:00
|
|
|
const char *inet_trycreate(p_sock ps, int type)
|
2002-03-21 14:52:38 +01:00
|
|
|
{
|
2003-05-25 03:54:13 +02:00
|
|
|
return sock_create(ps, AF_INET, type, 0);
|
2002-03-21 14:52:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
|
|
|
* Some systems do not provide this so that we provide our own. It's not
|
|
|
|
* marvelously fast, but it works just fine.
|
|
|
|
\*-------------------------------------------------------------------------*/
|
|
|
|
#ifdef COMPAT_INETATON
|
|
|
|
static int inet_aton(const char *cp, struct in_addr *inp)
|
|
|
|
{
|
|
|
|
unsigned int a = 0, b = 0, c = 0, d = 0;
|
|
|
|
int n = 0, r;
|
|
|
|
unsigned long int addr = 0;
|
|
|
|
r = sscanf(cp, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n);
|
|
|
|
if (r == 0 || n == 0) return 0;
|
|
|
|
cp += n;
|
|
|
|
if (*cp) return 0;
|
|
|
|
if (a > 255 || b > 255 || c > 255 || d > 255) return 0;
|
|
|
|
if (inp) {
|
|
|
|
addr += a; addr <<= 8;
|
|
|
|
addr += b; addr <<= 8;
|
|
|
|
addr += c; addr <<= 8;
|
|
|
|
addr += d;
|
|
|
|
inp->s_addr = htonl(addr);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|