diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/bridge/netfilter/ebt_mark.c | 21 | ||||
-rw-r--r-- | net/core/neighbour.c | 12 | ||||
-rw-r--r-- | net/ipv4/Kconfig | 9 | ||||
-rw-r--r-- | net/ipv4/Makefile | 1 | ||||
-rw-r--r-- | net/ipv4/esp4.c | 26 | ||||
-rw-r--r-- | net/ipv4/ipcomp.c | 5 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_core.c | 10 | ||||
-rw-r--r-- | net/ipv4/netfilter.c | 9 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_standalone.c | 3 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_REJECT.c | 97 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_mangle.c | 3 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 2 | ||||
-rw-r--r-- | net/ipv4/udp.c | 2 | ||||
-rw-r--r-- | net/ipv4/xfrm4_mode_beet.c | 139 | ||||
-rw-r--r-- | net/ipv6/Kconfig | 10 | ||||
-rw-r--r-- | net/ipv6/Makefile | 1 | ||||
-rw-r--r-- | net/ipv6/ipcomp6.c | 5 | ||||
-rw-r--r-- | net/ipv6/udp.c | 64 | ||||
-rw-r--r-- | net/ipv6/xfrm6_mode_beet.c | 107 | ||||
-rw-r--r-- | net/netfilter/Kconfig | 2 | ||||
-rw-r--r-- | net/sched/estimator.c | 196 | ||||
-rw-r--r-- | net/sched/sch_htb.c | 2 | ||||
-rw-r--r-- | net/tipc/link.c | 5 | ||||
-rw-r--r-- | net/xfrm/xfrm_hash.h | 7 | ||||
-rw-r--r-- | net/xfrm/xfrm_policy.c | 7 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 16 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 1 |
27 files changed, 416 insertions, 346 deletions
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c index 770c0df972a3..b54306a934e5 100644 --- a/net/bridge/netfilter/ebt_mark.c +++ b/net/bridge/netfilter/ebt_mark.c | |||
@@ -22,24 +22,37 @@ static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr, | |||
22 | const void *data, unsigned int datalen) | 22 | const void *data, unsigned int datalen) |
23 | { | 23 | { |
24 | struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)data; | 24 | struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)data; |
25 | int action = info->target & -16; | ||
25 | 26 | ||
26 | if ((*pskb)->nfmark != info->mark) | 27 | if (action == MARK_SET_VALUE) |
27 | (*pskb)->nfmark = info->mark; | 28 | (*pskb)->nfmark = info->mark; |
29 | else if (action == MARK_OR_VALUE) | ||
30 | (*pskb)->nfmark |= info->mark; | ||
31 | else if (action == MARK_AND_VALUE) | ||
32 | (*pskb)->nfmark &= info->mark; | ||
33 | else | ||
34 | (*pskb)->nfmark ^= info->mark; | ||
28 | 35 | ||
29 | return info->target; | 36 | return info->target | -16; |
30 | } | 37 | } |
31 | 38 | ||
32 | static int ebt_target_mark_check(const char *tablename, unsigned int hookmask, | 39 | static int ebt_target_mark_check(const char *tablename, unsigned int hookmask, |
33 | const struct ebt_entry *e, void *data, unsigned int datalen) | 40 | const struct ebt_entry *e, void *data, unsigned int datalen) |
34 | { | 41 | { |
35 | struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)data; | 42 | struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)data; |
43 | int tmp; | ||
36 | 44 | ||
37 | if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_t_info))) | 45 | if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_t_info))) |
38 | return -EINVAL; | 46 | return -EINVAL; |
39 | if (BASE_CHAIN && info->target == EBT_RETURN) | 47 | tmp = info->target | -16; |
48 | if (BASE_CHAIN && tmp == EBT_RETURN) | ||
40 | return -EINVAL; | 49 | return -EINVAL; |
41 | CLEAR_BASE_CHAIN_BIT; | 50 | CLEAR_BASE_CHAIN_BIT; |
42 | if (INVALID_TARGET) | 51 | if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) |
52 | return -EINVAL; | ||
53 | tmp = info->target & -16; | ||
54 | if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE && | ||
55 | tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE) | ||
43 | return -EINVAL; | 56 | return -EINVAL; |
44 | return 0; | 57 | return 0; |
45 | } | 58 | } |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 8ce8c471d868..b4b478353b27 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -344,12 +344,12 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, | |||
344 | { | 344 | { |
345 | struct neighbour *n; | 345 | struct neighbour *n; |
346 | int key_len = tbl->key_len; | 346 | int key_len = tbl->key_len; |
347 | u32 hash_val = tbl->hash(pkey, dev) & tbl->hash_mask; | 347 | u32 hash_val = tbl->hash(pkey, dev); |
348 | 348 | ||
349 | NEIGH_CACHE_STAT_INC(tbl, lookups); | 349 | NEIGH_CACHE_STAT_INC(tbl, lookups); |
350 | 350 | ||
351 | read_lock_bh(&tbl->lock); | 351 | read_lock_bh(&tbl->lock); |
352 | for (n = tbl->hash_buckets[hash_val]; n; n = n->next) { | 352 | for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) { |
353 | if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len)) { | 353 | if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len)) { |
354 | neigh_hold(n); | 354 | neigh_hold(n); |
355 | NEIGH_CACHE_STAT_INC(tbl, hits); | 355 | NEIGH_CACHE_STAT_INC(tbl, hits); |
@@ -364,12 +364,12 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, const void *pkey) | |||
364 | { | 364 | { |
365 | struct neighbour *n; | 365 | struct neighbour *n; |
366 | int key_len = tbl->key_len; | 366 | int key_len = tbl->key_len; |
367 | u32 hash_val = tbl->hash(pkey, NULL) & tbl->hash_mask; | 367 | u32 hash_val = tbl->hash(pkey, NULL); |
368 | 368 | ||
369 | NEIGH_CACHE_STAT_INC(tbl, lookups); | 369 | NEIGH_CACHE_STAT_INC(tbl, lookups); |
370 | 370 | ||
371 | read_lock_bh(&tbl->lock); | 371 | read_lock_bh(&tbl->lock); |
372 | for (n = tbl->hash_buckets[hash_val]; n; n = n->next) { | 372 | for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) { |
373 | if (!memcmp(n->primary_key, pkey, key_len)) { | 373 | if (!memcmp(n->primary_key, pkey, key_len)) { |
374 | neigh_hold(n); | 374 | neigh_hold(n); |
375 | NEIGH_CACHE_STAT_INC(tbl, hits); | 375 | NEIGH_CACHE_STAT_INC(tbl, hits); |
@@ -1998,12 +1998,12 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, | |||
1998 | int rc, h, s_h = cb->args[1]; | 1998 | int rc, h, s_h = cb->args[1]; |
1999 | int idx, s_idx = idx = cb->args[2]; | 1999 | int idx, s_idx = idx = cb->args[2]; |
2000 | 2000 | ||
2001 | read_lock_bh(&tbl->lock); | ||
2001 | for (h = 0; h <= tbl->hash_mask; h++) { | 2002 | for (h = 0; h <= tbl->hash_mask; h++) { |
2002 | if (h < s_h) | 2003 | if (h < s_h) |
2003 | continue; | 2004 | continue; |
2004 | if (h > s_h) | 2005 | if (h > s_h) |
2005 | s_idx = 0; | 2006 | s_idx = 0; |
2006 | read_lock_bh(&tbl->lock); | ||
2007 | for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next, idx++) { | 2007 | for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next, idx++) { |
2008 | if (idx < s_idx) | 2008 | if (idx < s_idx) |
2009 | continue; | 2009 | continue; |
@@ -2016,8 +2016,8 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, | |||
2016 | goto out; | 2016 | goto out; |
2017 | } | 2017 | } |
2018 | } | 2018 | } |
2019 | read_unlock_bh(&tbl->lock); | ||
2020 | } | 2019 | } |
2020 | read_unlock_bh(&tbl->lock); | ||
2021 | rc = skb->len; | 2021 | rc = skb->len; |
2022 | out: | 2022 | out: |
2023 | cb->args[1] = h; | 2023 | cb->args[1] = h; |
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index d172a9804448..5572071af735 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig | |||
@@ -434,6 +434,15 @@ config INET_XFRM_MODE_TUNNEL | |||
434 | 434 | ||
435 | If unsure, say Y. | 435 | If unsure, say Y. |
436 | 436 | ||
437 | config INET_XFRM_MODE_BEET | ||
438 | tristate "IP: IPsec BEET mode" | ||
439 | default y | ||
440 | select XFRM | ||
441 | ---help--- | ||
442 | Support for IPsec BEET mode. | ||
443 | |||
444 | If unsure, say Y. | ||
445 | |||
437 | config INET_DIAG | 446 | config INET_DIAG |
438 | tristate "INET: socket monitoring interface" | 447 | tristate "INET: socket monitoring interface" |
439 | default y | 448 | default y |
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index f66049e28aeb..15645c51520c 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile | |||
@@ -23,6 +23,7 @@ obj-$(CONFIG_INET_AH) += ah4.o | |||
23 | obj-$(CONFIG_INET_ESP) += esp4.o | 23 | obj-$(CONFIG_INET_ESP) += esp4.o |
24 | obj-$(CONFIG_INET_IPCOMP) += ipcomp.o | 24 | obj-$(CONFIG_INET_IPCOMP) += ipcomp.o |
25 | obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_tunnel.o | 25 | obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_tunnel.o |
26 | obj-$(CONFIG_INET_XFRM_MODE_BEET) += xfrm4_mode_beet.o | ||
26 | obj-$(CONFIG_INET_TUNNEL) += tunnel4.o | 27 | obj-$(CONFIG_INET_TUNNEL) += tunnel4.o |
27 | obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o | 28 | obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o |
28 | obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o | 29 | obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o |
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 13b29360d102..b5c205b57669 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c | |||
@@ -253,7 +253,8 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) | |||
253 | * as per draft-ietf-ipsec-udp-encaps-06, | 253 | * as per draft-ietf-ipsec-udp-encaps-06, |
254 | * section 3.1.2 | 254 | * section 3.1.2 |
255 | */ | 255 | */ |
256 | if (x->props.mode == XFRM_MODE_TRANSPORT) | 256 | if (x->props.mode == XFRM_MODE_TRANSPORT || |
257 | x->props.mode == XFRM_MODE_BEET) | ||
257 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 258 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
258 | } | 259 | } |
259 | 260 | ||
@@ -271,17 +272,28 @@ static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) | |||
271 | { | 272 | { |
272 | struct esp_data *esp = x->data; | 273 | struct esp_data *esp = x->data; |
273 | u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); | 274 | u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); |
274 | 275 | int enclen = 0; | |
275 | if (x->props.mode == XFRM_MODE_TUNNEL) { | 276 | |
276 | mtu = ALIGN(mtu + 2, blksize); | 277 | switch (x->props.mode) { |
277 | } else { | 278 | case XFRM_MODE_TUNNEL: |
278 | /* The worst case. */ | 279 | mtu = ALIGN(mtu +2, blksize); |
280 | break; | ||
281 | default: | ||
282 | case XFRM_MODE_TRANSPORT: | ||
283 | /* The worst case */ | ||
279 | mtu = ALIGN(mtu + 2, 4) + blksize - 4; | 284 | mtu = ALIGN(mtu + 2, 4) + blksize - 4; |
285 | break; | ||
286 | case XFRM_MODE_BEET: | ||
287 | /* The worst case. */ | ||
288 | enclen = IPV4_BEET_PHMAXLEN; | ||
289 | mtu = ALIGN(mtu + enclen + 2, blksize); | ||
290 | break; | ||
280 | } | 291 | } |
292 | |||
281 | if (esp->conf.padlen) | 293 | if (esp->conf.padlen) |
282 | mtu = ALIGN(mtu, esp->conf.padlen); | 294 | mtu = ALIGN(mtu, esp->conf.padlen); |
283 | 295 | ||
284 | return mtu + x->props.header_len + esp->auth.icv_trunc_len; | 296 | return mtu + x->props.header_len + esp->auth.icv_trunc_len - enclen; |
285 | } | 297 | } |
286 | 298 | ||
287 | static void esp4_err(struct sk_buff *skb, u32 info) | 299 | static void esp4_err(struct sk_buff *skb, u32 info) |
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 2017d36024d4..3839b706142e 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c | |||
@@ -206,6 +206,7 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info) | |||
206 | static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x) | 206 | static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x) |
207 | { | 207 | { |
208 | struct xfrm_state *t; | 208 | struct xfrm_state *t; |
209 | u8 mode = XFRM_MODE_TUNNEL; | ||
209 | 210 | ||
210 | t = xfrm_state_alloc(); | 211 | t = xfrm_state_alloc(); |
211 | if (t == NULL) | 212 | if (t == NULL) |
@@ -216,7 +217,9 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x) | |||
216 | t->id.daddr.a4 = x->id.daddr.a4; | 217 | t->id.daddr.a4 = x->id.daddr.a4; |
217 | memcpy(&t->sel, &x->sel, sizeof(t->sel)); | 218 | memcpy(&t->sel, &x->sel, sizeof(t->sel)); |
218 | t->props.family = AF_INET; | 219 | t->props.family = AF_INET; |
219 | t->props.mode = XFRM_MODE_TUNNEL; | 220 | if (x->props.mode == XFRM_MODE_BEET) |
221 | mode = x->props.mode; | ||
222 | t->props.mode = mode; | ||
220 | t->props.saddr.a4 = x->props.saddr.a4; | 223 | t->props.saddr.a4 = x->props.saddr.a4; |
221 | t->props.flags = x->props.flags; | 224 | t->props.flags = x->props.flags; |
222 | 225 | ||
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index 6dee03935f78..1445bb47fea4 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c | |||
@@ -813,6 +813,16 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb, | |||
813 | skb->nh.iph->saddr = cp->vaddr; | 813 | skb->nh.iph->saddr = cp->vaddr; |
814 | ip_send_check(skb->nh.iph); | 814 | ip_send_check(skb->nh.iph); |
815 | 815 | ||
816 | /* For policy routing, packets originating from this | ||
817 | * machine itself may be routed differently to packets | ||
818 | * passing through. We want this packet to be routed as | ||
819 | * if it came from this machine itself. So re-compute | ||
820 | * the routing information. | ||
821 | */ | ||
822 | if (ip_route_me_harder(pskb, RTN_LOCAL) != 0) | ||
823 | goto drop; | ||
824 | skb = *pskb; | ||
825 | |||
816 | IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT"); | 826 | IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT"); |
817 | 827 | ||
818 | ip_vs_out_stats(cp, skb); | 828 | ip_vs_out_stats(cp, skb); |
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index 5ac15379a0cf..e2005c6810a4 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
@@ -8,7 +8,7 @@ | |||
8 | #include <net/ip.h> | 8 | #include <net/ip.h> |
9 | 9 | ||
10 | /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */ | 10 | /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */ |
11 | int ip_route_me_harder(struct sk_buff **pskb) | 11 | int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type) |
12 | { | 12 | { |
13 | struct iphdr *iph = (*pskb)->nh.iph; | 13 | struct iphdr *iph = (*pskb)->nh.iph; |
14 | struct rtable *rt; | 14 | struct rtable *rt; |
@@ -16,10 +16,13 @@ int ip_route_me_harder(struct sk_buff **pskb) | |||
16 | struct dst_entry *odst; | 16 | struct dst_entry *odst; |
17 | unsigned int hh_len; | 17 | unsigned int hh_len; |
18 | 18 | ||
19 | if (addr_type == RTN_UNSPEC) | ||
20 | addr_type = inet_addr_type(iph->saddr); | ||
21 | |||
19 | /* some non-standard hacks like ipt_REJECT.c:send_reset() can cause | 22 | /* some non-standard hacks like ipt_REJECT.c:send_reset() can cause |
20 | * packets with foreign saddr to appear on the NF_IP_LOCAL_OUT hook. | 23 | * packets with foreign saddr to appear on the NF_IP_LOCAL_OUT hook. |
21 | */ | 24 | */ |
22 | if (inet_addr_type(iph->saddr) == RTN_LOCAL) { | 25 | if (addr_type == RTN_LOCAL) { |
23 | fl.nl_u.ip4_u.daddr = iph->daddr; | 26 | fl.nl_u.ip4_u.daddr = iph->daddr; |
24 | fl.nl_u.ip4_u.saddr = iph->saddr; | 27 | fl.nl_u.ip4_u.saddr = iph->saddr; |
25 | fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); | 28 | fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); |
@@ -156,7 +159,7 @@ static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info) | |||
156 | if (!(iph->tos == rt_info->tos | 159 | if (!(iph->tos == rt_info->tos |
157 | && iph->daddr == rt_info->daddr | 160 | && iph->daddr == rt_info->daddr |
158 | && iph->saddr == rt_info->saddr)) | 161 | && iph->saddr == rt_info->saddr)) |
159 | return ip_route_me_harder(pskb); | 162 | return ip_route_me_harder(pskb, RTN_UNSPEC); |
160 | } | 163 | } |
161 | return 0; | 164 | return 0; |
162 | } | 165 | } |
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 021395b67463..d85d2de50449 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c | |||
@@ -265,7 +265,8 @@ ip_nat_local_fn(unsigned int hooknum, | |||
265 | ct->tuplehash[!dir].tuple.src.u.all | 265 | ct->tuplehash[!dir].tuple.src.u.all |
266 | #endif | 266 | #endif |
267 | ) | 267 | ) |
268 | return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; | 268 | if (ip_route_me_harder(pskb, RTN_UNSPEC)) |
269 | ret = NF_DROP; | ||
269 | } | 270 | } |
270 | return ret; | 271 | return ret; |
271 | } | 272 | } |
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index fd0c05efed8a..ad0312d0e4fd 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c | |||
@@ -38,76 +38,16 @@ MODULE_DESCRIPTION("iptables REJECT target module"); | |||
38 | #define DEBUGP(format, args...) | 38 | #define DEBUGP(format, args...) |
39 | #endif | 39 | #endif |
40 | 40 | ||
41 | static inline struct rtable *route_reverse(struct sk_buff *skb, | ||
42 | struct tcphdr *tcph, int hook) | ||
43 | { | ||
44 | struct iphdr *iph = skb->nh.iph; | ||
45 | struct dst_entry *odst; | ||
46 | struct flowi fl = {}; | ||
47 | struct rtable *rt; | ||
48 | |||
49 | /* We don't require ip forwarding to be enabled to be able to | ||
50 | * send a RST reply for bridged traffic. */ | ||
51 | if (hook != NF_IP_FORWARD | ||
52 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
53 | || (skb->nf_bridge && skb->nf_bridge->mask & BRNF_BRIDGED) | ||
54 | #endif | ||
55 | ) { | ||
56 | fl.nl_u.ip4_u.daddr = iph->saddr; | ||
57 | if (hook == NF_IP_LOCAL_IN) | ||
58 | fl.nl_u.ip4_u.saddr = iph->daddr; | ||
59 | fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); | ||
60 | |||
61 | if (ip_route_output_key(&rt, &fl) != 0) | ||
62 | return NULL; | ||
63 | } else { | ||
64 | /* non-local src, find valid iif to satisfy | ||
65 | * rp-filter when calling ip_route_input. */ | ||
66 | fl.nl_u.ip4_u.daddr = iph->daddr; | ||
67 | if (ip_route_output_key(&rt, &fl) != 0) | ||
68 | return NULL; | ||
69 | |||
70 | odst = skb->dst; | ||
71 | if (ip_route_input(skb, iph->saddr, iph->daddr, | ||
72 | RT_TOS(iph->tos), rt->u.dst.dev) != 0) { | ||
73 | dst_release(&rt->u.dst); | ||
74 | return NULL; | ||
75 | } | ||
76 | dst_release(&rt->u.dst); | ||
77 | rt = (struct rtable *)skb->dst; | ||
78 | skb->dst = odst; | ||
79 | |||
80 | fl.nl_u.ip4_u.daddr = iph->saddr; | ||
81 | fl.nl_u.ip4_u.saddr = iph->daddr; | ||
82 | fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); | ||
83 | } | ||
84 | |||
85 | if (rt->u.dst.error) { | ||
86 | dst_release(&rt->u.dst); | ||
87 | return NULL; | ||
88 | } | ||
89 | |||
90 | fl.proto = IPPROTO_TCP; | ||
91 | fl.fl_ip_sport = tcph->dest; | ||
92 | fl.fl_ip_dport = tcph->source; | ||
93 | security_skb_classify_flow(skb, &fl); | ||
94 | |||
95 | xfrm_lookup((struct dst_entry **)&rt, &fl, NULL, 0); | ||
96 | |||
97 | return rt; | ||
98 | } | ||
99 | |||
100 | /* Send RST reply */ | 41 | /* Send RST reply */ |
101 | static void send_reset(struct sk_buff *oldskb, int hook) | 42 | static void send_reset(struct sk_buff *oldskb, int hook) |
102 | { | 43 | { |
103 | struct sk_buff *nskb; | 44 | struct sk_buff *nskb; |
104 | struct iphdr *iph = oldskb->nh.iph; | 45 | struct iphdr *iph = oldskb->nh.iph; |
105 | struct tcphdr _otcph, *oth, *tcph; | 46 | struct tcphdr _otcph, *oth, *tcph; |
106 | struct rtable *rt; | ||
107 | __be16 tmp_port; | 47 | __be16 tmp_port; |
108 | __be32 tmp_addr; | 48 | __be32 tmp_addr; |
109 | int needs_ack; | 49 | int needs_ack; |
110 | int hh_len; | 50 | unsigned int addr_type; |
111 | 51 | ||
112 | /* IP header checks: fragment. */ | 52 | /* IP header checks: fragment. */ |
113 | if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)) | 53 | if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)) |
@@ -126,23 +66,13 @@ static void send_reset(struct sk_buff *oldskb, int hook) | |||
126 | if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP)) | 66 | if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP)) |
127 | return; | 67 | return; |
128 | 68 | ||
129 | if ((rt = route_reverse(oldskb, oth, hook)) == NULL) | ||
130 | return; | ||
131 | |||
132 | hh_len = LL_RESERVED_SPACE(rt->u.dst.dev); | ||
133 | |||
134 | /* We need a linear, writeable skb. We also need to expand | 69 | /* We need a linear, writeable skb. We also need to expand |
135 | headroom in case hh_len of incoming interface < hh_len of | 70 | headroom in case hh_len of incoming interface < hh_len of |
136 | outgoing interface */ | 71 | outgoing interface */ |
137 | nskb = skb_copy_expand(oldskb, hh_len, skb_tailroom(oldskb), | 72 | nskb = skb_copy_expand(oldskb, LL_MAX_HEADER, skb_tailroom(oldskb), |
138 | GFP_ATOMIC); | 73 | GFP_ATOMIC); |
139 | if (!nskb) { | 74 | if (!nskb) |
140 | dst_release(&rt->u.dst); | ||
141 | return; | 75 | return; |
142 | } | ||
143 | |||
144 | dst_release(nskb->dst); | ||
145 | nskb->dst = &rt->u.dst; | ||
146 | 76 | ||
147 | /* This packet will not be the same as the other: clear nf fields */ | 77 | /* This packet will not be the same as the other: clear nf fields */ |
148 | nf_reset(nskb); | 78 | nf_reset(nskb); |
@@ -184,6 +114,21 @@ static void send_reset(struct sk_buff *oldskb, int hook) | |||
184 | tcph->window = 0; | 114 | tcph->window = 0; |
185 | tcph->urg_ptr = 0; | 115 | tcph->urg_ptr = 0; |
186 | 116 | ||
117 | /* Set DF, id = 0 */ | ||
118 | nskb->nh.iph->frag_off = htons(IP_DF); | ||
119 | nskb->nh.iph->id = 0; | ||
120 | |||
121 | addr_type = RTN_UNSPEC; | ||
122 | if (hook != NF_IP_FORWARD | ||
123 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
124 | || (nskb->nf_bridge && nskb->nf_bridge->mask & BRNF_BRIDGED) | ||
125 | #endif | ||
126 | ) | ||
127 | addr_type = RTN_LOCAL; | ||
128 | |||
129 | if (ip_route_me_harder(&nskb, addr_type)) | ||
130 | goto free_nskb; | ||
131 | |||
187 | /* Adjust TCP checksum */ | 132 | /* Adjust TCP checksum */ |
188 | nskb->ip_summed = CHECKSUM_NONE; | 133 | nskb->ip_summed = CHECKSUM_NONE; |
189 | tcph->check = 0; | 134 | tcph->check = 0; |
@@ -192,12 +137,8 @@ static void send_reset(struct sk_buff *oldskb, int hook) | |||
192 | nskb->nh.iph->daddr, | 137 | nskb->nh.iph->daddr, |
193 | csum_partial((char *)tcph, | 138 | csum_partial((char *)tcph, |
194 | sizeof(struct tcphdr), 0)); | 139 | sizeof(struct tcphdr), 0)); |
195 | 140 | /* Adjust IP TTL */ | |
196 | /* Adjust IP TTL, DF */ | ||
197 | nskb->nh.iph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT); | 141 | nskb->nh.iph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT); |
198 | /* Set DF, id = 0 */ | ||
199 | nskb->nh.iph->frag_off = htons(IP_DF); | ||
200 | nskb->nh.iph->id = 0; | ||
201 | 142 | ||
202 | /* Adjust IP checksum */ | 143 | /* Adjust IP checksum */ |
203 | nskb->nh.iph->check = 0; | 144 | nskb->nh.iph->check = 0; |
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index e62ea2bb9c0a..b91f3582359b 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c | |||
@@ -157,7 +157,8 @@ ipt_local_hook(unsigned int hook, | |||
157 | || (*pskb)->nfmark != nfmark | 157 | || (*pskb)->nfmark != nfmark |
158 | #endif | 158 | #endif |
159 | || (*pskb)->nh.iph->tos != tos)) | 159 | || (*pskb)->nh.iph->tos != tos)) |
160 | return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; | 160 | if (ip_route_me_harder(pskb, RTN_UNSPEC)) |
161 | ret = NF_DROP; | ||
161 | 162 | ||
162 | return ret; | 163 | return ret; |
163 | } | 164 | } |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 3f884cea14ff..cf06accbe687 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -2259,7 +2259,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p) | |||
2259 | u32 pkts_acked = 0; | 2259 | u32 pkts_acked = 0; |
2260 | void (*rtt_sample)(struct sock *sk, u32 usrtt) | 2260 | void (*rtt_sample)(struct sock *sk, u32 usrtt) |
2261 | = icsk->icsk_ca_ops->rtt_sample; | 2261 | = icsk->icsk_ca_ops->rtt_sample; |
2262 | struct timeval tv; | 2262 | struct timeval tv = { .tv_sec = 0, .tv_usec = 0 }; |
2263 | 2263 | ||
2264 | while ((skb = skb_peek(&sk->sk_write_queue)) && | 2264 | while ((skb = skb_peek(&sk->sk_write_queue)) && |
2265 | skb != sk->sk_send_head) { | 2265 | skb != sk->sk_send_head) { |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 6d6142f9c478..865d75214a9a 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -675,6 +675,8 @@ do_append_data: | |||
675 | udp_flush_pending_frames(sk); | 675 | udp_flush_pending_frames(sk); |
676 | else if (!corkreq) | 676 | else if (!corkreq) |
677 | err = udp_push_pending_frames(sk, up); | 677 | err = udp_push_pending_frames(sk, up); |
678 | else if (unlikely(skb_queue_empty(&sk->sk_write_queue))) | ||
679 | up->pending = 0; | ||
678 | release_sock(sk); | 680 | release_sock(sk); |
679 | 681 | ||
680 | out: | 682 | out: |
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c new file mode 100644 index 000000000000..89cf59ea7bbe --- /dev/null +++ b/net/ipv4/xfrm4_mode_beet.c | |||
@@ -0,0 +1,139 @@ | |||
1 | /* | ||
2 | * xfrm4_mode_beet.c - BEET mode encapsulation for IPv4. | ||
3 | * | ||
4 | * Copyright (c) 2006 Diego Beltrami <diego.beltrami@gmail.com> | ||
5 | * Miika Komu <miika@iki.fi> | ||
6 | * Herbert Xu <herbert@gondor.apana.org.au> | ||
7 | * Abhinav Pathak <abhinav.pathak@hiit.fi> | ||
8 | * Jeff Ahrenholz <ahrenholz@gmail.com> | ||
9 | */ | ||
10 | |||
11 | #include <linux/init.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/skbuff.h> | ||
15 | #include <linux/stringify.h> | ||
16 | #include <net/dst.h> | ||
17 | #include <net/ip.h> | ||
18 | #include <net/xfrm.h> | ||
19 | |||
20 | /* Add encapsulation header. | ||
21 | * | ||
22 | * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt. | ||
23 | * The following fields in it shall be filled in by x->type->output: | ||
24 | * tot_len | ||
25 | * check | ||
26 | * | ||
27 | * On exit, skb->h will be set to the start of the payload to be processed | ||
28 | * by x->type->output and skb->nh will be set to the top IP header. | ||
29 | */ | ||
30 | static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) | ||
31 | { | ||
32 | struct iphdr *iph, *top_iph = NULL; | ||
33 | int hdrlen, optlen; | ||
34 | |||
35 | iph = skb->nh.iph; | ||
36 | skb->h.ipiph = iph; | ||
37 | |||
38 | hdrlen = 0; | ||
39 | optlen = iph->ihl * 4 - sizeof(*iph); | ||
40 | if (unlikely(optlen)) | ||
41 | hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4); | ||
42 | |||
43 | skb->nh.raw = skb_push(skb, x->props.header_len + hdrlen); | ||
44 | top_iph = skb->nh.iph; | ||
45 | hdrlen = iph->ihl * 4 - optlen; | ||
46 | skb->h.raw += hdrlen; | ||
47 | |||
48 | memmove(top_iph, iph, hdrlen); | ||
49 | if (unlikely(optlen)) { | ||
50 | struct ip_beet_phdr *ph; | ||
51 | |||
52 | BUG_ON(optlen < 0); | ||
53 | |||
54 | ph = (struct ip_beet_phdr *)skb->h.raw; | ||
55 | ph->padlen = 4 - (optlen & 4); | ||
56 | ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8; | ||
57 | ph->nexthdr = top_iph->protocol; | ||
58 | |||
59 | top_iph->protocol = IPPROTO_BEETPH; | ||
60 | top_iph->ihl = sizeof(struct iphdr) / 4; | ||
61 | } | ||
62 | |||
63 | top_iph->saddr = x->props.saddr.a4; | ||
64 | top_iph->daddr = x->id.daddr.a4; | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb) | ||
70 | { | ||
71 | struct iphdr *iph = skb->nh.iph; | ||
72 | int phlen = 0; | ||
73 | int optlen = 0; | ||
74 | __u8 ph_nexthdr = 0, protocol = 0; | ||
75 | int err = -EINVAL; | ||
76 | |||
77 | protocol = iph->protocol; | ||
78 | |||
79 | if (unlikely(iph->protocol == IPPROTO_BEETPH)) { | ||
80 | struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(iph + 1); | ||
81 | |||
82 | if (!pskb_may_pull(skb, sizeof(*ph))) | ||
83 | goto out; | ||
84 | |||
85 | phlen = ph->hdrlen * 8; | ||
86 | optlen = phlen - ph->padlen - sizeof(*ph); | ||
87 | if (optlen < 0 || optlen & 3 || optlen > 250) | ||
88 | goto out; | ||
89 | |||
90 | if (!pskb_may_pull(skb, phlen)) | ||
91 | goto out; | ||
92 | |||
93 | ph_nexthdr = ph->nexthdr; | ||
94 | } | ||
95 | |||
96 | skb_push(skb, sizeof(*iph) - phlen + optlen); | ||
97 | memmove(skb->data, skb->nh.raw, sizeof(*iph)); | ||
98 | skb->nh.raw = skb->data; | ||
99 | |||
100 | iph = skb->nh.iph; | ||
101 | iph->ihl = (sizeof(*iph) + optlen) / 4; | ||
102 | iph->tot_len = htons(skb->len); | ||
103 | iph->daddr = x->sel.daddr.a4; | ||
104 | iph->saddr = x->sel.saddr.a4; | ||
105 | if (ph_nexthdr) | ||
106 | iph->protocol = ph_nexthdr; | ||
107 | else | ||
108 | iph->protocol = protocol; | ||
109 | iph->check = 0; | ||
110 | iph->check = ip_fast_csum(skb->nh.raw, iph->ihl); | ||
111 | err = 0; | ||
112 | out: | ||
113 | return err; | ||
114 | } | ||
115 | |||
116 | static struct xfrm_mode xfrm4_beet_mode = { | ||
117 | .input = xfrm4_beet_input, | ||
118 | .output = xfrm4_beet_output, | ||
119 | .owner = THIS_MODULE, | ||
120 | .encap = XFRM_MODE_BEET, | ||
121 | }; | ||
122 | |||
123 | static int __init xfrm4_beet_init(void) | ||
124 | { | ||
125 | return xfrm_register_mode(&xfrm4_beet_mode, AF_INET); | ||
126 | } | ||
127 | |||
128 | static void __exit xfrm4_beet_exit(void) | ||
129 | { | ||
130 | int err; | ||
131 | |||
132 | err = xfrm_unregister_mode(&xfrm4_beet_mode, AF_INET); | ||
133 | BUG_ON(err); | ||
134 | } | ||
135 | |||
136 | module_init(xfrm4_beet_init); | ||
137 | module_exit(xfrm4_beet_exit); | ||
138 | MODULE_LICENSE("GPL"); | ||
139 | MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_BEET); | ||
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index a2d211da2aba..a460e8132b4d 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
@@ -136,6 +136,16 @@ config INET6_XFRM_MODE_TUNNEL | |||
136 | 136 | ||
137 | If unsure, say Y. | 137 | If unsure, say Y. |
138 | 138 | ||
139 | config INET6_XFRM_MODE_BEET | ||
140 | tristate "IPv6: IPsec BEET mode" | ||
141 | depends on IPV6 | ||
142 | default IPV6 | ||
143 | select XFRM | ||
144 | ---help--- | ||
145 | Support for IPsec BEET mode. | ||
146 | |||
147 | If unsure, say Y. | ||
148 | |||
139 | config INET6_XFRM_MODE_ROUTEOPTIMIZATION | 149 | config INET6_XFRM_MODE_ROUTEOPTIMIZATION |
140 | tristate "IPv6: MIPv6 route optimization mode (EXPERIMENTAL)" | 150 | tristate "IPv6: MIPv6 route optimization mode (EXPERIMENTAL)" |
141 | depends on IPV6 && EXPERIMENTAL | 151 | depends on IPV6 && EXPERIMENTAL |
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 0213c6612b58..87274e47fe32 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile | |||
@@ -26,6 +26,7 @@ obj-$(CONFIG_INET6_TUNNEL) += tunnel6.o | |||
26 | obj-$(CONFIG_INET6_XFRM_MODE_TRANSPORT) += xfrm6_mode_transport.o | 26 | obj-$(CONFIG_INET6_XFRM_MODE_TRANSPORT) += xfrm6_mode_transport.o |
27 | obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o | 27 | obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o |
28 | obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o | 28 | obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o |
29 | obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o | ||
29 | obj-$(CONFIG_NETFILTER) += netfilter/ | 30 | obj-$(CONFIG_NETFILTER) += netfilter/ |
30 | 31 | ||
31 | obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o | 32 | obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o |
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index a2860e35efd7..71f59f18ede8 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c | |||
@@ -199,6 +199,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
199 | static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) | 199 | static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) |
200 | { | 200 | { |
201 | struct xfrm_state *t = NULL; | 201 | struct xfrm_state *t = NULL; |
202 | u8 mode = XFRM_MODE_TUNNEL; | ||
202 | 203 | ||
203 | t = xfrm_state_alloc(); | 204 | t = xfrm_state_alloc(); |
204 | if (!t) | 205 | if (!t) |
@@ -212,7 +213,9 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) | |||
212 | memcpy(t->id.daddr.a6, x->id.daddr.a6, sizeof(struct in6_addr)); | 213 | memcpy(t->id.daddr.a6, x->id.daddr.a6, sizeof(struct in6_addr)); |
213 | memcpy(&t->sel, &x->sel, sizeof(t->sel)); | 214 | memcpy(&t->sel, &x->sel, sizeof(t->sel)); |
214 | t->props.family = AF_INET6; | 215 | t->props.family = AF_INET6; |
215 | t->props.mode = XFRM_MODE_TUNNEL; | 216 | if (x->props.mode == XFRM_MODE_BEET) |
217 | mode = x->props.mode; | ||
218 | t->props.mode = mode; | ||
216 | memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr)); | 219 | memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr)); |
217 | 220 | ||
218 | if (xfrm_init_state(t)) | 221 | if (xfrm_init_state(t)) |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 9662561701d1..e0c3934a7e4b 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -546,7 +546,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
546 | struct in6_addr *daddr, *final_p = NULL, final; | 546 | struct in6_addr *daddr, *final_p = NULL, final; |
547 | struct ipv6_txoptions *opt = NULL; | 547 | struct ipv6_txoptions *opt = NULL; |
548 | struct ip6_flowlabel *flowlabel = NULL; | 548 | struct ip6_flowlabel *flowlabel = NULL; |
549 | struct flowi *fl = &inet->cork.fl; | 549 | struct flowi fl; |
550 | struct dst_entry *dst; | 550 | struct dst_entry *dst; |
551 | int addr_len = msg->msg_namelen; | 551 | int addr_len = msg->msg_namelen; |
552 | int ulen = len; | 552 | int ulen = len; |
@@ -626,19 +626,19 @@ do_udp_sendmsg: | |||
626 | } | 626 | } |
627 | ulen += sizeof(struct udphdr); | 627 | ulen += sizeof(struct udphdr); |
628 | 628 | ||
629 | memset(fl, 0, sizeof(*fl)); | 629 | memset(&fl, 0, sizeof(fl)); |
630 | 630 | ||
631 | if (sin6) { | 631 | if (sin6) { |
632 | if (sin6->sin6_port == 0) | 632 | if (sin6->sin6_port == 0) |
633 | return -EINVAL; | 633 | return -EINVAL; |
634 | 634 | ||
635 | fl->fl_ip_dport = sin6->sin6_port; | 635 | fl.fl_ip_dport = sin6->sin6_port; |
636 | daddr = &sin6->sin6_addr; | 636 | daddr = &sin6->sin6_addr; |
637 | 637 | ||
638 | if (np->sndflow) { | 638 | if (np->sndflow) { |
639 | fl->fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; | 639 | fl.fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; |
640 | if (fl->fl6_flowlabel&IPV6_FLOWLABEL_MASK) { | 640 | if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) { |
641 | flowlabel = fl6_sock_lookup(sk, fl->fl6_flowlabel); | 641 | flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); |
642 | if (flowlabel == NULL) | 642 | if (flowlabel == NULL) |
643 | return -EINVAL; | 643 | return -EINVAL; |
644 | daddr = &flowlabel->dst; | 644 | daddr = &flowlabel->dst; |
@@ -656,32 +656,32 @@ do_udp_sendmsg: | |||
656 | if (addr_len >= sizeof(struct sockaddr_in6) && | 656 | if (addr_len >= sizeof(struct sockaddr_in6) && |
657 | sin6->sin6_scope_id && | 657 | sin6->sin6_scope_id && |
658 | ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL) | 658 | ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL) |
659 | fl->oif = sin6->sin6_scope_id; | 659 | fl.oif = sin6->sin6_scope_id; |
660 | } else { | 660 | } else { |
661 | if (sk->sk_state != TCP_ESTABLISHED) | 661 | if (sk->sk_state != TCP_ESTABLISHED) |
662 | return -EDESTADDRREQ; | 662 | return -EDESTADDRREQ; |
663 | 663 | ||
664 | fl->fl_ip_dport = inet->dport; | 664 | fl.fl_ip_dport = inet->dport; |
665 | daddr = &np->daddr; | 665 | daddr = &np->daddr; |
666 | fl->fl6_flowlabel = np->flow_label; | 666 | fl.fl6_flowlabel = np->flow_label; |
667 | connected = 1; | 667 | connected = 1; |
668 | } | 668 | } |
669 | 669 | ||
670 | if (!fl->oif) | 670 | if (!fl.oif) |
671 | fl->oif = sk->sk_bound_dev_if; | 671 | fl.oif = sk->sk_bound_dev_if; |
672 | 672 | ||
673 | if (msg->msg_controllen) { | 673 | if (msg->msg_controllen) { |
674 | opt = &opt_space; | 674 | opt = &opt_space; |
675 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 675 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
676 | opt->tot_len = sizeof(*opt); | 676 | opt->tot_len = sizeof(*opt); |
677 | 677 | ||
678 | err = datagram_send_ctl(msg, fl, opt, &hlimit, &tclass); | 678 | err = datagram_send_ctl(msg, &fl, opt, &hlimit, &tclass); |
679 | if (err < 0) { | 679 | if (err < 0) { |
680 | fl6_sock_release(flowlabel); | 680 | fl6_sock_release(flowlabel); |
681 | return err; | 681 | return err; |
682 | } | 682 | } |
683 | if ((fl->fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { | 683 | if ((fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { |
684 | flowlabel = fl6_sock_lookup(sk, fl->fl6_flowlabel); | 684 | flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); |
685 | if (flowlabel == NULL) | 685 | if (flowlabel == NULL) |
686 | return -EINVAL; | 686 | return -EINVAL; |
687 | } | 687 | } |
@@ -695,39 +695,39 @@ do_udp_sendmsg: | |||
695 | opt = fl6_merge_options(&opt_space, flowlabel, opt); | 695 | opt = fl6_merge_options(&opt_space, flowlabel, opt); |
696 | opt = ipv6_fixup_options(&opt_space, opt); | 696 | opt = ipv6_fixup_options(&opt_space, opt); |
697 | 697 | ||
698 | fl->proto = IPPROTO_UDP; | 698 | fl.proto = IPPROTO_UDP; |
699 | ipv6_addr_copy(&fl->fl6_dst, daddr); | 699 | ipv6_addr_copy(&fl.fl6_dst, daddr); |
700 | if (ipv6_addr_any(&fl->fl6_src) && !ipv6_addr_any(&np->saddr)) | 700 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) |
701 | ipv6_addr_copy(&fl->fl6_src, &np->saddr); | 701 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); |
702 | fl->fl_ip_sport = inet->sport; | 702 | fl.fl_ip_sport = inet->sport; |
703 | 703 | ||
704 | /* merge ip6_build_xmit from ip6_output */ | 704 | /* merge ip6_build_xmit from ip6_output */ |
705 | if (opt && opt->srcrt) { | 705 | if (opt && opt->srcrt) { |
706 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | 706 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; |
707 | ipv6_addr_copy(&final, &fl->fl6_dst); | 707 | ipv6_addr_copy(&final, &fl.fl6_dst); |
708 | ipv6_addr_copy(&fl->fl6_dst, rt0->addr); | 708 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); |
709 | final_p = &final; | 709 | final_p = &final; |
710 | connected = 0; | 710 | connected = 0; |
711 | } | 711 | } |
712 | 712 | ||
713 | if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst)) { | 713 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) { |
714 | fl->oif = np->mcast_oif; | 714 | fl.oif = np->mcast_oif; |
715 | connected = 0; | 715 | connected = 0; |
716 | } | 716 | } |
717 | 717 | ||
718 | security_sk_classify_flow(sk, fl); | 718 | security_sk_classify_flow(sk, &fl); |
719 | 719 | ||
720 | err = ip6_sk_dst_lookup(sk, &dst, fl); | 720 | err = ip6_sk_dst_lookup(sk, &dst, &fl); |
721 | if (err) | 721 | if (err) |
722 | goto out; | 722 | goto out; |
723 | if (final_p) | 723 | if (final_p) |
724 | ipv6_addr_copy(&fl->fl6_dst, final_p); | 724 | ipv6_addr_copy(&fl.fl6_dst, final_p); |
725 | 725 | ||
726 | if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) | 726 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) |
727 | goto out; | 727 | goto out; |
728 | 728 | ||
729 | if (hlimit < 0) { | 729 | if (hlimit < 0) { |
730 | if (ipv6_addr_is_multicast(&fl->fl6_dst)) | 730 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) |
731 | hlimit = np->mcast_hops; | 731 | hlimit = np->mcast_hops; |
732 | else | 732 | else |
733 | hlimit = np->hop_limit; | 733 | hlimit = np->hop_limit; |
@@ -763,21 +763,23 @@ back_from_confirm: | |||
763 | do_append_data: | 763 | do_append_data: |
764 | up->len += ulen; | 764 | up->len += ulen; |
765 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen, | 765 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen, |
766 | sizeof(struct udphdr), hlimit, tclass, opt, fl, | 766 | sizeof(struct udphdr), hlimit, tclass, opt, &fl, |
767 | (struct rt6_info*)dst, | 767 | (struct rt6_info*)dst, |
768 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); | 768 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); |
769 | if (err) | 769 | if (err) |
770 | udp_v6_flush_pending_frames(sk); | 770 | udp_v6_flush_pending_frames(sk); |
771 | else if (!corkreq) | 771 | else if (!corkreq) |
772 | err = udp_v6_push_pending_frames(sk, up); | 772 | err = udp_v6_push_pending_frames(sk, up); |
773 | else if (unlikely(skb_queue_empty(&sk->sk_write_queue))) | ||
774 | up->pending = 0; | ||
773 | 775 | ||
774 | if (dst) { | 776 | if (dst) { |
775 | if (connected) { | 777 | if (connected) { |
776 | ip6_dst_store(sk, dst, | 778 | ip6_dst_store(sk, dst, |
777 | ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ? | 779 | ipv6_addr_equal(&fl.fl6_dst, &np->daddr) ? |
778 | &np->daddr : NULL, | 780 | &np->daddr : NULL, |
779 | #ifdef CONFIG_IPV6_SUBTREES | 781 | #ifdef CONFIG_IPV6_SUBTREES |
780 | ipv6_addr_equal(&fl->fl6_src, &np->saddr) ? | 782 | ipv6_addr_equal(&fl.fl6_src, &np->saddr) ? |
781 | &np->saddr : | 783 | &np->saddr : |
782 | #endif | 784 | #endif |
783 | NULL); | 785 | NULL); |
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c new file mode 100644 index 000000000000..edcfffa9e87b --- /dev/null +++ b/net/ipv6/xfrm6_mode_beet.c | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * xfrm6_mode_beet.c - BEET mode encapsulation for IPv6. | ||
3 | * | ||
4 | * Copyright (c) 2006 Diego Beltrami <diego.beltrami@gmail.com> | ||
5 | * Miika Komu <miika@iki.fi> | ||
6 | * Herbert Xu <herbert@gondor.apana.org.au> | ||
7 | * Abhinav Pathak <abhinav.pathak@hiit.fi> | ||
8 | * Jeff Ahrenholz <ahrenholz@gmail.com> | ||
9 | */ | ||
10 | |||
11 | #include <linux/init.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/skbuff.h> | ||
15 | #include <linux/stringify.h> | ||
16 | #include <net/dsfield.h> | ||
17 | #include <net/dst.h> | ||
18 | #include <net/inet_ecn.h> | ||
19 | #include <net/ipv6.h> | ||
20 | #include <net/xfrm.h> | ||
21 | |||
22 | /* Add encapsulation header. | ||
23 | * | ||
24 | * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt. | ||
25 | * The following fields in it shall be filled in by x->type->output: | ||
26 | * payload_len | ||
27 | * | ||
28 | * On exit, skb->h will be set to the start of the encapsulation header to be | ||
29 | * filled in by x->type->output and skb->nh will be set to the nextheader field | ||
30 | * of the extension header directly preceding the encapsulation header, or in | ||
31 | * its absence, that of the top IP header. The value of skb->data will always | ||
32 | * point to the top IP header. | ||
33 | */ | ||
34 | static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) | ||
35 | { | ||
36 | struct ipv6hdr *iph, *top_iph; | ||
37 | u8 *prevhdr; | ||
38 | int hdr_len; | ||
39 | |||
40 | skb_push(skb, x->props.header_len); | ||
41 | iph = skb->nh.ipv6h; | ||
42 | |||
43 | hdr_len = ip6_find_1stfragopt(skb, &prevhdr); | ||
44 | skb->nh.raw = prevhdr - x->props.header_len; | ||
45 | skb->h.raw = skb->data + hdr_len; | ||
46 | memmove(skb->data, iph, hdr_len); | ||
47 | |||
48 | skb->nh.raw = skb->data; | ||
49 | top_iph = skb->nh.ipv6h; | ||
50 | skb->nh.raw = &top_iph->nexthdr; | ||
51 | skb->h.ipv6h = top_iph + 1; | ||
52 | |||
53 | ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); | ||
54 | ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) | ||
60 | { | ||
61 | struct ipv6hdr *ip6h; | ||
62 | int size = sizeof(struct ipv6hdr); | ||
63 | int err = -EINVAL; | ||
64 | |||
65 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | ||
66 | goto out; | ||
67 | |||
68 | skb_push(skb, size); | ||
69 | memmove(skb->data, skb->nh.raw, size); | ||
70 | skb->nh.raw = skb->data; | ||
71 | |||
72 | skb->mac.raw = memmove(skb->data - skb->mac_len, | ||
73 | skb->mac.raw, skb->mac_len); | ||
74 | |||
75 | ip6h = skb->nh.ipv6h; | ||
76 | ip6h->payload_len = htons(skb->len - size); | ||
77 | ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *) &x->sel.daddr.a6); | ||
78 | ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *) &x->sel.saddr.a6); | ||
79 | err = 0; | ||
80 | out: | ||
81 | return err; | ||
82 | } | ||
83 | |||
84 | static struct xfrm_mode xfrm6_beet_mode = { | ||
85 | .input = xfrm6_beet_input, | ||
86 | .output = xfrm6_beet_output, | ||
87 | .owner = THIS_MODULE, | ||
88 | .encap = XFRM_MODE_BEET, | ||
89 | }; | ||
90 | |||
91 | static int __init xfrm6_beet_init(void) | ||
92 | { | ||
93 | return xfrm_register_mode(&xfrm6_beet_mode, AF_INET6); | ||
94 | } | ||
95 | |||
96 | static void __exit xfrm6_beet_exit(void) | ||
97 | { | ||
98 | int err; | ||
99 | |||
100 | err = xfrm_unregister_mode(&xfrm6_beet_mode, AF_INET6); | ||
101 | BUG_ON(err); | ||
102 | } | ||
103 | |||
104 | module_init(xfrm6_beet_init); | ||
105 | module_exit(xfrm6_beet_exit); | ||
106 | MODULE_LICENSE("GPL"); | ||
107 | MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_BEET); | ||
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 0a28d2c5c44f..ce94732b8e23 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -365,7 +365,7 @@ config NETFILTER_XT_MATCH_MULTIPORT | |||
365 | 365 | ||
366 | config NETFILTER_XT_MATCH_PHYSDEV | 366 | config NETFILTER_XT_MATCH_PHYSDEV |
367 | tristate '"physdev" match support' | 367 | tristate '"physdev" match support' |
368 | depends on NETFILTER_XTABLES && BRIDGE_NETFILTER | 368 | depends on NETFILTER_XTABLES && BRIDGE && BRIDGE_NETFILTER |
369 | help | 369 | help |
370 | Physdev packet matching matches against the physical bridge ports | 370 | Physdev packet matching matches against the physical bridge ports |
371 | the IP packet arrived on or will leave by. | 371 | the IP packet arrived on or will leave by. |
diff --git a/net/sched/estimator.c b/net/sched/estimator.c deleted file mode 100644 index 0ebc98e9be2d..000000000000 --- a/net/sched/estimator.c +++ /dev/null | |||
@@ -1,196 +0,0 @@ | |||
1 | /* | ||
2 | * net/sched/estimator.c Simple rate estimator. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | ||
10 | */ | ||
11 | |||
12 | #include <asm/uaccess.h> | ||
13 | #include <asm/system.h> | ||
14 | #include <linux/bitops.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/types.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/jiffies.h> | ||
19 | #include <linux/string.h> | ||
20 | #include <linux/mm.h> | ||
21 | #include <linux/socket.h> | ||
22 | #include <linux/sockios.h> | ||
23 | #include <linux/in.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/netdevice.h> | ||
27 | #include <linux/skbuff.h> | ||
28 | #include <linux/rtnetlink.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <net/sock.h> | ||
31 | #include <net/pkt_sched.h> | ||
32 | |||
33 | /* | ||
34 | This code is NOT intended to be used for statistics collection, | ||
35 | its purpose is to provide a base for statistical multiplexing | ||
36 | for controlled load service. | ||
37 | If you need only statistics, run a user level daemon which | ||
38 | periodically reads byte counters. | ||
39 | |||
40 | Unfortunately, rate estimation is not a very easy task. | ||
41 | F.e. I did not find a simple way to estimate the current peak rate | ||
42 | and even failed to formulate the problem 8)8) | ||
43 | |||
44 | So I preferred not to built an estimator into the scheduler, | ||
45 | but run this task separately. | ||
46 | Ideally, it should be kernel thread(s), but for now it runs | ||
47 | from timers, which puts apparent top bounds on the number of rated | ||
48 | flows, has minimal overhead on small, but is enough | ||
49 | to handle controlled load service, sets of aggregates. | ||
50 | |||
51 | We measure rate over A=(1<<interval) seconds and evaluate EWMA: | ||
52 | |||
53 | avrate = avrate*(1-W) + rate*W | ||
54 | |||
55 | where W is chosen as negative power of 2: W = 2^(-ewma_log) | ||
56 | |||
57 | The resulting time constant is: | ||
58 | |||
59 | T = A/(-ln(1-W)) | ||
60 | |||
61 | |||
62 | NOTES. | ||
63 | |||
64 | * The stored value for avbps is scaled by 2^5, so that maximal | ||
65 | rate is ~1Gbit, avpps is scaled by 2^10. | ||
66 | |||
67 | * Minimal interval is HZ/4=250msec (it is the greatest common divisor | ||
68 | for HZ=100 and HZ=1024 8)), maximal interval | ||
69 | is (HZ*2^EST_MAX_INTERVAL)/4 = 8sec. Shorter intervals | ||
70 | are too expensive, longer ones can be implemented | ||
71 | at user level painlessly. | ||
72 | */ | ||
73 | |||
74 | #define EST_MAX_INTERVAL 5 | ||
75 | |||
76 | struct qdisc_estimator | ||
77 | { | ||
78 | struct qdisc_estimator *next; | ||
79 | struct tc_stats *stats; | ||
80 | spinlock_t *stats_lock; | ||
81 | unsigned interval; | ||
82 | int ewma_log; | ||
83 | u64 last_bytes; | ||
84 | u32 last_packets; | ||
85 | u32 avpps; | ||
86 | u32 avbps; | ||
87 | }; | ||
88 | |||
89 | struct qdisc_estimator_head | ||
90 | { | ||
91 | struct timer_list timer; | ||
92 | struct qdisc_estimator *list; | ||
93 | }; | ||
94 | |||
95 | static struct qdisc_estimator_head elist[EST_MAX_INTERVAL+1]; | ||
96 | |||
97 | /* Estimator array lock */ | ||
98 | static DEFINE_RWLOCK(est_lock); | ||
99 | |||
100 | static void est_timer(unsigned long arg) | ||
101 | { | ||
102 | int idx = (int)arg; | ||
103 | struct qdisc_estimator *e; | ||
104 | |||
105 | read_lock(&est_lock); | ||
106 | for (e = elist[idx].list; e; e = e->next) { | ||
107 | struct tc_stats *st = e->stats; | ||
108 | u64 nbytes; | ||
109 | u32 npackets; | ||
110 | u32 rate; | ||
111 | |||
112 | spin_lock(e->stats_lock); | ||
113 | nbytes = st->bytes; | ||
114 | npackets = st->packets; | ||
115 | rate = (nbytes - e->last_bytes)<<(7 - idx); | ||
116 | e->last_bytes = nbytes; | ||
117 | e->avbps += ((long)rate - (long)e->avbps) >> e->ewma_log; | ||
118 | st->bps = (e->avbps+0xF)>>5; | ||
119 | |||
120 | rate = (npackets - e->last_packets)<<(12 - idx); | ||
121 | e->last_packets = npackets; | ||
122 | e->avpps += ((long)rate - (long)e->avpps) >> e->ewma_log; | ||
123 | e->stats->pps = (e->avpps+0x1FF)>>10; | ||
124 | spin_unlock(e->stats_lock); | ||
125 | } | ||
126 | |||
127 | mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4)); | ||
128 | read_unlock(&est_lock); | ||
129 | } | ||
130 | |||
131 | int qdisc_new_estimator(struct tc_stats *stats, spinlock_t *stats_lock, struct rtattr *opt) | ||
132 | { | ||
133 | struct qdisc_estimator *est; | ||
134 | struct tc_estimator *parm = RTA_DATA(opt); | ||
135 | |||
136 | if (RTA_PAYLOAD(opt) < sizeof(*parm)) | ||
137 | return -EINVAL; | ||
138 | |||
139 | if (parm->interval < -2 || parm->interval > 3) | ||
140 | return -EINVAL; | ||
141 | |||
142 | est = kzalloc(sizeof(*est), GFP_KERNEL); | ||
143 | if (est == NULL) | ||
144 | return -ENOBUFS; | ||
145 | |||
146 | est->interval = parm->interval + 2; | ||
147 | est->stats = stats; | ||
148 | est->stats_lock = stats_lock; | ||
149 | est->ewma_log = parm->ewma_log; | ||
150 | est->last_bytes = stats->bytes; | ||
151 | est->avbps = stats->bps<<5; | ||
152 | est->last_packets = stats->packets; | ||
153 | est->avpps = stats->pps<<10; | ||
154 | |||
155 | est->next = elist[est->interval].list; | ||
156 | if (est->next == NULL) { | ||
157 | init_timer(&elist[est->interval].timer); | ||
158 | elist[est->interval].timer.data = est->interval; | ||
159 | elist[est->interval].timer.expires = jiffies + ((HZ<<est->interval)/4); | ||
160 | elist[est->interval].timer.function = est_timer; | ||
161 | add_timer(&elist[est->interval].timer); | ||
162 | } | ||
163 | write_lock_bh(&est_lock); | ||
164 | elist[est->interval].list = est; | ||
165 | write_unlock_bh(&est_lock); | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | void qdisc_kill_estimator(struct tc_stats *stats) | ||
170 | { | ||
171 | int idx; | ||
172 | struct qdisc_estimator *est, **pest; | ||
173 | |||
174 | for (idx=0; idx <= EST_MAX_INTERVAL; idx++) { | ||
175 | int killed = 0; | ||
176 | pest = &elist[idx].list; | ||
177 | while ((est=*pest) != NULL) { | ||
178 | if (est->stats != stats) { | ||
179 | pest = &est->next; | ||
180 | continue; | ||
181 | } | ||
182 | |||
183 | write_lock_bh(&est_lock); | ||
184 | *pest = est->next; | ||
185 | write_unlock_bh(&est_lock); | ||
186 | |||
187 | kfree(est); | ||
188 | killed++; | ||
189 | } | ||
190 | if (killed && elist[idx].list == NULL) | ||
191 | del_timer(&elist[idx].timer); | ||
192 | } | ||
193 | } | ||
194 | |||
195 | EXPORT_SYMBOL(qdisc_kill_estimator); | ||
196 | EXPORT_SYMBOL(qdisc_new_estimator); | ||
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 6c058e3660c0..bb3ddd4784b1 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -391,7 +391,7 @@ static inline void htb_add_class_to_row(struct htb_sched *q, | |||
391 | /* If this triggers, it is a bug in this code, but it need not be fatal */ | 391 | /* If this triggers, it is a bug in this code, but it need not be fatal */ |
392 | static void htb_safe_rb_erase(struct rb_node *rb, struct rb_root *root) | 392 | static void htb_safe_rb_erase(struct rb_node *rb, struct rb_root *root) |
393 | { | 393 | { |
394 | if (!RB_EMPTY_NODE(rb)) { | 394 | if (RB_EMPTY_NODE(rb)) { |
395 | WARN_ON(1); | 395 | WARN_ON(1); |
396 | } else { | 396 | } else { |
397 | rb_erase(rb, root); | 397 | rb_erase(rb, root); |
diff --git a/net/tipc/link.c b/net/tipc/link.c index 693f02eca6d6..53bc8cb5adbc 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -1666,8 +1666,9 @@ static void link_retransmit_failure(struct link *l_ptr, struct sk_buff *buf) | |||
1666 | char addr_string[16]; | 1666 | char addr_string[16]; |
1667 | 1667 | ||
1668 | tipc_printf(TIPC_OUTPUT, "Msg seq number: %u, ", msg_seqno(msg)); | 1668 | tipc_printf(TIPC_OUTPUT, "Msg seq number: %u, ", msg_seqno(msg)); |
1669 | tipc_printf(TIPC_OUTPUT, "Outstanding acks: %u\n", (u32)TIPC_SKB_CB(buf)->handle); | 1669 | tipc_printf(TIPC_OUTPUT, "Outstanding acks: %lu\n", |
1670 | 1670 | (unsigned long) TIPC_SKB_CB(buf)->handle); | |
1671 | |||
1671 | n_ptr = l_ptr->owner->next; | 1672 | n_ptr = l_ptr->owner->next; |
1672 | tipc_node_lock(n_ptr); | 1673 | tipc_node_lock(n_ptr); |
1673 | 1674 | ||
diff --git a/net/xfrm/xfrm_hash.h b/net/xfrm/xfrm_hash.h index 6ac4e4f033ac..d401dc8f05ed 100644 --- a/net/xfrm/xfrm_hash.h +++ b/net/xfrm/xfrm_hash.h | |||
@@ -41,17 +41,18 @@ static inline unsigned int __xfrm_dst_hash(xfrm_address_t *daddr, xfrm_address_t | |||
41 | return (h ^ (h >> 16)) & hmask; | 41 | return (h ^ (h >> 16)) & hmask; |
42 | } | 42 | } |
43 | 43 | ||
44 | static inline unsigned __xfrm_src_hash(xfrm_address_t *saddr, | 44 | static inline unsigned __xfrm_src_hash(xfrm_address_t *daddr, |
45 | xfrm_address_t *saddr, | ||
45 | unsigned short family, | 46 | unsigned short family, |
46 | unsigned int hmask) | 47 | unsigned int hmask) |
47 | { | 48 | { |
48 | unsigned int h = family; | 49 | unsigned int h = family; |
49 | switch (family) { | 50 | switch (family) { |
50 | case AF_INET: | 51 | case AF_INET: |
51 | h ^= __xfrm4_addr_hash(saddr); | 52 | h ^= __xfrm4_daddr_saddr_hash(daddr, saddr); |
52 | break; | 53 | break; |
53 | case AF_INET6: | 54 | case AF_INET6: |
54 | h ^= __xfrm6_addr_hash(saddr); | 55 | h ^= __xfrm6_daddr_saddr_hash(daddr, saddr); |
55 | break; | 56 | break; |
56 | }; | 57 | }; |
57 | return (h ^ (h >> 16)) & hmask; | 58 | return (h ^ (h >> 16)) & hmask; |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index b6e2e79d7261..2a7861661f14 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -778,8 +778,9 @@ void xfrm_policy_flush(u8 type) | |||
778 | for (dir = 0; dir < XFRM_POLICY_MAX; dir++) { | 778 | for (dir = 0; dir < XFRM_POLICY_MAX; dir++) { |
779 | struct xfrm_policy *pol; | 779 | struct xfrm_policy *pol; |
780 | struct hlist_node *entry; | 780 | struct hlist_node *entry; |
781 | int i; | 781 | int i, killed; |
782 | 782 | ||
783 | killed = 0; | ||
783 | again1: | 784 | again1: |
784 | hlist_for_each_entry(pol, entry, | 785 | hlist_for_each_entry(pol, entry, |
785 | &xfrm_policy_inexact[dir], bydst) { | 786 | &xfrm_policy_inexact[dir], bydst) { |
@@ -790,6 +791,7 @@ void xfrm_policy_flush(u8 type) | |||
790 | write_unlock_bh(&xfrm_policy_lock); | 791 | write_unlock_bh(&xfrm_policy_lock); |
791 | 792 | ||
792 | xfrm_policy_kill(pol); | 793 | xfrm_policy_kill(pol); |
794 | killed++; | ||
793 | 795 | ||
794 | write_lock_bh(&xfrm_policy_lock); | 796 | write_lock_bh(&xfrm_policy_lock); |
795 | goto again1; | 797 | goto again1; |
@@ -807,13 +809,14 @@ void xfrm_policy_flush(u8 type) | |||
807 | write_unlock_bh(&xfrm_policy_lock); | 809 | write_unlock_bh(&xfrm_policy_lock); |
808 | 810 | ||
809 | xfrm_policy_kill(pol); | 811 | xfrm_policy_kill(pol); |
812 | killed++; | ||
810 | 813 | ||
811 | write_lock_bh(&xfrm_policy_lock); | 814 | write_lock_bh(&xfrm_policy_lock); |
812 | goto again2; | 815 | goto again2; |
813 | } | 816 | } |
814 | } | 817 | } |
815 | 818 | ||
816 | xfrm_policy_count[dir] = 0; | 819 | xfrm_policy_count[dir] -= killed; |
817 | } | 820 | } |
818 | atomic_inc(&flow_cache_genid); | 821 | atomic_inc(&flow_cache_genid); |
819 | write_unlock_bh(&xfrm_policy_lock); | 822 | write_unlock_bh(&xfrm_policy_lock); |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index f927b7330f02..39b8bf3a9ded 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -63,10 +63,11 @@ static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, | |||
63 | return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask); | 63 | return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask); |
64 | } | 64 | } |
65 | 65 | ||
66 | static inline unsigned int xfrm_src_hash(xfrm_address_t *addr, | 66 | static inline unsigned int xfrm_src_hash(xfrm_address_t *daddr, |
67 | xfrm_address_t *saddr, | ||
67 | unsigned short family) | 68 | unsigned short family) |
68 | { | 69 | { |
69 | return __xfrm_src_hash(addr, family, xfrm_state_hmask); | 70 | return __xfrm_src_hash(daddr, saddr, family, xfrm_state_hmask); |
70 | } | 71 | } |
71 | 72 | ||
72 | static inline unsigned int | 73 | static inline unsigned int |
@@ -92,7 +93,8 @@ static void xfrm_hash_transfer(struct hlist_head *list, | |||
92 | nhashmask); | 93 | nhashmask); |
93 | hlist_add_head(&x->bydst, ndsttable+h); | 94 | hlist_add_head(&x->bydst, ndsttable+h); |
94 | 95 | ||
95 | h = __xfrm_src_hash(&x->props.saddr, x->props.family, | 96 | h = __xfrm_src_hash(&x->id.daddr, &x->props.saddr, |
97 | x->props.family, | ||
96 | nhashmask); | 98 | nhashmask); |
97 | hlist_add_head(&x->bysrc, nsrctable+h); | 99 | hlist_add_head(&x->bysrc, nsrctable+h); |
98 | 100 | ||
@@ -458,7 +460,7 @@ static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, | |||
458 | 460 | ||
459 | static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) | 461 | static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) |
460 | { | 462 | { |
461 | unsigned int h = xfrm_src_hash(saddr, family); | 463 | unsigned int h = xfrm_src_hash(daddr, saddr, family); |
462 | struct xfrm_state *x; | 464 | struct xfrm_state *x; |
463 | struct hlist_node *entry; | 465 | struct hlist_node *entry; |
464 | 466 | ||
@@ -587,7 +589,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
587 | if (km_query(x, tmpl, pol) == 0) { | 589 | if (km_query(x, tmpl, pol) == 0) { |
588 | x->km.state = XFRM_STATE_ACQ; | 590 | x->km.state = XFRM_STATE_ACQ; |
589 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); | 591 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); |
590 | h = xfrm_src_hash(saddr, family); | 592 | h = xfrm_src_hash(daddr, saddr, family); |
591 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); | 593 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); |
592 | if (x->id.spi) { | 594 | if (x->id.spi) { |
593 | h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family); | 595 | h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family); |
@@ -622,7 +624,7 @@ static void __xfrm_state_insert(struct xfrm_state *x) | |||
622 | x->props.reqid, x->props.family); | 624 | x->props.reqid, x->props.family); |
623 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); | 625 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); |
624 | 626 | ||
625 | h = xfrm_src_hash(&x->props.saddr, x->props.family); | 627 | h = xfrm_src_hash(&x->id.daddr, &x->props.saddr, x->props.family); |
626 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); | 628 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); |
627 | 629 | ||
628 | if (x->id.spi) { | 630 | if (x->id.spi) { |
@@ -748,7 +750,7 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re | |||
748 | x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ; | 750 | x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ; |
749 | add_timer(&x->timer); | 751 | add_timer(&x->timer); |
750 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); | 752 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); |
751 | h = xfrm_src_hash(saddr, family); | 753 | h = xfrm_src_hash(daddr, saddr, family); |
752 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); | 754 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); |
753 | wake_up(&km_waitq); | 755 | wake_up(&km_waitq); |
754 | } | 756 | } |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index c59a78d2923a..d54b3a70d5df 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -211,6 +211,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, | |||
211 | case XFRM_MODE_TRANSPORT: | 211 | case XFRM_MODE_TRANSPORT: |
212 | case XFRM_MODE_TUNNEL: | 212 | case XFRM_MODE_TUNNEL: |
213 | case XFRM_MODE_ROUTEOPTIMIZATION: | 213 | case XFRM_MODE_ROUTEOPTIMIZATION: |
214 | case XFRM_MODE_BEET: | ||
214 | break; | 215 | break; |
215 | 216 | ||
216 | default: | 217 | default: |