X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fluci.git;a=blobdiff_plain;f=libs%2Fluci-lib-ip%2Fsrc%2Fip.c;h=595ac8c3a50c5311dc9c8d521ab3920a5ad56452;hp=b72b6c05caad2ad3c2eb50818232bee67a388a22;hb=65f0135491112341fc3af8559537eab85aa47e18;hpb=e85698638f87403e756e78e0b9019c5fc3af415d diff --git a/libs/luci-lib-ip/src/ip.c b/libs/luci-lib-ip/src/ip.c index b72b6c05c..595ac8c3a 100644 --- a/libs/luci-lib-ip/src/ip.c +++ b/libs/luci-lib-ip/src/ip.c @@ -81,14 +81,14 @@ struct dump_state { }; -static int _cidr_new(lua_State *L, int index, int family); +static int _cidr_new(lua_State *L, int index, int family, bool mask); static cidr_t *L_checkcidr (lua_State *L, int index, cidr_t *p) { if (lua_type(L, index) == LUA_TUSERDATA) return luaL_checkudata(L, index, LUCI_IP_CIDR); - if (_cidr_new(L, index, p ? p->family : 0)) + if (_cidr_new(L, index, p ? p->family : 0, false)) return lua_touserdata(L, -1); luaL_error(L, "Invalid operand"); @@ -284,7 +284,7 @@ static int L_checkbits(lua_State *L, int index, cidr_t *p) return bits; } -static int _cidr_new(lua_State *L, int index, int family) +static int _cidr_new(lua_State *L, int index, int family, bool mask) { uint32_t n; const char *addr; @@ -299,10 +299,10 @@ static int _cidr_new(lua_State *L, int index, int family) cidr.family = AF_INET6; cidr.bits = 128; cidr.len = sizeof(cidr.addr.v6); - cidr.addr.v6.s6_addr[15] = n; - cidr.addr.v6.s6_addr[14] = (n >> 8); - cidr.addr.v6.s6_addr[13] = (n >> 16); - cidr.addr.v6.s6_addr[12] = (n >> 24); + cidr.addr.v6.s6_addr[12] = n; + cidr.addr.v6.s6_addr[13] = (n >> 8); + cidr.addr.v6.s6_addr[14] = (n >> 16); + cidr.addr.v6.s6_addr[15] = (n >> 24); } else { @@ -321,6 +321,9 @@ static int _cidr_new(lua_State *L, int index, int family) if (family && cidr.family != family) return 0; + + if (mask) + cidr.bits = L_checkbits(L, index + 1, &cidr); } if (!(cidrp = lua_newuserdata(L, sizeof(*cidrp)))) @@ -334,17 +337,17 @@ static int _cidr_new(lua_State *L, int index, int family) static int cidr_new(lua_State *L) { - return _cidr_new(L, 1, 0); + return _cidr_new(L, 1, 0, true); } static int cidr_ipv4(lua_State *L) { - return _cidr_new(L, 1, AF_INET); + return _cidr_new(L, 1, AF_INET, true); } static int cidr_ipv6(lua_State *L) { - return _cidr_new(L, 1, AF_INET6); + return _cidr_new(L, 1, AF_INET6, true); } static int cidr_is4(lua_State *L) @@ -583,7 +586,7 @@ static int _cidr_add_sub(lua_State *L, bool add) { if (p1->family == AF_INET6) { - for (i = 0, carry = 0; i < sizeof(r); i++) + for (i = 0, carry = 0; i < sizeof(r.addr.v6.s6_addr); i++) { if (add) { @@ -962,7 +965,7 @@ static int _route_dump(lua_State *L, struct dump_filter *filter) out: nl_cb_put(cb); - return (s.index > 0 && s.callback == 0); + return (s.callback == 0); } static int route_get(lua_State *L) @@ -1120,7 +1123,7 @@ out: static int neighbor_dump(lua_State *L) { - cidr_t p; + cidr_t p = { }; const char *s; struct ether_addr *mac; struct dump_filter filter = { .type = 0xFF & ~NUD_NOARP }; @@ -1191,7 +1194,97 @@ static int neighbor_dump(lua_State *L) out: nl_cb_put(cb); - return (st.index > 0 && st.callback == 0); + return (st.callback == 0); +} + + +static int cb_dump_link(struct nl_msg *msg, void *arg) +{ + char *p, *addr, buf[48]; + struct dump_state *s = arg; + struct nlmsghdr *hdr = nlmsg_hdr(msg); + struct ifinfomsg *ifm = NLMSG_DATA(hdr); + struct nlattr *tb[IFLA_MAX+1]; + int i, len; + + if (hdr->nlmsg_type != RTM_NEWLINK) + return NL_SKIP; + + nlmsg_parse(hdr, sizeof(*ifm), tb, IFLA_MAX, NULL); + + L_setbool(s->L, "up", (ifm->ifi_flags & IFF_RUNNING)); + L_setint(s->L, "type", ifm->ifi_type); + L_setstr(s->L, "name", if_indextoname(ifm->ifi_index, buf)); + + if (tb[IFLA_MTU]) + L_setint(s->L, "mtu", RTA_U32(tb[IFLA_MTU])); + + if (tb[IFLA_TXQLEN]) + L_setint(s->L, "qlen", RTA_U32(tb[IFLA_TXQLEN])); + + if (tb[IFLA_MASTER]) + L_setdev(s->L, "master", tb[IFLA_MASTER]); + + if (tb[IFLA_ADDRESS]) + { + len = nla_len(tb[IFLA_ADDRESS]); + addr = nla_get_string(tb[IFLA_ADDRESS]); + + if ((len * 3) <= sizeof(buf)) + { + for (p = buf, i = 0; i < len; i++) + p += sprintf(p, "%s%02x", (i ? ":" : ""), (uint8_t)*addr++); + + L_setstr(s->L, "mac", buf); + } + } + + s->pending = 0; + return NL_SKIP; +} + +static int link_get(lua_State *L) +{ + const char *dev = luaL_checkstring(L, 1); + struct dump_state st = { + .pending = 1, + .L = L + }; + + if (!sock) + { + sock = nl_socket_alloc(); + if (!sock) + return _error(L, -1, "Out of memory"); + + if (nl_connect(sock, NETLINK_ROUTE)) + return _error(L, 0, NULL); + } + + struct nl_msg *msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_REQUEST); + struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT); + struct ifinfomsg ifm = { .ifi_index = if_nametoindex(dev) }; + + if (!msg || !cb) + return 0; + + nlmsg_append(msg, &ifm, sizeof(ifm), 0); + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_dump_link, &st); + nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_done, &st); + nl_cb_err(cb, NL_CB_CUSTOM, cb_error, &st); + + lua_newtable(L); + + nl_send_auto_complete(sock, msg); + + while (st.pending > 0) + nl_recvmsgs(sock, cb); + + nlmsg_free(msg); + nl_cb_put(cb); + + return 1; } @@ -1205,6 +1298,8 @@ static const luaL_reg ip_methods[] = { { "neighbors", neighbor_dump }, + { "link", link_get }, + { } };