This source file includes following definitions.
- ipcomp_attach
- ipcomp_init
- ipcomp_zeroize
- ipcomp_input
- ipcomp_input_cb
- ipcomp_output
- ipcomp_output_cb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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/bpf.h>
39
40 #include <dev/rndvar.h>
41
42 #ifdef INET
43 #include <netinet/in.h>
44 #include <netinet/in_systm.h>
45 #include <netinet/ip.h>
46 #endif
47
48 #ifdef INET6
49 #ifndef INET
50 #include <netinet/in.h>
51 #endif
52 #include <netinet/ip6.h>
53 #endif
54
55 #include <netinet/ip_ipsp.h>
56 #include <netinet/ip_ipcomp.h>
57 #include <net/pfkeyv2.h>
58 #include <net/if_enc.h>
59
60 #include <crypto/cryptodev.h>
61 #include <crypto/deflate.h>
62 #include <crypto/xform.h>
63
64 #include "bpfilter.h"
65
66 #ifdef ENCDEBUG
67 #define DPRINTF(x) if (encdebug) printf x
68 #else
69 #define DPRINTF(x)
70 #endif
71
72 struct ipcompstat ipcompstat;
73
74
75
76
77 int
78 ipcomp_attach(void)
79 {
80 return 0;
81 }
82
83
84
85
86 int
87 ipcomp_init(tdbp, xsp, ii)
88 struct tdb *tdbp;
89 struct xformsw *xsp;
90 struct ipsecinit *ii;
91 {
92 struct comp_algo *tcomp = NULL;
93 struct cryptoini cric;
94
95 switch (ii->ii_compalg) {
96 case SADB_X_CALG_DEFLATE:
97 tcomp = &comp_algo_deflate;
98 break;
99 case SADB_X_CALG_LZS:
100 tcomp = &comp_algo_lzs;
101 break;
102
103 default:
104 DPRINTF(("ipcomp_init(): unsupported compression algorithm %d specified\n",
105 ii->ii_compalg));
106 return EINVAL;
107 }
108
109 tdbp->tdb_compalgxform = tcomp;
110
111 DPRINTF(("ipcomp_init(): initialized TDB with ipcomp algorithm %s\n",
112 tcomp->name));
113
114 tdbp->tdb_xform = xsp;
115 tdbp->tdb_bitmap = 0;
116
117
118 bzero(&cric, sizeof(cric));
119 cric.cri_alg = tdbp->tdb_compalgxform->type;
120
121 return crypto_newsession(&tdbp->tdb_cryptoid, &cric, 0);
122 }
123
124
125
126
127 int
128 ipcomp_zeroize(tdbp)
129 struct tdb *tdbp;
130 {
131 int err;
132
133 err = crypto_freesession(tdbp->tdb_cryptoid);
134 tdbp->tdb_cryptoid = 0;
135 return err;
136 }
137
138
139
140
141 int
142 ipcomp_input(m, tdb, skip, protoff)
143 struct mbuf *m;
144 struct tdb *tdb;
145 int skip;
146 int protoff;
147 {
148 struct comp_algo *ipcompx = (struct comp_algo *) tdb->tdb_compalgxform;
149 struct tdb_crypto *tc;
150 int hlen;
151
152 struct cryptodesc *crdc = NULL;
153 struct cryptop *crp;
154
155 hlen = IPCOMP_HLENGTH;
156
157
158 crp = crypto_getreq(1);
159 if (crp == NULL) {
160 m_freem(m);
161 DPRINTF(("ipcomp_input(): failed to acquire crypto descriptors\n"));
162 ipcompstat.ipcomps_crypto++;
163 return ENOBUFS;
164 }
165
166 MALLOC(tc, struct tdb_crypto *, sizeof(struct tdb_crypto),
167 M_XDATA, M_NOWAIT);
168 if (tc == NULL) {
169 m_freem(m);
170 crypto_freereq(crp);
171 DPRINTF(("ipcomp_input(): failed to allocate tdb_crypto\n"));
172 ipcompstat.ipcomps_crypto++;
173 return ENOBUFS;
174 }
175 bzero(tc, sizeof(struct tdb_crypto));
176 crdc = crp->crp_desc;
177
178 crdc->crd_skip = skip + hlen;
179 crdc->crd_len = m->m_pkthdr.len - (skip + hlen);
180 crdc->crd_inject = skip;
181
182 tc->tc_ptr = 0;
183
184
185 crdc->crd_alg = ipcompx->type;
186
187
188 crp->crp_ilen = m->m_pkthdr.len - (skip + hlen);
189 crp->crp_flags = CRYPTO_F_IMBUF;
190 crp->crp_buf = (caddr_t) m;
191 crp->crp_callback = (int (*) (struct cryptop *)) ipcomp_input_cb;
192 crp->crp_sid = tdb->tdb_cryptoid;
193 crp->crp_opaque = (caddr_t) tc;
194
195
196 tc->tc_skip = skip;
197 tc->tc_protoff = protoff;
198 tc->tc_spi = tdb->tdb_spi;
199 tc->tc_proto = IPPROTO_IPCOMP;
200 bcopy(&tdb->tdb_dst, &tc->tc_dst, sizeof(union sockaddr_union));
201
202 return crypto_dispatch(crp);
203 }
204
205
206
207
208 int
209 ipcomp_input_cb(op)
210 void *op;
211 {
212 int error, s, skip, protoff, roff, hlen = IPCOMP_HLENGTH, clen;
213 u_int8_t nproto;
214 struct mbuf *m, *m1, *mo;
215 struct cryptodesc *crd;
216 struct comp_algo *ipcompx;
217 struct tdb_crypto *tc;
218 struct cryptop *crp;
219 struct tdb *tdb;
220 struct ipcomp *ipcomp;
221 caddr_t addr;
222
223 crp = (struct cryptop *) op;
224 crd = crp->crp_desc;
225
226 tc = (struct tdb_crypto *) crp->crp_opaque;
227 skip = tc->tc_skip;
228 protoff = tc->tc_protoff;
229
230 m = (struct mbuf *) crp->crp_buf;
231 if (m == NULL) {
232
233 FREE(tc, M_XDATA);
234 crypto_freereq(crp);
235 ipcompstat.ipcomps_crypto++;
236 DPRINTF(("ipcomp_input_cb(): bogus returned buffer from crypto\n"));
237 return (EINVAL);
238 }
239
240 s = spltdb();
241
242 tdb = gettdb(tc->tc_spi, &tc->tc_dst, tc->tc_proto);
243 if (tdb == NULL) {
244 FREE(tc, M_XDATA);
245 ipcompstat.ipcomps_notdb++;
246 DPRINTF(("ipcomp_input_cb(): TDB expired while in crypto"));
247 error = EPERM;
248 goto baddone;
249 }
250 ipcompx = (struct comp_algo *) tdb->tdb_compalgxform;
251
252
253 tdb->tdb_cur_bytes += m->m_pkthdr.len - (skip + hlen);
254 ipcompstat.ipcomps_ibytes += m->m_pkthdr.len - (skip + hlen);
255
256
257 if ((tdb->tdb_flags & TDBF_BYTES) &&
258 (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) {
259 FREE(tc, M_XDATA);
260 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
261 tdb_delete(tdb);
262 error = ENXIO;
263 goto baddone;
264 }
265
266 if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
267 (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) {
268 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
269 tdb->tdb_flags &= ~TDBF_SOFT_BYTES;
270 }
271
272
273 if (crp->crp_etype) {
274 if (crp->crp_etype == EAGAIN) {
275
276 if (tdb->tdb_cryptoid != 0)
277 tdb->tdb_cryptoid = crp->crp_sid;
278 splx(s);
279 return crypto_dispatch(crp);
280 }
281 FREE(tc, M_XDATA);
282 ipcompstat.ipcomps_noxform++;
283 DPRINTF(("ipcomp_input_cb(): crypto error %d\n",
284 crp->crp_etype));
285 error = crp->crp_etype;
286 goto baddone;
287 }
288 FREE(tc, M_XDATA);
289
290
291 clen = crp->crp_olen;
292
293
294 m->m_pkthdr.len = clen + hlen + skip;
295
296 if ((m->m_len < skip + hlen) && (m = m_pullup(m, skip + hlen)) == 0) {
297 error = ENOBUFS;
298 goto baddone;
299 }
300
301
302 m1 = m_getptr(m, skip, &roff);
303 if (m1 == NULL) {
304 ipcompstat.ipcomps_hdrops++;
305 DPRINTF(("ipcomp_input_cb(): bad mbuf chain, IPCA %s/%08x\n",
306 ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
307 error = EINVAL;
308 goto baddone;
309 }
310
311 addr = (caddr_t) mtod(m, struct ip *) + skip;
312 ipcomp = (struct ipcomp *) addr;
313 nproto = ipcomp->ipcomp_nh;
314
315
316 if (roff == 0) {
317
318 m_adj(m1, hlen);
319 if (!(m1->m_flags & M_PKTHDR))
320 m->m_pkthdr.len -= hlen;
321 } else if (roff + hlen >= m1->m_len) {
322 if (roff + hlen > m1->m_len) {
323
324 m_adj(m1->m_next, roff + hlen - m1->m_len);
325
326
327
328
329
330 m->m_pkthdr.len -= (roff + hlen - m1->m_len);
331 }
332
333 mo = m1->m_next;
334 m1->m_next = NULL;
335
336
337 m_adj(m1, -(m1->m_len - roff));
338 if (!(m1->m_flags & M_PKTHDR))
339 m->m_pkthdr.len -= (m1->m_len - roff);
340
341
342 m1->m_next = mo;
343 } else {
344 bcopy(mtod(m1, u_char *) + roff + hlen,
345 mtod(m1, u_char *) + roff,
346 m1->m_len - (roff + hlen));
347 m1->m_len -= hlen;
348 m->m_pkthdr.len -= hlen;
349 }
350
351
352 crypto_freereq(crp);
353
354
355 m_copyback(m, protoff, sizeof(u_int8_t), &nproto);
356
357
358 error = ipsec_common_input_cb(m, tdb, skip, protoff, NULL);
359 splx(s);
360 return error;
361
362 baddone:
363 splx(s);
364
365 if (m)
366 m_freem(m);
367
368 crypto_freereq(crp);
369
370 return error;
371 }
372
373
374
375
376 int
377 ipcomp_output(m, tdb, mp, skip, protoff)
378 struct mbuf *m;
379 struct tdb *tdb;
380 struct mbuf **mp;
381 int skip;
382 int protoff;
383 {
384 struct comp_algo *ipcompx = (struct comp_algo *) tdb->tdb_compalgxform;
385 int hlen;
386 struct cryptodesc *crdc = NULL;
387 struct cryptop *crp;
388 struct tdb_crypto *tc;
389 struct mbuf *mi, *mo;
390 #if NBPFILTER > 0
391 struct ifnet *ifn = &(encif[0].sc_if);
392
393 if (ifn->if_bpf) {
394 struct enchdr hdr;
395
396 bzero(&hdr, sizeof(hdr));
397
398 hdr.af = tdb->tdb_dst.sa.sa_family;
399 hdr.spi = tdb->tdb_spi;
400
401 bpf_mtap_hdr(ifn->if_bpf, (char *)&hdr, ENC_HDRLEN, m,
402 BPF_DIRECTION_OUT);
403 }
404 #endif
405 hlen = IPCOMP_HLENGTH;
406
407 ipcompstat.ipcomps_output++;
408
409 switch (tdb->tdb_dst.sa.sa_family) {
410 #ifdef INET
411 case AF_INET:
412
413
414
415
416
417 if (m->m_pkthdr.len + hlen > IP_MAXPACKET) {
418 DPRINTF(("ipcomp_output(): packet in IPCA %s/%08x got too big\n",
419 ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
420 m_freem(m);
421 ipcompstat.ipcomps_toobig++;
422 return EMSGSIZE;
423 }
424 break;
425 #endif
426
427 #ifdef INET6
428 case AF_INET6:
429
430 if (m->m_pkthdr.len + hlen > IPV6_MAXPACKET) {
431 DPRINTF(("ipcomp_output(): packet in IPCA %s/%08x got too big\n",
432 ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
433 m_freem(m);
434 ipcompstat.ipcomps_toobig++;
435 return EMSGSIZE;
436 }
437 #endif
438
439 default:
440 DPRINTF(("ipcomp_output(): unknown/unsupported protocol family %d, IPCA %s/%08x\n",
441 tdb->tdb_dst.sa.sa_family, ipsp_address(tdb->tdb_dst),
442 ntohl(tdb->tdb_spi)));
443 m_freem(m);
444 ipcompstat.ipcomps_nopf++;
445 return EPFNOSUPPORT;
446 }
447
448
449
450 tdb->tdb_cur_bytes += m->m_pkthdr.len - skip;
451 ipcompstat.ipcomps_obytes += m->m_pkthdr.len - skip;
452
453
454 if ((tdb->tdb_flags & TDBF_BYTES) &&
455 (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) {
456 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
457 tdb_delete(tdb);
458 m_freem(m);
459 return EINVAL;
460 }
461
462 if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
463 (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) {
464 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
465 tdb->tdb_flags &= ~TDBF_SOFT_BYTES;
466 }
467
468
469
470
471 mo = NULL;
472 mi = m;
473 while (mi != NULL && !M_READONLY(mi)) {
474 mo = mi;
475 mi = mi->m_next;
476 }
477
478 if (mi != NULL) {
479
480 struct mbuf *n = m_copym2(mi, 0, M_COPYALL, M_DONTWAIT);
481
482 if (n == NULL) {
483 DPRINTF(("ipcomp_output(): bad mbuf chain, IPCA %s/%08x\n",
484 ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
485 ipcompstat.ipcomps_hdrops++;
486 m_freem(m);
487 return ENOBUFS;
488 }
489 if (mo != NULL)
490 mo->m_next = n;
491 else
492 m = n;
493
494 m_freem(mi);
495 }
496
497
498
499 crp = crypto_getreq(1);
500 if (crp == NULL) {
501 m_freem(m);
502 DPRINTF(("ipcomp_output(): failed to acquire crypto descriptors\n"));
503 ipcompstat.ipcomps_crypto++;
504 return ENOBUFS;
505 }
506 crdc = crp->crp_desc;
507
508
509 crdc->crd_skip = skip;
510 crdc->crd_len = m->m_pkthdr.len - skip;
511 crdc->crd_flags = CRD_F_COMP;
512 crdc->crd_inject = skip;
513
514
515 crdc->crd_alg = ipcompx->type;
516
517
518 MALLOC(tc, struct tdb_crypto *, sizeof(struct tdb_crypto),
519 M_XDATA, M_NOWAIT);
520 if (tc == NULL) {
521 m_freem(m);
522 crypto_freereq(crp);
523 DPRINTF(("ipcomp_output(): failed to allocate tdb_crypto\n"));
524 ipcompstat.ipcomps_crypto++;
525 return ENOBUFS;
526 }
527 bzero(tc, sizeof(struct tdb_crypto));
528
529 tc->tc_spi = tdb->tdb_spi;
530 tc->tc_proto = tdb->tdb_sproto;
531 tc->tc_skip = skip;
532 bcopy(&tdb->tdb_dst, &tc->tc_dst, sizeof(union sockaddr_union));
533
534
535 crp->crp_ilen = m->m_pkthdr.len;
536 crp->crp_flags = CRYPTO_F_IMBUF;
537 crp->crp_buf = (caddr_t) m;
538 crp->crp_callback = (int (*) (struct cryptop *)) ipcomp_output_cb;
539 crp->crp_opaque = (caddr_t) tc;
540 crp->crp_sid = tdb->tdb_cryptoid;
541
542 return crypto_dispatch(crp);
543 }
544
545
546
547
548 int
549 ipcomp_output_cb(cp)
550 void *cp;
551 {
552 struct cryptop *crp = (struct cryptop *) cp;
553 struct tdb_crypto *tc;
554 struct tdb *tdb;
555 struct mbuf *m, *mo;
556 int error, s, skip, rlen;
557 u_int16_t cpi;
558 #ifdef INET
559 struct ip *ip;
560 #endif
561 #ifdef INET6
562 struct ip6_hdr *ip6;
563 #endif
564 struct ipcomp *ipcomp;
565
566 tc = (struct tdb_crypto *) crp->crp_opaque;
567 skip = tc->tc_skip;
568 rlen = crp->crp_ilen - skip;
569
570 m = (struct mbuf *) crp->crp_buf;
571 if (m == NULL) {
572
573 FREE(tc, M_XDATA);
574 crypto_freereq(crp);
575 ipcompstat.ipcomps_crypto++;
576 DPRINTF(("ipcomp_output_cb(): bogus returned buffer from "
577 "crypto\n"));
578 return (EINVAL);
579 }
580
581 s = spltdb();
582
583 tdb = gettdb(tc->tc_spi, &tc->tc_dst, tc->tc_proto);
584 if (tdb == NULL) {
585 FREE(tc, M_XDATA);
586 ipcompstat.ipcomps_notdb++;
587 DPRINTF(("ipcomp_output_cb(): TDB expired while in crypto\n"));
588 error = EPERM;
589 goto baddone;
590 }
591
592
593 if (crp->crp_etype) {
594 if (crp->crp_etype == EAGAIN) {
595
596 if (tdb->tdb_cryptoid != 0)
597 tdb->tdb_cryptoid = crp->crp_sid;
598 splx(s);
599 return crypto_dispatch(crp);
600 }
601 FREE(tc, M_XDATA);
602 ipcompstat.ipcomps_noxform++;
603 DPRINTF(("ipcomp_output_cb(): crypto error %d\n",
604 crp->crp_etype));
605 error = crp->crp_etype;
606 goto baddone;
607 }
608 FREE(tc, M_XDATA);
609
610
611 if (rlen < crp->crp_olen) {
612
613 crypto_freereq(crp);
614 error = ipsp_process_done(m, tdb);
615 splx(s);
616 return error;
617 }
618
619
620 mo = m_inject(m, skip, IPCOMP_HLENGTH, M_DONTWAIT);
621 if (mo == NULL) {
622 DPRINTF(("ipcomp_output_cb(): failed to inject IPCOMP header "
623 "for IPCA %s/%08x\n",
624 ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
625 ipcompstat.ipcomps_wrap++;
626 error = ENOBUFS;
627 goto baddone;
628 }
629
630
631 ipcomp = mtod(mo, struct ipcomp *);
632 bzero(ipcomp, sizeof(struct ipcomp));
633 cpi = (u_int16_t) ntohl(tdb->tdb_spi);
634 ipcomp->ipcomp_cpi = htons(cpi);
635
636
637 switch (tdb->tdb_dst.sa.sa_family) {
638 #ifdef INET
639 case AF_INET:
640 ip = mtod(m, struct ip *);
641 ipcomp->ipcomp_nh = ip->ip_p;
642 ip->ip_p = IPPROTO_IPCOMP;
643 break;
644 #endif
645 #ifdef INET6
646 case AF_INET6:
647 ip6 = mtod(m, struct ip6_hdr *);
648 ipcomp->ipcomp_nh = ip6->ip6_nxt;
649 ip6->ip6_nxt = IPPROTO_IPCOMP;
650 break;
651 #endif
652 default:
653 DPRINTF(("ipcomp_output_cb(): unsupported protocol family %d, "
654 "IPCA %s/%08x\n",
655 tdb->tdb_dst.sa.sa_family, ipsp_address(tdb->tdb_dst),
656 ntohl(tdb->tdb_spi)));
657 ipcompstat.ipcomps_nopf++;
658 error = EPFNOSUPPORT;
659 goto baddone;
660 break;
661 }
662
663
664 crypto_freereq(crp);
665
666 error = ipsp_process_done(m, tdb);
667 splx(s);
668 return error;
669
670 baddone:
671 splx(s);
672
673 if (m)
674 m_freem(m);
675
676 crypto_freereq(crp);
677
678 return error;
679 }