/* _gethostaddr * * gets the address of a host passed by name, and fills out a sockaddr * structure * * Arguments: * L lua State * addr ip address or hostname * type SOCK_STREAM or SOCK_DGRAM * port port number for sockaddr * family (out) address family (AF_INET or AF_INET6) of address * protocol (out) protocol of address * sa (out) pointer to struct sockaddr to fill with data. * slen (inout) length of sa, and on return length of data * * Returns: * 0 when the lookup succeeded, -1 otherwise * On success, the arguments family, protocol, sa and slen will have * been updated with values from the looked up address */ static int _gethostaddr(lua_State *L, const char *addr, int type, int port, int *family, int *protocol, struct sockaddr *sa, socklen_t *slen) { struct addrinfo hint, *info =0; memset(&hint, 0, sizeof(hint)); hint.ai_family = AF_UNSPEC; hint.ai_socktype = type; if (_needsnolookup(addr)) hint.ai_flags = AI_NUMERICHOST; int err = getaddrinfo(addr, 0, &hint, &info); if (err != 0) { if (info) freeaddrinfo(info); return lsocket_error(L, gai_strerror(err)); } else if (info->ai_family != AF_INET && info->ai_family != AF_INET6) { if (info) freeaddrinfo(info); return lsocket_error(L, "unknown address family"); } *family = info->ai_family; *slen = info->ai_addrlen; *protocol = info->ai_protocol; memcpy(sa, info->ai_addr, *slen); if (*family == AF_INET) ((struct sockaddr_in*) sa)->sin_port = htons(port); else ((struct sockaddr_in6*) sa)->sin6_port = htons(port); freeaddrinfo(info); return 0; }
/* ares_aresolver * * starts an asynchronous getaddrinfo request * * Arguments: * L Lua State * * Lua Stack: * 1 the name to resolve * * Lua Returns: * +1 true, if the cancel request was sent, nil + error message if an * error occurred. */ static int ares_aresolver(lua_State *L) { const char *name = luaL_checkstring(L, 1); aResolver *ares = ares_pushaResolver(L); struct addrinfo hint; memset(&hint, 0, sizeof(hint)); hint.ai_family = AF_UNSPEC; /* reduce the number of duplicate hits, this makes no difference for * the actual dns resolving. */ hint.ai_protocol = IPPROTO_TCP; hint.ai_socktype = SOCK_STREAM; if (_needsnolookup(name)) hint.ai_flags = AI_NUMERICHOST; ares->rq = gai_start(name, 0, &hint); if (ares->rq == NULL) return ares_error(L, strerror(errno)); return 1; }
/* lsocket_resolve * * resolves a name to an address * * Arguments: * L lua State * * Lua Stack: * 1 name of host to resolve * * Lua Returns: * +1 a table of all addresses the argument resolves to. For each address, * a subtable with the fields family and addr is created. */ static int lsocket_resolve(lua_State *L) { const char *name = luaL_checkstring(L, 1); char buf[TOSTRING_BUFSIZ]; struct addrinfo hint, *info =0; memset(&hint, 0, sizeof(hint)); hint.ai_family = AF_UNSPEC; if (_needsnolookup(name)) hint.ai_flags = AI_NUMERICHOST; int err = getaddrinfo(name, 0, &hint, &info); if (err != 0) { if (info) freeaddrinfo(info); return lsocket_error(L, gai_strerror(err)); } int i = 1; lua_newtable(L); while (info) { if (info->ai_family == AF_INET || info->ai_family == AF_INET6) { lua_newtable(L); lua_pushliteral(L, "family"); lua_pushstring(L, info->ai_family == AF_INET ? LSOCKET_INET : LSOCKET_INET6); lua_rawset(L, -3); lua_pushliteral(L, "addr"); lua_pushstring(L, _addr2string(info->ai_addr, buf, TOSTRING_BUFSIZ)); lua_rawset(L, -3); lua_rawseti(L, -2, i++); info = info->ai_next; } /* silently ignore unknown address families */ } freeaddrinfo(info); return 1; }