diff options
-rw-r--r-- | include/linux/fib_rules.h | 2 | ||||
-rw-r--r-- | include/net/flow.h | 2 | ||||
-rw-r--r-- | net/ipv6/Kconfig | 7 | ||||
-rw-r--r-- | net/ipv6/fib6_rules.c | 23 | ||||
-rw-r--r-- | net/ipv6/route.c | 1 |
5 files changed, 34 insertions, 1 deletions
diff --git a/include/linux/fib_rules.h b/include/linux/fib_rules.h index 19a82b6c1c1f..2987549d6044 100644 --- a/include/linux/fib_rules.h +++ b/include/linux/fib_rules.h | |||
@@ -34,7 +34,7 @@ enum | |||
34 | FRA_UNUSED3, | 34 | FRA_UNUSED3, |
35 | FRA_UNUSED4, | 35 | FRA_UNUSED4, |
36 | FRA_UNUSED5, | 36 | FRA_UNUSED5, |
37 | FRA_FWMARK, /* netfilter mark (IPv4) */ | 37 | FRA_FWMARK, /* netfilter mark (IPv4/IPv6) */ |
38 | FRA_FLOW, /* flow/class id */ | 38 | FRA_FLOW, /* flow/class id */ |
39 | FRA_UNUSED6, | 39 | FRA_UNUSED6, |
40 | FRA_UNUSED7, | 40 | FRA_UNUSED7, |
diff --git a/include/net/flow.h b/include/net/flow.h index e0522914316e..3ca210ec1379 100644 --- a/include/net/flow.h +++ b/include/net/flow.h | |||
@@ -26,6 +26,7 @@ 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; | ||
29 | __u32 flowlabel; | 30 | __u32 flowlabel; |
30 | } ip6_u; | 31 | } ip6_u; |
31 | 32 | ||
@@ -42,6 +43,7 @@ struct flowi { | |||
42 | #define fld_scope nl_u.dn_u.scope | 43 | #define fld_scope nl_u.dn_u.scope |
43 | #define fl6_dst nl_u.ip6_u.daddr | 44 | #define fl6_dst nl_u.ip6_u.daddr |
44 | #define fl6_src nl_u.ip6_u.saddr | 45 | #define fl6_src nl_u.ip6_u.saddr |
46 | #define fl6_fwmark nl_u.ip6_u.fwmark | ||
45 | #define fl6_flowlabel nl_u.ip6_u.flowlabel | 47 | #define fl6_flowlabel nl_u.ip6_u.flowlabel |
46 | #define fl4_dst nl_u.ip4_u.daddr | 48 | #define fl4_dst nl_u.ip4_u.daddr |
47 | #define fl4_src nl_u.ip4_u.saddr | 49 | #define fl4_src nl_u.ip4_u.saddr |
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index 21e0cc808f44..a2d211da2aba 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
@@ -173,3 +173,10 @@ config IPV6_MULTIPLE_TABLES | |||
173 | ---help--- | 173 | ---help--- |
174 | Support multiple routing tables. | 174 | Support multiple routing tables. |
175 | 175 | ||
176 | config IPV6_ROUTE_FWMARK | ||
177 | bool "IPv6: use netfilter MARK value as routing key" | ||
178 | depends on IPV6_MULTIPLE_TABLES && NETFILTER | ||
179 | ---help--- | ||
180 | If you say Y here, you will be able to specify different routes for | ||
181 | packets with different mark values (see iptables(8), MARK target). | ||
182 | |||
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 91f6233d8efd..aebd9e2b85a8 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -26,6 +26,9 @@ struct fib6_rule | |||
26 | struct fib_rule common; | 26 | struct fib_rule common; |
27 | struct rt6key src; | 27 | struct rt6key src; |
28 | struct rt6key dst; | 28 | struct rt6key dst; |
29 | #ifdef CONFIG_IPV6_ROUTE_FWMARK | ||
30 | u8 fwmark; | ||
31 | #endif | ||
29 | u8 tclass; | 32 | u8 tclass; |
30 | }; | 33 | }; |
31 | 34 | ||
@@ -124,6 +127,11 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) | |||
124 | if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff)) | 127 | if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff)) |
125 | return 0; | 128 | return 0; |
126 | 129 | ||
130 | #ifdef CONFIG_IPV6_ROUTE_FWMARK | ||
131 | if (r->fwmark && (r->fwmark != fl->fl6_fwmark)) | ||
132 | return 0; | ||
133 | #endif | ||
134 | |||
127 | return 1; | 135 | return 1; |
128 | } | 136 | } |
129 | 137 | ||
@@ -164,6 +172,11 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | |||
164 | nla_memcpy(&rule6->dst.addr, tb[FRA_DST], | 172 | nla_memcpy(&rule6->dst.addr, tb[FRA_DST], |
165 | sizeof(struct in6_addr)); | 173 | sizeof(struct in6_addr)); |
166 | 174 | ||
175 | #ifdef CONFIG_IPV6_ROUTE_FWMARK | ||
176 | if (tb[FRA_FWMARK]) | ||
177 | rule6->fwmark = nla_get_u32(tb[FRA_FWMARK]); | ||
178 | #endif | ||
179 | |||
167 | rule6->src.plen = frh->src_len; | 180 | rule6->src.plen = frh->src_len; |
168 | rule6->dst.plen = frh->dst_len; | 181 | rule6->dst.plen = frh->dst_len; |
169 | rule6->tclass = frh->tos; | 182 | rule6->tclass = frh->tos; |
@@ -195,6 +208,11 @@ static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, | |||
195 | nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr))) | 208 | nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr))) |
196 | return 0; | 209 | return 0; |
197 | 210 | ||
211 | #ifdef CONFIG_IPV6_ROUTE_FWMARK | ||
212 | if (tb[FRA_FWMARK] && (rule6->fwmark != nla_get_u32(tb[FRA_FWMARK]))) | ||
213 | return 0; | ||
214 | #endif | ||
215 | |||
198 | return 1; | 216 | return 1; |
199 | } | 217 | } |
200 | 218 | ||
@@ -216,6 +234,11 @@ static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb, | |||
216 | NLA_PUT(skb, FRA_SRC, sizeof(struct in6_addr), | 234 | NLA_PUT(skb, FRA_SRC, sizeof(struct in6_addr), |
217 | &rule6->src.addr); | 235 | &rule6->src.addr); |
218 | 236 | ||
237 | #ifdef CONFIG_IPV6_ROUTE_FWMARK | ||
238 | if (rule6->fwmark) | ||
239 | NLA_PUT_U32(skb, FRA_FWMARK, rule6->fwmark); | ||
240 | #endif | ||
241 | |||
219 | return 0; | 242 | return 0; |
220 | 243 | ||
221 | nla_put_failure: | 244 | nla_put_failure: |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 20691285aee5..649350bd9299 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -703,6 +703,7 @@ void ip6_route_input(struct sk_buff *skb) | |||
703 | .ip6_u = { | 703 | .ip6_u = { |
704 | .daddr = iph->daddr, | 704 | .daddr = iph->daddr, |
705 | .saddr = iph->saddr, | 705 | .saddr = iph->saddr, |
706 | .fwmark = skb->nfmark, | ||
706 | .flowlabel = (* (u32 *) iph)&IPV6_FLOWINFO_MASK, | 707 | .flowlabel = (* (u32 *) iph)&IPV6_FLOWINFO_MASK, |
707 | }, | 708 | }, |
708 | }, | 709 | }, |