545 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			545 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*=========================================================================*\
 | 
						|
* Internet domain functions
 | 
						|
* LuaSocket toolkit
 | 
						|
\*=========================================================================*/
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
 | 
						|
#include "lua.h"
 | 
						|
#include "lauxlib.h"
 | 
						|
 | 
						|
#include "inet.h"
 | 
						|
 | 
						|
 #ifdef _WIN32
 | 
						|
#define gai_strerror gai_strerrorA
 | 
						|
#endif
 | 
						|
 | 
						|
namespace NS_SLUA {
 | 
						|
 | 
						|
/*=========================================================================*\
 | 
						|
* Internal function prototypes.
 | 
						|
\*=========================================================================*/
 | 
						|
static int inet_global_toip(lua_State *L);
 | 
						|
static int inet_global_getaddrinfo(lua_State *L);
 | 
						|
static int inet_global_tohostname(lua_State *L);
 | 
						|
static int inet_global_getnameinfo(lua_State *L);
 | 
						|
static void inet_pushresolved(lua_State *L, struct hostent *hp);
 | 
						|
static int inet_global_gethostname(lua_State *L);
 | 
						|
 | 
						|
/* DNS functions */
 | 
						|
static luaL_Reg inet_func[] = {
 | 
						|
    { "toip", inet_global_toip},
 | 
						|
    { "getaddrinfo", inet_global_getaddrinfo},
 | 
						|
    { "tohostname", inet_global_tohostname},
 | 
						|
    { "getnameinfo", inet_global_getnameinfo},
 | 
						|
    { "gethostname", inet_global_gethostname},
 | 
						|
    { NULL, NULL}
 | 
						|
};
 | 
						|
 | 
						|
/*=========================================================================*\
 | 
						|
* Exported functions
 | 
						|
\*=========================================================================*/
 | 
						|
/*-------------------------------------------------------------------------*\
 | 
						|
* Initializes module
 | 
						|
\*-------------------------------------------------------------------------*/
 | 
						|
int inet_open(lua_State *L)
 | 
						|
{
 | 
						|
    lua_pushstring(L, "dns");
 | 
						|
    lua_newtable(L);
 | 
						|
#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
 | 
						|
    luaL_setfuncs(L, inet_func, 0);
 | 
						|
#else
 | 
						|
    luaL_openlib(L, NULL, inet_func, 0);
 | 
						|
#endif
 | 
						|
    lua_settable(L, -3);
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
/*=========================================================================*\
 | 
						|
* Global Lua functions
 | 
						|
\*=========================================================================*/
 | 
						|
/*-------------------------------------------------------------------------*\
 | 
						|
* Returns all information provided by the resolver given a host name
 | 
						|
* or ip address
 | 
						|
\*-------------------------------------------------------------------------*/
 | 
						|
static int inet_gethost(const char *address, struct hostent **hp) {
 | 
						|
    struct in_addr addr;
 | 
						|
    if (inet_aton(address, &addr))
 | 
						|
        return socket_gethostbyaddr((char *) &addr, sizeof(addr), hp);
 | 
						|
    else
 | 
						|
        return socket_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) {
 | 
						|
        lua_pushnil(L);
 | 
						|
        lua_pushstring(L, socket_hoststrerror(err));
 | 
						|
        return 2;
 | 
						|
    }
 | 
						|
    lua_pushstring(L, hp->h_name);
 | 
						|
    inet_pushresolved(L, hp);
 | 
						|
    return 2;
 | 
						|
}
 | 
						|
 | 
						|
static int inet_global_getnameinfo(lua_State *L) {
 | 
						|
    char hbuf[NI_MAXHOST];
 | 
						|
    char sbuf[NI_MAXSERV];
 | 
						|
    int i, ret;
 | 
						|
    struct addrinfo hints;
 | 
						|
    struct addrinfo *resolved, *iter;
 | 
						|
    const char *host = luaL_optstring(L, 1, NULL);
 | 
						|
    const char *serv = luaL_optstring(L, 2, NULL);
 | 
						|
 | 
						|
    if (!(host || serv))
 | 
						|
        luaL_error(L, "host and serv cannot be both nil");
 | 
						|
 | 
						|
    memset(&hints, 0, sizeof(hints));
 | 
						|
    hints.ai_socktype = SOCK_STREAM;
 | 
						|
    hints.ai_family = PF_UNSPEC;
 | 
						|
 | 
						|
    ret = getaddrinfo(host, serv, &hints, &resolved);
 | 
						|
    if (ret != 0) {
 | 
						|
        lua_pushnil(L);
 | 
						|
        lua_pushstring(L, socket_gaistrerror(ret));
 | 
						|
        return 2;
 | 
						|
    }
 | 
						|
 | 
						|
    lua_newtable(L);
 | 
						|
    for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) {
 | 
						|
        getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen, 
 | 
						|
            hbuf, host? (socklen_t) sizeof(hbuf): 0, 
 | 
						|
            sbuf, serv? (socklen_t) sizeof(sbuf): 0, 0);
 | 
						|
        if (host) {
 | 
						|
            lua_pushnumber(L, i);
 | 
						|
            lua_pushstring(L, hbuf);
 | 
						|
            lua_settable(L, -3);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    freeaddrinfo(resolved);
 | 
						|
 | 
						|
    if (serv) {
 | 
						|
        lua_pushstring(L, sbuf);
 | 
						|
        return 2;
 | 
						|
    } else {
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/*-------------------------------------------------------------------------*\
 | 
						|
* Returns all information provided by the resolver given a host name
 | 
						|
* or ip address
 | 
						|
\*-------------------------------------------------------------------------*/
 | 
						|
static int inet_global_toip(lua_State *L)
 | 
						|
{
 | 
						|
    const char *address = luaL_checkstring(L, 1);
 | 
						|
    struct hostent *hp = NULL;
 | 
						|
    int err = inet_gethost(address, &hp);
 | 
						|
    if (err != IO_DONE) {
 | 
						|
        lua_pushnil(L);
 | 
						|
        lua_pushstring(L, socket_hoststrerror(err));
 | 
						|
        return 2;
 | 
						|
    }
 | 
						|
    lua_pushstring(L, inet_ntoa(*((struct in_addr *) hp->h_addr)));
 | 
						|
    inet_pushresolved(L, hp);
 | 
						|
    return 2;
 | 
						|
}
 | 
						|
 | 
						|
int inet_optfamily(lua_State* L, int narg, const char* def)
 | 
						|
{
 | 
						|
    static const char* optname[] = { "unspec", "inet", "inet6", NULL };
 | 
						|
    static int optvalue[] = { PF_UNSPEC, PF_INET, PF_INET6, 0 };
 | 
						|
 | 
						|
    return optvalue[luaL_checkoption(L, narg, def, optname)];
 | 
						|
}
 | 
						|
 | 
						|
int inet_optsocktype(lua_State* L, int narg, const char* def)
 | 
						|
{
 | 
						|
    static const char* optname[] = { "stream", "dgram", NULL };
 | 
						|
    static int optvalue[] = { SOCK_STREAM, SOCK_DGRAM, 0 };
 | 
						|
 | 
						|
    return optvalue[luaL_checkoption(L, narg, def, optname)];
 | 
						|
}
 | 
						|
 | 
						|
static int inet_global_getaddrinfo(lua_State *L)
 | 
						|
{
 | 
						|
    const char *hostname = luaL_checkstring(L, 1);
 | 
						|
    struct addrinfo *iterator = NULL, *resolved = NULL;
 | 
						|
    struct addrinfo hints;
 | 
						|
    int i = 1, ret = 0;
 | 
						|
    memset(&hints, 0, sizeof(hints));
 | 
						|
    hints.ai_socktype = SOCK_STREAM;
 | 
						|
    hints.ai_family = PF_UNSPEC;
 | 
						|
    ret = getaddrinfo(hostname, NULL, &hints, &resolved);
 | 
						|
    if (ret != 0) {
 | 
						|
        lua_pushnil(L);
 | 
						|
        lua_pushstring(L, socket_gaistrerror(ret));
 | 
						|
        return 2;
 | 
						|
    }
 | 
						|
    lua_newtable(L);
 | 
						|
    for (iterator = resolved; iterator; iterator = iterator->ai_next) {
 | 
						|
        char hbuf[NI_MAXHOST];
 | 
						|
        ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen, 
 | 
						|
            hbuf, (socklen_t) sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
 | 
						|
        if (ret){
 | 
						|
          lua_pushnil(L);
 | 
						|
          lua_pushstring(L, socket_gaistrerror(ret));
 | 
						|
          return 2;
 | 
						|
        }
 | 
						|
        lua_pushnumber(L, i);
 | 
						|
        lua_newtable(L);
 | 
						|
        switch (iterator->ai_family) {
 | 
						|
            case AF_INET:
 | 
						|
                lua_pushliteral(L, "family");
 | 
						|
                lua_pushliteral(L, "inet");
 | 
						|
                lua_settable(L, -3);
 | 
						|
                break;
 | 
						|
            case AF_INET6:
 | 
						|
                lua_pushliteral(L, "family");
 | 
						|
                lua_pushliteral(L, "inet6");
 | 
						|
                lua_settable(L, -3);
 | 
						|
                break;
 | 
						|
        }
 | 
						|
        lua_pushliteral(L, "addr");
 | 
						|
        lua_pushstring(L, hbuf);
 | 
						|
        lua_settable(L, -3);
 | 
						|
        lua_settable(L, -3);
 | 
						|
        i++;
 | 
						|
    }
 | 
						|
    freeaddrinfo(resolved);
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
/*-------------------------------------------------------------------------*\
 | 
						|
* 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, socket_strerror(errno));
 | 
						|
        return 2;
 | 
						|
    } else {
 | 
						|
        lua_pushstring(L, name);
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/*=========================================================================*\
 | 
						|
* Lua methods
 | 
						|
\*=========================================================================*/
 | 
						|
/*-------------------------------------------------------------------------*\
 | 
						|
* Retrieves socket peer name
 | 
						|
\*-------------------------------------------------------------------------*/
 | 
						|
int inet_meth_getpeername(lua_State *L, p_socket ps, int family)
 | 
						|
{
 | 
						|
    int err;
 | 
						|
    struct sockaddr_storage peer;
 | 
						|
    socklen_t peer_len = sizeof(peer);
 | 
						|
    char name[INET6_ADDRSTRLEN];
 | 
						|
    char port[6]; /* 65535 = 5 bytes + 0 to terminate it */
 | 
						|
    if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) {
 | 
						|
        lua_pushnil(L);
 | 
						|
        lua_pushstring(L, socket_strerror(errno));
 | 
						|
        return 2;
 | 
						|
    }
 | 
						|
	err = getnameinfo((struct sockaddr *) &peer, peer_len,
 | 
						|
        name, INET6_ADDRSTRLEN,
 | 
						|
        port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
 | 
						|
    if (err) {
 | 
						|
        lua_pushnil(L);
 | 
						|
        lua_pushstring(L, gai_strerror(err));
 | 
						|
        return 2;
 | 
						|
    }
 | 
						|
    lua_pushstring(L, name);
 | 
						|
    lua_pushinteger(L, (int) strtol(port, (char **) NULL, 10));
 | 
						|
    if (family == PF_INET) {
 | 
						|
        lua_pushliteral(L, "inet");
 | 
						|
    } else if (family == PF_INET6) {
 | 
						|
        lua_pushliteral(L, "inet6");
 | 
						|
    } else {
 | 
						|
        lua_pushliteral(L, "uknown family");
 | 
						|
    }
 | 
						|
    return 3;
 | 
						|
}
 | 
						|
 | 
						|
/*-------------------------------------------------------------------------*\
 | 
						|
* Retrieves socket local name
 | 
						|
\*-------------------------------------------------------------------------*/
 | 
						|
int inet_meth_getsockname(lua_State *L, p_socket ps, int family)
 | 
						|
{
 | 
						|
    int err;
 | 
						|
    struct sockaddr_storage peer;
 | 
						|
    socklen_t peer_len = sizeof(peer);
 | 
						|
    char name[INET6_ADDRSTRLEN];
 | 
						|
    char port[6]; /* 65535 = 5 bytes + 0 to terminate it */
 | 
						|
    if (getsockname(*ps, (SA *) &peer, &peer_len) < 0) {
 | 
						|
        lua_pushnil(L);
 | 
						|
        lua_pushstring(L, socket_strerror(errno));
 | 
						|
        return 2;
 | 
						|
    }
 | 
						|
	err=getnameinfo((struct sockaddr *)&peer, peer_len, 
 | 
						|
		name, INET6_ADDRSTRLEN, port, 6, NI_NUMERICHOST | NI_NUMERICSERV);
 | 
						|
    if (err) {
 | 
						|
        lua_pushnil(L);
 | 
						|
        lua_pushstring(L, gai_strerror(err));
 | 
						|
        return 2;
 | 
						|
    }
 | 
						|
    lua_pushstring(L, name);
 | 
						|
    lua_pushstring(L, port);
 | 
						|
    if (family == PF_INET) {
 | 
						|
        lua_pushliteral(L, "inet");
 | 
						|
    } else if (family == PF_INET6) {
 | 
						|
        lua_pushliteral(L, "inet6");
 | 
						|
    } else {
 | 
						|
        lua_pushliteral(L, "uknown family");
 | 
						|
    }
 | 
						|
    return 3;
 | 
						|
}
 | 
						|
 | 
						|
/*=========================================================================*\
 | 
						|
* 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);
 | 
						|
    if (alias) {
 | 
						|
        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;
 | 
						|
    if (addr) {
 | 
						|
        while (*addr) {
 | 
						|
            lua_pushnumber(L, i);
 | 
						|
            lua_pushstring(L, inet_ntoa(**addr));
 | 
						|
            lua_settable(L, -3);
 | 
						|
            i++; addr++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    lua_settable(L, resolved);
 | 
						|
}
 | 
						|
 | 
						|
/*-------------------------------------------------------------------------*\
 | 
						|
* Tries to create a new inet socket
 | 
						|
\*-------------------------------------------------------------------------*/
 | 
						|
const char *inet_trycreate(p_socket ps, int family, int type) {
 | 
						|
    return socket_strerror(socket_create(ps, family, type, 0));
 | 
						|
}
 | 
						|
 | 
						|
/*-------------------------------------------------------------------------*\
 | 
						|
* "Disconnects" a DGRAM socket
 | 
						|
\*-------------------------------------------------------------------------*/
 | 
						|
const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm)
 | 
						|
{
 | 
						|
    switch (family) {
 | 
						|
        case PF_INET: {
 | 
						|
            struct sockaddr_in sin;
 | 
						|
            memset((char *) &sin, 0, sizeof(sin));
 | 
						|
            sin.sin_family = AF_UNSPEC;
 | 
						|
            sin.sin_addr.s_addr = INADDR_ANY;
 | 
						|
            return socket_strerror(socket_connect(ps, (SA *) &sin, 
 | 
						|
                sizeof(sin), tm));
 | 
						|
        }
 | 
						|
        case PF_INET6: {
 | 
						|
            struct sockaddr_in6 sin6;
 | 
						|
            struct in6_addr addrany = IN6ADDR_ANY_INIT; 
 | 
						|
            memset((char *) &sin6, 0, sizeof(sin6));
 | 
						|
            sin6.sin6_family = AF_UNSPEC;
 | 
						|
            sin6.sin6_addr = addrany;
 | 
						|
            return socket_strerror(socket_connect(ps, (SA *) &sin6, 
 | 
						|
                sizeof(sin6), tm));
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/*-------------------------------------------------------------------------*\
 | 
						|
* Tries to connect to remote address (address, port)
 | 
						|
\*-------------------------------------------------------------------------*/
 | 
						|
const char *inet_tryconnect(p_socket ps, int *family, const char *address,
 | 
						|
        const char *serv, p_timeout tm, struct addrinfo *connecthints)
 | 
						|
{
 | 
						|
    struct addrinfo *iterator = NULL, *resolved = NULL;
 | 
						|
    const char *err = NULL;
 | 
						|
    /* try resolving */
 | 
						|
    err = socket_gaistrerror(getaddrinfo(address, serv,
 | 
						|
                connecthints, &resolved));
 | 
						|
    if (err != NULL) {
 | 
						|
        if (resolved) freeaddrinfo(resolved);
 | 
						|
        return err;
 | 
						|
    }
 | 
						|
    for (iterator = resolved; iterator; iterator = iterator->ai_next) {
 | 
						|
        timeout_markstart(tm);
 | 
						|
        /* create new socket if necessary. if there was no
 | 
						|
         * bind, we need to create one for every new family
 | 
						|
         * that shows up while iterating. if there was a
 | 
						|
         * bind, all families will be the same and we will
 | 
						|
         * not enter this branch. */
 | 
						|
        if (*family != iterator->ai_family) {
 | 
						|
            socket_destroy(ps);
 | 
						|
            err = socket_strerror(socket_create(ps, iterator->ai_family, 
 | 
						|
                iterator->ai_socktype, iterator->ai_protocol));
 | 
						|
            if (err != NULL) {
 | 
						|
                freeaddrinfo(resolved);
 | 
						|
                return err;
 | 
						|
            }
 | 
						|
            *family = iterator->ai_family;
 | 
						|
            /* all sockets initially non-blocking */
 | 
						|
            socket_setnonblocking(ps);
 | 
						|
        }
 | 
						|
        /* try connecting to remote address */
 | 
						|
        err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr, 
 | 
						|
            (socklen_t) iterator->ai_addrlen, tm));
 | 
						|
        /* if success, break out of loop */
 | 
						|
        if (err == NULL) break;
 | 
						|
    }
 | 
						|
    freeaddrinfo(resolved);
 | 
						|
    /* here, if err is set, we failed */
 | 
						|
    return err;
 | 
						|
}
 | 
						|
 | 
						|
/*-------------------------------------------------------------------------*\
 | 
						|
* Tries to accept a socket
 | 
						|
\*-------------------------------------------------------------------------*/
 | 
						|
const char *inet_tryaccept(p_socket server, int family, p_socket client, 
 | 
						|
    p_timeout tm)
 | 
						|
{
 | 
						|
	socklen_t len;
 | 
						|
	t_sockaddr_storage addr;
 | 
						|
	if (family == PF_INET6) {
 | 
						|
		len = sizeof(struct sockaddr_in6);
 | 
						|
	} else {
 | 
						|
		len = sizeof(struct sockaddr_in);
 | 
						|
	}
 | 
						|
	return socket_strerror(socket_accept(server, client, (SA *) &addr, 
 | 
						|
        &len, tm));
 | 
						|
}
 | 
						|
 | 
						|
/*-------------------------------------------------------------------------*\
 | 
						|
* Tries to bind socket to (address, port)
 | 
						|
\*-------------------------------------------------------------------------*/
 | 
						|
const char *inet_trybind(p_socket ps, const char *address, const char *serv,
 | 
						|
        struct addrinfo *bindhints)
 | 
						|
{
 | 
						|
    struct addrinfo *iterator = NULL, *resolved = NULL;
 | 
						|
    const char *err = NULL;
 | 
						|
    t_socket sock = *ps;
 | 
						|
    /* translate luasocket special values to C */
 | 
						|
    if (strcmp(address, "*") == 0) address = NULL;
 | 
						|
    if (!serv) serv = "0";
 | 
						|
    /* try resolving */
 | 
						|
    err = socket_gaistrerror(getaddrinfo(address, serv, bindhints, &resolved));
 | 
						|
    if (err) {
 | 
						|
        if (resolved) freeaddrinfo(resolved);
 | 
						|
        return err;
 | 
						|
    }
 | 
						|
    /* iterate over resolved addresses until one is good */
 | 
						|
    for (iterator = resolved; iterator; iterator = iterator->ai_next) {
 | 
						|
        if(sock == SOCKET_INVALID) {
 | 
						|
            err = socket_strerror(socket_create(&sock, iterator->ai_family,
 | 
						|
                        iterator->ai_socktype, iterator->ai_protocol));
 | 
						|
            if(err)
 | 
						|
                continue;
 | 
						|
        }
 | 
						|
        /* try binding to local address */
 | 
						|
        err = socket_strerror(socket_bind(&sock,
 | 
						|
            (SA *) iterator->ai_addr,
 | 
						|
            (socklen_t) iterator->ai_addrlen));
 | 
						|
 | 
						|
        /* keep trying unless bind succeeded */
 | 
						|
        if (err) {
 | 
						|
            if(sock != *ps)
 | 
						|
                socket_destroy(&sock);
 | 
						|
        } else {
 | 
						|
            /* remember what we connected to, particularly the family */
 | 
						|
            *bindhints = *iterator;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    /* cleanup and return error */
 | 
						|
    freeaddrinfo(resolved);
 | 
						|
    *ps = sock;
 | 
						|
    return err;
 | 
						|
}
 | 
						|
 | 
						|
/*-------------------------------------------------------------------------*\
 | 
						|
* Some systems do not provide these so that we provide our own. 
 | 
						|
\*-------------------------------------------------------------------------*/
 | 
						|
#ifdef LUASOCKET_INET_ATON
 | 
						|
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
 | 
						|
 | 
						|
#ifdef LUASOCKET_INET_PTON
 | 
						|
int inet_pton(int af, const char *src, void *dst) 
 | 
						|
{
 | 
						|
    struct addrinfo hints, *res;
 | 
						|
    int ret = 1;
 | 
						|
    memset(&hints, 0, sizeof(struct addrinfo));
 | 
						|
    hints.ai_family = af;
 | 
						|
    hints.ai_flags = AI_NUMERICHOST;
 | 
						|
    if (getaddrinfo(src, NULL, &hints, &res) != 0) return -1;
 | 
						|
    if (af == AF_INET) {
 | 
						|
        struct sockaddr_in *in = (struct sockaddr_in *) res->ai_addr;
 | 
						|
        memcpy(dst, &in->sin_addr, sizeof(in->sin_addr));
 | 
						|
    } else if (af == AF_INET6) {
 | 
						|
        struct sockaddr_in6 *in = (struct sockaddr_in6 *) res->ai_addr;
 | 
						|
        memcpy(dst, &in->sin6_addr, sizeof(in->sin6_addr));
 | 
						|
    } else {
 | 
						|
        ret = -1;
 | 
						|
    }
 | 
						|
    freeaddrinfo(res); 
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
} // end NS_SLUA
 |