diff options
author | David S. Miller <davem@davemloft.net> | 2008-03-27 21:48:56 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-03-27 21:48:56 -0400 |
commit | 8e8e43843ba3ced0c657cbc0fdb10644ec60f772 (patch) | |
tree | e64954326ced9c365c52c256f01b5f9fb1bcae66 /net | |
parent | ed85f2c3b2b72bd20f617ac749f5c22be8d0f66e (diff) | |
parent | 50fd4407b8bfbde7c1a0bfe4f24de7df37164342 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts:
drivers/net/usb/rndis_host.c
drivers/net/wireless/b43/dma.c
net/ipv6/ndisc.c
Diffstat (limited to 'net')
33 files changed, 180 insertions, 103 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index e536162b1ebc..0e3b2d3e2339 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 75c3f7f4edd5..7aa01125287e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -3330,7 +3330,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) | |||
3330 | return -EOPNOTSUPP; | 3330 | return -EOPNOTSUPP; |
3331 | 3331 | ||
3332 | case SIOCADDMULTI: | 3332 | case SIOCADDMULTI: |
3333 | if (!dev->set_multicast_list || | 3333 | if ((!dev->set_multicast_list && !dev->set_rx_mode) || |
3334 | ifr->ifr_hwaddr.sa_family != AF_UNSPEC) | 3334 | ifr->ifr_hwaddr.sa_family != AF_UNSPEC) |
3335 | return -EINVAL; | 3335 | return -EINVAL; |
3336 | if (!netif_device_present(dev)) | 3336 | if (!netif_device_present(dev)) |
@@ -3339,7 +3339,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) | |||
3339 | dev->addr_len, 1); | 3339 | dev->addr_len, 1); |
3340 | 3340 | ||
3341 | case SIOCDELMULTI: | 3341 | case SIOCDELMULTI: |
3342 | if (!dev->set_multicast_list || | 3342 | if ((!dev->set_multicast_list && !dev->set_rx_mode) || |
3343 | ifr->ifr_hwaddr.sa_family != AF_UNSPEC) | 3343 | ifr->ifr_hwaddr.sa_family != AF_UNSPEC) |
3344 | return -EINVAL; | 3344 | return -EINVAL; |
3345 | if (!netif_device_present(dev)) | 3345 | if (!netif_device_present(dev)) |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 857915a12c15..d8d0ca99c651 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 | (pneigh_net(n) == 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) |
@@ -2808,6 +2830,7 @@ EXPORT_SYMBOL(neigh_table_init_no_netlink); | |||
2808 | EXPORT_SYMBOL(neigh_update); | 2830 | EXPORT_SYMBOL(neigh_update); |
2809 | EXPORT_SYMBOL(pneigh_enqueue); | 2831 | EXPORT_SYMBOL(pneigh_enqueue); |
2810 | EXPORT_SYMBOL(pneigh_lookup); | 2832 | EXPORT_SYMBOL(pneigh_lookup); |
2833 | EXPORT_SYMBOL_GPL(__pneigh_lookup); | ||
2811 | 2834 | ||
2812 | #ifdef CONFIG_ARPD | 2835 | #ifdef CONFIG_ARPD |
2813 | EXPORT_SYMBOL(neigh_app_ns); | 2836 | EXPORT_SYMBOL(neigh_app_ns); |
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index f3ceca31aa45..4e73e5708e70 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c | |||
@@ -336,7 +336,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) | |||
336 | struct scatterlist *asg; | 336 | struct scatterlist *asg; |
337 | int err = -EINVAL; | 337 | int err = -EINVAL; |
338 | 338 | ||
339 | if (!pskb_may_pull(skb, sizeof(*esph))) | 339 | if (!pskb_may_pull(skb, sizeof(*esph) + crypto_aead_ivsize(aead))) |
340 | goto out; | 340 | goto out; |
341 | 341 | ||
342 | if (elen <= 0) | 342 | if (elen <= 0) |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 3697e0528317..803bc9f173a7 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -577,7 +577,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
577 | } | 577 | } |
578 | 578 | ||
579 | if (xfrm_decode_session_reverse(skb_in, &fl, AF_INET)) | 579 | if (xfrm_decode_session_reverse(skb_in, &fl, AF_INET)) |
580 | goto out_unlock; | 580 | goto ende; |
581 | 581 | ||
582 | if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL) | 582 | if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL) |
583 | err = __ip_route_output_key(net, &rt2, &fl); | 583 | err = __ip_route_output_key(net, &rt2, &fl); |
@@ -587,7 +587,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
587 | 587 | ||
588 | fl2.fl4_dst = fl.fl4_src; | 588 | fl2.fl4_dst = fl.fl4_src; |
589 | if (ip_route_output_key(net, &rt2, &fl2)) | 589 | if (ip_route_output_key(net, &rt2, &fl2)) |
590 | goto out_unlock; | 590 | goto ende; |
591 | 591 | ||
592 | /* Ugh! */ | 592 | /* Ugh! */ |
593 | odst = skb_in->dst; | 593 | odst = skb_in->dst; |
@@ -600,7 +600,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
600 | } | 600 | } |
601 | 601 | ||
602 | if (err) | 602 | if (err) |
603 | goto out_unlock; | 603 | goto ende; |
604 | 604 | ||
605 | err = xfrm_lookup((struct dst_entry **)&rt2, &fl, NULL, | 605 | err = xfrm_lookup((struct dst_entry **)&rt2, &fl, NULL, |
606 | XFRM_LOOKUP_ICMP); | 606 | XFRM_LOOKUP_ICMP); |
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 500998a2dec1..719be29f7506 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c | |||
@@ -588,11 +588,9 @@ static int __init ip_queue_init(void) | |||
588 | } | 588 | } |
589 | 589 | ||
590 | #ifdef CONFIG_PROC_FS | 590 | #ifdef CONFIG_PROC_FS |
591 | proc = create_proc_entry(IPQ_PROC_FS_NAME, 0, init_net.proc_net); | 591 | proc = proc_create(IPQ_PROC_FS_NAME, 0, init_net.proc_net, |
592 | if (proc) { | 592 | &ip_queue_proc_fops); |
593 | proc->owner = THIS_MODULE; | 593 | if (!proc) { |
594 | proc->proc_fops = &ip_queue_proc_fops; | ||
595 | } else { | ||
596 | printk(KERN_ERR "ip_queue: failed to create proc entry\n"); | 594 | printk(KERN_ERR "ip_queue: failed to create proc entry\n"); |
597 | goto cleanup_ipqnl; | 595 | goto cleanup_ipqnl; |
598 | } | 596 | } |
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 1b10f3628390..965b08a7d738 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
@@ -167,14 +167,13 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, __be32 ip, | |||
167 | 167 | ||
168 | /* create proc dir entry */ | 168 | /* create proc dir entry */ |
169 | sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip)); | 169 | sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip)); |
170 | c->pde = create_proc_entry(buffer, S_IWUSR|S_IRUSR, | 170 | c->pde = proc_create(buffer, S_IWUSR|S_IRUSR, |
171 | clusterip_procdir); | 171 | clusterip_procdir, &clusterip_proc_fops); |
172 | if (!c->pde) { | 172 | if (!c->pde) { |
173 | kfree(c); | 173 | kfree(c); |
174 | return NULL; | 174 | return NULL; |
175 | } | 175 | } |
176 | } | 176 | } |
177 | c->pde->proc_fops = &clusterip_proc_fops; | ||
178 | c->pde->data = c; | 177 | c->pde->data = c; |
179 | #endif | 178 | #endif |
180 | 179 | ||
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c index 8e8f0425a8ed..50e06690eb5b 100644 --- a/net/ipv4/netfilter/ipt_recent.c +++ b/net/ipv4/netfilter/ipt_recent.c | |||
@@ -276,12 +276,11 @@ recent_mt_check(const char *tablename, const void *ip, | |||
276 | for (i = 0; i < ip_list_hash_size; i++) | 276 | for (i = 0; i < ip_list_hash_size; i++) |
277 | INIT_LIST_HEAD(&t->iphash[i]); | 277 | INIT_LIST_HEAD(&t->iphash[i]); |
278 | #ifdef CONFIG_PROC_FS | 278 | #ifdef CONFIG_PROC_FS |
279 | t->proc = create_proc_entry(t->name, ip_list_perms, proc_dir); | 279 | t->proc = proc_create(t->name, ip_list_perms, proc_dir, &recent_fops); |
280 | if (t->proc == NULL) { | 280 | if (t->proc == NULL) { |
281 | kfree(t); | 281 | kfree(t); |
282 | goto out; | 282 | goto out; |
283 | } | 283 | } |
284 | t->proc->proc_fops = &recent_fops; | ||
285 | t->proc->uid = ip_list_uid; | 284 | t->proc->uid = ip_list_uid; |
286 | t->proc->gid = ip_list_gid; | 285 | t->proc->gid = ip_list_gid; |
287 | t->proc->data = t; | 286 | t->proc->data = t; |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c index 9668c3a23efe..e60b885d2dcd 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c | |||
@@ -395,13 +395,10 @@ int __init nf_conntrack_ipv4_compat_init(void) | |||
395 | if (!proc_exp) | 395 | if (!proc_exp) |
396 | goto err2; | 396 | goto err2; |
397 | 397 | ||
398 | proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, init_net.proc_net_stat); | 398 | proc_stat = proc_create("ip_conntrack", S_IRUGO, |
399 | init_net.proc_net_stat, &ct_cpu_seq_fops); | ||
399 | if (!proc_stat) | 400 | if (!proc_stat) |
400 | goto err3; | 401 | goto err3; |
401 | |||
402 | proc_stat->proc_fops = &ct_cpu_seq_fops; | ||
403 | proc_stat->owner = THIS_MODULE; | ||
404 | |||
405 | return 0; | 402 | return 0; |
406 | 403 | ||
407 | err3: | 404 | err3: |
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/esp6.c b/net/ipv6/esp6.c index 0ec1402320ea..c6bb4c6d24b3 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -282,7 +282,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
282 | struct scatterlist *sg; | 282 | struct scatterlist *sg; |
283 | struct scatterlist *asg; | 283 | struct scatterlist *asg; |
284 | 284 | ||
285 | if (!pskb_may_pull(skb, sizeof(*esph))) { | 285 | if (!pskb_may_pull(skb, sizeof(*esph) + crypto_aead_ivsize(aead))) { |
286 | ret = -EINVAL; | 286 | ret = -EINVAL; |
287 | goto out; | 287 | goto out; |
288 | } | 288 | } |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index b4d8e331432e..e77b74edfd63 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -661,6 +661,20 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) | |||
661 | } | 661 | } |
662 | } | 662 | } |
663 | 663 | ||
664 | static struct pneigh_entry *pndisc_check_router(struct net_device *dev, | ||
665 | struct in6_addr *addr, int *is_router) | ||
666 | { | ||
667 | struct pneigh_entry *n; | ||
668 | |||
669 | read_lock_bh(&nd_tbl.lock); | ||
670 | n = __pneigh_lookup(&nd_tbl, dev_net(dev), addr, dev); | ||
671 | if (n != NULL) | ||
672 | *is_router = (n->flags & NTF_ROUTER); | ||
673 | read_unlock_bh(&nd_tbl.lock); | ||
674 | |||
675 | return n; | ||
676 | } | ||
677 | |||
664 | static void ndisc_recv_ns(struct sk_buff *skb) | 678 | static void ndisc_recv_ns(struct sk_buff *skb) |
665 | { | 679 | { |
666 | struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); | 680 | struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); |
@@ -677,7 +691,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
677 | struct pneigh_entry *pneigh = NULL; | 691 | struct pneigh_entry *pneigh = NULL; |
678 | int dad = ipv6_addr_any(saddr); | 692 | int dad = ipv6_addr_any(saddr); |
679 | int inc; | 693 | int inc; |
680 | int is_router; | 694 | int is_router = 0; |
681 | 695 | ||
682 | if (ipv6_addr_is_multicast(&msg->target)) { | 696 | if (ipv6_addr_is_multicast(&msg->target)) { |
683 | ND_PRINTK2(KERN_WARNING | 697 | ND_PRINTK2(KERN_WARNING |
@@ -776,8 +790,8 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
776 | if (ipv6_chk_acast_addr(dev_net(dev), dev, &msg->target) || | 790 | if (ipv6_chk_acast_addr(dev_net(dev), dev, &msg->target) || |
777 | (idev->cnf.forwarding && | 791 | (idev->cnf.forwarding && |
778 | (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) && | 792 | (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) && |
779 | (pneigh = pneigh_lookup(&nd_tbl, dev_net(dev), | 793 | (pneigh = pndisc_check_router(dev, &msg->target, |
780 | &msg->target, dev, 0)) != NULL)) { | 794 | &is_router)) != NULL)) { |
781 | if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) && | 795 | if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) && |
782 | skb->pkt_type != PACKET_HOST && | 796 | skb->pkt_type != PACKET_HOST && |
783 | inc != 0 && | 797 | inc != 0 && |
@@ -798,7 +812,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
798 | goto out; | 812 | goto out; |
799 | } | 813 | } |
800 | 814 | ||
801 | is_router = !!(pneigh ? pneigh->flags & NTF_ROUTER : idev->cnf.forwarding); | 815 | is_router = !!(pneigh ? is_router : idev->cnf.forwarding); |
802 | 816 | ||
803 | if (dad) { | 817 | if (dad) { |
804 | struct in6_addr maddr; | 818 | struct in6_addr maddr; |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index a6d30626b47c..92a36c9e5402 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -591,11 +591,9 @@ static int __init ip6_queue_init(void) | |||
591 | } | 591 | } |
592 | 592 | ||
593 | #ifdef CONFIG_PROC_FS | 593 | #ifdef CONFIG_PROC_FS |
594 | proc = create_proc_entry(IPQ_PROC_FS_NAME, 0, init_net.proc_net); | 594 | proc = proc_create(IPQ_PROC_FS_NAME, 0, init_net.proc_net, |
595 | if (proc) { | 595 | &ip6_queue_proc_fops); |
596 | proc->owner = THIS_MODULE; | 596 | if (!proc) { |
597 | proc->proc_fops = &ip6_queue_proc_fops; | ||
598 | } else { | ||
599 | printk(KERN_ERR "ip6_queue: failed to create proc entry\n"); | 597 | printk(KERN_ERR "ip6_queue: failed to create proc entry\n"); |
600 | goto cleanup_ipqnl; | 598 | goto cleanup_ipqnl; |
601 | } | 599 | } |
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 5a46bb99c3af..89884a4f23aa 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -151,10 +151,12 @@ int xfrm6_extract_header(struct sk_buff *skb) | |||
151 | { | 151 | { |
152 | struct ipv6hdr *iph = ipv6_hdr(skb); | 152 | struct ipv6hdr *iph = ipv6_hdr(skb); |
153 | 153 | ||
154 | XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph); | ||
154 | XFRM_MODE_SKB_CB(skb)->id = 0; | 155 | XFRM_MODE_SKB_CB(skb)->id = 0; |
155 | XFRM_MODE_SKB_CB(skb)->frag_off = htons(IP_DF); | 156 | XFRM_MODE_SKB_CB(skb)->frag_off = htons(IP_DF); |
156 | XFRM_MODE_SKB_CB(skb)->tos = ipv6_get_dsfield(iph); | 157 | XFRM_MODE_SKB_CB(skb)->tos = ipv6_get_dsfield(iph); |
157 | XFRM_MODE_SKB_CB(skb)->ttl = iph->hop_limit; | 158 | XFRM_MODE_SKB_CB(skb)->ttl = iph->hop_limit; |
159 | XFRM_MODE_SKB_CB(skb)->optlen = 0; | ||
158 | memcpy(XFRM_MODE_SKB_CB(skb)->flow_lbl, iph->flow_lbl, | 160 | memcpy(XFRM_MODE_SKB_CB(skb)->flow_lbl, iph->flow_lbl, |
159 | sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl)); | 161 | sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl)); |
160 | 162 | ||
diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h index a00e422c822e..b001c361ad30 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 50c442fc99ce..6db58924368a 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -1251,7 +1251,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, | |||
1251 | x->sel.prefixlen_s = addr->sadb_address_prefixlen; | 1251 | x->sel.prefixlen_s = addr->sadb_address_prefixlen; |
1252 | } | 1252 | } |
1253 | 1253 | ||
1254 | if (!x->sel.family) | 1254 | if (x->props.mode == XFRM_MODE_TRANSPORT) |
1255 | x->sel.family = x->props.family; | 1255 | x->sel.family = x->props.family; |
1256 | 1256 | ||
1257 | if (ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1]) { | 1257 | if (ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1]) { |
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index a9bf6e4fd0cc..9d0b8bb4113c 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c | |||
@@ -395,7 +395,7 @@ EXPORT_SYMBOL_GPL(nf_ct_log_invalid); | |||
395 | static int __init nf_conntrack_standalone_init(void) | 395 | static int __init nf_conntrack_standalone_init(void) |
396 | { | 396 | { |
397 | #ifdef CONFIG_PROC_FS | 397 | #ifdef CONFIG_PROC_FS |
398 | struct proc_dir_entry *proc, *proc_stat; | 398 | struct proc_dir_entry *proc; |
399 | #endif | 399 | #endif |
400 | int ret = 0; | 400 | int ret = 0; |
401 | 401 | ||
@@ -407,12 +407,9 @@ static int __init nf_conntrack_standalone_init(void) | |||
407 | proc = proc_net_fops_create(&init_net, "nf_conntrack", 0440, &ct_file_ops); | 407 | proc = proc_net_fops_create(&init_net, "nf_conntrack", 0440, &ct_file_ops); |
408 | if (!proc) goto cleanup_init; | 408 | if (!proc) goto cleanup_init; |
409 | 409 | ||
410 | proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, init_net.proc_net_stat); | 410 | if (!proc_create("nf_conntrack", S_IRUGO, |
411 | if (!proc_stat) | 411 | init_net.proc_net_stat, &ct_cpu_seq_fops)) |
412 | goto cleanup_proc; | 412 | goto cleanup_proc; |
413 | |||
414 | proc_stat->proc_fops = &ct_cpu_seq_fops; | ||
415 | proc_stat->owner = THIS_MODULE; | ||
416 | #endif | 413 | #endif |
417 | #ifdef CONFIG_SYSCTL | 414 | #ifdef CONFIG_SYSCTL |
418 | nf_ct_sysctl_header = register_sysctl_paths(nf_ct_path, | 415 | nf_ct_sysctl_header = register_sysctl_paths(nf_ct_path, |
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index cec9976aecbf..bc11d7092032 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c | |||
@@ -168,13 +168,9 @@ static const struct file_operations nflog_file_ops = { | |||
168 | int __init netfilter_log_init(void) | 168 | int __init netfilter_log_init(void) |
169 | { | 169 | { |
170 | #ifdef CONFIG_PROC_FS | 170 | #ifdef CONFIG_PROC_FS |
171 | struct proc_dir_entry *pde; | 171 | if (!proc_create("nf_log", S_IRUGO, |
172 | 172 | proc_net_netfilter, &nflog_file_ops)) | |
173 | pde = create_proc_entry("nf_log", S_IRUGO, proc_net_netfilter); | ||
174 | if (!pde) | ||
175 | return -1; | 173 | return -1; |
176 | |||
177 | pde->proc_fops = &nflog_file_ops; | ||
178 | #endif | 174 | #endif |
179 | return 0; | 175 | return 0; |
180 | } | 176 | } |
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index ddc80ea114cd..bbd26893c0c4 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c | |||
@@ -348,12 +348,9 @@ static const struct file_operations nfqueue_file_ops = { | |||
348 | int __init netfilter_queue_init(void) | 348 | int __init netfilter_queue_init(void) |
349 | { | 349 | { |
350 | #ifdef CONFIG_PROC_FS | 350 | #ifdef CONFIG_PROC_FS |
351 | struct proc_dir_entry *pde; | 351 | if (!proc_create("nf_queue", S_IRUGO, |
352 | 352 | proc_net_netfilter, &nfqueue_file_ops)) | |
353 | pde = create_proc_entry("nf_queue", S_IRUGO, proc_net_netfilter); | ||
354 | if (!pde) | ||
355 | return -1; | 353 | return -1; |
356 | pde->proc_fops = &nfqueue_file_ops; | ||
357 | #endif | 354 | #endif |
358 | return 0; | 355 | return 0; |
359 | } | 356 | } |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index bf3f19b21fe4..b8173af8c24a 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -923,9 +923,6 @@ static const struct file_operations nful_file_ops = { | |||
923 | static int __init nfnetlink_log_init(void) | 923 | static int __init nfnetlink_log_init(void) |
924 | { | 924 | { |
925 | int i, status = -ENOMEM; | 925 | int i, status = -ENOMEM; |
926 | #ifdef CONFIG_PROC_FS | ||
927 | struct proc_dir_entry *proc_nful; | ||
928 | #endif | ||
929 | 926 | ||
930 | for (i = 0; i < INSTANCE_BUCKETS; i++) | 927 | for (i = 0; i < INSTANCE_BUCKETS; i++) |
931 | INIT_HLIST_HEAD(&instance_table[i]); | 928 | INIT_HLIST_HEAD(&instance_table[i]); |
@@ -943,11 +940,9 @@ static int __init nfnetlink_log_init(void) | |||
943 | } | 940 | } |
944 | 941 | ||
945 | #ifdef CONFIG_PROC_FS | 942 | #ifdef CONFIG_PROC_FS |
946 | proc_nful = create_proc_entry("nfnetlink_log", 0440, | 943 | if (!proc_create("nfnetlink_log", 0440, |
947 | proc_net_netfilter); | 944 | proc_net_netfilter, &nful_file_ops)) |
948 | if (!proc_nful) | ||
949 | goto cleanup_subsys; | 945 | goto cleanup_subsys; |
950 | proc_nful->proc_fops = &nful_file_ops; | ||
951 | #endif | 946 | #endif |
952 | return status; | 947 | return status; |
953 | 948 | ||
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 81fb048add88..2c9fe5c12894 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c | |||
@@ -896,9 +896,6 @@ static const struct file_operations nfqnl_file_ops = { | |||
896 | static int __init nfnetlink_queue_init(void) | 896 | static int __init nfnetlink_queue_init(void) |
897 | { | 897 | { |
898 | int i, status = -ENOMEM; | 898 | int i, status = -ENOMEM; |
899 | #ifdef CONFIG_PROC_FS | ||
900 | struct proc_dir_entry *proc_nfqueue; | ||
901 | #endif | ||
902 | 899 | ||
903 | for (i = 0; i < INSTANCE_BUCKETS; i++) | 900 | for (i = 0; i < INSTANCE_BUCKETS; i++) |
904 | INIT_HLIST_HEAD(&instance_table[i]); | 901 | INIT_HLIST_HEAD(&instance_table[i]); |
@@ -911,11 +908,9 @@ static int __init nfnetlink_queue_init(void) | |||
911 | } | 908 | } |
912 | 909 | ||
913 | #ifdef CONFIG_PROC_FS | 910 | #ifdef CONFIG_PROC_FS |
914 | proc_nfqueue = create_proc_entry("nfnetlink_queue", 0440, | 911 | if (!proc_create("nfnetlink_queue", 0440, |
915 | proc_net_netfilter); | 912 | proc_net_netfilter, &nfqnl_file_ops)) |
916 | if (!proc_nfqueue) | ||
917 | goto cleanup_subsys; | 913 | goto cleanup_subsys; |
918 | proc_nfqueue->proc_fops = &nfqnl_file_ops; | ||
919 | #endif | 914 | #endif |
920 | 915 | ||
921 | register_netdevice_notifier(&nfqnl_dev_notifier); | 916 | register_netdevice_notifier(&nfqnl_dev_notifier); |
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index 5418ce59ac3a..dc29007c52cd 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c | |||
@@ -237,14 +237,14 @@ static int htable_create_v0(struct xt_hashlimit_info *minfo, int family) | |||
237 | hinfo->family = family; | 237 | hinfo->family = family; |
238 | hinfo->rnd_initialized = 0; | 238 | hinfo->rnd_initialized = 0; |
239 | spin_lock_init(&hinfo->lock); | 239 | spin_lock_init(&hinfo->lock); |
240 | hinfo->pde = create_proc_entry(minfo->name, 0, | 240 | hinfo->pde = proc_create(minfo->name, 0, |
241 | family == AF_INET ? hashlimit_procdir4 : | 241 | family == AF_INET ? hashlimit_procdir4 : |
242 | hashlimit_procdir6); | 242 | hashlimit_procdir6, |
243 | &dl_file_ops); | ||
243 | if (!hinfo->pde) { | 244 | if (!hinfo->pde) { |
244 | vfree(hinfo); | 245 | vfree(hinfo); |
245 | return -1; | 246 | return -1; |
246 | } | 247 | } |
247 | hinfo->pde->proc_fops = &dl_file_ops; | ||
248 | hinfo->pde->data = hinfo; | 248 | hinfo->pde->data = hinfo; |
249 | 249 | ||
250 | setup_timer(&hinfo->timer, htable_gc, (unsigned long )hinfo); | 250 | setup_timer(&hinfo->timer, htable_gc, (unsigned long )hinfo); |
@@ -301,14 +301,14 @@ static int htable_create(struct xt_hashlimit_mtinfo1 *minfo, | |||
301 | hinfo->rnd_initialized = 0; | 301 | hinfo->rnd_initialized = 0; |
302 | spin_lock_init(&hinfo->lock); | 302 | spin_lock_init(&hinfo->lock); |
303 | 303 | ||
304 | hinfo->pde = create_proc_entry(minfo->name, 0, | 304 | hinfo->pde = proc_create(minfo->name, 0, |
305 | family == AF_INET ? hashlimit_procdir4 : | 305 | family == AF_INET ? hashlimit_procdir4 : |
306 | hashlimit_procdir6); | 306 | hashlimit_procdir6, |
307 | &dl_file_ops); | ||
307 | if (hinfo->pde == NULL) { | 308 | if (hinfo->pde == NULL) { |
308 | vfree(hinfo); | 309 | vfree(hinfo); |
309 | return -1; | 310 | return -1; |
310 | } | 311 | } |
311 | hinfo->pde->proc_fops = &dl_file_ops; | ||
312 | hinfo->pde->data = hinfo; | 312 | hinfo->pde->data = hinfo; |
313 | 313 | ||
314 | setup_timer(&hinfo->timer, htable_gc, (unsigned long)hinfo); | 314 | setup_timer(&hinfo->timer, htable_gc, (unsigned long)hinfo); |
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 9880b792e6a5..5dcc10b93c86 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -389,6 +389,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) | |||
389 | kfree(x->coaddr); | 389 | kfree(x->coaddr); |
390 | if (x->inner_mode) | 390 | if (x->inner_mode) |
391 | xfrm_put_mode(x->inner_mode); | 391 | xfrm_put_mode(x->inner_mode); |
392 | if (x->inner_mode_iaf) | ||
393 | xfrm_put_mode(x->inner_mode_iaf); | ||
392 | if (x->outer_mode) | 394 | if (x->outer_mode) |
393 | xfrm_put_mode(x->outer_mode); | 395 | xfrm_put_mode(x->outer_mode); |
394 | if (x->type) { | 396 | if (x->type) { |
@@ -525,6 +527,8 @@ struct xfrm_state *xfrm_state_alloc(void) | |||
525 | x->lft.hard_packet_limit = XFRM_INF; | 527 | x->lft.hard_packet_limit = XFRM_INF; |
526 | x->replay_maxage = 0; | 528 | x->replay_maxage = 0; |
527 | x->replay_maxdiff = 0; | 529 | x->replay_maxdiff = 0; |
530 | x->inner_mode = NULL; | ||
531 | x->inner_mode_iaf = NULL; | ||
528 | spin_lock_init(&x->lock); | 532 | spin_lock_init(&x->lock); |
529 | } | 533 | } |
530 | return x; | 534 | return x; |
@@ -802,7 +806,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
802 | selector. | 806 | selector. |
803 | */ | 807 | */ |
804 | if (x->km.state == XFRM_STATE_VALID) { | 808 | if (x->km.state == XFRM_STATE_VALID) { |
805 | if (!xfrm_selector_match(&x->sel, fl, x->sel.family) || | 809 | if ((x->sel.family && !xfrm_selector_match(&x->sel, fl, x->sel.family)) || |
806 | !security_xfrm_state_pol_flow_match(x, pol, fl)) | 810 | !security_xfrm_state_pol_flow_match(x, pol, fl)) |
807 | continue; | 811 | continue; |
808 | if (!best || | 812 | if (!best || |
@@ -1963,6 +1967,7 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu) | |||
1963 | int xfrm_init_state(struct xfrm_state *x) | 1967 | int xfrm_init_state(struct xfrm_state *x) |
1964 | { | 1968 | { |
1965 | struct xfrm_state_afinfo *afinfo; | 1969 | struct xfrm_state_afinfo *afinfo; |
1970 | struct xfrm_mode *inner_mode; | ||
1966 | int family = x->props.family; | 1971 | int family = x->props.family; |
1967 | int err; | 1972 | int err; |
1968 | 1973 | ||
@@ -1981,13 +1986,48 @@ int xfrm_init_state(struct xfrm_state *x) | |||
1981 | goto error; | 1986 | goto error; |
1982 | 1987 | ||
1983 | err = -EPROTONOSUPPORT; | 1988 | err = -EPROTONOSUPPORT; |
1984 | x->inner_mode = xfrm_get_mode(x->props.mode, x->sel.family); | ||
1985 | if (x->inner_mode == NULL) | ||
1986 | goto error; | ||
1987 | 1989 | ||
1988 | if (!(x->inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) && | 1990 | if (x->sel.family != AF_UNSPEC) { |
1989 | family != x->sel.family) | 1991 | inner_mode = xfrm_get_mode(x->props.mode, x->sel.family); |
1990 | goto error; | 1992 | if (inner_mode == NULL) |
1993 | goto error; | ||
1994 | |||
1995 | if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) && | ||
1996 | family != x->sel.family) { | ||
1997 | xfrm_put_mode(inner_mode); | ||
1998 | goto error; | ||
1999 | } | ||
2000 | |||
2001 | x->inner_mode = inner_mode; | ||
2002 | } else { | ||
2003 | struct xfrm_mode *inner_mode_iaf; | ||
2004 | |||
2005 | inner_mode = xfrm_get_mode(x->props.mode, AF_INET); | ||
2006 | if (inner_mode == NULL) | ||
2007 | goto error; | ||
2008 | |||
2009 | if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL)) { | ||
2010 | xfrm_put_mode(inner_mode); | ||
2011 | goto error; | ||
2012 | } | ||
2013 | |||
2014 | inner_mode_iaf = xfrm_get_mode(x->props.mode, AF_INET6); | ||
2015 | if (inner_mode_iaf == NULL) | ||
2016 | goto error; | ||
2017 | |||
2018 | if (!(inner_mode_iaf->flags & XFRM_MODE_FLAG_TUNNEL)) { | ||
2019 | xfrm_put_mode(inner_mode_iaf); | ||
2020 | goto error; | ||
2021 | } | ||
2022 | |||
2023 | if (x->props.family == AF_INET) { | ||
2024 | x->inner_mode = inner_mode; | ||
2025 | x->inner_mode_iaf = inner_mode_iaf; | ||
2026 | } else { | ||
2027 | x->inner_mode = inner_mode_iaf; | ||
2028 | x->inner_mode_iaf = inner_mode; | ||
2029 | } | ||
2030 | } | ||
1991 | 2031 | ||
1992 | x->type = xfrm_get_type(x->id.proto, family); | 2032 | x->type = xfrm_get_type(x->id.proto, family); |
1993 | if (x->type == NULL) | 2033 | if (x->type == NULL) |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index f5fd5b3147cc..5578c909fcf6 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 | /* |