This source file includes following definitions.
- ipsp_process_packet
- ipsp_process_done
- ipsec_hdrsz
- ipsec_adjust_mtu
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #include "pf.h"
24
25 #include <sys/param.h>
26 #include <sys/systm.h>
27 #include <sys/mbuf.h>
28 #include <sys/socket.h>
29 #include <sys/kernel.h>
30
31 #include <net/if.h>
32 #include <net/route.h>
33
34 #if NPF > 0
35 #include <net/pfvar.h>
36 #endif
37
38 #ifdef INET
39 #include <netinet/in.h>
40 #include <netinet/in_systm.h>
41 #include <netinet/ip.h>
42 #include <netinet/in_pcb.h>
43 #include <netinet/ip_var.h>
44 #endif
45
46 #ifdef INET6
47 #ifndef INET
48 #include <netinet/in.h>
49 #endif
50 #include <netinet6/in6_var.h>
51 #endif
52
53 #include <netinet/udp.h>
54 #include <netinet/ip_ipsp.h>
55 #include <netinet/ip_ah.h>
56 #include <netinet/ip_esp.h>
57 #include <netinet/ip_ipcomp.h>
58 #include <crypto/xform.h>
59
60 #ifdef ENCDEBUG
61 #define DPRINTF(x) if (encdebug) printf x
62 #else
63 #define DPRINTF(x)
64 #endif
65
66 int udpencap_enable = 1;
67 int udpencap_port = 4500;
68
69
70
71
72
73
74 int
75 ipsp_process_packet(struct mbuf *m, struct tdb *tdb, int af, int tunalready)
76 {
77 struct timeval tv;
78 int i, off, error;
79 struct mbuf *mp;
80 #ifdef INET6
81 struct ip6_ext ip6e;
82 int nxt;
83 int dstopt = 0;
84 #endif
85
86 #ifdef INET
87 int setdf = 0;
88 struct ip *ip;
89 #endif
90 #ifdef INET6
91 struct ip6_hdr *ip6;
92 #endif
93
94
95 if ((tdb->tdb_sproto == IPPROTO_ESP && !esp_enable) ||
96 (tdb->tdb_sproto == IPPROTO_AH && !ah_enable) ||
97 (tdb->tdb_sproto == IPPROTO_IPCOMP && !ipcomp_enable)) {
98 DPRINTF(("ipsp_process_packet(): IPsec outbound packet "
99 "dropped due to policy (check your sysctls)\n"));
100 m_freem(m);
101 return EHOSTUNREACH;
102 }
103
104
105 if (!tdb->tdb_xform) {
106 DPRINTF(("ipsp_process_packet(): uninitialized TDB\n"));
107 m_freem(m);
108 return EHOSTUNREACH;
109 }
110
111
112 if (tdb->tdb_flags & TDBF_INVALID) {
113 DPRINTF(("ipsp_process_packet(): attempt to use invalid "
114 "SA %s/%08x/%u\n", ipsp_address(tdb->tdb_dst),
115 ntohl(tdb->tdb_spi), tdb->tdb_sproto));
116 m_freem(m);
117 return ENXIO;
118 }
119
120
121 switch (tdb->tdb_dst.sa.sa_family) {
122 #ifdef INET
123 case AF_INET:
124 break;
125 #endif
126
127 #ifdef INET6
128 case AF_INET6:
129 break;
130 #endif
131
132 default:
133 DPRINTF(("ipsp_process_packet(): attempt to use "
134 "SA %s/%08x/%u for protocol family %d\n",
135 ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi),
136 tdb->tdb_sproto, tdb->tdb_dst.sa.sa_family));
137 m_freem(m);
138 return ENXIO;
139 }
140
141
142
143
144 if (tdb->tdb_first_use == 0) {
145 tdb->tdb_first_use = time_second;
146
147 tv.tv_usec = 0;
148
149 tv.tv_sec = tdb->tdb_first_use + tdb->tdb_exp_first_use;
150 if (tdb->tdb_flags & TDBF_FIRSTUSE)
151 timeout_add(&tdb->tdb_first_tmo,
152 hzto(&tv));
153
154 tv.tv_sec = tdb->tdb_first_use + tdb->tdb_soft_first_use;
155 if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE)
156 timeout_add(&tdb->tdb_sfirst_tmo,
157 hzto(&tv));
158 }
159
160
161
162
163
164
165 if (tunalready == 0) {
166
167
168
169
170 if (af == tdb->tdb_dst.sa.sa_family) {
171 #ifdef INET
172 if (af == AF_INET)
173 i = sizeof(struct ip);
174 #endif
175
176 #ifdef INET6
177 if (af == AF_INET6)
178 i = sizeof(struct ip6_hdr);
179 #endif
180
181
182 if (m->m_len < i) {
183 if ((m = m_pullup(m, i)) == NULL)
184 return ENOBUFS;
185 }
186
187 #ifdef INET
188 ip = mtod(m, struct ip *);
189
190
191
192
193
194 setdf = ip->ip_off & htons(IP_DF);
195 #endif
196
197 #ifdef INET6
198 ip6 = mtod(m, struct ip6_hdr *);
199 #endif
200 }
201
202
203 if ((tdb->tdb_dst.sa.sa_family != af) ||
204 (tdb->tdb_flags & TDBF_TUNNELING) ||
205 (tdb->tdb_xform->xf_type == XF_IP4) ||
206 #ifdef INET
207 ((tdb->tdb_dst.sa.sa_family == AF_INET) &&
208 (tdb->tdb_dst.sin.sin_addr.s_addr != INADDR_ANY) &&
209 (tdb->tdb_dst.sin.sin_addr.s_addr != ip->ip_dst.s_addr)) ||
210 #endif
211 #ifdef INET6
212 ((tdb->tdb_dst.sa.sa_family == AF_INET6) &&
213 (!IN6_IS_ADDR_UNSPECIFIED(&tdb->tdb_dst.sin6.sin6_addr)) &&
214 (!IN6_ARE_ADDR_EQUAL(&tdb->tdb_dst.sin6.sin6_addr,
215 &ip6->ip6_dst))) ||
216 #endif
217 0) {
218 #ifdef INET
219
220 if (af == AF_INET) {
221 if (m->m_len < sizeof(struct ip))
222 if ((m = m_pullup(m,
223 sizeof(struct ip))) == NULL)
224 return ENOBUFS;
225
226 ip = mtod(m, struct ip *);
227 ip->ip_len = htons(m->m_pkthdr.len);
228 ip->ip_sum = 0;
229 ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
230 }
231 #endif
232
233 #ifdef INET6
234
235 if (af == AF_INET6) {
236 if (m->m_len < sizeof(struct ip6_hdr))
237 if ((m = m_pullup(m,
238 sizeof(struct ip6_hdr))) == NULL)
239 return ENOBUFS;
240
241 if (m->m_pkthdr.len - sizeof(*ip6) >
242 IPV6_MAXPACKET) {
243
244 m_freem(m);
245 return ENXIO;
246 }
247 ip6 = mtod(m, struct ip6_hdr *);
248 ip6->ip6_plen = htons(m->m_pkthdr.len
249 - sizeof(*ip6));
250 }
251 #endif
252
253
254 error = ipip_output(m, tdb, &mp, 0, 0);
255 if ((mp == NULL) && (!error))
256 error = EFAULT;
257 if (error) {
258 if (mp) {
259 m_freem(mp);
260 mp = NULL;
261 }
262 return error;
263 }
264
265 m = mp;
266 mp = NULL;
267
268 #ifdef INET
269 if (tdb->tdb_dst.sa.sa_family == AF_INET && setdf) {
270 if (m->m_len < sizeof(struct ip))
271 if ((m = m_pullup(m,
272 sizeof(struct ip))) == NULL)
273 return ENOBUFS;
274
275 ip = mtod(m, struct ip *);
276 ip->ip_off |= htons(IP_DF);
277 }
278 #endif
279
280
281 tdb->tdb_flags |= TDBF_USEDTUNNEL;
282 }
283
284
285 if (tdb->tdb_xform->xf_type == XF_IP4)
286 return ipsp_process_done(m, tdb);
287 } else {
288
289
290
291
292 if (tdb->tdb_xform->xf_type == XF_IP4)
293 return ipsp_process_done(m, tdb);
294 }
295
296
297 switch (tdb->tdb_dst.sa.sa_family) {
298 #ifdef INET
299 case AF_INET:
300 ip = mtod(m, struct ip *);
301 i = ip->ip_hl << 2;
302 off = offsetof(struct ip, ip_p);
303 break;
304 #endif
305
306 #ifdef INET6
307 case AF_INET6:
308 ip6 = mtod(m, struct ip6_hdr *);
309 i = sizeof(struct ip6_hdr);
310 off = offsetof(struct ip6_hdr, ip6_nxt);
311 nxt = ip6->ip6_nxt;
312
313
314
315
316
317 do {
318 switch (nxt) {
319 case IPPROTO_AH:
320 case IPPROTO_ESP:
321 case IPPROTO_IPCOMP:
322
323
324
325
326 goto exitip6loop;
327
328 case IPPROTO_HOPOPTS:
329 case IPPROTO_DSTOPTS:
330 case IPPROTO_ROUTING:
331
332
333
334
335 if (nxt == IPPROTO_DSTOPTS && dstopt)
336 goto exitip6loop;
337
338 if (nxt == IPPROTO_DSTOPTS) {
339
340
341
342
343 dstopt = 1;
344 } else if (nxt == IPPROTO_ROUTING) {
345
346
347
348
349 dstopt = 2;
350 }
351
352
353 m_copydata(m, i, sizeof(ip6e), (caddr_t)&ip6e);
354 nxt = ip6e.ip6e_nxt;
355 off = i + offsetof(struct ip6_ext, ip6e_nxt);
356
357
358
359
360 i += (ip6e.ip6e_len + 1) << 3;
361 break;
362 default:
363 goto exitip6loop;
364 }
365 } while (i < m->m_pkthdr.len);
366 exitip6loop:;
367 break;
368 #endif
369 }
370
371
372 if (tdb->tdb_sproto == IPPROTO_IPCOMP) {
373 if ((m->m_pkthdr.len - i) < tdb->tdb_compalgxform->minlen) {
374 extern struct ipcompstat ipcompstat;
375
376
377 ipcompstat.ipcomps_minlen++;
378 return ipsp_process_done(m, tdb);
379 }
380 }
381
382
383 return (*(tdb->tdb_xform->xf_output))(m, tdb, NULL, i, off);
384 }
385
386
387
388
389
390 int
391 ipsp_process_done(struct mbuf *m, struct tdb *tdb)
392 {
393 #ifdef INET
394 struct ip *ip;
395 #endif
396
397 #ifdef INET6
398 struct ip6_hdr *ip6;
399 #endif
400
401 struct tdb_ident *tdbi;
402 struct m_tag *mtag;
403
404 tdb->tdb_last_used = time_second;
405
406 if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0) {
407 struct mbuf *mi;
408 struct udphdr *uh;
409
410 if (!udpencap_enable || !udpencap_port) {
411 m_freem(m);
412 return ENXIO;
413 }
414 mi = m_inject(m, sizeof(struct ip), sizeof(struct udphdr),
415 M_DONTWAIT);
416 if (mi == NULL) {
417 m_freem(m);
418 return ENOMEM;
419 }
420 uh = mtod(mi, struct udphdr *);
421 uh->uh_sport = uh->uh_dport = htons(udpencap_port);
422 if (tdb->tdb_udpencap_port)
423 uh->uh_dport = tdb->tdb_udpencap_port;
424
425 uh->uh_ulen = htons(m->m_pkthdr.len - sizeof(struct ip));
426 uh->uh_sum = 0;
427 espstat.esps_udpencout++;
428 }
429
430 switch (tdb->tdb_dst.sa.sa_family) {
431 #ifdef INET
432 case AF_INET:
433
434 ip = mtod(m, struct ip *);
435 ip->ip_len = htons(m->m_pkthdr.len);
436 if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0)
437 ip->ip_p = IPPROTO_UDP;
438 break;
439 #endif
440
441 #ifdef INET6
442 case AF_INET6:
443
444 if (m->m_pkthdr.len < sizeof(*ip6)) {
445 m_freem(m);
446 return ENXIO;
447 }
448 if (m->m_pkthdr.len - sizeof(*ip6) > IPV6_MAXPACKET) {
449
450 m_freem(m);
451 return ENXIO;
452 }
453 ip6 = mtod(m, struct ip6_hdr *);
454 ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6));
455 if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0)
456 ip6->ip6_nxt = IPPROTO_UDP;
457 break;
458 #endif
459
460 default:
461 m_freem(m);
462 DPRINTF(("ipsp_process_done(): unknown protocol family (%d)\n",
463 tdb->tdb_dst.sa.sa_family));
464 return ENXIO;
465 }
466
467
468
469
470
471 if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0)
472 mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE,
473 sizeof(struct tdb_ident),
474 M_NOWAIT);
475 else
476 mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED,
477 sizeof(struct tdb_ident), M_NOWAIT);
478
479 if (mtag == NULL) {
480 m_freem(m);
481 DPRINTF(("ipsp_process_done(): could not allocate packet "
482 "tag\n"));
483 return ENOMEM;
484 }
485
486 tdbi = (struct tdb_ident *)(mtag + 1);
487 bcopy(&tdb->tdb_dst, &tdbi->dst, sizeof(union sockaddr_union));
488 tdbi->proto = tdb->tdb_sproto;
489 tdbi->spi = tdb->tdb_spi;
490
491 m_tag_prepend(m, mtag);
492
493
494 if (tdb->tdb_onext)
495 return ipsp_process_packet(m, tdb->tdb_onext,
496 tdb->tdb_dst.sa.sa_family, 0);
497
498 #if NPF > 0
499
500 if (pf_tag_packet(m, tdb->tdb_tag, -1))
501 DPRINTF(("failed to tag ipsec packet\n"));
502 #endif
503
504
505
506
507
508
509 switch (tdb->tdb_dst.sa.sa_family) {
510 #ifdef INET
511 case AF_INET:
512 return ip_output(m, (void *)NULL, (void *)NULL, IP_RAWOUTPUT, (void *)NULL, (void *)NULL);
513 #endif
514
515 #ifdef INET6
516 case AF_INET6:
517
518
519
520
521 return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
522 #endif
523 }
524 return EINVAL;
525 }
526
527 ssize_t
528 ipsec_hdrsz(struct tdb *tdbp)
529 {
530 ssize_t adjust;
531
532 switch (tdbp->tdb_sproto) {
533 case IPPROTO_IPIP:
534 adjust = 0;
535 break;
536
537 case IPPROTO_ESP:
538 if (tdbp->tdb_encalgxform == NULL)
539 return (-1);
540
541
542 if (tdbp->tdb_flags & TDBF_NOREPLAY)
543 adjust = sizeof(u_int32_t) + tdbp->tdb_ivlen;
544 else
545 adjust = 2 * sizeof(u_int32_t) + tdbp->tdb_ivlen;
546 if (tdbp->tdb_flags & TDBF_UDPENCAP)
547 adjust += sizeof(struct udphdr);
548
549 if (tdbp->tdb_authalgxform != NULL)
550 adjust += AH_HMAC_HASHLEN;
551
552 adjust += tdbp->tdb_encalgxform->blocksize;
553 break;
554
555 case IPPROTO_AH:
556 if (tdbp->tdb_authalgxform == NULL)
557 return (-1);
558
559 if (!(tdbp->tdb_flags & TDBF_NOREPLAY))
560 adjust = AH_FLENGTH + sizeof(u_int32_t);
561 else
562 adjust = AH_FLENGTH;
563 adjust += tdbp->tdb_authalgxform->authsize;
564 break;
565
566 default:
567 return (-1);
568 }
569
570 if (!(tdbp->tdb_flags & TDBF_TUNNELING) &&
571 !(tdbp->tdb_flags & TDBF_USEDTUNNEL))
572 return (adjust);
573
574 switch (tdbp->tdb_dst.sa.sa_family) {
575 #ifdef INET
576 case AF_INET:
577 adjust += sizeof(struct ip);
578 break;
579 #endif
580 #ifdef INET6
581 case AF_INET6:
582 adjust += sizeof(struct ip6_hdr);
583 break;
584 #endif
585 }
586
587 return (adjust);
588 }
589
590 void
591 ipsec_adjust_mtu(struct mbuf *m, u_int32_t mtu)
592 {
593 struct tdb_ident *tdbi;
594 struct tdb *tdbp;
595 struct m_tag *mtag;
596 ssize_t adjust;
597 int s;
598
599 s = spltdb();
600
601 for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, NULL); mtag;
602 mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, mtag)) {
603 tdbi = (struct tdb_ident *)(mtag + 1);
604 tdbp = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto);
605 if (tdbp == NULL)
606 break;
607
608 if ((adjust = ipsec_hdrsz(tdbp)) == -1)
609 break;
610
611 mtu -= adjust;
612 tdbp->tdb_mtu = mtu;
613 tdbp->tdb_mtutimeout = time_second + ip_mtudisc_timeout;
614 DPRINTF(("ipsec_adjust_mtu: "
615 "spi %08x mtu %d adjust %d mbuf %p\n",
616 ntohl(tdbp->tdb_spi), tdbp->tdb_mtu,
617 adjust, m));
618 }
619
620 splx(s);
621 }