Annotation of sys/netinet/ipsec_input.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ipsec_input.c,v 1.84 2007/05/28 17:16:39 henning Exp $ */
2: /*
3: * The authors of this code are John Ioannidis (ji@tla.org),
4: * Angelos D. Keromytis (kermit@csd.uch.gr) and
5: * Niels Provos (provos@physnet.uni-hamburg.de).
6: *
7: * This code was written by John Ioannidis for BSD/OS in Athens, Greece,
8: * in November 1995.
9: *
10: * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
11: * by Angelos D. Keromytis.
12: *
13: * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
14: * and Niels Provos.
15: *
16: * Additional features in 1999 by Angelos D. Keromytis.
17: *
18: * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
19: * Angelos D. Keromytis and Niels Provos.
20: * Copyright (c) 2001, Angelos D. Keromytis.
21: *
22: * Permission to use, copy, and modify this software with or without fee
23: * is hereby granted, provided that this entire notice is included in
24: * all copies of any software which is or includes a copy or
25: * modification of this software.
26: * You may use this code under the GNU public license if you so wish. Please
27: * contribute changes back to the authors under this freer than GPL license
28: * so that we may further the use of strong encryption without limitations to
29: * all.
30: *
31: * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
32: * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
33: * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
34: * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
35: * PURPOSE.
36: */
37:
38: #include "pf.h"
39:
40: #include <sys/param.h>
41: #include <sys/systm.h>
42: #include <sys/protosw.h>
43: #include <sys/mbuf.h>
44: #include <sys/socket.h>
45: #include <sys/sysctl.h>
46: #include <sys/kernel.h>
47:
48: #include <net/if.h>
49: #include <net/netisr.h>
50: #include <net/bpf.h>
51:
52: #if NPF > 0
53: #include <net/pfvar.h>
54: #endif
55:
56: #include <netinet/in.h>
57: #include <netinet/in_systm.h>
58: #include <netinet/ip.h>
59: #include <netinet/ip_var.h>
60: #include <netinet/in_var.h>
61: #include <netinet/ip_icmp.h>
62: #include <netinet/tcp.h>
63: #include <netinet/udp.h>
64:
65: #ifdef INET6
66: #ifndef INET
67: #include <netinet/in.h>
68: #endif
69: #include <netinet/ip6.h>
70: #include <netinet6/ip6_var.h>
71: #include <netinet6/ip6protosw.h>
72: #endif /* INET6 */
73:
74: #include <netinet/ip_ipsp.h>
75: #include <netinet/ip_esp.h>
76: #include <netinet/ip_ah.h>
77: #include <netinet/ip_ipcomp.h>
78:
79: #include <net/if_enc.h>
80:
81: #include "bpfilter.h"
82:
83: void *ipsec_common_ctlinput(int, struct sockaddr *, void *, int);
84:
85: #ifdef ENCDEBUG
86: #define DPRINTF(x) if (encdebug) printf x
87: #else
88: #define DPRINTF(x)
89: #endif
90:
91: /* sysctl variables */
92: int esp_enable = 1;
93: int ah_enable = 1;
94: int ipcomp_enable = 0;
95:
96: int *espctl_vars[ESPCTL_MAXID] = ESPCTL_VARS;
97: int *ahctl_vars[AHCTL_MAXID] = AHCTL_VARS;
98: int *ipcompctl_vars[IPCOMPCTL_MAXID] = IPCOMPCTL_VARS;
99:
100: #ifdef INET6
101: extern struct ip6protosw inet6sw[];
102: extern u_char ip6_protox[];
103: #endif
104:
105: /*
106: * ipsec_common_input() gets called when we receive an IPsec-protected packet
107: * in IPv4 or IPv6. All it does is find the right TDB and call the appropriate
108: * transform. The callback takes care of further processing (like ingress
109: * filtering).
110: */
111: int
112: ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto,
113: int udpencap)
114: {
115: #define IPSEC_ISTAT(x,y,z) (sproto == IPPROTO_ESP ? (x)++ : \
116: sproto == IPPROTO_AH ? (y)++ : (z)++)
117:
118: union sockaddr_union dst_address;
119: struct timeval tv;
120: struct tdb *tdbp;
121: u_int32_t spi;
122: u_int16_t cpi;
123: int s, error;
124:
125: IPSEC_ISTAT(espstat.esps_input, ahstat.ahs_input,
126: ipcompstat.ipcomps_input);
127:
128: if (m == 0) {
129: DPRINTF(("ipsec_common_input(): NULL packet received\n"));
130: IPSEC_ISTAT(espstat.esps_hdrops, ahstat.ahs_hdrops,
131: ipcompstat.ipcomps_hdrops);
132: return EINVAL;
133: }
134:
135: if ((sproto == IPPROTO_ESP && !esp_enable) ||
136: (sproto == IPPROTO_AH && !ah_enable) ||
137: (sproto == IPPROTO_IPCOMP && !ipcomp_enable)) {
138: rip_input(m, skip, sproto);
139: return 0;
140: }
141:
142: if (m->m_pkthdr.len - skip < 2 * sizeof(u_int32_t)) {
143: m_freem(m);
144: IPSEC_ISTAT(espstat.esps_hdrops, ahstat.ahs_hdrops,
145: ipcompstat.ipcomps_hdrops);
146: DPRINTF(("ipsec_common_input(): packet too small\n"));
147: return EINVAL;
148: }
149:
150: /* Retrieve the SPI from the relevant IPsec header */
151: if (sproto == IPPROTO_ESP)
152: m_copydata(m, skip, sizeof(u_int32_t), (caddr_t) &spi);
153: else if (sproto == IPPROTO_AH)
154: m_copydata(m, skip + sizeof(u_int32_t), sizeof(u_int32_t),
155: (caddr_t) &spi);
156: else if (sproto == IPPROTO_IPCOMP) {
157: m_copydata(m, skip + sizeof(u_int16_t), sizeof(u_int16_t),
158: (caddr_t) &cpi);
159: spi = ntohl(htons(cpi));
160: }
161:
162: /*
163: * Find tunnel control block and (indirectly) call the appropriate
164: * kernel crypto routine. The resulting mbuf chain is a valid
165: * IP packet ready to go through input processing.
166: */
167:
168: bzero(&dst_address, sizeof(dst_address));
169: dst_address.sa.sa_family = af;
170:
171: switch (af) {
172: #ifdef INET
173: case AF_INET:
174: dst_address.sin.sin_len = sizeof(struct sockaddr_in);
175: m_copydata(m, offsetof(struct ip, ip_dst),
176: sizeof(struct in_addr),
177: (caddr_t) &(dst_address.sin.sin_addr));
178: break;
179: #endif /* INET */
180:
181: #ifdef INET6
182: case AF_INET6:
183: dst_address.sin6.sin6_len = sizeof(struct sockaddr_in6);
184: m_copydata(m, offsetof(struct ip6_hdr, ip6_dst),
185: sizeof(struct in6_addr),
186: (caddr_t) &(dst_address.sin6.sin6_addr));
187: in6_recoverscope(&dst_address.sin6, &dst_address.sin6.sin6_addr,
188: NULL);
189: break;
190: #endif /* INET6 */
191:
192: default:
193: DPRINTF(("ipsec_common_input(): unsupported protocol "
194: "family %d\n", af));
195: m_freem(m);
196: IPSEC_ISTAT(espstat.esps_nopf, ahstat.ahs_nopf,
197: ipcompstat.ipcomps_nopf);
198: return EPFNOSUPPORT;
199: }
200:
201: s = spltdb();
202: tdbp = gettdb(spi, &dst_address, sproto);
203: if (tdbp == NULL) {
204: splx(s);
205: DPRINTF(("ipsec_common_input(): could not find SA for "
206: "packet to %s, spi %08x\n",
207: ipsp_address(dst_address), ntohl(spi)));
208: m_freem(m);
209: IPSEC_ISTAT(espstat.esps_notdb, ahstat.ahs_notdb,
210: ipcompstat.ipcomps_notdb);
211: return ENOENT;
212: }
213:
214: if (tdbp->tdb_flags & TDBF_INVALID) {
215: splx(s);
216: DPRINTF(("ipsec_common_input(): attempted to use invalid SA %s/%08x/%u\n", ipsp_address(dst_address), ntohl(spi), tdbp->tdb_sproto));
217: m_freem(m);
218: IPSEC_ISTAT(espstat.esps_invalid, ahstat.ahs_invalid,
219: ipcompstat.ipcomps_invalid);
220: return EINVAL;
221: }
222:
223: if (udpencap && !(tdbp->tdb_flags & TDBF_UDPENCAP)) {
224: splx(s);
225: DPRINTF(("ipsec_common_input(): attempted to use non-udpencap SA %s/%08x/%u\n", ipsp_address(dst_address), ntohl(spi), tdbp->tdb_sproto));
226: m_freem(m);
227: espstat.esps_udpinval++;
228: return EINVAL;
229: }
230:
231: if (tdbp->tdb_xform == NULL) {
232: splx(s);
233: DPRINTF(("ipsec_common_input(): attempted to use uninitialized SA %s/%08x/%u\n", ipsp_address(dst_address), ntohl(spi), tdbp->tdb_sproto));
234: m_freem(m);
235: IPSEC_ISTAT(espstat.esps_noxform, ahstat.ahs_noxform,
236: ipcompstat.ipcomps_noxform);
237: return ENXIO;
238: }
239:
240: if (tdbp->tdb_dst.sa.sa_family == AF_INET &&
241: sproto != IPPROTO_IPCOMP) {
242: /*
243: * XXX The fragment conflicts with scoped nature of
244: * IPv6, so do it for only for IPv4 for now.
245: */
246: m->m_pkthdr.rcvif = &encif[0].sc_if;
247: }
248:
249: /* Register first use, setup expiration timer. */
250: if (tdbp->tdb_first_use == 0) {
251: tdbp->tdb_first_use = time_second;
252:
253: tv.tv_usec = 0;
254:
255: tv.tv_sec = tdbp->tdb_exp_first_use + tdbp->tdb_first_use;
256: if (tdbp->tdb_flags & TDBF_FIRSTUSE)
257: timeout_add(&tdbp->tdb_first_tmo, hzto(&tv));
258:
259: tv.tv_sec = tdbp->tdb_first_use + tdbp->tdb_soft_first_use;
260: if (tdbp->tdb_flags & TDBF_SOFT_FIRSTUSE)
261: timeout_add(&tdbp->tdb_sfirst_tmo, hzto(&tv));
262: }
263:
264: /*
265: * Call appropriate transform and return -- callback takes care of
266: * everything else.
267: */
268: error = (*(tdbp->tdb_xform->xf_input))(m, tdbp, skip, protoff);
269: splx(s);
270: return error;
271: }
272:
273: /*
274: * IPsec input callback, called by the transform callback. Takes care of
275: * filtering and other sanity checks on the processed packet.
276: */
277: int
278: ipsec_common_input_cb(struct mbuf *m, struct tdb *tdbp, int skip, int protoff,
279: struct m_tag *mt)
280: {
281: int prot, af, sproto;
282:
283: #if NBPFILTER > 0
284: struct ifnet *bpfif;
285: #endif
286:
287: #ifdef INET
288: struct ip *ip, ipn;
289: #endif /* INET */
290:
291: #ifdef INET6
292: struct ip6_hdr *ip6, ip6n;
293: #endif /* INET6 */
294: struct m_tag *mtag;
295: struct tdb_ident *tdbi;
296:
297: af = tdbp->tdb_dst.sa.sa_family;
298: sproto = tdbp->tdb_sproto;
299:
300: tdbp->tdb_last_used = time_second;
301:
302: /* Sanity check */
303: if (m == NULL) {
304: /* The called routine will print a message if necessary */
305: IPSEC_ISTAT(espstat.esps_badkcr, ahstat.ahs_badkcr,
306: ipcompstat.ipcomps_badkcr);
307: return EINVAL;
308: }
309:
310: #ifdef INET
311: /* Fix IPv4 header */
312: if (tdbp->tdb_dst.sa.sa_family == AF_INET) {
313: if ((m->m_len < skip) && ((m = m_pullup(m, skip)) == NULL)) {
314: DPRINTF(("ipsec_common_input_cb(): processing failed "
315: "for SA %s/%08x\n", ipsp_address(tdbp->tdb_dst),
316: ntohl(tdbp->tdb_spi)));
317: IPSEC_ISTAT(espstat.esps_hdrops, ahstat.ahs_hdrops,
318: ipcompstat.ipcomps_hdrops);
319: return ENOBUFS;
320: }
321:
322: ip = mtod(m, struct ip *);
323: ip->ip_len = htons(m->m_pkthdr.len);
324: ip->ip_sum = 0;
325: ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
326: prot = ip->ip_p;
327:
328: /* IP-in-IP encapsulation */
329: if (prot == IPPROTO_IPIP) {
330: if (m->m_pkthdr.len - skip < sizeof(struct ip)) {
331: m_freem(m);
332: IPSEC_ISTAT(espstat.esps_hdrops,
333: ahstat.ahs_hdrops,
334: ipcompstat.ipcomps_hdrops);
335: return EINVAL;
336: }
337: /* ipn will now contain the inner IPv4 header */
338: m_copydata(m, skip, sizeof(struct ip),
339: (caddr_t) &ipn);
340:
341: /*
342: * Check that the inner source address is the same as
343: * the proxy address, if available.
344: */
345: if ((tdbp->tdb_proxy.sa.sa_family == AF_INET &&
346: tdbp->tdb_proxy.sin.sin_addr.s_addr !=
347: INADDR_ANY &&
348: ipn.ip_src.s_addr !=
349: tdbp->tdb_proxy.sin.sin_addr.s_addr) ||
350: (tdbp->tdb_proxy.sa.sa_family != AF_INET &&
351: tdbp->tdb_proxy.sa.sa_family != 0)) {
352:
353: DPRINTF(("ipsec_common_input_cb(): inner "
354: "source address %s doesn't correspond to "
355: "expected proxy source %s, SA %s/%08x\n",
356: inet_ntoa4(ipn.ip_src),
357: ipsp_address(tdbp->tdb_proxy),
358: ipsp_address(tdbp->tdb_dst),
359: ntohl(tdbp->tdb_spi)));
360:
361: m_freem(m);
362: IPSEC_ISTAT(espstat.esps_pdrops,
363: ahstat.ahs_pdrops,
364: ipcompstat.ipcomps_pdrops);
365: return EACCES;
366: }
367: }
368:
369: #if INET6
370: /* IPv6-in-IP encapsulation. */
371: if (prot == IPPROTO_IPV6) {
372: if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) {
373: m_freem(m);
374: IPSEC_ISTAT(espstat.esps_hdrops,
375: ahstat.ahs_hdrops,
376: ipcompstat.ipcomps_hdrops);
377: return EINVAL;
378: }
379: /* ip6n will now contain the inner IPv6 header. */
380: m_copydata(m, skip, sizeof(struct ip6_hdr),
381: (caddr_t) &ip6n);
382:
383: /*
384: * Check that the inner source address is the same as
385: * the proxy address, if available.
386: */
387: if ((tdbp->tdb_proxy.sa.sa_family == AF_INET6 &&
388: !IN6_IS_ADDR_UNSPECIFIED(&tdbp->tdb_proxy.sin6.sin6_addr) &&
389: !IN6_ARE_ADDR_EQUAL(&ip6n.ip6_src,
390: &tdbp->tdb_proxy.sin6.sin6_addr)) ||
391: (tdbp->tdb_proxy.sa.sa_family != AF_INET6 &&
392: tdbp->tdb_proxy.sa.sa_family != 0)) {
393:
394: DPRINTF(("ipsec_common_input_cb(): inner "
395: "source address %s doesn't correspond to "
396: "expected proxy source %s, SA %s/%08x\n",
397: ip6_sprintf(&ip6n.ip6_src),
398: ipsp_address(tdbp->tdb_proxy),
399: ipsp_address(tdbp->tdb_dst),
400: ntohl(tdbp->tdb_spi)));
401:
402: m_freem(m);
403: IPSEC_ISTAT(espstat.esps_pdrops,
404: ahstat.ahs_pdrops,
405: ipcompstat.ipcomps_pdrops);
406: return EACCES;
407: }
408: }
409: #endif /* INET6 */
410: }
411: #endif /* INET */
412:
413: #ifdef INET6
414: /* Fix IPv6 header */
415: if (af == INET6)
416: {
417: if (m->m_len < sizeof(struct ip6_hdr) &&
418: (m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
419:
420: DPRINTF(("ipsec_common_input_cb(): processing failed "
421: "for SA %s/%08x\n", ipsp_address(tdbp->tdb_dst),
422: ntohl(tdbp->tdb_spi)));
423:
424: IPSEC_ISTAT(espstat.esps_hdrops, ahstat.ahs_hdrops,
425: ipcompstat.ipcomps_hdrops);
426: return EACCES;
427: }
428:
429: ip6 = mtod(m, struct ip6_hdr *);
430: ip6->ip6_plen = htons(m->m_pkthdr.len -
431: sizeof(struct ip6_hdr));
432:
433: /* Save protocol */
434: m_copydata(m, protoff, 1, (unsigned char *) &prot);
435:
436: #ifdef INET
437: /* IP-in-IP encapsulation */
438: if (prot == IPPROTO_IPIP) {
439: if (m->m_pkthdr.len - skip < sizeof(struct ip)) {
440: m_freem(m);
441: IPSEC_ISTAT(espstat.esps_hdrops,
442: ahstat.ahs_hdrops,
443: ipcompstat.ipcomps_hdrops);
444: return EINVAL;
445: }
446: /* ipn will now contain the inner IPv4 header */
447: m_copydata(m, skip, sizeof(struct ip), (caddr_t) &ipn);
448:
449: /*
450: * Check that the inner source address is the same as
451: * the proxy address, if available.
452: */
453: if ((tdbp->tdb_proxy.sa.sa_family == AF_INET &&
454: tdbp->tdb_proxy.sin.sin_addr.s_addr !=
455: INADDR_ANY &&
456: ipn.ip_src.s_addr !=
457: tdbp->tdb_proxy.sin.sin_addr.s_addr) ||
458: (tdbp->tdb_proxy.sa.sa_family != AF_INET &&
459: tdbp->tdb_proxy.sa.sa_family != 0)) {
460:
461: DPRINTF(("ipsec_common_input_cb(): inner "
462: "source address %s doesn't correspond to "
463: "expected proxy source %s, SA %s/%08x\n",
464: inet_ntoa4(ipn.ip_src),
465: ipsp_address(tdbp->tdb_proxy),
466: ipsp_address(tdbp->tdb_dst),
467: ntohl(tdbp->tdb_spi)));
468:
469: m_freem(m);
470: IPSEC_ISTAT(espstat.esps_pdrops,
471: ahstat.ahs_pdrops,
472: ipcompstat.ipcomps_pdrops);
473: return EACCES;
474: }
475: }
476: #endif /* INET */
477:
478: /* IPv6-in-IP encapsulation */
479: if (prot == IPPROTO_IPV6) {
480: if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) {
481: m_freem(m);
482: IPSEC_ISTAT(espstat.esps_hdrops,
483: ahstat.ahs_hdrops,
484: ipcompstat.ipcomps_hdrops);
485: return EINVAL;
486: }
487: /* ip6n will now contain the inner IPv6 header. */
488: m_copydata(m, skip, sizeof(struct ip6_hdr),
489: (caddr_t) &ip6n);
490:
491: /*
492: * Check that the inner source address is the same as
493: * the proxy address, if available.
494: */
495: if ((tdbp->tdb_proxy.sa.sa_family == AF_INET6 &&
496: !IN6_IS_ADDR_UNSPECIFIED(&tdbp->tdb_proxy.sin6.sin6_addr) &&
497: !IN6_ARE_ADDR_EQUAL(&ip6n.ip6_src,
498: &tdbp->tdb_proxy.sin6.sin6_addr)) ||
499: (tdbp->tdb_proxy.sa.sa_family != AF_INET6 &&
500: tdbp->tdb_proxy.sa.sa_family != 0)) {
501:
502: DPRINTF(("ipsec_common_input_cb(): inner "
503: "source address %s doesn't correspond to "
504: "expected proxy source %s, SA %s/%08x\n",
505: ip6_sprintf(&ip6n.ip6_src),
506: ipsp_address(tdbp->tdb_proxy),
507: ipsp_address(tdbp->tdb_dst),
508: ntohl(tdbp->tdb_spi)));
509:
510: m_freem(m);
511: IPSEC_ISTAT(espstat.esps_pdrops,
512: ahstat.ahs_pdrops,
513: ipcompstat.ipcomps_pdrops);
514: return EACCES;
515: }
516: }
517: }
518: #endif /* INET6 */
519:
520: /*
521: * Record what we've done to the packet (under what SA it was
522: * processed). If we've been passed an mtag, it means the packet
523: * was already processed by an ethernet/crypto combo card and
524: * thus has a tag attached with all the right information, but
525: * with a PACKET_TAG_IPSEC_IN_CRYPTO_DONE as opposed to
526: * PACKET_TAG_IPSEC_IN_DONE type; in that case, just change the type.
527: */
528: if (mt == NULL && tdbp->tdb_sproto != IPPROTO_IPCOMP) {
529: mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE,
530: sizeof(struct tdb_ident), M_NOWAIT);
531: if (mtag == NULL) {
532: m_freem(m);
533: DPRINTF(("ipsec_common_input_cb(): failed to "
534: "get tag\n"));
535: IPSEC_ISTAT(espstat.esps_hdrops, ahstat.ahs_hdrops,
536: ipcompstat.ipcomps_hdrops);
537: return ENOMEM;
538: }
539:
540: tdbi = (struct tdb_ident *)(mtag + 1);
541: bcopy(&tdbp->tdb_dst, &tdbi->dst,
542: sizeof(union sockaddr_union));
543: tdbi->proto = tdbp->tdb_sproto;
544: tdbi->spi = tdbp->tdb_spi;
545:
546: m_tag_prepend(m, mtag);
547: } else {
548: if (mt != NULL)
549: mt->m_tag_id = PACKET_TAG_IPSEC_IN_DONE;
550: }
551:
552: if (sproto == IPPROTO_ESP) {
553: /* Packet is confidential ? */
554: if (tdbp->tdb_encalgxform)
555: m->m_flags |= M_CONF;
556:
557: /* Check if we had authenticated ESP. */
558: if (tdbp->tdb_authalgxform)
559: m->m_flags |= M_AUTH;
560: } else if (sproto == IPPROTO_AH)
561: m->m_flags |= M_AUTH | M_AUTH_AH;
562:
563: #if NPF > 0
564: /* Add pf tag if requested. */
565: if (pf_tag_packet(m, tdbp->tdb_tag, -1))
566: DPRINTF(("failed to tag ipsec packet\n"));
567: #endif
568:
569: if (tdbp->tdb_flags & TDBF_TUNNELING)
570: m->m_flags |= M_TUNNEL;
571:
572: #if NBPFILTER > 0
573: bpfif = &encif[0].sc_if;
574: bpfif->if_ipackets++;
575: bpfif->if_ibytes += m->m_pkthdr.len;
576:
577: if (bpfif->if_bpf) {
578: struct enchdr hdr;
579:
580: hdr.af = af;
581: hdr.spi = tdbp->tdb_spi;
582: hdr.flags = m->m_flags & (M_AUTH|M_CONF|M_AUTH_AH);
583:
584: bpf_mtap_hdr(bpfif->if_bpf, (char *)&hdr, ENC_HDRLEN, m,
585: BPF_DIRECTION_IN);
586: }
587: #endif
588:
589: /* Call the appropriate IPsec transform callback. */
590: switch (af) {
591: #ifdef INET
592: case AF_INET:
593: switch (sproto)
594: {
595: case IPPROTO_ESP:
596: return esp4_input_cb(m);
597:
598: case IPPROTO_AH:
599: return ah4_input_cb(m);
600:
601: case IPPROTO_IPCOMP:
602: return ipcomp4_input_cb(m);
603:
604: default:
605: DPRINTF(("ipsec_common_input_cb(): unknown/unsupported"
606: " security protocol %d\n", sproto));
607: m_freem(m);
608: return EPFNOSUPPORT;
609: }
610: break;
611: #endif /* INET */
612:
613: #ifdef INET6
614: case AF_INET6:
615: switch (sproto) {
616: case IPPROTO_ESP:
617: return esp6_input_cb(m, skip, protoff);
618:
619: case IPPROTO_AH:
620: return ah6_input_cb(m, skip, protoff);
621:
622: case IPPROTO_IPCOMP:
623: return ipcomp6_input_cb(m, skip, protoff);
624:
625: default:
626: DPRINTF(("ipsec_common_input_cb(): unknown/unsupported"
627: " security protocol %d\n", sproto));
628: m_freem(m);
629: return EPFNOSUPPORT;
630: }
631: break;
632: #endif /* INET6 */
633:
634: default:
635: DPRINTF(("ipsec_common_input_cb(): unknown/unsupported "
636: "protocol family %d\n", af));
637: m_freem(m);
638: return EPFNOSUPPORT;
639: }
640: #undef IPSEC_ISTAT
641: }
642:
643: int
644: esp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
645: size_t newlen)
646: {
647: if (name[0] < ESPCTL_MAXID)
648: return (sysctl_int_arr(espctl_vars, name, namelen,
649: oldp, oldlenp, newp, newlen));
650: return (ENOPROTOOPT);
651: }
652:
653: int
654: ah_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
655: size_t newlen)
656: {
657: if (name[0] < AHCTL_MAXID)
658: return (sysctl_int_arr(ahctl_vars, name, namelen,
659: oldp, oldlenp, newp, newlen));
660: return (ENOPROTOOPT);
661: }
662:
663: int
664: ipcomp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
665: size_t newlen)
666: {
667: if (name[0] < IPCOMPCTL_MAXID)
668: return (sysctl_int_arr(ipcompctl_vars, name, namelen,
669: oldp, oldlenp, newp, newlen));
670: return (ENOPROTOOPT);
671: }
672:
673: #ifdef INET
674: /* IPv4 AH wrapper. */
675: void
676: ah4_input(struct mbuf *m, ...)
677: {
678: int skip;
679:
680: va_list ap;
681: va_start(ap, m);
682: skip = va_arg(ap, int);
683: va_end(ap);
684:
685: ipsec_common_input(m, skip, offsetof(struct ip, ip_p), AF_INET,
686: IPPROTO_AH, 0);
687: return;
688: }
689:
690: /* IPv4 AH callback. */
691: int
692: ah4_input_cb(struct mbuf *m, ...)
693: {
694: struct ifqueue *ifq = &ipintrq;
695: int s = splnet();
696:
697: /*
698: * Interface pointer is already in first mbuf; chop off the
699: * `outer' header and reschedule.
700: */
701:
702: if (IF_QFULL(ifq)) {
703: IF_DROP(ifq);
704: ahstat.ahs_qfull++;
705: splx(s);
706:
707: m_freem(m);
708: DPRINTF(("ah4_input_cb(): dropped packet because of full "
709: "IP queue\n"));
710: return ENOBUFS;
711: }
712:
713: IF_ENQUEUE(ifq, m);
714: schednetisr(NETISR_IP);
715: splx(s);
716: return 0;
717: }
718:
719:
720: void *
721: ah4_ctlinput(int cmd, struct sockaddr *sa, void *v)
722: {
723: if (sa->sa_family != AF_INET ||
724: sa->sa_len != sizeof(struct sockaddr_in))
725: return (NULL);
726:
727: return (ipsec_common_ctlinput(cmd, sa, v, IPPROTO_AH));
728: }
729:
730: /* IPv4 ESP wrapper. */
731: void
732: esp4_input(struct mbuf *m, ...)
733: {
734: int skip;
735:
736: va_list ap;
737: va_start(ap, m);
738: skip = va_arg(ap, int);
739: va_end(ap);
740:
741: ipsec_common_input(m, skip, offsetof(struct ip, ip_p), AF_INET,
742: IPPROTO_ESP, 0);
743: }
744:
745: /* IPv4 ESP callback. */
746: int
747: esp4_input_cb(struct mbuf *m, ...)
748: {
749: struct ifqueue *ifq = &ipintrq;
750: int s = splnet();
751:
752: /*
753: * Interface pointer is already in first mbuf; chop off the
754: * `outer' header and reschedule.
755: */
756: if (IF_QFULL(ifq)) {
757: IF_DROP(ifq);
758: espstat.esps_qfull++;
759: splx(s);
760:
761: m_freem(m);
762: DPRINTF(("esp4_input_cb(): dropped packet because of full "
763: "IP queue\n"));
764: return ENOBUFS;
765: }
766:
767: IF_ENQUEUE(ifq, m);
768: schednetisr(NETISR_IP);
769: splx(s);
770: return 0;
771: }
772:
773: /* IPv4 IPCOMP wrapper */
774: void
775: ipcomp4_input(struct mbuf *m, ...)
776: {
777: int skip;
778: va_list ap;
779: va_start(ap, m);
780: skip = va_arg(ap, int);
781: va_end(ap);
782:
783: ipsec_common_input(m, skip, offsetof(struct ip, ip_p), AF_INET,
784: IPPROTO_IPCOMP, 0);
785: }
786:
787: /* IPv4 IPCOMP callback */
788: int
789: ipcomp4_input_cb(struct mbuf *m, ...)
790: {
791: struct ifqueue *ifq = &ipintrq;
792: int s = splnet();
793:
794: /*
795: * Interface pointer is already in first mbuf; chop off the
796: * `outer' header and reschedule.
797: */
798: if (IF_QFULL(ifq)) {
799: IF_DROP(ifq);
800: ipcompstat.ipcomps_qfull++;
801: splx(s);
802:
803: m_freem(m);
804: DPRINTF(("ipcomp4_input_cb(): dropped packet because of full IP queue\n"));
805: return ENOBUFS;
806: }
807:
808: IF_ENQUEUE(ifq, m);
809: schednetisr(NETISR_IP);
810: splx(s);
811:
812: return 0;
813: }
814:
815: void *
816: ipsec_common_ctlinput(int cmd, struct sockaddr *sa, void *v, int proto)
817: {
818: extern u_int ip_mtudisc_timeout;
819: struct ip *ip = v;
820: int s;
821:
822: if (cmd == PRC_MSGSIZE && ip && ip_mtudisc && ip->ip_v == 4) {
823: struct tdb *tdbp;
824: struct sockaddr_in dst;
825: struct icmp *icp;
826: int hlen = ip->ip_hl << 2;
827: u_int32_t spi, mtu;
828: ssize_t adjust;
829:
830: /* Find the right MTU. */
831: icp = (struct icmp *)((caddr_t) ip -
832: offsetof(struct icmp, icmp_ip));
833: mtu = ntohs(icp->icmp_nextmtu);
834:
835: /*
836: * Ignore the packet, if we do not receive a MTU
837: * or the MTU is too small to be acceptable.
838: */
839: if (mtu < 296)
840: return (NULL);
841:
842: bzero(&dst, sizeof(struct sockaddr_in));
843: dst.sin_family = AF_INET;
844: dst.sin_len = sizeof(struct sockaddr_in);
845: dst.sin_addr.s_addr = ip->ip_dst.s_addr;
846:
847: bcopy((caddr_t)ip + hlen, &spi, sizeof(u_int32_t));
848:
849: s = spltdb();
850: tdbp = gettdb(spi, (union sockaddr_union *)&dst, proto);
851: if (tdbp == NULL || tdbp->tdb_flags & TDBF_INVALID) {
852: splx(s);
853: return (NULL);
854: }
855:
856: /* Walk the chain backswards to the first tdb */
857: for (; tdbp; tdbp = tdbp->tdb_inext) {
858: if (tdbp->tdb_flags & TDBF_INVALID ||
859: (adjust = ipsec_hdrsz(tdbp)) == -1) {
860: splx(s);
861: return (NULL);
862: }
863:
864: mtu -= adjust;
865:
866: /* Store adjusted MTU in tdb */
867: tdbp->tdb_mtu = mtu;
868: tdbp->tdb_mtutimeout = time_second +
869: ip_mtudisc_timeout;
870: DPRINTF(("ipsec_common_ctlinput: "
871: "spi %08x mtu %d adjust %d\n",
872: ntohl(tdbp->tdb_spi), tdbp->tdb_mtu,
873: adjust));
874: }
875: splx(s);
876: return (NULL);
877: }
878: return (NULL);
879: }
880:
881: void *
882: udpencap_ctlinput(int cmd, struct sockaddr *sa, void *v)
883: {
884: struct ip *ip = v;
885: struct tdb *tdbp;
886: struct icmp *icp;
887: u_int32_t mtu;
888: ssize_t adjust;
889: struct sockaddr_in dst, src;
890: union sockaddr_union *su_dst, *su_src;
891: int s;
892:
893: icp = (struct icmp *)((caddr_t) ip - offsetof(struct icmp, icmp_ip));
894: mtu = ntohs(icp->icmp_nextmtu);
895:
896: /*
897: * Ignore the packet, if we do not receive a MTU
898: * or the MTU is too small to be acceptable.
899: */
900: if (mtu < 296)
901: return (NULL);
902:
903: bzero(&dst, sizeof(dst));
904: dst.sin_family = AF_INET;
905: dst.sin_len = sizeof(struct sockaddr_in);
906: dst.sin_addr.s_addr = ip->ip_dst.s_addr;
907: su_dst = (union sockaddr_union *)&dst;
908: bzero(&src, sizeof(src));
909: src.sin_family = AF_INET;
910: src.sin_len = sizeof(struct sockaddr_in);
911: src.sin_addr.s_addr = ip->ip_src.s_addr;
912: su_src = (union sockaddr_union *)&src;
913:
914: s = spltdb();
915: tdbp = gettdbbysrcdst(0, su_src, su_dst, IPPROTO_ESP);
916:
917: for (; tdbp != NULL; tdbp = tdbp->tdb_snext) {
918: if (tdbp->tdb_sproto == IPPROTO_ESP &&
919: ((tdbp->tdb_flags & (TDBF_INVALID|TDBF_UDPENCAP))
920: == TDBF_UDPENCAP) &&
921: !bcmp(&tdbp->tdb_dst, &dst, SA_LEN(&su_dst->sa)) &&
922: !bcmp(&tdbp->tdb_src, &src, SA_LEN(&su_src->sa))) {
923: if ((adjust = ipsec_hdrsz(tdbp)) != -1) {
924: /* Store adjusted MTU in tdb */
925: tdbp->tdb_mtu = mtu - adjust;
926: tdbp->tdb_mtutimeout = time_second +
927: ip_mtudisc_timeout;
928: DPRINTF(("udpencap_ctlinput: "
929: "spi %08x mtu %d adjust %d\n",
930: ntohl(tdbp->tdb_spi), tdbp->tdb_mtu,
931: adjust));
932: }
933: }
934: }
935: splx(s);
936: return (NULL);
937: }
938:
939: void *
940: esp4_ctlinput(int cmd, struct sockaddr *sa, void *v)
941: {
942: if (sa->sa_family != AF_INET ||
943: sa->sa_len != sizeof(struct sockaddr_in))
944: return (NULL);
945:
946: return (ipsec_common_ctlinput(cmd, sa, v, IPPROTO_ESP));
947: }
948: #endif /* INET */
949:
950: #ifdef INET6
951: /* IPv6 AH wrapper. */
952: int
953: ah6_input(struct mbuf **mp, int *offp, int proto)
954: {
955: int l = 0;
956: int protoff, nxt;
957: struct ip6_ext ip6e;
958:
959: if (*offp < sizeof(struct ip6_hdr)) {
960: DPRINTF(("ah6_input(): bad offset\n"));
961: return IPPROTO_DONE;
962: } else if (*offp == sizeof(struct ip6_hdr)) {
963: protoff = offsetof(struct ip6_hdr, ip6_nxt);
964: } else {
965: /* Chase down the header chain... */
966: protoff = sizeof(struct ip6_hdr);
967: nxt = (mtod(*mp, struct ip6_hdr *))->ip6_nxt;
968:
969: do {
970: protoff += l;
971: m_copydata(*mp, protoff, sizeof(ip6e),
972: (caddr_t) &ip6e);
973:
974: if (nxt == IPPROTO_AH)
975: l = (ip6e.ip6e_len + 2) << 2;
976: else
977: l = (ip6e.ip6e_len + 1) << 3;
978: #ifdef DIAGNOSTIC
979: if (l <= 0)
980: panic("ah6_input: l went zero or negative");
981: #endif
982:
983: nxt = ip6e.ip6e_nxt;
984: } while (protoff + l < *offp);
985:
986: /* Malformed packet check */
987: if (protoff + l != *offp) {
988: DPRINTF(("ah6_input(): bad packet header chain\n"));
989: ahstat.ahs_hdrops++;
990: m_freem(*mp);
991: *mp = NULL;
992: return IPPROTO_DONE;
993: }
994: protoff += offsetof(struct ip6_ext, ip6e_nxt);
995: }
996: ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto, 0);
997: return IPPROTO_DONE;
998: }
999:
1000: /* IPv6 AH callback. */
1001: int
1002: ah6_input_cb(struct mbuf *m, int off, int protoff)
1003: {
1004: int nxt;
1005: u_int8_t nxt8;
1006: int nest = 0;
1007:
1008: /* Retrieve new protocol */
1009: m_copydata(m, protoff, sizeof(u_int8_t), (caddr_t) &nxt8);
1010: nxt = nxt8;
1011:
1012: /*
1013: * see the end of ip6_input for this logic.
1014: * IPPROTO_IPV[46] case will be processed just like other ones
1015: */
1016: while (nxt != IPPROTO_DONE) {
1017: if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
1018: ip6stat.ip6s_toomanyhdr++;
1019: goto bad;
1020: }
1021:
1022: /*
1023: * Protection against faulty packet - there should be
1024: * more sanity checks in header chain processing.
1025: */
1026: if (m->m_pkthdr.len < off) {
1027: ip6stat.ip6s_tooshort++;
1028: in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
1029: goto bad;
1030: }
1031: nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
1032: }
1033: return 0;
1034:
1035: bad:
1036: m_freem(m);
1037: return EINVAL;
1038: }
1039:
1040: /* IPv6 ESP wrapper. */
1041: int
1042: esp6_input(struct mbuf **mp, int *offp, int proto)
1043: {
1044: int l = 0;
1045: int protoff, nxt;
1046: struct ip6_ext ip6e;
1047:
1048: if (*offp < sizeof(struct ip6_hdr)) {
1049: DPRINTF(("esp6_input(): bad offset\n"));
1050: return IPPROTO_DONE;
1051: } else if (*offp == sizeof(struct ip6_hdr)) {
1052: protoff = offsetof(struct ip6_hdr, ip6_nxt);
1053: } else {
1054: /* Chase down the header chain... */
1055: protoff = sizeof(struct ip6_hdr);
1056: nxt = (mtod(*mp, struct ip6_hdr *))->ip6_nxt;
1057:
1058: do {
1059: protoff += l;
1060: m_copydata(*mp, protoff, sizeof(ip6e),
1061: (caddr_t) &ip6e);
1062:
1063: if (nxt == IPPROTO_AH)
1064: l = (ip6e.ip6e_len + 2) << 2;
1065: else
1066: l = (ip6e.ip6e_len + 1) << 3;
1067: #ifdef DIAGNOSTIC
1068: if (l <= 0)
1069: panic("esp6_input: l went zero or negative");
1070: #endif
1071:
1072: nxt = ip6e.ip6e_nxt;
1073: } while (protoff + l < *offp);
1074:
1075: /* Malformed packet check */
1076: if (protoff + l != *offp) {
1077: DPRINTF(("esp6_input(): bad packet header chain\n"));
1078: espstat.esps_hdrops++;
1079: m_freem(*mp);
1080: *mp = NULL;
1081: return IPPROTO_DONE;
1082: }
1083: protoff += offsetof(struct ip6_ext, ip6e_nxt);
1084: }
1085: ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto, 0);
1086: return IPPROTO_DONE;
1087:
1088: }
1089:
1090: /* IPv6 ESP callback */
1091: int
1092: esp6_input_cb(struct mbuf *m, int skip, int protoff)
1093: {
1094: return ah6_input_cb(m, skip, protoff);
1095: }
1096:
1097: /* IPv6 IPcomp wrapper */
1098: int
1099: ipcomp6_input(struct mbuf **mp, int *offp, int proto)
1100: {
1101: int l = 0;
1102: int protoff, nxt;
1103: struct ip6_ext ip6e;
1104:
1105: if (*offp < sizeof(struct ip6_hdr)) {
1106: DPRINTF(("ipcomp6_input(): bad offset\n"));
1107: return IPPROTO_DONE;
1108: } else if (*offp == sizeof(struct ip6_hdr)) {
1109: protoff = offsetof(struct ip6_hdr, ip6_nxt);
1110: } else {
1111: /* Chase down the header chain... */
1112: protoff = sizeof(struct ip6_hdr);
1113: nxt = (mtod(*mp, struct ip6_hdr *))->ip6_nxt;
1114:
1115: do {
1116: protoff += l;
1117: m_copydata(*mp, protoff, sizeof(ip6e),
1118: (caddr_t) &ip6e);
1119: if (nxt == IPPROTO_AH)
1120: l = (ip6e.ip6e_len + 2) << 2;
1121: else
1122: l = (ip6e.ip6e_len + 1) << 3;
1123: #ifdef DIAGNOSTIC
1124: if (l <= 0)
1125: panic("ipcomp6_input: l went zero or negative");
1126: #endif
1127:
1128: nxt = ip6e.ip6e_nxt;
1129: } while (protoff + l < *offp);
1130:
1131: /* Malformed packet check */
1132: if (protoff + l != *offp) {
1133: DPRINTF(("ipcomp6_input(): bad packet header chain\n"));
1134: ipcompstat.ipcomps_hdrops++;
1135: m_freem(*mp);
1136: *mp = NULL;
1137: return IPPROTO_DONE;
1138: }
1139:
1140: protoff += offsetof(struct ip6_ext, ip6e_nxt);
1141: }
1142: ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto, 0);
1143: return IPPROTO_DONE;
1144: }
1145:
1146: /* IPv6 IPcomp callback */
1147: int
1148: ipcomp6_input_cb(struct mbuf *m, int skip, int protoff)
1149: {
1150: return ah6_input_cb(m, skip, protoff);
1151: }
1152:
1153: #endif /* INET6 */
CVSweb