aboutsummaryrefslogtreecommitdiffstats
path: root/package/utils/busybox/patches/302-ip-rule-add-suppress-prefixlength.patch
blob: 7b4797505e2fa5a3a779271dc3a34adc12b09e20 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
From dbac30c3784c267bbe44a2a3ebed4e827c8fe82a Mon Sep 17 00:00:00 2001
From: Stefan Tomanek <stefan.tomanek@wertarbyte.de>
Date: Tue, 13 Jun 2017 19:06:09 +0200
Subject: [PATCH] ip rule: add suppress_{prefixlength,ifgroup} options

(cherry-picked from 192dce4b84fb32346ebc5194de7daa5da3b8d1b4)

function                                             old     new   delta
iprule_modify                                        816     887     +71
print_rule                                           610     680     +70
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 141/0)             Total: 141 bytes

Signed-off-by: Stefan Tomanek <stefan.tomanek@wertarbyte.de>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 networking/libiproute/iprule.c | 73 ++++++++++++++++++++++++++----------------
 1 file changed, 46 insertions(+), 27 deletions(-)

--- a/networking/libiproute/iprule.c
+++ b/networking/libiproute/iprule.c
@@ -17,25 +17,32 @@
 #include <netinet/ip.h>
 #include <arpa/inet.h>
 
+/* from <linux/fib_rules.h>: */
+#define FRA_SUPPRESS_IFGROUP   13
+#define FRA_SUPPRESS_PREFIXLEN 14
+
 #include "ip_common.h"  /* #include "libbb.h" is inside */
 #include "rt_names.h"
 #include "utils.h"
 
-/*
-static void usage(void) __attribute__((noreturn));
-
-static void usage(void)
-{
-	fprintf(stderr, "Usage: ip rule [ list | add | del ] SELECTOR ACTION\n");
-	fprintf(stderr, "SELECTOR := [ from PREFIX ] [ to PREFIX ] [ tos TOS ] [ fwmark FWMARK ]\n");
-	fprintf(stderr, "            [ dev STRING ] [ pref NUMBER ]\n");
-	fprintf(stderr, "ACTION := [ table TABLE_ID ] [ nat ADDRESS ]\n");
-	fprintf(stderr, "          [ prohibit | reject | unreachable ]\n");
-	fprintf(stderr, "          [ realms [SRCREALM/]DSTREALM ]\n");
-	fprintf(stderr, "TABLE_ID := [ local | main | default | NUMBER ]\n");
-	exit(-1);
-}
-*/
+/* If you add stuff here, update iprule_full_usage */
+static const char keywords[] ALIGN1 =
+	"from\0""to\0""preference\0""order\0""priority\0"
+	"tos\0""fwmark\0""realms\0""table\0""lookup\0"
+	"suppress_prefixlength\0""suppress_ifgroup\0"
+	"dev\0""iif\0""nat\0""map-to\0""type\0""help\0"
+	;
+#define keyword_preference            (keywords           + sizeof("from") + sizeof("to"))
+#define keyword_fwmark                (keyword_preference + sizeof("preference") + sizeof("order") + sizeof("priority") + sizeof("tos"))
+#define keyword_realms                (keyword_fwmark     + sizeof("fwmark"))
+#define keyword_suppress_prefixlength (keyword_realms     + sizeof("realms") + sizeof("table") + sizeof("lookup"))
+#define keyword_suppress_ifgroup      (keyword_suppress_prefixlength + sizeof("suppress_prefixlength"))
+enum {
+	ARG_from = 1, ARG_to, ARG_preference, ARG_order, ARG_priority,
+	ARG_tos, ARG_fwmark, ARG_realms, ARG_table, ARG_lookup,
+	ARG_suppress_prefixlength, ARG_suppress_ifgroup,
+	ARG_dev, ARG_iif, ARG_nat, ARG_map_to, ARG_type, ARG_help,
+};
 
 static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
 					struct nlmsghdr *n, void *arg UNUSED_PARAM)
@@ -119,6 +126,17 @@ static int FAST_FUNC print_rule(const st
 	else if (r->rtm_table)
 		printf("lookup %s ", rtnl_rttable_n2a(r->rtm_table));
 
+	if (tb[FRA_SUPPRESS_PREFIXLEN]) {
+		int pl = *(uint32_t*)RTA_DATA(tb[FRA_SUPPRESS_PREFIXLEN]);
+		if (pl != -1)
+			printf("%s %d ", keyword_suppress_prefixlength, pl);
+	}
+	if (tb[FRA_SUPPRESS_IFGROUP]) {
+		int grp = *(uint32_t*)RTA_DATA(tb[FRA_SUPPRESS_IFGROUP]);
+		if (grp != -1)
+			printf("%s %d ", keyword_suppress_ifgroup, grp);
+	}
+
 	if (tb[RTA_FLOW]) {
 		uint32_t to = *(uint32_t*)RTA_DATA(tb[RTA_FLOW]);
 		uint32_t from = to>>16;
@@ -174,15 +192,6 @@ static int iprule_list(char **argv)
 /* Return value becomes exitcode. It's okay to not return at all */
 static int iprule_modify(int cmd, char **argv)
 {
-	static const char keywords[] ALIGN1 =
-		"from\0""to\0""preference\0""order\0""priority\0"
-		"tos\0""fwmark\0""realms\0""table\0""lookup\0""dev\0"
-		"iif\0""nat\0""map-to\0""type\0""help\0";
-	enum {
-		ARG_from = 1, ARG_to, ARG_preference, ARG_order, ARG_priority,
-		ARG_tos, ARG_fwmark, ARG_realms, ARG_table, ARG_lookup, ARG_dev,
-		ARG_iif, ARG_nat, ARG_map_to, ARG_type, ARG_help
-	};
 	bool table_ok = 0;
 	struct rtnl_handle rth;
 	struct {
@@ -232,7 +241,7 @@ static int iprule_modify(int cmd, char *
 		) {
 			uint32_t pref;
 			NEXT_ARG();
-			pref = get_u32(*argv, "preference");
+			pref = get_u32(*argv, keyword_preference);
 			addattr32(&req.n, sizeof(req), RTA_PRIORITY, pref);
 		} else if (key == ARG_tos) {
 			uint32_t tos;
@@ -243,13 +252,13 @@ static int iprule_modify(int cmd, char *
 		} else if (key == ARG_fwmark) {
 			uint32_t fwmark;
 			NEXT_ARG();
-			fwmark = get_u32(*argv, "fwmark");
+			fwmark = get_u32(*argv, keyword_fwmark);
 			addattr32(&req.n, sizeof(req), RTA_PROTOINFO, fwmark);
 		} else if (key == ARG_realms) {
 			uint32_t realm;
 			NEXT_ARG();
 			if (get_rt_realms(&realm, *argv))
-				invarg_1_to_2(*argv, "realms");
+				invarg_1_to_2(*argv, keyword_realms);
 			addattr32(&req.n, sizeof(req), RTA_FLOW, realm);
 		} else if (key == ARG_table ||
 			   key == ARG_lookup
@@ -265,6 +274,16 @@ static int iprule_modify(int cmd, char *
 				addattr32(&req.n, sizeof(req), RTA_TABLE, tid);
 			}
 			table_ok = 1;
+		} else if (key == ARG_suppress_prefixlength) {
+			int prefix_length;
+			NEXT_ARG();
+			prefix_length = get_u32(*argv, keyword_suppress_prefixlength);
+			addattr32(&req.n, sizeof(req), FRA_SUPPRESS_PREFIXLEN, prefix_length);
+		} else if (key == ARG_suppress_ifgroup) {
+			int grp;
+			NEXT_ARG();
+			grp = get_u32(*argv, keyword_suppress_ifgroup);
+			addattr32(&req.n, sizeof(req), FRA_SUPPRESS_IFGROUP, grp);
 		} else if (key == ARG_dev ||
 			   key == ARG_iif
 		) {