Blame view

net/ipv6/ah6.c 18.5 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
  /*
   * Copyright (C)2002 USAGI/WIDE Project
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
3
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
6
7
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
8
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
13
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
   * You should have received a copy of the GNU General Public License
a99421d9b   Jeff Kirsher   ipv4/ipv6: Fix FS...
15
   * along with this program; if not, see <http://www.gnu.org/licenses/>.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
18
   *
   * Authors
   *
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
19
   *	Mitsuru KANDA @USAGI       : IPv6 Support
67ba4152e   Ian Morris   ipv6: White-space...
20
21
   *	Kazunori MIYAZAWA @USAGI   :
   *	Kunihiro Ishiguro <kunihiro@ipinfusion.com>
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
22
   *
67ba4152e   Ian Morris   ipv6: White-space...
23
   *	This file is derived from net/ipv4/ah.c.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
   */
f32138319   Joe Perches   net: ipv6: Standa...
25
  #define pr_fmt(fmt) "IPv6: " fmt
67df58a3e   Sabrina Dubroca   ah: use crypto_me...
26
  #include <crypto/algapi.h>
8631e9bdf   Steffen Klassert   ah6: convert to a...
27
  #include <crypto/hash.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
29
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
33
34
  #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...
35
  #include <linux/scatterlist.h>
81aded246   David S. Miller   ipv6: Handle PMTU...
36
  #include <net/ip6_route.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
  #include <net/icmp.h>
  #include <net/ipv6.h>
14c850212   Arnaldo Carvalho de Melo   [INET_SOCK]: Move...
39
  #include <net/protocol.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  #include <net/xfrm.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41

8631e9bdf   Steffen Klassert   ah6: convert to a...
42
43
44
  #define IPV6HDR_BASELEN 8
  
  struct tmp_ext {
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
45
  #if IS_ENABLED(CONFIG_IPV6_MIP6)
8631e9bdf   Steffen Klassert   ah6: convert to a...
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
102
103
104
105
106
107
108
109
110
111
112
113
  		struct in6_addr saddr;
  #endif
  		struct in6_addr daddr;
  		char hdrs[0];
  };
  
  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 ...
114
  static bool zero_out_mutable_opts(struct ipv6_opt_hdr *opthdr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
116
117
118
119
120
121
122
123
124
125
126
  {
  	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...
127
  		case IPV6_TLV_PAD1:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
129
130
  			optlen = 1;
  			break;
  		default:
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
131
  			if (len < 2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
133
134
135
136
137
138
139
140
141
142
143
144
  				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 ...
145
  		return true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
147
  
  bad:
a50feda54   Eric Dumazet   ipv6: bool/const ...
148
  	return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
  }
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
150
  #if IS_ENABLED(CONFIG_IPV6_MIP6)
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
  /**
   *	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...
169
  		case IPV6_TLV_PAD1:
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
  			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_...
189
190
191
  					net_warn_ratelimited("destopt hao: invalid header length: %u
  ",
  							     hao->length);
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
192
193
  					goto bad;
  				}
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
194
195
196
  				final_addr = hao->addr;
  				hao->addr = iph->saddr;
  				iph->saddr = final_addr;
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
197
198
199
200
201
202
203
  			}
  			break;
  		}
  
  		off += optlen;
  		len -= optlen;
  	}
e731c248b   YOSHIFUJI Hideaki   [IPV6] MIP6: Seve...
204
  	/* Note: ok if len == 0 */
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
205
206
207
  bad:
  	return;
  }
136ebf08b   Masahide NAKAMURA   [IPV6] MIP6: Kill...
208
209
  #else
  static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *destopt) {}
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
210
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
  /**
   *	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...
229
  	rthdr->segments_left = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
232
233
234
235
236
237
238
239
240
  
  	/* 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_...
241
  	final_addr = addrs[segments - 1];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
244
  
  	addrs += segments - segments_left;
  	memmove(addrs + 1, addrs, (segments_left - 1) * sizeof(*addrs));
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
245
246
  	addrs[0] = iph->daddr;
  	iph->daddr = final_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
  }
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
248
  static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
251
252
253
254
255
256
257
258
259
260
261
262
  {
  	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...
263
264
265
  		case NEXTHDR_DEST:
  			if (dir == XFRM_POLICY_OUT)
  				ipv6_rearrange_destopt(iph, exthdr.opth);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
  		case NEXTHDR_HOP:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
  			if (!zero_out_mutable_opts(exthdr.opth)) {
ba7a46f16   Joe Perches   net: Convert LIMI...
268
269
270
271
  				net_dbg_ratelimited("overrun %sopts
  ",
  						    nexthdr == NEXTHDR_HOP ?
  						    "hop" : "dest");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
273
274
275
276
277
278
  				return -EINVAL;
  			}
  			break;
  
  		case NEXTHDR_ROUTING:
  			ipv6_rearrange_rthdr(iph, exthdr.rth);
  			break;
67ba4152e   Ian Morris   ipv6: White-space...
279
  		default:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
281
282
283
284
285
286
287
288
  			return 0;
  		}
  
  		nexthdr = exthdr.opth->nexthdr;
  		exthdr.raw += ipv6_optlen(exthdr.opth);
  	}
  
  	return 0;
  }
8631e9bdf   Steffen Klassert   ah6: convert to a...
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
  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...
313
  #if IS_ENABLED(CONFIG_IPV6_MIP6)
8631e9bdf   Steffen Klassert   ah6: convert to a...
314
315
316
317
318
  		memcpy(&top_iph->saddr, iph_ext, extlen);
  #else
  		memcpy(&top_iph->daddr, iph_ext, extlen);
  #endif
  	}
8631e9bdf   Steffen Klassert   ah6: convert to a...
319
320
321
  	kfree(AH_SKB_CB(skb)->tmp);
  	xfrm_output_resume(skb, err);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
324
  static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
  {
  	int err;
8631e9bdf   Steffen Klassert   ah6: convert to a...
325
  	int nfrags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326
  	int extlen;
8631e9bdf   Steffen Klassert   ah6: convert to a...
327
328
329
330
331
332
333
  	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
334
335
336
  	struct ipv6hdr *top_iph;
  	struct ip_auth_hdr *ah;
  	struct ah_data *ahp;
8631e9bdf   Steffen Klassert   ah6: convert to a...
337
  	struct tmp_ext *iph_ext;
26dd70c3f   Fan Du   {IPv6,xfrm} Add E...
338
339
340
341
  	int seqhi_len = 0;
  	__be32 *seqhi;
  	int sglists = 0;
  	struct scatterlist *seqhisg;
8631e9bdf   Steffen Klassert   ah6: convert to a...
342
343
344
  
  	ahp = x->data;
  	ahash = ahp->ahash;
e5d08d718   Ian Morris   ipv6: coding styl...
345
346
  	err = skb_cow_data(skb, 0, &trailer);
  	if (err < 0)
8631e9bdf   Steffen Klassert   ah6: convert to a...
347
348
  		goto out;
  	nfrags = err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349

7b277b1a5   Herbert Xu   [IPSEC]: Set skb-...
350
  	skb_push(skb, -skb_network_offset(skb));
8631e9bdf   Steffen Klassert   ah6: convert to a...
351
352
353
  	extlen = skb_network_header_len(skb) - sizeof(struct ipv6hdr);
  	if (extlen)
  		extlen += sizeof(*iph_ext);
26dd70c3f   Fan Du   {IPv6,xfrm} Add E...
354
355
356
357
  	if (x->props.flags & XFRM_STATE_ESN) {
  		sglists = 1;
  		seqhi_len = sizeof(*seqhi);
  	}
8631e9bdf   Steffen Klassert   ah6: convert to a...
358
  	err = -ENOMEM;
26dd70c3f   Fan Du   {IPv6,xfrm} Add E...
359
360
  	iph_base = ah_alloc_tmp(ahash, nfrags + sglists, IPV6HDR_BASELEN +
  				extlen + seqhi_len);
8631e9bdf   Steffen Klassert   ah6: convert to a...
361
362
363
364
  	if (!iph_base)
  		goto out;
  
  	iph_ext = ah_tmp_ext(iph_base);
26dd70c3f   Fan Du   {IPv6,xfrm} Add E...
365
366
  	seqhi = (__be32 *)((char *)iph_ext + extlen);
  	icv = ah_tmp_icv(ahash, seqhi, seqhi_len);
8631e9bdf   Steffen Klassert   ah6: convert to a...
367
368
  	req = ah_tmp_req(ahash, icv);
  	sg = ah_req_sg(ahash, req);
26dd70c3f   Fan Du   {IPv6,xfrm} Add E...
369
  	seqhisg = sg + nfrags;
8631e9bdf   Steffen Klassert   ah6: convert to a...
370
371
372
  
  	ah = ip_auth_hdr(skb);
  	memset(ah->auth_data, 0, ahp->icv_trunc_len);
007f0211a   Herbert Xu   [IPSEC]: Store IP...
373
  	top_iph = ipv6_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
  	top_iph->payload_len = htons(skb->len - sizeof(*top_iph));
007f0211a   Herbert Xu   [IPSEC]: Store IP...
375
376
  	nexthdr = *skb_mac_header(skb);
  	*skb_mac_header(skb) = IPPROTO_AH;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377
378
379
380
  
  	/* 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...
381
  	memcpy(iph_base, top_iph, IPV6HDR_BASELEN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
  	if (extlen) {
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
384
  #if IS_ENABLED(CONFIG_IPV6_MIP6)
8631e9bdf   Steffen Klassert   ah6: convert to a...
385
  		memcpy(iph_ext, &top_iph->saddr, extlen);
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
386
  #else
8631e9bdf   Steffen Klassert   ah6: convert to a...
387
  		memcpy(iph_ext, &top_iph->daddr, extlen);
e731c248b   YOSHIFUJI Hideaki   [IPV6] MIP6: Seve...
388
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
  		err = ipv6_clear_mutable_options(top_iph,
8631e9bdf   Steffen Klassert   ah6: convert to a...
390
  						 extlen - sizeof(*iph_ext) +
e731c248b   YOSHIFUJI Hideaki   [IPV6] MIP6: Seve...
391
392
  						 sizeof(*top_iph),
  						 XFRM_POLICY_OUT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
  		if (err)
8631e9bdf   Steffen Klassert   ah6: convert to a...
394
  			goto out_free;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
397
398
399
400
401
402
  	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 ...
403
  	ah->hdrlen  = (XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len) >> 2) - 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
405
406
  
  	ah->reserved = 0;
  	ah->spi = x->id.spi;
1ce3644ad   Steffen Klassert   xfrm: Use separat...
407
  	ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low);
b7c6538cd   Herbert Xu   [IPSEC]: Move sta...
408

26dd70c3f   Fan Du   {IPv6,xfrm} Add E...
409
  	sg_init_table(sg, nfrags + sglists);
3f2977072   Jason A. Donenfeld   ipsec: check retu...
410
411
412
  	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
413

26dd70c3f   Fan Du   {IPv6,xfrm} Add E...
414
415
416
417
418
419
  	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...
420
421
422
  	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
423

8631e9bdf   Steffen Klassert   ah6: convert to a...
424
425
426
427
428
429
430
431
432
433
434
435
436
437
  	err = crypto_ahash_digest(req);
  	if (err) {
  		if (err == -EINPROGRESS)
  			goto out;
  
  		if (err == -EBUSY)
  			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...
438
  #if IS_ENABLED(CONFIG_IPV6_MIP6)
8631e9bdf   Steffen Klassert   ah6: convert to a...
439
  		memcpy(&top_iph->saddr, iph_ext, extlen);
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
440
  #else
8631e9bdf   Steffen Klassert   ah6: convert to a...
441
  		memcpy(&top_iph->daddr, iph_ext, extlen);
27637df92   Masahide NAKAMURA   [IPV6] IPSEC: Sup...
442
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
  	}
8631e9bdf   Steffen Klassert   ah6: convert to a...
444
445
446
  out_free:
  	kfree(iph_base);
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
448
  	return err;
  }
8631e9bdf   Steffen Klassert   ah6: convert to a...
449
450
451
452
453
454
455
456
457
458
459
  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);
  	int ah_hlen = (ah->hdrlen + 2) << 2;
726282aa6   Gilad Ben-Yossef   IPsec: do not ign...
460
461
  	if (err)
  		goto out;
8631e9bdf   Steffen Klassert   ah6: convert to a...
462
463
464
  	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...
465
  	err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
8631e9bdf   Steffen Klassert   ah6: convert to a...
466
467
  	if (err)
  		goto out;
b7ea81a58   Nick Bowler   ah: Read nexthdr ...
468
  	err = ah->nexthdr;
8631e9bdf   Steffen Klassert   ah6: convert to a...
469
470
471
  	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...
472
473
474
475
  	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...
476
477
478
479
  out:
  	kfree(AH_SKB_CB(skb)->tmp);
  	xfrm_input_resume(skb, err);
  }
e695633e2   Herbert Xu   [IPSEC]: Kill unu...
480
  static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
482
483
484
485
486
487
488
  {
  	/*
  	 * 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...
489
490
  	 * 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
491
  	 * If destination header following AH exists, copy it into after [Ext2].
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
492
  	 *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
494
495
  	 * |<>|[IPv6][Ext1][Ext2][Dest][Payload]
  	 * There is offset of AH before IPv6 header after the process.
  	 */
8631e9bdf   Steffen Klassert   ah6: convert to a...
496
497
498
499
500
501
502
  	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 ...
503
  	struct ip_auth_hdr *ah;
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
504
  	struct ipv6hdr *ip6h;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
505
  	struct ah_data *ahp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506
507
508
  	u16 hdr_len;
  	u16 ah_hlen;
  	int nexthdr;
8631e9bdf   Steffen Klassert   ah6: convert to a...
509
510
  	int nfrags;
  	int err = -ENOMEM;
8d6da6f32   Fan Du   {IPv6,xfrm} Add E...
511
512
513
514
  	int seqhi_len = 0;
  	__be32 *seqhi;
  	int sglists = 0;
  	struct scatterlist *seqhisg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
516
517
518
519
520
  
  	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...
521
  	if (skb_unclone(skb, GFP_ATOMIC))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
  		goto out;
7aa68cb90   Herbert Xu   [IPSEC]: Move ip_...
523
  	skb->ip_summed = CHECKSUM_NONE;
8631e9bdf   Steffen Klassert   ah6: convert to a...
524
  	hdr_len = skb_network_header_len(skb);
87bdc48d3   Herbert Xu   [IPSEC]: Get rid ...
525
  	ah = (struct ip_auth_hdr *)skb->data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526
  	ahp = x->data;
8631e9bdf   Steffen Klassert   ah6: convert to a...
527
  	ahash = ahp->ahash;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
528
529
  	nexthdr = ah->nexthdr;
  	ah_hlen = (ah->hdrlen + 2) << 2;
87bdc48d3   Herbert Xu   [IPSEC]: Get rid ...
530
531
  	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...
532
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
534
535
  
  	if (!pskb_may_pull(skb, ah_hlen))
  		goto out;
e5d08d718   Ian Morris   ipv6: coding styl...
536
537
  	err = skb_cow_data(skb, 0, &trailer);
  	if (err < 0)
8631e9bdf   Steffen Klassert   ah6: convert to a...
538
539
  		goto out;
  	nfrags = err;
4b0ef1f22   Dang Hongwu   ah: reload pointe...
540
541
542
543
  	ah = (struct ip_auth_hdr *)skb->data;
  	ip6h = ipv6_hdr(skb);
  
  	skb_push(skb, hdr_len);
8d6da6f32   Fan Du   {IPv6,xfrm} Add E...
544
545
546
547
548
549
550
  	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...
551
552
  	if (!work_iph) {
  		err = -ENOMEM;
8631e9bdf   Steffen Klassert   ah6: convert to a...
553
  		goto out;
25105051f   Julia Lawall   ah6: fix error re...
554
  	}
8631e9bdf   Steffen Klassert   ah6: convert to a...
555

8d6da6f32   Fan Du   {IPv6,xfrm} Add E...
556
557
558
  	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...
559
560
  	req = ah_tmp_req(ahash, icv);
  	sg = ah_req_sg(ahash, req);
8d6da6f32   Fan Du   {IPv6,xfrm} Add E...
561
  	seqhisg = sg + nfrags;
8631e9bdf   Steffen Klassert   ah6: convert to a...
562
563
564
565
  
  	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);
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
566
  	if (ipv6_clear_mutable_options(ip6h, hdr_len, XFRM_POLICY_IN))
8631e9bdf   Steffen Klassert   ah6: convert to a...
567
  		goto out_free;
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
568
569
570
571
572
  	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
573

8d6da6f32   Fan Du   {IPv6,xfrm} Add E...
574
  	sg_init_table(sg, nfrags + sglists);
3f2977072   Jason A. Donenfeld   ipsec: check retu...
575
576
577
  	err = skb_to_sgvec_nomark(skb, sg, 0, skb->len);
  	if (unlikely(err < 0))
  		goto out_free;
8d6da6f32   Fan Du   {IPv6,xfrm} Add E...
578
579
580
581
582
583
  
  	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
584

8d6da6f32   Fan Du   {IPv6,xfrm} Add E...
585
  	ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len);
8631e9bdf   Steffen Klassert   ah6: convert to a...
586
587
588
589
590
591
592
593
  	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...
594
  		goto out_free;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595
  	}
0ebea8ef3   Herbert Xu   [IPSEC]: Move sta...
596

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

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

a9403f8ae   Li RongQing   ah6/esp6: set tra...
605
606
607
608
  	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...
609
  	err = nexthdr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610

8631e9bdf   Steffen Klassert   ah6: convert to a...
611
612
  out_free:
  	kfree(work_iph);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
  out:
07d4ee583   Herbert Xu   [IPSEC]: Use HMAC...
614
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615
  }
e924d2d68   Steffen Klassert   ah6: Use the IPse...
616
617
  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
618
  {
4fb236bac   Alexey Dobriyan   netns xfrm: AH/ES...
619
  	struct net *net = dev_net(skb->dev);
67ba4152e   Ian Morris   ipv6: White-space...
620
621
  	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
622
  	struct xfrm_state *x;
b3b2b9e19   Steffen Klassert   ipsec: Don't upda...
623
  	if (type != ICMPV6_PKT_TOOBIG &&
ec18d9a26   David S. Miller   ipv6: Add redirec...
624
  	    type != NDISC_REDIRECT)
e924d2d68   Steffen Klassert   ah6: Use the IPse...
625
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626

bd55775c8   Jamal Hadi Salim   xfrm: SA lookups ...
627
  	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
628
  	if (!x)
e924d2d68   Steffen Klassert   ah6: Use the IPse...
629
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
630

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661
662
663
664
  	/*
  	 * 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...
665
  	 * after a successful crypto_alloc_hash().
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
668
669
670
  	 */
  	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...
671
  	    crypto_ahash_digestsize(ahash)) {
f32138319   Joe Perches   net: ipv6: Standa...
672
673
674
675
  		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
676
677
  		goto error;
  	}
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
678

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

87bdc48d3   Herbert Xu   [IPSEC]: Get rid ...
682
683
  	x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) +
  					  ahp->icv_trunc_len);
ca68145f1   Herbert Xu   [IPSEC]: Disallow...
684
685
686
687
688
  	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
689
  		x->props.header_len += sizeof(struct ipv6hdr);
ea2c47b42   Masahide NAKAMURA   [IPSEC] IPV6: Fix...
690
  		break;
ca68145f1   Herbert Xu   [IPSEC]: Disallow...
691
692
693
  	default:
  		goto error;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694
695
696
697
698
699
  	x->data = ahp;
  
  	return 0;
  
  error:
  	if (ahp) {
8631e9bdf   Steffen Klassert   ah6: convert to a...
700
  		crypto_free_ahash(ahp->ahash);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701
702
703
704
705
706
707
708
709
710
711
  		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...
712
  	crypto_free_ahash(ahp->ahash);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
713
714
  	kfree(ahp);
  }
e924d2d68   Steffen Klassert   ah6: Use the IPse...
715
716
717
718
  static int ah6_rcv_cb(struct sk_buff *skb, int err)
  {
  	return 0;
  }
cc24becae   Ian Morris   ipv6: White-space...
719
  static const struct xfrm_type ah6_type = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
720
721
  	.description	= "AH6",
  	.owner		= THIS_MODULE,
cc24becae   Ian Morris   ipv6: White-space...
722
  	.proto		= IPPROTO_AH,
436a0a402   Herbert Xu   [IPSEC]: Move out...
723
  	.flags		= XFRM_TYPE_REPLAY_PROT,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
724
725
726
  	.init_state	= ah6_init_state,
  	.destructor	= ah6_destroy,
  	.input		= ah6_input,
aee5adb43   Masahide NAKAMURA   [XFRM] STATE: Add...
727
728
  	.output		= ah6_output,
  	.hdr_offset	= xfrm6_find_1stfragopt,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
729
  };
e924d2d68   Steffen Klassert   ah6: Use the IPse...
730
  static struct xfrm6_protocol ah6_protocol = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731
  	.handler	=	xfrm6_rcv,
e924d2d68   Steffen Klassert   ah6: Use the IPse...
732
  	.cb_handler	=	ah6_rcv_cb,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
733
  	.err_handler	=	ah6_err,
e924d2d68   Steffen Klassert   ah6: Use the IPse...
734
  	.priority	=	0,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
735
736
737
738
739
  };
  
  static int __init ah6_init(void)
  {
  	if (xfrm_register_type(&ah6_type, AF_INET6) < 0) {
f32138319   Joe Perches   net: ipv6: Standa...
740
741
  		pr_info("%s: can't add xfrm type
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
743
  		return -EAGAIN;
  	}
e924d2d68   Steffen Klassert   ah6: Use the IPse...
744
  	if (xfrm6_protocol_register(&ah6_protocol, IPPROTO_AH) < 0) {
f32138319   Joe Perches   net: ipv6: Standa...
745
746
  		pr_info("%s: can't add protocol
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
747
748
749
750
751
752
753
754
755
  		xfrm_unregister_type(&ah6_type, AF_INET6);
  		return -EAGAIN;
  	}
  
  	return 0;
  }
  
  static void __exit ah6_fini(void)
  {
e924d2d68   Steffen Klassert   ah6: Use the IPse...
756
  	if (xfrm6_protocol_deregister(&ah6_protocol, IPPROTO_AH) < 0)
f32138319   Joe Perches   net: ipv6: Standa...
757
758
  		pr_info("%s: can't remove protocol
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
759
760
  
  	if (xfrm_unregister_type(&ah6_type, AF_INET6) < 0)
f32138319   Joe Perches   net: ipv6: Standa...
761
762
  		pr_info("%s: can't remove xfrm type
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763
764
765
766
767
768
769
  
  }
  
  module_init(ah6_init);
  module_exit(ah6_fini);
  
  MODULE_LICENSE("GPL");
d3d6dd3ad   Masahide NAKAMURA   [XFRM]: Add modul...
770
  MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_AH);