diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-04 11:26:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-04 11:26:19 -0400 |
commit | d002ec481c24f325ed6cfcb7810d317c015dd1b5 (patch) | |
tree | 71fbdce6aab6ffb5f8590e7ddde7c095a7fa31ab /net/ipv6 | |
parent | 5a96c5d0c58ead9a0ece03ffe1c116dea6dafe9c (diff) | |
parent | 0a69452cb45add0841c2bc1e75c25f6bd4f1d8d9 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
[XFRM]: BEET mode
[TCP]: Kill warning in tcp_clean_rtx_queue().
[NET_SCHED]: Remove old estimator implementation
[ATM]: [zatm] always *pcr in alloc_shaper()
[ATM]: [ambassador] Change the return type to reflect reality
[ATM]: kmalloc to kzalloc patches for drivers/atm
[TIPC]: fix printk warning
[XFRM]: Clearing xfrm_policy_count[] to zero during flush is incorrect.
[XFRM] STATE: Use destination address for src hash.
[NEIGH]: always use hash_mask under tbl lock
[UDP]: Fix MSG_PROBE crash
[UDP6]: Fix flowi clobbering
[NET_SCHED]: Revert "HTB: fix incorrect use of RB_EMPTY_NODE"
[NETFILTER]: ebt_mark: add or/and/xor action support to mark target
[NETFILTER]: ipt_REJECT: remove largely duplicate route_reverse function
[NETFILTER]: Honour source routing for LVS-NAT
[NETFILTER]: add type parameter to ip_route_me_harder
[NETFILTER]: Kconfig: fix xt_physdev dependencies
Diffstat (limited to 'net/ipv6')
-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 |
5 files changed, 155 insertions, 32 deletions
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); | ||