2 Copyright 2015 Jo-Philipp Wich <jow@openwrt.org>
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
32 #include <netinet/ether.h>
33 #include <arpa/inet.h>
34 #include <netlink/msg.h>
35 #include <netlink/attr.h>
36 #include <netlink/socket.h>
37 #include <linux/rtnetlink.h>
39 #define LUCI_IP "luci.ip"
40 #define LUCI_IP_CIDR "luci.ip.cidr"
42 #define RTA_INT(x) (*(int *)RTA_DATA(x))
43 #define RTA_U32(x) (*(uint32_t *)RTA_DATA(x))
46 static struct nl_sock
*sock
= NULL
;
79 struct dump_filter
*filter
;
83 static int _cidr_new(lua_State
*L
, int index
, int family
);
85 static cidr_t
*L_checkcidr (lua_State
*L
, int index
, cidr_t
*p
)
87 if (lua_type(L
, index
) == LUA_TUSERDATA
)
88 return luaL_checkudata(L
, index
, LUCI_IP_CIDR
);
90 if (_cidr_new(L
, index
, p
? p
->family
: 0))
91 return lua_touserdata(L
, -1);
93 luaL_error(L
, "Invalid operand");
97 static bool parse_mask(int family
, const char *mask
, int *bits
)
103 if (family
== AF_INET
&& inet_pton(AF_INET
, mask
, &m
))
105 for (*bits
= 0, m
.s_addr
= ntohl(m
.s_addr
);
106 *bits
< 32 && (m
.s_addr
<< *bits
) & 0x80000000;
109 else if (family
== AF_INET6
&& inet_pton(AF_INET6
, mask
, &m6
))
112 *bits
< 128 && (m6
.s6_addr
[*bits
/ 8] << (*bits
% 8)) & 128;
117 *bits
= strtoul(mask
, &e
, 10);
119 if (e
== mask
|| *e
!= 0 || *bits
> ((family
== AF_INET
) ? 32 : 128))
126 static bool parse_cidr(const char *dest
, cidr_t
*pp
)
128 char *p
, *a
, buf
[INET6_ADDRSTRLEN
* 2 + 2];
131 strncpy(buf
, dest
, sizeof(buf
) - 1);
134 p
= strchr(buf
, '/');
139 if (!strncasecmp(buf
, "::ffff:", 7))
142 if (inet_pton(AF_INET
, a
, &pp
->addr
.v4
))
145 pp
->family
= AF_INET
;
146 pp
->len
= sizeof(struct in_addr
);
148 else if (inet_pton(AF_INET6
, a
, &pp
->addr
.v6
))
151 pp
->family
= AF_INET6
;
152 pp
->len
= sizeof(struct in6_addr
);
159 if (!parse_mask(pp
->family
, p
, &pp
->bits
))
170 static int L_getint(lua_State
*L
, int index
, const char *name
)
174 lua_getfield(L
, index
, name
);
176 if (lua_type(L
, -1) == LUA_TNUMBER
)
177 rv
= lua_tonumber(L
, -1);
184 static const char * L_getstr(lua_State
*L
, int index
, const char *name
)
186 const char *rv
= NULL
;
188 lua_getfield(L
, index
, name
);
190 if (lua_type(L
, -1) == LUA_TSTRING
)
191 rv
= lua_tostring(L
, -1);
198 static void L_setint(struct lua_State
*L
, const char *name
, uint32_t n
)
200 lua_pushinteger(L
, n
);
201 lua_setfield(L
, -2, name
);
204 static void L_setbool(struct lua_State
*L
, const char *name
, bool val
)
206 lua_pushboolean(L
, val
);
207 lua_setfield(L
, -2, name
);
210 static void L_setaddr(struct lua_State
*L
, const char *name
,
211 int family
, void *addr
, int bits
)
218 p
= lua_newuserdata(L
, sizeof(*p
));
223 if (family
== AF_INET
)
226 p
->bits
= (bits
< 0) ? 32 : bits
;
227 p
->len
= sizeof(p
->addr
.v4
);
228 p
->addr
.v4
= *(struct in_addr
*)addr
;
232 p
->family
= AF_INET6
;
233 p
->bits
= (bits
< 0) ? 128 : bits
;
234 p
->len
= sizeof(p
->addr
.v6
);
235 p
->addr
.v6
= *(struct in6_addr
*)addr
;
238 luaL_getmetatable(L
, LUCI_IP_CIDR
);
239 lua_setmetatable(L
, -2);
240 lua_setfield(L
, -2, name
);
243 static void L_setstr(struct lua_State
*L
, const char *name
, const char *val
)
245 lua_pushstring(L
, val
);
246 lua_setfield(L
, -2, name
);
249 static void L_setdev(struct lua_State
*L
, const char *name
,
254 if (if_indextoname(RTA_INT(attr
), buf
))
255 L_setstr(L
, name
, buf
);
258 static int L_checkbits(lua_State
*L
, int index
, cidr_t
*p
)
262 if (lua_gettop(L
) < index
|| lua_isnil(L
, index
))
266 else if (lua_type(L
, index
) == LUA_TNUMBER
)
268 bits
= lua_tointeger(L
, index
);
270 if (bits
< 0 || bits
> ((p
->family
== AF_INET
) ? 32 : 128))
271 return luaL_error(L
, "Invalid prefix size");
273 else if (lua_type(L
, index
) == LUA_TSTRING
)
275 if (!parse_mask(p
->family
, lua_tostring(L
, index
), &bits
))
276 return luaL_error(L
, "Invalid netmask format");
280 return luaL_error(L
, "Invalid data type");
286 static int _cidr_new(lua_State
*L
, int index
, int family
)
290 cidr_t cidr
= { }, *cidrp
;
292 if (lua_type(L
, index
) == LUA_TNUMBER
)
294 n
= htonl(lua_tointeger(L
, index
));
296 if (family
== AF_INET6
)
298 cidr
.family
= AF_INET6
;
300 cidr
.len
= sizeof(cidr
.addr
.v6
);
301 cidr
.addr
.v6
.s6_addr
[15] = n
;
302 cidr
.addr
.v6
.s6_addr
[14] = (n
>> 8);
303 cidr
.addr
.v6
.s6_addr
[13] = (n
>> 16);
304 cidr
.addr
.v6
.s6_addr
[12] = (n
>> 24);
308 cidr
.family
= AF_INET
;
310 cidr
.len
= sizeof(cidr
.addr
.v4
);
311 cidr
.addr
.v4
.s_addr
= n
;
316 addr
= luaL_checkstring(L
, index
);
318 if (!parse_cidr(addr
, &cidr
))
321 if (family
&& cidr
.family
!= family
)
325 if (!(cidrp
= lua_newuserdata(L
, sizeof(*cidrp
))))
329 luaL_getmetatable(L
, LUCI_IP_CIDR
);
330 lua_setmetatable(L
, -2);
334 static int cidr_new(lua_State
*L
)
336 return _cidr_new(L
, 1, 0);
339 static int cidr_ipv4(lua_State
*L
)
341 return _cidr_new(L
, 1, AF_INET
);
344 static int cidr_ipv6(lua_State
*L
)
346 return _cidr_new(L
, 1, AF_INET6
);
349 static int cidr_is4(lua_State
*L
)
351 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
353 lua_pushboolean(L
, p
->family
== AF_INET
);
357 static int cidr_is4rfc1918(lua_State
*L
)
359 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
360 uint32_t a
= htonl(p
->addr
.v4
.s_addr
);
362 lua_pushboolean(L
, (p
->family
== AF_INET
&&
363 ((a
>= 0x0A000000 && a
<= 0x0AFFFFFF) ||
364 (a
>= 0xAC100000 && a
<= 0xAC1FFFFF) ||
365 (a
>= 0xC0A80000 && a
<= 0xC0A8FFFF))));
370 static int cidr_is4linklocal(lua_State
*L
)
372 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
373 uint32_t a
= htonl(p
->addr
.v4
.s_addr
);
375 lua_pushboolean(L
, (p
->family
== AF_INET
&&
382 static int cidr_is6(lua_State
*L
)
384 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
386 lua_pushboolean(L
, p
->family
== AF_INET6
);
390 static int cidr_is6linklocal(lua_State
*L
)
392 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
394 lua_pushboolean(L
, (p
->family
== AF_INET6
&&
395 p
->addr
.v6
.s6_addr
[0] == 0xFE &&
396 p
->addr
.v6
.s6_addr
[1] >= 0x80 &&
397 p
->addr
.v6
.s6_addr
[1] <= 0xBF));
402 static int _cidr_cmp(lua_State
*L
)
404 cidr_t
*a
= L_checkcidr(L
, 1, NULL
);
405 cidr_t
*b
= L_checkcidr(L
, 2, NULL
);
407 if (a
->family
!= b
->family
)
408 return (a
->family
- b
->family
);
410 return memcmp(&a
->addr
.v6
, &b
->addr
.v6
, a
->len
);
413 static int cidr_lower(lua_State
*L
)
415 lua_pushboolean(L
, _cidr_cmp(L
) < 0);
419 static int cidr_higher(lua_State
*L
)
421 lua_pushboolean(L
, _cidr_cmp(L
) > 0);
425 static int cidr_equal(lua_State
*L
)
427 lua_pushboolean(L
, _cidr_cmp(L
) == 0);
431 static int cidr_lower_equal(lua_State
*L
)
433 lua_pushboolean(L
, _cidr_cmp(L
) <= 0);
437 static int cidr_prefix(lua_State
*L
)
439 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
440 int bits
= L_checkbits(L
, 2, p
);
443 lua_pushinteger(L
, p
->bits
);
447 static void _apply_mask(cidr_t
*p
, int bits
, bool inv
)
453 memset(&p
->addr
.v6
, inv
* 0xFF, p
->len
);
455 else if (p
->family
== AF_INET
&& bits
<= 32)
458 p
->addr
.v4
.s_addr
|= ntohl((1 << (32 - bits
)) - 1);
460 p
->addr
.v4
.s_addr
&= ntohl(~((1 << (32 - bits
)) - 1));
462 else if (p
->family
== AF_INET6
&& bits
<= 128)
464 for (i
= 0; i
< sizeof(p
->addr
.v6
.s6_addr
); i
++)
466 b
= (bits
> 8) ? 8 : bits
;
468 p
->addr
.v6
.s6_addr
[i
] |= ~((uint8_t)(0xFF << (8 - b
)));
470 p
->addr
.v6
.s6_addr
[i
] &= (uint8_t)(0xFF << (8 - b
));
476 static int cidr_network(lua_State
*L
)
478 cidr_t
*p1
= L_checkcidr(L
, 1, NULL
), *p2
;
479 int bits
= L_checkbits(L
, 2, p1
);
481 if (!(p2
= lua_newuserdata(L
, sizeof(*p2
))))
485 p2
->bits
= (p1
->family
== AF_INET
) ? 32 : 128;
486 _apply_mask(p2
, bits
, false);
488 luaL_getmetatable(L
, LUCI_IP_CIDR
);
489 lua_setmetatable(L
, -2);
493 static int cidr_host(lua_State
*L
)
495 cidr_t
*p1
= L_checkcidr(L
, 1, NULL
);
496 cidr_t
*p2
= lua_newuserdata(L
, sizeof(*p2
));
502 p2
->bits
= (p1
->family
== AF_INET
) ? 32 : 128;
504 luaL_getmetatable(L
, LUCI_IP_CIDR
);
505 lua_setmetatable(L
, -2);
509 static int cidr_mask(lua_State
*L
)
511 cidr_t
*p1
= L_checkcidr(L
, 1, NULL
), *p2
;
512 int bits
= L_checkbits(L
, 2, p1
);
514 if (!(p2
= lua_newuserdata(L
, sizeof(*p2
))))
517 p2
->bits
= (p1
->family
== AF_INET
) ? 32 : 128;
518 p2
->family
= p1
->family
;
520 memset(&p2
->addr
.v6
.s6_addr
, 0xFF, sizeof(p2
->addr
.v6
.s6_addr
));
521 _apply_mask(p2
, bits
, false);
523 luaL_getmetatable(L
, LUCI_IP_CIDR
);
524 lua_setmetatable(L
, -2);
528 static int cidr_broadcast(lua_State
*L
)
530 cidr_t
*p1
= L_checkcidr(L
, 1, NULL
);
532 int bits
= L_checkbits(L
, 2, p1
);
534 if (p1
->family
== AF_INET6
)
537 if (!(p2
= lua_newuserdata(L
, sizeof(*p2
))))
541 p2
->bits
= (p1
->family
== AF_INET
) ? 32 : 128;
542 _apply_mask(p2
, bits
, true);
544 luaL_getmetatable(L
, LUCI_IP_CIDR
);
545 lua_setmetatable(L
, -2);
549 static int cidr_contains(lua_State
*L
)
551 cidr_t
*p1
= L_checkcidr(L
, 1, NULL
);
552 cidr_t
*p2
= L_checkcidr(L
, 2, NULL
);
553 cidr_t a
= *p1
, b
= *p2
;
556 if (p1
->family
== p2
->family
&& p1
->bits
<= p2
->bits
)
558 _apply_mask(&a
, p1
->bits
, false);
559 _apply_mask(&b
, p1
->bits
, false);
561 rv
= !memcmp(&a
.addr
.v6
, &b
.addr
.v6
, a
.len
);
564 lua_pushboolean(L
, rv
);
568 #define S6_BYTE(a, i) \
569 (a)->addr.v6.s6_addr[sizeof((a)->addr.v6.s6_addr) - (i) - 1]
571 static int _cidr_add_sub(lua_State
*L
, bool add
)
573 cidr_t
*p1
= L_checkcidr(L
, 1, NULL
);
574 cidr_t
*p2
= L_checkcidr(L
, 2, p1
);
576 bool inplace
= lua_isboolean(L
, 3) ? lua_toboolean(L
, 3) : false;
581 if (p1
->family
== p2
->family
)
583 if (p1
->family
== AF_INET6
)
585 for (i
= 0, carry
= 0; i
< sizeof(r
); i
++)
589 S6_BYTE(&r
, i
) = S6_BYTE(p1
, i
) + S6_BYTE(p2
, i
) + carry
;
590 carry
= (S6_BYTE(p1
, i
) + S6_BYTE(p2
, i
) + carry
) / 256;
594 S6_BYTE(&r
, i
) = (S6_BYTE(p1
, i
) - S6_BYTE(p2
, i
) - carry
);
595 carry
= (S6_BYTE(p1
, i
) < (S6_BYTE(p2
, i
) + carry
));
599 /* would over/underflow */
602 memset(&r
.addr
.v6
, add
* 0xFF, sizeof(r
.addr
.v6
));
608 a
= ntohl(p1
->addr
.v4
.s_addr
);
609 b
= ntohl(p2
->addr
.v4
.s_addr
);
611 /* would over/underflow */
612 if ((add
&& (UINT_MAX
- a
) < b
) || (!add
&& a
< b
))
614 r
.addr
.v4
.s_addr
= add
* 0xFFFFFFFF;
619 r
.addr
.v4
.s_addr
= add
? htonl(a
+ b
) : htonl(a
- b
);
631 lua_pushboolean(L
, ok
);
635 if (!(p1
= lua_newuserdata(L
, sizeof(*p1
))))
640 luaL_getmetatable(L
, LUCI_IP_CIDR
);
641 lua_setmetatable(L
, -2);
645 static int cidr_add(lua_State
*L
)
647 return _cidr_add_sub(L
, true);
650 static int cidr_sub(lua_State
*L
)
652 return _cidr_add_sub(L
, false);
655 static int cidr_minhost(lua_State
*L
)
657 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
659 uint8_t i
, rest
, carry
;
661 _apply_mask(&r
, r
.bits
, false);
663 if (r
.family
== AF_INET6
&& r
.bits
< 128)
667 for (i
= 0, carry
= 1; i
< sizeof(r
.addr
.v6
.s6_addr
); i
++)
669 rest
= (S6_BYTE(&r
, i
) + carry
) > 255;
670 S6_BYTE(&r
, i
) += carry
;
674 else if (r
.family
== AF_INET
&& r
.bits
< 32)
677 r
.addr
.v4
.s_addr
= htonl(ntohl(r
.addr
.v4
.s_addr
) + 1);
680 if (!(p
= lua_newuserdata(L
, sizeof(*p
))))
685 luaL_getmetatable(L
, LUCI_IP_CIDR
);
686 lua_setmetatable(L
, -2);
690 static int cidr_maxhost(lua_State
*L
)
692 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
695 _apply_mask(&r
, r
.bits
, true);
697 if (r
.family
== AF_INET
&& r
.bits
< 32)
700 r
.addr
.v4
.s_addr
= htonl(ntohl(r
.addr
.v4
.s_addr
) - 1);
702 else if (r
.family
== AF_INET6
)
707 if (!(p
= lua_newuserdata(L
, sizeof(*p
))))
712 luaL_getmetatable(L
, LUCI_IP_CIDR
);
713 lua_setmetatable(L
, -2);
717 static int cidr_gc (lua_State
*L
)
722 static int cidr_tostring (lua_State
*L
)
724 char buf
[INET6_ADDRSTRLEN
];
725 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
727 if ((p
->family
== AF_INET
&& p
->bits
< 32) ||
728 (p
->family
== AF_INET6
&& p
->bits
< 128))
730 lua_pushfstring(L
, "%s/%d",
731 inet_ntop(p
->family
, &p
->addr
.v6
, buf
, sizeof(buf
)),
736 lua_pushstring(L
, inet_ntop(p
->family
, &p
->addr
.v6
, buf
, sizeof(buf
)));
746 static bool diff_prefix(int family
, void *addr
, int bits
, cidr_t
*p
)
754 if (!addr
|| p
->family
!= family
|| p
->bits
> bits
)
757 if (family
== AF_INET6
)
759 for (i
= 0, r
= p
->bits
; i
< sizeof(struct in6_addr
); i
++)
761 b
= r
? (0xFF << (8 - ((r
> 8) ? 8 : r
))) : 0;
763 if ((((struct in6_addr
*)addr
)->s6_addr
[i
] & b
) !=
764 (p
->addr
.v6
.s6_addr
[i
] & b
))
767 r
-= ((r
> 8) ? 8 : r
);
772 m
= p
->bits
? htonl(~((1 << (32 - p
->bits
)) - 1)) : 0;
774 if ((((struct in_addr
*)addr
)->s_addr
& m
) != (p
->addr
.v4
.s_addr
& m
))
778 return (p
->exact
&& p
->bits
!= bits
);
781 static int cb_dump_route(struct nl_msg
*msg
, void *arg
)
783 struct dump_state
*s
= arg
;
784 struct dump_filter
*f
= s
->filter
;
785 struct nlmsghdr
*hdr
= nlmsg_hdr(msg
);
786 struct rtmsg
*rt
= NLMSG_DATA(hdr
);
787 struct nlattr
*tb
[RTA_MAX
+1];
788 struct in6_addr
*src
, *dst
, *gw
, *from
, def
= { };
789 int iif
, oif
, bitlen
;
792 if (hdr
->nlmsg_type
!= RTM_NEWROUTE
||
793 (rt
->rtm_family
!= AF_INET
&& rt
->rtm_family
!= AF_INET6
))
796 nlmsg_parse(hdr
, sizeof(*rt
), tb
, RTA_MAX
, NULL
);
798 iif
= tb
[RTA_IIF
] ? RTA_INT(tb
[RTA_IIF
]) : 0;
799 oif
= tb
[RTA_OIF
] ? RTA_INT(tb
[RTA_OIF
]) : 0;
800 table
= tb
[RTA_TABLE
] ? RTA_U32(tb
[RTA_TABLE
]) : rt
->rtm_table
;
801 from
= tb
[RTA_SRC
] ? RTA_DATA(tb
[RTA_SRC
]) : NULL
;
802 src
= tb
[RTA_PREFSRC
] ? RTA_DATA(tb
[RTA_PREFSRC
]) : NULL
;
803 dst
= tb
[RTA_DST
] ? RTA_DATA(tb
[RTA_DST
]) : &def
;
804 gw
= tb
[RTA_GATEWAY
] ? RTA_DATA(tb
[RTA_GATEWAY
]) : NULL
;
806 bitlen
= (rt
->rtm_family
== AF_INET6
) ? 128 : 32;
808 if ((f
->type
&& rt
->rtm_type
!= f
->type
) ||
809 (f
->family
&& rt
->rtm_family
!= f
->family
) ||
810 (f
->proto
&& rt
->rtm_protocol
!= f
->proto
) ||
811 (f
->scope
&& rt
->rtm_scope
!= f
->scope
) ||
812 (f
->iif
&& iif
!= f
->iif
) ||
813 (f
->oif
&& oif
!= f
->oif
) ||
814 (f
->table
&& table
!= f
->table
) ||
815 diff_prefix(rt
->rtm_family
, from
, rt
->rtm_src_len
, &f
->from
) ||
816 diff_prefix(rt
->rtm_family
, dst
, rt
->rtm_dst_len
, &f
->dst
) ||
817 diff_prefix(rt
->rtm_family
, gw
, bitlen
, &f
->gw
) ||
818 diff_prefix(rt
->rtm_family
, src
, bitlen
, &f
->src
))
822 lua_pushvalue(s
->L
, 2);
826 L_setint(s
->L
, "type", rt
->rtm_type
);
827 L_setint(s
->L
, "family", (rt
->rtm_family
== AF_INET
) ? 4 : 6);
829 L_setaddr(s
->L
, "dest", rt
->rtm_family
, dst
, rt
->rtm_dst_len
);
832 L_setaddr(s
->L
, "gw", rt
->rtm_family
, gw
, -1);
835 L_setaddr(s
->L
, "from", rt
->rtm_family
, from
, rt
->rtm_src_len
);
838 L_setdev(s
->L
, "iif", tb
[RTA_IIF
]);
841 L_setdev(s
->L
, "dev", tb
[RTA_OIF
]);
843 L_setint(s
->L
, "table", table
);
844 L_setint(s
->L
, "proto", rt
->rtm_protocol
);
845 L_setint(s
->L
, "scope", rt
->rtm_scope
);
848 L_setaddr(s
->L
, "src", rt
->rtm_family
, src
, -1);
850 if (tb
[RTA_PRIORITY
])
851 L_setint(s
->L
, "metric", RTA_U32(tb
[RTA_PRIORITY
]));
853 if (rt
->rtm_family
== AF_INET6
&& tb
[RTA_CACHEINFO
])
855 struct rta_cacheinfo
*ci
= RTA_DATA(tb
[RTA_CACHEINFO
]);
860 L_setint(s
->L
, "expires", ci
->rta_expires
/ hz
);
862 if (ci
->rta_error
!= 0)
863 L_setint(s
->L
, "error", ci
->rta_error
);
870 lua_call(s
->L
, 1, 0);
871 else if (hdr
->nlmsg_flags
& NLM_F_MULTI
)
872 lua_rawseti(s
->L
, -2, s
->index
);
875 s
->pending
= !!(hdr
->nlmsg_flags
& NLM_F_MULTI
);
880 cb_done(struct nl_msg
*msg
, void *arg
)
882 struct dump_state
*s
= arg
;
888 cb_error(struct sockaddr_nl
*nla
, struct nlmsgerr
*err
, void *arg
)
890 struct dump_state
*s
= arg
;
895 static int _error(lua_State
*L
, int code
, const char *msg
)
898 lua_pushnumber(L
, code
? code
: errno
);
899 lua_pushstring(L
, msg
? msg
: strerror(errno
));
904 static int _route_dump(lua_State
*L
, struct dump_filter
*filter
)
906 int flags
= NLM_F_REQUEST
;
907 struct dump_state s
= {
911 .callback
= lua_isfunction(L
, 2),
916 hz
= sysconf(_SC_CLK_TCK
);
920 sock
= nl_socket_alloc();
922 return _error(L
, -1, "Out of memory");
924 if (nl_connect(sock
, NETLINK_ROUTE
))
925 return _error(L
, 0, NULL
);
929 struct nl_cb
*cb
= nl_cb_alloc(NL_CB_DEFAULT
);
931 .rtm_family
= filter
->family
,
932 .rtm_dst_len
= filter
->dst
.bits
,
933 .rtm_src_len
= filter
->src
.bits
939 msg
= nlmsg_alloc_simple(RTM_GETROUTE
, flags
);
943 nlmsg_append(msg
, &rtm
, sizeof(rtm
), 0);
946 nla_put(msg
, RTA_DST
, filter
->dst
.len
, &filter
->dst
.addr
.v6
);
948 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, cb_dump_route
, &s
);
949 nl_cb_set(cb
, NL_CB_FINISH
, NL_CB_CUSTOM
, cb_done
, &s
);
950 nl_cb_err(cb
, NL_CB_CUSTOM
, cb_error
, &s
);
952 nl_send_auto_complete(sock
, msg
);
954 if (!filter
->get
&& !s
.callback
)
957 while (s
.pending
> 0)
958 nl_recvmsgs(sock
, cb
);
964 return (s
.index
> 0 && s
.callback
== 0);
967 static int route_get(lua_State
*L
)
969 struct dump_filter filter
= { .get
= true };
970 const char *dest
= luaL_checkstring(L
, 1);
972 if (!parse_cidr(dest
, &filter
.dst
))
973 return _error(L
, -1, "Invalid destination");
975 filter
.family
= filter
.dst
.family
;
977 return _route_dump(L
, &filter
);
980 static int route_dump(lua_State
*L
)
984 struct dump_filter filter
= { };
986 if (lua_type(L
, 1) == LUA_TTABLE
)
988 filter
.family
= L_getint(L
, 1, "family");
990 if (filter
.family
== 4)
991 filter
.family
= AF_INET
;
992 else if (filter
.family
== 6)
993 filter
.family
= AF_INET6
;
997 if ((s
= L_getstr(L
, 1, "iif")) != NULL
)
998 filter
.iif
= if_nametoindex(s
);
1000 if ((s
= L_getstr(L
, 1, "oif")) != NULL
)
1001 filter
.oif
= if_nametoindex(s
);
1003 filter
.type
= L_getint(L
, 1, "type");
1004 filter
.scope
= L_getint(L
, 1, "scope");
1005 filter
.proto
= L_getint(L
, 1, "proto");
1006 filter
.table
= L_getint(L
, 1, "table");
1008 if ((s
= L_getstr(L
, 1, "gw")) != NULL
&& parse_cidr(s
, &p
))
1011 if ((s
= L_getstr(L
, 1, "from")) != NULL
&& parse_cidr(s
, &p
))
1014 if ((s
= L_getstr(L
, 1, "src")) != NULL
&& parse_cidr(s
, &p
))
1017 if ((s
= L_getstr(L
, 1, "dest")) != NULL
&& parse_cidr(s
, &p
))
1020 if ((s
= L_getstr(L
, 1, "from_exact")) != NULL
&& parse_cidr(s
, &p
))
1021 filter
.from
= p
, filter
.from
.exact
= true;
1023 if ((s
= L_getstr(L
, 1, "dest_exact")) != NULL
&& parse_cidr(s
, &p
))
1024 filter
.dst
= p
, filter
.dst
.exact
= true;
1027 return _route_dump(L
, &filter
);
1031 static int cb_dump_neigh(struct nl_msg
*msg
, void *arg
)
1034 struct ether_addr
*addr
;
1035 struct dump_state
*s
= arg
;
1036 struct dump_filter
*f
= s
->filter
;
1037 struct nlmsghdr
*hdr
= nlmsg_hdr(msg
);
1038 struct ndmsg
*nd
= NLMSG_DATA(hdr
);
1039 struct nlattr
*tb
[NDA_MAX
+1];
1041 if (hdr
->nlmsg_type
!= RTM_NEWNEIGH
||
1042 (nd
->ndm_family
!= AF_INET
&& nd
->ndm_family
!= AF_INET6
))
1045 if ((f
->family
&& nd
->ndm_family
!= f
->family
) ||
1046 (f
->iif
&& nd
->ndm_ifindex
!= f
->iif
) ||
1047 (f
->type
&& !(f
->type
& nd
->ndm_state
)))
1050 nlmsg_parse(hdr
, sizeof(*nd
), tb
, NDA_MAX
, NULL
);
1053 lua_pushvalue(s
->L
, 2);
1057 L_setint(s
->L
, "family", (nd
->ndm_family
== AF_INET
) ? 4 : 6);
1058 L_setstr(s
->L
, "dev", if_indextoname(nd
->ndm_ifindex
, buf
));
1060 L_setbool(s
->L
, "router", (nd
->ndm_flags
& NTF_ROUTER
));
1061 L_setbool(s
->L
, "proxy", (nd
->ndm_flags
& NTF_PROXY
));
1063 L_setbool(s
->L
, "incomplete", (nd
->ndm_state
& NUD_INCOMPLETE
));
1064 L_setbool(s
->L
, "reachable", (nd
->ndm_state
& NUD_REACHABLE
));
1065 L_setbool(s
->L
, "stale", (nd
->ndm_state
& NUD_STALE
));
1066 L_setbool(s
->L
, "delay", (nd
->ndm_state
& NUD_DELAY
));
1067 L_setbool(s
->L
, "probe", (nd
->ndm_state
& NUD_PROBE
));
1068 L_setbool(s
->L
, "failed", (nd
->ndm_state
& NUD_FAILED
));
1069 L_setbool(s
->L
, "noarp", (nd
->ndm_state
& NUD_NOARP
));
1070 L_setbool(s
->L
, "permanent", (nd
->ndm_state
& NUD_PERMANENT
));
1073 L_setaddr(s
->L
, "dest", nd
->ndm_family
, RTA_DATA(tb
[NDA_DST
]), -1);
1077 addr
= RTA_DATA(tb
[NDA_LLADDR
]);
1078 snprintf(buf
, sizeof(buf
), "%02x:%02x:%02x:%02x:%02x:%02x",
1079 addr
->ether_addr_octet
[0], addr
->ether_addr_octet
[1],
1080 addr
->ether_addr_octet
[2], addr
->ether_addr_octet
[3],
1081 addr
->ether_addr_octet
[4], addr
->ether_addr_octet
[5]);
1083 lua_pushstring(s
->L
, buf
);
1084 lua_setfield(s
->L
, -2, "mac");
1090 lua_call(s
->L
, 1, 0);
1091 else if (hdr
->nlmsg_flags
& NLM_F_MULTI
)
1092 lua_rawseti(s
->L
, -2, s
->index
);
1095 s
->pending
= !!(hdr
->nlmsg_flags
& NLM_F_MULTI
);
1099 static int neighbor_dump(lua_State
*L
)
1102 struct dump_filter filter
= {
1103 .type
= 0xFF & ~NUD_NOARP
1105 struct dump_state st
= {
1106 .callback
= lua_isfunction(L
, 2),
1112 if (lua_type(L
, 1) == LUA_TTABLE
)
1114 filter
.family
= L_getint(L
, 1, "family");
1116 if (filter
.family
== 4)
1117 filter
.family
= AF_INET
;
1118 else if (filter
.family
== 6)
1119 filter
.family
= AF_INET6
;
1123 if ((s
= L_getstr(L
, 1, "dev")) != NULL
)
1124 filter
.iif
= if_nametoindex(s
);
1129 sock
= nl_socket_alloc();
1131 return _error(L
, -1, "Out of memory");
1133 if (nl_connect(sock
, NETLINK_ROUTE
))
1134 return _error(L
, 0, NULL
);
1138 struct nl_cb
*cb
= nl_cb_alloc(NL_CB_DEFAULT
);
1139 struct ndmsg ndm
= {
1140 .ndm_family
= filter
.family
1143 msg
= nlmsg_alloc_simple(RTM_GETNEIGH
, NLM_F_REQUEST
| NLM_F_DUMP
);
1147 nlmsg_append(msg
, &ndm
, sizeof(ndm
), 0);
1149 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, cb_dump_neigh
, &st
);
1150 nl_cb_set(cb
, NL_CB_FINISH
, NL_CB_CUSTOM
, cb_done
, &st
);
1151 nl_cb_err(cb
, NL_CB_CUSTOM
, cb_error
, &st
);
1153 nl_send_auto_complete(sock
, msg
);
1158 while (st
.pending
> 0)
1159 nl_recvmsgs(sock
, cb
);
1165 return (st
.index
> 0 && st
.callback
== 0);
1169 static const luaL_reg ip_methods
[] = {
1170 { "new", cidr_new
},
1171 { "IPv4", cidr_ipv4
},
1172 { "IPv6", cidr_ipv6
},
1174 { "route", route_get
},
1175 { "routes", route_dump
},
1177 { "neighbors", neighbor_dump
},
1182 static const luaL_reg ip_cidr_methods
[] = {
1183 { "is4", cidr_is4
},
1184 { "is4rfc1918", cidr_is4rfc1918
},
1185 { "is4linklocal", cidr_is4linklocal
},
1186 { "is6", cidr_is6
},
1187 { "is6linklocal", cidr_is6linklocal
},
1188 { "lower", cidr_lower
},
1189 { "higher", cidr_higher
},
1190 { "equal", cidr_equal
},
1191 { "prefix", cidr_prefix
},
1192 { "network", cidr_network
},
1193 { "host", cidr_host
},
1194 { "mask", cidr_mask
},
1195 { "broadcast", cidr_broadcast
},
1196 { "contains", cidr_contains
},
1197 { "add", cidr_add
},
1198 { "sub", cidr_sub
},
1199 { "minhost", cidr_minhost
},
1200 { "maxhost", cidr_maxhost
},
1201 { "string", cidr_tostring
},
1203 { "__lt", cidr_lower
},
1204 { "__le", cidr_lower_equal
},
1205 { "__eq", cidr_equal
},
1206 { "__add", cidr_add
},
1207 { "__sub", cidr_sub
},
1208 { "__gc", cidr_gc
},
1209 { "__tostring", cidr_tostring
},
1214 int luaopen_luci_ip(lua_State
*L
)
1216 luaL_register(L
, LUCI_IP
, ip_methods
);
1218 luaL_newmetatable(L
, LUCI_IP_CIDR
);
1219 luaL_register(L
, NULL
, ip_cidr_methods
);
1220 lua_pushvalue(L
, -1);
1221 lua_setfield(L
, -2, "__index");