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