xref: /openbsd-src/sys/netinet/ip_ipcomp.c (revision ae3cb403620ab940fbaabb3055fac045a63d56b7)
1 /* $OpenBSD: ip_ipcomp.c,v 1.59 2017/11/08 16:29:20 visa Exp $ */
2 
3 /*
4  * Copyright (c) 2001 Jean-Jacques Bernard-Gundol (jj@wabbitt.org)
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *   notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *   derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 /* IP payload compression protocol (IPComp), see RFC 2393 */
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/mbuf.h>
35 #include <sys/socket.h>
36 
37 #include <net/if.h>
38 #include <net/if_var.h>
39 #include <net/bpf.h>
40 
41 #include <netinet/in.h>
42 #include <netinet/ip.h>
43 #include <netinet/ip_var.h>
44 
45 #ifdef INET6
46 #include <netinet/ip6.h>
47 #endif				/* INET6 */
48 
49 #include <netinet/ip_ipsp.h>
50 #include <netinet/ip_ipcomp.h>
51 #include <net/pfkeyv2.h>
52 #include <net/if_enc.h>
53 
54 #include <crypto/cryptodev.h>
55 #include <crypto/xform.h>
56 
57 #include "bpfilter.h"
58 
59 void ipcomp_output_cb(struct cryptop *);
60 void ipcomp_input_cb(struct cryptop *);
61 
62 #ifdef ENCDEBUG
63 #define DPRINTF(x)      if (encdebug) printf x
64 #else
65 #define DPRINTF(x)
66 #endif
67 
68 /*
69  * ipcomp_attach() is called from the transformation code
70  */
71 int
72 ipcomp_attach(void)
73 {
74 	return 0;
75 }
76 
77 /*
78  * ipcomp_init() is called when an CPI is being set up.
79  */
80 int
81 ipcomp_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
82 {
83 	struct comp_algo *tcomp = NULL;
84 	struct cryptoini cric;
85 
86 	switch (ii->ii_compalg) {
87 	case SADB_X_CALG_DEFLATE:
88 		tcomp = &comp_algo_deflate;
89 		break;
90 	case SADB_X_CALG_LZS:
91 		tcomp = &comp_algo_lzs;
92 		break;
93 
94 	default:
95 		DPRINTF(("%s: unsupported compression algorithm %d specified\n",
96 		    __func__, ii->ii_compalg));
97 		return EINVAL;
98 	}
99 
100 	tdbp->tdb_compalgxform = tcomp;
101 
102 	DPRINTF(("%s: initialized TDB with ipcomp algorithm %s\n", __func__,
103 	    tcomp->name));
104 
105 	tdbp->tdb_xform = xsp;
106 
107 	/* Initialize crypto session */
108 	memset(&cric, 0, sizeof(cric));
109 	cric.cri_alg = tdbp->tdb_compalgxform->type;
110 
111 	return crypto_newsession(&tdbp->tdb_cryptoid, &cric, 0);
112 }
113 
114 /*
115  * ipcomp_zeroize() used when IPCA is deleted
116  */
117 int
118 ipcomp_zeroize(struct tdb *tdbp)
119 {
120 	int err;
121 
122 	err = crypto_freesession(tdbp->tdb_cryptoid);
123 	tdbp->tdb_cryptoid = 0;
124 	return err;
125 }
126 
127 /*
128  * ipcomp_input() gets called to uncompress an input packet
129  */
130 int
131 ipcomp_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
132 {
133 	struct comp_algo *ipcompx = (struct comp_algo *) tdb->tdb_compalgxform;
134 	struct tdb_crypto *tc;
135 	int hlen;
136 
137 	struct cryptodesc *crdc = NULL;
138 	struct cryptop *crp;
139 
140 	hlen = IPCOMP_HLENGTH;
141 
142 	/* Get crypto descriptors */
143 	crp = crypto_getreq(1);
144 	if (crp == NULL) {
145 		m_freem(m);
146 		DPRINTF(("%s: failed to acquire crypto descriptors\n", __func__));
147 		ipcompstat_inc(ipcomps_crypto);
148 		return ENOBUFS;
149 	}
150 	/* Get IPsec-specific opaque pointer */
151 	tc = malloc(sizeof(*tc), M_XDATA, M_NOWAIT | M_ZERO);
152 	if (tc == NULL) {
153 		m_freem(m);
154 		crypto_freereq(crp);
155 		DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__));
156 		ipcompstat_inc(ipcomps_crypto);
157 		return ENOBUFS;
158 	}
159 	crdc = &crp->crp_desc[0];
160 
161 	crdc->crd_skip = skip + hlen;
162 	crdc->crd_len = m->m_pkthdr.len - (skip + hlen);
163 	crdc->crd_inject = skip;
164 
165 	/* Decompression operation */
166 	crdc->crd_alg = ipcompx->type;
167 
168 	/* Crypto operation descriptor */
169 	crp->crp_ilen = m->m_pkthdr.len - (skip + hlen);
170 	crp->crp_flags = CRYPTO_F_IMBUF;
171 	crp->crp_buf = (caddr_t)m;
172 	crp->crp_callback = ipcomp_input_cb;
173 	crp->crp_sid = tdb->tdb_cryptoid;
174 	crp->crp_opaque = (caddr_t)tc;
175 
176 	/* These are passed as-is to the callback */
177 	tc->tc_skip = skip;
178 	tc->tc_protoff = protoff;
179 	tc->tc_spi = tdb->tdb_spi;
180 	tc->tc_proto = IPPROTO_IPCOMP;
181 	tc->tc_rdomain = tdb->tdb_rdomain;
182 	tc->tc_dst = tdb->tdb_dst;
183 
184 	return crypto_dispatch(crp);
185 }
186 
187 /*
188  * IPComp input callback, called directly by the crypto driver
189  */
190 void
191 ipcomp_input_cb(struct cryptop *crp)
192 {
193 	int skip, protoff, roff, hlen = IPCOMP_HLENGTH, clen;
194 	u_int8_t nproto;
195 	struct mbuf *m, *m1, *mo;
196 	struct tdb_crypto *tc;
197 	struct tdb *tdb;
198 	struct ipcomp  *ipcomp;
199 	caddr_t addr;
200 #ifdef ENCDEBUG
201 	char buf[INET6_ADDRSTRLEN];
202 #endif
203 
204 	tc = (struct tdb_crypto *) crp->crp_opaque;
205 	skip = tc->tc_skip;
206 	protoff = tc->tc_protoff;
207 
208 	m = (struct mbuf *) crp->crp_buf;
209 	if (m == NULL) {
210 		/* Shouldn't happen... */
211 		free(tc, M_XDATA, 0);
212 		crypto_freereq(crp);
213 		ipcompstat_inc(ipcomps_crypto);
214 		DPRINTF(("%s: bogus returned buffer from crypto\n", __func__));
215 		return;
216 	}
217 
218 	NET_LOCK();
219 
220 	tdb = gettdb(tc->tc_rdomain, tc->tc_spi, &tc->tc_dst, tc->tc_proto);
221 	if (tdb == NULL) {
222 		free(tc, M_XDATA, 0);
223 		ipcompstat_inc(ipcomps_notdb);
224 		DPRINTF(("%s: TDB expired while in crypto", __func__));
225 		goto baddone;
226 	}
227 
228 	/* update the counters */
229 	tdb->tdb_cur_bytes += m->m_pkthdr.len - (skip + hlen);
230 	ipcompstat_add(ipcomps_ibytes, m->m_pkthdr.len - (skip + hlen));
231 
232 	/* Hard expiration */
233 	if ((tdb->tdb_flags & TDBF_BYTES) &&
234 	    (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) {
235 		free(tc, M_XDATA, 0);
236 		pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
237 		tdb_delete(tdb);
238 		goto baddone;
239 	}
240 	/* Notify on soft expiration */
241 	if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
242 	    (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) {
243 		pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
244 		tdb->tdb_flags &= ~TDBF_SOFT_BYTES;	/* Turn off checking */
245 	}
246 
247 	/* Check for crypto errors */
248 	if (crp->crp_etype) {
249 		if (crp->crp_etype == EAGAIN) {
250 			/* Reset the session ID */
251 			if (tdb->tdb_cryptoid != 0)
252 				tdb->tdb_cryptoid = crp->crp_sid;
253 			NET_UNLOCK();
254 			crypto_dispatch(crp);
255 			return;
256 		}
257 		free(tc, M_XDATA, 0);
258 		ipcompstat_inc(ipcomps_noxform);
259 		DPRINTF(("%s: crypto error %d\n", __func__,
260 		    crp->crp_etype));
261 		goto baddone;
262 	}
263 	free(tc, M_XDATA, 0);
264 
265 	/* Length of data after processing */
266 	clen = crp->crp_olen;
267 
268 	/* In case it's not done already, adjust the size of the mbuf chain */
269 	m->m_pkthdr.len = clen + hlen + skip;
270 
271 	if ((m->m_len < skip + hlen) && (m = m_pullup(m, skip + hlen)) == 0) {
272 		goto baddone;
273 	}
274 
275 	/* Find the beginning of the IPCOMP header */
276 	m1 = m_getptr(m, skip, &roff);
277 	if (m1 == NULL) {
278 		ipcompstat_inc(ipcomps_hdrops);
279 		DPRINTF(("%s: bad mbuf chain, IPCA %s/%08x\n", __func__,
280 		    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
281 		    ntohl(tdb->tdb_spi)));
282 		goto baddone;
283 	}
284 	/* Keep the next protocol field */
285 	addr = (caddr_t) mtod(m, struct ip *) + skip;
286 	ipcomp = (struct ipcomp *) addr;
287 	nproto = ipcomp->ipcomp_nh;
288 
289 	/* Remove the IPCOMP header from the mbuf */
290 	if (roff == 0) {
291 		/* The IPCOMP header is at the beginning of m1 */
292 		m_adj(m1, hlen);
293 		if (!(m1->m_flags & M_PKTHDR))
294 			m->m_pkthdr.len -= hlen;
295 	} else if (roff + hlen >= m1->m_len) {
296 		if (roff + hlen > m1->m_len) {
297 			/* Adjust the next mbuf by the remainder */
298 			m_adj(m1->m_next, roff + hlen - m1->m_len);
299 
300 			/*
301 			 * The second mbuf is guaranteed not to have a
302 			 * pkthdr...
303 			 */
304 			m->m_pkthdr.len -= (roff + hlen - m1->m_len);
305 		}
306 		/* Now, let's unlink the mbuf chain for a second... */
307 		mo = m1->m_next;
308 		m1->m_next = NULL;
309 
310 		/* ...and trim the end of the first part of the chain...sick */
311 		m_adj(m1, -(m1->m_len - roff));
312 		if (!(m1->m_flags & M_PKTHDR))
313 			m->m_pkthdr.len -= (m1->m_len - roff);
314 
315 		/* Finally, let's relink */
316 		m1->m_next = mo;
317 	} else {
318 		memmove(mtod(m1, u_char *) + roff,
319 		    mtod(m1, u_char *) + roff + hlen,
320 		    m1->m_len - (roff + hlen));
321 		m1->m_len -= hlen;
322 		m->m_pkthdr.len -= hlen;
323 	}
324 
325 	/* Release the crypto descriptors */
326 	crypto_freereq(crp);
327 
328 	/* Restore the Next Protocol field */
329 	m_copyback(m, protoff, sizeof(u_int8_t), &nproto, M_NOWAIT);
330 
331 	/* Back to generic IPsec input processing */
332 	ipsec_common_input_cb(m, tdb, skip, protoff);
333 	NET_UNLOCK();
334 	return;
335 
336 baddone:
337 	NET_UNLOCK();
338 
339 	m_freem(m);
340 
341 	crypto_freereq(crp);
342 }
343 
344 /*
345  * IPComp output routine, called by ipsp_process_packet()
346  */
347 int
348 ipcomp_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
349     int protoff)
350 {
351 	struct comp_algo *ipcompx = (struct comp_algo *) tdb->tdb_compalgxform;
352 	int             hlen;
353 	struct cryptodesc *crdc = NULL;
354 	struct cryptop *crp;
355 	struct tdb_crypto *tc;
356 	struct mbuf    *mi;
357 #ifdef ENCDEBUG
358 	char buf[INET6_ADDRSTRLEN];
359 #endif
360 #if NBPFILTER > 0
361 	struct ifnet *encif;
362 
363 	if ((encif = enc_getif(0, tdb->tdb_tap)) != NULL) {
364 		encif->if_opackets++;
365 		encif->if_obytes += m->m_pkthdr.len;
366 
367 		if (encif->if_bpf) {
368 			struct enchdr hdr;
369 
370 			memset(&hdr, 0, sizeof(hdr));
371 
372 			hdr.af = tdb->tdb_dst.sa.sa_family;
373 			hdr.spi = tdb->tdb_spi;
374 
375 			bpf_mtap_hdr(encif->if_bpf, (char *)&hdr,
376 			    ENC_HDRLEN, m, BPF_DIRECTION_OUT, NULL);
377 		}
378 	}
379 #endif
380 	hlen = IPCOMP_HLENGTH;
381 
382 	ipcompstat_inc(ipcomps_output);
383 
384 	switch (tdb->tdb_dst.sa.sa_family) {
385 	case AF_INET:
386 		/* Check for IPv4 maximum packet size violations */
387 		/*
388 		 * Since compression is going to reduce the size, no need to
389 		 * worry
390 		 */
391 		if (m->m_pkthdr.len + hlen > IP_MAXPACKET) {
392 			DPRINTF(("%s: packet in IPCA %s/%08x got too big\n",
393 			    __func__, ipsp_address(&tdb->tdb_dst, buf,
394 			    sizeof(buf)), ntohl(tdb->tdb_spi)));
395 			m_freem(m);
396 			ipcompstat_inc(ipcomps_toobig);
397 			return EMSGSIZE;
398 		}
399 		break;
400 
401 #ifdef INET6
402 	case AF_INET6:
403 		/* Check for IPv6 maximum packet size violations */
404 		if (m->m_pkthdr.len + hlen > IPV6_MAXPACKET) {
405 			DPRINTF(("%s: packet in IPCA %s/%08x got too big\n",
406 			    __func__, ipsp_address(&tdb->tdb_dst, buf,
407 			    sizeof(buf)), ntohl(tdb->tdb_spi)));
408 			m_freem(m);
409 			ipcompstat_inc(ipcomps_toobig);
410 			return EMSGSIZE;
411 		}
412 		break;
413 #endif /* INET6 */
414 
415 	default:
416 		DPRINTF(("%s: unknown/unsupported protocol family %d, "
417 		    "IPCA %s/%08x\n", __func__, tdb->tdb_dst.sa.sa_family,
418 		    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
419 		    ntohl(tdb->tdb_spi)));
420 		m_freem(m);
421 		ipcompstat_inc(ipcomps_nopf);
422 		return EPFNOSUPPORT;
423 	}
424 
425 	/* Update the counters */
426 
427 	tdb->tdb_cur_bytes += m->m_pkthdr.len - skip;
428 	ipcompstat_add(ipcomps_obytes, m->m_pkthdr.len - skip);
429 
430 	/* Hard byte expiration */
431 	if ((tdb->tdb_flags & TDBF_BYTES) &&
432 	    (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) {
433 		pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
434 		tdb_delete(tdb);
435 		m_freem(m);
436 		return EINVAL;
437 	}
438 	/* Soft byte expiration */
439 	if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
440 	    (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) {
441 		pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
442 		tdb->tdb_flags &= ~TDBF_SOFT_BYTES;	/* Turn off checking */
443 	}
444 	/*
445 	 * Loop through mbuf chain; if we find a readonly mbuf,
446 	 * copy the packet.
447 	 */
448 	mi = m;
449 	while (mi != NULL && !M_READONLY(mi))
450 		mi = mi->m_next;
451 
452 	if (mi != NULL) {
453 		struct mbuf *n = m_dup_pkt(m, 0, M_DONTWAIT);
454 
455 		if (n == NULL) {
456 			DPRINTF(("%s: bad mbuf chain, IPCA %s/%08x\n", __func__,
457 			    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
458 			    ntohl(tdb->tdb_spi)));
459 			ipcompstat_inc(ipcomps_hdrops);
460 			m_freem(m);
461 			return ENOBUFS;
462 		}
463 
464 		m_freem(m);
465 		m = n;
466 	}
467 	/* Ok now, we can pass to the crypto processing */
468 
469 	/* Get crypto descriptors */
470 	crp = crypto_getreq(1);
471 	if (crp == NULL) {
472 		m_freem(m);
473 		DPRINTF(("%s: failed to acquire crypto descriptors\n", __func__));
474 		ipcompstat_inc(ipcomps_crypto);
475 		return ENOBUFS;
476 	}
477 	crdc = &crp->crp_desc[0];
478 
479 	/* Compression descriptor */
480 	crdc->crd_skip = skip;
481 	crdc->crd_len = m->m_pkthdr.len - skip;
482 	crdc->crd_flags = CRD_F_COMP;
483 	crdc->crd_inject = skip;
484 
485 	/* Compression operation */
486 	crdc->crd_alg = ipcompx->type;
487 
488 	/* IPsec-specific opaque crypto info */
489 	tc = malloc(sizeof(*tc), M_XDATA, M_NOWAIT | M_ZERO);
490 	if (tc == NULL) {
491 		m_freem(m);
492 		crypto_freereq(crp);
493 		DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__));
494 		ipcompstat_inc(ipcomps_crypto);
495 		return ENOBUFS;
496 	}
497 
498 	tc->tc_spi = tdb->tdb_spi;
499 	tc->tc_proto = tdb->tdb_sproto;
500 	tc->tc_skip = skip;
501 	tc->tc_rdomain = tdb->tdb_rdomain;
502 	tc->tc_dst = tdb->tdb_dst;
503 
504 	/* Crypto operation descriptor */
505 	crp->crp_ilen = m->m_pkthdr.len;	/* Total input length */
506 	crp->crp_flags = CRYPTO_F_IMBUF;
507 	crp->crp_buf = (caddr_t)m;
508 	crp->crp_callback = ipcomp_output_cb;
509 	crp->crp_opaque = (caddr_t)tc;
510 	crp->crp_sid = tdb->tdb_cryptoid;
511 
512 	return crypto_dispatch(crp);
513 }
514 
515 /*
516  * IPComp output callback, called directly from the crypto driver
517  */
518 void
519 ipcomp_output_cb(struct cryptop *crp)
520 {
521 	struct tdb_crypto *tc;
522 	struct tdb *tdb;
523 	struct mbuf *m, *mo;
524 	int skip, rlen, roff;
525 	u_int16_t cpi;
526 	struct ip *ip;
527 #ifdef INET6
528 	struct ip6_hdr *ip6;
529 #endif
530 	struct ipcomp  *ipcomp;
531 #ifdef ENCDEBUG
532 	char buf[INET6_ADDRSTRLEN];
533 #endif
534 
535 	tc = (struct tdb_crypto *) crp->crp_opaque;
536 	skip = tc->tc_skip;
537 	rlen = crp->crp_ilen - skip;
538 
539 	m = (struct mbuf *) crp->crp_buf;
540 	if (m == NULL) {
541 		/* Shouldn't happen... */
542 		free(tc, M_XDATA, 0);
543 		crypto_freereq(crp);
544 		ipcompstat_inc(ipcomps_crypto);
545 		DPRINTF(("%s: bogus returned buffer from crypto\n", __func__));
546 		return;
547 	}
548 
549 	NET_LOCK();
550 
551 	tdb = gettdb(tc->tc_rdomain, tc->tc_spi, &tc->tc_dst, tc->tc_proto);
552 	if (tdb == NULL) {
553 		free(tc, M_XDATA, 0);
554 		ipcompstat_inc(ipcomps_notdb);
555 		DPRINTF(("%s: TDB expired while in crypto\n", __func__));
556 		goto baddone;
557 	}
558 
559 	/* Check for crypto errors. */
560 	if (crp->crp_etype) {
561 		if (crp->crp_etype == EAGAIN) {
562 			/* Reset the session ID */
563 			if (tdb->tdb_cryptoid != 0)
564 				tdb->tdb_cryptoid = crp->crp_sid;
565 			NET_UNLOCK();
566 			crypto_dispatch(crp);
567 			return;
568 		}
569 		free(tc, M_XDATA, 0);
570 		ipcompstat_inc(ipcomps_noxform);
571 		DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
572 		goto baddone;
573 	}
574 	free(tc, M_XDATA, 0);
575 
576 	/* Check sizes. */
577 	if (rlen < crp->crp_olen) {
578 		/* Compression was useless, we have lost time. */
579 		crypto_freereq(crp);
580 		if (ipsp_process_done(m, tdb))
581 			ipcompstat_inc(ipcomps_outfail);
582 		NET_UNLOCK();
583 		return;
584 	}
585 
586 	/* Inject IPCOMP header */
587 	mo = m_makespace(m, skip, IPCOMP_HLENGTH, &roff);
588 	if (mo == NULL) {
589 		DPRINTF(("%s: failed to inject IPCOMP header for "
590 		    "IPCA %s/%08x\n", __func__, ipsp_address(&tdb->tdb_dst, buf,
591 		     sizeof(buf)), ntohl(tdb->tdb_spi)));
592 		ipcompstat_inc(ipcomps_wrap);
593 		goto baddone;
594 	}
595 
596 	/* Initialize the IPCOMP header */
597 	ipcomp = (struct ipcomp *)(mtod(mo, caddr_t) + roff);
598 	memset(ipcomp, 0, sizeof(struct ipcomp));
599 	cpi = (u_int16_t) ntohl(tdb->tdb_spi);
600 	ipcomp->ipcomp_cpi = htons(cpi);
601 
602 	/* m_pullup before ? */
603 	switch (tdb->tdb_dst.sa.sa_family) {
604 	case AF_INET:
605 		ip = mtod(m, struct ip *);
606 		ipcomp->ipcomp_nh = ip->ip_p;
607 		ip->ip_p = IPPROTO_IPCOMP;
608 		break;
609 #ifdef INET6
610 	case AF_INET6:
611 		ip6 = mtod(m, struct ip6_hdr *);
612 		ipcomp->ipcomp_nh = ip6->ip6_nxt;
613 		ip6->ip6_nxt = IPPROTO_IPCOMP;
614 		break;
615 #endif
616 	default:
617 		DPRINTF(("%s: unsupported protocol family %d, IPCA %s/%08x\n",
618 		    __func__, tdb->tdb_dst.sa.sa_family,
619 		    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
620 		    ntohl(tdb->tdb_spi)));
621 		ipcompstat_inc(ipcomps_nopf);
622 		goto baddone;
623 		break;
624 	}
625 
626 	/* Release the crypto descriptor. */
627 	crypto_freereq(crp);
628 
629 	if (ipsp_process_done(m, tdb))
630 		ipcompstat_inc(ipcomps_outfail);
631 	NET_UNLOCK();
632 	return;
633 
634 baddone:
635 	NET_UNLOCK();
636 
637 	m_freem(m);
638 
639 	crypto_freereq(crp);
640 }
641