diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/ah4.c | 3 | ||||
-rw-r--r-- | net/ipv4/esp4.c | 30 | ||||
-rw-r--r-- | net/ipv4/esp4_offload.c | 4 | ||||
-rw-r--r-- | net/ipv4/ipcomp.c | 3 | ||||
-rw-r--r-- | net/ipv4/xfrm4_state.c | 45 | ||||
-rw-r--r-- | net/ipv4/xfrm4_tunnel.c | 3 | ||||
-rw-r--r-- | net/ipv6/ah6.c | 4 | ||||
-rw-r--r-- | net/ipv6/esp6.c | 23 | ||||
-rw-r--r-- | net/ipv6/esp6_offload.c | 4 | ||||
-rw-r--r-- | net/ipv6/ipcomp6.c | 3 | ||||
-rw-r--r-- | net/ipv6/mip6.c | 6 | ||||
-rw-r--r-- | net/ipv6/xfrm6_state.c | 137 | ||||
-rw-r--r-- | net/xfrm/xfrm_device.c | 5 | ||||
-rw-r--r-- | net/xfrm/xfrm_input.c | 25 | ||||
-rw-r--r-- | net/xfrm/xfrm_interface.c | 6 | ||||
-rw-r--r-- | net/xfrm/xfrm_policy.c | 2 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 437 |
17 files changed, 358 insertions, 382 deletions
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 9c3afd550612..974179b3b314 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c | |||
@@ -590,8 +590,7 @@ static void __exit ah4_fini(void) | |||
590 | { | 590 | { |
591 | if (xfrm4_protocol_deregister(&ah4_protocol, IPPROTO_AH) < 0) | 591 | if (xfrm4_protocol_deregister(&ah4_protocol, IPPROTO_AH) < 0) |
592 | pr_info("%s: can't remove protocol\n", __func__); | 592 | pr_info("%s: can't remove protocol\n", __func__); |
593 | if (xfrm_unregister_type(&ah_type, AF_INET) < 0) | 593 | xfrm_unregister_type(&ah_type, AF_INET); |
594 | pr_info("%s: can't remove xfrm type\n", __func__); | ||
595 | } | 594 | } |
596 | 595 | ||
597 | module_init(ah4_init); | 596 | module_init(ah4_init); |
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index b9ae95576084..5c967764041f 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c | |||
@@ -33,8 +33,6 @@ struct esp_output_extra { | |||
33 | 33 | ||
34 | #define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0])) | 34 | #define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0])) |
35 | 35 | ||
36 | static u32 esp4_get_mtu(struct xfrm_state *x, int mtu); | ||
37 | |||
38 | /* | 36 | /* |
39 | * Allocate an AEAD request structure with extra space for SG and IV. | 37 | * Allocate an AEAD request structure with extra space for SG and IV. |
40 | * | 38 | * |
@@ -506,7 +504,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) | |||
506 | struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb); | 504 | struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb); |
507 | u32 padto; | 505 | u32 padto; |
508 | 506 | ||
509 | padto = min(x->tfcpad, esp4_get_mtu(x, dst->child_mtu_cached)); | 507 | padto = min(x->tfcpad, xfrm_state_mtu(x, dst->child_mtu_cached)); |
510 | if (skb->len < padto) | 508 | if (skb->len < padto) |
511 | esp.tfclen = padto - skb->len; | 509 | esp.tfclen = padto - skb->len; |
512 | } | 510 | } |
@@ -788,28 +786,6 @@ out: | |||
788 | return err; | 786 | return err; |
789 | } | 787 | } |
790 | 788 | ||
791 | static u32 esp4_get_mtu(struct xfrm_state *x, int mtu) | ||
792 | { | ||
793 | struct crypto_aead *aead = x->data; | ||
794 | u32 blksize = ALIGN(crypto_aead_blocksize(aead), 4); | ||
795 | unsigned int net_adj; | ||
796 | |||
797 | switch (x->props.mode) { | ||
798 | case XFRM_MODE_TRANSPORT: | ||
799 | case XFRM_MODE_BEET: | ||
800 | net_adj = sizeof(struct iphdr); | ||
801 | break; | ||
802 | case XFRM_MODE_TUNNEL: | ||
803 | net_adj = 0; | ||
804 | break; | ||
805 | default: | ||
806 | BUG(); | ||
807 | } | ||
808 | |||
809 | return ((mtu - x->props.header_len - crypto_aead_authsize(aead) - | ||
810 | net_adj) & ~(blksize - 1)) + net_adj - 2; | ||
811 | } | ||
812 | |||
813 | static int esp4_err(struct sk_buff *skb, u32 info) | 789 | static int esp4_err(struct sk_buff *skb, u32 info) |
814 | { | 790 | { |
815 | struct net *net = dev_net(skb->dev); | 791 | struct net *net = dev_net(skb->dev); |
@@ -1035,7 +1011,6 @@ static const struct xfrm_type esp_type = | |||
1035 | .flags = XFRM_TYPE_REPLAY_PROT, | 1011 | .flags = XFRM_TYPE_REPLAY_PROT, |
1036 | .init_state = esp_init_state, | 1012 | .init_state = esp_init_state, |
1037 | .destructor = esp_destroy, | 1013 | .destructor = esp_destroy, |
1038 | .get_mtu = esp4_get_mtu, | ||
1039 | .input = esp_input, | 1014 | .input = esp_input, |
1040 | .output = esp_output, | 1015 | .output = esp_output, |
1041 | }; | 1016 | }; |
@@ -1066,8 +1041,7 @@ static void __exit esp4_fini(void) | |||
1066 | { | 1041 | { |
1067 | if (xfrm4_protocol_deregister(&esp4_protocol, IPPROTO_ESP) < 0) | 1042 | if (xfrm4_protocol_deregister(&esp4_protocol, IPPROTO_ESP) < 0) |
1068 | pr_info("%s: can't remove protocol\n", __func__); | 1043 | pr_info("%s: can't remove protocol\n", __func__); |
1069 | if (xfrm_unregister_type(&esp_type, AF_INET) < 0) | 1044 | xfrm_unregister_type(&esp_type, AF_INET); |
1070 | pr_info("%s: can't remove xfrm type\n", __func__); | ||
1071 | } | 1045 | } |
1072 | 1046 | ||
1073 | module_init(esp4_init); | 1047 | module_init(esp4_init); |
diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c index 2e5e377f50a1..0e4a7cf6bc87 100644 --- a/net/ipv4/esp4_offload.c +++ b/net/ipv4/esp4_offload.c | |||
@@ -312,9 +312,7 @@ static int __init esp4_offload_init(void) | |||
312 | 312 | ||
313 | static void __exit esp4_offload_exit(void) | 313 | static void __exit esp4_offload_exit(void) |
314 | { | 314 | { |
315 | if (xfrm_unregister_type_offload(&esp_type_offload, AF_INET) < 0) | 315 | xfrm_unregister_type_offload(&esp_type_offload, AF_INET); |
316 | pr_info("%s: can't remove xfrm type offload\n", __func__); | ||
317 | |||
318 | inet_del_offload(&esp4_offload, IPPROTO_ESP); | 316 | inet_del_offload(&esp4_offload, IPPROTO_ESP); |
319 | } | 317 | } |
320 | 318 | ||
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 2f4cdcc13d53..59bfa3825810 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c | |||
@@ -186,8 +186,7 @@ static void __exit ipcomp4_fini(void) | |||
186 | { | 186 | { |
187 | if (xfrm4_protocol_deregister(&ipcomp4_protocol, IPPROTO_COMP) < 0) | 187 | if (xfrm4_protocol_deregister(&ipcomp4_protocol, IPPROTO_COMP) < 0) |
188 | pr_info("%s: can't remove protocol\n", __func__); | 188 | pr_info("%s: can't remove protocol\n", __func__); |
189 | if (xfrm_unregister_type(&ipcomp_type, AF_INET) < 0) | 189 | xfrm_unregister_type(&ipcomp_type, AF_INET); |
190 | pr_info("%s: can't remove xfrm type\n", __func__); | ||
191 | } | 190 | } |
192 | 191 | ||
193 | module_init(ipcomp4_init); | 192 | module_init(ipcomp4_init); |
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index 80c40b4981bb..f8ed3c3bb928 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c | |||
@@ -15,46 +15,6 @@ | |||
15 | #include <linux/netfilter_ipv4.h> | 15 | #include <linux/netfilter_ipv4.h> |
16 | #include <linux/export.h> | 16 | #include <linux/export.h> |
17 | 17 | ||
18 | static int xfrm4_init_flags(struct xfrm_state *x) | ||
19 | { | ||
20 | if (xs_net(x)->ipv4.sysctl_ip_no_pmtu_disc) | ||
21 | x->props.flags |= XFRM_STATE_NOPMTUDISC; | ||
22 | return 0; | ||
23 | } | ||
24 | |||
25 | static void | ||
26 | __xfrm4_init_tempsel(struct xfrm_selector *sel, const struct flowi *fl) | ||
27 | { | ||
28 | const struct flowi4 *fl4 = &fl->u.ip4; | ||
29 | |||
30 | sel->daddr.a4 = fl4->daddr; | ||
31 | sel->saddr.a4 = fl4->saddr; | ||
32 | sel->dport = xfrm_flowi_dport(fl, &fl4->uli); | ||
33 | sel->dport_mask = htons(0xffff); | ||
34 | sel->sport = xfrm_flowi_sport(fl, &fl4->uli); | ||
35 | sel->sport_mask = htons(0xffff); | ||
36 | sel->family = AF_INET; | ||
37 | sel->prefixlen_d = 32; | ||
38 | sel->prefixlen_s = 32; | ||
39 | sel->proto = fl4->flowi4_proto; | ||
40 | sel->ifindex = fl4->flowi4_oif; | ||
41 | } | ||
42 | |||
43 | static void | ||
44 | xfrm4_init_temprop(struct xfrm_state *x, const struct xfrm_tmpl *tmpl, | ||
45 | const xfrm_address_t *daddr, const xfrm_address_t *saddr) | ||
46 | { | ||
47 | x->id = tmpl->id; | ||
48 | if (x->id.daddr.a4 == 0) | ||
49 | x->id.daddr.a4 = daddr->a4; | ||
50 | x->props.saddr = tmpl->saddr; | ||
51 | if (x->props.saddr.a4 == 0) | ||
52 | x->props.saddr.a4 = saddr->a4; | ||
53 | x->props.mode = tmpl->mode; | ||
54 | x->props.reqid = tmpl->reqid; | ||
55 | x->props.family = AF_INET; | ||
56 | } | ||
57 | |||
58 | int xfrm4_extract_header(struct sk_buff *skb) | 18 | int xfrm4_extract_header(struct sk_buff *skb) |
59 | { | 19 | { |
60 | const struct iphdr *iph = ip_hdr(skb); | 20 | const struct iphdr *iph = ip_hdr(skb); |
@@ -74,11 +34,6 @@ int xfrm4_extract_header(struct sk_buff *skb) | |||
74 | static struct xfrm_state_afinfo xfrm4_state_afinfo = { | 34 | static struct xfrm_state_afinfo xfrm4_state_afinfo = { |
75 | .family = AF_INET, | 35 | .family = AF_INET, |
76 | .proto = IPPROTO_IPIP, | 36 | .proto = IPPROTO_IPIP, |
77 | .eth_proto = htons(ETH_P_IP), | ||
78 | .owner = THIS_MODULE, | ||
79 | .init_flags = xfrm4_init_flags, | ||
80 | .init_tempsel = __xfrm4_init_tempsel, | ||
81 | .init_temprop = xfrm4_init_temprop, | ||
82 | .output = xfrm4_output, | 37 | .output = xfrm4_output, |
83 | .output_finish = xfrm4_output_finish, | 38 | .output_finish = xfrm4_output_finish, |
84 | .extract_input = xfrm4_extract_input, | 39 | .extract_input = xfrm4_extract_input, |
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c index 5d00e54cd319..dc19aff7c2e0 100644 --- a/net/ipv4/xfrm4_tunnel.c +++ b/net/ipv4/xfrm4_tunnel.c | |||
@@ -108,8 +108,7 @@ static void __exit ipip_fini(void) | |||
108 | if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET)) | 108 | if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET)) |
109 | pr_info("%s: can't remove xfrm handler for AF_INET\n", | 109 | pr_info("%s: can't remove xfrm handler for AF_INET\n", |
110 | __func__); | 110 | __func__); |
111 | if (xfrm_unregister_type(&ipip_type, AF_INET) < 0) | 111 | xfrm_unregister_type(&ipip_type, AF_INET); |
112 | pr_info("%s: can't remove xfrm type\n", __func__); | ||
113 | } | 112 | } |
114 | 113 | ||
115 | module_init(ipip_init); | 114 | module_init(ipip_init); |
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 68b9e92e469e..25e1172fd1c3 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
@@ -793,9 +793,7 @@ static void __exit ah6_fini(void) | |||
793 | if (xfrm6_protocol_deregister(&ah6_protocol, IPPROTO_AH) < 0) | 793 | if (xfrm6_protocol_deregister(&ah6_protocol, IPPROTO_AH) < 0) |
794 | pr_info("%s: can't remove protocol\n", __func__); | 794 | pr_info("%s: can't remove protocol\n", __func__); |
795 | 795 | ||
796 | if (xfrm_unregister_type(&ah6_type, AF_INET6) < 0) | 796 | xfrm_unregister_type(&ah6_type, AF_INET6); |
797 | pr_info("%s: can't remove xfrm type\n", __func__); | ||
798 | |||
799 | } | 797 | } |
800 | 798 | ||
801 | module_init(ah6_init); | 799 | module_init(ah6_init); |
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index ae6a739c5f52..a3b403ba8f8f 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -41,8 +41,6 @@ struct esp_skb_cb { | |||
41 | 41 | ||
42 | #define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0])) | 42 | #define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0])) |
43 | 43 | ||
44 | static u32 esp6_get_mtu(struct xfrm_state *x, int mtu); | ||
45 | |||
46 | /* | 44 | /* |
47 | * Allocate an AEAD request structure with extra space for SG and IV. | 45 | * Allocate an AEAD request structure with extra space for SG and IV. |
48 | * | 46 | * |
@@ -447,7 +445,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
447 | struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb); | 445 | struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb); |
448 | u32 padto; | 446 | u32 padto; |
449 | 447 | ||
450 | padto = min(x->tfcpad, esp6_get_mtu(x, dst->child_mtu_cached)); | 448 | padto = min(x->tfcpad, xfrm_state_mtu(x, dst->child_mtu_cached)); |
451 | if (skb->len < padto) | 449 | if (skb->len < padto) |
452 | esp.tfclen = padto - skb->len; | 450 | esp.tfclen = padto - skb->len; |
453 | } | 451 | } |
@@ -687,21 +685,6 @@ out: | |||
687 | return ret; | 685 | return ret; |
688 | } | 686 | } |
689 | 687 | ||
690 | static u32 esp6_get_mtu(struct xfrm_state *x, int mtu) | ||
691 | { | ||
692 | struct crypto_aead *aead = x->data; | ||
693 | u32 blksize = ALIGN(crypto_aead_blocksize(aead), 4); | ||
694 | unsigned int net_adj; | ||
695 | |||
696 | if (x->props.mode != XFRM_MODE_TUNNEL) | ||
697 | net_adj = sizeof(struct ipv6hdr); | ||
698 | else | ||
699 | net_adj = 0; | ||
700 | |||
701 | return ((mtu - x->props.header_len - crypto_aead_authsize(aead) - | ||
702 | net_adj) & ~(blksize - 1)) + net_adj - 2; | ||
703 | } | ||
704 | |||
705 | static int esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 688 | static int esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
706 | u8 type, u8 code, int offset, __be32 info) | 689 | u8 type, u8 code, int offset, __be32 info) |
707 | { | 690 | { |
@@ -919,7 +902,6 @@ static const struct xfrm_type esp6_type = { | |||
919 | .flags = XFRM_TYPE_REPLAY_PROT, | 902 | .flags = XFRM_TYPE_REPLAY_PROT, |
920 | .init_state = esp6_init_state, | 903 | .init_state = esp6_init_state, |
921 | .destructor = esp6_destroy, | 904 | .destructor = esp6_destroy, |
922 | .get_mtu = esp6_get_mtu, | ||
923 | .input = esp6_input, | 905 | .input = esp6_input, |
924 | .output = esp6_output, | 906 | .output = esp6_output, |
925 | .hdr_offset = xfrm6_find_1stfragopt, | 907 | .hdr_offset = xfrm6_find_1stfragopt, |
@@ -951,8 +933,7 @@ static void __exit esp6_fini(void) | |||
951 | { | 933 | { |
952 | if (xfrm6_protocol_deregister(&esp6_protocol, IPPROTO_ESP) < 0) | 934 | if (xfrm6_protocol_deregister(&esp6_protocol, IPPROTO_ESP) < 0) |
953 | pr_info("%s: can't remove protocol\n", __func__); | 935 | pr_info("%s: can't remove protocol\n", __func__); |
954 | if (xfrm_unregister_type(&esp6_type, AF_INET6) < 0) | 936 | xfrm_unregister_type(&esp6_type, AF_INET6); |
955 | pr_info("%s: can't remove xfrm type\n", __func__); | ||
956 | } | 937 | } |
957 | 938 | ||
958 | module_init(esp6_init); | 939 | module_init(esp6_init); |
diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c index d0d8528b294a..e31626ffccd1 100644 --- a/net/ipv6/esp6_offload.c +++ b/net/ipv6/esp6_offload.c | |||
@@ -336,9 +336,7 @@ static int __init esp6_offload_init(void) | |||
336 | 336 | ||
337 | static void __exit esp6_offload_exit(void) | 337 | static void __exit esp6_offload_exit(void) |
338 | { | 338 | { |
339 | if (xfrm_unregister_type_offload(&esp6_type_offload, AF_INET6) < 0) | 339 | xfrm_unregister_type_offload(&esp6_type_offload, AF_INET6); |
340 | pr_info("%s: can't remove xfrm type offload\n", __func__); | ||
341 | |||
342 | inet6_del_offload(&esp6_offload, IPPROTO_ESP); | 340 | inet6_del_offload(&esp6_offload, IPPROTO_ESP); |
343 | } | 341 | } |
344 | 342 | ||
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 51fd33294c7c..3752bd3e92ce 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c | |||
@@ -206,8 +206,7 @@ static void __exit ipcomp6_fini(void) | |||
206 | { | 206 | { |
207 | if (xfrm6_protocol_deregister(&ipcomp6_protocol, IPPROTO_COMP) < 0) | 207 | if (xfrm6_protocol_deregister(&ipcomp6_protocol, IPPROTO_COMP) < 0) |
208 | pr_info("%s: can't remove protocol\n", __func__); | 208 | pr_info("%s: can't remove protocol\n", __func__); |
209 | if (xfrm_unregister_type(&ipcomp6_type, AF_INET6) < 0) | 209 | xfrm_unregister_type(&ipcomp6_type, AF_INET6); |
210 | pr_info("%s: can't remove xfrm type\n", __func__); | ||
211 | } | 210 | } |
212 | 211 | ||
213 | module_init(ipcomp6_init); | 212 | module_init(ipcomp6_init); |
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 91801432878c..878fcec14949 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c | |||
@@ -499,10 +499,8 @@ static void __exit mip6_fini(void) | |||
499 | { | 499 | { |
500 | if (rawv6_mh_filter_unregister(mip6_mh_filter) < 0) | 500 | if (rawv6_mh_filter_unregister(mip6_mh_filter) < 0) |
501 | pr_info("%s: can't remove rawv6 mh filter\n", __func__); | 501 | pr_info("%s: can't remove rawv6 mh filter\n", __func__); |
502 | if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0) | 502 | xfrm_unregister_type(&mip6_rthdr_type, AF_INET6); |
503 | pr_info("%s: can't remove xfrm type(rthdr)\n", __func__); | 503 | xfrm_unregister_type(&mip6_destopt_type, AF_INET6); |
504 | if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0) | ||
505 | pr_info("%s: can't remove xfrm type(destopt)\n", __func__); | ||
506 | } | 504 | } |
507 | 505 | ||
508 | module_init(mip6_init); | 506 | module_init(mip6_init); |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index 5bdca3d5d6b7..78daadecbdef 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -21,137 +21,6 @@ | |||
21 | #include <net/ipv6.h> | 21 | #include <net/ipv6.h> |
22 | #include <net/addrconf.h> | 22 | #include <net/addrconf.h> |
23 | 23 | ||
24 | static void | ||
25 | __xfrm6_init_tempsel(struct xfrm_selector *sel, const struct flowi *fl) | ||
26 | { | ||
27 | const struct flowi6 *fl6 = &fl->u.ip6; | ||
28 | |||
29 | /* Initialize temporary selector matching only | ||
30 | * to current session. */ | ||
31 | *(struct in6_addr *)&sel->daddr = fl6->daddr; | ||
32 | *(struct in6_addr *)&sel->saddr = fl6->saddr; | ||
33 | sel->dport = xfrm_flowi_dport(fl, &fl6->uli); | ||
34 | sel->dport_mask = htons(0xffff); | ||
35 | sel->sport = xfrm_flowi_sport(fl, &fl6->uli); | ||
36 | sel->sport_mask = htons(0xffff); | ||
37 | sel->family = AF_INET6; | ||
38 | sel->prefixlen_d = 128; | ||
39 | sel->prefixlen_s = 128; | ||
40 | sel->proto = fl6->flowi6_proto; | ||
41 | sel->ifindex = fl6->flowi6_oif; | ||
42 | } | ||
43 | |||
44 | static void | ||
45 | xfrm6_init_temprop(struct xfrm_state *x, const struct xfrm_tmpl *tmpl, | ||
46 | const xfrm_address_t *daddr, const xfrm_address_t *saddr) | ||
47 | { | ||
48 | x->id = tmpl->id; | ||
49 | if (ipv6_addr_any((struct in6_addr *)&x->id.daddr)) | ||
50 | memcpy(&x->id.daddr, daddr, sizeof(x->sel.daddr)); | ||
51 | memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr)); | ||
52 | if (ipv6_addr_any((struct in6_addr *)&x->props.saddr)) | ||
53 | memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr)); | ||
54 | x->props.mode = tmpl->mode; | ||
55 | x->props.reqid = tmpl->reqid; | ||
56 | x->props.family = AF_INET6; | ||
57 | } | ||
58 | |||
59 | /* distribution counting sort function for xfrm_state and xfrm_tmpl */ | ||
60 | static int | ||
61 | __xfrm6_sort(void **dst, void **src, int n, int (*cmp)(void *p), int maxclass) | ||
62 | { | ||
63 | int count[XFRM_MAX_DEPTH] = { }; | ||
64 | int class[XFRM_MAX_DEPTH]; | ||
65 | int i; | ||
66 | |||
67 | for (i = 0; i < n; i++) { | ||
68 | int c; | ||
69 | class[i] = c = cmp(src[i]); | ||
70 | count[c]++; | ||
71 | } | ||
72 | |||
73 | for (i = 2; i < maxclass; i++) | ||
74 | count[i] += count[i - 1]; | ||
75 | |||
76 | for (i = 0; i < n; i++) { | ||
77 | dst[count[class[i] - 1]++] = src[i]; | ||
78 | src[i] = NULL; | ||
79 | } | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | /* | ||
85 | * Rule for xfrm_state: | ||
86 | * | ||
87 | * rule 1: select IPsec transport except AH | ||
88 | * rule 2: select MIPv6 RO or inbound trigger | ||
89 | * rule 3: select IPsec transport AH | ||
90 | * rule 4: select IPsec tunnel | ||
91 | * rule 5: others | ||
92 | */ | ||
93 | static int __xfrm6_state_sort_cmp(void *p) | ||
94 | { | ||
95 | struct xfrm_state *v = p; | ||
96 | |||
97 | switch (v->props.mode) { | ||
98 | case XFRM_MODE_TRANSPORT: | ||
99 | if (v->id.proto != IPPROTO_AH) | ||
100 | return 1; | ||
101 | else | ||
102 | return 3; | ||
103 | #if IS_ENABLED(CONFIG_IPV6_MIP6) | ||
104 | case XFRM_MODE_ROUTEOPTIMIZATION: | ||
105 | case XFRM_MODE_IN_TRIGGER: | ||
106 | return 2; | ||
107 | #endif | ||
108 | case XFRM_MODE_TUNNEL: | ||
109 | case XFRM_MODE_BEET: | ||
110 | return 4; | ||
111 | } | ||
112 | return 5; | ||
113 | } | ||
114 | |||
115 | static int | ||
116 | __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) | ||
117 | { | ||
118 | return __xfrm6_sort((void **)dst, (void **)src, n, | ||
119 | __xfrm6_state_sort_cmp, 6); | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | * Rule for xfrm_tmpl: | ||
124 | * | ||
125 | * rule 1: select IPsec transport | ||
126 | * rule 2: select MIPv6 RO or inbound trigger | ||
127 | * rule 3: select IPsec tunnel | ||
128 | * rule 4: others | ||
129 | */ | ||
130 | static int __xfrm6_tmpl_sort_cmp(void *p) | ||
131 | { | ||
132 | struct xfrm_tmpl *v = p; | ||
133 | switch (v->mode) { | ||
134 | case XFRM_MODE_TRANSPORT: | ||
135 | return 1; | ||
136 | #if IS_ENABLED(CONFIG_IPV6_MIP6) | ||
137 | case XFRM_MODE_ROUTEOPTIMIZATION: | ||
138 | case XFRM_MODE_IN_TRIGGER: | ||
139 | return 2; | ||
140 | #endif | ||
141 | case XFRM_MODE_TUNNEL: | ||
142 | case XFRM_MODE_BEET: | ||
143 | return 3; | ||
144 | } | ||
145 | return 4; | ||
146 | } | ||
147 | |||
148 | static int | ||
149 | __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n) | ||
150 | { | ||
151 | return __xfrm6_sort((void **)dst, (void **)src, n, | ||
152 | __xfrm6_tmpl_sort_cmp, 5); | ||
153 | } | ||
154 | |||
155 | int xfrm6_extract_header(struct sk_buff *skb) | 24 | int xfrm6_extract_header(struct sk_buff *skb) |
156 | { | 25 | { |
157 | struct ipv6hdr *iph = ipv6_hdr(skb); | 26 | struct ipv6hdr *iph = ipv6_hdr(skb); |
@@ -171,12 +40,6 @@ int xfrm6_extract_header(struct sk_buff *skb) | |||
171 | static struct xfrm_state_afinfo xfrm6_state_afinfo = { | 40 | static struct xfrm_state_afinfo xfrm6_state_afinfo = { |
172 | .family = AF_INET6, | 41 | .family = AF_INET6, |
173 | .proto = IPPROTO_IPV6, | 42 | .proto = IPPROTO_IPV6, |
174 | .eth_proto = htons(ETH_P_IPV6), | ||
175 | .owner = THIS_MODULE, | ||
176 | .init_tempsel = __xfrm6_init_tempsel, | ||
177 | .init_temprop = xfrm6_init_temprop, | ||
178 | .tmpl_sort = __xfrm6_tmpl_sort, | ||
179 | .state_sort = __xfrm6_state_sort, | ||
180 | .output = xfrm6_output, | 43 | .output = xfrm6_output, |
181 | .output_finish = xfrm6_output_finish, | 44 | .output_finish = xfrm6_output_finish, |
182 | .extract_input = xfrm6_extract_input, | 45 | .extract_input = xfrm6_extract_input, |
diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c index ff654306d836..189ef15acbbc 100644 --- a/net/xfrm/xfrm_device.c +++ b/net/xfrm/xfrm_device.c | |||
@@ -271,9 +271,8 @@ bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x) | |||
271 | return false; | 271 | return false; |
272 | 272 | ||
273 | if ((!dev || (dev == xfrm_dst_path(dst)->dev)) && | 273 | if ((!dev || (dev == xfrm_dst_path(dst)->dev)) && |
274 | (!xdst->child->xfrm && x->type->get_mtu)) { | 274 | (!xdst->child->xfrm)) { |
275 | mtu = x->type->get_mtu(x, xdst->child_mtu_cached); | 275 | mtu = xfrm_state_mtu(x, xdst->child_mtu_cached); |
276 | |||
277 | if (skb->len <= mtu) | 276 | if (skb->len <= mtu) |
278 | goto ok; | 277 | goto ok; |
279 | 278 | ||
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 314973aaa414..6088bc2dc11e 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c | |||
@@ -359,28 +359,29 @@ static int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb) | |||
359 | afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode.family); | 359 | afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode.family); |
360 | if (likely(afinfo)) | 360 | if (likely(afinfo)) |
361 | err = afinfo->extract_input(x, skb); | 361 | err = afinfo->extract_input(x, skb); |
362 | rcu_read_unlock(); | ||
362 | 363 | ||
363 | if (err) { | 364 | if (err) |
364 | rcu_read_unlock(); | ||
365 | return err; | 365 | return err; |
366 | } | ||
367 | 366 | ||
368 | if (x->sel.family == AF_UNSPEC) { | 367 | if (x->sel.family == AF_UNSPEC) { |
369 | inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); | 368 | inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); |
370 | if (!inner_mode) { | 369 | if (!inner_mode) |
371 | rcu_read_unlock(); | ||
372 | return -EAFNOSUPPORT; | 370 | return -EAFNOSUPPORT; |
373 | } | ||
374 | } | 371 | } |
375 | 372 | ||
376 | afinfo = xfrm_state_afinfo_get_rcu(inner_mode->family); | 373 | switch (inner_mode->family) { |
377 | if (unlikely(!afinfo)) { | 374 | case AF_INET: |
378 | rcu_read_unlock(); | 375 | skb->protocol = htons(ETH_P_IP); |
379 | return -EAFNOSUPPORT; | 376 | break; |
377 | case AF_INET6: | ||
378 | skb->protocol = htons(ETH_P_IPV6); | ||
379 | break; | ||
380 | default: | ||
381 | WARN_ON_ONCE(1); | ||
382 | break; | ||
380 | } | 383 | } |
381 | 384 | ||
382 | skb->protocol = afinfo->eth_proto; | ||
383 | rcu_read_unlock(); | ||
384 | return xfrm_inner_mode_encap_remove(x, inner_mode, skb); | 385 | return xfrm_inner_mode_encap_remove(x, inner_mode, skb); |
385 | } | 386 | } |
386 | 387 | ||
diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c index ad3a2555c517..f8eb9e342173 100644 --- a/net/xfrm/xfrm_interface.c +++ b/net/xfrm/xfrm_interface.c | |||
@@ -793,11 +793,6 @@ static void __net_exit xfrmi_destroy_interfaces(struct xfrmi_net *xfrmn) | |||
793 | unregister_netdevice_many(&list); | 793 | unregister_netdevice_many(&list); |
794 | } | 794 | } |
795 | 795 | ||
796 | static int __net_init xfrmi_init_net(struct net *net) | ||
797 | { | ||
798 | return 0; | ||
799 | } | ||
800 | |||
801 | static void __net_exit xfrmi_exit_net(struct net *net) | 796 | static void __net_exit xfrmi_exit_net(struct net *net) |
802 | { | 797 | { |
803 | struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id); | 798 | struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id); |
@@ -808,7 +803,6 @@ static void __net_exit xfrmi_exit_net(struct net *net) | |||
808 | } | 803 | } |
809 | 804 | ||
810 | static struct pernet_operations xfrmi_net_ops = { | 805 | static struct pernet_operations xfrmi_net_ops = { |
811 | .init = xfrmi_init_net, | ||
812 | .exit = xfrmi_exit_net, | 806 | .exit = xfrmi_exit_net, |
813 | .id = &xfrmi_net_id, | 807 | .id = &xfrmi_net_id, |
814 | .size = sizeof(struct xfrmi_net), | 808 | .size = sizeof(struct xfrmi_net), |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index b1694d5d15d3..1070dfece76b 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -3628,7 +3628,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
3628 | } | 3628 | } |
3629 | xfrm_nr = ti; | 3629 | xfrm_nr = ti; |
3630 | if (npols > 1) { | 3630 | if (npols > 1) { |
3631 | xfrm_tmpl_sort(stp, tpp, xfrm_nr, family, net); | 3631 | xfrm_tmpl_sort(stp, tpp, xfrm_nr, family); |
3632 | tpp = stp; | 3632 | tpp = stp; |
3633 | } | 3633 | } |
3634 | 3634 | ||
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 50621d982970..c6f3c4a1bd99 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
29 | 29 | ||
30 | #include <crypto/aead.h> | ||
31 | |||
30 | #include "xfrm_hash.h" | 32 | #include "xfrm_hash.h" |
31 | 33 | ||
32 | #define xfrm_state_deref_prot(table, net) \ | 34 | #define xfrm_state_deref_prot(table, net) \ |
@@ -177,63 +179,132 @@ int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol) | |||
177 | static bool km_is_alive(const struct km_event *c); | 179 | static bool km_is_alive(const struct km_event *c); |
178 | void km_state_expired(struct xfrm_state *x, int hard, u32 portid); | 180 | void km_state_expired(struct xfrm_state *x, int hard, u32 portid); |
179 | 181 | ||
180 | static DEFINE_SPINLOCK(xfrm_type_lock); | ||
181 | int xfrm_register_type(const struct xfrm_type *type, unsigned short family) | 182 | int xfrm_register_type(const struct xfrm_type *type, unsigned short family) |
182 | { | 183 | { |
183 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); | 184 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); |
184 | const struct xfrm_type **typemap; | ||
185 | int err = 0; | 185 | int err = 0; |
186 | 186 | ||
187 | if (unlikely(afinfo == NULL)) | 187 | if (!afinfo) |
188 | return -EAFNOSUPPORT; | 188 | return -EAFNOSUPPORT; |
189 | typemap = afinfo->type_map; | ||
190 | spin_lock_bh(&xfrm_type_lock); | ||
191 | 189 | ||
192 | if (likely(typemap[type->proto] == NULL)) | 190 | #define X(afi, T, name) do { \ |
193 | typemap[type->proto] = type; | 191 | WARN_ON((afi)->type_ ## name); \ |
194 | else | 192 | (afi)->type_ ## name = (T); \ |
195 | err = -EEXIST; | 193 | } while (0) |
196 | spin_unlock_bh(&xfrm_type_lock); | 194 | |
195 | switch (type->proto) { | ||
196 | case IPPROTO_COMP: | ||
197 | X(afinfo, type, comp); | ||
198 | break; | ||
199 | case IPPROTO_AH: | ||
200 | X(afinfo, type, ah); | ||
201 | break; | ||
202 | case IPPROTO_ESP: | ||
203 | X(afinfo, type, esp); | ||
204 | break; | ||
205 | case IPPROTO_IPIP: | ||
206 | X(afinfo, type, ipip); | ||
207 | break; | ||
208 | case IPPROTO_DSTOPTS: | ||
209 | X(afinfo, type, dstopts); | ||
210 | break; | ||
211 | case IPPROTO_ROUTING: | ||
212 | X(afinfo, type, routing); | ||
213 | break; | ||
214 | case IPPROTO_IPV6: | ||
215 | X(afinfo, type, ipip6); | ||
216 | break; | ||
217 | default: | ||
218 | WARN_ON(1); | ||
219 | err = -EPROTONOSUPPORT; | ||
220 | break; | ||
221 | } | ||
222 | #undef X | ||
197 | rcu_read_unlock(); | 223 | rcu_read_unlock(); |
198 | return err; | 224 | return err; |
199 | } | 225 | } |
200 | EXPORT_SYMBOL(xfrm_register_type); | 226 | EXPORT_SYMBOL(xfrm_register_type); |
201 | 227 | ||
202 | int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family) | 228 | void xfrm_unregister_type(const struct xfrm_type *type, unsigned short family) |
203 | { | 229 | { |
204 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); | 230 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); |
205 | const struct xfrm_type **typemap; | ||
206 | int err = 0; | ||
207 | 231 | ||
208 | if (unlikely(afinfo == NULL)) | 232 | if (unlikely(afinfo == NULL)) |
209 | return -EAFNOSUPPORT; | 233 | return; |
210 | typemap = afinfo->type_map; | ||
211 | spin_lock_bh(&xfrm_type_lock); | ||
212 | 234 | ||
213 | if (unlikely(typemap[type->proto] != type)) | 235 | #define X(afi, T, name) do { \ |
214 | err = -ENOENT; | 236 | WARN_ON((afi)->type_ ## name != (T)); \ |
215 | else | 237 | (afi)->type_ ## name = NULL; \ |
216 | typemap[type->proto] = NULL; | 238 | } while (0) |
217 | spin_unlock_bh(&xfrm_type_lock); | 239 | |
240 | switch (type->proto) { | ||
241 | case IPPROTO_COMP: | ||
242 | X(afinfo, type, comp); | ||
243 | break; | ||
244 | case IPPROTO_AH: | ||
245 | X(afinfo, type, ah); | ||
246 | break; | ||
247 | case IPPROTO_ESP: | ||
248 | X(afinfo, type, esp); | ||
249 | break; | ||
250 | case IPPROTO_IPIP: | ||
251 | X(afinfo, type, ipip); | ||
252 | break; | ||
253 | case IPPROTO_DSTOPTS: | ||
254 | X(afinfo, type, dstopts); | ||
255 | break; | ||
256 | case IPPROTO_ROUTING: | ||
257 | X(afinfo, type, routing); | ||
258 | break; | ||
259 | case IPPROTO_IPV6: | ||
260 | X(afinfo, type, ipip6); | ||
261 | break; | ||
262 | default: | ||
263 | WARN_ON(1); | ||
264 | break; | ||
265 | } | ||
266 | #undef X | ||
218 | rcu_read_unlock(); | 267 | rcu_read_unlock(); |
219 | return err; | ||
220 | } | 268 | } |
221 | EXPORT_SYMBOL(xfrm_unregister_type); | 269 | EXPORT_SYMBOL(xfrm_unregister_type); |
222 | 270 | ||
223 | static const struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family) | 271 | static const struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family) |
224 | { | 272 | { |
273 | const struct xfrm_type *type = NULL; | ||
225 | struct xfrm_state_afinfo *afinfo; | 274 | struct xfrm_state_afinfo *afinfo; |
226 | const struct xfrm_type **typemap; | ||
227 | const struct xfrm_type *type; | ||
228 | int modload_attempted = 0; | 275 | int modload_attempted = 0; |
229 | 276 | ||
230 | retry: | 277 | retry: |
231 | afinfo = xfrm_state_get_afinfo(family); | 278 | afinfo = xfrm_state_get_afinfo(family); |
232 | if (unlikely(afinfo == NULL)) | 279 | if (unlikely(afinfo == NULL)) |
233 | return NULL; | 280 | return NULL; |
234 | typemap = afinfo->type_map; | ||
235 | 281 | ||
236 | type = READ_ONCE(typemap[proto]); | 282 | switch (proto) { |
283 | case IPPROTO_COMP: | ||
284 | type = afinfo->type_comp; | ||
285 | break; | ||
286 | case IPPROTO_AH: | ||
287 | type = afinfo->type_ah; | ||
288 | break; | ||
289 | case IPPROTO_ESP: | ||
290 | type = afinfo->type_esp; | ||
291 | break; | ||
292 | case IPPROTO_IPIP: | ||
293 | type = afinfo->type_ipip; | ||
294 | break; | ||
295 | case IPPROTO_DSTOPTS: | ||
296 | type = afinfo->type_dstopts; | ||
297 | break; | ||
298 | case IPPROTO_ROUTING: | ||
299 | type = afinfo->type_routing; | ||
300 | break; | ||
301 | case IPPROTO_IPV6: | ||
302 | type = afinfo->type_ipip6; | ||
303 | break; | ||
304 | default: | ||
305 | break; | ||
306 | } | ||
307 | |||
237 | if (unlikely(type && !try_module_get(type->owner))) | 308 | if (unlikely(type && !try_module_get(type->owner))) |
238 | type = NULL; | 309 | type = NULL; |
239 | 310 | ||
@@ -253,65 +324,71 @@ static void xfrm_put_type(const struct xfrm_type *type) | |||
253 | module_put(type->owner); | 324 | module_put(type->owner); |
254 | } | 325 | } |
255 | 326 | ||
256 | static DEFINE_SPINLOCK(xfrm_type_offload_lock); | ||
257 | int xfrm_register_type_offload(const struct xfrm_type_offload *type, | 327 | int xfrm_register_type_offload(const struct xfrm_type_offload *type, |
258 | unsigned short family) | 328 | unsigned short family) |
259 | { | 329 | { |
260 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); | 330 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); |
261 | const struct xfrm_type_offload **typemap; | ||
262 | int err = 0; | 331 | int err = 0; |
263 | 332 | ||
264 | if (unlikely(afinfo == NULL)) | 333 | if (unlikely(afinfo == NULL)) |
265 | return -EAFNOSUPPORT; | 334 | return -EAFNOSUPPORT; |
266 | typemap = afinfo->type_offload_map; | ||
267 | spin_lock_bh(&xfrm_type_offload_lock); | ||
268 | 335 | ||
269 | if (likely(typemap[type->proto] == NULL)) | 336 | switch (type->proto) { |
270 | typemap[type->proto] = type; | 337 | case IPPROTO_ESP: |
271 | else | 338 | WARN_ON(afinfo->type_offload_esp); |
272 | err = -EEXIST; | 339 | afinfo->type_offload_esp = type; |
273 | spin_unlock_bh(&xfrm_type_offload_lock); | 340 | break; |
341 | default: | ||
342 | WARN_ON(1); | ||
343 | err = -EPROTONOSUPPORT; | ||
344 | break; | ||
345 | } | ||
346 | |||
274 | rcu_read_unlock(); | 347 | rcu_read_unlock(); |
275 | return err; | 348 | return err; |
276 | } | 349 | } |
277 | EXPORT_SYMBOL(xfrm_register_type_offload); | 350 | EXPORT_SYMBOL(xfrm_register_type_offload); |
278 | 351 | ||
279 | int xfrm_unregister_type_offload(const struct xfrm_type_offload *type, | 352 | void xfrm_unregister_type_offload(const struct xfrm_type_offload *type, |
280 | unsigned short family) | 353 | unsigned short family) |
281 | { | 354 | { |
282 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); | 355 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); |
283 | const struct xfrm_type_offload **typemap; | ||
284 | int err = 0; | ||
285 | 356 | ||
286 | if (unlikely(afinfo == NULL)) | 357 | if (unlikely(afinfo == NULL)) |
287 | return -EAFNOSUPPORT; | 358 | return; |
288 | typemap = afinfo->type_offload_map; | ||
289 | spin_lock_bh(&xfrm_type_offload_lock); | ||
290 | 359 | ||
291 | if (unlikely(typemap[type->proto] != type)) | 360 | switch (type->proto) { |
292 | err = -ENOENT; | 361 | case IPPROTO_ESP: |
293 | else | 362 | WARN_ON(afinfo->type_offload_esp != type); |
294 | typemap[type->proto] = NULL; | 363 | afinfo->type_offload_esp = NULL; |
295 | spin_unlock_bh(&xfrm_type_offload_lock); | 364 | break; |
365 | default: | ||
366 | WARN_ON(1); | ||
367 | break; | ||
368 | } | ||
296 | rcu_read_unlock(); | 369 | rcu_read_unlock(); |
297 | return err; | ||
298 | } | 370 | } |
299 | EXPORT_SYMBOL(xfrm_unregister_type_offload); | 371 | EXPORT_SYMBOL(xfrm_unregister_type_offload); |
300 | 372 | ||
301 | static const struct xfrm_type_offload * | 373 | static const struct xfrm_type_offload * |
302 | xfrm_get_type_offload(u8 proto, unsigned short family, bool try_load) | 374 | xfrm_get_type_offload(u8 proto, unsigned short family, bool try_load) |
303 | { | 375 | { |
376 | const struct xfrm_type_offload *type = NULL; | ||
304 | struct xfrm_state_afinfo *afinfo; | 377 | struct xfrm_state_afinfo *afinfo; |
305 | const struct xfrm_type_offload **typemap; | ||
306 | const struct xfrm_type_offload *type; | ||
307 | 378 | ||
308 | retry: | 379 | retry: |
309 | afinfo = xfrm_state_get_afinfo(family); | 380 | afinfo = xfrm_state_get_afinfo(family); |
310 | if (unlikely(afinfo == NULL)) | 381 | if (unlikely(afinfo == NULL)) |
311 | return NULL; | 382 | return NULL; |
312 | typemap = afinfo->type_offload_map; | ||
313 | 383 | ||
314 | type = typemap[proto]; | 384 | switch (proto) { |
385 | case IPPROTO_ESP: | ||
386 | type = afinfo->type_offload_esp; | ||
387 | break; | ||
388 | default: | ||
389 | break; | ||
390 | } | ||
391 | |||
315 | if ((type && !try_module_get(type->owner))) | 392 | if ((type && !try_module_get(type->owner))) |
316 | type = NULL; | 393 | type = NULL; |
317 | 394 | ||
@@ -770,24 +847,79 @@ void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si) | |||
770 | EXPORT_SYMBOL(xfrm_sad_getinfo); | 847 | EXPORT_SYMBOL(xfrm_sad_getinfo); |
771 | 848 | ||
772 | static void | 849 | static void |
850 | __xfrm4_init_tempsel(struct xfrm_selector *sel, const struct flowi *fl) | ||
851 | { | ||
852 | const struct flowi4 *fl4 = &fl->u.ip4; | ||
853 | |||
854 | sel->daddr.a4 = fl4->daddr; | ||
855 | sel->saddr.a4 = fl4->saddr; | ||
856 | sel->dport = xfrm_flowi_dport(fl, &fl4->uli); | ||
857 | sel->dport_mask = htons(0xffff); | ||
858 | sel->sport = xfrm_flowi_sport(fl, &fl4->uli); | ||
859 | sel->sport_mask = htons(0xffff); | ||
860 | sel->family = AF_INET; | ||
861 | sel->prefixlen_d = 32; | ||
862 | sel->prefixlen_s = 32; | ||
863 | sel->proto = fl4->flowi4_proto; | ||
864 | sel->ifindex = fl4->flowi4_oif; | ||
865 | } | ||
866 | |||
867 | static void | ||
868 | __xfrm6_init_tempsel(struct xfrm_selector *sel, const struct flowi *fl) | ||
869 | { | ||
870 | const struct flowi6 *fl6 = &fl->u.ip6; | ||
871 | |||
872 | /* Initialize temporary selector matching only to current session. */ | ||
873 | *(struct in6_addr *)&sel->daddr = fl6->daddr; | ||
874 | *(struct in6_addr *)&sel->saddr = fl6->saddr; | ||
875 | sel->dport = xfrm_flowi_dport(fl, &fl6->uli); | ||
876 | sel->dport_mask = htons(0xffff); | ||
877 | sel->sport = xfrm_flowi_sport(fl, &fl6->uli); | ||
878 | sel->sport_mask = htons(0xffff); | ||
879 | sel->family = AF_INET6; | ||
880 | sel->prefixlen_d = 128; | ||
881 | sel->prefixlen_s = 128; | ||
882 | sel->proto = fl6->flowi6_proto; | ||
883 | sel->ifindex = fl6->flowi6_oif; | ||
884 | } | ||
885 | |||
886 | static void | ||
773 | xfrm_init_tempstate(struct xfrm_state *x, const struct flowi *fl, | 887 | xfrm_init_tempstate(struct xfrm_state *x, const struct flowi *fl, |
774 | const struct xfrm_tmpl *tmpl, | 888 | const struct xfrm_tmpl *tmpl, |
775 | const xfrm_address_t *daddr, const xfrm_address_t *saddr, | 889 | const xfrm_address_t *daddr, const xfrm_address_t *saddr, |
776 | unsigned short family) | 890 | unsigned short family) |
777 | { | 891 | { |
778 | struct xfrm_state_afinfo *afinfo = xfrm_state_afinfo_get_rcu(family); | 892 | switch (family) { |
779 | 893 | case AF_INET: | |
780 | if (!afinfo) | 894 | __xfrm4_init_tempsel(&x->sel, fl); |
781 | return; | 895 | break; |
896 | case AF_INET6: | ||
897 | __xfrm6_init_tempsel(&x->sel, fl); | ||
898 | break; | ||
899 | } | ||
782 | 900 | ||
783 | afinfo->init_tempsel(&x->sel, fl); | 901 | x->id = tmpl->id; |
784 | 902 | ||
785 | if (family != tmpl->encap_family) { | 903 | switch (tmpl->encap_family) { |
786 | afinfo = xfrm_state_afinfo_get_rcu(tmpl->encap_family); | 904 | case AF_INET: |
787 | if (!afinfo) | 905 | if (x->id.daddr.a4 == 0) |
788 | return; | 906 | x->id.daddr.a4 = daddr->a4; |
907 | x->props.saddr = tmpl->saddr; | ||
908 | if (x->props.saddr.a4 == 0) | ||
909 | x->props.saddr.a4 = saddr->a4; | ||
910 | break; | ||
911 | case AF_INET6: | ||
912 | if (ipv6_addr_any((struct in6_addr *)&x->id.daddr)) | ||
913 | memcpy(&x->id.daddr, daddr, sizeof(x->sel.daddr)); | ||
914 | memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr)); | ||
915 | if (ipv6_addr_any((struct in6_addr *)&x->props.saddr)) | ||
916 | memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr)); | ||
917 | break; | ||
789 | } | 918 | } |
790 | afinfo->init_temprop(x, tmpl, daddr, saddr); | 919 | |
920 | x->props.mode = tmpl->mode; | ||
921 | x->props.reqid = tmpl->reqid; | ||
922 | x->props.family = tmpl->encap_family; | ||
791 | } | 923 | } |
792 | 924 | ||
793 | static struct xfrm_state *__xfrm_state_lookup(struct net *net, u32 mark, | 925 | static struct xfrm_state *__xfrm_state_lookup(struct net *net, u32 mark, |
@@ -1633,51 +1765,129 @@ xfrm_find_acq(struct net *net, const struct xfrm_mark *mark, u8 mode, u32 reqid, | |||
1633 | EXPORT_SYMBOL(xfrm_find_acq); | 1765 | EXPORT_SYMBOL(xfrm_find_acq); |
1634 | 1766 | ||
1635 | #ifdef CONFIG_XFRM_SUB_POLICY | 1767 | #ifdef CONFIG_XFRM_SUB_POLICY |
1636 | int | 1768 | #if IS_ENABLED(CONFIG_IPV6) |
1769 | /* distribution counting sort function for xfrm_state and xfrm_tmpl */ | ||
1770 | static void | ||
1771 | __xfrm6_sort(void **dst, void **src, int n, | ||
1772 | int (*cmp)(const void *p), int maxclass) | ||
1773 | { | ||
1774 | int count[XFRM_MAX_DEPTH] = { }; | ||
1775 | int class[XFRM_MAX_DEPTH]; | ||
1776 | int i; | ||
1777 | |||
1778 | for (i = 0; i < n; i++) { | ||
1779 | int c = cmp(src[i]); | ||
1780 | |||
1781 | class[i] = c; | ||
1782 | count[c]++; | ||
1783 | } | ||
1784 | |||
1785 | for (i = 2; i < maxclass; i++) | ||
1786 | count[i] += count[i - 1]; | ||
1787 | |||
1788 | for (i = 0; i < n; i++) { | ||
1789 | dst[count[class[i] - 1]++] = src[i]; | ||
1790 | src[i] = NULL; | ||
1791 | } | ||
1792 | } | ||
1793 | |||
1794 | /* Rule for xfrm_state: | ||
1795 | * | ||
1796 | * rule 1: select IPsec transport except AH | ||
1797 | * rule 2: select MIPv6 RO or inbound trigger | ||
1798 | * rule 3: select IPsec transport AH | ||
1799 | * rule 4: select IPsec tunnel | ||
1800 | * rule 5: others | ||
1801 | */ | ||
1802 | static int __xfrm6_state_sort_cmp(const void *p) | ||
1803 | { | ||
1804 | const struct xfrm_state *v = p; | ||
1805 | |||
1806 | switch (v->props.mode) { | ||
1807 | case XFRM_MODE_TRANSPORT: | ||
1808 | if (v->id.proto != IPPROTO_AH) | ||
1809 | return 1; | ||
1810 | else | ||
1811 | return 3; | ||
1812 | #if IS_ENABLED(CONFIG_IPV6_MIP6) | ||
1813 | case XFRM_MODE_ROUTEOPTIMIZATION: | ||
1814 | case XFRM_MODE_IN_TRIGGER: | ||
1815 | return 2; | ||
1816 | #endif | ||
1817 | case XFRM_MODE_TUNNEL: | ||
1818 | case XFRM_MODE_BEET: | ||
1819 | return 4; | ||
1820 | } | ||
1821 | return 5; | ||
1822 | } | ||
1823 | |||
1824 | /* Rule for xfrm_tmpl: | ||
1825 | * | ||
1826 | * rule 1: select IPsec transport | ||
1827 | * rule 2: select MIPv6 RO or inbound trigger | ||
1828 | * rule 3: select IPsec tunnel | ||
1829 | * rule 4: others | ||
1830 | */ | ||
1831 | static int __xfrm6_tmpl_sort_cmp(const void *p) | ||
1832 | { | ||
1833 | const struct xfrm_tmpl *v = p; | ||
1834 | |||
1835 | switch (v->mode) { | ||
1836 | case XFRM_MODE_TRANSPORT: | ||
1837 | return 1; | ||
1838 | #if IS_ENABLED(CONFIG_IPV6_MIP6) | ||
1839 | case XFRM_MODE_ROUTEOPTIMIZATION: | ||
1840 | case XFRM_MODE_IN_TRIGGER: | ||
1841 | return 2; | ||
1842 | #endif | ||
1843 | case XFRM_MODE_TUNNEL: | ||
1844 | case XFRM_MODE_BEET: | ||
1845 | return 3; | ||
1846 | } | ||
1847 | return 4; | ||
1848 | } | ||
1849 | #else | ||
1850 | static inline int __xfrm6_state_sort_cmp(const void *p) { return 5; } | ||
1851 | static inline int __xfrm6_tmpl_sort_cmp(const void *p) { return 4; } | ||
1852 | |||
1853 | static inline void | ||
1854 | __xfrm6_sort(void **dst, void **src, int n, | ||
1855 | int (*cmp)(const void *p), int maxclass) | ||
1856 | { | ||
1857 | int i; | ||
1858 | |||
1859 | for (i = 0; i < n; i++) | ||
1860 | dst[i] = src[i]; | ||
1861 | } | ||
1862 | #endif /* CONFIG_IPV6 */ | ||
1863 | |||
1864 | void | ||
1637 | xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n, | 1865 | xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n, |
1638 | unsigned short family, struct net *net) | 1866 | unsigned short family) |
1639 | { | 1867 | { |
1640 | int i; | 1868 | int i; |
1641 | int err = 0; | ||
1642 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); | ||
1643 | if (!afinfo) | ||
1644 | return -EAFNOSUPPORT; | ||
1645 | 1869 | ||
1646 | spin_lock_bh(&net->xfrm.xfrm_state_lock); /*FIXME*/ | 1870 | if (family == AF_INET6) |
1647 | if (afinfo->tmpl_sort) | 1871 | __xfrm6_sort((void **)dst, (void **)src, n, |
1648 | err = afinfo->tmpl_sort(dst, src, n); | 1872 | __xfrm6_tmpl_sort_cmp, 5); |
1649 | else | 1873 | else |
1650 | for (i = 0; i < n; i++) | 1874 | for (i = 0; i < n; i++) |
1651 | dst[i] = src[i]; | 1875 | dst[i] = src[i]; |
1652 | spin_unlock_bh(&net->xfrm.xfrm_state_lock); | ||
1653 | rcu_read_unlock(); | ||
1654 | return err; | ||
1655 | } | 1876 | } |
1656 | EXPORT_SYMBOL(xfrm_tmpl_sort); | ||
1657 | 1877 | ||
1658 | int | 1878 | void |
1659 | xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n, | 1879 | xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n, |
1660 | unsigned short family) | 1880 | unsigned short family) |
1661 | { | 1881 | { |
1662 | int i; | 1882 | int i; |
1663 | int err = 0; | ||
1664 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); | ||
1665 | struct net *net = xs_net(*src); | ||
1666 | |||
1667 | if (!afinfo) | ||
1668 | return -EAFNOSUPPORT; | ||
1669 | 1883 | ||
1670 | spin_lock_bh(&net->xfrm.xfrm_state_lock); | 1884 | if (family == AF_INET6) |
1671 | if (afinfo->state_sort) | 1885 | __xfrm6_sort((void **)dst, (void **)src, n, |
1672 | err = afinfo->state_sort(dst, src, n); | 1886 | __xfrm6_state_sort_cmp, 6); |
1673 | else | 1887 | else |
1674 | for (i = 0; i < n; i++) | 1888 | for (i = 0; i < n; i++) |
1675 | dst[i] = src[i]; | 1889 | dst[i] = src[i]; |
1676 | spin_unlock_bh(&net->xfrm.xfrm_state_lock); | ||
1677 | rcu_read_unlock(); | ||
1678 | return err; | ||
1679 | } | 1890 | } |
1680 | EXPORT_SYMBOL(xfrm_state_sort); | ||
1681 | #endif | 1891 | #endif |
1682 | 1892 | ||
1683 | /* Silly enough, but I'm lazy to build resolution list */ | 1893 | /* Silly enough, but I'm lazy to build resolution list */ |
@@ -2195,38 +2405,49 @@ void xfrm_state_delete_tunnel(struct xfrm_state *x) | |||
2195 | } | 2405 | } |
2196 | EXPORT_SYMBOL(xfrm_state_delete_tunnel); | 2406 | EXPORT_SYMBOL(xfrm_state_delete_tunnel); |
2197 | 2407 | ||
2198 | int xfrm_state_mtu(struct xfrm_state *x, int mtu) | 2408 | u32 xfrm_state_mtu(struct xfrm_state *x, int mtu) |
2199 | { | 2409 | { |
2200 | const struct xfrm_type *type = READ_ONCE(x->type); | 2410 | const struct xfrm_type *type = READ_ONCE(x->type); |
2411 | struct crypto_aead *aead; | ||
2412 | u32 blksize, net_adj = 0; | ||
2413 | |||
2414 | if (x->km.state != XFRM_STATE_VALID || | ||
2415 | !type || type->proto != IPPROTO_ESP) | ||
2416 | return mtu - x->props.header_len; | ||
2417 | |||
2418 | aead = x->data; | ||
2419 | blksize = ALIGN(crypto_aead_blocksize(aead), 4); | ||
2201 | 2420 | ||
2202 | if (x->km.state == XFRM_STATE_VALID && | 2421 | switch (x->props.mode) { |
2203 | type && type->get_mtu) | 2422 | case XFRM_MODE_TRANSPORT: |
2204 | return type->get_mtu(x, mtu); | 2423 | case XFRM_MODE_BEET: |
2424 | if (x->props.family == AF_INET) | ||
2425 | net_adj = sizeof(struct iphdr); | ||
2426 | else if (x->props.family == AF_INET6) | ||
2427 | net_adj = sizeof(struct ipv6hdr); | ||
2428 | break; | ||
2429 | case XFRM_MODE_TUNNEL: | ||
2430 | break; | ||
2431 | default: | ||
2432 | WARN_ON_ONCE(1); | ||
2433 | break; | ||
2434 | } | ||
2205 | 2435 | ||
2206 | return mtu - x->props.header_len; | 2436 | return ((mtu - x->props.header_len - crypto_aead_authsize(aead) - |
2437 | net_adj) & ~(blksize - 1)) + net_adj - 2; | ||
2207 | } | 2438 | } |
2439 | EXPORT_SYMBOL_GPL(xfrm_state_mtu); | ||
2208 | 2440 | ||
2209 | int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload) | 2441 | int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload) |
2210 | { | 2442 | { |
2211 | const struct xfrm_state_afinfo *afinfo; | ||
2212 | const struct xfrm_mode *inner_mode; | 2443 | const struct xfrm_mode *inner_mode; |
2213 | const struct xfrm_mode *outer_mode; | 2444 | const struct xfrm_mode *outer_mode; |
2214 | int family = x->props.family; | 2445 | int family = x->props.family; |
2215 | int err; | 2446 | int err; |
2216 | 2447 | ||
2217 | err = -EAFNOSUPPORT; | 2448 | if (family == AF_INET && |
2218 | afinfo = xfrm_state_get_afinfo(family); | 2449 | xs_net(x)->ipv4.sysctl_ip_no_pmtu_disc) |
2219 | if (!afinfo) | 2450 | x->props.flags |= XFRM_STATE_NOPMTUDISC; |
2220 | goto error; | ||
2221 | |||
2222 | err = 0; | ||
2223 | if (afinfo->init_flags) | ||
2224 | err = afinfo->init_flags(x); | ||
2225 | |||
2226 | rcu_read_unlock(); | ||
2227 | |||
2228 | if (err) | ||
2229 | goto error; | ||
2230 | 2451 | ||
2231 | err = -EPROTONOSUPPORT; | 2452 | err = -EPROTONOSUPPORT; |
2232 | 2453 | ||