1
2
3
4
5
6
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <unistd.h>
11#include <fcntl.h>
12#include <sys/socket.h>
13#include <netinet/in.h>
14#include <netinet/ip.h>
15#include <arpa/inet.h>
16#include <string.h>
17#include <linux/if.h>
18#include <linux/fib_rules.h>
19#include <errno.h>
20
21#include "rt_names.h"
22#include "utils.h"
23#include "ip_common.h"
24#include "json_print.h"
25
26#define PORT_MAX_MASK 0xFFFF
27#define DSCP_MAX_MASK 0x3F
28
29enum list_action {
30 IPRULE_LIST,
31 IPRULE_FLUSH,
32 IPRULE_SAVE,
33};
34
35extern struct rtnl_handle rth;
36
37static void usage(void) __attribute__((noreturn));
38
39static void usage(void)
40{
41 fprintf(stderr,
42 "Usage: ip rule { add | del } SELECTOR ACTION\n"
43 " ip rule { flush | save | restore }\n"
44 " ip rule [ list [ SELECTOR ]]\n"
45 "SELECTOR := [ not ] [ from PREFIX ] [ to PREFIX ] [ tos TOS ]\n"
46 " [ fwmark FWMARK[/MASK] ]\n"
47 " [ iif STRING ] [ oif STRING ] [ pref NUMBER ] [ l3mdev ]\n"
48 " [ uidrange NUMBER-NUMBER ]\n"
49 " [ ipproto PROTOCOL ]\n"
50 " [ sport [ NUMBER[/MASK] | NUMBER-NUMBER ]\n"
51 " [ dport [ NUMBER[/MASK] | NUMBER-NUMBER ] ]\n"
52 " [ dscp DSCP[/MASK] ] [ flowlabel FLOWLABEL[/MASK] ]\n"
53 "ACTION := [ table TABLE_ID ]\n"
54 " [ protocol PROTO ]\n"
55 " [ nat ADDRESS ]\n"
56 " [ realms [SRCREALM/]DSTREALM ]\n"
57 " [ goto NUMBER ]\n"
58 " SUPPRESSOR\n"
59 "SUPPRESSOR := [ suppress_prefixlength NUMBER ]\n"
60 " [ suppress_ifgroup DEVGROUP ]\n"
61 "TABLE_ID := [ local | main | default | NUMBER ]\n");
62 exit(-1);
63}
64
65static struct
66{
67 int not;
68 int l3mdev;
69 int iifmask, oifmask, uidrange;
70 unsigned int tb;
71 unsigned int tos, tosmask;
72 unsigned int pref, prefmask;
73 unsigned int fwmark, fwmask;
74 unsigned int dscp, dscpmask;
75 __u32 flowlabel, flowlabel_mask;
76 uint64_t tun_id;
77 char iif[IFNAMSIZ];
78 char oif[IFNAMSIZ];
79 struct fib_rule_uid_range range;
80 inet_prefix src;
81 inet_prefix dst;
82 int protocol;
83 int protocolmask;
84 struct fib_rule_port_range sport;
85 struct fib_rule_port_range dport;
86 __u16 sport_mask, dport_mask;
87 __u8 ipproto;
88} filter;
89
90static inline int frh_get_table(struct fib_rule_hdr *frh, struct rtattr **tb)
91{
92 __u32 table = frh->table;
93 if (tb[RTA_TABLE])
94 table = rta_getattr_u32(tb[RTA_TABLE]);
95 return table;
96}
97
98static bool filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
99{
100 struct fib_rule_hdr *frh = NLMSG_DATA(n);
101 __u32 table;
102
103 if (preferred_family != AF_UNSPEC && frh->family != preferred_family)
104 return false;
105
106 if (filter.prefmask &&
107 filter.pref ^ (tb[FRA_PRIORITY] ? rta_getattr_u32(tb[FRA_PRIORITY]) : 0))
108 return false;
109 if (filter.not && !(frh->flags & FIB_RULE_INVERT))
110 return false;
111
112 if (filter.src.family) {
113 inet_prefix *f_src = &filter.src;
114
115 if (f_src->family != frh->family ||
116 f_src->bitlen > frh->src_len)
117 return false;
118
119 if (inet_addr_match_rta(f_src, tb[FRA_SRC]))
120 return false;
121 }
122
123 if (filter.dst.family) {
124 inet_prefix *f_dst = &filter.dst;
125
126 if (f_dst->family != frh->family ||
127 f_dst->bitlen > frh->dst_len)
128 return false;
129
130 if (inet_addr_match_rta(f_dst, tb[FRA_DST]))
131 return false;
132 }
133
134 if (filter.tosmask && filter.tos ^ frh->tos)
135 return false;
136
137 if (filter.fwmark) {
138 __u32 mark = 0;
139
140 if (tb[FRA_FWMARK])
141 mark = rta_getattr_u32(tb[FRA_FWMARK]);
142 if (filter.fwmark ^ mark)
143 return false;
144 }
145 if (filter.fwmask) {
146 __u32 mask = 0;
147
148 if (tb[FRA_FWMASK])
149 mask = rta_getattr_u32(tb[FRA_FWMASK]);
150 if (filter.fwmask ^ mask)
151 return false;
152 }
153
154 if (filter.iifmask) {
155 if (tb[FRA_IFNAME]) {
156 if (strcmp(filter.iif, rta_getattr_str(tb[FRA_IFNAME])) != 0)
157 return false;
158 } else {
159 return false;
160 }
161 }
162
163 if (filter.oifmask) {
164 if (tb[FRA_OIFNAME]) {
165 if (strcmp(filter.oif, rta_getattr_str(tb[FRA_OIFNAME])) != 0)
166 return false;
167 } else {
168 return false;
169 }
170 }
171
172 if (filter.l3mdev && !(tb[FRA_L3MDEV] && rta_getattr_u8(tb[FRA_L3MDEV])))
173 return false;
174
175 if (filter.uidrange) {
176 struct fib_rule_uid_range *r = RTA_DATA(tb[FRA_UID_RANGE]);
177
178 if (!tb[FRA_UID_RANGE] ||
179 r->start != filter.range.start ||
180 r->end != filter.range.end)
181 return false;
182 }
183
184 if (filter.ipproto) {
185 __u8 ipproto = 0;
186
187 if (tb[FRA_IP_PROTO])
188 ipproto = rta_getattr_u8(tb[FRA_IP_PROTO]);
189 if (filter.ipproto != ipproto)
190 return false;
191 }
192
193 if (filter.sport_mask) {
194 const struct fib_rule_port_range *r;
195 __u16 sport_mask = PORT_MAX_MASK;
196
197 if (!tb[FRA_SPORT_RANGE])
198 return false;
199
200 r = RTA_DATA(tb[FRA_SPORT_RANGE]);
201 if (r->start != filter.sport.start ||
202 r->end != filter.sport.end)
203 return false;
204
205 if (tb[FRA_SPORT_MASK])
206 sport_mask = rta_getattr_u16(tb[FRA_SPORT_MASK]);
207 if (filter.sport_mask != sport_mask)
208 return false;
209 }
210
211 if (filter.dport_mask) {
212 const struct fib_rule_port_range *r;
213 __u16 dport_mask = PORT_MAX_MASK;
214
215 if (!tb[FRA_DPORT_RANGE])
216 return false;
217
218 r = RTA_DATA(tb[FRA_DPORT_RANGE]);
219 if (r->start != filter.dport.start ||
220 r->end != filter.dport.end)
221 return false;
222
223 if (tb[FRA_DPORT_MASK])
224 dport_mask = rta_getattr_u16(tb[FRA_DPORT_MASK]);
225 if (filter.dport_mask != dport_mask)
226 return false;
227 }
228
229 if (filter.tun_id) {
230 __u64 tun_id = 0;
231
232 if (tb[FRA_TUN_ID]) {
233 tun_id = ntohll(rta_getattr_u64(tb[FRA_TUN_ID]));
234 if (filter.tun_id != tun_id)
235 return false;
236 } else {
237 return false;
238 }
239 }
240
241 if (filter.dscpmask) {
242 __u8 dscp_mask = DSCP_MAX_MASK;
243 __u8 dscp;
244
245 if (!tb[FRA_DSCP])
246 return false;
247
248 dscp = rta_getattr_u8(tb[FRA_DSCP]);
249 if (filter.dscp != dscp)
250 return false;
251
252 if (tb[FRA_DSCP_MASK])
253 dscp_mask = rta_getattr_u8(tb[FRA_DSCP_MASK]);
254
255 if (filter.dscpmask != dscp_mask)
256 return false;
257 }
258
259 if (filter.flowlabel_mask) {
260 __u32 flowlabel, flowlabel_mask;
261
262 if (!tb[FRA_FLOWLABEL] || !tb[FRA_FLOWLABEL_MASK])
263 return false;
264 flowlabel = rta_getattr_be32(tb[FRA_FLOWLABEL]);
265 flowlabel_mask = rta_getattr_be32(tb[FRA_FLOWLABEL_MASK]);
266
267 if (filter.flowlabel != flowlabel ||
268 filter.flowlabel_mask != flowlabel_mask)
269 return false;
270 }
271
272 table = frh_get_table(frh, tb);
273 if (filter.tb > 0 && filter.tb ^ table)
274 return false;
275
276 return true;
277}
278
279int print_rule(struct nlmsghdr *n, void *arg)
280{
281 FILE *fp = arg;
282 struct fib_rule_hdr *frh = NLMSG_DATA(n);
283 int len = n->nlmsg_len;
284 int host_len = -1;
285 __u32 table, prio = 0;
286 struct rtattr *tb[FRA_MAX+1];
287 SPRINT_BUF(b1);
288
289 if (n->nlmsg_type != RTM_NEWRULE && n->nlmsg_type != RTM_DELRULE)
290 return 0;
291
292 len -= NLMSG_LENGTH(sizeof(*frh));
293 if (len < 0)
294 return -1;
295
296 parse_rtattr(tb, FRA_MAX, RTM_RTA(frh), len);
297
298 host_len = af_bit_len(frh->family);
299
300 if (!filter_nlmsg(n, tb, host_len))
301 return 0;
302
303 print_headers(fp, "[RULE]");
304
305 open_json_object(NULL);
306 if (n->nlmsg_type == RTM_DELRULE)
307 print_bool(PRINT_ANY, "deleted", "Deleted ", true);
308
309 if (tb[FRA_PRIORITY])
310 prio = rta_getattr_u32(tb[FRA_PRIORITY]);
311
312 print_uint(PRINT_ANY, "priority", "%u:\t", prio);
313
314 if (frh->flags & FIB_RULE_INVERT)
315 print_null(PRINT_ANY, "not", "not ", NULL);
316
317 if (tb[FRA_SRC]) {
318 const char *src = rt_addr_n2a_rta(frh->family, tb[FRA_SRC]);
319
320 print_string(PRINT_FP, NULL, "from ", NULL);
321 print_color_string(PRINT_ANY, ifa_family_color(frh->family),
322 "src", "%s", src);
323 if (frh->src_len != host_len)
324 print_uint(PRINT_ANY, "srclen", "/%u", frh->src_len);
325 } else if (frh->src_len) {
326 print_string(PRINT_ANY, "src", "from %s", "0");
327 print_uint(PRINT_ANY, "srclen", "/%u", frh->src_len);
328 } else {
329 print_string(PRINT_ANY, "src", "from %s", "all");
330 }
331
332 if (tb[FRA_DST]) {
333 const char *dst = rt_addr_n2a_rta(frh->family, tb[FRA_DST]);
334
335 print_string(PRINT_FP, NULL, " to ", NULL);
336 print_color_string(PRINT_ANY, ifa_family_color(frh->family),
337 "dst", "%s", dst);
338 if (frh->dst_len != host_len)
339 print_uint(PRINT_ANY, "dstlen", "/%u", frh->dst_len);
340 } else if (frh->dst_len) {
341 print_string(PRINT_ANY, "dst", " to %s", "0");
342 print_uint(PRINT_ANY, "dstlen", "/%u", frh->dst_len);
343 }
344
345 if (frh->tos) {
346 print_string(PRINT_ANY, "tos",
347 " tos %s",
348 rtnl_dsfield_n2a(frh->tos, b1, sizeof(b1)));
349 }
350
351 if (tb[FRA_FWMARK] || tb[FRA_FWMASK]) {
352 __u32 mark = 0, mask = 0;
353
354 if (tb[FRA_FWMARK])
355 mark = rta_getattr_u32(tb[FRA_FWMARK]);
356
357 if (tb[FRA_FWMASK] &&
358 (mask = rta_getattr_u32(tb[FRA_FWMASK])) != 0xFFFFFFFF) {
359 print_0xhex(PRINT_ANY, "fwmark", " fwmark %#llx", mark);
360 print_0xhex(PRINT_ANY, "fwmask", "/%#llx", mask);
361 } else {
362 print_0xhex(PRINT_ANY, "fwmark", " fwmark %#llx", mark);
363 }
364 }
365
366 if (tb[FRA_IFNAME]) {
367 if (!is_json_context())
368 fprintf(fp, " iif ");
369 print_color_string(PRINT_ANY, COLOR_IFNAME,
370 "iif", "%s",
371 rta_getattr_str(tb[FRA_IFNAME]));
372
373 if (frh->flags & FIB_RULE_IIF_DETACHED)
374 print_null(PRINT_ANY, "iif_detached", " [detached]",
375 NULL);
376 }
377
378 if (tb[FRA_OIFNAME]) {
379 if (!is_json_context())
380 fprintf(fp, " oif ");
381
382 print_color_string(PRINT_ANY, COLOR_IFNAME, "oif", "%s",
383 rta_getattr_str(tb[FRA_OIFNAME]));
384
385 if (frh->flags & FIB_RULE_OIF_DETACHED)
386 print_null(PRINT_ANY, "oif_detached", " [detached]",
387 NULL);
388 }
389
390 if (tb[FRA_L3MDEV]) {
391 __u8 mdev = rta_getattr_u8(tb[FRA_L3MDEV]);
392
393 if (mdev)
394 print_null(PRINT_ANY, "l3mdev",
395 " lookup [l3mdev-table]", NULL);
396 }
397
398 if (tb[FRA_UID_RANGE]) {
399 struct fib_rule_uid_range *r = RTA_DATA(tb[FRA_UID_RANGE]);
400
401 print_uint(PRINT_ANY, "uid_start", " uidrange %u", r->start);
402 print_uint(PRINT_ANY, "uid_end", "-%u", r->end);
403 }
404
405 if (tb[FRA_IP_PROTO]) {
406 SPRINT_BUF(pbuf);
407 print_string(PRINT_ANY, "ipproto", " ipproto %s",
408 inet_proto_n2a(rta_getattr_u8(tb[FRA_IP_PROTO]),
409 pbuf, sizeof(pbuf)));
410 }
411
412 if (tb[FRA_SPORT_RANGE]) {
413 struct fib_rule_port_range *r = RTA_DATA(tb[FRA_SPORT_RANGE]);
414
415 if (r->start == r->end) {
416 if (tb[FRA_SPORT_MASK]) {
417 __u16 mask;
418
419 mask = rta_getattr_u16(tb[FRA_SPORT_MASK]);
420 print_uint(PRINT_JSON, "sport", NULL, r->start);
421 print_0xhex(PRINT_JSON, "sport_mask", NULL,
422 mask);
423 if (mask == PORT_MAX_MASK) {
424 print_uint(PRINT_FP, NULL, " sport %u",
425 r->start);
426 } else {
427 print_0xhex(PRINT_FP, NULL,
428 " sport %#x", r->start);
429 print_0xhex(PRINT_FP, NULL, "/%#x",
430 mask);
431 }
432 } else {
433 print_uint(PRINT_ANY, "sport", " sport %u",
434 r->start);
435 }
436 } else {
437 print_uint(PRINT_ANY, "sport_start", " sport %u",
438 r->start);
439 print_uint(PRINT_ANY, "sport_end", "-%u", r->end);
440 }
441 }
442
443 if (tb[FRA_DPORT_RANGE]) {
444 struct fib_rule_port_range *r = RTA_DATA(tb[FRA_DPORT_RANGE]);
445
446 if (r->start == r->end) {
447 if (tb[FRA_DPORT_MASK]) {
448 __u16 mask;
449
450 mask = rta_getattr_u16(tb[FRA_DPORT_MASK]);
451 print_uint(PRINT_JSON, "dport", NULL, r->start);
452 print_0xhex(PRINT_JSON, "dport_mask", NULL,
453 mask);
454 if (mask == 0xFFFF) {
455 print_uint(PRINT_FP, NULL, " dport %u",
456 r->start);
457 } else {
458 print_0xhex(PRINT_FP, NULL,
459 " dport %#x", r->start);
460 print_0xhex(PRINT_FP, NULL, "/%#x",
461 mask);
462 }
463 } else {
464 print_uint(PRINT_ANY, "dport", " dport %u",
465 r->start);
466 }
467 } else {
468 print_uint(PRINT_ANY, "dport_start", " dport %u",
469 r->start);
470 print_uint(PRINT_ANY, "dport_end", "-%u", r->end);
471 }
472 }
473
474 if (tb[FRA_TUN_ID]) {
475 __u64 tun_id = ntohll(rta_getattr_u64(tb[FRA_TUN_ID]));
476
477 print_u64(PRINT_ANY, "tun_id", " tun_id %llu", tun_id);
478 }
479
480 table = frh_get_table(frh, tb);
481 if (table) {
482 print_string(PRINT_ANY, "table",
483 " lookup %s",
484 rtnl_rttable_n2a(table, b1, sizeof(b1)));
485
486 if (tb[FRA_SUPPRESS_PREFIXLEN]) {
487 int pl = rta_getattr_u32(tb[FRA_SUPPRESS_PREFIXLEN]);
488
489 if (pl != -1)
490 print_int(PRINT_ANY, "suppress_prefixlen",
491 " suppress_prefixlength %d", pl);
492 }
493
494 if (tb[FRA_SUPPRESS_IFGROUP]) {
495 int group = rta_getattr_u32(tb[FRA_SUPPRESS_IFGROUP]);
496
497 if (group != -1) {
498 const char *grname
499 = rtnl_group_n2a(group, b1, sizeof(b1));
500
501 print_string(PRINT_ANY, "suppress_ifgroup",
502 " suppress_ifgroup %s", grname);
503 }
504 }
505 }
506
507 if (tb[FRA_FLOW]) {
508 __u32 to = rta_getattr_u32(tb[FRA_FLOW]);
509 __u32 from = to>>16;
510
511 to &= 0xFFFF;
512 if (from)
513 print_string(PRINT_ANY,
514 "flow_from", " realms %s/",
515 rtnl_rtrealm_n2a(from, b1, sizeof(b1)));
516 else
517 print_string(PRINT_FP, NULL, " realms ", NULL);
518
519 print_string(PRINT_ANY, "flow_to", "%s",
520 rtnl_rtrealm_n2a(to, b1, sizeof(b1)));
521 }
522
523 if (frh->action == RTN_NAT) {
524 if (tb[RTA_GATEWAY]) {
525 const char *gateway;
526
527 gateway = format_host_rta(frh->family, tb[RTA_GATEWAY]);
528
529 print_string(PRINT_ANY, "nat_gateway",
530 " map-to %s", gateway);
531 } else {
532 print_null(PRINT_ANY, "masquerade", " masquerade", NULL);
533 }
534 } else if (frh->action == FR_ACT_GOTO) {
535 if (tb[FRA_GOTO])
536 print_uint(PRINT_ANY, "goto", " goto %u",
537 rta_getattr_u32(tb[FRA_GOTO]));
538 else
539 print_string(PRINT_ANY, "goto", " goto %s", "none");
540
541 if (frh->flags & FIB_RULE_UNRESOLVED)
542 print_null(PRINT_ANY, "unresolved",
543 " [unresolved]", NULL);
544 } else if (frh->action == FR_ACT_NOP) {
545 print_null(PRINT_ANY, "nop", " nop", NULL);
546 } else if (frh->action != FR_ACT_TO_TBL) {
547 print_string(PRINT_ANY, "action", " %s",
548 rtnl_rtntype_n2a(frh->action, b1, sizeof(b1)));
549 }
550
551 if (tb[FRA_PROTOCOL]) {
552 __u8 protocol = rta_getattr_u8(tb[FRA_PROTOCOL]);
553
554 if ((protocol && protocol != RTPROT_KERNEL) || show_details > 0) {
555 print_string(PRINT_ANY, "protocol", " proto %s",
556 rtnl_rtprot_n2a(protocol, b1, sizeof(b1)));
557 }
558 }
559
560 if (tb[FRA_DSCP]) {
561 __u8 dscp = rta_getattr_u8(tb[FRA_DSCP]);
562
563 if (tb[FRA_DSCP_MASK]) {
564 __u8 mask = rta_getattr_u8(tb[FRA_DSCP_MASK]);
565
566 print_string(PRINT_JSON, "dscp", NULL,
567 rtnl_dscp_n2a(dscp, b1, sizeof(b1)));
568 print_0xhex(PRINT_JSON, "dscp_mask", NULL, mask);
569 if (mask == DSCP_MAX_MASK) {
570 print_string(PRINT_FP, NULL, " dscp %s",
571 rtnl_dscp_n2a(dscp, b1,
572 sizeof(b1)));
573 } else {
574 print_0xhex(PRINT_FP, NULL, " dscp %#x", dscp);
575 print_0xhex(PRINT_FP, NULL, "/%#x", mask);
576 }
577 } else {
578 print_string(PRINT_ANY, "dscp", " dscp %s",
579 rtnl_dscp_n2a(dscp, b1, sizeof(b1)));
580 }
581 }
582
583
584 if (tb[FRA_FLOWLABEL] && tb[FRA_FLOWLABEL_MASK]) {
585 __u32 flowlabel, flowlabel_mask;
586
587 flowlabel = rta_getattr_be32(tb[FRA_FLOWLABEL]);
588 flowlabel_mask = rta_getattr_be32(tb[FRA_FLOWLABEL_MASK]);
589
590 print_0xhex(PRINT_ANY, "flowlabel", " flowlabel %#llx",
591 flowlabel);
592 if (flowlabel_mask == LABEL_MAX_MASK)
593 print_0xhex(PRINT_JSON, "flowlabel_mask", NULL,
594 flowlabel_mask);
595 else
596 print_0xhex(PRINT_ANY, "flowlabel_mask", "/%#llx",
597 flowlabel_mask);
598 }
599
600 print_string(PRINT_FP, NULL, "\n", "");
601 close_json_object();
602 fflush(fp);
603 return 0;
604}
605
606static __u32 rule_dump_magic = 0x71706986;
607
608static int save_rule_prep(void)
609{
610 int ret;
611
612 if (isatty(STDOUT_FILENO)) {
613 fprintf(stderr, "Not sending a binary stream to stdout\n");
614 return -1;
615 }
616
617 ret = write(STDOUT_FILENO, &rule_dump_magic, sizeof(rule_dump_magic));
618 if (ret != sizeof(rule_dump_magic)) {
619 fprintf(stderr, "Can't write magic to dump file\n");
620 return -1;
621 }
622
623 return 0;
624}
625
626static int save_rule(struct nlmsghdr *n, void *arg)
627{
628 int ret;
629
630 ret = write(STDOUT_FILENO, n, n->nlmsg_len);
631 if ((ret > 0) && (ret != n->nlmsg_len)) {
632 fprintf(stderr, "Short write while saving nlmsg\n");
633 ret = -EIO;
634 }
635
636 return ret == n->nlmsg_len ? 0 : ret;
637}
638
639static int flush_rule(struct nlmsghdr *n, void *arg)
640{
641 struct rtnl_handle rth2;
642 struct fib_rule_hdr *frh = NLMSG_DATA(n);
643 int len = n->nlmsg_len;
644 struct rtattr *tb[FRA_MAX+1];
645 int host_len = -1;
646
647 len -= NLMSG_LENGTH(sizeof(*frh));
648 if (len < 0)
649 return -1;
650
651 parse_rtattr(tb, FRA_MAX, RTM_RTA(frh), len);
652
653 host_len = af_bit_len(frh->family);
654 if (!filter_nlmsg(n, tb, host_len))
655 return 0;
656
657 if (tb[FRA_PROTOCOL]) {
658 __u8 protocol = rta_getattr_u8(tb[FRA_PROTOCOL]);
659
660 if ((filter.protocol ^ protocol) & filter.protocolmask)
661 return 0;
662 }
663
664 if (tb[FRA_PRIORITY]) {
665 n->nlmsg_type = RTM_DELRULE;
666 n->nlmsg_flags = NLM_F_REQUEST;
667
668 if (rtnl_open(&rth2, 0) < 0)
669 return -1;
670
671 if (rtnl_talk(&rth2, n, NULL) < 0)
672 return -2;
673
674 rtnl_close(&rth2);
675 }
676
677 return 0;
678}
679
680static void iprule_port_parse(char *arg, struct fib_rule_port_range *r,
681 __u16 *mask)
682{
683 char *sep;
684
685 *mask = PORT_MAX_MASK;
686
687 sep = strchr(arg, '-');
688 if (sep) {
689 *sep = '\0';
690
691 if (get_u16(&r->start, arg, 0))
692 invarg("invalid port range start", arg);
693
694 if (get_u16(&r->end, sep + 1, 0))
695 invarg("invalid port range end", sep + 1);
696
697 return;
698 }
699
700 sep = strchr(arg, '/');
701 if (sep) {
702 *sep = '\0';
703
704 if (get_u16(mask, sep + 1, 0))
705 invarg("invalid mask", sep + 1);
706 }
707
708 if (get_u16(&r->start, arg, 0))
709 invarg("invalid port", arg);
710
711 r->end = r->start;
712}
713
714static void iprule_dscp_parse(char *arg, __u32 *dscp, __u32 *mask)
715{
716 char *slash;
717
718 *mask = DSCP_MAX_MASK;
719
720 slash = strchr(arg, '/');
721 if (slash != NULL)
722 *slash = '\0';
723 if (rtnl_dscp_a2n(dscp, arg))
724 invarg("invalid dscp", arg);
725 if (slash && get_u32(mask, slash + 1, 0))
726 invarg("invalid dscp mask", slash + 1);
727}
728
729static void iprule_flowlabel_parse(char *arg, __u32 *flowlabel,
730 __u32 *flowlabel_mask)
731{
732 char *slash;
733
734 slash = strchr(arg, '/');
735 if (slash != NULL)
736 *slash = '\0';
737 if (get_u32(flowlabel, arg, 0))
738 invarg("invalid flowlabel", arg);
739 if (slash) {
740 if (get_u32(flowlabel_mask, slash + 1, 0))
741 invarg("invalid flowlabel mask", slash + 1);
742 } else {
743 *flowlabel_mask = LABEL_MAX_MASK;
744 }
745}
746
747static int iprule_list_flush_or_save(int argc, char **argv, int action)
748{
749 rtnl_filter_t filter_fn;
750 int af = preferred_family;
751
752 if (af == AF_UNSPEC)
753 af = AF_INET;
754
755 if (action == IPRULE_SAVE && argc > 0) {
756 fprintf(stderr, "\"ip rule save\" does not take any arguments.\n");
757 return -1;
758 }
759
760 switch (action) {
761 case IPRULE_SAVE:
762 if (save_rule_prep())
763 return -1;
764 filter_fn = save_rule;
765 break;
766 case IPRULE_FLUSH:
767 filter_fn = flush_rule;
768 break;
769 default:
770 filter_fn = print_rule;
771 }
772
773 memset(&filter, 0, sizeof(filter));
774
775 while (argc > 0) {
776 if (matches(*argv, "preference") == 0 ||
777 matches(*argv, "order") == 0 ||
778 matches(*argv, "priority") == 0) {
779 __u32 pref;
780
781 NEXT_ARG();
782 if (get_u32(&pref, *argv, 0))
783 invarg("preference value is invalid\n", *argv);
784 filter.pref = pref;
785 filter.prefmask = 1;
786 } else if (strcmp(*argv, "not") == 0) {
787 filter.not = 1;
788 } else if (strcmp(*argv, "tos") == 0 ||
789 strcmp(*argv, "dsfield") == 0) {
790 __u32 tos;
791
792 NEXT_ARG();
793 if (rtnl_dsfield_a2n(&tos, *argv))
794 invarg("TOS value is invalid\n", *argv);
795 filter.tos = tos;
796 filter.tosmask = 1;
797 } else if (strcmp(*argv, "fwmark") == 0) {
798 char *slash;
799 __u32 fwmark, fwmask;
800
801 NEXT_ARG();
802 slash = strchr(*argv, '/');
803 if (slash != NULL)
804 *slash = '\0';
805 if (get_u32(&fwmark, *argv, 0))
806 invarg("fwmark value is invalid\n", *argv);
807 filter.fwmark = fwmark;
808 if (slash) {
809 if (get_u32(&fwmask, slash+1, 0))
810 invarg("fwmask value is invalid\n",
811 slash+1);
812 filter.fwmask = fwmask;
813 }
814 } else if (strcmp(*argv, "dev") == 0 ||
815 strcmp(*argv, "iif") == 0) {
816 NEXT_ARG();
817 if (get_ifname(filter.iif, *argv))
818 invarg("\"iif\"/\"dev\" not a valid ifname", *argv);
819 filter.iifmask = 1;
820 } else if (strcmp(*argv, "oif") == 0) {
821 NEXT_ARG();
822 if (get_ifname(filter.oif, *argv))
823 invarg("\"oif\" not a valid ifname", *argv);
824 filter.oifmask = 1;
825 } else if (strcmp(*argv, "l3mdev") == 0) {
826 filter.l3mdev = 1;
827 } else if (strcmp(*argv, "uidrange") == 0) {
828 NEXT_ARG();
829 filter.uidrange = 1;
830 if (sscanf(*argv, "%u-%u",
831 &filter.range.start,
832 &filter.range.end) != 2)
833 invarg("invalid UID range\n", *argv);
834
835 } else if (matches(*argv, "tun_id") == 0) {
836 __u64 tun_id;
837
838 NEXT_ARG();
839 if (get_u64(&tun_id, *argv, 0))
840 invarg("\"tun_id\" value is invalid\n", *argv);
841 filter.tun_id = tun_id;
842 } else if (matches(*argv, "lookup") == 0 ||
843 matches(*argv, "table") == 0) {
844 __u32 tid;
845
846 NEXT_ARG();
847 if (rtnl_rttable_a2n(&tid, *argv))
848 invarg("table id value is invalid\n", *argv);
849 filter.tb = tid;
850 } else if (matches(*argv, "from") == 0 ||
851 matches(*argv, "src") == 0) {
852 NEXT_ARG();
853 if (get_prefix(&filter.src, *argv, af))
854 invarg("from value is invalid\n", *argv);
855 } else if (matches(*argv, "protocol") == 0) {
856 __u32 prot;
857 NEXT_ARG();
858 filter.protocolmask = -1;
859 if (rtnl_rtprot_a2n(&prot, *argv)) {
860 if (strcmp(*argv, "all") != 0)
861 invarg("invalid \"protocol\"\n", *argv);
862 prot = 0;
863 filter.protocolmask = 0;
864 }
865 filter.protocol = prot;
866 } else if (strcmp(*argv, "ipproto") == 0) {
867 int ipproto;
868
869 NEXT_ARG();
870 ipproto = inet_proto_a2n(*argv);
871 if (ipproto < 0)
872 invarg("Invalid \"ipproto\" value\n", *argv);
873 filter.ipproto = ipproto;
874 } else if (strcmp(*argv, "sport") == 0) {
875 NEXT_ARG();
876 iprule_port_parse(*argv, &filter.sport,
877 &filter.sport_mask);
878 } else if (strcmp(*argv, "dport") == 0) {
879 NEXT_ARG();
880 iprule_port_parse(*argv, &filter.dport,
881 &filter.dport_mask);
882 } else if (strcmp(*argv, "dscp") == 0) {
883 NEXT_ARG();
884 iprule_dscp_parse(*argv, &filter.dscp,
885 &filter.dscpmask);
886 } else if (strcmp(*argv, "flowlabel") == 0) {
887 NEXT_ARG();
888
889 iprule_flowlabel_parse(*argv, &filter.flowlabel,
890 &filter.flowlabel_mask);
891 } else {
892 if (matches(*argv, "dst") == 0 ||
893 matches(*argv, "to") == 0) {
894 NEXT_ARG();
895 }
896 if (get_prefix(&filter.dst, *argv, af))
897 invarg("to value is invalid\n", *argv);
898 }
899 argc--; argv++;
900 }
901
902 if (rtnl_ruledump_req(&rth, af) < 0) {
903 perror("Cannot send dump request");
904 return 1;
905 }
906
907 new_json_obj(json);
908 if (rtnl_dump_filter(&rth, filter_fn, stdout) < 0) {
909 fprintf(stderr, "Dump terminated\n");
910 delete_json_obj();
911 return 1;
912 }
913 delete_json_obj();
914
915 return 0;
916}
917
918static int rule_dump_check_magic(void)
919{
920 int ret;
921 __u32 magic = 0;
922
923 if (isatty(STDIN_FILENO)) {
924 fprintf(stderr, "Can't restore rule dump from a terminal\n");
925 return -1;
926 }
927
928 ret = fread(&magic, sizeof(magic), 1, stdin);
929 if (magic != rule_dump_magic) {
930 fprintf(stderr, "Magic mismatch (%d elems, %x magic)\n",
931 ret, magic);
932 return -1;
933 }
934
935 return 0;
936}
937
938static int restore_handler(struct rtnl_ctrl_data *ctrl,
939 struct nlmsghdr *n, void *arg)
940{
941 int ret;
942
943 n->nlmsg_flags |= NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK;
944
945 ll_init_map(&rth);
946
947 ret = rtnl_talk(&rth, n, NULL);
948 if ((ret < 0) && (errno == EEXIST))
949 ret = 0;
950
951 return ret;
952}
953
954
955static int iprule_restore(void)
956{
957 if (rule_dump_check_magic())
958 exit(-1);
959
960 exit(rtnl_from_file(stdin, &restore_handler, NULL));
961}
962
963static int iprule_modify(int cmd, int argc, char **argv)
964{
965 int l3mdev_rule = 0;
966 int table_ok = 0;
967 __u32 tid = 0;
968 struct {
969 struct nlmsghdr n;
970 struct fib_rule_hdr frh;
971 char buf[1024];
972 } req = {
973 .n.nlmsg_type = cmd,
974 .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct fib_rule_hdr)),
975 .n.nlmsg_flags = NLM_F_REQUEST,
976 .frh.family = preferred_family,
977 .frh.action = FR_ACT_UNSPEC,
978 };
979 int ret;
980
981 if (cmd == RTM_NEWRULE) {
982 if (argc == 0) {
983 fprintf(stderr,
984 "\"ip rule add\" requires arguments.\n");
985 return -1;
986 }
987 req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;
988 req.frh.action = FR_ACT_TO_TBL;
989 }
990
991 if (cmd == RTM_DELRULE && argc == 0) {
992 fprintf(stderr, "\"ip rule del\" requires arguments.\n");
993 return -1;
994 }
995
996 while (argc > 0) {
997 if (strcmp(*argv, "not") == 0) {
998 req.frh.flags |= FIB_RULE_INVERT;
999 } else if (strcmp(*argv, "from") == 0) {
1000 inet_prefix dst;
1001
1002 NEXT_ARG();
1003 get_prefix(&dst, *argv, req.frh.family);
1004 req.frh.src_len = dst.bitlen;
1005 addattr_l(&req.n, sizeof(req), FRA_SRC,
1006 &dst.data, dst.bytelen);
1007 } else if (strcmp(*argv, "to") == 0) {
1008 inet_prefix dst;
1009
1010 NEXT_ARG();
1011 get_prefix(&dst, *argv, req.frh.family);
1012 req.frh.dst_len = dst.bitlen;
1013 addattr_l(&req.n, sizeof(req), FRA_DST,
1014 &dst.data, dst.bytelen);
1015 } else if (matches(*argv, "preference") == 0 ||
1016 matches(*argv, "order") == 0 ||
1017 matches(*argv, "priority") == 0) {
1018 __u32 pref;
1019
1020 NEXT_ARG();
1021 if (get_u32(&pref, *argv, 0))
1022 invarg("preference value is invalid\n", *argv);
1023 addattr32(&req.n, sizeof(req), FRA_PRIORITY, pref);
1024 } else if (strcmp(*argv, "tos") == 0 ||
1025 matches(*argv, "dsfield") == 0) {
1026 __u32 tos;
1027
1028 NEXT_ARG();
1029 if (rtnl_dsfield_a2n(&tos, *argv))
1030 invarg("TOS value is invalid\n", *argv);
1031 req.frh.tos = tos;
1032 } else if (strcmp(*argv, "fwmark") == 0) {
1033 char *slash;
1034 __u32 fwmark, fwmask;
1035
1036 NEXT_ARG();
1037
1038 slash = strchr(*argv, '/');
1039 if (slash != NULL)
1040 *slash = '\0';
1041 if (get_u32(&fwmark, *argv, 0))
1042 invarg("fwmark value is invalid\n", *argv);
1043 addattr32(&req.n, sizeof(req), FRA_FWMARK, fwmark);
1044 if (slash) {
1045 if (get_u32(&fwmask, slash+1, 0))
1046 invarg("fwmask value is invalid\n",
1047 slash+1);
1048 addattr32(&req.n, sizeof(req),
1049 FRA_FWMASK, fwmask);
1050 }
1051 } else if (matches(*argv, "realms") == 0) {
1052 __u32 realm;
1053
1054 NEXT_ARG();
1055 if (get_rt_realms_or_raw(&realm, *argv))
1056 invarg("invalid realms\n", *argv);
1057 addattr32(&req.n, sizeof(req), FRA_FLOW, realm);
1058 } else if (matches(*argv, "protocol") == 0) {
1059 __u32 proto;
1060
1061 NEXT_ARG();
1062 if (rtnl_rtprot_a2n(&proto, *argv))
1063 invarg("\"protocol\" value is invalid\n", *argv);
1064 addattr8(&req.n, sizeof(req), FRA_PROTOCOL, proto);
1065 } else if (matches(*argv, "tun_id") == 0) {
1066 __u64 tun_id;
1067
1068 NEXT_ARG();
1069 if (get_be64(&tun_id, *argv, 0))
1070 invarg("\"tun_id\" value is invalid\n", *argv);
1071 addattr64(&req.n, sizeof(req), FRA_TUN_ID, tun_id);
1072 } else if (matches(*argv, "table") == 0 ||
1073 strcmp(*argv, "lookup") == 0) {
1074 NEXT_ARG();
1075 if (rtnl_rttable_a2n(&tid, *argv))
1076 invarg("invalid table ID\n", *argv);
1077 if (tid < 256)
1078 req.frh.table = tid;
1079 else {
1080 req.frh.table = RT_TABLE_UNSPEC;
1081 addattr32(&req.n, sizeof(req), FRA_TABLE, tid);
1082 }
1083 table_ok = 1;
1084 } else if (matches(*argv, "suppress_prefixlength") == 0 ||
1085 strcmp(*argv, "sup_pl") == 0) {
1086 int pl;
1087
1088 NEXT_ARG();
1089 if (get_s32(&pl, *argv, 0) || pl < 0)
1090 invarg("suppress_prefixlength value is invalid\n",
1091 *argv);
1092 addattr32(&req.n, sizeof(req),
1093 FRA_SUPPRESS_PREFIXLEN, pl);
1094 } else if (matches(*argv, "suppress_ifgroup") == 0 ||
1095 strcmp(*argv, "sup_group") == 0) {
1096 NEXT_ARG();
1097 int group;
1098
1099 if (rtnl_group_a2n(&group, *argv))
1100 invarg("Invalid \"suppress_ifgroup\" value\n",
1101 *argv);
1102 addattr32(&req.n, sizeof(req),
1103 FRA_SUPPRESS_IFGROUP, group);
1104 } else if (strcmp(*argv, "dev") == 0 ||
1105 strcmp(*argv, "iif") == 0) {
1106 NEXT_ARG();
1107 if (check_ifname(*argv))
1108 invarg("\"iif\"/\"dev\" not a valid ifname", *argv);
1109 addattr_l(&req.n, sizeof(req), FRA_IFNAME,
1110 *argv, strlen(*argv)+1);
1111 } else if (strcmp(*argv, "oif") == 0) {
1112 NEXT_ARG();
1113 if (check_ifname(*argv))
1114 invarg("\"oif\" not a valid ifname", *argv);
1115 addattr_l(&req.n, sizeof(req), FRA_OIFNAME,
1116 *argv, strlen(*argv)+1);
1117 } else if (strcmp(*argv, "l3mdev") == 0) {
1118 addattr8(&req.n, sizeof(req), FRA_L3MDEV, 1);
1119 table_ok = 1;
1120 l3mdev_rule = 1;
1121 } else if (strcmp(*argv, "uidrange") == 0) {
1122 struct fib_rule_uid_range r;
1123
1124 NEXT_ARG();
1125 if (sscanf(*argv, "%u-%u", &r.start, &r.end) != 2)
1126 invarg("invalid UID range\n", *argv);
1127 addattr_l(&req.n, sizeof(req), FRA_UID_RANGE, &r,
1128 sizeof(r));
1129 } else if (strcmp(*argv, "nat") == 0 ||
1130 matches(*argv, "map-to") == 0) {
1131 NEXT_ARG();
1132 fprintf(stderr, "Warning: route NAT is deprecated\n");
1133 addattr32(&req.n, sizeof(req), RTA_GATEWAY,
1134 get_addr32(*argv));
1135 req.frh.action = RTN_NAT;
1136 } else if (strcmp(*argv, "ipproto") == 0) {
1137 int ipproto;
1138
1139 NEXT_ARG();
1140 ipproto = inet_proto_a2n(*argv);
1141 if (ipproto < 0)
1142 invarg("Invalid \"ipproto\" value\n",
1143 *argv);
1144 addattr8(&req.n, sizeof(req), FRA_IP_PROTO, ipproto);
1145 } else if (strcmp(*argv, "sport") == 0) {
1146 struct fib_rule_port_range r;
1147 __u16 sport_mask;
1148
1149 NEXT_ARG();
1150 iprule_port_parse(*argv, &r, &sport_mask);
1151 addattr_l(&req.n, sizeof(req), FRA_SPORT_RANGE, &r,
1152 sizeof(r));
1153 if (sport_mask != PORT_MAX_MASK)
1154 addattr16(&req.n, sizeof(req), FRA_SPORT_MASK,
1155 sport_mask);
1156 } else if (strcmp(*argv, "dport") == 0) {
1157 struct fib_rule_port_range r;
1158 __u16 dport_mask;
1159
1160 NEXT_ARG();
1161 iprule_port_parse(*argv, &r, &dport_mask);
1162 addattr_l(&req.n, sizeof(req), FRA_DPORT_RANGE, &r,
1163 sizeof(r));
1164 if (dport_mask != PORT_MAX_MASK)
1165 addattr16(&req.n, sizeof(req), FRA_DPORT_MASK,
1166 dport_mask);
1167 } else if (strcmp(*argv, "dscp") == 0) {
1168 __u32 dscp, dscp_mask;
1169
1170 NEXT_ARG();
1171 iprule_dscp_parse(*argv, &dscp, &dscp_mask);
1172 addattr8(&req.n, sizeof(req), FRA_DSCP, dscp);
1173 if (dscp_mask != DSCP_MAX_MASK)
1174 addattr8(&req.n, sizeof(req), FRA_DSCP_MASK,
1175 dscp_mask);
1176 } else if (strcmp(*argv, "flowlabel") == 0) {
1177 __u32 flowlabel, flowlabel_mask;
1178
1179 NEXT_ARG();
1180 iprule_flowlabel_parse(*argv, &flowlabel,
1181 &flowlabel_mask);
1182 addattr32(&req.n, sizeof(req), FRA_FLOWLABEL,
1183 htonl(flowlabel));
1184 addattr32(&req.n, sizeof(req), FRA_FLOWLABEL_MASK,
1185 htonl(flowlabel_mask));
1186 } else {
1187 int type;
1188
1189 if (strcmp(*argv, "type") == 0)
1190 NEXT_ARG();
1191
1192 if (matches(*argv, "help") == 0)
1193 usage();
1194 else if (matches(*argv, "goto") == 0) {
1195 __u32 target;
1196
1197 type = FR_ACT_GOTO;
1198 NEXT_ARG();
1199 if (get_u32(&target, *argv, 0))
1200 invarg("invalid target\n", *argv);
1201 addattr32(&req.n, sizeof(req),
1202 FRA_GOTO, target);
1203 } else if (matches(*argv, "nop") == 0)
1204 type = FR_ACT_NOP;
1205 else if (rtnl_rtntype_a2n(&type, *argv))
1206 invarg("Failed to parse rule type", *argv);
1207 req.frh.action = type;
1208 table_ok = 1;
1209 }
1210 argc--;
1211 argv++;
1212 }
1213
1214 if (l3mdev_rule && tid != 0) {
1215 fprintf(stderr,
1216 "table can not be specified for l3mdev rules\n");
1217 return -EINVAL;
1218 }
1219
1220 if (req.frh.family == AF_UNSPEC)
1221 req.frh.family = AF_INET;
1222
1223 if (!table_ok && cmd == RTM_NEWRULE)
1224 req.frh.table = RT_TABLE_MAIN;
1225
1226 if (echo_request)
1227 ret = rtnl_echo_talk(&rth, &req.n, json, print_rule);
1228 else
1229 ret = rtnl_talk(&rth, &req.n, NULL);
1230
1231 if (ret)
1232 return -2;
1233
1234 return 0;
1235}
1236
1237int do_iprule(int argc, char **argv)
1238{
1239 if (argc < 1) {
1240 return iprule_list_flush_or_save(0, NULL, IPRULE_LIST);
1241 } else if (matches(argv[0], "list") == 0 ||
1242 matches(argv[0], "lst") == 0 ||
1243 matches(argv[0], "show") == 0) {
1244 return iprule_list_flush_or_save(argc-1, argv+1, IPRULE_LIST);
1245 } else if (matches(argv[0], "save") == 0) {
1246 return iprule_list_flush_or_save(argc-1, argv+1, IPRULE_SAVE);
1247 } else if (matches(argv[0], "restore") == 0) {
1248 return iprule_restore();
1249 } else if (matches(argv[0], "add") == 0) {
1250 return iprule_modify(RTM_NEWRULE, argc-1, argv+1);
1251 } else if (matches(argv[0], "delete") == 0) {
1252 return iprule_modify(RTM_DELRULE, argc-1, argv+1);
1253 } else if (matches(argv[0], "flush") == 0) {
1254 return iprule_list_flush_or_save(argc-1, argv+1, IPRULE_FLUSH);
1255 } else if (matches(argv[0], "help") == 0)
1256 usage();
1257
1258 fprintf(stderr,
1259 "Command \"%s\" is unknown, try \"ip rule help\".\n", *argv);
1260 exit(-1);
1261}
1262
1263int do_multirule(int argc, char **argv)
1264{
1265 switch (preferred_family) {
1266 case AF_UNSPEC:
1267 case AF_INET:
1268 preferred_family = RTNL_FAMILY_IPMR;
1269 break;
1270 case AF_INET6:
1271 preferred_family = RTNL_FAMILY_IP6MR;
1272 break;
1273 case RTNL_FAMILY_IPMR:
1274 case RTNL_FAMILY_IP6MR:
1275 break;
1276 default:
1277 fprintf(stderr,
1278 "Multicast rules are only supported for IPv4/IPv6, was: %i\n",
1279 preferred_family);
1280 exit(-1);
1281 }
1282
1283 return do_iprule(argc, argv);
1284}
1285