コード例 #1
0
ファイル: sys_sock.c プロジェクト: LuaDist/luasys
/*
 * Arguments: sd_udata, binary_address (multiaddr),
 *	[binary_address_ipv4 (interface) | interface_ipv6 (number),
 *	add/drop (boolean)]
 * Returns: [sd_udata]
 */
static int
sock_membership (lua_State *L)
{
    sd_t sd = (sd_t) lua_unboxinteger(L, 1, SD_TYPENAME);
    int len, af;
    const char *maddrp = sock_checkladdr(L, 2, &len, &af);
    const int optflag = !lua_isboolean(L, -1) || lua_toboolean(L, -1)
     ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
    union {
	struct ip_mreq ip;
#ifdef IPPROTO_IPV6
	struct ipv6_mreq ip6;
#endif
    } mr;
    int level, mr_len;

    memset(&mr, 0, sizeof(mr));
    if (af == AF_INET) {
	const char *ifacep = (lua_type(L, 3) == LUA_TSTRING)
	 ? sock_checkladdr(L, 3, &len, &af) : NULL;

	if (ifacep && af != AF_INET)
	    luaL_argerror(L, 3, "invalid interface");

	memcpy(&mr.ip.imr_multiaddr, maddrp, len);
	if (ifacep)
	    memcpy(&mr.ip.imr_interface, ifacep, len);

	level = IPPROTO_IP;
	mr_len = sizeof(struct ip_mreq);
    }
    else {
#ifdef IPPROTO_IPV6
	memcpy(&mr.ip6.ipv6mr_multiaddr, maddrp, len);
	mr.ip6.ipv6mr_interface = lua_tointeger(L, 3);

	level = IPPROTO_IPV6;
	mr_len = sizeof(struct ipv6_mreq);
#else
	luaL_argerror(L, 2, "invalid family");
#endif
    }

    if (!setsockopt(sd, level, optflag, (char *) &mr, mr_len)) {
	lua_settop(L, 1);
	return 1;
    }
    return sys_seterror(L, 0);
}
コード例 #2
0
ファイル: sock_addr.c プロジェクト: tnodir/luasys
/*
 * Arguments: binary_address (string)
 * Returns: [host_name (string)]
 */
static int
sock_getnameinfo (lua_State *L)
{
  int len, af;
  const char *addr = sock_checkladdr(L, 1, &len, &af);
  struct sock_addr sa;
  void *inp = sock_addr_get_inp(&sa, af);
  const int in_len = sock_addr_get_inlen(af);
#ifdef USE_GAI
  char host[NI_MAXHOST];
#else
  struct hostent *hp;
#endif
  int gai_errno;

  memset(&sa, 0, sizeof(struct sock_addr));
  sa.u.addr.sa_family = (short) af;
  memcpy(inp, addr, in_len);

#ifdef USE_GAI
  sys_vm_leave(L);
  gai_errno = getnameinfo(&sa.u.addr, sizeof(struct sock_addr),
   host, sizeof(host), NULL, 0, NI_NAMEREQD);
  sys_vm_enter(L);

  if (gai_errno) goto err;

  lua_pushstring(L, host);
#else
  sys_vm_leave(L);
  hp = gethostbyaddr(inp, in_len, af);
  sys_vm_enter(L);

  if (!hp) {
    gai_errno = h_errno;
    goto err;
  }

  lua_pushstring(L, hp->h_name);
#endif
  return 1;
 err:
  return sock_gai_seterror(L, gai_errno);
}
コード例 #3
0
ファイル: sock_addr.c プロジェクト: tnodir/luasys
/*
 * Returns: [interfaces (table)]
 */
static int
sock_getifaddrs (lua_State *L)
{
  struct sock_addr *sap;
  int i, res;

#ifndef _WIN32
  struct ifaddrs *result, *rp;

  sys_vm_leave(L);
  res = getifaddrs(&result);
  sys_vm_enter(L);
#else
  INTERFACE_INFO result[8192], *rp;
  SOCKET sd = WSASocketW(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAGS);
  DWORD n;

  sys_vm_leave(L);
  res = WSAIoctl(sd, SIO_GET_INTERFACE_LIST, NULL, 0,
   result, sizeof(result), &n, NULL, NULL);

  closesocket(sd);
  sys_vm_enter(L);
#endif

  if (res == -1)
    return sys_seterror(L, 0);

  lua_createtable(L, 8, 0);
  rp = result;
#ifndef _WIN32
  for (i = 0; rp; rp = rp->ifa_next) {
#else
  for (i = 0; n--; ++rp) {
#endif
#ifndef _WIN32
    sap = (struct sock_addr *) rp->ifa_addr;
#else
    sap = (struct sock_addr *) &rp->iiAddress;
#endif
    if (!sap || sap->u.addr.sa_family == AF_UNSPEC)
      continue;

    lua_newtable(L);
    {
      const int af = sap->u.addr.sa_family;

      if (af == AF_INET
#ifdef AF_INET6
       || af == AF_INET6
#endif
      ) {
        sock_pushaddr(L, sap);
        lua_setfield(L, -2, "addr");
      }

      {
        const char *s = NULL;

        switch (af) {
        case AF_INET: s = "INET"; break;
#ifdef AF_INET6
        case AF_INET6: s = "INET6"; break;
#endif
#ifdef AF_LOCAL
        case AF_LOCAL: s = "LOCAL"; break;
#endif
#ifdef AF_AX25
        case AF_AX25: s = "AX25"; break;
#endif
#ifdef AF_IPX
        case AF_IPX: s = "IPX"; break;
#endif
#ifdef AF_APPLETALK
        case AF_APPLETALK: s = "APPLETALK"; break;
#endif
#ifdef AF_NETROM
        case AF_NETROM: s = "NETROM"; break;
#endif
#ifdef AF_BRIDGE
        case AF_BRIDGE: s = "BRIDGE"; break;
#endif
#ifdef AF_ATMPVC
        case AF_ATMPVC: s = "ATMPVC"; break;
#endif
#ifdef AF_X25
        case AF_X25: s = "X25"; break;
#endif
#ifdef AF_ROSE
        case AF_ROSE: s = "ROSE"; break;
#endif
#ifdef AF_DECnet
        case AF_DECnet: s = "DECnet"; break;
#endif
#ifdef AF_NETBEUI
        case AF_NETBEUI: s = "NETBEUI"; break;
#endif
#ifdef AF_SECURITY
        case AF_SECURITY: s = "SECURITY"; break;
#endif
#ifdef AF_KEY
        case AF_KEY: s = "KEY"; break;
#endif
#ifdef AF_NETLINK
        case AF_NETLINK: s = "NETLINK"; break;
#endif
#ifdef AF_PACKET
        case AF_PACKET: s = "PACKET"; break;
#endif
#ifdef AF_ASH
        case AF_ASH: s = "ASH"; break;
#endif
#ifdef AF_ECONET
        case AF_ECONET: s = "ECONET"; break;
#endif
#ifdef AF_ATMSVC
        case AF_ATMSVC: s = "ATMSVC"; break;
#endif
#ifdef AF_RDS
        case AF_RDS: s = "RDS"; break;
#endif
#ifdef AF_SNA
        case AF_SNA: s = "SNA"; break;
#endif
#ifdef AF_IRDA
        case AF_IRDA: s = "IRDA"; break;
#endif
#ifdef AF_PPPOX
        case AF_PPPOX: s = "PPPOX"; break;
#endif
#ifdef AF_WANPIPE
        case AF_WANPIPE: s = "WANPIPE"; break;
#endif
#ifdef AF_LLC
        case AF_LLC: s = "LLC"; break;
#endif
#ifdef AF_CAN
        case AF_CAN: s = "CAN"; break;
#endif
#ifdef AF_TIPC
        case AF_TIPC: s = "TIPC"; break;
#endif
#ifdef AF_BLUETOOTH
        case AF_BLUETOOTH: s = "BLUETOOTH"; break;
#endif
#ifdef AF_IUCV
        case AF_IUCV: s = "IUCV"; break;
#endif
#ifdef AF_RXRPC
        case AF_RXRPC: s = "RXRPC"; break;
#endif
#ifdef AF_ISDN
        case AF_ISDN: s = "ISDN"; break;
#endif
#ifdef AF_PHONET
        case AF_PHONET: s = "PHONET"; break;
#endif
#ifdef AF_IEEE802154
        case AF_IEEE802154: s = "IEEE802154"; break;
#endif
        default: s = "UNKNOWN";
        }
        if (s) {
          lua_pushstring(L, s);
          lua_setfield(L, -2, "family");
        }
      }

#ifndef _WIN32
      sap = (struct sock_addr *) rp->ifa_netmask;
#else
      sap = (struct sock_addr *) &rp->iiNetmask;
#endif
      if (sap) {
        sock_pushaddr(L, sap);
        lua_setfield(L, -2, "netmask");
      }

#ifndef _WIN32
      sap = (struct sock_addr *) rp->ifa_broadaddr;
#else
      sap = (struct sock_addr *) &rp->iiBroadcastAddress;
#endif
      if (sap) {
        sock_pushaddr(L, sap);
        lua_setfield(L, -2, "broadaddr");
      }

      lua_createtable(L, 0, 5);
      {
#ifndef _WIN32
        const int flags = rp->ifa_flags;
#else
        const int flags = rp->iiFlags;
#endif

        lua_pushboolean(L, flags & IFF_UP);
        lua_setfield(L, -2, "up");

        lua_pushboolean(L, flags & IFF_BROADCAST);
        lua_setfield(L, -2, "broadcast");

        lua_pushboolean(L, flags & IFF_LOOPBACK);
        lua_setfield(L, -2, "loopback");

        lua_pushboolean(L, flags & IFF_POINTOPOINT);
        lua_setfield(L, -2, "pointtopoint");

        lua_pushboolean(L, flags & IFF_MULTICAST);
        lua_setfield(L, -2, "multicast");
      }
      lua_setfield(L, -2, "flags");
    }
    lua_rawseti(L, -2, ++i);
  }
#ifndef _WIN32
  freeifaddrs(result);
#endif
  return 1;
}


/*
 * Arguments: text_address (string), [ip4_tonumber (true)]
 * Returns: [binary_address (string | number)]
 */
static int
sock_inet_pton (lua_State *L)
{
  const char *src = luaL_checkstring(L, 1);
  const int to_ip4 = lua_toboolean(L, 2);
  const int af = (!to_ip4 && strchr(src, ':')) ? AF_INET6 : AF_INET;
  struct sock_addr sa;
  void *inp = sock_addr_get_inp(&sa, af);
  const int in_len = sock_addr_get_inlen(af);
#ifdef _WIN32
  union sys_rwptr src_ptr;  /* to avoid "const cast" warning */
#endif

  memset(&sa, 0, sizeof(struct sock_addr));
  if (*src == '*') goto end;

#ifndef _WIN32
  if (inet_pton(af, src, inp) == 1) {
#else
  sa.addrlen = sizeof(sa);
  src_ptr.r = src;
  if (!WSAStringToAddressA(src_ptr.w, af, NULL,
   &sa.u.addr, &sa.addrlen)) {
#endif
 end:
    if (to_ip4)
      lua_pushnumber(L, ntohl(*((unsigned long *) inp)));
    else
      lua_pushlstring(L, inp, in_len);
    return 1;
  }
  return sys_seterror(L, 0);
}

/*
 * Arguments: binary_address (string | number)
 * Returns: [text_address (string)]
 */
static int
sock_inet_ntop (lua_State *L)
{
  const int is_ip4 = (lua_type(L, 1) == LUA_TNUMBER);
  unsigned long ip4;
  int in_len, af;
  const char *src;
  char buf[48];

  if (is_ip4) {
    const lua_Number num = lua_tonumber(L, 1);

    in_len = 4;
    af = AF_INET;
    ip4 = htonl((unsigned long) num);
    src = (const char *) &ip4;
  } else {
    src = sock_checkladdr(L, 1, &in_len, &af);
  }

#ifndef _WIN32
  if (inet_ntop(af, src, buf, sizeof(buf)) == NULL)
    goto err;
#else
  {
    struct sock_addr sa;
    void *inp = sock_addr_get_inp(&sa, af);
    const int sl = (af == AF_INET) ? sizeof(struct sockaddr_in)
     : sizeof(struct sockaddr_in6);
    DWORD buflen = sizeof(buf);

    memset(&sa, 0, sizeof(struct sock_addr));
    memcpy(inp, src, in_len);
    sa.u.addr.sa_family = (short) af;

    if (WSAAddressToStringA(&sa.u.addr, sl, NULL, buf, &buflen)
     || buflen >= sizeof(buf))
      goto err;
  }
#endif
  lua_pushstring(L, buf);
  return 1;
 err:
  return sys_seterror(L, 0);
}


/*
 * Returns: sock_addr_udata
 */
static int
sock_addr_new (lua_State *L)
{
  lua_newuserdata(L, sizeof(struct sock_addr));
  luaL_getmetatable(L, SA_TYPENAME);
  lua_setmetatable(L, -2);
  return 1;
}

/*
 * Arguments: sock_addr_udata, [port (number), binary_address (string)]
 * Returns: sock_addr_udata | port (number), binary_address (string)
 */
static int
sock_addr_inet (lua_State *L)
{
  struct sock_addr *sap = checkudata(L, 1, SA_TYPENAME);

  if (lua_gettop(L) == 1) {
    const int af = sap->u.addr.sa_family;

    if (af == AF_INET) {
      lua_pushinteger(L, ntohs(sap->u.in.sin_port));
      lua_pushlstring(L, (char *) &sap->u.in.sin_addr,
       sizeof(struct in_addr));
    } else if (af == AF_INET6) {
      lua_pushinteger(L, ntohs(sap->u.in6.sin6_port));
      lua_pushlstring(L, (char *) &sap->u.in6.sin6_addr,
       sizeof(struct in6_addr));
    } else
      return 0;
    return 2;
  } else {
    const int port = (int) lua_tointeger(L, 2);
    int in_len = SOCK_ADDR_LEN, af = AF_INET;
    const char *addr = lua_isnoneornil(L, 3) ? NULL
     : sock_checkladdr(L, 3, &in_len, &af);

    memset(sap, 0, sizeof(struct sock_addr));
    sap->u.addr.sa_family = (short) af;
    if (af == AF_INET) {
      sap->u.in.sin_port = htons((unsigned short) port);
      if (addr)
        memcpy(&sap->u.in.sin_addr, addr, in_len);
      sap->addrlen = sizeof(struct sockaddr_in);
    } else {
      sap->u.in6.sin6_port = htons((unsigned short) port);
      if (addr)
        memcpy(&sap->u.in6.sin6_addr, addr, in_len);
      sap->addrlen = sizeof(struct sockaddr_in6);
    }
    lua_settop(L, 1);
    return 1;
  };
}

/*
 * Arguments: sock_addr_udata, [path (string)]
 * Returns: sock_addr_udata | path (string)
 */
static int
sock_addr_file (lua_State *L)
{
  struct sock_addr *sap = checkudata(L, 1, SA_TYPENAME);

#ifndef _WIN32
  if (lua_gettop(L) == 1) {
    if (sap->u.addr.sa_family == AF_LOCAL) {
      lua_pushstring(L, sap->u.un.sun_path);
      return 1;
    }
  } else {
    size_t len;
    const char *path = luaL_checklstring(L, 2, &len);

    if (len < sizeof(sap->u.un.sun_path)) {
      sap->u.un.sun_family = AF_LOCAL;
      sap->addrlen = ++len;
      memcpy(sap->u.un.sun_path, path, len);

      lua_settop(L, 1);
      return 1;
    }
  };
#else
  (void) sap;
#endif
  return 0;
}

/*
 * Arguments: sock_addr_udata, sd_udata
 * Returns: [sock_addr_udata]
 */
static int
sock_addr_getsockname (lua_State *L)
{
  struct sock_addr *sap = checkudata(L, 1, SA_TYPENAME);
  sd_t sd = (sd_t) lua_unboxinteger(L, 2, SD_TYPENAME);

  sap->addrlen = SOCK_ADDR_LEN;
  if (!getsockname(sd, &sap->u.addr, &sap->addrlen)) {
    lua_settop(L, 1);
    return 1;
  }
  return sys_seterror(L, 0);
}

/*
 * Arguments: sock_addr_udata, sd_udata
 * Returns: [sock_addr_udata]
 */
static int
sock_addr_getpeername (lua_State *L)
{
  struct sock_addr *sap = checkudata(L, 1, SA_TYPENAME);
  sd_t sd = (sd_t) lua_unboxinteger(L, 2, SD_TYPENAME);

  sap->addrlen = SOCK_ADDR_LEN;
  if (!getpeername(sd, &sap->u.addr, &sap->addrlen)) {
    lua_settop(L, 1);
    return 1;
  }
  return sys_seterror(L, 0);
}

/*
 * Arguments: sock_addr_udata
 * Returns: string
 */
static int
sock_addr_tostring (lua_State *L)
{
  struct sock_addr *sap = checkudata(L, 1, SA_TYPENAME);

  lua_pushfstring(L, SA_TYPENAME " (%p)", sap);
  return 1;
}


#define ADDR_METHODS \
  {"getaddrinfo",	sock_getaddrinfo}, \
  {"getnameinfo",	sock_getnameinfo}, \
  {"getifaddrs",	sock_getifaddrs}, \
  {"inet_pton",		sock_inet_pton}, \
  {"inet_ntop",		sock_inet_ntop}, \
  {"addr",		sock_addr_new}

static luaL_Reg addr_meth[] = {
  {"inet",		sock_addr_inet},
  {"file",		sock_addr_file},
  {"getsockname",	sock_addr_getsockname},
  {"getpeername",	sock_addr_getpeername},
  {"__tostring",	sock_addr_tostring},
  {NULL, NULL}
};