diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/8021q/vlan_core.c | 12 | ||||
-rw-r--r-- | net/core/dev.c | 22 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 3 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_reasm.c | 8 | ||||
-rw-r--r-- | net/mac80211/tx.c | 2 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_core.c | 2 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 1 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_tcp.c | 4 | ||||
-rw-r--r-- | net/wireless/Kconfig | 10 | ||||
-rw-r--r-- | net/wireless/lib80211_crypt_ccmp.c | 2 | ||||
-rw-r--r-- | net/wireless/lib80211_crypt_tkip.c | 4 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 90 |
12 files changed, 99 insertions, 61 deletions
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 2d6e405fc498..654e45f5719d 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c | |||
@@ -98,16 +98,16 @@ static int vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp, | |||
98 | return dev_gro_receive(napi, skb); | 98 | return dev_gro_receive(napi, skb); |
99 | 99 | ||
100 | drop: | 100 | drop: |
101 | return 2; | 101 | return GRO_DROP; |
102 | } | 102 | } |
103 | 103 | ||
104 | int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, | 104 | int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, |
105 | unsigned int vlan_tci, struct sk_buff *skb) | 105 | unsigned int vlan_tci, struct sk_buff *skb) |
106 | { | 106 | { |
107 | skb_gro_reset_offset(skb); | 107 | if (netpoll_rx_on(skb)) |
108 | return vlan_hwaccel_receive_skb(skb, grp, vlan_tci); | ||
108 | 109 | ||
109 | if (netpoll_receive_skb(skb)) | 110 | skb_gro_reset_offset(skb); |
110 | return NET_RX_DROP; | ||
111 | 111 | ||
112 | return napi_skb_finish(vlan_gro_common(napi, grp, vlan_tci, skb), skb); | 112 | return napi_skb_finish(vlan_gro_common(napi, grp, vlan_tci, skb), skb); |
113 | } | 113 | } |
@@ -121,8 +121,8 @@ int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, | |||
121 | if (!skb) | 121 | if (!skb) |
122 | return NET_RX_DROP; | 122 | return NET_RX_DROP; |
123 | 123 | ||
124 | if (netpoll_receive_skb(skb)) | 124 | if (netpoll_rx_on(skb)) |
125 | return NET_RX_DROP; | 125 | return vlan_hwaccel_receive_skb(skb, grp, vlan_tci); |
126 | 126 | ||
127 | return napi_frags_finish(napi, skb, | 127 | return napi_frags_finish(napi, skb, |
128 | vlan_gro_common(napi, grp, vlan_tci, skb)); | 128 | vlan_gro_common(napi, grp, vlan_tci, skb)); |
diff --git a/net/core/dev.c b/net/core/dev.c index 033d7ca28e6e..c01303129119 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -135,14 +135,6 @@ | |||
135 | /* This should be increased if a protocol with a bigger head is added. */ | 135 | /* This should be increased if a protocol with a bigger head is added. */ |
136 | #define GRO_MAX_HEAD (MAX_HEADER + 128) | 136 | #define GRO_MAX_HEAD (MAX_HEADER + 128) |
137 | 137 | ||
138 | enum { | ||
139 | GRO_MERGED, | ||
140 | GRO_MERGED_FREE, | ||
141 | GRO_HELD, | ||
142 | GRO_NORMAL, | ||
143 | GRO_DROP, | ||
144 | }; | ||
145 | |||
146 | /* | 138 | /* |
147 | * The list of packet types we will receive (as opposed to discard) | 139 | * The list of packet types we will receive (as opposed to discard) |
148 | * and the routines to invoke. | 140 | * and the routines to invoke. |
@@ -2474,6 +2466,9 @@ static int __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) | |||
2474 | { | 2466 | { |
2475 | struct sk_buff *p; | 2467 | struct sk_buff *p; |
2476 | 2468 | ||
2469 | if (netpoll_rx_on(skb)) | ||
2470 | return GRO_NORMAL; | ||
2471 | |||
2477 | for (p = napi->gro_list; p; p = p->next) { | 2472 | for (p = napi->gro_list; p; p = p->next) { |
2478 | NAPI_GRO_CB(p)->same_flow = !compare_ether_header( | 2473 | NAPI_GRO_CB(p)->same_flow = !compare_ether_header( |
2479 | skb_mac_header(p), skb_gro_mac_header(skb)); | 2474 | skb_mac_header(p), skb_gro_mac_header(skb)); |
@@ -2487,9 +2482,6 @@ int napi_skb_finish(int ret, struct sk_buff *skb) | |||
2487 | { | 2482 | { |
2488 | int err = NET_RX_SUCCESS; | 2483 | int err = NET_RX_SUCCESS; |
2489 | 2484 | ||
2490 | if (netpoll_receive_skb(skb)) | ||
2491 | return NET_RX_DROP; | ||
2492 | |||
2493 | switch (ret) { | 2485 | switch (ret) { |
2494 | case GRO_NORMAL: | 2486 | case GRO_NORMAL: |
2495 | return netif_receive_skb(skb); | 2487 | return netif_receive_skb(skb); |
@@ -2587,9 +2579,6 @@ int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, int ret) | |||
2587 | { | 2579 | { |
2588 | int err = NET_RX_SUCCESS; | 2580 | int err = NET_RX_SUCCESS; |
2589 | 2581 | ||
2590 | if (netpoll_receive_skb(skb)) | ||
2591 | return NET_RX_DROP; | ||
2592 | |||
2593 | switch (ret) { | 2582 | switch (ret) { |
2594 | case GRO_NORMAL: | 2583 | case GRO_NORMAL: |
2595 | case GRO_HELD: | 2584 | case GRO_HELD: |
@@ -2638,9 +2627,9 @@ static int process_backlog(struct napi_struct *napi, int quota) | |||
2638 | local_irq_disable(); | 2627 | local_irq_disable(); |
2639 | skb = __skb_dequeue(&queue->input_pkt_queue); | 2628 | skb = __skb_dequeue(&queue->input_pkt_queue); |
2640 | if (!skb) { | 2629 | if (!skb) { |
2641 | __napi_complete(napi); | ||
2642 | local_irq_enable(); | 2630 | local_irq_enable(); |
2643 | break; | 2631 | napi_complete(napi); |
2632 | goto out; | ||
2644 | } | 2633 | } |
2645 | local_irq_enable(); | 2634 | local_irq_enable(); |
2646 | 2635 | ||
@@ -2649,6 +2638,7 @@ static int process_backlog(struct napi_struct *napi, int quota) | |||
2649 | 2638 | ||
2650 | napi_gro_flush(napi); | 2639 | napi_gro_flush(napi); |
2651 | 2640 | ||
2641 | out: | ||
2652 | return work; | 2642 | return work; |
2653 | } | 2643 | } |
2654 | 2644 | ||
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 3e2ddfaee81a..fbf533cc9dce 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -1202,6 +1202,9 @@ module_init(inet6_init); | |||
1202 | 1202 | ||
1203 | static void __exit inet6_exit(void) | 1203 | static void __exit inet6_exit(void) |
1204 | { | 1204 | { |
1205 | if (disable_ipv6) | ||
1206 | return; | ||
1207 | |||
1205 | /* First of all disallow new sockets creation. */ | 1208 | /* First of all disallow new sockets creation. */ |
1206 | sock_unregister(PF_INET6); | 1209 | sock_unregister(PF_INET6); |
1207 | /* Disallow any further netlink messages */ | 1210 | /* Disallow any further netlink messages */ |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index ed4d79a9e4a6..058a5e4a60c3 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -528,14 +528,14 @@ find_prev_fhdr(struct sk_buff *skb, u8 *prevhdrp, int *prevhoff, int *fhoff) | |||
528 | if (!ipv6_ext_hdr(nexthdr)) { | 528 | if (!ipv6_ext_hdr(nexthdr)) { |
529 | return -1; | 529 | return -1; |
530 | } | 530 | } |
531 | if (len < (int)sizeof(struct ipv6_opt_hdr)) { | ||
532 | pr_debug("too short\n"); | ||
533 | return -1; | ||
534 | } | ||
535 | if (nexthdr == NEXTHDR_NONE) { | 531 | if (nexthdr == NEXTHDR_NONE) { |
536 | pr_debug("next header is none\n"); | 532 | pr_debug("next header is none\n"); |
537 | return -1; | 533 | return -1; |
538 | } | 534 | } |
535 | if (len < (int)sizeof(struct ipv6_opt_hdr)) { | ||
536 | pr_debug("too short\n"); | ||
537 | return -1; | ||
538 | } | ||
539 | if (skb_copy_bits(skb, start, &hdr, sizeof(hdr))) | 539 | if (skb_copy_bits(skb, start, &hdr, sizeof(hdr))) |
540 | BUG(); | 540 | BUG(); |
541 | if (nexthdr == NEXTHDR_AUTH) | 541 | if (nexthdr == NEXTHDR_AUTH) |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c3f0e950125b..457238a2f3fc 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -784,6 +784,8 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
784 | skb_copy_queue_mapping(frag, first); | 784 | skb_copy_queue_mapping(frag, first); |
785 | 785 | ||
786 | frag->do_not_encrypt = first->do_not_encrypt; | 786 | frag->do_not_encrypt = first->do_not_encrypt; |
787 | frag->dev = first->dev; | ||
788 | frag->iif = first->iif; | ||
787 | 789 | ||
788 | pos += copylen; | 790 | pos += copylen; |
789 | left -= copylen; | 791 | left -= copylen; |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 90ce9ddb9451..f4935e344b61 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -726,7 +726,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, | |||
726 | NF_CT_ASSERT(skb->nfct); | 726 | NF_CT_ASSERT(skb->nfct); |
727 | 727 | ||
728 | ret = l4proto->packet(ct, skb, dataoff, ctinfo, pf, hooknum); | 728 | ret = l4proto->packet(ct, skb, dataoff, ctinfo, pf, hooknum); |
729 | if (ret < 0) { | 729 | if (ret <= 0) { |
730 | /* Invalid: inverse of the return code tells | 730 | /* Invalid: inverse of the return code tells |
731 | * the netfilter core what to do */ | 731 | * the netfilter core what to do */ |
732 | pr_debug("nf_conntrack_in: Can't track with proto module\n"); | 732 | pr_debug("nf_conntrack_in: Can't track with proto module\n"); |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index cb78aa00399e..ed6d873ad384 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -1780,6 +1780,7 @@ ctnetlink_create_expect(struct nlattr *cda[], u_int8_t u3, u32 pid, int report) | |||
1780 | goto out; | 1780 | goto out; |
1781 | } | 1781 | } |
1782 | 1782 | ||
1783 | exp->class = 0; | ||
1783 | exp->expectfn = NULL; | 1784 | exp->expectfn = NULL; |
1784 | exp->flags = 0; | 1785 | exp->flags = 0; |
1785 | exp->master = ct; | 1786 | exp->master = ct; |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index a1edb9c1adee..f3fd154d1ddd 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -859,7 +859,7 @@ static int tcp_packet(struct nf_conn *ct, | |||
859 | */ | 859 | */ |
860 | if (nf_ct_kill(ct)) | 860 | if (nf_ct_kill(ct)) |
861 | return -NF_REPEAT; | 861 | return -NF_REPEAT; |
862 | return -NF_DROP; | 862 | return NF_DROP; |
863 | } | 863 | } |
864 | /* Fall through */ | 864 | /* Fall through */ |
865 | case TCP_CONNTRACK_IGNORE: | 865 | case TCP_CONNTRACK_IGNORE: |
@@ -892,7 +892,7 @@ static int tcp_packet(struct nf_conn *ct, | |||
892 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, | 892 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, |
893 | "nf_ct_tcp: killing out of sync session "); | 893 | "nf_ct_tcp: killing out of sync session "); |
894 | nf_ct_kill(ct); | 894 | nf_ct_kill(ct); |
895 | return -NF_DROP; | 895 | return NF_DROP; |
896 | } | 896 | } |
897 | ct->proto.tcp.last_index = index; | 897 | ct->proto.tcp.last_index = index; |
898 | ct->proto.tcp.last_dir = dir; | 898 | ct->proto.tcp.last_dir = dir; |
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index e28e2b8fa436..092ae6faccca 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -102,3 +102,13 @@ config LIB80211_CRYPT_CCMP | |||
102 | 102 | ||
103 | config LIB80211_CRYPT_TKIP | 103 | config LIB80211_CRYPT_TKIP |
104 | tristate | 104 | tristate |
105 | |||
106 | config LIB80211_DEBUG | ||
107 | bool "lib80211 debugging messages" | ||
108 | depends on LIB80211 | ||
109 | default n | ||
110 | ---help--- | ||
111 | You can enable this if you want verbose debugging messages | ||
112 | from lib80211. | ||
113 | |||
114 | If unsure, say N. | ||
diff --git a/net/wireless/lib80211_crypt_ccmp.c b/net/wireless/lib80211_crypt_ccmp.c index db428194c16a..2301dc1edc4c 100644 --- a/net/wireless/lib80211_crypt_ccmp.c +++ b/net/wireless/lib80211_crypt_ccmp.c | |||
@@ -337,6 +337,7 @@ static int lib80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
337 | pos += 8; | 337 | pos += 8; |
338 | 338 | ||
339 | if (ccmp_replay_check(pn, key->rx_pn)) { | 339 | if (ccmp_replay_check(pn, key->rx_pn)) { |
340 | #ifdef CONFIG_LIB80211_DEBUG | ||
340 | if (net_ratelimit()) { | 341 | if (net_ratelimit()) { |
341 | printk(KERN_DEBUG "CCMP: replay detected: STA=%pM " | 342 | printk(KERN_DEBUG "CCMP: replay detected: STA=%pM " |
342 | "previous PN %02x%02x%02x%02x%02x%02x " | 343 | "previous PN %02x%02x%02x%02x%02x%02x " |
@@ -346,6 +347,7 @@ static int lib80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
346 | key->rx_pn[3], key->rx_pn[4], key->rx_pn[5], | 347 | key->rx_pn[3], key->rx_pn[4], key->rx_pn[5], |
347 | pn[0], pn[1], pn[2], pn[3], pn[4], pn[5]); | 348 | pn[0], pn[1], pn[2], pn[3], pn[4], pn[5]); |
348 | } | 349 | } |
350 | #endif | ||
349 | key->dot11RSNAStatsCCMPReplays++; | 351 | key->dot11RSNAStatsCCMPReplays++; |
350 | return -4; | 352 | return -4; |
351 | } | 353 | } |
diff --git a/net/wireless/lib80211_crypt_tkip.c b/net/wireless/lib80211_crypt_tkip.c index 7e8e22bfed90..c36287399d7e 100644 --- a/net/wireless/lib80211_crypt_tkip.c +++ b/net/wireless/lib80211_crypt_tkip.c | |||
@@ -465,12 +465,14 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
465 | pos += 8; | 465 | pos += 8; |
466 | 466 | ||
467 | if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) { | 467 | if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) { |
468 | #ifdef CONFIG_LIB80211_DEBUG | ||
468 | if (net_ratelimit()) { | 469 | if (net_ratelimit()) { |
469 | printk(KERN_DEBUG "TKIP: replay detected: STA=%pM" | 470 | printk(KERN_DEBUG "TKIP: replay detected: STA=%pM" |
470 | " previous TSC %08x%04x received TSC " | 471 | " previous TSC %08x%04x received TSC " |
471 | "%08x%04x\n", hdr->addr2, | 472 | "%08x%04x\n", hdr->addr2, |
472 | tkey->rx_iv32, tkey->rx_iv16, iv32, iv16); | 473 | tkey->rx_iv32, tkey->rx_iv16, iv32, iv16); |
473 | } | 474 | } |
475 | #endif | ||
474 | tkey->dot11RSNAStatsTKIPReplays++; | 476 | tkey->dot11RSNAStatsTKIPReplays++; |
475 | return -4; | 477 | return -4; |
476 | } | 478 | } |
@@ -505,10 +507,12 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
505 | * it needs to be recalculated for the next packet. */ | 507 | * it needs to be recalculated for the next packet. */ |
506 | tkey->rx_phase1_done = 0; | 508 | tkey->rx_phase1_done = 0; |
507 | } | 509 | } |
510 | #ifdef CONFIG_LIB80211_DEBUG | ||
508 | if (net_ratelimit()) { | 511 | if (net_ratelimit()) { |
509 | printk(KERN_DEBUG "TKIP: ICV error detected: STA=" | 512 | printk(KERN_DEBUG "TKIP: ICV error detected: STA=" |
510 | "%pM\n", hdr->addr2); | 513 | "%pM\n", hdr->addr2); |
511 | } | 514 | } |
515 | #endif | ||
512 | tkey->dot11RSNAStatsTKIPICVErrors++; | 516 | tkey->dot11RSNAStatsTKIPICVErrors++; |
513 | return -5; | 517 | return -5; |
514 | } | 518 | } |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index e25ff62ab2a6..62a5425cc6aa 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -748,12 +748,51 @@ static void xfrm_hash_grow_check(struct net *net, int have_hash_collision) | |||
748 | schedule_work(&net->xfrm.state_hash_work); | 748 | schedule_work(&net->xfrm.state_hash_work); |
749 | } | 749 | } |
750 | 750 | ||
751 | static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x, | ||
752 | struct flowi *fl, unsigned short family, | ||
753 | xfrm_address_t *daddr, xfrm_address_t *saddr, | ||
754 | struct xfrm_state **best, int *acq_in_progress, | ||
755 | int *error) | ||
756 | { | ||
757 | /* Resolution logic: | ||
758 | * 1. There is a valid state with matching selector. Done. | ||
759 | * 2. Valid state with inappropriate selector. Skip. | ||
760 | * | ||
761 | * Entering area of "sysdeps". | ||
762 | * | ||
763 | * 3. If state is not valid, selector is temporary, it selects | ||
764 | * only session which triggered previous resolution. Key | ||
765 | * manager will do something to install a state with proper | ||
766 | * selector. | ||
767 | */ | ||
768 | if (x->km.state == XFRM_STATE_VALID) { | ||
769 | if ((x->sel.family && | ||
770 | !xfrm_selector_match(&x->sel, fl, x->sel.family)) || | ||
771 | !security_xfrm_state_pol_flow_match(x, pol, fl)) | ||
772 | return; | ||
773 | |||
774 | if (!*best || | ||
775 | (*best)->km.dying > x->km.dying || | ||
776 | ((*best)->km.dying == x->km.dying && | ||
777 | (*best)->curlft.add_time < x->curlft.add_time)) | ||
778 | *best = x; | ||
779 | } else if (x->km.state == XFRM_STATE_ACQ) { | ||
780 | *acq_in_progress = 1; | ||
781 | } else if (x->km.state == XFRM_STATE_ERROR || | ||
782 | x->km.state == XFRM_STATE_EXPIRED) { | ||
783 | if (xfrm_selector_match(&x->sel, fl, x->sel.family) && | ||
784 | security_xfrm_state_pol_flow_match(x, pol, fl)) | ||
785 | *error = -ESRCH; | ||
786 | } | ||
787 | } | ||
788 | |||
751 | struct xfrm_state * | 789 | struct xfrm_state * |
752 | xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | 790 | xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, |
753 | struct flowi *fl, struct xfrm_tmpl *tmpl, | 791 | struct flowi *fl, struct xfrm_tmpl *tmpl, |
754 | struct xfrm_policy *pol, int *err, | 792 | struct xfrm_policy *pol, int *err, |
755 | unsigned short family) | 793 | unsigned short family) |
756 | { | 794 | { |
795 | static xfrm_address_t saddr_wildcard = { }; | ||
757 | struct net *net = xp_net(pol); | 796 | struct net *net = xp_net(pol); |
758 | unsigned int h; | 797 | unsigned int h; |
759 | struct hlist_node *entry; | 798 | struct hlist_node *entry; |
@@ -773,40 +812,27 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
773 | xfrm_state_addr_check(x, daddr, saddr, family) && | 812 | xfrm_state_addr_check(x, daddr, saddr, family) && |
774 | tmpl->mode == x->props.mode && | 813 | tmpl->mode == x->props.mode && |
775 | tmpl->id.proto == x->id.proto && | 814 | tmpl->id.proto == x->id.proto && |
776 | (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) { | 815 | (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) |
777 | /* Resolution logic: | 816 | xfrm_state_look_at(pol, x, fl, family, daddr, saddr, |
778 | 1. There is a valid state with matching selector. | 817 | &best, &acquire_in_progress, &error); |
779 | Done. | 818 | } |
780 | 2. Valid state with inappropriate selector. Skip. | 819 | if (best) |
781 | 820 | goto found; | |
782 | Entering area of "sysdeps". | 821 | |
783 | 822 | h = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, family); | |
784 | 3. If state is not valid, selector is temporary, | 823 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { |
785 | it selects only session which triggered | 824 | if (x->props.family == family && |
786 | previous resolution. Key manager will do | 825 | x->props.reqid == tmpl->reqid && |
787 | something to install a state with proper | 826 | !(x->props.flags & XFRM_STATE_WILDRECV) && |
788 | selector. | 827 | xfrm_state_addr_check(x, daddr, saddr, family) && |
789 | */ | 828 | tmpl->mode == x->props.mode && |
790 | if (x->km.state == XFRM_STATE_VALID) { | 829 | tmpl->id.proto == x->id.proto && |
791 | if ((x->sel.family && !xfrm_selector_match(&x->sel, fl, x->sel.family)) || | 830 | (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) |
792 | !security_xfrm_state_pol_flow_match(x, pol, fl)) | 831 | xfrm_state_look_at(pol, x, fl, family, daddr, saddr, |
793 | continue; | 832 | &best, &acquire_in_progress, &error); |
794 | if (!best || | ||
795 | best->km.dying > x->km.dying || | ||
796 | (best->km.dying == x->km.dying && | ||
797 | best->curlft.add_time < x->curlft.add_time)) | ||
798 | best = x; | ||
799 | } else if (x->km.state == XFRM_STATE_ACQ) { | ||
800 | acquire_in_progress = 1; | ||
801 | } else if (x->km.state == XFRM_STATE_ERROR || | ||
802 | x->km.state == XFRM_STATE_EXPIRED) { | ||
803 | if (xfrm_selector_match(&x->sel, fl, x->sel.family) && | ||
804 | security_xfrm_state_pol_flow_match(x, pol, fl)) | ||
805 | error = -ESRCH; | ||
806 | } | ||
807 | } | ||
808 | } | 833 | } |
809 | 834 | ||
835 | found: | ||
810 | x = best; | 836 | x = best; |
811 | if (!x && !error && !acquire_in_progress) { | 837 | if (!x && !error && !acquire_in_progress) { |
812 | if (tmpl->id.spi && | 838 | if (tmpl->id.spi && |