27 #define pr_fmt(fmt) "IPv6: " fmt
30 #include <linux/module.h>
31 #include <linux/slab.h>
36 #include <linux/string.h>
44 #define IPV6HDR_BASELEN 8
47 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
59 #define AH_SKB_CB(__skb) ((struct ah_skb_cb *)&((__skb)->cb[0]))
61 static void *ah_alloc_tmp(
struct crypto_ahash *ahash,
int nfrags,
66 len = size + crypto_ahash_digestsize(ahash) +
67 (crypto_ahash_alignmask(ahash) &
68 ~(crypto_tfm_ctx_alignment() - 1));
70 len =
ALIGN(len, crypto_tfm_ctx_alignment());
72 len +=
sizeof(
struct ahash_request) + crypto_ahash_reqsize(ahash);
80 static inline struct tmp_ext *ah_tmp_ext(
void *base)
93 return PTR_ALIGN((
u8 *)tmp + offset, crypto_ahash_alignmask(ahash) + 1);
101 req = (
void *)
PTR_ALIGN(icv + crypto_ahash_digestsize(ahash),
102 crypto_tfm_ctx_alignment());
104 ahash_request_set_tfm(req, ahash);
112 return (
void *)
ALIGN((
unsigned long)(req + 1) +
113 crypto_ahash_reqsize(ahash),
117 static bool zero_out_mutable_opts(
struct ipv6_opt_hdr *opthdr)
137 optlen = opt[off+1]+2;
141 memset(&opt[off+2], 0, opt[off+1]);
155 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
163 u8 *opt = (
u8 *)destopt;
181 optlen = opt[off+1]+2;
199 final_addr = hao->
addr;
201 iph->
saddr = final_addr;
228 int segments, segments_left;
233 if (segments_left == 0)
244 segments = rthdr->
hdrlen >> 1;
246 addrs = ((
struct rt0_hdr *)rthdr)->addr;
247 final_addr = addrs[segments - 1];
249 addrs += segments - segments_left;
250 memmove(addrs + 1, addrs, (segments_left - 1) *
sizeof(*addrs));
252 addrs[0] = iph->
daddr;
253 iph->
daddr = final_addr;
256 static int ipv6_clear_mutable_options(
struct ipv6hdr *iph,
int len,
int dir)
263 } exthdr = { .iph = iph };
264 char *
end = exthdr.raw + len;
269 while (exthdr.raw < end) {
273 ipv6_rearrange_destopt(iph, exthdr.opth);
275 if (!zero_out_mutable_opts(exthdr.opth)) {
285 ipv6_rearrange_rthdr(iph, exthdr.rth);
292 nexthdr = exthdr.opth->nexthdr;
307 struct ipv6hdr *top_iph = ipv6_hdr(skb);
311 extlen = skb_network_header_len(skb) -
sizeof(
struct ipv6hdr);
313 extlen +=
sizeof(*iph_ext);
316 iph_ext = ah_tmp_ext(iph_base);
317 icv = ah_tmp_icv(ahp->
ahash, iph_ext, extlen);
323 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
358 skb_push(skb, -skb_network_offset(skb));
359 extlen = skb_network_header_len(skb) -
sizeof(
struct ipv6hdr);
361 extlen +=
sizeof(*iph_ext);
368 iph_ext = ah_tmp_ext(iph_base);
369 icv = ah_tmp_icv(ahash, iph_ext, extlen);
370 req = ah_tmp_req(ahash, icv);
371 sg = ah_req_sg(ahash, req);
376 top_iph = ipv6_hdr(skb);
379 nexthdr = *skb_mac_header(skb);
388 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
393 err = ipv6_clear_mutable_options(top_iph,
394 extlen -
sizeof(*iph_ext) +
403 top_iph->priority = 0;
418 ahash_request_set_crypt(req, sg, icv, skb->
len);
419 ahash_request_set_callback(req, 0, ah6_output_done, skb);
437 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
459 int hdr_len = skb_network_header_len(skb);
460 int ah_hlen = (ah->
hdrlen + 2) << 2;
463 auth_data = ah_tmp_auth(work_iph, hdr_len);
473 memcpy(skb_network_header(skb), work_iph, hdr_len);
474 __skb_pull(skb, ah_hlen + hdr_len);
475 skb_set_transport_header(skb, -hdr_len);
516 if (!pskb_may_pull(skb,
sizeof(
struct ip_auth_hdr)))
521 if (skb_cloned(skb) &&
527 hdr_len = skb_network_header_len(skb);
533 ah_hlen = (ah->
hdrlen + 2) << 2;
539 if (!pskb_may_pull(skb, ah_hlen))
548 ip6h = ipv6_hdr(skb);
552 work_iph = ah_alloc_tmp(ahash, nfrags, hdr_len + ahp->
icv_trunc_len);
556 auth_data = ah_tmp_auth(work_iph, hdr_len);
558 req = ah_tmp_req(ahash, icv);
559 sg = ah_req_sg(ahash, req);
561 memcpy(work_iph, ip6h, hdr_len);
577 ahash_request_set_crypt(req, sg, icv, skb->
len);
578 ahash_request_set_callback(req, 0, ah6_input_done, skb);
595 memcpy(skb_network_header(skb), work_iph, hdr_len);
597 __skb_pull(skb, ah_hlen + hdr_len);
631 static int ah6_init_state(
struct xfrm_state *x)
653 (x->
aalg->alg_key_len + 7) / 8))
665 if (aalg_desc->
uinfo.
auth.icv_fullbits/8 !=
666 crypto_ahash_digestsize(ahash)) {
667 pr_info(
"AH: %s digestsize %u != %hu\n",
668 x->
aalg->alg_name, crypto_ahash_digestsize(ahash),
680 switch (x->
props.mode) {
696 crypto_free_ahash(ahp->
ahash);
709 crypto_free_ahash(ahp->
ahash);
715 .description =
"AH6",
719 .init_state = ah6_init_state,
720 .destructor = ah6_destroy,
722 .output = ah6_output,
726 static const struct inet6_protocol ah6_protocol = {
728 .err_handler = ah6_err,
729 .flags = INET6_PROTO_NOPOLICY,
732 static int __init ah6_init(
void)
735 pr_info(
"%s: can't add xfrm type\n", __func__);
740 pr_info(
"%s: can't add protocol\n", __func__);
748 static void __exit ah6_fini(
void)
751 pr_info(
"%s: can't remove protocol\n", __func__);
754 pr_info(
"%s: can't remove xfrm type\n", __func__);