1 /* $NetBSD: ip_fil_netbsd.c,v 1.3.2.11 2004/11/12 05:58:46 jmc Exp $ */
2
3 /*
4 * Copyright (C) 1993-2003 by Darren Reed.
5 *
6 * See the IPFILTER.LICENCE file for details on licencing.
7 */
8 #if !defined(lint)
9 static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
10 static const char rcsid[] = "@(#)Id: ip_fil_netbsd.c,v 2.55.2.12 2004/07/06 11:15:50 darrenr Exp";
11 #endif
12
13 #if defined(KERNEL) || defined(_KERNEL)
14 # undef KERNEL
15 # undef _KERNEL
16 # define KERNEL 1
17 # define _KERNEL 1
18 #endif
19 #include <sys/param.h>
20 #if (NetBSD >= 199905) && !defined(IPFILTER_LKM) && defined(_KERNEL)
21 # include "opt_ipfilter_log.h"
22 # include "opt_pfil_hooks.h"
23 # include "opt_ipsec.h"
24 #endif
25 #include <sys/errno.h>
26 #include <sys/types.h>
27 #include <sys/file.h>
28 #include <sys/ioctl.h>
29 #include <sys/time.h>
30 #include <sys/systm.h>
31 #if (NetBSD > 199609)
32 # include <sys/dirent.h>
33 #else
34 # include <sys/dir.h>
35 #endif
36 #include <sys/mbuf.h>
37 #include <sys/protosw.h>
38 #include <sys/socket.h>
39
40 #include <net/if.h>
41 #include <net/route.h>
42 #include <netinet/in.h>
43 #include <netinet/in_var.h>
44 #include <netinet/in_systm.h>
45 #include <netinet/ip.h>
46 #include <netinet/ip_var.h>
47 #include <netinet/tcp.h>
48 #include <netinet/udp.h>
49 #include <netinet/tcpip.h>
50 #include <netinet/ip_icmp.h>
51 #include "netinet/ip_compat.h"
52 #ifdef USE_INET6
53 # include <netinet/icmp6.h>
54 # if (__NetBSD_Version__ >= 106000000)
55 # include <netinet6/nd6.h>
56 # endif
57 #endif
58 #include "netinet/ip_fil.h"
59 #include "netinet/ip_nat.h"
60 #include "netinet/ip_frag.h"
61 #include "netinet/ip_state.h"
62 #include "netinet/ip_proxy.h"
63 #include "netinet/ip_auth.h"
64 #ifdef IPFILTER_SYNC
65 #include "netinet/ip_sync.h"
66 #endif
67 #ifdef IPFILTER_SCAN
68 #include "netinet/ip_scan.h"
69 #endif
70 #include "netinet/ip_pool.h"
71 #include <sys/md5.h>
72 #include <sys/kernel.h>
73 extern int ip_optcopy __P((struct ip *, struct ip *));
74
75 #ifdef IPFILTER_M_IPFILTER
76 MALLOC_DEFINE(M_IPFILTER, "IP Filter", "IP Filter packet filter data structures");
77 #endif
78
79 #if __NetBSD_Version__ >= 105009999
80 # define csuminfo csum_flags
81 #endif
82
83 extern struct protosw inetsw[];
84
85 static int (*fr_savep) __P((ip_t *, int, void *, int, struct mbuf **));
86 static int fr_send_ip __P((fr_info_t *, mb_t *, mb_t **));
87 #ifdef KMUTEX_T
88 extern ipfmutex_t ipf_rw;
89 extern ipfrwlock_t ipf_mutex;
90 #endif
91 #ifdef USE_INET6
92 static int ipfr_fastroute6 __P((struct mbuf *, struct mbuf **,
93 fr_info_t *, frdest_t *));
94 #endif
95
96 #if (__NetBSD_Version__ >= 104040000)
97 # include <sys/callout.h>
98 struct callout fr_slowtimer_ch;
99 #endif
100
101 #include <sys/conf.h>
102 #if defined(NETBSD_PF)
103 # include <net/pfil.h>
104 /*
105 * We provide the fr_checkp name just to minimize changes later.
106 */
107 int (*fr_checkp) __P((ip_t *ip, int hlen, void *ifp, int out, mb_t **mp));
108 #endif /* NETBSD_PF */
109
110 #if (__NetBSD_Version__ >= 106080000) && defined(_KERNEL)
111 const struct cdevsw ipl_cdevsw = {
112 iplopen, iplclose, iplread, nowrite, iplioctl,
113 nostop, notty, nopoll, nommap,
114 };
115 #endif
116
117
118
119 #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000)
120 # include <net/pfil.h>
121
122 static int fr_check_wrapper(void *, struct mbuf **, struct ifnet *, int );
123
124 static int fr_check_wrapper(arg, mp, ifp, dir)
125 void *arg;
126 struct mbuf **mp;
127 struct ifnet *ifp;
128 int dir;
129 {
130 struct ip *ip;
131 int rv, hlen;
132 int error;
133
134 /*
135 * ensure that mbufs are writable beforehand
136 * as it's assumed by ipf code.
137 * XXX inefficient
138 */
139 error = m_makewritable(mp, 0, M_COPYALL, M_DONTWAIT);
140 if (error) {
141 m_freem(*mp);
142 *mp = NULL;
143 return error;
144 }
145
146 #if defined(M_CSUM_TCPv4)
147 /*
148 * If the packet is out-bound, we can't delay checksums
149 * here. For in-bound, the checksum has already been
150 * validated.
151 */
152 if (dir == PFIL_OUT) {
153 if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) {
154 in_delayed_cksum(*mp);
155 (*mp)->m_pkthdr.csum_flags &=
156 ~(M_CSUM_TCPv4|M_CSUM_UDPv4);
157 }
158 }
159 #endif /* M_CSUM_TCPv4 */
160
161 ip = mtod(*mp, struct ip *);
162 hlen = ip->ip_hl << 2;
163
164 /*
165 * We get the packet with all fields in network byte
166 * order. We expect ip_len and ip_off to be in host
167 * order. We frob them, call the filter, then frob
168 * them back.
169 *
170 * Note, we don't need to update the checksum, because
171 * it has already been verified.
172 */
173 NTOHS(ip->ip_len);
174 NTOHS(ip->ip_off);
175
176 rv = fr_check(ip, hlen, ifp, (dir == PFIL_OUT), mp);
177
178 if (rv == 0 && *mp != NULL) {
179 ip = mtod(*mp, struct ip *);
180 HTONS(ip->ip_len);
181 HTONS(ip->ip_off);
182 }
183
184 return (rv);
185 }
186
187 # ifdef USE_INET6
188 # include <netinet/ip6.h>
189
190 static int fr_check_wrapper6(void *, struct mbuf **, struct ifnet *, int );
191
192 static int fr_check_wrapper6(arg, mp, ifp, dir)
193 void *arg;
194 struct mbuf **mp;
195 struct ifnet *ifp;
196 int dir;
197 {
198 int error;
199
200 /*
201 * ensure that mbufs are writable beforehand
202 * as it's assumed by ipf code.
203 * XXX inefficient
204 */
205 error = m_makewritable(mp, 0, M_COPYALL, M_DONTWAIT);
206 if (error) {
207 m_freem(*mp);
208 *mp = NULL;
209 return error;
210 }
211
212 return (fr_check(mtod(*mp, struct ip *), sizeof(struct ip6_hdr),
213 ifp, (dir == PFIL_OUT), mp));
214 }
215 # endif
216 #endif /* __NetBSD_Version >= 105110000 */
217
218
219 #if defined(IPFILTER_LKM)
220 int iplidentify(s)
221 char *s;
222 {
223 if (strcmp(s, "ipl") == 0)
224 return 1;
225 return 0;
226 }
227 #endif /* IPFILTER_LKM */
228
229
230 /*
231 * Try to detect the case when compiling for NetBSD with pseudo-device
232 */
233 #if defined(PFIL_HOOKS)
234 void
235 ipfilterattach(count)
236 int count;
237 {
238 # if 0
239 if (iplattach() != 0)
240 printf("IP Filter failed to attach\n");
241 # endif
242 }
243 #endif
244
245
246 int iplattach()
247 {
248 int s;
249 #if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000)
250 int error = 0;
251 # if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000)
252 struct pfil_head *ph_inet;
253 # ifdef USE_INET6
254 struct pfil_head *ph_inet6;
255 # endif
256 # endif
257 #endif
258
259 SPL_NET(s);
260 if ((fr_running > 0) || (fr_checkp == fr_check)) {
261 printf("IP Filter: already initialized\n");
262 SPL_X(s);
263 return EBUSY;
264 }
265
266 if (fr_initialise() < 0) {
267 SPL_X(s);
268 return EIO;
269 }
270
271 #ifdef NETBSD_PF
272 # if (__NetBSD_Version__ >= 104200000)
273 # if __NetBSD_Version__ >= 105110000
274 ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
275 # ifdef USE_INET6
276 ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
277 # endif
278 if (ph_inet == NULL
279 # ifdef USE_INET6
280 && ph_inet6 == NULL
281 # endif
282 ) {
283 printf("pfil_head_get failed\n");
284 return ENODEV;
285 }
286
287 if (ph_inet != NULL)
288 error = pfil_add_hook((void *)fr_check_wrapper, NULL,
289 PFIL_IN|PFIL_OUT, ph_inet);
290 else
291 error = 0;
292 # else
293 error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
294 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
295 # endif
296 if (error) {
297 # ifdef USE_INET6
298 goto pfil_error;
299 # else
300 fr_deinitialise();
301 SPL_X(s);
302 return error;
303 # endif
304 }
305 # else
306 pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
307 # endif
308 # ifdef USE_INET6
309 # if __NetBSD_Version__ >= 105110000
310 if (ph_inet6 != NULL)
311 error = pfil_add_hook((void *)fr_check_wrapper6, NULL,
312 PFIL_IN|PFIL_OUT, ph_inet6);
313 else
314 error = 0;
315 if (error) {
316 pfil_remove_hook((void *)fr_check_wrapper6, NULL,
317 PFIL_IN|PFIL_OUT, ph_inet6);
318 # else
319 error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
320 &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh);
321 if (error) {
322 pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
323 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
324 # endif
325 pfil_error:
326 fr_deinitialise();
327 SPL_X(s);
328 return error;
329 }
330 # endif
331 #endif
332
333 bzero((char *)frcache, sizeof(frcache));
334 fr_savep = fr_checkp;
335 fr_checkp = fr_check;
336
337 if (fr_control_forwarding & 1)
338 ipforwarding = 1;
339
340 SPL_X(s);
341
342 #if (__NetBSD_Version__ >= 104010000)
343 callout_init(&fr_slowtimer_ch);
344 callout_reset(&fr_slowtimer_ch, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT,
345 fr_slowtimer, NULL);
346 #else
347 timeout(fr_slowtimer, NULL, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT);
348 #endif
349 return 0;
350 }
351
352
353 /*
354 * Disable the filter by removing the hooks from the IP input/output
355 * stream.
356 */
357 int ipldetach()
358 {
359 int s;
360 #if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000)
361 int error = 0;
362 # if __NetBSD_Version__ >= 105150000
363 struct pfil_head *ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
364 # ifdef USE_INET6
365 struct pfil_head *ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
366 # endif
367 # endif
368 #endif
369
370 SPL_NET(s);
371
372 #if (__NetBSD_Version__ >= 104010000)
373 callout_stop(&fr_slowtimer_ch);
374 #else
375 untimeout(fr_slowtimer, NULL);
376 #endif /* NetBSD */
377
378 fr_checkp = fr_savep;
379 (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE);
380 (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE);
381
382 if (fr_control_forwarding & 2)
383 ipforwarding = 0;
384
385 #ifdef NETBSD_PF
386 # if (__NetBSD_Version__ >= 104200000)
387 # if __NetBSD_Version__ >= 105110000
388 if (ph_inet != NULL)
389 error = pfil_remove_hook((void *)fr_check_wrapper, NULL,
390 PFIL_IN|PFIL_OUT, ph_inet);
391 else
392 error = 0;
393 # else
394 error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
395 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
396 # endif
397 if (error)
398 return error;
399 # else
400 pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
401 # endif
402 # ifdef USE_INET6
403 # if __NetBSD_Version__ >= 105110000
404 if (ph_inet6 != NULL)
405 error = pfil_remove_hook((void *)fr_check_wrapper6, NULL,
406 PFIL_IN|PFIL_OUT, ph_inet6);
407 else
408 error = 0;
409 # else
410 error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
411 &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh);
412 # endif
413 if (error)
414 return error;
415 # endif
416 #endif
417 fr_deinitialise();
418
419 SPL_X(s);
420 return 0;
421 }
422
423
424 /*
425 * Filter ioctl interface.
426 */
427 int iplioctl(dev, cmd, data, mode
428 #if (NetBSD >= 199511)
429 , p)
430 struct proc *p;
431 #else
432 )
433 #endif
434 dev_t dev;
435 u_long cmd;
436 caddr_t data;
437 int mode;
438 {
439 int s;
440 int error = 0, unit = 0, tmp;
441 friostat_t fio;
442
443 if ((securelevel >= 2) && (mode & FWRITE))
444 return EPERM;
445
446 unit = GET_MINOR(dev);
447 if ((IPL_LOGMAX < unit) || (unit < 0))
448 return ENXIO;
449
450 if (fr_running <= 0) {
451 if (unit != IPL_LOGIPF)
452 return EIO;
453 if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET &&
454 cmd != SIOCIPFSET && cmd != SIOCFRENB &&
455 cmd != SIOCGETFS && cmd != SIOCGETFF)
456 return EIO;
457 }
458
459 SPL_NET(s);
460
461 error = fr_ioctlswitch(unit, data, cmd, mode);
462 if (error != -1) {
463 SPL_X(s);
464 return error;
465 }
466 error = 0;
467
468 switch (cmd)
469 {
470 case FIONREAD :
471 #ifdef IPFILTER_LOG
472 BCOPYOUT(&iplused[IPL_LOGIPF], (caddr_t)data,
473 sizeof(iplused[IPL_LOGIPF]));
474 #endif
475 break;
476 case SIOCFRENB :
477 if (!(mode & FWRITE))
478 error = EPERM;
479 else {
480 BCOPYIN(data, &tmp, sizeof(tmp));
481 if (tmp) {
482 if (fr_running > 0)
483 error = 0;
484 else
485 error = iplattach();
486 if (error == 0)
487 fr_running = 1;
488 else
489 (void) ipldetach();
490 } else {
491 error = ipldetach();
492 if (error == 0)
493 fr_running = -1;
494 }
495 }
496 break;
497 case SIOCIPFSET :
498 if (!(mode & FWRITE)) {
499 error = EPERM;
500 break;
501 }
502 case SIOCIPFGETNEXT :
503 case SIOCIPFGET :
504 error = fr_ipftune(cmd, data);
505 break;
506 case SIOCSETFF :
507 if (!(mode & FWRITE))
508 error = EPERM;
509 else
510 BCOPYIN(data, &fr_flags, sizeof(fr_flags));
511 break;
512 case SIOCGETFF :
513 BCOPYOUT(&fr_flags, data, sizeof(fr_flags));
514 break;
515 case SIOCFUNCL :
516 error = fr_resolvefunc(data);
517 break;
518 case SIOCINAFR :
519 case SIOCRMAFR :
520 case SIOCADAFR :
521 case SIOCZRLST :
522 if (!(mode & FWRITE))
523 error = EPERM;
524 else
525 error = frrequest(unit, cmd, data, fr_active, 1);
526 break;
527 case SIOCINIFR :
528 case SIOCRMIFR :
529 case SIOCADIFR :
530 if (!(mode & FWRITE))
531 error = EPERM;
532 else
533 error = frrequest(unit, cmd, data, 1 - fr_active, 1);
534 break;
535 case SIOCSWAPA :
536 if (!(mode & FWRITE))
537 error = EPERM;
538 else {
539 bzero((char *)frcache, sizeof(frcache[0]) * 2);
540 *(u_int *)data = fr_active;
541 fr_active = 1 - fr_active;
542 }
543 break;
544 case SIOCGETFS :
545 fr_getstat(&fio);
546 error = fr_outobj(data, &fio, IPFOBJ_IPFSTAT);
547 break;
548 case SIOCFRZST :
549 if (!(mode & FWRITE))
550 error = EPERM;
551 else
552 error = fr_zerostats(data);
553 break;
554 case SIOCIPFFL :
555 if (!(mode & FWRITE))
556 error = EPERM;
557 else {
558 BCOPYIN(data, &tmp, sizeof(tmp));
559 tmp = frflush(unit, 4, tmp);
560 BCOPYOUT(&tmp, data, sizeof(tmp));
561 }
562 break;
563 #ifdef USE_INET6
564 case SIOCIPFL6 :
565 if (!(mode & FWRITE))
566 error = EPERM;
567 else {
568 BCOPYIN(data, &tmp, sizeof(tmp));
569 tmp = frflush(unit, 6, tmp);
570 BCOPYOUT(&tmp, data, sizeof(tmp));
571 }
572 break;
573 #endif
574 case SIOCSTLCK :
575 BCOPYIN(data, &tmp, sizeof(tmp));
576 fr_state_lock = tmp;
577 fr_nat_lock = tmp;
578 fr_frag_lock = tmp;
579 fr_auth_lock = tmp;
580 break;
581 #ifdef IPFILTER_LOG
582 case SIOCIPFFB :
583 if (!(mode & FWRITE))
584 error = EPERM;
585 else
586 *(int *)data = ipflog_clear(unit);
587 break;
588 #endif /* IPFILTER_LOG */
589 case SIOCGFRST :
590 error = fr_outobj(data, fr_fragstats(), IPFOBJ_FRAGSTAT);
591 break;
592 case SIOCFRSYN :
593 if (!(mode & FWRITE))
594 error = EPERM;
595 else {
596 frsync();
597 }
598 break;
599 default :
600 error = EINVAL;
601 break;
602 }
603 SPL_X(s);
604 return error;
605 }
606
607
608 void fr_forgetifp(ifp)
609 void *ifp;
610 {
611 register frentry_t *f;
612
613 WRITE_ENTER(&ipf_mutex);
614 for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next)
615 if (f->fr_ifa == ifp)
616 f->fr_ifa = (void *)-1;
617 for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next)
618 if (f->fr_ifa == ifp)
619 f->fr_ifa = (void *)-1;
620 for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next)
621 if (f->fr_ifa == ifp)
622 f->fr_ifa = (void *)-1;
623 for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next)
624 if (f->fr_ifa == ifp)
625 f->fr_ifa = (void *)-1;
626 #ifdef USE_INET6
627 for (f = ipacct6[0][fr_active]; (f != NULL); f = f->fr_next)
628 if (f->fr_ifa == ifp)
629 f->fr_ifa = (void *)-1;
630 for (f = ipacct6[1][fr_active]; (f != NULL); f = f->fr_next)
631 if (f->fr_ifa == ifp)
632 f->fr_ifa = (void *)-1;
633 for (f = ipfilter6[0][fr_active]; (f != NULL); f = f->fr_next)
634 if (f->fr_ifa == ifp)
635 f->fr_ifa = (void *)-1;
636 for (f = ipfilter6[1][fr_active]; (f != NULL); f = f->fr_next)
637 if (f->fr_ifa == ifp)
638 f->fr_ifa = (void *)-1;
639 #endif
640 RWLOCK_EXIT(&ipf_mutex);
641 fr_natsync(ifp);
642 }
643
644
645 /*
646 * routines below for saving IP headers to buffer
647 */
648 int iplopen(dev, flags
649 #if (NetBSD >= 199511)
650 , devtype, p)
651 int devtype;
652 struct proc *p;
653 #else
654 )
655 #endif
656 dev_t dev;
657 int flags;
658 {
659 u_int min = GET_MINOR(dev);
660
661 if (IPL_LOGMAX < min)
662 min = ENXIO;
663 else
664 min = 0;
665 return min;
666 }
667
668
669 int iplclose(dev, flags
670 #if (NetBSD >= 199511)
671 , devtype, p)
672 int devtype;
673 struct proc *p;
674 #else
675 )
676 #endif
677 dev_t dev;
678 int flags;
679 {
680 u_int min = GET_MINOR(dev);
681
682 if (IPL_LOGMAX < min)
683 min = ENXIO;
684 else
685 min = 0;
686 return min;
687 }
688
689 /*
690 * iplread/ipllog
691 * both of these must operate with at least splnet() lest they be
692 * called during packet processing and cause an inconsistancy to appear in
693 * the filter lists.
694 */
695 #if (BSD >= 199306)
696 int iplread(dev, uio, ioflag)
697 int ioflag;
698 #else
699 int iplread(dev, uio)
700 #endif
701 dev_t dev;
702 register struct uio *uio;
703 {
704 #ifdef IPFILTER_LOG
705 return ipflog_read(GET_MINOR(dev), uio);
706 #else
707 return ENXIO;
708 #endif
709 }
710
711
712 /*
713 * fr_send_reset - this could conceivably be a call to tcp_respond(), but that
714 * requires a large amount of setting up and isn't any more efficient.
715 */
716 int fr_send_reset(fin)
717 fr_info_t *fin;
718 {
719 struct tcphdr *tcp, *tcp2;
720 int tlen = 0, hlen;
721 struct mbuf *m;
722 #ifdef USE_INET6
723 ip6_t *ip6;
724 #endif
725 ip_t *ip;
726
727 tcp = fin->fin_dp;
728 if (tcp->th_flags & TH_RST)
729 return -1; /* feedback loop */
730
731 #ifndef IPFILTER_CKSUM
732 if (fr_checkl4sum(fin) == -1)
733 return -1;
734 #endif
735
736 tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) +
737 ((tcp->th_flags & TH_SYN) ? 1 : 0) +
738 ((tcp->th_flags & TH_FIN) ? 1 : 0);
739
740 #ifdef USE_INET6
741 hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t);
742 #else
743 hlen = sizeof(ip_t);
744 #endif
745 #ifdef MGETHDR
746 MGETHDR(m, M_DONTWAIT, MT_HEADER);
747 #else
748 MGET(m, M_DONTWAIT, MT_HEADER);
749 #endif
750 if (m == NULL)
751 return -1;
752 if (sizeof(*tcp2) + hlen > MHLEN) {
753 MCLGET(m, M_DONTWAIT);
754 if (m == NULL)
755 return -1;
756 if ((m->m_flags & M_EXT) == 0) {
757 FREE_MB_T(m);
758 return -1;
759 }
760 }
761
762 m->m_len = sizeof(*tcp2) + hlen;
763 m->m_data += max_linkhdr;
764 m->m_pkthdr.len = m->m_len;
765 m->m_pkthdr.rcvif = (struct ifnet *)0;
766 ip = mtod(m, struct ip *);
767 #ifdef USE_INET6
768 ip6 = (ip6_t *)ip;
769 #endif
770 bzero((char *)ip, sizeof(*tcp2) + hlen);
771 tcp2 = (struct tcphdr *)((char *)ip + hlen);
772 tcp2->th_sport = tcp->th_dport;
773 tcp2->th_dport = tcp->th_sport;
774
775 if (tcp->th_flags & TH_ACK) {
776 tcp2->th_seq = tcp->th_ack;
777 tcp2->th_flags = TH_RST;
778 tcp2->th_ack = 0;
779 } else {
780 tcp2->th_seq = 0;
781 tcp2->th_ack = ntohl(tcp->th_seq);
782 tcp2->th_ack += tlen;
783 tcp2->th_ack = htonl(tcp2->th_ack);
784 tcp2->th_flags = TH_RST|TH_ACK;
785 }
786 tcp2->th_x2 = 0;
787 TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2);
788 tcp2->th_win = tcp->th_win;
789 tcp2->th_sum = 0;
790 tcp2->th_urp = 0;
791
792 #ifdef USE_INET6
793 if (fin->fin_v == 6) {
794 ip6->ip6_flow = 0;
795 ip6->ip6_plen = htons(sizeof(struct tcphdr));
796 ip6->ip6_nxt = IPPROTO_TCP;
797 ip6->ip6_hlim = 0;
798 ip6->ip6_src = fin->fin_dst6;
799 ip6->ip6_dst = fin->fin_src6;
800 tcp2->th_sum = in6_cksum(m, IPPROTO_TCP,
801 sizeof(*ip6), sizeof(*tcp2));
802 return fr_send_ip(fin, m, &m);
803 }
804 #endif
805 ip->ip_p = IPPROTO_TCP;
806 ip->ip_len = htons(sizeof(struct tcphdr));
807 ip->ip_src.s_addr = fin->fin_daddr;
808 ip->ip_dst.s_addr = fin->fin_saddr;
809 tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2));
810 ip->ip_len = hlen + sizeof(*tcp2);
811 return fr_send_ip(fin, m, &m);
812 }
813
814
815 static int fr_send_ip(fin, m, mpp)
816 fr_info_t *fin;
817 mb_t *m, **mpp;
818 {
819 fr_info_t fnew;
820 ip_t *ip, *oip;
821 int hlen;
822
823 ip = mtod(m, ip_t *);
824 bzero((char *)&fnew, sizeof(fnew));
825
826 IP_V_A(ip, fin->fin_v);
827 switch (fin->fin_v)
828 {
829 case 4 :
830 fnew.fin_v = 4;
831 oip = fin->fin_ip;
832 IP_HL_A(ip, sizeof(*oip) >> 2);
833 ip->ip_tos = oip->ip_tos;
834 ip->ip_id = fr_nextipid(fin);
835 ip->ip_off = ip_mtudisc ? IP_DF : 0;
836 ip->ip_ttl = ip_defttl;
837 ip->ip_sum = 0;
838 hlen = sizeof(*oip);
839 break;
840 #ifdef USE_INET6
841 case 6 :
842 {
843 ip6_t *ip6 = (ip6_t *)ip;
844
845 ip6->ip6_vfc = 0x60;
846 ip6->ip6_hlim = IPDEFTTL;
847
848 fnew.fin_v = 6;
849 hlen = sizeof(*ip6);
850 break;
851 }
852 #endif
853 default :
854 return EINVAL;
855 }
856 #ifdef IPSEC
857 m->m_pkthdr.rcvif = NULL;
858 #endif
859
860 fnew.fin_ifp = fin->fin_ifp;
861 fnew.fin_flx = FI_NOCKSUM;
862 fnew.fin_m = m;
863 fnew.fin_ip = ip;
864 fnew.fin_mp = mpp;
865 fnew.fin_hlen = hlen;
866 fnew.fin_dp = (char *)ip + hlen;
867 (void) fr_makefrip(hlen, ip, &fnew);
868
869 return fr_fastroute(m, mpp, &fnew, NULL);
870 }
871
872
873 int fr_send_icmp_err(type, fin, dst)
874 int type;
875 fr_info_t *fin;
876 int dst;
877 {
878 int err, hlen, xtra, iclen, ohlen, avail, code;
879 struct in_addr dst4;
880 struct icmp *icmp;
881 struct mbuf *m;
882 void *ifp;
883 #ifdef USE_INET6
884 ip6_t *ip6, *ip62;
885 struct in6_addr dst6;
886 #endif
887 ip_t *ip, *ip2;
888
889 if ((type < 0) || (type > ICMP_MAXTYPE))
890 return -1;
891
892 code = fin->fin_icode;
893 #ifdef USE_INET6
894 if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int)))
895 return -1;
896 #endif
897
898 #ifndef IPFILTER_CKSUM
899 if (fr_checkl4sum(fin) == -1)
900 return -1;
901 #endif
902 #ifdef MGETHDR
903 MGETHDR(m, M_DONTWAIT, MT_HEADER);
904 #else
905 MGET(m, M_DONTWAIT, MT_HEADER);
906 #endif
907 if (m == NULL)
908 return -1;
909 avail = MHLEN;
910
911
912 xtra = 0;
913 hlen = 0;
914 ohlen = 0;
915 ifp = fin->fin_ifp;
916 if (fin->fin_v == 4) {
917 if ((fin->fin_p == IPPROTO_ICMP) &&
918 !(fin->fin_flx & FI_SHORT))
919 switch (ntohs(fin->fin_data[0]) >> 8)
920 {
921 case ICMP_ECHO :
922 case ICMP_TSTAMP :
923 case ICMP_IREQ :
924 case ICMP_MASKREQ :
925 break;
926 default :
927 return 0;
928 }
929
930 if (dst == 0) {
931 if (fr_ifpaddr(4, FRI_NORMAL, ifp,
932 &dst4, NULL) == -1) {
933 FREE_MB_T(m);
934 return -1;
935 }
936 } else
937 dst4.s_addr = fin->fin_daddr;
938
939 hlen = sizeof(ip_t);
940 ohlen = fin->fin_hlen;
941 if (fin->fin_hlen < fin->fin_plen)
942 xtra = MIN(fin->fin_dlen, 8);
943 else
944 xtra = 0;
945 }
946
947 #ifdef USE_INET6
948 else if (fin->fin_v == 6) {
949 hlen = sizeof(ip6_t);
950 ohlen = sizeof(ip6_t);
951 type = icmptoicmp6types[type];
952 if (type == ICMP6_DST_UNREACH)
953 code = icmptoicmp6unreach[code];
954
955 if (hlen + sizeof(*icmp) + max_linkhdr +
956 fin->fin_plen > avail) {
957 MCLGET(m, M_DONTWAIT);
958 if (m == NULL)
959 return -1;
960 if ((m->m_flags & M_EXT) == 0) {
961 FREE_MB_T(m);
962 return -1;
963 }
964 avail = MCLBYTES;
965 }
966 xtra = MIN(fin->fin_plen,
967 avail - hlen - sizeof(*icmp) - max_linkhdr);
968 if (dst == 0) {
969 if (fr_ifpaddr(6, FRI_NORMAL, ifp,
970 (struct in_addr *)&dst6, NULL) == -1) {
971 FREE_MB_T(m);
972 return -1;
973 }
974 } else
975 dst6 = fin->fin_dst6;
976 }
977 #endif
978 else
979 return -1;
980
981 iclen = hlen + sizeof(*icmp) + xtra;
982 avail -= (max_linkhdr + iclen);
983 m->m_data += max_linkhdr;
984 m->m_pkthdr.rcvif = (struct ifnet *)0;
985 if (xtra > avail)
986 xtra = avail;
987 iclen += xtra;
988 m->m_pkthdr.len = iclen;
989 if (avail < 0) {
990 FREE_MB_T(m);
991 return -1;
992 }
993 m->m_len = iclen;
994 ip = mtod(m, ip_t *);
995 icmp = (struct icmp *)((char *)ip + hlen);
996 ip2 = (ip_t *)&icmp->icmp_ip;
997
998 icmp->icmp_type = type;
999 icmp->icmp_code = fin->fin_icode;
1000 icmp->icmp_cksum = 0;
1001 #ifdef icmp_nextmtu
1002 if (type == ICMP_UNREACH &&
1003 fin->fin_icode == ICMP_UNREACH_NEEDFRAG && ifp)
1004 icmp->icmp_nextmtu = htons(((struct ifnet *)ifp)->if_mtu);
1005 #endif
1006
1007 bcopy((char *)fin->fin_ip, (char *)ip2, ohlen);
1008
1009 #if defined(M_CSUM_IPv4)
1010 /*
1011 * Clear any in-bound checksum flags for this packet.
1012 */
1013 m->m_pkthdr.csuminfo = 0;
1014 #endif /* __NetBSD__ && M_CSUM_IPv4 */
1015
1016 #ifdef USE_INET6
1017 ip6 = (ip6_t *)ip;
1018 if (fin->fin_v == 6) {
1019 ip62 = (ip6_t *)ip2;
1020
1021 ip6->ip6_flow = 0;
1022 ip6->ip6_plen = htons(iclen - hlen);
1023 ip6->ip6_nxt = IPPROTO_ICMPV6;
1024 ip6->ip6_hlim = 0;
1025 ip6->ip6_src = dst6;
1026 ip6->ip6_dst = fin->fin_src6;
1027 if (xtra > 0)
1028 bcopy((char *)fin->fin_ip + ohlen,
1029 (char *)&icmp->icmp_ip + ohlen, xtra);
1030 icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6,
1031 sizeof(*ip6), iclen - hlen);
1032 } else
1033 #endif
1034 {
1035 ip->ip_p = IPPROTO_ICMP;
1036 ip->ip_src.s_addr = dst4.s_addr;
1037 ip->ip_dst.s_addr = fin->fin_saddr;
1038
1039 if (xtra > 0)
1040 bcopy((char *)fin->fin_ip + ohlen,
1041 (char *)&icmp->icmp_ip + ohlen, xtra);
1042 icmp->icmp_cksum = ipf_cksum((u_short *)icmp,
1043 sizeof(*icmp) + 8);
1044 ip->ip_len = iclen;
1045 ip->ip_p = IPPROTO_ICMP;
1046 }
1047 err = fr_send_ip(fin, m, &m);
1048 return err;
1049 }
1050
1051
1052 int fr_fastroute(m0, mpp, fin, fdp)
1053 mb_t *m0, **mpp;
1054 fr_info_t *fin;
1055 frdest_t *fdp;
1056 {
1057 register struct ip *ip, *mhip;
1058 register struct mbuf *m = m0;
1059 register struct route *ro;
1060 int len, off, error = 0, hlen, code;
1061 struct ifnet *ifp, *sifp;
1062 struct sockaddr_in *dst;
1063 struct route iproute;
1064 u_short ip_off;
1065 frentry_t *fr;
1066
1067 #ifdef USE_INET6
1068 if (fin->fin_v == 6) {
1069 error = ipfr_fastroute6(m0, mpp, fin, fdp);
1070 if ((error != 0) && (*mpp != NULL)) {
1071 FREE_MB_T(*mpp);
1072 *mpp = NULL;
1073 }
1074 return error;
1075 }
1076 #endif
1077
1078 hlen = fin->fin_hlen;
1079 ip = mtod(m0, struct ip *);
1080
1081 #if defined(M_CSUM_IPv4)
1082 /*
1083 * Clear any in-bound checksum flags for this packet.
1084 */
1085 m0->m_pkthdr.csuminfo = 0;
1086 #endif /* __NetBSD__ && M_CSUM_IPv4 */
1087
1088 /*
1089 * Route packet.
1090 */
1091 ro = &iproute;
1092 bzero((caddr_t)ro, sizeof (*ro));
1093 dst = (struct sockaddr_in *)&ro->ro_dst;
1094 dst->sin_family = AF_INET;
1095 dst->sin_addr = ip->ip_dst;
1096
1097 fr = fin->fin_fr;
1098 if (fdp != NULL)
1099 ifp = fdp->fd_ifp;
1100 else
1101 ifp = fin->fin_ifp;
1102
1103 if ((ifp == NULL) && (!fr || !(fr->fr_flags & FR_FASTROUTE))) {
1104 error = -2;
1105 goto bad;
1106 }
1107
1108 /*
1109 * In case we're here due to "to <if>" being used with "keep state",
1110 * check that we're going in the correct direction.
1111 */
1112 if ((fr != NULL) && (fin->fin_rev != 0)) {
1113 if ((ifp != NULL) && (fdp == &fr->fr_tif))
1114 return 0;
1115 } else if (fdp != NULL) {
1116 if (fdp->fd_ip.s_addr != 0)
1117 dst->sin_addr = fdp->fd_ip;
1118 }
1119
1120 dst->sin_len = sizeof(*dst);
1121 rtalloc(ro);
1122
1123 if ((ifp == NULL) && (ro->ro_rt != NULL))
1124 ifp = ro->ro_rt->rt_ifp;
1125
1126 if ((ro->ro_rt == NULL) || (ifp == NULL)) {
1127 if (in_localaddr(ip->ip_dst))
1128 error = EHOSTUNREACH;
1129 else
1130 error = ENETUNREACH;
1131 goto bad;
1132 }
1133 if (ro->ro_rt->rt_flags & RTF_GATEWAY)
1134 dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
1135 if (ro->ro_rt)
1136 ro->ro_rt->rt_use++;
1137
1138 /*
1139 * For input packets which are being "fastrouted", they won't
1140 * go back through output filtering and miss their chance to get
1141 * NAT'd and counted.
1142 */
1143 if (fin->fin_out == 0) {
1144 sifp = fin->fin_ifp;
1145 fin->fin_ifp = ifp;
1146 fin->fin_out = 1;
1147 (void) fr_acctpkt(fin, NULL);
1148 fin->fin_fr = NULL;
1149 if (!fr || !(fr->fr_flags & FR_RETMASK)) {
1150 u_32_t pass;
1151
1152 (void) fr_checkstate(fin, &pass);
1153 }
1154
1155 switch (fr_checknatout(fin, NULL))
1156 {
1157 case 0 :
1158 break;
1159 case 1 :
1160 ip->ip_sum = 0;
1161 break;
1162 case -1 :
1163 error = -1;
1164 goto done;
1165 break;
1166 }
1167
1168 fin->fin_ifp = sifp;
1169 fin->fin_out = 0;
1170 } else
1171 ip->ip_sum = 0;
1172 /*
1173 * If small enough for interface, can just send directly.
1174 */
1175 if (ip->ip_len <= ifp->if_mtu) {
1176 ip->ip_len = htons(ip->ip_len);
1177 ip->ip_off = htons(ip->ip_off);
1178 #if defined(M_CSUM_IPv4)
1179 if (ifp->if_capabilities & IFCAP_CSUM_IPv4)
1180 m->m_pkthdr.csuminfo |= M_CSUM_IPv4;
1181 else if (ip->ip_sum == 0)
1182 ip->ip_sum = in_cksum(m, hlen);
1183 #else
1184 if (!ip->ip_sum)
1185 ip->ip_sum = in_cksum(m, hlen);
1186 #endif /* M_CSUM_IPv4 */
1187 error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
1188 ro->ro_rt);
1189 goto done;
1190 }
1191 /*
1192 * Too large for interface; fragment if possible.
1193 * Must be able to put at least 8 bytes per fragment.
1194 */
1195 ip_off = ip->ip_off;
1196 if (ip_off & IP_DF) {
1197 error = EMSGSIZE;
1198 goto bad;
1199 }
1200 len = (ifp->if_mtu - hlen) &~ 7;
1201 if (len < 8) {
1202 error = EMSGSIZE;
1203 goto bad;
1204 }
1205
1206 {
1207 int mhlen, firstlen = len;
1208 struct mbuf **mnext = &m->m_act;
1209
1210 /*
1211 * Loop through length of segment after first fragment,
1212 * make new header and copy data of each part and link onto chain.
1213 */
1214 m0 = m;
1215 mhlen = sizeof (struct ip);
1216 for (off = hlen + len; off < ip->ip_len; off += len) {
1217 #ifdef MGETHDR
1218 MGETHDR(m, M_DONTWAIT, MT_HEADER);
1219 #else
1220 MGET(m, M_DONTWAIT, MT_HEADER);
1221 #endif
1222 if (m == 0) {
1223 m = m0;
1224 error = ENOBUFS;
1225 goto bad;
1226 }
1227 m->m_data += max_linkhdr;
1228 mhip = mtod(m, struct ip *);
1229 bcopy((char *)ip, (char *)mhip, sizeof(*ip));
1230 if (hlen > sizeof (struct ip)) {
1231 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
1232 IP_HL_A(mhip, mhlen >> 2);
1233 }
1234 m->m_len = mhlen;
1235 mhip->ip_off = ((off - hlen) >> 3) + ip_off;
1236 if (off + len >= ip->ip_len)
1237 len = ip->ip_len - off;
1238 else
1239 mhip->ip_off |= IP_MF;
1240 mhip->ip_len = htons((u_short)(len + mhlen));
1241 m->m_next = m_copy(m0, off, len);
1242 if (m->m_next == 0) {
1243 error = ENOBUFS; /* ??? */
1244 goto sendorfree;
1245 }
1246 m->m_pkthdr.len = mhlen + len;
1247 m->m_pkthdr.rcvif = NULL;
1248 mhip->ip_off = htons((u_short)mhip->ip_off);
1249 mhip->ip_sum = 0;
1250 mhip->ip_sum = in_cksum(m, mhlen);
1251 *mnext = m;
1252 mnext = &m->m_act;
1253 }
1254 /*
1255 * Update first fragment by trimming what's been copied out
1256 * and updating header, then send each fragment (in order).
1257 */
1258 m_adj(m0, hlen + firstlen - ip->ip_len);
1259 ip->ip_len = htons((u_short)(hlen + firstlen));
1260 ip->ip_off = htons((u_short)IP_MF);
1261 ip->ip_sum = 0;
1262 ip->ip_sum = in_cksum(m0, hlen);
1263 sendorfree:
1264 for (m = m0; m; m = m0) {
1265 m0 = m->m_act;
1266 m->m_act = 0;
1267 if (error == 0)
1268 error = (*ifp->if_output)(ifp, m,
1269 (struct sockaddr *)dst, ro->ro_rt);
1270 else
1271 FREE_MB_T(m);
1272 }
1273 }
1274 done:
1275 if (!error)
1276 fr_frouteok[0]++;
1277 else
1278 fr_frouteok[1]++;
1279
1280 if (ro->ro_rt) {
1281 RTFREE(ro->ro_rt);
1282 }
1283 *mpp = NULL;
1284 return error;
1285 bad:
1286 if (error == EMSGSIZE) {
1287 sifp = fin->fin_ifp;
1288 code = fin->fin_icode;
1289 fin->fin_icode = ICMP_UNREACH_NEEDFRAG;
1290 fin->fin_ifp = ifp;
1291 (void) fr_send_icmp_err(ICMP_UNREACH, fin, 1);
1292 fin->fin_ifp = sifp;
1293 fin->fin_icode = code;
1294 }
1295 FREE_MB_T(m);
1296 goto done;
1297 }
1298
1299
1300 #if defined(USE_INET6)
1301 /*
1302 * This is the IPv6 specific fastroute code. It doesn't clean up the mbuf's
1303 * or ensure that it is an IPv6 packet that is being forwarded, those are
1304 * expected to be done by the called (ipfr_fastroute).
1305 */
1306 static int ipfr_fastroute6(m0, mpp, fin, fdp)
1307 struct mbuf *m0, **mpp;
1308 fr_info_t *fin;
1309 frdest_t *fdp;
1310 {
1311 struct route_in6 ip6route;
1312 struct sockaddr_in6 *dst6;
1313 struct route_in6 *ro;
1314 struct ifnet *ifp;
1315 frentry_t *fr;
1316 u_long mtu;
1317 int error;
1318
1319 ro = &ip6route;
1320 fr = fin->fin_fr;
1321 bzero((caddr_t)ro, sizeof(*ro));
1322 dst6 = (struct sockaddr_in6 *)&ro->ro_dst;
1323 dst6->sin6_family = AF_INET6;
1324 dst6->sin6_len = sizeof(struct sockaddr_in6);
1325 dst6->sin6_addr = fin->fin_fi.fi_dst.in6;
1326
1327 if (fdp != NULL)
1328 ifp = fdp->fd_ifp;
1329 else
1330 ifp = fin->fin_ifp;
1331
1332 if ((fr != NULL) && (fin->fin_rev != 0)) {
1333 if ((ifp != NULL) && (fdp == &fr->fr_tif))
1334 return 0;
1335 } else if (fdp != NULL) {
1336 if (IP6_NOTZERO(&fdp->fd_ip6))
1337 dst6->sin6_addr = fdp->fd_ip6.in6;
1338 }
1339
1340 rtalloc((struct route *)ro);
1341
1342 if ((ifp == NULL) && (ro->ro_rt != NULL))
1343 ifp = ro->ro_rt->rt_ifp;
1344
1345 if ((ro->ro_rt == NULL) || (ifp == NULL)) {
1346 error = EHOSTUNREACH;
1347 goto bad;
1348 }
1349
1350 /* KAME */
1351 if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr))
1352 dst6->sin6_addr.s6_addr16[1] = htons(ifp->if_index);
1353
1354 {
1355 #if (__NetBSD_Version__ >= 106010000)
1356 struct in6_addr finaldst = fin->fin_dst6;
1357 int frag;
1358 #endif
1359 if (ro->ro_rt->rt_flags & RTF_GATEWAY)
1360 dst6 = (struct sockaddr_in6 *)ro->ro_rt->rt_gateway;
1361 ro->ro_rt->rt_use++;
1362
1363 #if (__NetBSD_Version__ <= 106009999)
1364 mtu = nd_ifinfo[ifp->if_index].linkmtu;
1365 #else
1366 /* Determine path MTU. */
1367 error = ip6_getpmtu(ro, ro, ifp, &finaldst, &mtu, &frag);
1368 #endif
1369 if ((error == 0) && (m0->m_pkthdr.len <= mtu)) {
1370 *mpp = NULL;
1371 error = nd6_output(ifp, fin->fin_ifp, m0,
1372 dst6, ro->ro_rt);
1373 } else {
1374 error = EMSGSIZE;
1375 }
1376 }
1377 bad:
1378 if (ro->ro_rt != NULL) {
1379 RTFREE(ro->ro_rt);
1380 }
1381 return error;
1382 }
1383 #endif
1384
1385
1386 int fr_verifysrc(fin)
1387 fr_info_t *fin;
1388 {
1389 struct sockaddr_in *dst;
1390 struct route iproute;
1391
1392 bzero((char *)&iproute, sizeof(iproute));
1393 dst = (struct sockaddr_in *)&iproute.ro_dst;
1394 dst->sin_len = sizeof(*dst);
1395 dst->sin_family = AF_INET;
1396 dst->sin_addr = fin->fin_src;
1397 rtalloc(&iproute);
1398 if (iproute.ro_rt == NULL)
1399 return 0;
1400 return (fin->fin_ifp == iproute.ro_rt->rt_ifp);
1401 }
1402
1403
1404 /*
1405 * return the first IP Address associated with an interface
1406 */
1407 int fr_ifpaddr(v, atype, ifptr, inp, inpmask)
1408 int v, atype;
1409 void *ifptr;
1410 struct in_addr *inp, *inpmask;
1411 {
1412 #ifdef USE_INET6
1413 struct in6_addr *inp6 = NULL;
1414 #endif
1415 struct sockaddr *sock, *mask;
1416 struct sockaddr_in *sin;
1417 struct ifaddr *ifa;
1418 struct ifnet *ifp;
1419
1420 if ((ifptr == NULL) || (ifptr == (void *)-1))
1421 return -1;
1422
1423 ifp = ifptr;
1424 mask = NULL;
1425
1426 if (v == 4)
1427 inp->s_addr = 0;
1428 #ifdef USE_INET6
1429 else if (v == 6)
1430 bzero((char *)inp, sizeof(struct in6_addr));
1431 #endif
1432
1433 ifa = ifp->if_addrlist.tqh_first;
1434 sock = ifa->ifa_addr;
1435 while (sock != NULL && ifa != NULL) {
1436 sin = (struct sockaddr_in *)sock;
1437 if ((v == 4) && (sin->sin_family == AF_INET))
1438 break;
1439 #ifdef USE_INET6
1440 if ((v == 6) && (sin->sin_family == AF_INET6)) {
1441 inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr;
1442 if (!IN6_IS_ADDR_LINKLOCAL(inp6) &&
1443 !IN6_IS_ADDR_LOOPBACK(inp6))
1444 break;
1445 }
1446 #endif
1447 ifa = ifa->ifa_list.tqe_next;
1448 if (ifa != NULL)
1449 sock = ifa->ifa_addr;
1450 }
1451 if (ifa == NULL || sock == NULL)
1452 return -1;
1453
1454 mask = ifa->ifa_netmask;
1455 if (atype == FRI_BROADCAST)
1456 sock = ifa->ifa_broadaddr;
1457 else if (atype == FRI_PEERADDR)
1458 sock = ifa->ifa_dstaddr;
1459
1460 #ifdef USE_INET6
1461 if (v == 6)
1462 return fr_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock,
1463 (struct sockaddr_in6 *)mask,
1464 inp, inpmask);
1465 #endif
1466 return fr_ifpfillv4addr(atype, (struct sockaddr_in *)sock,
1467 (struct sockaddr_in *)mask, inp, inpmask);
1468 }
1469
1470
1471 u_32_t fr_newisn(fin)
1472 fr_info_t *fin;
1473 {
1474 u_32_t newiss;
1475 #if __NetBSD_Version >= 105190000 /* 1.5T */
1476 size_t asz;
1477
1478
1479 if (fin->fin_v == 4)
1480 asz = sizeof(struct in_addr);
1481 else if (fin->fin_v == 6)
1482 asz = sizeof(fin->fin_src);
1483 newiss = tcp_new_iss1((void *)&fin->fin_src, (void *)&fin->fin_dst,
1484 fin->fin_sport, fin->fin_dport, asz);
1485 #else
1486 static int iss_seq_off = 0;
1487 u_char hash[16];
1488 MD5_CTX ctx;
1489
1490 /*
1491 * Compute the base value of the ISS. It is a hash
1492 * of (saddr, sport, daddr, dport, secret).
1493 */
1494 MD5Init(&ctx);
1495
1496 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
1497 sizeof(fin->fin_fi.fi_src));
1498 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
1499 sizeof(fin->fin_fi.fi_dst));
1500 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
1501
1502 MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret));
1503
1504 MD5Final(hash, &ctx);
1505
1506 memcpy(&newiss, hash, sizeof(newiss));
1507
1508 /*
1509 * Now increment our "timer", and add it in to
1510 * the computed value.
1511 *
1512 * XXX Use `addin'?
1513 * XXX TCP_ISSINCR too large to use?
1514 */
1515 iss_seq_off += 0x00010000;
1516 newiss += iss_seq_off;
1517 #endif
1518 return newiss;
1519 }
1520
1521
1522 /* ------------------------------------------------------------------------ */
1523 /* Function: fr_nextipid */
1524 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */
1525 /* Parameters: fin(I) - pointer to packet information */
1526 /* */
1527 /* Returns the next IPv4 ID to use for this packet. */
1528 /* ------------------------------------------------------------------------ */
1529 u_short fr_nextipid(fin)
1530 fr_info_t *fin;
1531 {
1532 static u_short ipid = 0;
1533 u_short id;
1534
1535 MUTEX_ENTER(&ipf_rw);
1536 id = ipid++;
1537 MUTEX_EXIT(&ipf_rw);
1538
1539 return id;
1540 }
1541
1542
1543 INLINE void fr_checkv4sum(fin)
1544 fr_info_t *fin;
1545 {
1546 #ifdef M_CSUM_TCP_UDP_BAD
1547 int manual, pflag, cflags, active;
1548 mb_t *m;
1549
1550 if ((fin->fin_flx & FI_NOCKSUM) != 0)
1551 return;
1552
1553 manual = 0;
1554 m = fin->fin_m;
1555 if (m == NULL) {
1556 manual = 1;
1557 goto skipauto;
1558 }
1559
1560 switch (fin->fin_p)
1561 {
1562 case IPPROTO_UDP :
1563 pflag = M_CSUM_UDPv4;
1564 break;
1565 case IPPROTO_TCP :
1566 pflag = M_CSUM_TCPv4;
1567 break;
1568 default :
1569 pflag = 0;
1570 manual = 1;
1571 break;
1572 }
1573
1574 active = ((struct ifnet *)fin->fin_ifp)->if_csum_flags_rx & pflag;
1575 active |= M_CSUM_TCP_UDP_BAD | M_CSUM_DATA;
1576 cflags = m->m_pkthdr.csum_flags & active;
1577
1578 if (pflag != 0) {
1579 if (cflags == (pflag | M_CSUM_TCP_UDP_BAD)) {
1580 fin->fin_flx |= FI_BAD;
1581 } else if (cflags == (pflag | M_CSUM_DATA)) {
1582 if ((m->m_pkthdr.csum_data ^ 0xffff) != 0)
1583 fin->fin_flx |= FI_BAD;
1584 } else if (cflags == pflag) {
1585 ;
1586 } else {
1587 manual = 1;
1588 }
1589 }
1590 skipauto:
1591 # ifdef IPFILTER_CKSUM
1592 if (manual != 0)
1593 if (fr_checkl4sum(fin) == -1)
1594 fin->fin_flx |= FI_BAD;
1595 # else
1596 ;
1597 # endif
1598 #else
1599 # ifdef IPFILTER_CKSUM
1600 if (fr_checkl4sum(fin) == -1)
1601 fin->fin_flx |= FI_BAD;
1602 # endif
1603 #endif
1604 }
1605
1606
1607 #ifdef USE_INET6
1608 INLINE void fr_checkv6sum(fin)
1609 fr_info_t *fin;
1610 {
1611 # ifdef M_CSUM_TCP_UDP_BAD
1612 int manual, pflag, cflags, active;
1613 mb_t *m;
1614
1615 if ((fin->fin_flx & FI_NOCKSUM) != 0)
1616 return;
1617
1618 manual = 0;
1619 m = fin->fin_m;
1620
1621 switch (fin->fin_p)
1622 {
1623 case IPPROTO_UDP :
1624 pflag = M_CSUM_UDPv6;
1625 break;
1626 case IPPROTO_TCP :
1627 pflag = M_CSUM_TCPv6;
1628 break;
1629 default :
1630 pflag = 0;
1631 manual = 1;
1632 break;
1633 }
1634
1635 active = ((struct ifnet *)fin->fin_ifp)->if_csum_flags_rx & pflag;
1636 active |= M_CSUM_TCP_UDP_BAD | M_CSUM_DATA;
1637 cflags = m->m_pkthdr.csum_flags & active;
1638
1639 if (pflag != 0) {
1640 if (cflags == (pflag | M_CSUM_TCP_UDP_BAD)) {
1641 fin->fin_flx |= FI_BAD;
1642 } else if (cflags == (pflag | M_CSUM_DATA)) {
1643 if ((m->m_pkthdr.csum_data ^ 0xffff) != 0)
1644 fin->fin_flx |= FI_BAD;
1645 } else if (cflags == pflag) {
1646 ;
1647 } else {
1648 manual = 1;
1649 }
1650 }
1651 # ifdef IPFILTER_CKSUM
1652 if (manual != 0)
1653 if (fr_checkl4sum(fin) == -1)
1654 fin->fin_flx |= FI_BAD;
1655 # endif
1656 # else
1657 # ifdef IPFILTER_CKSUM
1658 if (fr_checkl4sum(fin) == -1)
1659 fin->fin_flx |= FI_BAD;
1660 # endif
1661 # endif
1662 }
1663 #endif /* USE_INET6 */
1664
1665
1666 size_t mbufchainlen(m0)
1667 struct mbuf *m0;
1668 {
1669 size_t len;
1670
1671 if ((m0->m_flags & M_PKTHDR) != 0) {
1672 len = m0->m_pkthdr.len;
1673 } else {
1674 struct mbuf *m;
1675
1676 for (m = m0, len = 0; m != NULL; m = m->m_next)
1677 len += m->m_len;
1678 }
1679 return len;
1680 }
Cache object: 2c7af8930dca01f5c2403f11e837ff57
|