xform_ipip.c revision 1.47 1 /* $NetBSD: xform_ipip.c,v 1.47 2017/04/18 05:26:42 ozaki-r Exp $ */
2 /* $FreeBSD: src/sys/netipsec/xform_ipip.c,v 1.3.2.1 2003/01/24 05:11:36 sam Exp $ */
3 /* $OpenBSD: ip_ipip.c,v 1.25 2002/06/10 18:04:55 itojun Exp $ */
4
5 /*
6 * The authors of this code are John Ioannidis (ji (at) tla.org),
7 * Angelos D. Keromytis (kermit (at) csd.uch.gr) and
8 * Niels Provos (provos (at) physnet.uni-hamburg.de).
9 *
10 * The original version of this code was written by John Ioannidis
11 * for BSD/OS in Athens, Greece, in November 1995.
12 *
13 * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
14 * by Angelos D. Keromytis.
15 *
16 * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
17 * and Niels Provos.
18 *
19 * Additional features in 1999 by Angelos D. Keromytis.
20 *
21 * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
22 * Angelos D. Keromytis and Niels Provos.
23 * Copyright (c) 2001, Angelos D. Keromytis.
24 *
25 * Permission to use, copy, and modify this software with or without fee
26 * is hereby granted, provided that this entire notice is included in
27 * all copies of any software which is or includes a copy or
28 * modification of this software.
29 * You may use this code under the GNU public license if you so wish. Please
30 * contribute changes back to the authors under this freer than GPL license
31 * so that we may further the use of strong encryption without limitations to
32 * all.
33 *
34 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
35 * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
36 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
37 * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
38 * PURPOSE.
39 */
40
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: xform_ipip.c,v 1.47 2017/04/18 05:26:42 ozaki-r Exp $");
43
44 /*
45 * IP-inside-IP processing
46 */
47 #if defined(_KERNEL_OPT)
48 #include "opt_inet.h"
49 #endif
50
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/mbuf.h>
54 #include <sys/socket.h>
55 #include <sys/kernel.h>
56 #include <sys/protosw.h>
57 #include <sys/sysctl.h>
58
59 #include <net/if.h>
60 #include <net/route.h>
61 #include <net/netisr.h>
62
63 #include <netinet/in.h>
64 #include <netinet/in_systm.h>
65 #include <netinet/in_var.h>
66 #include <netinet/ip.h>
67 #include <netinet/ip_ecn.h>
68 #include <netinet/ip_var.h>
69 #include <netinet/ip_encap.h>
70
71 #include <netipsec/ipsec.h>
72 #include <netipsec/ipsec_private.h>
73 #include <netipsec/xform.h>
74
75 #include <netipsec/ipip_var.h>
76
77 #ifdef MROUTING
78 #include <netinet/ip_mroute.h>
79 #endif
80
81 #ifdef INET6
82 #include <netinet/ip6.h>
83 #include <netipsec/ipsec6.h>
84 #include <netinet6/in6_var.h>
85 #include <netinet6/ip6protosw.h>
86 #endif
87
88 #include <netipsec/key.h>
89 #include <netipsec/key_debug.h>
90 #include <netipsec/ipsec_osdep.h>
91
92 typedef void pr_in_input_t (struct mbuf *m, ...);
93
94 /*
95 * We can control the acceptance of IP4 packets by altering the sysctl
96 * net.inet.ipip.allow value. Zero means drop them, all else is acceptance.
97 */
98 int ipip_allow = 0;
99
100 percpu_t *ipipstat_percpu;
101
102 #ifdef SYSCTL_DECL
103 SYSCTL_DECL(_net_inet_ipip);
104
105 SYSCTL_INT(_net_inet_ipip, OID_AUTO,
106 ipip_allow, CTLFLAG_RW, &ipip_allow, 0, "");
107 SYSCTL_STRUCT(_net_inet_ipip, IPSECCTL_STATS,
108 stats, CTLFLAG_RD, &ipipstat, ipipstat, "");
109
110 #endif
111
112 void ipe4_attach(void);
113
114
115 /* XXX IPCOMP */
116 #define M_IPSEC (M_AUTHIPHDR|M_AUTHIPDGM|M_DECRYPTED)
117
118 static void _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp);
119
120 #ifdef INET6
121 /*
122 * Really only a wrapper for ipip_input(), for use with IPv6.
123 */
124 int
125 ip4_input6(struct mbuf **m, int *offp, int proto)
126 {
127 #if 0
128 /* If we do not accept IP-in-IP explicitly, drop. */
129 if (!ipip_allow && ((*m)->m_flags & M_IPSEC) == 0) {
130 DPRINTF(("%s: dropped due to policy\n", __func__));
131 IPIP_STATINC(IPIP_STAT_PDROPS);
132 m_freem(*m);
133 return IPPROTO_DONE;
134 }
135 #endif
136 _ipip_input(*m, *offp, NULL);
137 return IPPROTO_DONE;
138 }
139 #endif /* INET6 */
140
141 #ifdef INET
142 /*
143 * Really only a wrapper for ipip_input(), for use with IPv4.
144 */
145 void
146 ip4_input(struct mbuf *m, int off, int proto)
147 {
148
149 #if 0
150 /* If we do not accept IP-in-IP explicitly, drop. */
151 if (!ipip_allow && (m->m_flags & M_IPSEC) == 0) {
152 DPRINTF(("%s: dropped due to policy\n", __func__));
153 IPIP_STATINC(IPIP_STAT_PDROPS);
154 m_freem(m);
155 return;
156 }
157 #endif
158
159 _ipip_input(m, off, NULL);
160 }
161 #endif /* INET */
162
163 /*
164 * ipip_input gets called when we receive an IP{46} encapsulated packet,
165 * either because we got it at a real interface, or because AH or ESP
166 * were being used in tunnel mode (in which case the rcvif element will
167 * contain the address of the encX interface associated with the tunnel.
168 */
169
170 static void
171 _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
172 {
173 register struct sockaddr_in *sin;
174 register struct ifnet *ifp;
175 register struct ifaddr *ifa;
176 pktqueue_t *pktq = NULL;
177 struct ip *ipo;
178 #ifdef INET6
179 register struct sockaddr_in6 *sin6;
180 struct ip6_hdr *ip6 = NULL;
181 uint8_t itos;
182 #endif
183 uint8_t otos;
184 uint8_t v;
185 int hlen;
186
187 IPIP_STATINC(IPIP_STAT_IPACKETS);
188
189 m_copydata(m, 0, 1, &v);
190
191 switch (v >> 4) {
192 #ifdef INET
193 case 4:
194 hlen = sizeof(struct ip);
195 break;
196 #endif /* INET */
197 #ifdef INET6
198 case 6:
199 hlen = sizeof(struct ip6_hdr);
200 break;
201 #endif
202 default:
203 DPRINTF(("%s: bad protocol version 0x%x (%u) "
204 "for outer header\n", __func__, v, v>>4));
205 IPIP_STATINC(IPIP_STAT_FAMILY);
206 m_freem(m);
207 return /* EAFNOSUPPORT */;
208 }
209
210 /* Bring the IP header in the first mbuf, if not there already */
211 if (m->m_len < hlen) {
212 if ((m = m_pullup(m, hlen)) == NULL) {
213 DPRINTF(("%s: m_pullup (1) failed\n", __func__));
214 IPIP_STATINC(IPIP_STAT_HDROPS);
215 return;
216 }
217 }
218
219 ipo = mtod(m, struct ip *);
220
221 #ifdef MROUTING
222 if (ipo->ip_v == IPVERSION && ipo->ip_p == IPPROTO_IPV4) {
223 if (IN_MULTICAST(((struct ip *)((char *) ipo + iphlen))->ip_dst.s_addr)) {
224 ipip_mroute_input (m, iphlen);
225 return;
226 }
227 }
228 #endif /* MROUTING */
229
230 /* Keep outer ecn field. */
231 switch (v >> 4) {
232 #ifdef INET
233 case 4:
234 otos = ipo->ip_tos;
235 break;
236 #endif /* INET */
237 #ifdef INET6
238 case 6:
239 otos = (ntohl(mtod(m, struct ip6_hdr *)->ip6_flow) >> 20) & 0xff;
240 break;
241 #endif
242 default:
243 panic("%s: unknown ip version %u (outer)", __func__, v >> 4);
244 }
245
246 /* Remove outer IP header */
247 m_adj(m, iphlen);
248
249 /* Sanity check */
250 if (m->m_pkthdr.len < sizeof(struct ip)) {
251 IPIP_STATINC(IPIP_STAT_HDROPS);
252 m_freem(m);
253 return;
254 }
255
256 m_copydata(m, 0, 1, &v);
257
258 switch (v >> 4) {
259 #ifdef INET
260 case 4:
261 hlen = sizeof(struct ip);
262 break;
263 #endif /* INET */
264
265 #ifdef INET6
266 case 6:
267 hlen = sizeof(struct ip6_hdr);
268 break;
269 #endif
270 default:
271 DPRINTF(("%s: bad protocol version %#x (%u) "
272 "for inner header\n", __func__, v, v >> 4));
273 IPIP_STATINC(IPIP_STAT_FAMILY);
274 m_freem(m);
275 return; /* EAFNOSUPPORT */
276 }
277
278 /*
279 * Bring the inner IP header in the first mbuf, if not there already.
280 */
281 if (m->m_len < hlen) {
282 if ((m = m_pullup(m, hlen)) == NULL) {
283 DPRINTF(("%s: m_pullup (2) failed\n", __func__));
284 IPIP_STATINC(IPIP_STAT_HDROPS);
285 return;
286 }
287 }
288
289 /*
290 * RFC 1853 specifies that the inner TTL should not be touched on
291 * decapsulation. There's no reason this comment should be here, but
292 * this is as good as any a position.
293 */
294
295 /* Some sanity checks in the inner IP header */
296 switch (v >> 4) {
297 #ifdef INET
298 case 4:
299 ipo = mtod(m, struct ip *);
300 ip_ecn_egress(ip4_ipsec_ecn, &otos, &ipo->ip_tos);
301 break;
302 #endif /* INET */
303 #ifdef INET6
304 case 6:
305 ip6 = (struct ip6_hdr *) ipo;
306 itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
307 ip_ecn_egress(ip6_ipsec_ecn, &otos, &itos);
308 ip6->ip6_flow &= ~htonl(0xff << 20);
309 ip6->ip6_flow |= htonl((uint32_t) itos << 20);
310 break;
311 #endif
312 default:
313 panic("%s: unknown ip version %u (inner)", __func__, v>>4);
314 }
315
316 /* Check for local address spoofing. */
317 if ((m_get_rcvif_NOMPSAFE(m) == NULL ||
318 !(m_get_rcvif_NOMPSAFE(m)->if_flags & IFF_LOOPBACK)) &&
319 ipip_allow != 2) {
320 int s = pserialize_read_enter();
321 IFNET_READER_FOREACH(ifp) {
322 IFADDR_READER_FOREACH(ifa, ifp) {
323 #ifdef INET
324 if (ipo) {
325 if (ifa->ifa_addr->sa_family !=
326 AF_INET)
327 continue;
328
329 sin = (struct sockaddr_in *) ifa->ifa_addr;
330
331 if (sin->sin_addr.s_addr ==
332 ipo->ip_src.s_addr) {
333 pserialize_read_exit(s);
334 IPIP_STATINC(IPIP_STAT_SPOOF);
335 m_freem(m);
336 return;
337 }
338 }
339 #endif /* INET */
340
341 #ifdef INET6
342 if (ip6) {
343 if (ifa->ifa_addr->sa_family !=
344 AF_INET6)
345 continue;
346
347 sin6 = (struct sockaddr_in6 *) ifa->ifa_addr;
348
349 if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_src)) {
350 pserialize_read_exit(s);
351 IPIP_STATINC(IPIP_STAT_SPOOF);
352 m_freem(m);
353 return;
354 }
355
356 }
357 #endif /* INET6 */
358 }
359 }
360 pserialize_read_exit(s);
361 }
362
363 /* Statistics */
364 IPIP_STATADD(IPIP_STAT_IBYTES, m->m_pkthdr.len - iphlen);
365
366 /*
367 * Interface pointer stays the same; if no IPsec processing has
368 * been done (or will be done), this will point to a normal
369 * interface. Otherwise, it'll point to an enc interface, which
370 * will allow a packet filter to distinguish between secure and
371 * untrusted packets.
372 */
373
374 switch (v >> 4) {
375 #ifdef INET
376 case 4:
377 pktq = ip_pktq;
378 break;
379 #endif
380 #ifdef INET6
381 case 6:
382 pktq = ip6_pktq;
383 break;
384 #endif
385 default:
386 panic("%s: should never reach here", __func__);
387 }
388
389 int s = splnet();
390 if (__predict_false(!pktq_enqueue(pktq, m, 0))) {
391 IPIP_STATINC(IPIP_STAT_QFULL);
392 m_freem(m);
393 }
394 splx(s);
395 }
396
397 int
398 ipip_output(
399 struct mbuf *m,
400 struct ipsecrequest *isr,
401 struct mbuf **mp,
402 int skip,
403 int protoff
404 )
405 {
406 const struct secasvar *sav;
407 uint8_t tp, otos;
408 struct secasindex *saidx;
409 int error;
410 #ifdef INET
411 uint8_t itos;
412 struct ip *ipo;
413 #endif /* INET */
414 #ifdef INET6
415 struct ip6_hdr *ip6, *ip6o;
416 #endif /* INET6 */
417
418 IPSEC_SPLASSERT_SOFTNET(__func__);
419
420 KASSERT(isr->sav != NULL);
421 sav = isr->sav;
422 KASSERT(sav->sah != NULL);
423
424 /* XXX Deal with empty TDB source/destination addresses. */
425
426 m_copydata(m, 0, 1, &tp);
427 tp = (tp >> 4) & 0xff; /* Get the IP version number. */
428
429 saidx = &sav->sah->saidx;
430 switch (saidx->dst.sa.sa_family) {
431 #ifdef INET
432 case AF_INET:
433 if (saidx->src.sa.sa_family != AF_INET ||
434 saidx->src.sin.sin_addr.s_addr == INADDR_ANY ||
435 saidx->dst.sin.sin_addr.s_addr == INADDR_ANY) {
436 DPRINTF(("%s: unspecified tunnel endpoint "
437 "address in SA %s/%08lx\n", __func__,
438 ipsec_address(&saidx->dst),
439 (u_long) ntohl(sav->spi)));
440 IPIP_STATINC(IPIP_STAT_UNSPEC);
441 error = EINVAL;
442 goto bad;
443 }
444
445 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
446 if (m == 0) {
447 DPRINTF(("%s: M_PREPEND failed\n", __func__));
448 IPIP_STATINC(IPIP_STAT_HDROPS);
449 error = ENOBUFS;
450 goto bad;
451 }
452
453 ipo = mtod(m, struct ip *);
454
455 ipo->ip_v = IPVERSION;
456 ipo->ip_hl = 5;
457 ipo->ip_len = htons(m->m_pkthdr.len);
458 ipo->ip_ttl = ip_defttl;
459 ipo->ip_sum = 0;
460 ipo->ip_src = saidx->src.sin.sin_addr;
461 ipo->ip_dst = saidx->dst.sin.sin_addr;
462 ipo->ip_id = ip_newid(NULL);
463
464 /* If the inner protocol is IP... */
465 if (tp == IPVERSION) {
466 /* Save ECN notification */
467 m_copydata(m, sizeof(struct ip) +
468 offsetof(struct ip, ip_tos),
469 sizeof(uint8_t), &itos);
470
471 ipo->ip_p = IPPROTO_IPIP;
472
473 /*
474 * We should be keeping tunnel soft-state and
475 * send back ICMPs if needed.
476 */
477 m_copydata(m, sizeof(struct ip) +
478 offsetof(struct ip, ip_off),
479 sizeof(uint16_t), &ipo->ip_off);
480 ipo->ip_off &= ~ IP_OFF_CONVERT(IP_DF | IP_MF | IP_OFFMASK);
481 }
482 #ifdef INET6
483 else if (tp == (IPV6_VERSION >> 4)) {
484 uint32_t itos32;
485
486 /* Save ECN notification. */
487 m_copydata(m, sizeof(struct ip) +
488 offsetof(struct ip6_hdr, ip6_flow),
489 sizeof(uint32_t), &itos32);
490 itos = ntohl(itos32) >> 20;
491 ipo->ip_p = IPPROTO_IPV6;
492 ipo->ip_off = 0;
493 }
494 #endif /* INET6 */
495 else {
496 goto nofamily;
497 }
498
499 otos = 0;
500 ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
501 ipo->ip_tos = otos;
502 break;
503 #endif /* INET */
504
505 #ifdef INET6
506 case AF_INET6:
507 if (IN6_IS_ADDR_UNSPECIFIED(&saidx->dst.sin6.sin6_addr) ||
508 saidx->src.sa.sa_family != AF_INET6 ||
509 IN6_IS_ADDR_UNSPECIFIED(&saidx->src.sin6.sin6_addr)) {
510 DPRINTF(("%s: unspecified tunnel endpoint "
511 "address in SA %s/%08lx\n", __func__,
512 ipsec_address(&saidx->dst),
513 (u_long) ntohl(sav->spi)));
514 IPIP_STATINC(IPIP_STAT_UNSPEC);
515 error = ENOBUFS;
516 goto bad;
517 }
518
519 if (tp == (IPV6_VERSION >> 4)) {
520 /* scoped address handling */
521 ip6 = mtod(m, struct ip6_hdr *);
522 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
523 ip6->ip6_src.s6_addr16[1] = 0;
524 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
525 ip6->ip6_dst.s6_addr16[1] = 0;
526 }
527
528 M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
529 if (m == 0) {
530 DPRINTF(("%s: M_PREPEND failed\n", __func__));
531 IPIP_STATINC(IPIP_STAT_HDROPS);
532 error = ENOBUFS;
533 goto bad;
534 }
535
536 /* Initialize IPv6 header */
537 ip6o = mtod(m, struct ip6_hdr *);
538 ip6o->ip6_flow = 0;
539 ip6o->ip6_vfc &= ~IPV6_VERSION_MASK;
540 ip6o->ip6_vfc |= IPV6_VERSION;
541 ip6o->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6o));
542 ip6o->ip6_hlim = ip_defttl;
543 ip6o->ip6_dst = saidx->dst.sin6.sin6_addr;
544 ip6o->ip6_src = saidx->src.sin6.sin6_addr;
545 if (IN6_IS_SCOPE_LINKLOCAL(&ip6o->ip6_dst))
546 ip6o->ip6_dst.s6_addr16[1] = htons(saidx->dst.sin6.sin6_scope_id);
547 if (IN6_IS_SCOPE_LINKLOCAL(&ip6o->ip6_src))
548 ip6o->ip6_src.s6_addr16[1] = htons(saidx->src.sin6.sin6_scope_id);
549
550 #ifdef INET
551 if (tp == IPVERSION) {
552 /* Save ECN notification */
553 m_copydata(m, sizeof(struct ip6_hdr) +
554 offsetof(struct ip, ip_tos), sizeof(uint8_t),
555 &itos);
556
557 /* This is really IPVERSION. */
558 ip6o->ip6_nxt = IPPROTO_IPIP;
559 } else
560 #endif /* INET */
561 if (tp == (IPV6_VERSION >> 4)) {
562 uint32_t itos32;
563
564 /* Save ECN notification. */
565 m_copydata(m, sizeof(struct ip6_hdr) +
566 offsetof(struct ip6_hdr, ip6_flow),
567 sizeof(uint32_t), &itos32);
568 itos = ntohl(itos32) >> 20;
569
570 ip6o->ip6_nxt = IPPROTO_IPV6;
571 } else {
572 goto nofamily;
573 }
574
575 otos = 0;
576 ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
577 ip6o->ip6_flow |= htonl((uint32_t) otos << 20);
578 break;
579 #endif /* INET6 */
580
581 default:
582 nofamily:
583 DPRINTF(("%s: unsupported protocol family %u\n", __func__,
584 saidx->dst.sa.sa_family));
585 IPIP_STATINC(IPIP_STAT_FAMILY);
586 error = EAFNOSUPPORT; /* XXX diffs from openbsd */
587 goto bad;
588 }
589
590 IPIP_STATINC(IPIP_STAT_OPACKETS);
591 *mp = m;
592
593 #ifdef INET
594 if (saidx->dst.sa.sa_family == AF_INET) {
595 #if 0
596 if (sav->tdb_xform->xf_type == XF_IP4)
597 tdb->tdb_cur_bytes +=
598 m->m_pkthdr.len - sizeof(struct ip);
599 #endif
600 IPIP_STATADD(IPIP_STAT_OBYTES,
601 m->m_pkthdr.len - sizeof(struct ip));
602 }
603 #endif /* INET */
604
605 #ifdef INET6
606 if (saidx->dst.sa.sa_family == AF_INET6) {
607 #if 0
608 if (sav->tdb_xform->xf_type == XF_IP4)
609 tdb->tdb_cur_bytes +=
610 m->m_pkthdr.len - sizeof(struct ip6_hdr);
611 #endif
612 IPIP_STATADD(IPIP_STAT_OBYTES,
613 m->m_pkthdr.len - sizeof(struct ip6_hdr));
614 }
615 #endif /* INET6 */
616
617 return 0;
618 bad:
619 if (m)
620 m_freem(m);
621 *mp = NULL;
622 return (error);
623 }
624
625 static int
626 ipe4_init(struct secasvar *sav, const struct xformsw *xsp)
627 {
628 sav->tdb_xform = xsp;
629 return 0;
630 }
631
632 static int
633 ipe4_zeroize(struct secasvar *sav)
634 {
635 sav->tdb_xform = NULL;
636 return 0;
637 }
638
639 static int
640 ipe4_input(
641 struct mbuf *m,
642 const struct secasvar *sav,
643 int skip,
644 int protoff
645 )
646 {
647 /* This is a rather serious mistake, so no conditional printing. */
648 printf("%s: should never be called\n", __func__);
649 if (m)
650 m_freem(m);
651 return EOPNOTSUPP;
652 }
653
654 static struct xformsw ipe4_xformsw = {
655 XF_IP4, 0, "IPv4 Simple Encapsulation",
656 ipe4_init, ipe4_zeroize, ipe4_input, ipip_output,
657 NULL,
658 };
659
660 #ifdef INET
661 static struct encapsw ipe4_encapsw = {
662 .encapsw4 = {
663 .pr_input = ip4_input,
664 .pr_ctlinput = NULL,
665 }
666 };
667 #endif
668 #ifdef INET6
669 static struct encapsw ipe4_encapsw6 = {
670 .encapsw6 = {
671 .pr_input = ip4_input6,
672 .pr_ctlinput = NULL,
673 }
674 };
675 #endif
676
677 /*
678 * Check the encapsulated packet to see if we want it
679 */
680 static int
681 ipe4_encapcheck(struct mbuf *m,
682 int off,
683 int proto,
684 void *arg
685 )
686 {
687 /*
688 * Only take packets coming from IPSEC tunnels; the rest
689 * must be handled by the gif tunnel code. Note that we
690 * also return a minimum priority when we want the packet
691 * so any explicit gif tunnels take precedence.
692 */
693 return ((m->m_flags & M_IPSEC) != 0 ? 1 : 0);
694 }
695
696 INITFN void
697 ipe4_attach(void)
698 {
699
700 ipipstat_percpu = percpu_alloc(sizeof(uint64_t) * IPIP_NSTATS);
701
702 xform_register(&ipe4_xformsw);
703 /* attach to encapsulation framework */
704 /* XXX save return cookie for detach on module remove */
705
706 encapinit();
707 /* This function is called before ifinit(). Who else gets lock? */
708 (void)encap_lock_enter();
709 /* ipe4_encapsw and ipe4_encapsw must be added atomically */
710 #ifdef INET
711 (void) encap_attach_func(AF_INET, -1,
712 ipe4_encapcheck, &ipe4_encapsw, NULL);
713 #endif
714 #ifdef INET6
715 (void) encap_attach_func(AF_INET6, -1,
716 ipe4_encapcheck, &ipe4_encapsw6, NULL);
717 #endif
718 encap_lock_exit();
719 }
720
721 #ifdef SYSINIT
722 SYSINIT(ipe4_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ipe4_attach, NULL);
723 #endif
724
725