aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/flow.h7
-rw-r--r--include/net/ip_mp_alg.h4
-rw-r--r--net/decnet/Kconfig8
-rw-r--r--net/decnet/dn_route.c28
-rw-r--r--net/decnet/dn_rules.c12
-rw-r--r--net/ipv4/Kconfig7
-rw-r--r--net/ipv4/fib_frontend.c4
-rw-r--r--net/ipv4/fib_rules.c12
-rw-r--r--net/ipv4/netfilter.c4
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c2
-rw-r--r--net/ipv4/route.c36
-rw-r--r--net/ipv6/Kconfig7
-rw-r--r--net/ipv6/fib6_rules.c12
-rw-r--r--net/ipv6/route.c4
14 files changed, 26 insertions, 121 deletions
diff --git a/include/net/flow.h b/include/net/flow.h
index 270d4c1761af..ce4b10d8b412 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -13,12 +13,12 @@
13struct flowi { 13struct flowi {
14 int oif; 14 int oif;
15 int iif; 15 int iif;
16 __u32 mark;
16 17
17 union { 18 union {
18 struct { 19 struct {
19 __be32 daddr; 20 __be32 daddr;
20 __be32 saddr; 21 __be32 saddr;
21 __u32 fwmark;
22 __u8 tos; 22 __u8 tos;
23 __u8 scope; 23 __u8 scope;
24 } ip4_u; 24 } ip4_u;
@@ -26,28 +26,23 @@ struct flowi {
26 struct { 26 struct {
27 struct in6_addr daddr; 27 struct in6_addr daddr;
28 struct in6_addr saddr; 28 struct in6_addr saddr;
29 __u32 fwmark;
30 __be32 flowlabel; 29 __be32 flowlabel;
31 } ip6_u; 30 } ip6_u;
32 31
33 struct { 32 struct {
34 __le16 daddr; 33 __le16 daddr;
35 __le16 saddr; 34 __le16 saddr;
36 __u32 fwmark;
37 __u8 scope; 35 __u8 scope;
38 } dn_u; 36 } dn_u;
39 } nl_u; 37 } nl_u;
40#define fld_dst nl_u.dn_u.daddr 38#define fld_dst nl_u.dn_u.daddr
41#define fld_src nl_u.dn_u.saddr 39#define fld_src nl_u.dn_u.saddr
42#define fld_fwmark nl_u.dn_u.fwmark
43#define fld_scope nl_u.dn_u.scope 40#define fld_scope nl_u.dn_u.scope
44#define fl6_dst nl_u.ip6_u.daddr 41#define fl6_dst nl_u.ip6_u.daddr
45#define fl6_src nl_u.ip6_u.saddr 42#define fl6_src nl_u.ip6_u.saddr
46#define fl6_fwmark nl_u.ip6_u.fwmark
47#define fl6_flowlabel nl_u.ip6_u.flowlabel 43#define fl6_flowlabel nl_u.ip6_u.flowlabel
48#define fl4_dst nl_u.ip4_u.daddr 44#define fl4_dst nl_u.ip4_u.daddr
49#define fl4_src nl_u.ip4_u.saddr 45#define fl4_src nl_u.ip4_u.saddr
50#define fl4_fwmark nl_u.ip4_u.fwmark
51#define fl4_tos nl_u.ip4_u.tos 46#define fl4_tos nl_u.ip4_u.tos
52#define fl4_scope nl_u.ip4_u.scope 47#define fl4_scope nl_u.ip4_u.scope
53 48
diff --git a/include/net/ip_mp_alg.h b/include/net/ip_mp_alg.h
index beffdd66ad74..25b56571e54b 100644
--- a/include/net/ip_mp_alg.h
+++ b/include/net/ip_mp_alg.h
@@ -88,9 +88,7 @@ static inline int multipath_comparekeys(const struct flowi *flp1,
88 return flp1->fl4_dst == flp2->fl4_dst && 88 return flp1->fl4_dst == flp2->fl4_dst &&
89 flp1->fl4_src == flp2->fl4_src && 89 flp1->fl4_src == flp2->fl4_src &&
90 flp1->oif == flp2->oif && 90 flp1->oif == flp2->oif &&
91#ifdef CONFIG_IP_ROUTE_FWMARK 91 flp1->mark == flp2->mark &&
92 flp1->fl4_fwmark == flp2->fl4_fwmark &&
93#endif
94 !((flp1->fl4_tos ^ flp2->fl4_tos) & 92 !((flp1->fl4_tos ^ flp2->fl4_tos) &
95 (IPTOS_RT_MASK | RTO_ONLINK)); 93 (IPTOS_RT_MASK | RTO_ONLINK));
96} 94}
diff --git a/net/decnet/Kconfig b/net/decnet/Kconfig
index 36e72cb145b0..7914fd619c5c 100644
--- a/net/decnet/Kconfig
+++ b/net/decnet/Kconfig
@@ -41,11 +41,3 @@ config DECNET_ROUTER
41 41
42 See <file:Documentation/networking/decnet.txt> for more information. 42 See <file:Documentation/networking/decnet.txt> for more information.
43 43
44config DECNET_ROUTE_FWMARK
45 bool "DECnet: use FWMARK value as routing key (EXPERIMENTAL)"
46 depends on DECNET_ROUTER && NETFILTER
47 help
48 If you say Y here, you will be able to specify different routes for
49 packets with different FWMARK ("firewalling mark") values
50 (see ipchains(8), "-m" argument).
51
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 3482839af280..f759d6f422ea 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -269,9 +269,7 @@ static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
269{ 269{
270 return ((fl1->nl_u.dn_u.daddr ^ fl2->nl_u.dn_u.daddr) | 270 return ((fl1->nl_u.dn_u.daddr ^ fl2->nl_u.dn_u.daddr) |
271 (fl1->nl_u.dn_u.saddr ^ fl2->nl_u.dn_u.saddr) | 271 (fl1->nl_u.dn_u.saddr ^ fl2->nl_u.dn_u.saddr) |
272#ifdef CONFIG_DECNET_ROUTE_FWMARK 272 (fl1->mark ^ fl2->mark) |
273 (fl1->nl_u.dn_u.fwmark ^ fl2->nl_u.dn_u.fwmark) |
274#endif
275 (fl1->nl_u.dn_u.scope ^ fl2->nl_u.dn_u.scope) | 273 (fl1->nl_u.dn_u.scope ^ fl2->nl_u.dn_u.scope) |
276 (fl1->oif ^ fl2->oif) | 274 (fl1->oif ^ fl2->oif) |
277 (fl1->iif ^ fl2->iif)) == 0; 275 (fl1->iif ^ fl2->iif)) == 0;
@@ -882,10 +880,8 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old
882 { .daddr = oldflp->fld_dst, 880 { .daddr = oldflp->fld_dst,
883 .saddr = oldflp->fld_src, 881 .saddr = oldflp->fld_src,
884 .scope = RT_SCOPE_UNIVERSE, 882 .scope = RT_SCOPE_UNIVERSE,
885#ifdef CONFIG_DECNET_ROUTE_FWMARK
886 .fwmark = oldflp->fld_fwmark
887#endif
888 } }, 883 } },
884 .mark = oldflp->mark,
889 .iif = loopback_dev.ifindex, 885 .iif = loopback_dev.ifindex,
890 .oif = oldflp->oif }; 886 .oif = oldflp->oif };
891 struct dn_route *rt = NULL; 887 struct dn_route *rt = NULL;
@@ -903,7 +899,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old
903 "dn_route_output_slow: dst=%04x src=%04x mark=%d" 899 "dn_route_output_slow: dst=%04x src=%04x mark=%d"
904 " iif=%d oif=%d\n", dn_ntohs(oldflp->fld_dst), 900 " iif=%d oif=%d\n", dn_ntohs(oldflp->fld_dst),
905 dn_ntohs(oldflp->fld_src), 901 dn_ntohs(oldflp->fld_src),
906 oldflp->fld_fwmark, loopback_dev.ifindex, oldflp->oif); 902 oldflp->mark, loopback_dev.ifindex, oldflp->oif);
907 903
908 /* If we have an output interface, verify its a DECnet device */ 904 /* If we have an output interface, verify its a DECnet device */
909 if (oldflp->oif) { 905 if (oldflp->oif) {
@@ -1108,9 +1104,7 @@ make_route:
1108 rt->fl.fld_dst = oldflp->fld_dst; 1104 rt->fl.fld_dst = oldflp->fld_dst;
1109 rt->fl.oif = oldflp->oif; 1105 rt->fl.oif = oldflp->oif;
1110 rt->fl.iif = 0; 1106 rt->fl.iif = 0;
1111#ifdef CONFIG_DECNET_ROUTE_FWMARK 1107 rt->fl.mark = oldflp->mark;
1112 rt->fl.fld_fwmark = oldflp->fld_fwmark;
1113#endif
1114 1108
1115 rt->rt_saddr = fl.fld_src; 1109 rt->rt_saddr = fl.fld_src;
1116 rt->rt_daddr = fl.fld_dst; 1110 rt->rt_daddr = fl.fld_dst;
@@ -1178,9 +1172,7 @@ static int __dn_route_output_key(struct dst_entry **pprt, const struct flowi *fl
1178 rt = rcu_dereference(rt->u.rt_next)) { 1172 rt = rcu_dereference(rt->u.rt_next)) {
1179 if ((flp->fld_dst == rt->fl.fld_dst) && 1173 if ((flp->fld_dst == rt->fl.fld_dst) &&
1180 (flp->fld_src == rt->fl.fld_src) && 1174 (flp->fld_src == rt->fl.fld_src) &&
1181#ifdef CONFIG_DECNET_ROUTE_FWMARK 1175 (flp->mark == rt->fl.mark) &&
1182 (flp->fld_fwmark == rt->fl.fld_fwmark) &&
1183#endif
1184 (rt->fl.iif == 0) && 1176 (rt->fl.iif == 0) &&
1185 (rt->fl.oif == flp->oif)) { 1177 (rt->fl.oif == flp->oif)) {
1186 rt->u.dst.lastuse = jiffies; 1178 rt->u.dst.lastuse = jiffies;
@@ -1235,10 +1227,8 @@ static int dn_route_input_slow(struct sk_buff *skb)
1235 { .daddr = cb->dst, 1227 { .daddr = cb->dst,
1236 .saddr = cb->src, 1228 .saddr = cb->src,
1237 .scope = RT_SCOPE_UNIVERSE, 1229 .scope = RT_SCOPE_UNIVERSE,
1238#ifdef CONFIG_DECNET_ROUTE_FWMARK
1239 .fwmark = skb->mark
1240#endif
1241 } }, 1230 } },
1231 .mark = skb->mark,
1242 .iif = skb->dev->ifindex }; 1232 .iif = skb->dev->ifindex };
1243 struct dn_fib_res res = { .fi = NULL, .type = RTN_UNREACHABLE }; 1233 struct dn_fib_res res = { .fi = NULL, .type = RTN_UNREACHABLE };
1244 int err = -EINVAL; 1234 int err = -EINVAL;
@@ -1385,7 +1375,7 @@ make_route:
1385 rt->fl.fld_dst = cb->dst; 1375 rt->fl.fld_dst = cb->dst;
1386 rt->fl.oif = 0; 1376 rt->fl.oif = 0;
1387 rt->fl.iif = in_dev->ifindex; 1377 rt->fl.iif = in_dev->ifindex;
1388 rt->fl.fld_fwmark = fl.fld_fwmark; 1378 rt->fl.mark = fl.mark;
1389 1379
1390 rt->u.dst.flags = DST_HOST; 1380 rt->u.dst.flags = DST_HOST;
1391 rt->u.dst.neighbour = neigh; 1381 rt->u.dst.neighbour = neigh;
@@ -1457,9 +1447,7 @@ int dn_route_input(struct sk_buff *skb)
1457 if ((rt->fl.fld_src == cb->src) && 1447 if ((rt->fl.fld_src == cb->src) &&
1458 (rt->fl.fld_dst == cb->dst) && 1448 (rt->fl.fld_dst == cb->dst) &&
1459 (rt->fl.oif == 0) && 1449 (rt->fl.oif == 0) &&
1460#ifdef CONFIG_DECNET_ROUTE_FWMARK 1450 (rt->fl.mark == skb->mark) &&
1461 (rt->fl.fld_fwmark == skb->mark) &&
1462#endif
1463 (rt->fl.iif == cb->iif)) { 1451 (rt->fl.iif == cb->iif)) {
1464 rt->u.dst.lastuse = jiffies; 1452 rt->u.dst.lastuse = jiffies;
1465 dst_hold(&rt->u.dst); 1453 dst_hold(&rt->u.dst);
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index 590e0a72495c..a09c09f5572d 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -45,10 +45,8 @@ struct dn_fib_rule
45 __le16 dstmask; 45 __le16 dstmask;
46 __le16 srcmap; 46 __le16 srcmap;
47 u8 flags; 47 u8 flags;
48#ifdef CONFIG_DECNET_ROUTE_FWMARK
49 u32 fwmark; 48 u32 fwmark;
50 u32 fwmask; 49 u32 fwmask;
51#endif
52}; 50};
53 51
54static struct dn_fib_rule default_rule = { 52static struct dn_fib_rule default_rule = {
@@ -131,10 +129,8 @@ static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
131 ((daddr ^ r->dst) & r->dstmask)) 129 ((daddr ^ r->dst) & r->dstmask))
132 return 0; 130 return 0;
133 131
134#ifdef CONFIG_DECNET_ROUTE_FWMARK 132 if ((r->fwmark ^ fl->mark) & r->fwmask)
135 if ((r->fwmark ^ fl->fld_fwmark) & r->fwmask)
136 return 0; 133 return 0;
137#endif
138 134
139 return 1; 135 return 1;
140} 136}
@@ -169,7 +165,6 @@ static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
169 if (tb[FRA_DST]) 165 if (tb[FRA_DST])
170 r->dst = nla_get_u16(tb[FRA_DST]); 166 r->dst = nla_get_u16(tb[FRA_DST]);
171 167
172#ifdef CONFIG_DECNET_ROUTE_FWMARK
173 if (tb[FRA_FWMARK]) { 168 if (tb[FRA_FWMARK]) {
174 r->fwmark = nla_get_u32(tb[FRA_FWMARK]); 169 r->fwmark = nla_get_u32(tb[FRA_FWMARK]);
175 if (r->fwmark) 170 if (r->fwmark)
@@ -181,7 +176,6 @@ static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
181 176
182 if (tb[FRA_FWMASK]) 177 if (tb[FRA_FWMASK])
183 r->fwmask = nla_get_u32(tb[FRA_FWMASK]); 178 r->fwmask = nla_get_u32(tb[FRA_FWMASK]);
184#endif
185 179
186 r->src_len = frh->src_len; 180 r->src_len = frh->src_len;
187 r->srcmask = dnet_make_mask(r->src_len); 181 r->srcmask = dnet_make_mask(r->src_len);
@@ -203,13 +197,11 @@ static int dn_fib_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
203 if (frh->dst_len && (r->dst_len != frh->dst_len)) 197 if (frh->dst_len && (r->dst_len != frh->dst_len))
204 return 0; 198 return 0;
205 199
206#ifdef CONFIG_DECNET_ROUTE_FWMARK
207 if (tb[FRA_FWMARK] && (r->fwmark != nla_get_u32(tb[FRA_FWMARK]))) 200 if (tb[FRA_FWMARK] && (r->fwmark != nla_get_u32(tb[FRA_FWMARK])))
208 return 0; 201 return 0;
209 202
210 if (tb[FRA_FWMASK] && (r->fwmask != nla_get_u32(tb[FRA_FWMASK]))) 203 if (tb[FRA_FWMASK] && (r->fwmask != nla_get_u32(tb[FRA_FWMASK])))
211 return 0; 204 return 0;
212#endif
213 205
214 if (tb[FRA_SRC] && (r->src != nla_get_u16(tb[FRA_SRC]))) 206 if (tb[FRA_SRC] && (r->src != nla_get_u16(tb[FRA_SRC])))
215 return 0; 207 return 0;
@@ -248,12 +240,10 @@ static int dn_fib_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
248 frh->src_len = r->src_len; 240 frh->src_len = r->src_len;
249 frh->tos = 0; 241 frh->tos = 0;
250 242
251#ifdef CONFIG_DECNET_ROUTE_FWMARK
252 if (r->fwmark) 243 if (r->fwmark)
253 NLA_PUT_U32(skb, FRA_FWMARK, r->fwmark); 244 NLA_PUT_U32(skb, FRA_FWMARK, r->fwmark);
254 if (r->fwmask || r->fwmark) 245 if (r->fwmask || r->fwmark)
255 NLA_PUT_U32(skb, FRA_FWMASK, r->fwmask); 246 NLA_PUT_U32(skb, FRA_FWMASK, r->fwmask);
256#endif
257 if (r->dst_len) 247 if (r->dst_len)
258 NLA_PUT_U16(skb, FRA_DST, r->dst); 248 NLA_PUT_U16(skb, FRA_DST, r->dst);
259 if (r->src_len) 249 if (r->src_len)
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 5572071af735..bc298bcc344e 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -104,13 +104,6 @@ config IP_MULTIPLE_TABLES
104 104
105 If unsure, say N. 105 If unsure, say N.
106 106
107config IP_ROUTE_FWMARK
108 bool "IP: use netfilter MARK value as routing key"
109 depends on IP_MULTIPLE_TABLES && NETFILTER
110 help
111 If you say Y here, you will be able to specify different routes for
112 packets with different mark values (see iptables(8), MARK target).
113
114config IP_ROUTE_MULTIPATH 107config IP_ROUTE_MULTIPATH
115 bool "IP: equal cost multipath" 108 bool "IP: equal cost multipath"
116 depends on IP_ADVANCED_ROUTER 109 depends on IP_ADVANCED_ROUTER
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index af0190d8b6c0..ee8daaebcfaf 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -768,8 +768,8 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb )
768{ 768{
769 769
770 struct fib_result res; 770 struct fib_result res;
771 struct flowi fl = { .nl_u = { .ip4_u = { .daddr = frn->fl_addr, 771 struct flowi fl = { .mark = frn->fl_fwmark,
772 .fwmark = frn->fl_fwmark, 772 .nl_u = { .ip4_u = { .daddr = frn->fl_addr,
773 .tos = frn->fl_tos, 773 .tos = frn->fl_tos,
774 .scope = frn->fl_scope } } }; 774 .scope = frn->fl_scope } } };
775 if (tb) { 775 if (tb) {
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 0852b9cd065a..de8d5dd7099b 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -44,10 +44,8 @@ struct fib4_rule
44 __be32 srcmask; 44 __be32 srcmask;
45 __be32 dst; 45 __be32 dst;
46 __be32 dstmask; 46 __be32 dstmask;
47#ifdef CONFIG_IP_ROUTE_FWMARK
48 u32 fwmark; 47 u32 fwmark;
49 u32 fwmask; 48 u32 fwmask;
50#endif
51#ifdef CONFIG_NET_CLS_ROUTE 49#ifdef CONFIG_NET_CLS_ROUTE
52 u32 tclassid; 50 u32 tclassid;
53#endif 51#endif
@@ -160,10 +158,8 @@ static int fib4_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
160 if (r->tos && (r->tos != fl->fl4_tos)) 158 if (r->tos && (r->tos != fl->fl4_tos))
161 return 0; 159 return 0;
162 160
163#ifdef CONFIG_IP_ROUTE_FWMARK 161 if ((r->fwmark ^ fl->mark) & r->fwmask)
164 if ((r->fwmark ^ fl->fl4_fwmark) & r->fwmask)
165 return 0; 162 return 0;
166#endif
167 163
168 return 1; 164 return 1;
169} 165}
@@ -220,7 +216,6 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
220 if (tb[FRA_DST]) 216 if (tb[FRA_DST])
221 rule4->dst = nla_get_be32(tb[FRA_DST]); 217 rule4->dst = nla_get_be32(tb[FRA_DST]);
222 218
223#ifdef CONFIG_IP_ROUTE_FWMARK
224 if (tb[FRA_FWMARK]) { 219 if (tb[FRA_FWMARK]) {
225 rule4->fwmark = nla_get_u32(tb[FRA_FWMARK]); 220 rule4->fwmark = nla_get_u32(tb[FRA_FWMARK]);
226 if (rule4->fwmark) 221 if (rule4->fwmark)
@@ -232,7 +227,6 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
232 227
233 if (tb[FRA_FWMASK]) 228 if (tb[FRA_FWMASK])
234 rule4->fwmask = nla_get_u32(tb[FRA_FWMASK]); 229 rule4->fwmask = nla_get_u32(tb[FRA_FWMASK]);
235#endif
236 230
237#ifdef CONFIG_NET_CLS_ROUTE 231#ifdef CONFIG_NET_CLS_ROUTE
238 if (tb[FRA_FLOW]) 232 if (tb[FRA_FLOW])
@@ -264,13 +258,11 @@ static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
264 if (frh->tos && (rule4->tos != frh->tos)) 258 if (frh->tos && (rule4->tos != frh->tos))
265 return 0; 259 return 0;
266 260
267#ifdef CONFIG_IP_ROUTE_FWMARK
268 if (tb[FRA_FWMARK] && (rule4->fwmark != nla_get_u32(tb[FRA_FWMARK]))) 261 if (tb[FRA_FWMARK] && (rule4->fwmark != nla_get_u32(tb[FRA_FWMARK])))
269 return 0; 262 return 0;
270 263
271 if (tb[FRA_FWMASK] && (rule4->fwmask != nla_get_u32(tb[FRA_FWMASK]))) 264 if (tb[FRA_FWMASK] && (rule4->fwmask != nla_get_u32(tb[FRA_FWMASK])))
272 return 0; 265 return 0;
273#endif
274 266
275#ifdef CONFIG_NET_CLS_ROUTE 267#ifdef CONFIG_NET_CLS_ROUTE
276 if (tb[FRA_FLOW] && (rule4->tclassid != nla_get_u32(tb[FRA_FLOW]))) 268 if (tb[FRA_FLOW] && (rule4->tclassid != nla_get_u32(tb[FRA_FLOW])))
@@ -296,13 +288,11 @@ static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
296 frh->src_len = rule4->src_len; 288 frh->src_len = rule4->src_len;
297 frh->tos = rule4->tos; 289 frh->tos = rule4->tos;
298 290
299#ifdef CONFIG_IP_ROUTE_FWMARK
300 if (rule4->fwmark) 291 if (rule4->fwmark)
301 NLA_PUT_U32(skb, FRA_FWMARK, rule4->fwmark); 292 NLA_PUT_U32(skb, FRA_FWMARK, rule4->fwmark);
302 293
303 if (rule4->fwmask || rule4->fwmark) 294 if (rule4->fwmask || rule4->fwmark)
304 NLA_PUT_U32(skb, FRA_FWMASK, rule4->fwmask); 295 NLA_PUT_U32(skb, FRA_FWMASK, rule4->fwmask);
305#endif
306 296
307 if (rule4->dst_len) 297 if (rule4->dst_len)
308 NLA_PUT_BE32(skb, FRA_DST, rule4->dst); 298 NLA_PUT_BE32(skb, FRA_DST, rule4->dst);
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index bfc8d753a23a..e49441ac3571 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -27,9 +27,7 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type)
27 fl.nl_u.ip4_u.saddr = iph->saddr; 27 fl.nl_u.ip4_u.saddr = iph->saddr;
28 fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); 28 fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
29 fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0; 29 fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0;
30#ifdef CONFIG_IP_ROUTE_FWMARK 30 fl.mark = (*pskb)->mark;
31 fl.nl_u.ip4_u.fwmark = (*pskb)->mark;
32#endif
33 if (ip_route_output_key(&rt, &fl) != 0) 31 if (ip_route_output_key(&rt, &fl) != 0)
34 return -1; 32 return -1;
35 33
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 62d4ccc259ca..af2939889444 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -153,9 +153,7 @@ ipt_local_hook(unsigned int hook,
153 if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE 153 if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE
154 && ((*pskb)->nh.iph->saddr != saddr 154 && ((*pskb)->nh.iph->saddr != saddr
155 || (*pskb)->nh.iph->daddr != daddr 155 || (*pskb)->nh.iph->daddr != daddr
156#ifdef CONFIG_IP_ROUTE_FWMARK
157 || (*pskb)->mark != mark 156 || (*pskb)->mark != mark
158#endif
159 || (*pskb)->nh.iph->tos != tos)) 157 || (*pskb)->nh.iph->tos != tos))
160 if (ip_route_me_harder(pskb, RTN_UNSPEC)) 158 if (ip_route_me_harder(pskb, RTN_UNSPEC))
161 ret = NF_DROP; 159 ret = NF_DROP;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 4de3e38fa1a8..d7152b2b2c64 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -568,9 +568,7 @@ static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
568{ 568{
569 return ((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) | 569 return ((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) |
570 (fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr) | 570 (fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr) |
571#ifdef CONFIG_IP_ROUTE_FWMARK 571 (fl1->mark ^ fl2->mark) |
572 (fl1->nl_u.ip4_u.fwmark ^ fl2->nl_u.ip4_u.fwmark) |
573#endif
574 (*(u16 *)&fl1->nl_u.ip4_u.tos ^ 572 (*(u16 *)&fl1->nl_u.ip4_u.tos ^
575 *(u16 *)&fl2->nl_u.ip4_u.tos) | 573 *(u16 *)&fl2->nl_u.ip4_u.tos) |
576 (fl1->oif ^ fl2->oif) | 574 (fl1->oif ^ fl2->oif) |
@@ -1643,9 +1641,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1643 rth->fl.fl4_dst = daddr; 1641 rth->fl.fl4_dst = daddr;
1644 rth->rt_dst = daddr; 1642 rth->rt_dst = daddr;
1645 rth->fl.fl4_tos = tos; 1643 rth->fl.fl4_tos = tos;
1646#ifdef CONFIG_IP_ROUTE_FWMARK 1644 rth->fl.mark = skb->mark;
1647 rth->fl.fl4_fwmark= skb->mark;
1648#endif
1649 rth->fl.fl4_src = saddr; 1645 rth->fl.fl4_src = saddr;
1650 rth->rt_src = saddr; 1646 rth->rt_src = saddr;
1651#ifdef CONFIG_NET_CLS_ROUTE 1647#ifdef CONFIG_NET_CLS_ROUTE
@@ -1789,9 +1785,7 @@ static inline int __mkroute_input(struct sk_buff *skb,
1789 rth->fl.fl4_dst = daddr; 1785 rth->fl.fl4_dst = daddr;
1790 rth->rt_dst = daddr; 1786 rth->rt_dst = daddr;
1791 rth->fl.fl4_tos = tos; 1787 rth->fl.fl4_tos = tos;
1792#ifdef CONFIG_IP_ROUTE_FWMARK 1788 rth->fl.mark = skb->mark;
1793 rth->fl.fl4_fwmark= skb->mark;
1794#endif
1795 rth->fl.fl4_src = saddr; 1789 rth->fl.fl4_src = saddr;
1796 rth->rt_src = saddr; 1790 rth->rt_src = saddr;
1797 rth->rt_gateway = daddr; 1791 rth->rt_gateway = daddr;
@@ -1920,10 +1914,8 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1920 .saddr = saddr, 1914 .saddr = saddr,
1921 .tos = tos, 1915 .tos = tos,
1922 .scope = RT_SCOPE_UNIVERSE, 1916 .scope = RT_SCOPE_UNIVERSE,
1923#ifdef CONFIG_IP_ROUTE_FWMARK
1924 .fwmark = skb->mark
1925#endif
1926 } }, 1917 } },
1918 .mark = skb->mark,
1927 .iif = dev->ifindex }; 1919 .iif = dev->ifindex };
1928 unsigned flags = 0; 1920 unsigned flags = 0;
1929 u32 itag = 0; 1921 u32 itag = 0;
@@ -2034,9 +2026,7 @@ local_input:
2034 rth->fl.fl4_dst = daddr; 2026 rth->fl.fl4_dst = daddr;
2035 rth->rt_dst = daddr; 2027 rth->rt_dst = daddr;
2036 rth->fl.fl4_tos = tos; 2028 rth->fl.fl4_tos = tos;
2037#ifdef CONFIG_IP_ROUTE_FWMARK 2029 rth->fl.mark = skb->mark;
2038 rth->fl.fl4_fwmark= skb->mark;
2039#endif
2040 rth->fl.fl4_src = saddr; 2030 rth->fl.fl4_src = saddr;
2041 rth->rt_src = saddr; 2031 rth->rt_src = saddr;
2042#ifdef CONFIG_NET_CLS_ROUTE 2032#ifdef CONFIG_NET_CLS_ROUTE
@@ -2113,9 +2103,7 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
2113 rth->fl.fl4_src == saddr && 2103 rth->fl.fl4_src == saddr &&
2114 rth->fl.iif == iif && 2104 rth->fl.iif == iif &&
2115 rth->fl.oif == 0 && 2105 rth->fl.oif == 0 &&
2116#ifdef CONFIG_IP_ROUTE_FWMARK 2106 rth->fl.mark == skb->mark &&
2117 rth->fl.fl4_fwmark == skb->mark &&
2118#endif
2119 rth->fl.fl4_tos == tos) { 2107 rth->fl.fl4_tos == tos) {
2120 rth->u.dst.lastuse = jiffies; 2108 rth->u.dst.lastuse = jiffies;
2121 dst_hold(&rth->u.dst); 2109 dst_hold(&rth->u.dst);
@@ -2239,9 +2227,7 @@ static inline int __mkroute_output(struct rtable **result,
2239 rth->fl.fl4_tos = tos; 2227 rth->fl.fl4_tos = tos;
2240 rth->fl.fl4_src = oldflp->fl4_src; 2228 rth->fl.fl4_src = oldflp->fl4_src;
2241 rth->fl.oif = oldflp->oif; 2229 rth->fl.oif = oldflp->oif;
2242#ifdef CONFIG_IP_ROUTE_FWMARK 2230 rth->fl.mark = oldflp->mark;
2243 rth->fl.fl4_fwmark= oldflp->fl4_fwmark;
2244#endif
2245 rth->rt_dst = fl->fl4_dst; 2231 rth->rt_dst = fl->fl4_dst;
2246 rth->rt_src = fl->fl4_src; 2232 rth->rt_src = fl->fl4_src;
2247 rth->rt_iif = oldflp->oif ? : dev_out->ifindex; 2233 rth->rt_iif = oldflp->oif ? : dev_out->ifindex;
@@ -2385,10 +2371,8 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
2385 .scope = ((tos & RTO_ONLINK) ? 2371 .scope = ((tos & RTO_ONLINK) ?
2386 RT_SCOPE_LINK : 2372 RT_SCOPE_LINK :
2387 RT_SCOPE_UNIVERSE), 2373 RT_SCOPE_UNIVERSE),
2388#ifdef CONFIG_IP_ROUTE_FWMARK
2389 .fwmark = oldflp->fl4_fwmark
2390#endif
2391 } }, 2374 } },
2375 .mark = oldflp->mark,
2392 .iif = loopback_dev.ifindex, 2376 .iif = loopback_dev.ifindex,
2393 .oif = oldflp->oif }; 2377 .oif = oldflp->oif };
2394 struct fib_result res; 2378 struct fib_result res;
@@ -2583,9 +2567,7 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp)
2583 rth->fl.fl4_src == flp->fl4_src && 2567 rth->fl.fl4_src == flp->fl4_src &&
2584 rth->fl.iif == 0 && 2568 rth->fl.iif == 0 &&
2585 rth->fl.oif == flp->oif && 2569 rth->fl.oif == flp->oif &&
2586#ifdef CONFIG_IP_ROUTE_FWMARK 2570 rth->fl.mark == flp->mark &&
2587 rth->fl.fl4_fwmark == flp->fl4_fwmark &&
2588#endif
2589 !((rth->fl.fl4_tos ^ flp->fl4_tos) & 2571 !((rth->fl.fl4_tos ^ flp->fl4_tos) &
2590 (IPTOS_RT_MASK | RTO_ONLINK))) { 2572 (IPTOS_RT_MASK | RTO_ONLINK))) {
2591 2573
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index 6e48f52e197c..deb4101a2a81 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -196,10 +196,3 @@ config IPV6_SUBTREES
196 196
197 If unsure, say N. 197 If unsure, say N.
198 198
199config IPV6_ROUTE_FWMARK
200 bool "IPv6: use netfilter MARK value as routing key"
201 depends on IPV6_MULTIPLE_TABLES && NETFILTER
202 ---help---
203 If you say Y here, you will be able to specify different routes for
204 packets with different mark values (see iptables(8), MARK target).
205
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 1896ecb52899..89bea64eee1c 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -25,10 +25,8 @@ struct fib6_rule
25 struct fib_rule common; 25 struct fib_rule common;
26 struct rt6key src; 26 struct rt6key src;
27 struct rt6key dst; 27 struct rt6key dst;
28#ifdef CONFIG_IPV6_ROUTE_FWMARK
29 u32 fwmark; 28 u32 fwmark;
30 u32 fwmask; 29 u32 fwmask;
31#endif
32 u8 tclass; 30 u8 tclass;
33}; 31};
34 32
@@ -130,10 +128,8 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
130 if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff)) 128 if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff))
131 return 0; 129 return 0;
132 130
133#ifdef CONFIG_IPV6_ROUTE_FWMARK 131 if ((r->fwmark ^ fl->mark) & r->fwmask)
134 if ((r->fwmark ^ fl->fl6_fwmark) & r->fwmask)
135 return 0; 132 return 0;
136#endif
137 133
138 return 1; 134 return 1;
139} 135}
@@ -177,7 +173,6 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
177 nla_memcpy(&rule6->dst.addr, tb[FRA_DST], 173 nla_memcpy(&rule6->dst.addr, tb[FRA_DST],
178 sizeof(struct in6_addr)); 174 sizeof(struct in6_addr));
179 175
180#ifdef CONFIG_IPV6_ROUTE_FWMARK
181 if (tb[FRA_FWMARK]) { 176 if (tb[FRA_FWMARK]) {
182 rule6->fwmark = nla_get_u32(tb[FRA_FWMARK]); 177 rule6->fwmark = nla_get_u32(tb[FRA_FWMARK]);
183 if (rule6->fwmark) { 178 if (rule6->fwmark) {
@@ -192,7 +187,6 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
192 187
193 if (tb[FRA_FWMASK]) 188 if (tb[FRA_FWMASK])
194 rule6->fwmask = nla_get_u32(tb[FRA_FWMASK]); 189 rule6->fwmask = nla_get_u32(tb[FRA_FWMASK]);
195#endif
196 190
197 rule6->src.plen = frh->src_len; 191 rule6->src.plen = frh->src_len;
198 rule6->dst.plen = frh->dst_len; 192 rule6->dst.plen = frh->dst_len;
@@ -225,13 +219,11 @@ static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
225 nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr))) 219 nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr)))
226 return 0; 220 return 0;
227 221
228#ifdef CONFIG_IPV6_ROUTE_FWMARK
229 if (tb[FRA_FWMARK] && (rule6->fwmark != nla_get_u32(tb[FRA_FWMARK]))) 222 if (tb[FRA_FWMARK] && (rule6->fwmark != nla_get_u32(tb[FRA_FWMARK])))
230 return 0; 223 return 0;
231 224
232 if (tb[FRA_FWMASK] && (rule6->fwmask != nla_get_u32(tb[FRA_FWMASK]))) 225 if (tb[FRA_FWMASK] && (rule6->fwmask != nla_get_u32(tb[FRA_FWMASK])))
233 return 0; 226 return 0;
234#endif
235 227
236 return 1; 228 return 1;
237} 229}
@@ -254,13 +246,11 @@ static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
254 NLA_PUT(skb, FRA_SRC, sizeof(struct in6_addr), 246 NLA_PUT(skb, FRA_SRC, sizeof(struct in6_addr),
255 &rule6->src.addr); 247 &rule6->src.addr);
256 248
257#ifdef CONFIG_IPV6_ROUTE_FWMARK
258 if (rule6->fwmark) 249 if (rule6->fwmark)
259 NLA_PUT_U32(skb, FRA_FWMARK, rule6->fwmark); 250 NLA_PUT_U32(skb, FRA_FWMARK, rule6->fwmark);
260 251
261 if (rule6->fwmask || rule6->fwmark) 252 if (rule6->fwmask || rule6->fwmark)
262 NLA_PUT_U32(skb, FRA_FWMASK, rule6->fwmask); 253 NLA_PUT_U32(skb, FRA_FWMASK, rule6->fwmask);
263#endif
264 254
265 return 0; 255 return 0;
266 256
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index aaabb1fad1cf..e3eab1529633 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -711,12 +711,10 @@ void ip6_route_input(struct sk_buff *skb)
711 .ip6_u = { 711 .ip6_u = {
712 .daddr = iph->daddr, 712 .daddr = iph->daddr,
713 .saddr = iph->saddr, 713 .saddr = iph->saddr,
714#ifdef CONFIG_IPV6_ROUTE_FWMARK
715 .fwmark = skb->mark,
716#endif
717 .flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK, 714 .flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK,
718 }, 715 },
719 }, 716 },
717 .mark = skb->mark,
720 .proto = iph->nexthdr, 718 .proto = iph->nexthdr,
721 }; 719 };
722 720