diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-03-26 21:35:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-03-26 21:35:50 -0400 |
commit | ee20a0dd5400e771ff93eb7f2bcc731eab1f377e (patch) | |
tree | 43743bd300a5b1ed94888881689e1d6a8ecac1e1 /net | |
parent | d55a4528f7f607ca2872fec18574bc8cec060f05 (diff) | |
parent | 732c8bd590625e8bc0b88313b82930e336b2bec4 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (43 commits)
[IPSEC]: Fix BEET output
[ICMP]: Dst entry leak in icmp_send host re-lookup code (v2).
[AX25]: Remove obsolete references to BKL from TODO file.
[NET]: Fix multicast device ioctl checks
[IRDA]: Store irnet_socket termios properly.
[UML]: uml-net: don't set IFF_ALLMULTI in set_multicast_list
[VLAN]: Don't copy ALLMULTI/PROMISC flags from underlying device
netxen, phy/marvell, skge: minor checkpatch fixes
S2io: Handle TX completions on the same CPU as the sender for MIS-X interrupts
b44: Truncate PHY address
skge napi->poll() locking bug
rndis_host: fix oops when query for OID_GEN_PHYSICAL_MEDIUM fails
cxgb3: Fix lockdep problems with sge.reg_lock
ehea: Fix IPv6 support
dm9000: Support promisc and all-multi modes
dm9601: configure MAC to drop invalid (crc/length) packets
dm9601: add Hirose USB-100 device ID
Marvell PHY m88e1111 driver fix
netxen: fix rx dropped stats
netxen: remove low level tx lock
...
Diffstat (limited to 'net')
-rw-r--r-- | net/8021q/vlan_dev.c | 2 | ||||
-rw-r--r-- | net/ax25/TODO | 4 | ||||
-rw-r--r-- | net/core/dev.c | 4 | ||||
-rw-r--r-- | net/core/neighbour.c | 23 | ||||
-rw-r--r-- | net/ipv4/icmp.c | 6 | ||||
-rw-r--r-- | net/ipv4/xfrm4_mode_beet.c | 11 | ||||
-rw-r--r-- | net/ipv4/xfrm4_mode_tunnel.c | 2 | ||||
-rw-r--r-- | net/ipv4/xfrm4_output.c | 2 | ||||
-rw-r--r-- | net/ipv4/xfrm4_state.c | 2 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 22 | ||||
-rw-r--r-- | net/ipv6/xfrm6_mode_beet.c | 1 | ||||
-rw-r--r-- | net/ipv6/xfrm6_mode_tunnel.c | 2 | ||||
-rw-r--r-- | net/ipv6/xfrm6_output.c | 2 | ||||
-rw-r--r-- | net/ipv6/xfrm6_state.c | 2 | ||||
-rw-r--r-- | net/irda/irnet/irnet.h | 2 | ||||
-rw-r--r-- | net/key/af_key.c | 2 | ||||
-rw-r--r-- | net/xfrm/xfrm_input.c | 22 | ||||
-rw-r--r-- | net/xfrm/xfrm_output.c | 18 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 54 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 7 |
20 files changed, 148 insertions, 42 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 8fbcefe10c9f..480ea90e7dcd 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -660,7 +660,7 @@ static int vlan_dev_init(struct net_device *dev) | |||
660 | int subclass = 0; | 660 | int subclass = 0; |
661 | 661 | ||
662 | /* IFF_BROADCAST|IFF_MULTICAST; ??? */ | 662 | /* IFF_BROADCAST|IFF_MULTICAST; ??? */ |
663 | dev->flags = real_dev->flags & ~IFF_UP; | 663 | dev->flags = real_dev->flags & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI); |
664 | dev->iflink = real_dev->ifindex; | 664 | dev->iflink = real_dev->ifindex; |
665 | dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) | | 665 | dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) | |
666 | (1<<__LINK_STATE_DORMANT))) | | 666 | (1<<__LINK_STATE_DORMANT))) | |
diff --git a/net/ax25/TODO b/net/ax25/TODO index 4089c49e45cc..69fb4e368d92 100644 --- a/net/ax25/TODO +++ b/net/ax25/TODO | |||
@@ -9,10 +9,6 @@ being used. | |||
9 | Routes to a device being taken down might be deleted by ax25_rt_device_down | 9 | Routes to a device being taken down might be deleted by ax25_rt_device_down |
10 | but added by somebody else before the device has been deleted fully. | 10 | but added by somebody else before the device has been deleted fully. |
11 | 11 | ||
12 | Massive amounts of lock_kernel / unlock_kernel are just a temporary solution to | ||
13 | get around the removal of SOCKOPS_WRAP. A serious locking strategy has to be | ||
14 | implemented. | ||
15 | |||
16 | The ax25_rt_find_route synopsys is pervert but I somehow had to deal with | 12 | The ax25_rt_find_route synopsys is pervert but I somehow had to deal with |
17 | the race caused by the static variable in it's previous implementation. | 13 | the race caused by the static variable in it's previous implementation. |
18 | 14 | ||
diff --git a/net/core/dev.c b/net/core/dev.c index fcdf03cf3b3f..460e7f99ce3e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -3329,7 +3329,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) | |||
3329 | return -EOPNOTSUPP; | 3329 | return -EOPNOTSUPP; |
3330 | 3330 | ||
3331 | case SIOCADDMULTI: | 3331 | case SIOCADDMULTI: |
3332 | if (!dev->set_multicast_list || | 3332 | if ((!dev->set_multicast_list && !dev->set_rx_mode) || |
3333 | ifr->ifr_hwaddr.sa_family != AF_UNSPEC) | 3333 | ifr->ifr_hwaddr.sa_family != AF_UNSPEC) |
3334 | return -EINVAL; | 3334 | return -EINVAL; |
3335 | if (!netif_device_present(dev)) | 3335 | if (!netif_device_present(dev)) |
@@ -3338,7 +3338,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) | |||
3338 | dev->addr_len, 1); | 3338 | dev->addr_len, 1); |
3339 | 3339 | ||
3340 | case SIOCDELMULTI: | 3340 | case SIOCDELMULTI: |
3341 | if (!dev->set_multicast_list || | 3341 | if ((!dev->set_multicast_list && !dev->set_rx_mode) || |
3342 | ifr->ifr_hwaddr.sa_family != AF_UNSPEC) | 3342 | ifr->ifr_hwaddr.sa_family != AF_UNSPEC) |
3343 | return -EINVAL; | 3343 | return -EINVAL; |
3344 | if (!netif_device_present(dev)) | 3344 | if (!netif_device_present(dev)) |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index d9a02b2cc289..19b8e003f150 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -466,6 +466,28 @@ out_neigh_release: | |||
466 | goto out; | 466 | goto out; |
467 | } | 467 | } |
468 | 468 | ||
469 | struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl, | ||
470 | struct net *net, const void *pkey, struct net_device *dev) | ||
471 | { | ||
472 | struct pneigh_entry *n; | ||
473 | int key_len = tbl->key_len; | ||
474 | u32 hash_val = *(u32 *)(pkey + key_len - 4); | ||
475 | |||
476 | hash_val ^= (hash_val >> 16); | ||
477 | hash_val ^= hash_val >> 8; | ||
478 | hash_val ^= hash_val >> 4; | ||
479 | hash_val &= PNEIGH_HASHMASK; | ||
480 | |||
481 | for (n = tbl->phash_buckets[hash_val]; n; n = n->next) { | ||
482 | if (!memcmp(n->key, pkey, key_len) && | ||
483 | (n->net == net) && | ||
484 | (n->dev == dev || !n->dev)) | ||
485 | break; | ||
486 | } | ||
487 | |||
488 | return n; | ||
489 | } | ||
490 | |||
469 | struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, | 491 | struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, |
470 | struct net *net, const void *pkey, | 492 | struct net *net, const void *pkey, |
471 | struct net_device *dev, int creat) | 493 | struct net_device *dev, int creat) |
@@ -2803,6 +2825,7 @@ EXPORT_SYMBOL(neigh_table_init_no_netlink); | |||
2803 | EXPORT_SYMBOL(neigh_update); | 2825 | EXPORT_SYMBOL(neigh_update); |
2804 | EXPORT_SYMBOL(pneigh_enqueue); | 2826 | EXPORT_SYMBOL(pneigh_enqueue); |
2805 | EXPORT_SYMBOL(pneigh_lookup); | 2827 | EXPORT_SYMBOL(pneigh_lookup); |
2828 | EXPORT_SYMBOL_GPL(__pneigh_lookup); | ||
2806 | 2829 | ||
2807 | #ifdef CONFIG_ARPD | 2830 | #ifdef CONFIG_ARPD |
2808 | EXPORT_SYMBOL(neigh_app_ns); | 2831 | EXPORT_SYMBOL(neigh_app_ns); |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index a13c074dac09..a944e8053e28 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -591,7 +591,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
591 | } | 591 | } |
592 | 592 | ||
593 | if (xfrm_decode_session_reverse(skb_in, &fl, AF_INET)) | 593 | if (xfrm_decode_session_reverse(skb_in, &fl, AF_INET)) |
594 | goto out_unlock; | 594 | goto ende; |
595 | 595 | ||
596 | if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL) | 596 | if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL) |
597 | err = __ip_route_output_key(net, &rt2, &fl); | 597 | err = __ip_route_output_key(net, &rt2, &fl); |
@@ -601,7 +601,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
601 | 601 | ||
602 | fl2.fl4_dst = fl.fl4_src; | 602 | fl2.fl4_dst = fl.fl4_src; |
603 | if (ip_route_output_key(net, &rt2, &fl2)) | 603 | if (ip_route_output_key(net, &rt2, &fl2)) |
604 | goto out_unlock; | 604 | goto ende; |
605 | 605 | ||
606 | /* Ugh! */ | 606 | /* Ugh! */ |
607 | odst = skb_in->dst; | 607 | odst = skb_in->dst; |
@@ -614,7 +614,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
614 | } | 614 | } |
615 | 615 | ||
616 | if (err) | 616 | if (err) |
617 | goto out_unlock; | 617 | goto ende; |
618 | 618 | ||
619 | err = xfrm_lookup((struct dst_entry **)&rt2, &fl, NULL, | 619 | err = xfrm_lookup((struct dst_entry **)&rt2, &fl, NULL, |
620 | XFRM_LOOKUP_ICMP); | 620 | XFRM_LOOKUP_ICMP); |
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c index b47030ba162b..9c798abce736 100644 --- a/net/ipv4/xfrm4_mode_beet.c +++ b/net/ipv4/xfrm4_mode_beet.c | |||
@@ -39,13 +39,11 @@ static void xfrm4_beet_make_header(struct sk_buff *skb) | |||
39 | static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) | 39 | static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) |
40 | { | 40 | { |
41 | struct ip_beet_phdr *ph; | 41 | struct ip_beet_phdr *ph; |
42 | struct iphdr *iph, *top_iph; | 42 | struct iphdr *top_iph; |
43 | int hdrlen, optlen; | 43 | int hdrlen, optlen; |
44 | 44 | ||
45 | iph = ip_hdr(skb); | ||
46 | |||
47 | hdrlen = 0; | 45 | hdrlen = 0; |
48 | optlen = iph->ihl * 4 - sizeof(*iph); | 46 | optlen = XFRM_MODE_SKB_CB(skb)->optlen; |
49 | if (unlikely(optlen)) | 47 | if (unlikely(optlen)) |
50 | hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4); | 48 | hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4); |
51 | 49 | ||
@@ -53,11 +51,12 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) | |||
53 | hdrlen); | 51 | hdrlen); |
54 | skb->mac_header = skb->network_header + | 52 | skb->mac_header = skb->network_header + |
55 | offsetof(struct iphdr, protocol); | 53 | offsetof(struct iphdr, protocol); |
56 | skb->transport_header = skb->network_header + sizeof(*iph); | 54 | skb->transport_header = skb->network_header + sizeof(*top_iph); |
57 | 55 | ||
58 | xfrm4_beet_make_header(skb); | 56 | xfrm4_beet_make_header(skb); |
59 | 57 | ||
60 | ph = (struct ip_beet_phdr *)__skb_pull(skb, sizeof(*iph) - hdrlen); | 58 | ph = (struct ip_beet_phdr *) |
59 | __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl - hdrlen); | ||
61 | 60 | ||
62 | top_iph = ip_hdr(skb); | 61 | top_iph = ip_hdr(skb); |
63 | 62 | ||
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c index 8dee617ee900..584e6d74e3a9 100644 --- a/net/ipv4/xfrm4_mode_tunnel.c +++ b/net/ipv4/xfrm4_mode_tunnel.c | |||
@@ -41,7 +41,7 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) | |||
41 | top_iph->ihl = 5; | 41 | top_iph->ihl = 5; |
42 | top_iph->version = 4; | 42 | top_iph->version = 4; |
43 | 43 | ||
44 | top_iph->protocol = x->inner_mode->afinfo->proto; | 44 | top_iph->protocol = xfrm_af2proto(skb->dst->ops->family); |
45 | 45 | ||
46 | /* DS disclosed */ | 46 | /* DS disclosed */ |
47 | top_iph->tos = INET_ECN_encapsulate(XFRM_MODE_SKB_CB(skb)->tos, | 47 | top_iph->tos = INET_ECN_encapsulate(XFRM_MODE_SKB_CB(skb)->tos, |
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index d5a58a818021..8c3180adddbf 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c | |||
@@ -56,7 +56,7 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb) | |||
56 | { | 56 | { |
57 | int err; | 57 | int err; |
58 | 58 | ||
59 | err = x->inner_mode->afinfo->extract_output(x, skb); | 59 | err = xfrm_inner_extract_output(x, skb); |
60 | if (err) | 60 | if (err) |
61 | return err; | 61 | return err; |
62 | 62 | ||
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index fdeebe68a379..07735ed280d7 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c | |||
@@ -52,10 +52,12 @@ int xfrm4_extract_header(struct sk_buff *skb) | |||
52 | { | 52 | { |
53 | struct iphdr *iph = ip_hdr(skb); | 53 | struct iphdr *iph = ip_hdr(skb); |
54 | 54 | ||
55 | XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph); | ||
55 | XFRM_MODE_SKB_CB(skb)->id = iph->id; | 56 | XFRM_MODE_SKB_CB(skb)->id = iph->id; |
56 | XFRM_MODE_SKB_CB(skb)->frag_off = iph->frag_off; | 57 | XFRM_MODE_SKB_CB(skb)->frag_off = iph->frag_off; |
57 | XFRM_MODE_SKB_CB(skb)->tos = iph->tos; | 58 | XFRM_MODE_SKB_CB(skb)->tos = iph->tos; |
58 | XFRM_MODE_SKB_CB(skb)->ttl = iph->ttl; | 59 | XFRM_MODE_SKB_CB(skb)->ttl = iph->ttl; |
60 | XFRM_MODE_SKB_CB(skb)->optlen = iph->ihl * 4 - sizeof(*iph); | ||
59 | memset(XFRM_MODE_SKB_CB(skb)->flow_lbl, 0, | 61 | memset(XFRM_MODE_SKB_CB(skb)->flow_lbl, 0, |
60 | sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl)); | 62 | sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl)); |
61 | 63 | ||
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 51557c27a0cd..452a2ac4eec8 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -676,6 +676,20 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) | |||
676 | } | 676 | } |
677 | } | 677 | } |
678 | 678 | ||
679 | static struct pneigh_entry *pndisc_check_router(struct net_device *dev, | ||
680 | struct in6_addr *addr, int *is_router) | ||
681 | { | ||
682 | struct pneigh_entry *n; | ||
683 | |||
684 | read_lock_bh(&nd_tbl.lock); | ||
685 | n = __pneigh_lookup(&nd_tbl, &init_net, addr, dev); | ||
686 | if (n != NULL) | ||
687 | *is_router = (n->flags & NTF_ROUTER); | ||
688 | read_unlock_bh(&nd_tbl.lock); | ||
689 | |||
690 | return n; | ||
691 | } | ||
692 | |||
679 | static void ndisc_recv_ns(struct sk_buff *skb) | 693 | static void ndisc_recv_ns(struct sk_buff *skb) |
680 | { | 694 | { |
681 | struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); | 695 | struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); |
@@ -692,7 +706,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
692 | struct pneigh_entry *pneigh = NULL; | 706 | struct pneigh_entry *pneigh = NULL; |
693 | int dad = ipv6_addr_any(saddr); | 707 | int dad = ipv6_addr_any(saddr); |
694 | int inc; | 708 | int inc; |
695 | int is_router; | 709 | int is_router = 0; |
696 | 710 | ||
697 | if (ipv6_addr_is_multicast(&msg->target)) { | 711 | if (ipv6_addr_is_multicast(&msg->target)) { |
698 | ND_PRINTK2(KERN_WARNING | 712 | ND_PRINTK2(KERN_WARNING |
@@ -790,8 +804,8 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
790 | if (ipv6_chk_acast_addr(dev, &msg->target) || | 804 | if (ipv6_chk_acast_addr(dev, &msg->target) || |
791 | (idev->cnf.forwarding && | 805 | (idev->cnf.forwarding && |
792 | (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) && | 806 | (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) && |
793 | (pneigh = pneigh_lookup(&nd_tbl, &init_net, | 807 | (pneigh = pndisc_check_router(dev, &msg->target, |
794 | &msg->target, dev, 0)) != NULL)) { | 808 | &is_router)) != NULL)) { |
795 | if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) && | 809 | if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) && |
796 | skb->pkt_type != PACKET_HOST && | 810 | skb->pkt_type != PACKET_HOST && |
797 | inc != 0 && | 811 | inc != 0 && |
@@ -812,7 +826,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
812 | goto out; | 826 | goto out; |
813 | } | 827 | } |
814 | 828 | ||
815 | is_router = !!(pneigh ? pneigh->flags & NTF_ROUTER : idev->cnf.forwarding); | 829 | is_router = !!(pneigh ? is_router : idev->cnf.forwarding); |
816 | 830 | ||
817 | if (dad) { | 831 | if (dad) { |
818 | struct in6_addr maddr; | 832 | struct in6_addr maddr; |
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c index 0527d11c1ae3..d6ce400f585f 100644 --- a/net/ipv6/xfrm6_mode_beet.c +++ b/net/ipv6/xfrm6_mode_beet.c | |||
@@ -45,6 +45,7 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) | |||
45 | skb->mac_header = skb->network_header + | 45 | skb->mac_header = skb->network_header + |
46 | offsetof(struct ipv6hdr, nexthdr); | 46 | offsetof(struct ipv6hdr, nexthdr); |
47 | skb->transport_header = skb->network_header + sizeof(*top_iph); | 47 | skb->transport_header = skb->network_header + sizeof(*top_iph); |
48 | __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl); | ||
48 | 49 | ||
49 | xfrm6_beet_make_header(skb); | 50 | xfrm6_beet_make_header(skb); |
50 | 51 | ||
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c index 0c742faaa30b..e20529b4c825 100644 --- a/net/ipv6/xfrm6_mode_tunnel.c +++ b/net/ipv6/xfrm6_mode_tunnel.c | |||
@@ -45,7 +45,7 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) | |||
45 | 45 | ||
46 | memcpy(top_iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl, | 46 | memcpy(top_iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl, |
47 | sizeof(top_iph->flow_lbl)); | 47 | sizeof(top_iph->flow_lbl)); |
48 | top_iph->nexthdr = x->inner_mode->afinfo->proto; | 48 | top_iph->nexthdr = xfrm_af2proto(skb->dst->ops->family); |
49 | 49 | ||
50 | dsfield = XFRM_MODE_SKB_CB(skb)->tos; | 50 | dsfield = XFRM_MODE_SKB_CB(skb)->tos; |
51 | dsfield = INET_ECN_encapsulate(dsfield, dsfield); | 51 | dsfield = INET_ECN_encapsulate(dsfield, dsfield); |
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 79ccfb080733..0af823cf7f1f 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c | |||
@@ -62,7 +62,7 @@ int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb) | |||
62 | { | 62 | { |
63 | int err; | 63 | int err; |
64 | 64 | ||
65 | err = x->inner_mode->afinfo->extract_output(x, skb); | 65 | err = xfrm_inner_extract_output(x, skb); |
66 | if (err) | 66 | if (err) |
67 | return err; | 67 | return err; |
68 | 68 | ||
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index dc817e035e23..ff1e1db8e236 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -174,10 +174,12 @@ int xfrm6_extract_header(struct sk_buff *skb) | |||
174 | { | 174 | { |
175 | struct ipv6hdr *iph = ipv6_hdr(skb); | 175 | struct ipv6hdr *iph = ipv6_hdr(skb); |
176 | 176 | ||
177 | XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph); | ||
177 | XFRM_MODE_SKB_CB(skb)->id = 0; | 178 | XFRM_MODE_SKB_CB(skb)->id = 0; |
178 | XFRM_MODE_SKB_CB(skb)->frag_off = htons(IP_DF); | 179 | XFRM_MODE_SKB_CB(skb)->frag_off = htons(IP_DF); |
179 | XFRM_MODE_SKB_CB(skb)->tos = ipv6_get_dsfield(iph); | 180 | XFRM_MODE_SKB_CB(skb)->tos = ipv6_get_dsfield(iph); |
180 | XFRM_MODE_SKB_CB(skb)->ttl = iph->hop_limit; | 181 | XFRM_MODE_SKB_CB(skb)->ttl = iph->hop_limit; |
182 | XFRM_MODE_SKB_CB(skb)->optlen = 0; | ||
181 | memcpy(XFRM_MODE_SKB_CB(skb)->flow_lbl, iph->flow_lbl, | 183 | memcpy(XFRM_MODE_SKB_CB(skb)->flow_lbl, iph->flow_lbl, |
182 | sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl)); | 184 | sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl)); |
183 | 185 | ||
diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h index bc2e15ce7004..7873c392ab4c 100644 --- a/net/irda/irnet/irnet.h +++ b/net/irda/irnet/irnet.h | |||
@@ -405,7 +405,7 @@ typedef struct irnet_socket | |||
405 | /* "pppd" interact directly with us on a /dev/ file */ | 405 | /* "pppd" interact directly with us on a /dev/ file */ |
406 | struct file * file; /* File descriptor of this instance */ | 406 | struct file * file; /* File descriptor of this instance */ |
407 | /* TTY stuff - to keep "pppd" happy */ | 407 | /* TTY stuff - to keep "pppd" happy */ |
408 | struct termios termios; /* Various tty flags */ | 408 | struct ktermios termios; /* Various tty flags */ |
409 | /* Stuff for the control channel */ | 409 | /* Stuff for the control channel */ |
410 | int event_index; /* Last read in the event log */ | 410 | int event_index; /* Last read in the event log */ |
411 | 411 | ||
diff --git a/net/key/af_key.c b/net/key/af_key.c index 8b5f486ac80f..e9ef9af4a53b 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -1219,7 +1219,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, | |||
1219 | x->sel.prefixlen_s = addr->sadb_address_prefixlen; | 1219 | x->sel.prefixlen_s = addr->sadb_address_prefixlen; |
1220 | } | 1220 | } |
1221 | 1221 | ||
1222 | if (!x->sel.family) | 1222 | if (x->props.mode == XFRM_MODE_TRANSPORT) |
1223 | x->sel.family = x->props.family; | 1223 | x->sel.family = x->props.family; |
1224 | 1224 | ||
1225 | if (ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1]) { | 1225 | if (ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1]) { |
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 62188c6a06dd..75279402ccf4 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c | |||
@@ -84,14 +84,21 @@ int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq) | |||
84 | 84 | ||
85 | int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb) | 85 | int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb) |
86 | { | 86 | { |
87 | struct xfrm_mode *inner_mode = x->inner_mode; | ||
87 | int err; | 88 | int err; |
88 | 89 | ||
89 | err = x->outer_mode->afinfo->extract_input(x, skb); | 90 | err = x->outer_mode->afinfo->extract_input(x, skb); |
90 | if (err) | 91 | if (err) |
91 | return err; | 92 | return err; |
92 | 93 | ||
93 | skb->protocol = x->inner_mode->afinfo->eth_proto; | 94 | if (x->sel.family == AF_UNSPEC) { |
94 | return x->inner_mode->input2(x, skb); | 95 | inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); |
96 | if (inner_mode == NULL) | ||
97 | return -EAFNOSUPPORT; | ||
98 | } | ||
99 | |||
100 | skb->protocol = inner_mode->afinfo->eth_proto; | ||
101 | return inner_mode->input2(x, skb); | ||
95 | } | 102 | } |
96 | EXPORT_SYMBOL(xfrm_prepare_input); | 103 | EXPORT_SYMBOL(xfrm_prepare_input); |
97 | 104 | ||
@@ -101,6 +108,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
101 | __be32 seq; | 108 | __be32 seq; |
102 | struct xfrm_state *x; | 109 | struct xfrm_state *x; |
103 | xfrm_address_t *daddr; | 110 | xfrm_address_t *daddr; |
111 | struct xfrm_mode *inner_mode; | ||
104 | unsigned int family; | 112 | unsigned int family; |
105 | int decaps = 0; | 113 | int decaps = 0; |
106 | int async = 0; | 114 | int async = 0; |
@@ -207,7 +215,15 @@ resume: | |||
207 | 215 | ||
208 | XFRM_MODE_SKB_CB(skb)->protocol = nexthdr; | 216 | XFRM_MODE_SKB_CB(skb)->protocol = nexthdr; |
209 | 217 | ||
210 | if (x->inner_mode->input(x, skb)) { | 218 | inner_mode = x->inner_mode; |
219 | |||
220 | if (x->sel.family == AF_UNSPEC) { | ||
221 | inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); | ||
222 | if (inner_mode == NULL) | ||
223 | goto drop; | ||
224 | } | ||
225 | |||
226 | if (inner_mode->input(x, skb)) { | ||
211 | XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEMODEERROR); | 227 | XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEMODEERROR); |
212 | goto drop; | 228 | goto drop; |
213 | } | 229 | } |
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 569d377932c4..2519129c6d21 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
@@ -124,7 +124,7 @@ int xfrm_output_resume(struct sk_buff *skb, int err) | |||
124 | if (!x) | 124 | if (!x) |
125 | return dst_output(skb); | 125 | return dst_output(skb); |
126 | 126 | ||
127 | err = nf_hook(x->inner_mode->afinfo->family, | 127 | err = nf_hook(skb->dst->ops->family, |
128 | NF_INET_POST_ROUTING, skb, | 128 | NF_INET_POST_ROUTING, skb, |
129 | NULL, skb->dst->dev, xfrm_output2); | 129 | NULL, skb->dst->dev, xfrm_output2); |
130 | if (unlikely(err != 1)) | 130 | if (unlikely(err != 1)) |
@@ -193,4 +193,20 @@ int xfrm_output(struct sk_buff *skb) | |||
193 | 193 | ||
194 | return xfrm_output2(skb); | 194 | return xfrm_output2(skb); |
195 | } | 195 | } |
196 | |||
197 | int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb) | ||
198 | { | ||
199 | struct xfrm_mode *inner_mode; | ||
200 | if (x->sel.family == AF_UNSPEC) | ||
201 | inner_mode = xfrm_ip2inner_mode(x, | ||
202 | xfrm_af2proto(skb->dst->ops->family)); | ||
203 | else | ||
204 | inner_mode = x->inner_mode; | ||
205 | |||
206 | if (inner_mode == NULL) | ||
207 | return -EAFNOSUPPORT; | ||
208 | return inner_mode->afinfo->extract_output(x, skb); | ||
209 | } | ||
210 | |||
196 | EXPORT_SYMBOL_GPL(xfrm_output); | 211 | EXPORT_SYMBOL_GPL(xfrm_output); |
212 | EXPORT_SYMBOL_GPL(xfrm_inner_extract_output); | ||
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 7ba65e82941c..58f1f9347b54 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -388,6 +388,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) | |||
388 | kfree(x->coaddr); | 388 | kfree(x->coaddr); |
389 | if (x->inner_mode) | 389 | if (x->inner_mode) |
390 | xfrm_put_mode(x->inner_mode); | 390 | xfrm_put_mode(x->inner_mode); |
391 | if (x->inner_mode_iaf) | ||
392 | xfrm_put_mode(x->inner_mode_iaf); | ||
391 | if (x->outer_mode) | 393 | if (x->outer_mode) |
392 | xfrm_put_mode(x->outer_mode); | 394 | xfrm_put_mode(x->outer_mode); |
393 | if (x->type) { | 395 | if (x->type) { |
@@ -523,6 +525,8 @@ struct xfrm_state *xfrm_state_alloc(void) | |||
523 | x->lft.hard_packet_limit = XFRM_INF; | 525 | x->lft.hard_packet_limit = XFRM_INF; |
524 | x->replay_maxage = 0; | 526 | x->replay_maxage = 0; |
525 | x->replay_maxdiff = 0; | 527 | x->replay_maxdiff = 0; |
528 | x->inner_mode = NULL; | ||
529 | x->inner_mode_iaf = NULL; | ||
526 | spin_lock_init(&x->lock); | 530 | spin_lock_init(&x->lock); |
527 | } | 531 | } |
528 | return x; | 532 | return x; |
@@ -796,7 +800,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
796 | selector. | 800 | selector. |
797 | */ | 801 | */ |
798 | if (x->km.state == XFRM_STATE_VALID) { | 802 | if (x->km.state == XFRM_STATE_VALID) { |
799 | if (!xfrm_selector_match(&x->sel, fl, x->sel.family) || | 803 | if ((x->sel.family && !xfrm_selector_match(&x->sel, fl, x->sel.family)) || |
800 | !security_xfrm_state_pol_flow_match(x, pol, fl)) | 804 | !security_xfrm_state_pol_flow_match(x, pol, fl)) |
801 | continue; | 805 | continue; |
802 | if (!best || | 806 | if (!best || |
@@ -1944,6 +1948,7 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu) | |||
1944 | int xfrm_init_state(struct xfrm_state *x) | 1948 | int xfrm_init_state(struct xfrm_state *x) |
1945 | { | 1949 | { |
1946 | struct xfrm_state_afinfo *afinfo; | 1950 | struct xfrm_state_afinfo *afinfo; |
1951 | struct xfrm_mode *inner_mode; | ||
1947 | int family = x->props.family; | 1952 | int family = x->props.family; |
1948 | int err; | 1953 | int err; |
1949 | 1954 | ||
@@ -1962,13 +1967,48 @@ int xfrm_init_state(struct xfrm_state *x) | |||
1962 | goto error; | 1967 | goto error; |
1963 | 1968 | ||
1964 | err = -EPROTONOSUPPORT; | 1969 | err = -EPROTONOSUPPORT; |
1965 | x->inner_mode = xfrm_get_mode(x->props.mode, x->sel.family); | ||
1966 | if (x->inner_mode == NULL) | ||
1967 | goto error; | ||
1968 | 1970 | ||
1969 | if (!(x->inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) && | 1971 | if (x->sel.family != AF_UNSPEC) { |
1970 | family != x->sel.family) | 1972 | inner_mode = xfrm_get_mode(x->props.mode, x->sel.family); |
1971 | goto error; | 1973 | if (inner_mode == NULL) |
1974 | goto error; | ||
1975 | |||
1976 | if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) && | ||
1977 | family != x->sel.family) { | ||
1978 | xfrm_put_mode(inner_mode); | ||
1979 | goto error; | ||
1980 | } | ||
1981 | |||
1982 | x->inner_mode = inner_mode; | ||
1983 | } else { | ||
1984 | struct xfrm_mode *inner_mode_iaf; | ||
1985 | |||
1986 | inner_mode = xfrm_get_mode(x->props.mode, AF_INET); | ||
1987 | if (inner_mode == NULL) | ||
1988 | goto error; | ||
1989 | |||
1990 | if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL)) { | ||
1991 | xfrm_put_mode(inner_mode); | ||
1992 | goto error; | ||
1993 | } | ||
1994 | |||
1995 | inner_mode_iaf = xfrm_get_mode(x->props.mode, AF_INET6); | ||
1996 | if (inner_mode_iaf == NULL) | ||
1997 | goto error; | ||
1998 | |||
1999 | if (!(inner_mode_iaf->flags & XFRM_MODE_FLAG_TUNNEL)) { | ||
2000 | xfrm_put_mode(inner_mode_iaf); | ||
2001 | goto error; | ||
2002 | } | ||
2003 | |||
2004 | if (x->props.family == AF_INET) { | ||
2005 | x->inner_mode = inner_mode; | ||
2006 | x->inner_mode_iaf = inner_mode_iaf; | ||
2007 | } else { | ||
2008 | x->inner_mode = inner_mode_iaf; | ||
2009 | x->inner_mode_iaf = inner_mode; | ||
2010 | } | ||
2011 | } | ||
1972 | 2012 | ||
1973 | x->type = xfrm_get_type(x->id.proto, family); | 2013 | x->type = xfrm_get_type(x->id.proto, family); |
1974 | if (x->type == NULL) | 2014 | if (x->type == NULL) |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index f971ca5645f8..5d96f2728dc6 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -288,12 +288,9 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info * | |||
288 | memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr)); | 288 | memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr)); |
289 | x->props.flags = p->flags; | 289 | x->props.flags = p->flags; |
290 | 290 | ||
291 | /* | 291 | if (x->props.mode == XFRM_MODE_TRANSPORT) |
292 | * Set inner address family if the KM left it as zero. | ||
293 | * See comment in validate_tmpl. | ||
294 | */ | ||
295 | if (!x->sel.family) | ||
296 | x->sel.family = p->family; | 292 | x->sel.family = p->family; |
293 | |||
297 | } | 294 | } |
298 | 295 | ||
299 | /* | 296 | /* |