libs: add luci-lib-ip
[project/luci.git] / libs / luci-lib-ip / src / ip.c
1 /*
2 Copyright 2015 Jo-Philipp Wich <jow@openwrt.org>
3
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
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
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.
15 */
16
17 #define _GNU_SOURCE
18
19 #include <stdio.h>
20 #include <stdint.h>
21 #include <stdbool.h>
22 #include <unistd.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <limits.h>
26
27 #include <lua.h>
28 #include <lualib.h>
29 #include <lauxlib.h>
30
31 #include <net/if.h>
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>
38
39 #define LUCI_IP "luci.ip"
40 #define LUCI_IP_CIDR "luci.ip.cidr"
41
42 #define RTA_INT(x) (*(int *)RTA_DATA(x))
43 #define RTA_U32(x) (*(uint32_t *)RTA_DATA(x))
44
45 static int hz = 0;
46 static struct nl_sock *sock = NULL;
47
48 typedef struct {
49 union {
50 struct in_addr v4;
51 struct in6_addr v6;
52 } addr;
53 int len;
54 int bits;
55 int family;
56 bool exact;
57 } cidr_t;
58
59 struct dump_filter {
60 bool get;
61 int family;
62 int iif;
63 int oif;
64 int type;
65 int scope;
66 int proto;
67 int table;
68 cidr_t gw;
69 cidr_t from;
70 cidr_t src;
71 cidr_t dst;
72 };
73
74 struct dump_state {
75 int index;
76 int pending;
77 int callback;
78 struct lua_State *L;
79 struct dump_filter *filter;
80 };
81
82
83 static int _cidr_new(lua_State *L, int index, int family);
84
85 static cidr_t *L_checkcidr (lua_State *L, int index, cidr_t *p)
86 {
87 if (lua_type(L, index) == LUA_TUSERDATA)
88 return luaL_checkudata(L, index, LUCI_IP_CIDR);
89
90 if (_cidr_new(L, index, p ? p->family : 0))
91 return lua_touserdata(L, -1);
92
93 luaL_error(L, "Invalid operand");
94 return NULL;
95 }
96
97 static bool parse_mask(int family, const char *mask, int *bits)
98 {
99 char *e;
100 struct in_addr m;
101 struct in6_addr m6;
102
103 if (family == AF_INET && inet_pton(AF_INET, mask, &m))
104 {
105 for (*bits = 0, m.s_addr = ntohl(m.s_addr);
106 *bits < 32 && (m.s_addr << *bits) & 0x80000000;
107 ++*bits);
108 }
109 else if (family == AF_INET6 && inet_pton(AF_INET6, mask, &m6))
110 {
111 for (*bits = 0;
112 *bits < 128 && (m6.s6_addr[*bits / 8] << (*bits % 8)) & 128;
113 ++*bits);
114 }
115 else
116 {
117 *bits = strtoul(mask, &e, 10);
118
119 if (e == mask || *e != 0 || *bits > ((family == AF_INET) ? 32 : 128))
120 return false;
121 }
122
123 return true;
124 }
125
126 static bool parse_cidr(const char *dest, cidr_t *pp)
127 {
128 char *p, *a, buf[INET6_ADDRSTRLEN * 2 + 2];
129 uint8_t bitlen = 0;
130
131 strncpy(buf, dest, sizeof(buf) - 1);
132
133 a = buf;
134 p = strchr(buf, '/');
135
136 if (p)
137 *p++ = 0;
138
139 if (!strncasecmp(buf, "::ffff:", 7))
140 a += 7;
141
142 if (inet_pton(AF_INET, a, &pp->addr.v4))
143 {
144 bitlen = 32;
145 pp->family = AF_INET;
146 pp->len = sizeof(struct in_addr);
147 }
148 else if (inet_pton(AF_INET6, a, &pp->addr.v6))
149 {
150 bitlen = 128;
151 pp->family = AF_INET6;
152 pp->len = sizeof(struct in6_addr);
153 }
154 else
155 return false;
156
157 if (p)
158 {
159 if (!parse_mask(pp->family, p, &pp->bits))
160 return false;
161 }
162 else
163 {
164 pp->bits = bitlen;
165 }
166
167 return true;
168 }
169
170 static int L_getint(lua_State *L, int index, const char *name)
171 {
172 int rv = 0;
173
174 lua_getfield(L, index, name);
175
176 if (lua_type(L, -1) == LUA_TNUMBER)
177 rv = lua_tonumber(L, -1);
178
179 lua_pop(L, 1);
180
181 return rv;
182 }
183
184 static const char * L_getstr(lua_State *L, int index, const char *name)
185 {
186 const char *rv = NULL;
187
188 lua_getfield(L, index, name);
189
190 if (lua_type(L, -1) == LUA_TSTRING)
191 rv = lua_tostring(L, -1);
192
193 lua_pop(L, 1);
194
195 return rv;
196 }
197
198 static void L_setint(struct lua_State *L, const char *name, uint32_t n)
199 {
200 lua_pushinteger(L, n);
201 lua_setfield(L, -2, name);
202 }
203
204 static void L_setbool(struct lua_State *L, const char *name, bool val)
205 {
206 lua_pushboolean(L, val);
207 lua_setfield(L, -2, name);
208 }
209
210 static void L_setaddr(struct lua_State *L, const char *name,
211 int family, void *addr, int bits)
212 {
213 cidr_t *p;
214
215 if (!addr)
216 return;
217
218 p = lua_newuserdata(L, sizeof(*p));
219
220 if (!p)
221 return;
222
223 if (family == AF_INET)
224 {
225 p->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;
229 }
230 else
231 {
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;
236 }
237
238 luaL_getmetatable(L, LUCI_IP_CIDR);
239 lua_setmetatable(L, -2);
240 lua_setfield(L, -2, name);
241 }
242
243 static void L_setstr(struct lua_State *L, const char *name, const char *val)
244 {
245 lua_pushstring(L, val);
246 lua_setfield(L, -2, name);
247 }
248
249 static void L_setdev(struct lua_State *L, const char *name,
250 struct nlattr *attr)
251 {
252 char buf[32];
253
254 if (if_indextoname(RTA_INT(attr), buf))
255 L_setstr(L, name, buf);
256 }
257
258 static int L_checkbits(lua_State *L, int index, cidr_t *p)
259 {
260 int bits;
261
262 if (lua_gettop(L) < index || lua_isnil(L, index))
263 {
264 bits = p->bits;
265 }
266 else if (lua_type(L, index) == LUA_TNUMBER)
267 {
268 bits = lua_tointeger(L, index);
269
270 if (bits < 0 || bits > ((p->family == AF_INET) ? 32 : 128))
271 return luaL_error(L, "Invalid prefix size");
272 }
273 else if (lua_type(L, index) == LUA_TSTRING)
274 {
275 if (!parse_mask(p->family, lua_tostring(L, index), &bits))
276 return luaL_error(L, "Invalid netmask format");
277 }
278 else
279 {
280 return luaL_error(L, "Invalid data type");
281 }
282
283 return bits;
284 }
285
286 static int _cidr_new(lua_State *L, int index, int family)
287 {
288 uint32_t n;
289 const char *addr;
290 cidr_t cidr = { }, *cidrp;
291
292 if (lua_type(L, index) == LUA_TNUMBER)
293 {
294 n = htonl(lua_tointeger(L, index));
295
296 if (family == AF_INET6)
297 {
298 cidr.family = AF_INET6;
299 cidr.bits = 128;
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);
305 }
306 else
307 {
308 cidr.family = AF_INET;
309 cidr.bits = 32;
310 cidr.len = sizeof(cidr.addr.v4);
311 cidr.addr.v4.s_addr = n;
312 }
313 }
314 else
315 {
316 addr = luaL_checkstring(L, index);
317
318 if (!parse_cidr(addr, &cidr))
319 return 0;
320
321 if (family && cidr.family != family)
322 return 0;
323 }
324
325 if (!(cidrp = lua_newuserdata(L, sizeof(*cidrp))))
326 return 0;
327
328 *cidrp = cidr;
329 luaL_getmetatable(L, LUCI_IP_CIDR);
330 lua_setmetatable(L, -2);
331 return 1;
332 }
333
334 static int cidr_new(lua_State *L)
335 {
336 return _cidr_new(L, 1, 0);
337 }
338
339 static int cidr_ipv4(lua_State *L)
340 {
341 return _cidr_new(L, 1, AF_INET);
342 }
343
344 static int cidr_ipv6(lua_State *L)
345 {
346 return _cidr_new(L, 1, AF_INET6);
347 }
348
349 static int cidr_is4(lua_State *L)
350 {
351 cidr_t *p = L_checkcidr(L, 1, NULL);
352
353 lua_pushboolean(L, p->family == AF_INET);
354 return 1;
355 }
356
357 static int cidr_is4rfc1918(lua_State *L)
358 {
359 cidr_t *p = L_checkcidr(L, 1, NULL);
360 uint32_t a = htonl(p->addr.v4.s_addr);
361
362 lua_pushboolean(L, (p->family == AF_INET &&
363 ((a >= 0x0A000000 && a <= 0x0AFFFFFF) ||
364 (a >= 0xAC100000 && a <= 0xAC1FFFFF) ||
365 (a >= 0xC0A80000 && a <= 0xC0A8FFFF))));
366
367 return 1;
368 }
369
370 static int cidr_is4linklocal(lua_State *L)
371 {
372 cidr_t *p = L_checkcidr(L, 1, NULL);
373 uint32_t a = htonl(p->addr.v4.s_addr);
374
375 lua_pushboolean(L, (p->family == AF_INET &&
376 a >= 0xA9FE0000 &&
377 a <= 0xA9FEFFFF));
378
379 return 1;
380 }
381
382 static int cidr_is6(lua_State *L)
383 {
384 cidr_t *p = L_checkcidr(L, 1, NULL);
385
386 lua_pushboolean(L, p->family == AF_INET6);
387 return 1;
388 }
389
390 static int cidr_is6linklocal(lua_State *L)
391 {
392 cidr_t *p = L_checkcidr(L, 1, NULL);
393
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));
398
399 return 1;
400 }
401
402 static int _cidr_cmp(lua_State *L)
403 {
404 cidr_t *a = L_checkcidr(L, 1, NULL);
405 cidr_t *b = L_checkcidr(L, 2, NULL);
406
407 if (a->family != b->family)
408 return (a->family - b->family);
409
410 return memcmp(&a->addr.v6, &b->addr.v6, a->len);
411 }
412
413 static int cidr_lower(lua_State *L)
414 {
415 lua_pushboolean(L, _cidr_cmp(L) < 0);
416 return 1;
417 }
418
419 static int cidr_higher(lua_State *L)
420 {
421 lua_pushboolean(L, _cidr_cmp(L) > 0);
422 return 1;
423 }
424
425 static int cidr_equal(lua_State *L)
426 {
427 lua_pushboolean(L, _cidr_cmp(L) == 0);
428 return 1;
429 }
430
431 static int cidr_lower_equal(lua_State *L)
432 {
433 lua_pushboolean(L, _cidr_cmp(L) <= 0);
434 return 1;
435 }
436
437 static int cidr_prefix(lua_State *L)
438 {
439 cidr_t *p = L_checkcidr(L, 1, NULL);
440 int bits = L_checkbits(L, 2, p);
441
442 p->bits = bits;
443 lua_pushinteger(L, p->bits);
444 return 1;
445 }
446
447 static void _apply_mask(cidr_t *p, int bits, bool inv)
448 {
449 uint8_t b, i;
450
451 if (bits <= 0)
452 {
453 memset(&p->addr.v6, inv * 0xFF, p->len);
454 }
455 else if (p->family == AF_INET && bits <= 32)
456 {
457 if (inv)
458 p->addr.v4.s_addr |= ntohl((1 << (32 - bits)) - 1);
459 else
460 p->addr.v4.s_addr &= ntohl(~((1 << (32 - bits)) - 1));
461 }
462 else if (p->family == AF_INET6 && bits <= 128)
463 {
464 for (i = 0; i < sizeof(p->addr.v6.s6_addr); i++)
465 {
466 b = (bits > 8) ? 8 : bits;
467 if (inv)
468 p->addr.v6.s6_addr[i] |= ~((uint8_t)(0xFF << (8 - b)));
469 else
470 p->addr.v6.s6_addr[i] &= (uint8_t)(0xFF << (8 - b));
471 bits -= b;
472 }
473 }
474 }
475
476 static int cidr_network(lua_State *L)
477 {
478 cidr_t *p1 = L_checkcidr(L, 1, NULL), *p2;
479 int bits = L_checkbits(L, 2, p1);
480
481 if (!(p2 = lua_newuserdata(L, sizeof(*p2))))
482 return 0;
483
484 *p2 = *p1;
485 p2->bits = (p1->family == AF_INET) ? 32 : 128;
486 _apply_mask(p2, bits, false);
487
488 luaL_getmetatable(L, LUCI_IP_CIDR);
489 lua_setmetatable(L, -2);
490 return 1;
491 }
492
493 static int cidr_host(lua_State *L)
494 {
495 cidr_t *p1 = L_checkcidr(L, 1, NULL);
496 cidr_t *p2 = lua_newuserdata(L, sizeof(*p2));
497
498 if (!p2)
499 return 0;
500
501 *p2 = *p1;
502 p2->bits = (p1->family == AF_INET) ? 32 : 128;
503
504 luaL_getmetatable(L, LUCI_IP_CIDR);
505 lua_setmetatable(L, -2);
506 return 1;
507 }
508
509 static int cidr_mask(lua_State *L)
510 {
511 cidr_t *p1 = L_checkcidr(L, 1, NULL), *p2;
512 int bits = L_checkbits(L, 2, p1);
513
514 if (!(p2 = lua_newuserdata(L, sizeof(*p2))))
515 return 0;
516
517 p2->bits = (p1->family == AF_INET) ? 32 : 128;
518 p2->family = p1->family;
519
520 memset(&p2->addr.v6.s6_addr, 0xFF, sizeof(p2->addr.v6.s6_addr));
521 _apply_mask(p2, bits, false);
522
523 luaL_getmetatable(L, LUCI_IP_CIDR);
524 lua_setmetatable(L, -2);
525 return 1;
526 }
527
528 static int cidr_broadcast(lua_State *L)
529 {
530 cidr_t *p1 = L_checkcidr(L, 1, NULL);
531 cidr_t *p2;
532 int bits = L_checkbits(L, 2, p1);
533
534 if (p1->family == AF_INET6)
535 return 0;
536
537 if (!(p2 = lua_newuserdata(L, sizeof(*p2))))
538 return 0;
539
540 *p2 = *p1;
541 p2->bits = (p1->family == AF_INET) ? 32 : 128;
542 _apply_mask(p2, bits, true);
543
544 luaL_getmetatable(L, LUCI_IP_CIDR);
545 lua_setmetatable(L, -2);
546 return 1;
547 }
548
549 static int cidr_contains(lua_State *L)
550 {
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;
554 bool rv = false;
555
556 if (p1->family == p2->family && p1->bits <= p2->bits)
557 {
558 _apply_mask(&a, p1->bits, false);
559 _apply_mask(&b, p1->bits, false);
560
561 rv = !memcmp(&a.addr.v6, &b.addr.v6, a.len);
562 }
563
564 lua_pushboolean(L, rv);
565 return 1;
566 }
567
568 #define S6_BYTE(a, i) \
569 (a)->addr.v6.s6_addr[sizeof((a)->addr.v6.s6_addr) - (i) - 1]
570
571 static int _cidr_add_sub(lua_State *L, bool add)
572 {
573 cidr_t *p1 = L_checkcidr(L, 1, NULL);
574 cidr_t *p2 = L_checkcidr(L, 2, p1);
575 cidr_t r = *p1;
576 bool inplace = lua_isboolean(L, 3) ? lua_toboolean(L, 3) : false;
577 bool ok = true;
578 uint8_t i, carry;
579 uint32_t a, b;
580
581 if (p1->family == p2->family)
582 {
583 if (p1->family == AF_INET6)
584 {
585 for (i = 0, carry = 0; i < sizeof(r); i++)
586 {
587 if (add)
588 {
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;
591 }
592 else
593 {
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));
596 }
597 }
598
599 /* would over/underflow */
600 if (carry)
601 {
602 memset(&r.addr.v6, add * 0xFF, sizeof(r.addr.v6));
603 ok = false;
604 }
605 }
606 else
607 {
608 a = ntohl(p1->addr.v4.s_addr);
609 b = ntohl(p2->addr.v4.s_addr);
610
611 /* would over/underflow */
612 if ((add && (UINT_MAX - a) < b) || (!add && a < b))
613 {
614 r.addr.v4.s_addr = add * 0xFFFFFFFF;
615 ok = false;
616 }
617 else
618 {
619 r.addr.v4.s_addr = add ? htonl(a + b) : htonl(a - b);
620 }
621 }
622 }
623 else
624 {
625 ok = false;
626 }
627
628 if (inplace)
629 {
630 *p1 = r;
631 lua_pushboolean(L, ok);
632 return 1;
633 }
634
635 if (!(p1 = lua_newuserdata(L, sizeof(*p1))))
636 return 0;
637
638 *p1 = r;
639
640 luaL_getmetatable(L, LUCI_IP_CIDR);
641 lua_setmetatable(L, -2);
642 return 1;
643 }
644
645 static int cidr_add(lua_State *L)
646 {
647 return _cidr_add_sub(L, true);
648 }
649
650 static int cidr_sub(lua_State *L)
651 {
652 return _cidr_add_sub(L, false);
653 }
654
655 static int cidr_minhost(lua_State *L)
656 {
657 cidr_t *p = L_checkcidr(L, 1, NULL);
658 cidr_t r = *p;
659 uint8_t i, rest, carry;
660
661 _apply_mask(&r, r.bits, false);
662
663 if (r.family == AF_INET6 && r.bits < 128)
664 {
665 r.bits = 128;
666
667 for (i = 0, carry = 1; i < sizeof(r.addr.v6.s6_addr); i++)
668 {
669 rest = (S6_BYTE(&r, i) + carry) > 255;
670 S6_BYTE(&r, i) += carry;
671 carry = rest;
672 }
673 }
674 else if (r.family == AF_INET && r.bits < 32)
675 {
676 r.bits = 32;
677 r.addr.v4.s_addr = htonl(ntohl(r.addr.v4.s_addr) + 1);
678 }
679
680 if (!(p = lua_newuserdata(L, sizeof(*p))))
681 return 0;
682
683 *p = r;
684
685 luaL_getmetatable(L, LUCI_IP_CIDR);
686 lua_setmetatable(L, -2);
687 return 1;
688 }
689
690 static int cidr_maxhost(lua_State *L)
691 {
692 cidr_t *p = L_checkcidr(L, 1, NULL);
693 cidr_t r = *p;
694
695 _apply_mask(&r, r.bits, true);
696
697 if (r.family == AF_INET && r.bits < 32)
698 {
699 r.bits = 32;
700 r.addr.v4.s_addr = htonl(ntohl(r.addr.v4.s_addr) - 1);
701 }
702 else if (r.family == AF_INET6)
703 {
704 r.bits = 128;
705 }
706
707 if (!(p = lua_newuserdata(L, sizeof(*p))))
708 return 0;
709
710 *p = r;
711
712 luaL_getmetatable(L, LUCI_IP_CIDR);
713 lua_setmetatable(L, -2);
714 return 1;
715 }
716
717 static int cidr_gc (lua_State *L)
718 {
719 return 0;
720 }
721
722 static int cidr_tostring (lua_State *L)
723 {
724 char buf[INET6_ADDRSTRLEN];
725 cidr_t *p = L_checkcidr(L, 1, NULL);
726
727 if ((p->family == AF_INET && p->bits < 32) ||
728 (p->family == AF_INET6 && p->bits < 128))
729 {
730 lua_pushfstring(L, "%s/%d",
731 inet_ntop(p->family, &p->addr.v6, buf, sizeof(buf)),
732 p->bits);
733 }
734 else
735 {
736 lua_pushstring(L, inet_ntop(p->family, &p->addr.v6, buf, sizeof(buf)));
737 }
738
739 return 1;
740 }
741
742 /*
743 * route functions
744 */
745
746 static bool diff_prefix(int family, void *addr, int bits, cidr_t *p)
747 {
748 uint8_t i, b, r;
749 uint32_t m;
750
751 if (!p->family)
752 return false;
753
754 if (!addr || p->family != family || p->bits > bits)
755 return true;
756
757 if (family == AF_INET6)
758 {
759 for (i = 0, r = p->bits; i < sizeof(struct in6_addr); i++)
760 {
761 b = r ? (0xFF << (8 - ((r > 8) ? 8 : r))) : 0;
762
763 if ((((struct in6_addr *)addr)->s6_addr[i] & b) !=
764 (p->addr.v6.s6_addr[i] & b))
765 return true;
766
767 r -= ((r > 8) ? 8 : r);
768 }
769 }
770 else
771 {
772 m = p->bits ? htonl(~((1 << (32 - p->bits)) - 1)) : 0;
773
774 if ((((struct in_addr *)addr)->s_addr & m) != (p->addr.v4.s_addr & m))
775 return true;
776 }
777
778 return (p->exact && p->bits != bits);
779 }
780
781 static int cb_dump_route(struct nl_msg *msg, void *arg)
782 {
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;
790 uint32_t table;
791
792 if (hdr->nlmsg_type != RTM_NEWROUTE ||
793 (rt->rtm_family != AF_INET && rt->rtm_family != AF_INET6))
794 return NL_SKIP;
795
796 nlmsg_parse(hdr, sizeof(*rt), tb, RTA_MAX, NULL);
797
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;
805
806 bitlen = (rt->rtm_family == AF_INET6) ? 128 : 32;
807
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))
819 goto out;
820
821 if (s->callback)
822 lua_pushvalue(s->L, 2);
823
824 lua_newtable(s->L);
825
826 L_setint(s->L, "type", rt->rtm_type);
827 L_setint(s->L, "family", (rt->rtm_family == AF_INET) ? 4 : 6);
828
829 L_setaddr(s->L, "dest", rt->rtm_family, dst, rt->rtm_dst_len);
830
831 if (gw)
832 L_setaddr(s->L, "gw", rt->rtm_family, gw, -1);
833
834 if (from)
835 L_setaddr(s->L, "from", rt->rtm_family, from, rt->rtm_src_len);
836
837 if (iif)
838 L_setdev(s->L, "iif", tb[RTA_IIF]);
839
840 if (oif)
841 L_setdev(s->L, "dev", tb[RTA_OIF]);
842
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);
846
847 if (src)
848 L_setaddr(s->L, "src", rt->rtm_family, src, -1);
849
850 if (tb[RTA_PRIORITY])
851 L_setint(s->L, "metric", RTA_U32(tb[RTA_PRIORITY]));
852
853 if (rt->rtm_family == AF_INET6 && tb[RTA_CACHEINFO])
854 {
855 struct rta_cacheinfo *ci = RTA_DATA(tb[RTA_CACHEINFO]);
856
857 if (ci->rta_expires)
858 {
859 if (ci->rta_expires)
860 L_setint(s->L, "expires", ci->rta_expires / hz);
861
862 if (ci->rta_error != 0)
863 L_setint(s->L, "error", ci->rta_error);
864 }
865 }
866
867 s->index++;
868
869 if (s->callback)
870 lua_call(s->L, 1, 0);
871 else if (hdr->nlmsg_flags & NLM_F_MULTI)
872 lua_rawseti(s->L, 3, s->index);
873
874 out:
875 s->pending = !!(hdr->nlmsg_flags & NLM_F_MULTI);
876 return NL_SKIP;
877 }
878
879 static int
880 cb_done(struct nl_msg *msg, void *arg)
881 {
882 struct dump_state *s = arg;
883 s->pending = 0;
884 return NL_STOP;
885 }
886
887 static int
888 cb_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
889 {
890 struct dump_state *s = arg;
891 s->pending = 0;
892 return NL_STOP;
893 }
894
895 static int _error(lua_State *L, int code, const char *msg)
896 {
897 lua_pushnil(L);
898 lua_pushnumber(L, code ? code : errno);
899 lua_pushstring(L, msg ? msg : strerror(errno));
900
901 return 3;
902 }
903
904 static int _route_dump(lua_State *L, struct dump_filter *filter)
905 {
906 int flags = NLM_F_REQUEST;
907 struct dump_state s = {
908 .L = L,
909 .pending = 1,
910 .index = 0,
911 .callback = lua_isfunction(L, 2),
912 .filter = filter
913 };
914
915 if (!hz)
916 hz = sysconf(_SC_CLK_TCK);
917
918 if (!sock)
919 {
920 sock = nl_socket_alloc();
921 if (!sock)
922 return _error(L, -1, "Out of memory");
923
924 if (nl_connect(sock, NETLINK_ROUTE))
925 return _error(L, 0, NULL);
926 }
927
928 struct nl_msg *msg;
929 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
930 struct rtmsg rtm = {
931 .rtm_family = filter->family,
932 .rtm_dst_len = filter->dst.bits,
933 .rtm_src_len = filter->src.bits
934 };
935
936 if (!filter->get)
937 flags |= NLM_F_DUMP;
938
939 msg = nlmsg_alloc_simple(RTM_GETROUTE, flags);
940 if (!msg)
941 goto out;
942
943 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
944
945 if (filter->get)
946 nla_put(msg, RTA_DST, filter->dst.len, &filter->dst.addr.v6);
947
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);
951
952 nl_send_auto_complete(sock, msg);
953
954 if (!filter->get && !s.callback)
955 lua_newtable(L);
956
957 while (s.pending > 0)
958 nl_recvmsgs(sock, cb);
959
960 nlmsg_free(msg);
961
962 out:
963 nl_cb_put(cb);
964 return (s.index > 0 && s.callback == 0);
965 }
966
967 static int route_get(lua_State *L)
968 {
969 struct dump_filter filter = { .get = true };
970 const char *dest = luaL_checkstring(L, 1);
971
972 if (!parse_cidr(dest, &filter.dst))
973 return _error(L, -1, "Invalid destination");
974
975 filter.family = filter.dst.family;
976
977 return _route_dump(L, &filter);
978 }
979
980 static int route_dump(lua_State *L)
981 {
982 const char *s;
983 cidr_t p = { };
984 struct dump_filter filter = { };
985
986 if (lua_type(L, 1) == LUA_TTABLE)
987 {
988 filter.family = L_getint(L, 1, "family");
989
990 if (filter.family == 4)
991 filter.family = AF_INET;
992 else if (filter.family == 6)
993 filter.family = AF_INET6;
994 else
995 filter.family = 0;
996
997 if ((s = L_getstr(L, 1, "iif")) != NULL)
998 filter.iif = if_nametoindex(s);
999
1000 if ((s = L_getstr(L, 1, "oif")) != NULL)
1001 filter.oif = if_nametoindex(s);
1002
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");
1007
1008 if ((s = L_getstr(L, 1, "gw")) != NULL && parse_cidr(s, &p))
1009 filter.gw = p;
1010
1011 if ((s = L_getstr(L, 1, "from")) != NULL && parse_cidr(s, &p))
1012 filter.from = p;
1013
1014 if ((s = L_getstr(L, 1, "src")) != NULL && parse_cidr(s, &p))
1015 filter.src = p;
1016
1017 if ((s = L_getstr(L, 1, "dest")) != NULL && parse_cidr(s, &p))
1018 filter.dst = p;
1019
1020 if ((s = L_getstr(L, 1, "from_exact")) != NULL && parse_cidr(s, &p))
1021 filter.from = p, filter.from.exact = true;
1022
1023 if ((s = L_getstr(L, 1, "dest_exact")) != NULL && parse_cidr(s, &p))
1024 filter.dst = p, filter.dst.exact = true;
1025 }
1026
1027 return _route_dump(L, &filter);
1028 }
1029
1030
1031 static int cb_dump_neigh(struct nl_msg *msg, void *arg)
1032 {
1033 char buf[32];
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];
1040
1041 if (hdr->nlmsg_type != RTM_NEWNEIGH ||
1042 (nd->ndm_family != AF_INET && nd->ndm_family != AF_INET6))
1043 return NL_SKIP;
1044
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)))
1048 goto out;
1049
1050 nlmsg_parse(hdr, sizeof(*nd), tb, NDA_MAX, NULL);
1051
1052 if (s->callback)
1053 lua_pushvalue(s->L, 2);
1054
1055 lua_newtable(s->L);
1056
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));
1059
1060 L_setbool(s->L, "router", (nd->ndm_flags & NTF_ROUTER));
1061 L_setbool(s->L, "proxy", (nd->ndm_flags & NTF_PROXY));
1062
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));
1071
1072 if (tb[NDA_DST])
1073 L_setaddr(s->L, "dest", nd->ndm_family, RTA_DATA(tb[NDA_DST]), -1);
1074
1075 if (tb[NDA_LLADDR])
1076 {
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]);
1082
1083 lua_pushstring(s->L, buf);
1084 lua_setfield(s->L, -2, "mac");
1085 }
1086
1087 s->index++;
1088
1089 if (s->callback)
1090 lua_call(s->L, 1, 0);
1091 else if (hdr->nlmsg_flags & NLM_F_MULTI)
1092 lua_rawseti(s->L, -2, s->index);
1093
1094 out:
1095 s->pending = !!(hdr->nlmsg_flags & NLM_F_MULTI);
1096 return NL_SKIP;
1097 }
1098
1099 static int neighbor_dump(lua_State *L)
1100 {
1101 const char *s;
1102 struct dump_filter filter = {
1103 .type = 0xFF & ~NUD_NOARP
1104 };
1105 struct dump_state st = {
1106 .callback = lua_isfunction(L, 2),
1107 .pending = 1,
1108 .filter = &filter,
1109 .L = L
1110 };
1111
1112 if (lua_type(L, 1) == LUA_TTABLE)
1113 {
1114 filter.family = L_getint(L, 1, "family");
1115
1116 if (filter.family == 4)
1117 filter.family = AF_INET;
1118 else if (filter.family == 6)
1119 filter.family = AF_INET6;
1120 else
1121 filter.family = 0;
1122
1123 if ((s = L_getstr(L, 1, "dev")) != NULL)
1124 filter.iif = if_nametoindex(s);
1125 }
1126
1127 if (!sock)
1128 {
1129 sock = nl_socket_alloc();
1130 if (!sock)
1131 return _error(L, -1, "Out of memory");
1132
1133 if (nl_connect(sock, NETLINK_ROUTE))
1134 return _error(L, 0, NULL);
1135 }
1136
1137 struct nl_msg *msg;
1138 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1139 struct ndmsg ndm = {
1140 .ndm_family = filter.family
1141 };
1142
1143 msg = nlmsg_alloc_simple(RTM_GETNEIGH, NLM_F_REQUEST | NLM_F_DUMP);
1144 if (!msg)
1145 goto out;
1146
1147 nlmsg_append(msg, &ndm, sizeof(ndm), 0);
1148
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);
1152
1153 nl_send_auto_complete(sock, msg);
1154
1155 if (!st.callback)
1156 lua_newtable(L);
1157
1158 while (st.pending > 0)
1159 nl_recvmsgs(sock, cb);
1160
1161 nlmsg_free(msg);
1162
1163 out:
1164 nl_cb_put(cb);
1165 return (st.index > 0 && st.callback == 0);
1166 }
1167
1168
1169 static const luaL_reg ip_methods[] = {
1170 { "new", cidr_new },
1171 { "IPv4", cidr_ipv4 },
1172 { "IPv6", cidr_ipv6 },
1173
1174 { "route", route_get },
1175 { "routes", route_dump },
1176
1177 { "neighbors", neighbor_dump },
1178
1179 { }
1180 };
1181
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 },
1202
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 },
1210
1211 { }
1212 };
1213
1214 int luaopen_luci_ip(lua_State *L)
1215 {
1216 luaL_register(L, LUCI_IP, ip_methods);
1217
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");
1222 lua_pop(L, 1);
1223
1224 return 1;
1225 }