Blame view

net/ipv6/ah6.c 17.9 KB
1ccea77e2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
  /*
   * Copyright (C)2002 USAGI/WIDE Project
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
4
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
   * Authors
   *
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
7
   *	Mitsuru KANDA @USAGI       : IPv6 Support
67ba4152e   Ian Morris   ipv6: White-space...
8
9
   *	Kazunori MIYAZAWA @USAGI   :
   *	Kunihiro Ishiguro <kunihiro@ipinfusion.com>
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
10
   *
67ba4152e   Ian Morris   ipv6: White-space...
11
   *	This file is derived from net/ipv4/ah.c.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
   */
f32138319   Joe Perches   net: ipv6: Standa...
13
  #define pr_fmt(fmt) "IPv6: " fmt
67df58a3e   Sabrina Dubroca   ah: use crypto_me...
14
  #include <crypto/algapi.h>
8631e9bdf   Steffen Klassert   ah6: convert to a...
15
  #include <crypto/hash.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
17
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
22
  #include <net/ip.h>
  #include <net/ah.h>
  #include <linux/crypto.h>
  #include <linux/pfkeyv2.h>
  #include <linux/string.h>
8631e9bdf   Steffen Klassert   ah6: convert to a...
23
  #include <linux/scatterlist.h>
81aded246   David S. Miller   ipv6: Handle PMTU...
24
  #include <net/ip6_route.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
  #include <net/icmp.h>
  #include <net/ipv6.h>
14c850212   Arnaldo Carvalho de Melo   [INET_SOCK]: Move...
27
  #include <net/protocol.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  #include <net/xfrm.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29

8631e9bdf   Steffen Klassert   ah6: convert to a...
30
31
32
  #define IPV6HDR_BASELEN 8
  
  struct tmp_ext {
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
33
  #if IS_ENABLED(CONFIG_IPV6_MIP6)
8631e9bdf   Steffen Klassert   ah6: convert to a...
34
35
36
  		struct in6_addr saddr;
  #endif
  		struct in6_addr daddr;
b0c9a2d9a   Gustavo A. R. Silva   ipv6: Replace zer...
37
  		char hdrs[];
8631e9bdf   Steffen Klassert   ah6: convert to a...
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
  };
  
  struct ah_skb_cb {
  	struct xfrm_skb_cb xfrm;
  	void *tmp;
  };
  
  #define AH_SKB_CB(__skb) ((struct ah_skb_cb *)&((__skb)->cb[0]))
  
  static void *ah_alloc_tmp(struct crypto_ahash *ahash, int nfrags,
  			  unsigned int size)
  {
  	unsigned int len;
  
  	len = size + crypto_ahash_digestsize(ahash) +
  	      (crypto_ahash_alignmask(ahash) &
  	       ~(crypto_tfm_ctx_alignment() - 1));
  
  	len = ALIGN(len, crypto_tfm_ctx_alignment());
  
  	len += sizeof(struct ahash_request) + crypto_ahash_reqsize(ahash);
  	len = ALIGN(len, __alignof__(struct scatterlist));
  
  	len += sizeof(struct scatterlist) * nfrags;
  
  	return kmalloc(len, GFP_ATOMIC);
  }
  
  static inline struct tmp_ext *ah_tmp_ext(void *base)
  {
  	return base + IPV6HDR_BASELEN;
  }
  
  static inline u8 *ah_tmp_auth(u8 *tmp, unsigned int offset)
  {
  	return tmp + offset;
  }
  
  static inline u8 *ah_tmp_icv(struct crypto_ahash *ahash, void *tmp,
  			     unsigned int offset)
  {
  	return PTR_ALIGN((u8 *)tmp + offset, crypto_ahash_alignmask(ahash) + 1);
  }
  
  static inline struct ahash_request *ah_tmp_req(struct crypto_ahash *ahash,
  					       u8 *icv)
  {
  	struct ahash_request *req;
  
  	req = (void *)PTR_ALIGN(icv + crypto_ahash_digestsize(ahash),
  				crypto_tfm_ctx_alignment());
  
  	ahash_request_set_tfm(req, ahash);
  
  	return req;
  }
  
  static inline struct scatterlist *ah_req_sg(struct crypto_ahash *ahash,
  					     struct ahash_request *req)
  {
  	return (void *)ALIGN((unsigned long)(req + 1) +
  			     crypto_ahash_reqsize(ahash),
  			     __alignof__(struct scatterlist));
  }
a50feda54   Eric Dumazet   ipv6: bool/const ...
102
  static bool zero_out_mutable_opts(struct ipv6_opt_hdr *opthdr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
104
105
106
107
108
109
110
111
112
113
114
  {
  	u8 *opt = (u8 *)opthdr;
  	int len = ipv6_optlen(opthdr);
  	int off = 0;
  	int optlen = 0;
  
  	off += 2;
  	len -= 2;
  
  	while (len > 0) {
  
  		switch (opt[off]) {
1de5a71c3   Eldad Zack   ipv6: correct the...
115
  		case IPV6_TLV_PAD1:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
118
  			optlen = 1;
  			break;
  		default:
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
119
  			if (len < 2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
121
122
123
124
125
126
127
128
129
130
131
132
  				goto bad;
  			optlen = opt[off+1]+2;
  			if (len < optlen)
  				goto bad;
  			if (opt[off] & 0x20)
  				memset(&opt[off+2], 0, opt[off+1]);
  			break;
  		}
  
  		off += optlen;
  		len -= optlen;
  	}
  	if (len == 0)
a50feda54   Eric Dumazet   ipv6: bool/const ...
133
  		return true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
  
  bad:
a50feda54   Eric Dumazet   ipv6: bool/const ...
136
  	return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
  }
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
138
  #if IS_ENABLED(CONFIG_IPV6_MIP6)
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
  /**
   *	ipv6_rearrange_destopt - rearrange IPv6 destination options header
   *	@iph: IPv6 header
   *	@destopt: destionation options header
   */
  static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *destopt)
  {
  	u8 *opt = (u8 *)destopt;
  	int len = ipv6_optlen(destopt);
  	int off = 0;
  	int optlen = 0;
  
  	off += 2;
  	len -= 2;
  
  	while (len > 0) {
  
  		switch (opt[off]) {
1de5a71c3   Eldad Zack   ipv6: correct the...
157
  		case IPV6_TLV_PAD1:
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
  			optlen = 1;
  			break;
  		default:
  			if (len < 2)
  				goto bad;
  			optlen = opt[off+1]+2;
  			if (len < optlen)
  				goto bad;
  
  			/* Rearrange the source address in @iph and the
  			 * addresses in home address option for final source.
  			 * See 11.3.2 of RFC 3775 for details.
  			 */
  			if (opt[off] == IPV6_TLV_HAO) {
  				struct in6_addr final_addr;
  				struct ipv6_destopt_hao *hao;
  
  				hao = (struct ipv6_destopt_hao *)&opt[off];
  				if (hao->length != sizeof(hao->addr)) {
e87cc4728   Joe Perches   net: Convert net_...
177
178
179
  					net_warn_ratelimited("destopt hao: invalid header length: %u
  ",
  							     hao->length);
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
180
181
  					goto bad;
  				}
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
182
183
184
  				final_addr = hao->addr;
  				hao->addr = iph->saddr;
  				iph->saddr = final_addr;
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
185
186
187
188
189
190
191
  			}
  			break;
  		}
  
  		off += optlen;
  		len -= optlen;
  	}
e731c248b   YOSHIFUJI Hideaki   [IPV6] MIP6: Seve...
192
  	/* Note: ok if len == 0 */
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
193
194
195
  bad:
  	return;
  }
136ebf08b   Masahide NAKAMURA   [IPV6] MIP6: Kill...
196
197
  #else
  static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *destopt) {}
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
198
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
  /**
   *	ipv6_rearrange_rthdr - rearrange IPv6 routing header
   *	@iph: IPv6 header
   *	@rthdr: routing header
   *
   *	Rearrange the destination address in @iph and the addresses in @rthdr
   *	so that they appear in the order they will at the final destination.
   *	See Appendix A2 of RFC 2402 for details.
   */
  static void ipv6_rearrange_rthdr(struct ipv6hdr *iph, struct ipv6_rt_hdr *rthdr)
  {
  	int segments, segments_left;
  	struct in6_addr *addrs;
  	struct in6_addr final_addr;
  
  	segments_left = rthdr->segments_left;
  	if (segments_left == 0)
  		return;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
217
  	rthdr->segments_left = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
219
220
221
222
223
224
225
226
227
228
  
  	/* The value of rthdr->hdrlen has been verified either by the system
  	 * call if it is locally generated, or by ipv6_rthdr_rcv() for incoming
  	 * packets.  So we can assume that it is even and that segments is
  	 * greater than or equal to segments_left.
  	 *
  	 * For the same reason we can assume that this option is of type 0.
  	 */
  	segments = rthdr->hdrlen >> 1;
  
  	addrs = ((struct rt0_hdr *)rthdr)->addr;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
229
  	final_addr = addrs[segments - 1];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
232
  
  	addrs += segments - segments_left;
  	memmove(addrs + 1, addrs, (segments_left - 1) * sizeof(*addrs));
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
233
234
  	addrs[0] = iph->daddr;
  	iph->daddr = final_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
  }
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
236
  static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
238
239
240
241
242
243
244
245
246
247
248
249
250
  {
  	union {
  		struct ipv6hdr *iph;
  		struct ipv6_opt_hdr *opth;
  		struct ipv6_rt_hdr *rth;
  		char *raw;
  	} exthdr = { .iph = iph };
  	char *end = exthdr.raw + len;
  	int nexthdr = iph->nexthdr;
  
  	exthdr.iph++;
  
  	while (exthdr.raw < end) {
  		switch (nexthdr) {
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
251
252
253
  		case NEXTHDR_DEST:
  			if (dir == XFRM_POLICY_OUT)
  				ipv6_rearrange_destopt(iph, exthdr.opth);
a8eceea84   Joe Perches   inet: Use fallthr...
254
  			fallthrough;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
  		case NEXTHDR_HOP:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256
  			if (!zero_out_mutable_opts(exthdr.opth)) {
ba7a46f16   Joe Perches   net: Convert LIMI...
257
258
259
260
  				net_dbg_ratelimited("overrun %sopts
  ",
  						    nexthdr == NEXTHDR_HOP ?
  						    "hop" : "dest");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
262
263
264
265
266
267
  				return -EINVAL;
  			}
  			break;
  
  		case NEXTHDR_ROUTING:
  			ipv6_rearrange_rthdr(iph, exthdr.rth);
  			break;
67ba4152e   Ian Morris   ipv6: White-space...
268
  		default:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
271
272
273
274
275
276
277
  			return 0;
  		}
  
  		nexthdr = exthdr.opth->nexthdr;
  		exthdr.raw += ipv6_optlen(exthdr.opth);
  	}
  
  	return 0;
  }
8631e9bdf   Steffen Klassert   ah6: convert to a...
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
  static void ah6_output_done(struct crypto_async_request *base, int err)
  {
  	int extlen;
  	u8 *iph_base;
  	u8 *icv;
  	struct sk_buff *skb = base->data;
  	struct xfrm_state *x = skb_dst(skb)->xfrm;
  	struct ah_data *ahp = x->data;
  	struct ipv6hdr *top_iph = ipv6_hdr(skb);
  	struct ip_auth_hdr *ah = ip_auth_hdr(skb);
  	struct tmp_ext *iph_ext;
  
  	extlen = skb_network_header_len(skb) - sizeof(struct ipv6hdr);
  	if (extlen)
  		extlen += sizeof(*iph_ext);
  
  	iph_base = AH_SKB_CB(skb)->tmp;
  	iph_ext = ah_tmp_ext(iph_base);
  	icv = ah_tmp_icv(ahp->ahash, iph_ext, extlen);
  
  	memcpy(ah->auth_data, icv, ahp->icv_trunc_len);
  	memcpy(top_iph, iph_base, IPV6HDR_BASELEN);
  
  	if (extlen) {
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
302
  #if IS_ENABLED(CONFIG_IPV6_MIP6)
8631e9bdf   Steffen Klassert   ah6: convert to a...
303
304
305
306
307
  		memcpy(&top_iph->saddr, iph_ext, extlen);
  #else
  		memcpy(&top_iph->daddr, iph_ext, extlen);
  #endif
  	}
8631e9bdf   Steffen Klassert   ah6: convert to a...
308
309
310
  	kfree(AH_SKB_CB(skb)->tmp);
  	xfrm_output_resume(skb, err);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
312
313
  static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
  {
  	int err;
8631e9bdf   Steffen Klassert   ah6: convert to a...
314
  	int nfrags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
  	int extlen;
8631e9bdf   Steffen Klassert   ah6: convert to a...
316
317
318
319
320
321
322
  	u8 *iph_base;
  	u8 *icv;
  	u8 nexthdr;
  	struct sk_buff *trailer;
  	struct crypto_ahash *ahash;
  	struct ahash_request *req;
  	struct scatterlist *sg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
324
325
  	struct ipv6hdr *top_iph;
  	struct ip_auth_hdr *ah;
  	struct ah_data *ahp;
8631e9bdf   Steffen Klassert   ah6: convert to a...
326
  	struct tmp_ext *iph_ext;
26dd70c3f   Fan Du   {IPv6,xfrm} Add E...
327
328
329
330
  	int seqhi_len = 0;
  	__be32 *seqhi;
  	int sglists = 0;
  	struct scatterlist *seqhisg;
8631e9bdf   Steffen Klassert   ah6: convert to a...
331
332
333
  
  	ahp = x->data;
  	ahash = ahp->ahash;
e5d08d718   Ian Morris   ipv6: coding styl...
334
335
  	err = skb_cow_data(skb, 0, &trailer);
  	if (err < 0)
8631e9bdf   Steffen Klassert   ah6: convert to a...
336
337
  		goto out;
  	nfrags = err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338

7b277b1a5   Herbert Xu   [IPSEC]: Set skb-...
339
  	skb_push(skb, -skb_network_offset(skb));
8631e9bdf   Steffen Klassert   ah6: convert to a...
340
341
342
  	extlen = skb_network_header_len(skb) - sizeof(struct ipv6hdr);
  	if (extlen)
  		extlen += sizeof(*iph_ext);
26dd70c3f   Fan Du   {IPv6,xfrm} Add E...
343
344
345
346
  	if (x->props.flags & XFRM_STATE_ESN) {
  		sglists = 1;
  		seqhi_len = sizeof(*seqhi);
  	}
8631e9bdf   Steffen Klassert   ah6: convert to a...
347
  	err = -ENOMEM;
26dd70c3f   Fan Du   {IPv6,xfrm} Add E...
348
349
  	iph_base = ah_alloc_tmp(ahash, nfrags + sglists, IPV6HDR_BASELEN +
  				extlen + seqhi_len);
8631e9bdf   Steffen Klassert   ah6: convert to a...
350
351
352
353
  	if (!iph_base)
  		goto out;
  
  	iph_ext = ah_tmp_ext(iph_base);
26dd70c3f   Fan Du   {IPv6,xfrm} Add E...
354
355
  	seqhi = (__be32 *)((char *)iph_ext + extlen);
  	icv = ah_tmp_icv(ahash, seqhi, seqhi_len);
8631e9bdf   Steffen Klassert   ah6: convert to a...
356
357
  	req = ah_tmp_req(ahash, icv);
  	sg = ah_req_sg(ahash, req);
26dd70c3f   Fan Du   {IPv6,xfrm} Add E...
358
  	seqhisg = sg + nfrags;
8631e9bdf   Steffen Klassert   ah6: convert to a...
359
360
361
  
  	ah = ip_auth_hdr(skb);
  	memset(ah->auth_data, 0, ahp->icv_trunc_len);
007f0211a   Herbert Xu   [IPSEC]: Store IP...
362
  	top_iph = ipv6_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
  	top_iph->payload_len = htons(skb->len - sizeof(*top_iph));
007f0211a   Herbert Xu   [IPSEC]: Store IP...
364
365
  	nexthdr = *skb_mac_header(skb);
  	*skb_mac_header(skb) = IPPROTO_AH;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
367
368
369
  
  	/* When there are no extension headers, we only need to save the first
  	 * 8 bytes of the base IP header.
  	 */
8631e9bdf   Steffen Klassert   ah6: convert to a...
370
  	memcpy(iph_base, top_iph, IPV6HDR_BASELEN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
372
  	if (extlen) {
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
373
  #if IS_ENABLED(CONFIG_IPV6_MIP6)
8631e9bdf   Steffen Klassert   ah6: convert to a...
374
  		memcpy(iph_ext, &top_iph->saddr, extlen);
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
375
  #else
8631e9bdf   Steffen Klassert   ah6: convert to a...
376
  		memcpy(iph_ext, &top_iph->daddr, extlen);
e731c248b   YOSHIFUJI Hideaki   [IPV6] MIP6: Seve...
377
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
  		err = ipv6_clear_mutable_options(top_iph,
8631e9bdf   Steffen Klassert   ah6: convert to a...
379
  						 extlen - sizeof(*iph_ext) +
e731c248b   YOSHIFUJI Hideaki   [IPV6] MIP6: Seve...
380
381
  						 sizeof(*top_iph),
  						 XFRM_POLICY_OUT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
  		if (err)
8631e9bdf   Steffen Klassert   ah6: convert to a...
383
  			goto out_free;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385
386
387
388
389
390
391
  	ah->nexthdr = nexthdr;
  
  	top_iph->priority    = 0;
  	top_iph->flow_lbl[0] = 0;
  	top_iph->flow_lbl[1] = 0;
  	top_iph->flow_lbl[2] = 0;
  	top_iph->hop_limit   = 0;
87bdc48d3   Herbert Xu   [IPSEC]: Get rid ...
392
  	ah->hdrlen  = (XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len) >> 2) - 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
394
395
  
  	ah->reserved = 0;
  	ah->spi = x->id.spi;
1ce3644ad   Steffen Klassert   xfrm: Use separat...
396
  	ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low);
b7c6538cd   Herbert Xu   [IPSEC]: Move sta...
397

26dd70c3f   Fan Du   {IPv6,xfrm} Add E...
398
  	sg_init_table(sg, nfrags + sglists);
3f2977072   Jason A. Donenfeld   ipsec: check retu...
399
400
401
  	err = skb_to_sgvec_nomark(skb, sg, 0, skb->len);
  	if (unlikely(err < 0))
  		goto out_free;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402

26dd70c3f   Fan Du   {IPv6,xfrm} Add E...
403
404
405
406
407
408
  	if (x->props.flags & XFRM_STATE_ESN) {
  		/* Attach seqhi sg right after packet payload */
  		*seqhi = htonl(XFRM_SKB_CB(skb)->seq.output.hi);
  		sg_set_buf(seqhisg, seqhi, seqhi_len);
  	}
  	ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len);
8631e9bdf   Steffen Klassert   ah6: convert to a...
409
410
411
  	ahash_request_set_callback(req, 0, ah6_output_done, skb);
  
  	AH_SKB_CB(skb)->tmp = iph_base;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412

8631e9bdf   Steffen Klassert   ah6: convert to a...
413
414
415
416
  	err = crypto_ahash_digest(req);
  	if (err) {
  		if (err == -EINPROGRESS)
  			goto out;
068c2e703   Gilad Ben-Yossef   net: use -ENOSPC ...
417
  		if (err == -ENOSPC)
8631e9bdf   Steffen Klassert   ah6: convert to a...
418
419
420
421
422
423
424
425
  			err = NET_XMIT_DROP;
  		goto out_free;
  	}
  
  	memcpy(ah->auth_data, icv, ahp->icv_trunc_len);
  	memcpy(top_iph, iph_base, IPV6HDR_BASELEN);
  
  	if (extlen) {
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
426
  #if IS_ENABLED(CONFIG_IPV6_MIP6)
8631e9bdf   Steffen Klassert   ah6: convert to a...
427
  		memcpy(&top_iph->saddr, iph_ext, extlen);
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
428
  #else
8631e9bdf   Steffen Klassert   ah6: convert to a...
429
  		memcpy(&top_iph->daddr, iph_ext, extlen);
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
430
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
  	}
8631e9bdf   Steffen Klassert   ah6: convert to a...
432
433
434
  out_free:
  	kfree(iph_base);
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
436
  	return err;
  }
8631e9bdf   Steffen Klassert   ah6: convert to a...
437
438
439
440
441
442
443
444
445
446
  static void ah6_input_done(struct crypto_async_request *base, int err)
  {
  	u8 *auth_data;
  	u8 *icv;
  	u8 *work_iph;
  	struct sk_buff *skb = base->data;
  	struct xfrm_state *x = xfrm_input_state(skb);
  	struct ah_data *ahp = x->data;
  	struct ip_auth_hdr *ah = ip_auth_hdr(skb);
  	int hdr_len = skb_network_header_len(skb);
416e8126a   yangxingwu   ipv6: Use ipv6_au...
447
  	int ah_hlen = ipv6_authlen(ah);
8631e9bdf   Steffen Klassert   ah6: convert to a...
448

726282aa6   Gilad Ben-Yossef   IPsec: do not ign...
449
450
  	if (err)
  		goto out;
8631e9bdf   Steffen Klassert   ah6: convert to a...
451
452
453
  	work_iph = AH_SKB_CB(skb)->tmp;
  	auth_data = ah_tmp_auth(work_iph, hdr_len);
  	icv = ah_tmp_icv(ahp->ahash, auth_data, ahp->icv_trunc_len);
67df58a3e   Sabrina Dubroca   ah: use crypto_me...
454
  	err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
8631e9bdf   Steffen Klassert   ah6: convert to a...
455
456
  	if (err)
  		goto out;
b7ea81a58   Nick Bowler   ah: Read nexthdr ...
457
  	err = ah->nexthdr;
8631e9bdf   Steffen Klassert   ah6: convert to a...
458
459
460
  	skb->network_header += ah_hlen;
  	memcpy(skb_network_header(skb), work_iph, hdr_len);
  	__skb_pull(skb, ah_hlen + hdr_len);
a9403f8ae   Li RongQing   ah6/esp6: set tra...
461
462
463
464
  	if (x->props.mode == XFRM_MODE_TUNNEL)
  		skb_reset_transport_header(skb);
  	else
  		skb_set_transport_header(skb, -hdr_len);
8631e9bdf   Steffen Klassert   ah6: convert to a...
465
466
467
468
  out:
  	kfree(AH_SKB_CB(skb)->tmp);
  	xfrm_input_resume(skb, err);
  }
e695633e2   Herbert Xu   [IPSEC]: Kill unu...
469
  static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
471
472
473
474
475
476
477
  {
  	/*
  	 * Before process AH
  	 * [IPv6][Ext1][Ext2][AH][Dest][Payload]
  	 * |<-------------->| hdr_len
  	 *
  	 * To erase AH:
  	 * Keeping copy of cleared headers. After AH processing,
b0e380b1d   Arnaldo Carvalho de Melo   [SK_BUFF]: unions...
478
479
  	 * Moving the pointer of skb->network_header by using skb_pull as long
  	 * as AH header length. Then copy back the copy as long as hdr_len
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
  	 * If destination header following AH exists, copy it into after [Ext2].
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
481
  	 *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
483
484
  	 * |<>|[IPv6][Ext1][Ext2][Dest][Payload]
  	 * There is offset of AH before IPv6 header after the process.
  	 */
8631e9bdf   Steffen Klassert   ah6: convert to a...
485
486
487
488
489
490
491
  	u8 *auth_data;
  	u8 *icv;
  	u8 *work_iph;
  	struct sk_buff *trailer;
  	struct crypto_ahash *ahash;
  	struct ahash_request *req;
  	struct scatterlist *sg;
87bdc48d3   Herbert Xu   [IPSEC]: Get rid ...
492
  	struct ip_auth_hdr *ah;
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
493
  	struct ipv6hdr *ip6h;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494
  	struct ah_data *ahp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495
496
497
  	u16 hdr_len;
  	u16 ah_hlen;
  	int nexthdr;
8631e9bdf   Steffen Klassert   ah6: convert to a...
498
499
  	int nfrags;
  	int err = -ENOMEM;
8d6da6f32   Fan Du   {IPv6,xfrm} Add E...
500
501
502
503
  	int seqhi_len = 0;
  	__be32 *seqhi;
  	int sglists = 0;
  	struct scatterlist *seqhisg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504
505
506
507
508
509
  
  	if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr)))
  		goto out;
  
  	/* We are going to _remove_ AH header to keep sockets happy,
  	 * so... Later this can change. */
14bbd6a56   Pravin B Shelar   net: Add skb_uncl...
510
  	if (skb_unclone(skb, GFP_ATOMIC))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
  		goto out;
7aa68cb90   Herbert Xu   [IPSEC]: Move ip_...
512
  	skb->ip_summed = CHECKSUM_NONE;
8631e9bdf   Steffen Klassert   ah6: convert to a...
513
  	hdr_len = skb_network_header_len(skb);
87bdc48d3   Herbert Xu   [IPSEC]: Get rid ...
514
  	ah = (struct ip_auth_hdr *)skb->data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
  	ahp = x->data;
8631e9bdf   Steffen Klassert   ah6: convert to a...
516
  	ahash = ahp->ahash;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517
  	nexthdr = ah->nexthdr;
416e8126a   yangxingwu   ipv6: Use ipv6_au...
518
  	ah_hlen = ipv6_authlen(ah);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
519

87bdc48d3   Herbert Xu   [IPSEC]: Get rid ...
520
521
  	if (ah_hlen != XFRM_ALIGN8(sizeof(*ah) + ahp->icv_full_len) &&
  	    ah_hlen != XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len))
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
522
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523
524
525
  
  	if (!pskb_may_pull(skb, ah_hlen))
  		goto out;
e5d08d718   Ian Morris   ipv6: coding styl...
526
527
  	err = skb_cow_data(skb, 0, &trailer);
  	if (err < 0)
8631e9bdf   Steffen Klassert   ah6: convert to a...
528
529
  		goto out;
  	nfrags = err;
4b0ef1f22   Dang Hongwu   ah: reload pointe...
530
531
532
533
  	ah = (struct ip_auth_hdr *)skb->data;
  	ip6h = ipv6_hdr(skb);
  
  	skb_push(skb, hdr_len);
8d6da6f32   Fan Du   {IPv6,xfrm} Add E...
534
535
536
537
538
539
540
  	if (x->props.flags & XFRM_STATE_ESN) {
  		sglists = 1;
  		seqhi_len = sizeof(*seqhi);
  	}
  
  	work_iph = ah_alloc_tmp(ahash, nfrags + sglists, hdr_len +
  				ahp->icv_trunc_len + seqhi_len);
25105051f   Julia Lawall   ah6: fix error re...
541
542
  	if (!work_iph) {
  		err = -ENOMEM;
8631e9bdf   Steffen Klassert   ah6: convert to a...
543
  		goto out;
25105051f   Julia Lawall   ah6: fix error re...
544
  	}
8631e9bdf   Steffen Klassert   ah6: convert to a...
545

8d6da6f32   Fan Du   {IPv6,xfrm} Add E...
546
547
548
  	auth_data = ah_tmp_auth((u8 *)work_iph, hdr_len);
  	seqhi = (__be32 *)(auth_data + ahp->icv_trunc_len);
  	icv = ah_tmp_icv(ahash, seqhi, seqhi_len);
8631e9bdf   Steffen Klassert   ah6: convert to a...
549
550
  	req = ah_tmp_req(ahash, icv);
  	sg = ah_req_sg(ahash, req);
8d6da6f32   Fan Du   {IPv6,xfrm} Add E...
551
  	seqhisg = sg + nfrags;
8631e9bdf   Steffen Klassert   ah6: convert to a...
552
553
554
555
  
  	memcpy(work_iph, ip6h, hdr_len);
  	memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
  	memset(ah->auth_data, 0, ahp->icv_trunc_len);
a5ebcbdf3   Zhang Changzhong   ah6: fix error re...
556
557
  	err = ipv6_clear_mutable_options(ip6h, hdr_len, XFRM_POLICY_IN);
  	if (err)
8631e9bdf   Steffen Klassert   ah6: convert to a...
558
  		goto out_free;
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
559
560
561
562
563
  	ip6h->priority    = 0;
  	ip6h->flow_lbl[0] = 0;
  	ip6h->flow_lbl[1] = 0;
  	ip6h->flow_lbl[2] = 0;
  	ip6h->hop_limit   = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564

8d6da6f32   Fan Du   {IPv6,xfrm} Add E...
565
  	sg_init_table(sg, nfrags + sglists);
3f2977072   Jason A. Donenfeld   ipsec: check retu...
566
567
568
  	err = skb_to_sgvec_nomark(skb, sg, 0, skb->len);
  	if (unlikely(err < 0))
  		goto out_free;
8d6da6f32   Fan Du   {IPv6,xfrm} Add E...
569
570
571
572
573
574
  
  	if (x->props.flags & XFRM_STATE_ESN) {
  		/* Attach seqhi sg right after packet payload */
  		*seqhi = XFRM_SKB_CB(skb)->seq.input.hi;
  		sg_set_buf(seqhisg, seqhi, seqhi_len);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575

8d6da6f32   Fan Du   {IPv6,xfrm} Add E...
576
  	ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len);
8631e9bdf   Steffen Klassert   ah6: convert to a...
577
578
579
580
581
582
583
584
  	ahash_request_set_callback(req, 0, ah6_input_done, skb);
  
  	AH_SKB_CB(skb)->tmp = work_iph;
  
  	err = crypto_ahash_digest(req);
  	if (err) {
  		if (err == -EINPROGRESS)
  			goto out;
8631e9bdf   Steffen Klassert   ah6: convert to a...
585
  		goto out_free;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
  	}
0ebea8ef3   Herbert Xu   [IPSEC]: Move sta...
587

67df58a3e   Sabrina Dubroca   ah: use crypto_me...
588
  	err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
0ebea8ef3   Herbert Xu   [IPSEC]: Move sta...
589
  	if (err)
8631e9bdf   Steffen Klassert   ah6: convert to a...
590
  		goto out_free;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591

b0e380b1d   Arnaldo Carvalho de Melo   [SK_BUFF]: unions...
592
  	skb->network_header += ah_hlen;
8631e9bdf   Steffen Klassert   ah6: convert to a...
593
  	memcpy(skb_network_header(skb), work_iph, hdr_len);
31a4ab930   Herbert Xu   [IPSEC] proto: Mo...
594
  	__skb_pull(skb, ah_hlen + hdr_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595

a9403f8ae   Li RongQing   ah6/esp6: set tra...
596
597
598
599
  	if (x->props.mode == XFRM_MODE_TUNNEL)
  		skb_reset_transport_header(skb);
  	else
  		skb_set_transport_header(skb, -hdr_len);
8631e9bdf   Steffen Klassert   ah6: convert to a...
600
  	err = nexthdr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601

8631e9bdf   Steffen Klassert   ah6: convert to a...
602
603
  out_free:
  	kfree(work_iph);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
  out:
07d4ee583   Herbert Xu   [IPSEC]: Use HMAC...
605
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
606
  }
e924d2d68   Steffen Klassert   ah6: Use the IPse...
607
608
  static int ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
  		   u8 type, u8 code, int offset, __be32 info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
609
  {
4fb236bac   Alexey Dobriyan   netns xfrm: AH/ES...
610
  	struct net *net = dev_net(skb->dev);
67ba4152e   Ian Morris   ipv6: White-space...
611
612
  	struct ipv6hdr *iph = (struct ipv6hdr *)skb->data;
  	struct ip_auth_hdr *ah = (struct ip_auth_hdr *)(skb->data+offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
  	struct xfrm_state *x;
b3b2b9e19   Steffen Klassert   ipsec: Don't upda...
614
  	if (type != ICMPV6_PKT_TOOBIG &&
ec18d9a26   David S. Miller   ipv6: Add redirec...
615
  	    type != NDISC_REDIRECT)
e924d2d68   Steffen Klassert   ah6: Use the IPse...
616
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617

bd55775c8   Jamal Hadi Salim   xfrm: SA lookups ...
618
  	x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET6);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619
  	if (!x)
e924d2d68   Steffen Klassert   ah6: Use the IPse...
620
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
621

ec18d9a26   David S. Miller   ipv6: Add redirec...
622
  	if (type == NDISC_REDIRECT)
e2d118a1c   Lorenzo Colitti   net: inet: Suppor...
623
624
  		ip6_redirect(skb, net, skb->dev->ifindex, 0,
  			     sock_net_uid(net, NULL));
ec18d9a26   David S. Miller   ipv6: Add redirec...
625
  	else
e2d118a1c   Lorenzo Colitti   net: inet: Suppor...
626
  		ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627
  	xfrm_state_put(x);
e924d2d68   Steffen Klassert   ah6: Use the IPse...
628
629
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
630
  }
72cb6962a   Herbert Xu   [IPSEC]: Add xfrm...
631
  static int ah6_init_state(struct xfrm_state *x)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
633
634
  {
  	struct ah_data *ahp = NULL;
  	struct xfrm_algo_desc *aalg_desc;
8631e9bdf   Steffen Klassert   ah6: convert to a...
635
  	struct crypto_ahash *ahash;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636
637
638
  
  	if (!x->aalg)
  		goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
639
640
  	if (x->encap)
  		goto error;
0c600eda4   Ingo Oeser   [IPV6]: Nearly co...
641
  	ahp = kzalloc(sizeof(*ahp), GFP_KERNEL);
63159f29b   Ian Morris   ipv6: coding styl...
642
  	if (!ahp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643
  		return -ENOMEM;
8631e9bdf   Steffen Klassert   ah6: convert to a...
644
645
  	ahash = crypto_alloc_ahash(x->aalg->alg_name, 0, 0);
  	if (IS_ERR(ahash))
07d4ee583   Herbert Xu   [IPSEC]: Use HMAC...
646
  		goto error;
8631e9bdf   Steffen Klassert   ah6: convert to a...
647
648
  	ahp->ahash = ahash;
  	if (crypto_ahash_setkey(ahash, x->aalg->alg_key,
bc31d3b2c   Herbert Xu   [IPSEC] ah: Remov...
649
  			       (x->aalg->alg_key_len + 7) / 8))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
  		goto error;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
651

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652
653
654
655
  	/*
  	 * Lookup the algorithm description maintained by xfrm_algo,
  	 * verify crypto transform properties, and store information
  	 * we need for AH processing.  This lookup cannot fail here
07d4ee583   Herbert Xu   [IPSEC]: Use HMAC...
656
  	 * after a successful crypto_alloc_hash().
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
658
659
660
661
  	 */
  	aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
  	BUG_ON(!aalg_desc);
  
  	if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
8631e9bdf   Steffen Klassert   ah6: convert to a...
662
  	    crypto_ahash_digestsize(ahash)) {
f32138319   Joe Perches   net: ipv6: Standa...
663
664
665
666
  		pr_info("AH: %s digestsize %u != %hu
  ",
  			x->aalg->alg_name, crypto_ahash_digestsize(ahash),
  			aalg_desc->uinfo.auth.icv_fullbits/8);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
667
668
  		goto error;
  	}
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
669

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670
  	ahp->icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
8f8a088c2   Martin Willi   xfrm: Use the use...
671
  	ahp->icv_trunc_len = x->aalg->alg_trunc_len/8;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
672

87bdc48d3   Herbert Xu   [IPSEC]: Get rid ...
673
674
  	x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) +
  					  ahp->icv_trunc_len);
ca68145f1   Herbert Xu   [IPSEC]: Disallow...
675
676
677
678
679
  	switch (x->props.mode) {
  	case XFRM_MODE_BEET:
  	case XFRM_MODE_TRANSPORT:
  		break;
  	case XFRM_MODE_TUNNEL:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
680
  		x->props.header_len += sizeof(struct ipv6hdr);
ea2c47b42   Masahide NAKAMURA   [IPSEC] IPV6: Fix...
681
  		break;
ca68145f1   Herbert Xu   [IPSEC]: Disallow...
682
683
684
  	default:
  		goto error;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685
686
687
688
689
690
  	x->data = ahp;
  
  	return 0;
  
  error:
  	if (ahp) {
8631e9bdf   Steffen Klassert   ah6: convert to a...
691
  		crypto_free_ahash(ahp->ahash);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
693
694
695
696
697
698
699
700
701
702
  		kfree(ahp);
  	}
  	return -EINVAL;
  }
  
  static void ah6_destroy(struct xfrm_state *x)
  {
  	struct ah_data *ahp = x->data;
  
  	if (!ahp)
  		return;
8631e9bdf   Steffen Klassert   ah6: convert to a...
703
  	crypto_free_ahash(ahp->ahash);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
705
  	kfree(ahp);
  }
e924d2d68   Steffen Klassert   ah6: Use the IPse...
706
707
708
709
  static int ah6_rcv_cb(struct sk_buff *skb, int err)
  {
  	return 0;
  }
cc24becae   Ian Morris   ipv6: White-space...
710
  static const struct xfrm_type ah6_type = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
711
712
  	.description	= "AH6",
  	.owner		= THIS_MODULE,
cc24becae   Ian Morris   ipv6: White-space...
713
  	.proto		= IPPROTO_AH,
436a0a402   Herbert Xu   [IPSEC]: Move out...
714
  	.flags		= XFRM_TYPE_REPLAY_PROT,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
715
716
717
  	.init_state	= ah6_init_state,
  	.destructor	= ah6_destroy,
  	.input		= ah6_input,
aee5adb43   Masahide NAKAMURA   [XFRM] STATE: Add...
718
719
  	.output		= ah6_output,
  	.hdr_offset	= xfrm6_find_1stfragopt,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
720
  };
e924d2d68   Steffen Klassert   ah6: Use the IPse...
721
  static struct xfrm6_protocol ah6_protocol = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
  	.handler	=	xfrm6_rcv,
0146dca70   Sabrina Dubroca   xfrm: add support...
723
  	.input_handler	=	xfrm_input,
e924d2d68   Steffen Klassert   ah6: Use the IPse...
724
  	.cb_handler	=	ah6_rcv_cb,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
725
  	.err_handler	=	ah6_err,
e924d2d68   Steffen Klassert   ah6: Use the IPse...
726
  	.priority	=	0,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
727
728
729
730
731
  };
  
  static int __init ah6_init(void)
  {
  	if (xfrm_register_type(&ah6_type, AF_INET6) < 0) {
f32138319   Joe Perches   net: ipv6: Standa...
732
733
  		pr_info("%s: can't add xfrm type
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
735
  		return -EAGAIN;
  	}
e924d2d68   Steffen Klassert   ah6: Use the IPse...
736
  	if (xfrm6_protocol_register(&ah6_protocol, IPPROTO_AH) < 0) {
f32138319   Joe Perches   net: ipv6: Standa...
737
738
  		pr_info("%s: can't add protocol
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739
740
741
742
743
744
745
746
747
  		xfrm_unregister_type(&ah6_type, AF_INET6);
  		return -EAGAIN;
  	}
  
  	return 0;
  }
  
  static void __exit ah6_fini(void)
  {
e924d2d68   Steffen Klassert   ah6: Use the IPse...
748
  	if (xfrm6_protocol_deregister(&ah6_protocol, IPPROTO_AH) < 0)
f32138319   Joe Perches   net: ipv6: Standa...
749
750
  		pr_info("%s: can't remove protocol
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
751

4f518e802   Florian Westphal   xfrm: remove type...
752
  	xfrm_unregister_type(&ah6_type, AF_INET6);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
753
754
755
756
757
758
  }
  
  module_init(ah6_init);
  module_exit(ah6_fini);
  
  MODULE_LICENSE("GPL");
d3d6dd3ad   Masahide NAKAMURA   [XFRM]: Add modul...
759
  MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_AH);