aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/8021q/vlan_dev.c2
-rw-r--r--net/ax25/TODO4
-rw-r--r--net/core/dev.c4
-rw-r--r--net/core/neighbour.c23
-rw-r--r--net/ipv4/esp4.c2
-rw-r--r--net/ipv4/icmp.c6
-rw-r--r--net/ipv4/netfilter/ip_queue.c8
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c5
-rw-r--r--net/ipv4/netfilter/ipt_recent.c3
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c7
-rw-r--r--net/ipv4/xfrm4_mode_beet.c11
-rw-r--r--net/ipv4/xfrm4_mode_tunnel.c2
-rw-r--r--net/ipv4/xfrm4_output.c2
-rw-r--r--net/ipv4/xfrm4_state.c2
-rw-r--r--net/ipv6/esp6.c2
-rw-r--r--net/ipv6/ndisc.c22
-rw-r--r--net/ipv6/netfilter/ip6_queue.c8
-rw-r--r--net/ipv6/xfrm6_mode_beet.c1
-rw-r--r--net/ipv6/xfrm6_mode_tunnel.c2
-rw-r--r--net/ipv6/xfrm6_output.c2
-rw-r--r--net/ipv6/xfrm6_state.c2
-rw-r--r--net/irda/irnet/irnet.h2
-rw-r--r--net/key/af_key.c2
-rw-r--r--net/netfilter/nf_conntrack_standalone.c9
-rw-r--r--net/netfilter/nf_log.c8
-rw-r--r--net/netfilter/nf_queue.c7
-rw-r--r--net/netfilter/nfnetlink_log.c9
-rw-r--r--net/netfilter/nfnetlink_queue.c9
-rw-r--r--net/netfilter/xt_hashlimit.c16
-rw-r--r--net/xfrm/xfrm_input.c22
-rw-r--r--net/xfrm/xfrm_output.c18
-rw-r--r--net/xfrm/xfrm_state.c54
-rw-r--r--net/xfrm/xfrm_user.c7
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.
9Routes to a device being taken down might be deleted by ax25_rt_device_down 9Routes to a device being taken down might be deleted by ax25_rt_device_down
10but added by somebody else before the device has been deleted fully. 10but added by somebody else before the device has been deleted fully.
11 11
12Massive amounts of lock_kernel / unlock_kernel are just a temporary solution to
13get around the removal of SOCKOPS_WRAP. A serious locking strategy has to be
14implemented.
15
16The ax25_rt_find_route synopsys is pervert but I somehow had to deal with 12The ax25_rt_find_route synopsys is pervert but I somehow had to deal with
17the race caused by the static variable in it's previous implementation. 13the 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
469struct 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
469struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, 491struct 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);
2808EXPORT_SYMBOL(neigh_update); 2830EXPORT_SYMBOL(neigh_update);
2809EXPORT_SYMBOL(pneigh_enqueue); 2831EXPORT_SYMBOL(pneigh_enqueue);
2810EXPORT_SYMBOL(pneigh_lookup); 2832EXPORT_SYMBOL(pneigh_lookup);
2833EXPORT_SYMBOL_GPL(__pneigh_lookup);
2811 2834
2812#ifdef CONFIG_ARPD 2835#ifdef CONFIG_ARPD
2813EXPORT_SYMBOL(neigh_app_ns); 2836EXPORT_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
407err3: 404err3:
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)
39static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) 39static 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
664static 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
664static void ndisc_recv_ns(struct sk_buff *skb) 678static 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);
395static int __init nf_conntrack_standalone_init(void) 395static 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 = {
168int __init netfilter_log_init(void) 168int __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 = {
348int __init netfilter_queue_init(void) 348int __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 = {
923static int __init nfnetlink_log_init(void) 923static 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 = {
896static int __init nfnetlink_queue_init(void) 896static 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
85int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb) 85int 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}
96EXPORT_SYMBOL(xfrm_prepare_input); 103EXPORT_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
197int 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
196EXPORT_SYMBOL_GPL(xfrm_output); 211EXPORT_SYMBOL_GPL(xfrm_output);
212EXPORT_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)
1963int xfrm_init_state(struct xfrm_state *x) 1967int 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/*