luasocket/src/inet.c

282 lines
9.4 KiB
C
Raw Normal View History

2002-03-21 14:52:38 +01:00
/*=========================================================================*\
2003-05-25 03:54:13 +02:00
* Internet domain functions
* LuaSocket toolkit
2003-03-28 22:08:50 +01:00
*
* RCS ID: $Id$
2002-03-21 14:52:38 +01:00
\*=========================================================================*/
#include <stdio.h>
2002-03-21 14:52:38 +01:00
#include <string.h>
2005-09-29 08:11:42 +02:00
#include "lua.h"
#include "lauxlib.h"
2002-03-21 14:52:38 +01:00
2003-05-25 03:54:13 +02:00
#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);
static int inet_global_gethostname(lua_State *L);
2002-03-21 14:52:38 +01:00
/* DNS functions */
2003-05-25 03:54:13 +02:00
static luaL_reg func[] = {
{ "toip", inet_global_toip },
{ "tohostname", inet_global_tohostname },
{ "gethostname", inet_global_gethostname},
2003-05-25 03:54:13 +02:00
{ NULL, NULL}
};
2002-03-21 14:52:38 +01:00
/*=========================================================================*\
* Exported functions
\*=========================================================================*/
/*-------------------------------------------------------------------------*\
* Initializes module
\*-------------------------------------------------------------------------*/
int inet_open(lua_State *L)
2002-03-21 14:52:38 +01:00
{
lua_pushstring(L, "dns");
lua_newtable(L);
luaL_openlib(L, NULL, func, 0);
lua_settable(L, -3);
2004-03-26 01:18:41 +01:00
return 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
\*-------------------------------------------------------------------------*/
2004-07-15 08:11:53 +02:00
static int inet_gethost(const char *address, struct hostent **hp) {
2002-03-21 14:52:38 +01:00
struct in_addr addr;
if (inet_aton(address, &addr))
2004-07-15 08:11:53 +02:00
return sock_gethostbyaddr((char *) &addr, sizeof(addr), hp);
2003-05-25 03:54:13 +02:00
else
2004-07-15 08:11:53 +02:00
return sock_gethostbyname(address, hp);
}
/*-------------------------------------------------------------------------*\
* Returns all information provided by the resolver given a host name
* or ip address
\*-------------------------------------------------------------------------*/
static int inet_global_tohostname(lua_State *L) {
const char *address = luaL_checkstring(L, 1);
struct hostent *hp = NULL;
int err = inet_gethost(address, &hp);
if (err != IO_DONE) {
2002-03-21 14:52:38 +01:00
lua_pushnil(L);
2004-07-15 08:11:53 +02:00
lua_pushstring(L, sock_hoststrerror(err));
2002-03-21 14:52:38 +01:00
return 2;
}
2004-07-15 08:11:53 +02:00
lua_pushstring(L, hp->h_name);
2002-03-21 14:52:38 +01:00
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
\*-------------------------------------------------------------------------*/
2004-07-15 08:11:53 +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);
2004-07-15 08:11:53 +02:00
struct hostent *hp = NULL;
int err = inet_gethost(address, &hp);
if (err != IO_DONE) {
2002-03-21 14:52:38 +01:00
lua_pushnil(L);
2004-07-15 08:11:53 +02:00
lua_pushstring(L, sock_hoststrerror(err));
2002-03-21 14:52:38 +01:00
return 2;
}
2004-07-15 08:11:53 +02:00
lua_pushstring(L, inet_ntoa(*((struct in_addr *) hp->h_addr)));
2002-03-21 14:52:38 +01:00
inet_pushresolved(L, hp);
return 2;
}
2004-07-15 08:11:53 +02:00
/*-------------------------------------------------------------------------*\
* Gets the host name
\*-------------------------------------------------------------------------*/
static int inet_global_gethostname(lua_State *L)
{
char name[257];
name[256] = '\0';
if (gethostname(name, 256) < 0) {
lua_pushnil(L);
lua_pushstring(L, "gethostname failed");
return 2;
} else {
lua_pushstring(L, name);
return 1;
}
}
2002-03-21 14:52:38 +01:00
/*=========================================================================*\
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
int inet_meth_getpeername(lua_State *L, p_sock ps)
2002-03-21 14:52:38 +01:00
{
struct sockaddr_in peer;
socklen_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);
lua_pushstring(L, "getpeername failed");
} else {
lua_pushstring(L, inet_ntoa(peer.sin_addr));
lua_pushnumber(L, ntohs(peer.sin_port));
2002-03-21 14:52:38 +01:00
}
return 2;
}
/*-------------------------------------------------------------------------*\
* Retrieves socket local name
\*-------------------------------------------------------------------------*/
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;
socklen_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);
lua_pushstring(L, "getsockname failed");
} else {
lua_pushstring(L, inet_ntoa(local.sin_addr));
lua_pushnumber(L, ntohs(local.sin_port));
2002-03-21 14:52:38 +01:00
}
return 2;
}
/*=========================================================================*\
* Internal functions
\*=========================================================================*/
/*-------------------------------------------------------------------------*\
* Passes all resolver information to Lua as a table
\*-------------------------------------------------------------------------*/
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);
2005-06-14 06:29:23 +02:00
if (alias) {
while (*alias) {
lua_pushnumber(L, i);
lua_pushstring(L, *alias);
lua_settable(L, -3);
i++; alias++;
}
2002-03-21 14:52:38 +01:00
}
lua_settable(L, resolved);
i = 1;
lua_newtable(L);
addr = (struct in_addr **) hp->h_addr_list;
2005-06-14 06:29:23 +02:00
if (addr) {
while (*addr) {
lua_pushnumber(L, i);
lua_pushstring(L, inet_ntoa(**addr));
lua_settable(L, -3);
i++; addr++;
}
2002-03-21 14:52:38 +01:00
}
lua_settable(L, resolved);
}
/*-------------------------------------------------------------------------*\
* Tries to create a new inet socket
\*-------------------------------------------------------------------------*/
2004-07-15 08:11:53 +02:00
const char *inet_trycreate(p_sock ps, int type) {
return sock_strerror(sock_create(ps, AF_INET, type, 0));
}
2002-03-21 14:52:38 +01:00
/*-------------------------------------------------------------------------*\
2003-05-25 03:54:13 +02:00
* Tries to connect to remote address (address, port)
2002-03-21 14:52:38 +01:00
\*-------------------------------------------------------------------------*/
const char *inet_tryconnect(p_sock ps, const char *address,
unsigned short port, p_tm tm)
2002-03-21 14:52:38 +01:00
{
struct sockaddr_in remote;
2004-07-15 08:11:53 +02:00
int err;
2002-03-21 14:52:38 +01:00
memset(&remote, 0, sizeof(remote));
2002-07-03 21:06:55 +02:00
remote.sin_family = AF_INET;
remote.sin_port = htons(port);
if (strcmp(address, "*")) {
if (!inet_aton(address, &remote.sin_addr)) {
2004-07-15 08:11:53 +02:00
struct hostent *hp = NULL;
2003-05-25 03:54:13 +02:00
struct in_addr **addr;
2004-07-15 08:11:53 +02:00
err = sock_gethostbyname(address, &hp);
if (err != IO_DONE) return sock_hoststrerror(err);
2003-05-25 03:54:13 +02:00
addr = (struct in_addr **) hp->h_addr_list;
memcpy(&remote.sin_addr, *addr, sizeof(struct in_addr));
}
} else remote.sin_family = AF_UNSPEC;
err = sock_connect(ps, (SA *) &remote, sizeof(remote), tm);
2004-07-15 08:11:53 +02:00
return sock_strerror(err);
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
\*-------------------------------------------------------------------------*/
const char *inet_trybind(p_sock ps, const char *address, unsigned short port)
2002-03-21 14:52:38 +01:00
{
struct sockaddr_in local;
2004-07-15 08:11:53 +02:00
int err;
2002-03-21 14:52:38 +01:00
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, "*") && !inet_aton(address, &local.sin_addr)) {
2004-07-15 08:11:53 +02:00
struct hostent *hp = NULL;
2002-03-21 14:52:38 +01:00
struct in_addr **addr;
2004-07-15 08:11:53 +02:00
err = sock_gethostbyname(address, &hp);
if (err != IO_DONE) return sock_hoststrerror(err);
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));
}
err = sock_bind(ps, (SA *) &local, sizeof(local));
2004-07-15 08:11:53 +02:00
if (err != IO_DONE) sock_destroy(ps);
return sock_strerror(err);
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 INET_ATON
int inet_aton(const char *cp, struct in_addr *inp)
2002-03-21 14:52:38 +01:00
{
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