2 Copyright 2015-2018 Jo-Philipp Wich <jo@mein.io>
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 ((f) == AF_INET ? 32 : \
47 ((f) == AF_INET6 ? 128 : \
48 ((f) == AF_PACKET ? 48 : 0)))
51 ((f) == AF_INET ? 4 : \
52 ((f) == AF_INET6 ? 16 : \
53 ((f) == AF_PACKET ? 6 : 0)))
56 static struct nl_sock
*sock
= NULL
;
62 struct ether_addr mac
;
83 struct ether_addr mac
;
93 struct dump_filter
*filter
;
97 static int _cidr_new(lua_State
*L
, int index
, int family
, bool mask
);
99 static cidr_t
*L_checkcidr (lua_State
*L
, int index
, cidr_t
*p
)
101 if (lua_type(L
, index
) == LUA_TUSERDATA
)
102 return luaL_checkudata(L
, index
, LUCI_IP_CIDR
);
104 if (_cidr_new(L
, index
, p
? p
->family
: 0, false))
105 return lua_touserdata(L
, -1);
107 luaL_error(L
, "Invalid operand");
111 static bool parse_mac(const char *mac
, struct ether_addr
*ea
)
117 for (i
= 0; i
< 6; i
++)
121 if (sep
== 0 && (mac
[0] == ':' || mac
[0] == '-'))
124 if (sep
== 0 || mac
[0] != sep
)
130 n
= strtoul(mac
, &e
, 16);
136 ea
->ether_addr_octet
[i
] = n
;
145 static bool parse_mask(int family
, const char *mask
, int16_t *bits
)
151 struct ether_addr mac
;
155 if (family
== AF_INET
&& inet_pton(AF_INET
, mask
, &m
.v4
))
157 for (*bits
= 0, m
.v4
.s_addr
= ntohl(m
.v4
.s_addr
);
158 *bits
< AF_BITS(AF_INET
) && (m
.v4
.s_addr
<< *bits
) & 0x80000000;
161 else if ((family
== AF_INET6
&& inet_pton(AF_INET6
, mask
, &m
.v6
)) ||
162 (family
== AF_PACKET
&& parse_mac(mask
, &m
.mac
)))
165 *bits
< AF_BITS(family
) && (m
.u8
[*bits
/ 8] << (*bits
% 8)) & 128;
170 *bits
= strtoul(mask
, &e
, 10);
172 if (e
== mask
|| *e
!= 0 || *bits
> AF_BITS(family
))
179 static bool parse_cidr(const char *dest
, cidr_t
*pp
)
181 char *p
, *s
, buf
[INET6_ADDRSTRLEN
* 2 + 2];
183 strncpy(buf
, dest
, sizeof(buf
) - 1);
185 p
= strchr(buf
, '/');
190 s
= strchr(buf
, '%');
195 if (inet_pton(AF_INET
, buf
, &pp
->addr
.v4
))
196 pp
->family
= AF_INET
;
197 else if (inet_pton(AF_INET6
, buf
, &pp
->addr
.v6
))
198 pp
->family
= AF_INET6
;
199 else if (parse_mac(buf
, &pp
->addr
.mac
))
200 pp
->family
= AF_PACKET
;
206 if (pp
->family
!= AF_INET6
)
209 if (!(pp
->addr
.v6
.s6_addr
[0] == 0xFE &&
210 pp
->addr
.v6
.s6_addr
[1] >= 0x80 &&
211 pp
->addr
.v6
.s6_addr
[2] <= 0xBF))
214 pp
->scope
= if_nametoindex(s
);
225 if (!parse_mask(pp
->family
, p
, &pp
->bits
))
230 pp
->bits
= AF_BITS(pp
->family
);
236 static int format_cidr(lua_State
*L
, cidr_t
*p
)
238 char *s
, buf
[INET6_ADDRSTRLEN
+ 1 + IF_NAMESIZE
+ 4];
240 if (p
->family
== AF_PACKET
)
242 snprintf(buf
, sizeof(buf
), "%02X:%02X:%02X:%02X:%02X:%02X",
243 p
->addr
.mac
.ether_addr_octet
[0],
244 p
->addr
.mac
.ether_addr_octet
[1],
245 p
->addr
.mac
.ether_addr_octet
[2],
246 p
->addr
.mac
.ether_addr_octet
[3],
247 p
->addr
.mac
.ether_addr_octet
[4],
248 p
->addr
.mac
.ether_addr_octet
[5]);
250 if (p
->bits
< AF_BITS(AF_PACKET
))
251 lua_pushfstring(L
, "%s/%d", buf
, p
->bits
);
253 lua_pushstring(L
, buf
);
257 inet_ntop(p
->family
, &p
->addr
.v6
, buf
, sizeof(buf
));
259 s
= buf
+ strlen(buf
);
261 if (p
->scope
!= 0 && if_indextoname(p
->scope
, s
+ 1) != NULL
) {
266 if (p
->bits
< AF_BITS(p
->family
))
267 s
+= sprintf(s
, "/%d", p
->bits
);
269 lua_pushstring(L
, buf
);
275 static int L_getint(lua_State
*L
, int index
, const char *name
)
279 lua_getfield(L
, index
, name
);
281 if (lua_type(L
, -1) == LUA_TNUMBER
)
282 rv
= lua_tonumber(L
, -1);
289 static const char * L_getstr(lua_State
*L
, int index
, const char *name
)
291 const char *rv
= NULL
;
293 lua_getfield(L
, index
, name
);
295 if (lua_type(L
, -1) == LUA_TSTRING
)
296 rv
= lua_tostring(L
, -1);
303 static void L_setint(struct lua_State
*L
, const char *name
, uint32_t n
)
305 lua_pushinteger(L
, n
);
306 lua_setfield(L
, -2, name
);
309 static void L_setbool(struct lua_State
*L
, const char *name
, bool val
)
311 lua_pushboolean(L
, val
);
312 lua_setfield(L
, -2, name
);
315 static void L_setaddr(struct lua_State
*L
, const char *name
,
316 int family
, void *addr
, int bits
)
323 p
= lua_newuserdata(L
, sizeof(*p
));
328 if (family
== AF_INET
)
331 p
->bits
= (bits
< 0) ? AF_BITS(AF_INET
) : bits
;
332 p
->addr
.v4
= *(struct in_addr
*)addr
;
335 else if (family
== AF_INET6
)
337 p
->family
= AF_INET6
;
338 p
->bits
= (bits
< 0) ? AF_BITS(AF_INET6
) : bits
;
339 p
->addr
.v6
= *(struct in6_addr
*)addr
;
344 p
->family
= AF_PACKET
;
345 p
->bits
= (bits
< 0) ? AF_BITS(AF_PACKET
) : bits
;
346 p
->addr
.mac
= *(struct ether_addr
*)addr
;
350 luaL_getmetatable(L
, LUCI_IP_CIDR
);
351 lua_setmetatable(L
, -2);
352 lua_setfield(L
, -2, name
);
355 static void L_setstr(struct lua_State
*L
, const char *name
, const char *val
)
357 lua_pushstring(L
, val
);
358 lua_setfield(L
, -2, name
);
361 static void L_setdev(struct lua_State
*L
, const char *name
,
366 if (if_indextoname(RTA_INT(attr
), buf
))
367 L_setstr(L
, name
, buf
);
370 static int L_checkbits(lua_State
*L
, int index
, cidr_t
*p
)
375 if (lua_gettop(L
) < index
|| lua_isnil(L
, index
))
379 else if (lua_type(L
, index
) == LUA_TNUMBER
)
381 bits
= lua_tointeger(L
, index
);
383 if (bits
< 0 || bits
> AF_BITS(p
->family
))
384 return luaL_error(L
, "Invalid prefix size");
386 else if (lua_type(L
, index
) == LUA_TSTRING
)
388 if (!parse_mask(p
->family
, lua_tostring(L
, index
), &s16
))
389 return luaL_error(L
, "Invalid netmask format");
395 return luaL_error(L
, "Invalid data type");
401 static int _cidr_new(lua_State
*L
, int index
, int family
, bool mask
)
405 cidr_t cidr
= { }, *cidrp
;
407 if (lua_type(L
, index
) == LUA_TNUMBER
)
409 n
= lua_tointeger(L
, index
);
411 if (family
== AF_INET6
)
413 cidr
.family
= AF_INET6
;
414 cidr
.addr
.v6
.s6_addr
[12] = n
/ 0x1000000;
415 cidr
.addr
.v6
.s6_addr
[13] = n
% 0x1000000 / 0x10000;
416 cidr
.addr
.v6
.s6_addr
[14] = n
% 0x10000 / 0x100;
417 cidr
.addr
.v6
.s6_addr
[15] = n
% 0x100;
419 else if (family
== AF_INET
)
421 cidr
.family
= AF_INET
;
422 cidr
.addr
.v4
.s_addr
= htonl(n
);
426 cidr
.family
= AF_PACKET
;
427 cidr
.addr
.mac
.ether_addr_octet
[2] = n
/ 0x1000000;
428 cidr
.addr
.mac
.ether_addr_octet
[3] = n
% 0x1000000 / 0x10000;
429 cidr
.addr
.mac
.ether_addr_octet
[4] = n
% 0x10000 / 0x100;
430 cidr
.addr
.mac
.ether_addr_octet
[5] = n
% 0x100;
433 cidr
.bits
= AF_BITS(cidr
.family
);
437 addr
= luaL_checkstring(L
, index
);
439 if (!parse_cidr(addr
, &cidr
))
442 if (family
&& cidr
.family
!= family
)
446 cidr
.bits
= L_checkbits(L
, index
+ 1, &cidr
);
449 if (!(cidrp
= lua_newuserdata(L
, sizeof(*cidrp
))))
453 luaL_getmetatable(L
, LUCI_IP_CIDR
);
454 lua_setmetatable(L
, -2);
458 static int cidr_new(lua_State
*L
)
460 return _cidr_new(L
, 1, 0, true);
463 static int cidr_ipv4(lua_State
*L
)
465 return _cidr_new(L
, 1, AF_INET
, true);
468 static int cidr_ipv6(lua_State
*L
)
470 return _cidr_new(L
, 1, AF_INET6
, true);
473 static int cidr_mac(lua_State
*L
)
475 return _cidr_new(L
, 1, AF_PACKET
, true);
478 static int cidr_check(lua_State
*L
, int family
)
480 cidr_t cidr
= { }, *cidrp
;
483 if (lua_type(L
, 1) == LUA_TSTRING
)
485 addr
= lua_tostring(L
, 1);
487 if (addr
&& parse_cidr(addr
, &cidr
) && cidr
.family
== family
)
488 return format_cidr(L
, &cidr
);
492 cidrp
= lua_touserdata(L
, 1);
497 if (!lua_getmetatable(L
, 1))
500 lua_getfield(L
, LUA_REGISTRYINDEX
, LUCI_IP_CIDR
);
502 if (!lua_rawequal(L
, -1, -2))
507 if (cidrp
!= NULL
&& cidrp
->family
== family
)
508 return format_cidr(L
, cidrp
);
514 static int cidr_checkip4(lua_State
*L
)
516 return cidr_check(L
, AF_INET
);
519 static int cidr_checkip6(lua_State
*L
)
521 return cidr_check(L
, AF_INET6
);
524 static int cidr_checkmac(lua_State
*L
)
526 return cidr_check(L
, AF_PACKET
);
529 static int cidr_is4(lua_State
*L
)
531 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
533 lua_pushboolean(L
, p
->family
== AF_INET
);
537 static int cidr_is4rfc1918(lua_State
*L
)
539 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
540 uint32_t a
= htonl(p
->addr
.v4
.s_addr
);
542 lua_pushboolean(L
, (p
->family
== AF_INET
&&
543 ((a
>= 0x0A000000 && a
<= 0x0AFFFFFF) ||
544 (a
>= 0xAC100000 && a
<= 0xAC1FFFFF) ||
545 (a
>= 0xC0A80000 && a
<= 0xC0A8FFFF))));
550 static int cidr_is4linklocal(lua_State
*L
)
552 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
553 uint32_t a
= htonl(p
->addr
.v4
.s_addr
);
555 lua_pushboolean(L
, (p
->family
== AF_INET
&&
562 static bool _is_mapped4(cidr_t
*p
)
564 return (p
->family
== AF_INET6
&&
565 p
->addr
.v6
.s6_addr
[0] == 0 &&
566 p
->addr
.v6
.s6_addr
[1] == 0 &&
567 p
->addr
.v6
.s6_addr
[2] == 0 &&
568 p
->addr
.v6
.s6_addr
[3] == 0 &&
569 p
->addr
.v6
.s6_addr
[4] == 0 &&
570 p
->addr
.v6
.s6_addr
[5] == 0 &&
571 p
->addr
.v6
.s6_addr
[6] == 0 &&
572 p
->addr
.v6
.s6_addr
[7] == 0 &&
573 p
->addr
.v6
.s6_addr
[8] == 0 &&
574 p
->addr
.v6
.s6_addr
[9] == 0 &&
575 p
->addr
.v6
.s6_addr
[10] == 0xFF &&
576 p
->addr
.v6
.s6_addr
[11] == 0xFF);
579 static int cidr_is6mapped4(lua_State
*L
)
581 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
583 lua_pushboolean(L
, _is_mapped4(p
));
587 static int cidr_is6(lua_State
*L
)
589 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
591 lua_pushboolean(L
, p
->family
== AF_INET6
);
595 static int cidr_is6linklocal(lua_State
*L
)
597 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
599 lua_pushboolean(L
, (p
->family
== AF_INET6
&&
600 p
->addr
.v6
.s6_addr
[0] == 0xFE &&
601 p
->addr
.v6
.s6_addr
[1] >= 0x80 &&
602 p
->addr
.v6
.s6_addr
[1] <= 0xBF));
607 static int cidr_ismac(lua_State
*L
)
609 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
611 lua_pushboolean(L
, p
->family
== AF_PACKET
);
615 static int cidr_ismacmcast(lua_State
*L
)
617 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
619 lua_pushboolean(L
, (p
->family
== AF_PACKET
&&
620 (p
->addr
.mac
.ether_addr_octet
[0] & 0x1)));
625 static int cidr_ismaclocal(lua_State
*L
)
627 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
629 lua_pushboolean(L
, (p
->family
== AF_PACKET
&&
630 (p
->addr
.mac
.ether_addr_octet
[0] & 0x2)));
635 static int _cidr_cmp(lua_State
*L
)
637 cidr_t
*a
= L_checkcidr(L
, 1, NULL
);
638 cidr_t
*b
= L_checkcidr(L
, 2, NULL
);
640 if (a
->family
!= b
->family
)
641 return (a
->family
- b
->family
);
643 return memcmp(&a
->addr
.v6
, &b
->addr
.v6
, AF_BYTES(a
->family
));
646 static int cidr_lower(lua_State
*L
)
648 lua_pushboolean(L
, _cidr_cmp(L
) < 0);
652 static int cidr_higher(lua_State
*L
)
654 lua_pushboolean(L
, _cidr_cmp(L
) > 0);
658 static int cidr_equal(lua_State
*L
)
660 lua_pushboolean(L
, _cidr_cmp(L
) == 0);
664 static int cidr_lower_equal(lua_State
*L
)
666 lua_pushboolean(L
, _cidr_cmp(L
) <= 0);
670 static int cidr_prefix(lua_State
*L
)
672 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
673 int bits
= L_checkbits(L
, 2, p
);
676 lua_pushinteger(L
, p
->bits
);
680 static void _apply_mask(cidr_t
*p
, int bits
, bool inv
)
686 memset(&p
->addr
.u8
, inv
* 0xFF, AF_BYTES(p
->family
));
688 else if (p
->family
== AF_INET
&& bits
<= AF_BITS(AF_INET
))
691 p
->addr
.v4
.s_addr
|= ntohl((1 << (AF_BITS(AF_INET
) - bits
)) - 1);
693 p
->addr
.v4
.s_addr
&= ntohl(~((1 << (AF_BITS(AF_INET
) - bits
)) - 1));
695 else if (bits
<= AF_BITS(p
->family
))
697 for (i
= 0; i
< AF_BYTES(p
->family
); i
++)
699 b
= (bits
> 8) ? 8 : bits
;
701 p
->addr
.u8
[i
] |= ~((uint8_t)(0xFF << (8 - b
)));
703 p
->addr
.u8
[i
] &= (uint8_t)(0xFF << (8 - b
));
709 static int cidr_network(lua_State
*L
)
711 cidr_t
*p1
= L_checkcidr(L
, 1, NULL
), *p2
;
712 int bits
= L_checkbits(L
, 2, p1
);
714 if (!(p2
= lua_newuserdata(L
, sizeof(*p2
))))
718 p2
->bits
= AF_BITS(p1
->family
);
719 _apply_mask(p2
, bits
, false);
721 luaL_getmetatable(L
, LUCI_IP_CIDR
);
722 lua_setmetatable(L
, -2);
726 static int cidr_host(lua_State
*L
)
728 cidr_t
*p1
= L_checkcidr(L
, 1, NULL
);
729 cidr_t
*p2
= lua_newuserdata(L
, sizeof(*p2
));
735 p2
->bits
= AF_BITS(p1
->family
);
737 luaL_getmetatable(L
, LUCI_IP_CIDR
);
738 lua_setmetatable(L
, -2);
742 static int cidr_mask(lua_State
*L
)
744 cidr_t
*p1
= L_checkcidr(L
, 1, NULL
), *p2
;
745 int bits
= L_checkbits(L
, 2, p1
);
747 if (!(p2
= lua_newuserdata(L
, sizeof(*p2
))))
751 p2
->bits
= AF_BITS(p1
->family
);
752 p2
->family
= p1
->family
;
754 memset(&p2
->addr
.v6
.s6_addr
, 0xFF, sizeof(p2
->addr
.v6
.s6_addr
));
755 _apply_mask(p2
, bits
, false);
757 luaL_getmetatable(L
, LUCI_IP_CIDR
);
758 lua_setmetatable(L
, -2);
762 static int cidr_broadcast(lua_State
*L
)
764 cidr_t
*p1
= L_checkcidr(L
, 1, NULL
);
766 int bits
= L_checkbits(L
, 2, p1
);
768 if (p1
->family
!= AF_INET
)
771 if (!(p2
= lua_newuserdata(L
, sizeof(*p2
))))
775 p2
->bits
= AF_BITS(AF_INET
);
776 _apply_mask(p2
, bits
, true);
778 luaL_getmetatable(L
, LUCI_IP_CIDR
);
779 lua_setmetatable(L
, -2);
783 static int cidr_mapped4(lua_State
*L
)
785 cidr_t
*p1
= L_checkcidr(L
, 1, NULL
);
788 if (!_is_mapped4(p1
))
791 if (!(p2
= lua_newuserdata(L
, sizeof(*p2
))))
795 p2
->family
= AF_INET
;
796 p2
->bits
= (p1
->bits
> AF_BITS(AF_INET
)) ? AF_BITS(AF_INET
) : p1
->bits
;
797 memcpy(&p2
->addr
.v4
, p1
->addr
.v6
.s6_addr
+ 12, sizeof(p2
->addr
.v4
));
799 luaL_getmetatable(L
, LUCI_IP_CIDR
);
800 lua_setmetatable(L
, -2);
804 static int cidr_unscoped(lua_State
*L
)
806 cidr_t
*p1
= L_checkcidr(L
, 1, NULL
);
809 if (p1
->family
!= AF_INET6
)
812 if (!(p2
= lua_newuserdata(L
, sizeof(*p2
))))
818 luaL_getmetatable(L
, LUCI_IP_CIDR
);
819 lua_setmetatable(L
, -2);
823 static int cidr_tolinklocal(lua_State
*L
)
825 cidr_t
*p1
= L_checkcidr(L
, 1, NULL
);
829 if (p1
->family
!= AF_PACKET
)
832 if (!(p2
= lua_newuserdata(L
, sizeof(*p2
))))
835 p2
->scope
= p1
->scope
;
836 p2
->family
= AF_INET6
;
837 p2
->bits
= AF_BITS(AF_INET6
);
838 p2
->addr
.u8
[0] = 0xFE;
839 p2
->addr
.u8
[1] = 0x80;
840 p2
->addr
.u8
[2] = 0x00;
841 p2
->addr
.u8
[3] = 0x00;
842 p2
->addr
.u8
[4] = 0x00;
843 p2
->addr
.u8
[5] = 0x00;
844 p2
->addr
.u8
[6] = 0x00;
845 p2
->addr
.u8
[7] = 0x00;
846 p2
->addr
.u8
[8] = p1
->addr
.u8
[0] ^ 0x02;
847 p2
->addr
.u8
[9] = p1
->addr
.u8
[1];
848 p2
->addr
.u8
[10] = p1
->addr
.u8
[2];
849 p2
->addr
.u8
[11] = 0xFF;
850 p2
->addr
.u8
[12] = 0xFE;
851 p2
->addr
.u8
[13] = p1
->addr
.u8
[3];
852 p2
->addr
.u8
[14] = p1
->addr
.u8
[4];
853 p2
->addr
.u8
[15] = p1
->addr
.u8
[5];
855 luaL_getmetatable(L
, LUCI_IP_CIDR
);
856 lua_setmetatable(L
, -2);
860 static int cidr_tomac(lua_State
*L
)
862 cidr_t
*p1
= L_checkcidr(L
, 1, NULL
);
866 if (p1
->family
!= AF_INET6
||
867 p1
->addr
.u8
[0] != 0xFE ||
868 p1
->addr
.u8
[1] != 0x80 ||
869 p1
->addr
.u8
[2] != 0x00 ||
870 p1
->addr
.u8
[3] != 0x00 ||
871 p1
->addr
.u8
[4] != 0x00 ||
872 p1
->addr
.u8
[5] != 0x00 ||
873 p1
->addr
.u8
[6] != 0x00 ||
874 p1
->addr
.u8
[7] != 0x00 ||
875 p1
->addr
.u8
[11] != 0xFF ||
876 p1
->addr
.u8
[12] != 0xFE)
879 if (!(p2
= lua_newuserdata(L
, sizeof(*p2
))))
883 p2
->family
= AF_PACKET
;
884 p2
->bits
= AF_BITS(AF_PACKET
);
885 p2
->addr
.u8
[0] = p1
->addr
.u8
[8] ^ 0x02;
886 p2
->addr
.u8
[1] = p1
->addr
.u8
[9];
887 p2
->addr
.u8
[2] = p1
->addr
.u8
[10];
888 p2
->addr
.u8
[3] = p1
->addr
.u8
[13];
889 p2
->addr
.u8
[4] = p1
->addr
.u8
[14];
890 p2
->addr
.u8
[5] = p1
->addr
.u8
[15];
892 luaL_getmetatable(L
, LUCI_IP_CIDR
);
893 lua_setmetatable(L
, -2);
897 static int cidr_contains(lua_State
*L
)
899 cidr_t
*p1
= L_checkcidr(L
, 1, NULL
);
900 cidr_t
*p2
= L_checkcidr(L
, 2, NULL
);
901 cidr_t a
= *p1
, b
= *p2
;
904 if (p1
->family
== p2
->family
&& p1
->bits
<= p2
->bits
)
906 _apply_mask(&a
, p1
->bits
, false);
907 _apply_mask(&b
, p1
->bits
, false);
909 rv
= !memcmp(&a
.addr
.v6
, &b
.addr
.v6
, AF_BYTES(a
.family
));
912 lua_pushboolean(L
, rv
);
917 (a)->addr.u8[AF_BYTES((a)->family) - (i) - 1]
919 static int _cidr_add_sub(lua_State
*L
, bool add
)
921 cidr_t
*p1
= L_checkcidr(L
, 1, NULL
);
922 cidr_t
*p2
= L_checkcidr(L
, 2, p1
);
924 bool inplace
= lua_isboolean(L
, 3) ? lua_toboolean(L
, 3) : false;
929 if (p1
->family
== p2
->family
)
931 if (p1
->family
== AF_INET
)
933 a
= ntohl(p1
->addr
.v4
.s_addr
);
934 b
= ntohl(p2
->addr
.v4
.s_addr
);
936 /* would over/underflow */
937 if ((add
&& (UINT_MAX
- a
) < b
) || (!add
&& a
< b
))
939 r
.addr
.v4
.s_addr
= add
* 0xFFFFFFFF;
944 r
.addr
.v4
.s_addr
= add
? htonl(a
+ b
) : htonl(a
- b
);
949 for (i
= 0, carry
= 0; i
< AF_BYTES(p1
->family
); i
++)
953 BYTE(&r
, i
) = BYTE(p1
, i
) + BYTE(p2
, i
) + carry
;
954 carry
= (BYTE(p1
, i
) + BYTE(p2
, i
) + carry
) / 256;
958 BYTE(&r
, i
) = (BYTE(p1
, i
) - BYTE(p2
, i
) - carry
);
959 carry
= (BYTE(p1
, i
) < (BYTE(p2
, i
) + carry
));
963 /* would over/underflow */
966 memset(&r
.addr
.u8
, add
* 0xFF, AF_BYTES(r
.family
));
979 lua_pushboolean(L
, ok
);
983 if (!(p1
= lua_newuserdata(L
, sizeof(*p1
))))
988 luaL_getmetatable(L
, LUCI_IP_CIDR
);
989 lua_setmetatable(L
, -2);
993 static int cidr_add(lua_State
*L
)
995 return _cidr_add_sub(L
, true);
998 static int cidr_sub(lua_State
*L
)
1000 return _cidr_add_sub(L
, false);
1003 static int cidr_minhost(lua_State
*L
)
1005 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
1007 uint8_t i
, rest
, carry
;
1009 _apply_mask(&r
, r
.bits
, false);
1011 if (r
.family
== AF_INET
&& r
.bits
< AF_BITS(AF_INET
))
1013 r
.bits
= AF_BITS(AF_INET
);
1014 r
.addr
.v4
.s_addr
= htonl(ntohl(r
.addr
.v4
.s_addr
) + 1);
1016 else if (r
.bits
< AF_BITS(r
.family
))
1018 r
.bits
= AF_BITS(r
.family
);
1020 for (i
= 0, carry
= 1; i
< AF_BYTES(r
.family
); i
++)
1022 rest
= (BYTE(&r
, i
) + carry
) > 255;
1023 BYTE(&r
, i
) += carry
;
1028 if (!(p
= lua_newuserdata(L
, sizeof(*p
))))
1033 luaL_getmetatable(L
, LUCI_IP_CIDR
);
1034 lua_setmetatable(L
, -2);
1038 static int cidr_maxhost(lua_State
*L
)
1040 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
1043 _apply_mask(&r
, r
.bits
, true);
1045 if (r
.family
== AF_INET
&& r
.bits
< AF_BITS(AF_INET
))
1047 r
.bits
= AF_BITS(AF_INET
);
1048 r
.addr
.v4
.s_addr
= htonl(ntohl(r
.addr
.v4
.s_addr
) - 1);
1052 r
.bits
= AF_BITS(r
.family
);
1055 if (!(p
= lua_newuserdata(L
, sizeof(*p
))))
1060 luaL_getmetatable(L
, LUCI_IP_CIDR
);
1061 lua_setmetatable(L
, -2);
1065 static int cidr_gc (lua_State
*L
)
1070 static int cidr_tostring (lua_State
*L
)
1072 cidr_t
*p
= L_checkcidr(L
, 1, NULL
);
1073 return format_cidr(L
, p
);
1080 static bool diff_prefix(int family
, void *addr
, int bits
, bool exact
, cidr_t
*p
)
1082 uint8_t i
, b
, r
, *a
;
1088 if (!addr
|| p
->family
!= family
|| p
->bits
> bits
)
1091 if (family
== AF_INET
)
1093 m
= p
->bits
? htonl(~((1 << (AF_BITS(AF_INET
) - p
->bits
)) - 1)) : 0;
1095 if ((((struct in_addr
*)addr
)->s_addr
& m
) != (p
->addr
.v4
.s_addr
& m
))
1100 for (i
= 0, a
= addr
, r
= p
->bits
; i
< AF_BYTES(p
->family
); i
++)
1102 b
= r
? (0xFF << (8 - ((r
> 8) ? 8 : r
))) : 0;
1104 if ((a
[i
] & b
) != (p
->addr
.u8
[i
] & b
))
1107 r
-= ((r
> 8) ? 8 : r
);
1111 return (exact
&& p
->bits
!= bits
);
1114 static int cb_dump_route(struct nl_msg
*msg
, void *arg
)
1116 struct dump_state
*s
= arg
;
1117 struct dump_filter
*f
= s
->filter
;
1118 struct nlmsghdr
*hdr
= nlmsg_hdr(msg
);
1119 struct rtmsg
*rt
= NLMSG_DATA(hdr
);
1120 struct nlattr
*tb
[RTA_MAX
+1];
1121 struct in6_addr
*src
, *dst
, *gw
, *from
, def
= { };
1122 int iif
, oif
, bitlen
;
1125 if (hdr
->nlmsg_type
!= RTM_NEWROUTE
||
1126 (rt
->rtm_family
!= AF_INET
&& rt
->rtm_family
!= AF_INET6
))
1129 nlmsg_parse(hdr
, sizeof(*rt
), tb
, RTA_MAX
, NULL
);
1131 iif
= tb
[RTA_IIF
] ? RTA_INT(tb
[RTA_IIF
]) : 0;
1132 oif
= tb
[RTA_OIF
] ? RTA_INT(tb
[RTA_OIF
]) : 0;
1133 table
= tb
[RTA_TABLE
] ? RTA_U32(tb
[RTA_TABLE
]) : rt
->rtm_table
;
1134 from
= tb
[RTA_SRC
] ? RTA_DATA(tb
[RTA_SRC
]) : NULL
;
1135 src
= tb
[RTA_PREFSRC
] ? RTA_DATA(tb
[RTA_PREFSRC
]) : NULL
;
1136 dst
= tb
[RTA_DST
] ? RTA_DATA(tb
[RTA_DST
]) : &def
;
1137 gw
= tb
[RTA_GATEWAY
] ? RTA_DATA(tb
[RTA_GATEWAY
]) : NULL
;
1139 bitlen
= AF_BITS(rt
->rtm_family
);
1142 if ((f
->type
&& rt
->rtm_type
!= f
->type
) ||
1143 (f
->family
&& rt
->rtm_family
!= f
->family
) ||
1144 (f
->proto
&& rt
->rtm_protocol
!= f
->proto
) ||
1145 (f
->scope
&& rt
->rtm_scope
!= f
->scope
) ||
1146 (f
->iif
&& iif
!= f
->iif
) ||
1147 (f
->oif
&& oif
!= f
->oif
) ||
1148 (f
->table
&& table
!= f
->table
) ||
1149 diff_prefix(rt
->rtm_family
, from
, rt
->rtm_src_len
,
1150 f
->from_exact
, &f
->from
) ||
1151 diff_prefix(rt
->rtm_family
, dst
, rt
->rtm_dst_len
,
1152 f
->dst_exact
, &f
->dst
) ||
1153 diff_prefix(rt
->rtm_family
, gw
, bitlen
,
1155 diff_prefix(rt
->rtm_family
, src
, bitlen
,
1161 lua_pushvalue(s
->L
, 2);
1165 L_setint(s
->L
, "type", rt
->rtm_type
);
1166 L_setint(s
->L
, "family", (rt
->rtm_family
== AF_INET
) ? 4 : 6);
1168 L_setaddr(s
->L
, "dest", rt
->rtm_family
, dst
, rt
->rtm_dst_len
);
1171 L_setaddr(s
->L
, "gw", rt
->rtm_family
, gw
, -1);
1174 L_setaddr(s
->L
, "from", rt
->rtm_family
, from
, rt
->rtm_src_len
);
1177 L_setdev(s
->L
, "iif", tb
[RTA_IIF
]);
1180 L_setdev(s
->L
, "dev", tb
[RTA_OIF
]);
1182 L_setint(s
->L
, "table", table
);
1183 L_setint(s
->L
, "proto", rt
->rtm_protocol
);
1184 L_setint(s
->L
, "scope", rt
->rtm_scope
);
1187 L_setaddr(s
->L
, "src", rt
->rtm_family
, src
, -1);
1189 if (tb
[RTA_PRIORITY
])
1190 L_setint(s
->L
, "metric", RTA_U32(tb
[RTA_PRIORITY
]));
1192 if (rt
->rtm_family
== AF_INET6
&& tb
[RTA_CACHEINFO
])
1194 struct rta_cacheinfo
*ci
= RTA_DATA(tb
[RTA_CACHEINFO
]);
1196 if (ci
->rta_expires
)
1198 if (ci
->rta_expires
)
1199 L_setint(s
->L
, "expires", ci
->rta_expires
/ hz
);
1201 if (ci
->rta_error
!= 0)
1202 L_setint(s
->L
, "error", ci
->rta_error
);
1209 lua_call(s
->L
, 1, 0);
1210 else if (hdr
->nlmsg_flags
& NLM_F_MULTI
)
1211 lua_rawseti(s
->L
, -2, s
->index
);
1214 s
->pending
= !!(hdr
->nlmsg_flags
& NLM_F_MULTI
);
1219 cb_done(struct nl_msg
*msg
, void *arg
)
1221 struct dump_state
*s
= arg
;
1227 cb_error(struct sockaddr_nl
*nla
, struct nlmsgerr
*err
, void *arg
)
1229 struct dump_state
*s
= arg
;
1234 static int _error(lua_State
*L
, int code
, const char *msg
)
1237 lua_pushnumber(L
, code
? code
: errno
);
1238 lua_pushstring(L
, msg
? msg
: strerror(errno
));
1243 static int _route_dump(lua_State
*L
, struct dump_filter
*filter
)
1245 int flags
= NLM_F_REQUEST
;
1246 struct dump_state s
= {
1250 .callback
= lua_isfunction(L
, 2),
1255 hz
= sysconf(_SC_CLK_TCK
);
1259 sock
= nl_socket_alloc();
1261 return _error(L
, -1, "Out of memory");
1263 if (nl_connect(sock
, NETLINK_ROUTE
))
1264 return _error(L
, 0, NULL
);
1268 struct nl_cb
*cb
= nl_cb_alloc(NL_CB_DEFAULT
);
1269 struct rtmsg rtm
= {
1270 .rtm_family
= filter
->family
,
1271 .rtm_dst_len
= filter
->dst
.bits
,
1272 .rtm_src_len
= filter
->src
.bits
1276 flags
|= NLM_F_DUMP
;
1278 msg
= nlmsg_alloc_simple(RTM_GETROUTE
, flags
);
1282 nlmsg_append(msg
, &rtm
, sizeof(rtm
), 0);
1285 nla_put(msg
, RTA_DST
, AF_BYTES(filter
->dst
.family
),
1286 &filter
->dst
.addr
.v6
);
1288 if (filter
->src
.family
)
1289 nla_put(msg
, RTA_SRC
, AF_BYTES(filter
->src
.family
),
1290 &filter
->src
.addr
.v6
);
1293 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, cb_dump_route
, &s
);
1294 nl_cb_set(cb
, NL_CB_FINISH
, NL_CB_CUSTOM
, cb_done
, &s
);
1295 nl_cb_err(cb
, NL_CB_CUSTOM
, cb_error
, &s
);
1297 nl_send_auto_complete(sock
, msg
);
1299 if (!filter
->get
&& !s
.callback
)
1302 while (s
.pending
> 0)
1303 nl_recvmsgs(sock
, cb
);
1316 return (s
.index
> 0);
1319 static int route_get(lua_State
*L
)
1321 struct dump_filter filter
= { .get
= true };
1322 const char *dest
= luaL_checkstring(L
, 1);
1323 const char *from
= luaL_optstring(L
, 2, NULL
);
1325 if (!parse_cidr(dest
, &filter
.dst
))
1326 return _error(L
, -1, "Invalid destination");
1328 if (from
&& !parse_cidr(from
, &filter
.src
))
1329 return _error(L
, -1, "Invalid source");
1331 if (filter
.src
.family
!= 0 &&
1332 filter
.src
.family
!= filter
.dst
.family
)
1333 return _error(L
, -1, "Different source/destination family");
1335 filter
.family
= filter
.dst
.family
;
1337 return _route_dump(L
, &filter
);
1340 static int route_dump(lua_State
*L
)
1344 struct dump_filter filter
= { };
1346 if (lua_type(L
, 1) == LUA_TTABLE
)
1348 filter
.family
= L_getint(L
, 1, "family");
1350 if (filter
.family
== 4)
1351 filter
.family
= AF_INET
;
1352 else if (filter
.family
== 6)
1353 filter
.family
= AF_INET6
;
1357 if ((s
= L_getstr(L
, 1, "iif")) != NULL
)
1358 filter
.iif
= if_nametoindex(s
);
1360 if ((s
= L_getstr(L
, 1, "oif")) != NULL
)
1361 filter
.oif
= if_nametoindex(s
);
1363 filter
.type
= L_getint(L
, 1, "type");
1364 filter
.scope
= L_getint(L
, 1, "scope");
1365 filter
.proto
= L_getint(L
, 1, "proto");
1366 filter
.table
= L_getint(L
, 1, "table");
1368 if ((s
= L_getstr(L
, 1, "gw")) != NULL
&& parse_cidr(s
, &p
))
1371 if ((s
= L_getstr(L
, 1, "from")) != NULL
&& parse_cidr(s
, &p
))
1374 if ((s
= L_getstr(L
, 1, "src")) != NULL
&& parse_cidr(s
, &p
))
1377 if ((s
= L_getstr(L
, 1, "dest")) != NULL
&& parse_cidr(s
, &p
))
1380 if ((s
= L_getstr(L
, 1, "from_exact")) != NULL
&& parse_cidr(s
, &p
))
1381 filter
.from
= p
, filter
.from_exact
= true;
1383 if ((s
= L_getstr(L
, 1, "dest_exact")) != NULL
&& parse_cidr(s
, &p
))
1384 filter
.dst
= p
, filter
.dst_exact
= true;
1387 return _route_dump(L
, &filter
);
1391 static bool diff_macaddr(struct ether_addr
*mac1
, struct ether_addr
*mac2
)
1393 struct ether_addr empty
= { };
1395 if (!memcmp(mac2
, &empty
, sizeof(empty
)))
1398 if (!mac1
|| memcmp(mac1
, mac2
, sizeof(empty
)))
1404 static int cb_dump_neigh(struct nl_msg
*msg
, void *arg
)
1407 struct ether_addr
*mac
;
1408 struct in6_addr
*dst
;
1409 struct dump_state
*s
= arg
;
1410 struct dump_filter
*f
= s
->filter
;
1411 struct nlmsghdr
*hdr
= nlmsg_hdr(msg
);
1412 struct ndmsg
*nd
= NLMSG_DATA(hdr
);
1413 struct nlattr
*tb
[NDA_MAX
+1];
1416 if (hdr
->nlmsg_type
!= RTM_NEWNEIGH
||
1417 (nd
->ndm_family
!= AF_INET
&& nd
->ndm_family
!= AF_INET6
))
1420 nlmsg_parse(hdr
, sizeof(*nd
), tb
, NDA_MAX
, NULL
);
1422 mac
= tb
[NDA_LLADDR
] ? RTA_DATA(tb
[NDA_LLADDR
]) : NULL
;
1423 dst
= tb
[NDA_DST
] ? RTA_DATA(tb
[NDA_DST
]) : NULL
;
1425 bitlen
= AF_BITS(nd
->ndm_family
);
1427 if ((f
->family
&& nd
->ndm_family
!= f
->family
) ||
1428 (f
->iif
&& nd
->ndm_ifindex
!= f
->iif
) ||
1429 (f
->type
&& !(f
->type
& nd
->ndm_state
)) ||
1430 diff_prefix(nd
->ndm_family
, dst
, bitlen
, false, &f
->dst
) ||
1431 diff_macaddr(mac
, &f
->mac
))
1435 lua_pushvalue(s
->L
, 2);
1439 L_setint(s
->L
, "family", (nd
->ndm_family
== AF_INET
) ? 4 : 6);
1440 L_setstr(s
->L
, "dev", if_indextoname(nd
->ndm_ifindex
, buf
));
1442 L_setbool(s
->L
, "router", (nd
->ndm_flags
& NTF_ROUTER
));
1443 L_setbool(s
->L
, "proxy", (nd
->ndm_flags
& NTF_PROXY
));
1445 L_setbool(s
->L
, "incomplete", (nd
->ndm_state
& NUD_INCOMPLETE
));
1446 L_setbool(s
->L
, "reachable", (nd
->ndm_state
& NUD_REACHABLE
));
1447 L_setbool(s
->L
, "stale", (nd
->ndm_state
& NUD_STALE
));
1448 L_setbool(s
->L
, "delay", (nd
->ndm_state
& NUD_DELAY
));
1449 L_setbool(s
->L
, "probe", (nd
->ndm_state
& NUD_PROBE
));
1450 L_setbool(s
->L
, "failed", (nd
->ndm_state
& NUD_FAILED
));
1451 L_setbool(s
->L
, "noarp", (nd
->ndm_state
& NUD_NOARP
));
1452 L_setbool(s
->L
, "permanent", (nd
->ndm_state
& NUD_PERMANENT
));
1455 L_setaddr(s
->L
, "dest", nd
->ndm_family
, dst
, -1);
1458 L_setaddr(s
->L
, "mac", AF_PACKET
, mac
, -1);
1463 lua_call(s
->L
, 1, 0);
1464 else if (hdr
->nlmsg_flags
& NLM_F_MULTI
)
1465 lua_rawseti(s
->L
, -2, s
->index
);
1468 s
->pending
= !!(hdr
->nlmsg_flags
& NLM_F_MULTI
);
1472 static int neighbor_dump(lua_State
*L
)
1476 struct ether_addr
*mac
;
1477 struct dump_filter filter
= { .type
= 0xFF & ~NUD_NOARP
};
1478 struct dump_state st
= {
1479 .callback
= lua_isfunction(L
, 2),
1485 if (lua_type(L
, 1) == LUA_TTABLE
)
1487 filter
.family
= L_getint(L
, 1, "family");
1489 if (filter
.family
== 4)
1490 filter
.family
= AF_INET
;
1491 else if (filter
.family
== 6)
1492 filter
.family
= AF_INET6
;
1496 if ((s
= L_getstr(L
, 1, "dev")) != NULL
)
1497 filter
.iif
= if_nametoindex(s
);
1499 if ((s
= L_getstr(L
, 1, "dest")) != NULL
&& parse_cidr(s
, &p
))
1502 if ((s
= L_getstr(L
, 1, "mac")) != NULL
&&
1503 (mac
= ether_aton(s
)) != NULL
)
1509 sock
= nl_socket_alloc();
1511 return _error(L
, -1, "Out of memory");
1513 if (nl_connect(sock
, NETLINK_ROUTE
))
1514 return _error(L
, 0, NULL
);
1518 struct nl_cb
*cb
= nl_cb_alloc(NL_CB_DEFAULT
);
1519 struct ndmsg ndm
= {
1520 .ndm_family
= filter
.family
1523 msg
= nlmsg_alloc_simple(RTM_GETNEIGH
, NLM_F_REQUEST
| NLM_F_DUMP
);
1527 nlmsg_append(msg
, &ndm
, sizeof(ndm
), 0);
1529 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, cb_dump_neigh
, &st
);
1530 nl_cb_set(cb
, NL_CB_FINISH
, NL_CB_CUSTOM
, cb_done
, &st
);
1531 nl_cb_err(cb
, NL_CB_CUSTOM
, cb_error
, &st
);
1533 nl_send_auto_complete(sock
, msg
);
1538 while (st
.pending
> 0)
1539 nl_recvmsgs(sock
, cb
);
1545 return (st
.callback
== 0);
1549 static int cb_dump_link(struct nl_msg
*msg
, void *arg
)
1552 struct dump_state
*s
= arg
;
1553 struct nlmsghdr
*hdr
= nlmsg_hdr(msg
);
1554 struct ifinfomsg
*ifm
= NLMSG_DATA(hdr
);
1555 struct nlattr
*tb
[IFLA_MAX
+1];
1558 if (hdr
->nlmsg_type
!= RTM_NEWLINK
)
1561 nlmsg_parse(hdr
, sizeof(*ifm
), tb
, IFLA_MAX
, NULL
);
1563 L_setbool(s
->L
, "up", (ifm
->ifi_flags
& IFF_RUNNING
));
1564 L_setint(s
->L
, "type", ifm
->ifi_type
);
1565 L_setstr(s
->L
, "name", if_indextoname(ifm
->ifi_index
, buf
));
1568 L_setint(s
->L
, "mtu", RTA_U32(tb
[IFLA_MTU
]));
1570 if (tb
[IFLA_TXQLEN
])
1571 L_setint(s
->L
, "qlen", RTA_U32(tb
[IFLA_TXQLEN
]));
1573 if (tb
[IFLA_MASTER
])
1574 L_setdev(s
->L
, "master", tb
[IFLA_MASTER
]);
1576 if (tb
[IFLA_ADDRESS
] && nla_len(tb
[IFLA_ADDRESS
]) == AF_BYTES(AF_PACKET
))
1577 L_setaddr(s
->L
, "mac", AF_PACKET
, nla_get_string(tb
[IFLA_ADDRESS
]), -1);
1583 static int link_get(lua_State
*L
)
1585 const char *dev
= luaL_checkstring(L
, 1);
1586 struct dump_state st
= {
1593 sock
= nl_socket_alloc();
1595 return _error(L
, -1, "Out of memory");
1597 if (nl_connect(sock
, NETLINK_ROUTE
))
1598 return _error(L
, 0, NULL
);
1601 struct nl_msg
*msg
= nlmsg_alloc_simple(RTM_GETLINK
, NLM_F_REQUEST
);
1602 struct nl_cb
*cb
= nl_cb_alloc(NL_CB_DEFAULT
);
1603 struct ifinfomsg ifm
= { .ifi_index
= if_nametoindex(dev
) };
1608 nlmsg_append(msg
, &ifm
, sizeof(ifm
), 0);
1610 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, cb_dump_link
, &st
);
1611 nl_cb_set(cb
, NL_CB_FINISH
, NL_CB_CUSTOM
, cb_done
, &st
);
1612 nl_cb_err(cb
, NL_CB_CUSTOM
, cb_error
, &st
);
1616 nl_send_auto_complete(sock
, msg
);
1618 while (st
.pending
> 0)
1619 nl_recvmsgs(sock
, cb
);
1628 static const luaL_reg ip_methods
[] = {
1629 { "new", cidr_new
},
1630 { "IPv4", cidr_ipv4
},
1631 { "IPv6", cidr_ipv6
},
1632 { "MAC", cidr_mac
},
1634 { "checkip4", cidr_checkip4
},
1635 { "checkip6", cidr_checkip6
},
1636 { "checkmac", cidr_checkmac
},
1638 { "route", route_get
},
1639 { "routes", route_dump
},
1641 { "neighbors", neighbor_dump
},
1643 { "link", link_get
},
1648 static const luaL_reg ip_cidr_methods
[] = {
1649 { "is4", cidr_is4
},
1650 { "is4rfc1918", cidr_is4rfc1918
},
1651 { "is4linklocal", cidr_is4linklocal
},
1652 { "is6", cidr_is6
},
1653 { "is6linklocal", cidr_is6linklocal
},
1654 { "is6mapped4", cidr_is6mapped4
},
1655 { "ismac", cidr_ismac
},
1656 { "ismaclocal", cidr_ismaclocal
},
1657 { "ismacmcast", cidr_ismacmcast
},
1658 { "lower", cidr_lower
},
1659 { "higher", cidr_higher
},
1660 { "equal", cidr_equal
},
1661 { "prefix", cidr_prefix
},
1662 { "network", cidr_network
},
1663 { "host", cidr_host
},
1664 { "mask", cidr_mask
},
1665 { "broadcast", cidr_broadcast
},
1666 { "mapped4", cidr_mapped4
},
1667 { "unscoped", cidr_unscoped
},
1668 { "tomac", cidr_tomac
},
1669 { "tolinklocal", cidr_tolinklocal
},
1670 { "contains", cidr_contains
},
1671 { "add", cidr_add
},
1672 { "sub", cidr_sub
},
1673 { "minhost", cidr_minhost
},
1674 { "maxhost", cidr_maxhost
},
1675 { "string", cidr_tostring
},
1677 { "__lt", cidr_lower
},
1678 { "__le", cidr_lower_equal
},
1679 { "__eq", cidr_equal
},
1680 { "__add", cidr_add
},
1681 { "__sub", cidr_sub
},
1682 { "__gc", cidr_gc
},
1683 { "__tostring", cidr_tostring
},
1688 int luaopen_luci_ip(lua_State
*L
)
1690 luaL_register(L
, LUCI_IP
, ip_methods
);
1692 luaL_newmetatable(L
, LUCI_IP_CIDR
);
1693 luaL_register(L
, NULL
, ip_cidr_methods
);
1694 lua_pushvalue(L
, -1);
1695 lua_setfield(L
, -2, "__index");