ip_fil_netbsd.c revision 1.22.4.5 1 /* $NetBSD: ip_fil_netbsd.c,v 1.22.4.5 2017/05/02 05:17:56 pgoyette Exp $ */
2
3 /*
4 * Copyright (C) 2012 by Darren Reed.
5 *
6 * See the IPFILTER.LICENCE file for details on licencing.
7 */
8 #if !defined(lint)
9 #if defined(__NetBSD__)
10 #include <sys/cdefs.h>
11 __KERNEL_RCSID(0, "$NetBSD: ip_fil_netbsd.c,v 1.22.4.5 2017/05/02 05:17:56 pgoyette Exp $");
12 #else
13 static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
14 static const char rcsid[] = "@(#)Id: ip_fil_netbsd.c,v 1.1.1.2 2012/07/22 13:45:17 darrenr Exp";
15 #endif
16 #endif
17
18 #if defined(KERNEL) || defined(_KERNEL)
19 # undef KERNEL
20 # undef _KERNEL
21 # define KERNEL 1
22 # define _KERNEL 1
23 #endif
24 #include <sys/param.h>
25 #if (NetBSD >= 199905) && !defined(IPFILTER_LKM)
26 # if (__NetBSD_Version__ >= 799003000)
27 # ifdef _KERNEL_OPT
28 # include "opt_ipsec.h"
29 # endif
30 # else
31 # include "opt_ipsec.h"
32 # endif
33 #endif
34 #include <sys/errno.h>
35 #include <sys/types.h>
36 #include <sys/file.h>
37 #include <sys/ioctl.h>
38 #include <sys/time.h>
39 #include <sys/systm.h>
40 #include <sys/select.h>
41 #if (NetBSD > 199609)
42 # include <sys/dirent.h>
43 #else
44 # include <sys/dir.h>
45 #endif
46 #if (__NetBSD_Version__ >= 599005900)
47 # include <sys/cprng.h>
48 #endif
49 #include <sys/mbuf.h>
50 #include <sys/protosw.h>
51 #include <sys/socket.h>
52 #include <sys/poll.h>
53 #if (__NetBSD_Version__ >= 399002000)
54 # include <sys/kauth.h>
55 #endif
56 #if (__NetBSD_Version__ >= 799003000)
57 #include <sys/module.h>
58 #include <sys/mutex.h>
59 #endif
60
61 #include <net/if.h>
62 #include <net/route.h>
63 #include <netinet/in.h>
64 #include <netinet/in_var.h>
65 #include <netinet/in_systm.h>
66 #include <netinet/ip.h>
67 #include <netinet/ip_var.h>
68 #include <netinet/tcp.h>
69 #if __NetBSD_Version__ >= 105190000 /* 1.5T */
70 # include <netinet/tcp_timer.h>
71 # include <netinet/tcp_var.h>
72 #endif
73 #include <netinet/udp.h>
74 #include <netinet/tcpip.h>
75 #include <netinet/ip_icmp.h>
76 #include "netinet/ip_compat.h"
77 #ifdef USE_INET6
78 # include <netinet/icmp6.h>
79 # if (__NetBSD_Version__ >= 106000000)
80 # include <netinet6/nd6.h>
81 # endif
82 #endif
83 #include "netinet/ip_fil.h"
84 #include "netinet/ip_nat.h"
85 #include "netinet/ip_frag.h"
86 #include "netinet/ip_state.h"
87 #include "netinet/ip_proxy.h"
88 #include "netinet/ip_auth.h"
89 #include "netinet/ip_sync.h"
90 #include "netinet/ip_lookup.h"
91 #include "netinet/ip_dstlist.h"
92 #ifdef IPFILTER_SCAN
93 #include "netinet/ip_scan.h"
94 #endif
95 #include <sys/md5.h>
96 #include <sys/kernel.h>
97 #include <sys/conf.h>
98 #ifdef INET
99 extern int ip_optcopy (struct ip *, struct ip *);
100 #endif
101
102 #ifdef IPFILTER_M_IPFILTER
103 MALLOC_DEFINE(M_IPFILTER, "IP Filter", "IP Filter packet filter data structures");
104 #endif
105
106 #if __NetBSD_Version__ >= 105009999
107 # define csuminfo csum_flags
108 #endif
109
110 #if __NetBSD_Version__ < 200000000
111 extern struct protosw inetsw[];
112 #endif
113
114 #if (__NetBSD_Version__ >= 599002000)
115 static kauth_listener_t ipf_listener;
116 #endif
117
118 #if (__NetBSD_Version__ < 399001400)
119 extern int ip6_getpmtu (struct route_in6 *, struct route_in6 *,
120 struct ifnet *, struct in6_addr *, u_long *,
121 int *);
122 #endif
123 #if (NetBSD >= 199511)
124 static int ipfopen(dev_t dev, int flags, int devtype, PROC_T *p);
125 static int ipfclose(dev_t dev, int flags, int devtype, PROC_T *p);
126 #else
127 # if (__NetBSD_Version__ >= 399001400)
128 static int ipfopen(dev_t dev, int flags, struct lwp *);
129 static int ipfclose(dev_t dev, int flags, struct lwp *);
130 # else
131 static int ipfopen(dev_t dev, int flags);
132 static int ipfclose(dev_t dev, int flags);
133 # endif /* __NetBSD_Version__ >= 399001400 */
134 #endif
135 static int ipfread(dev_t, struct uio *, int ioflag);
136 static int ipfwrite(dev_t, struct uio *, int ioflag);
137 static int ipfpoll(dev_t, int events, PROC_T *);
138 static void ipf_timer_func(void *ptr);
139
140 const struct cdevsw ipl_cdevsw = {
141 #if (__NetBSD_Version__ >= 799007200)
142 DEVSW_MODULE_INIT
143 #endif
144 .d_open = ipfopen,
145 .d_close = ipfclose,
146 .d_read = ipfread,
147 .d_write = ipfwrite,
148 .d_ioctl = ipfioctl,
149 .d_stop = nostop,
150 .d_tty = notty,
151 .d_poll = ipfpoll,
152 .d_mmap = nommap,
153 #if (__NetBSD_Version__ >= 200000000)
154 .d_kqfilter = nokqfilter,
155 #endif
156 .d_discard = nodiscard,
157 #ifdef D_OTHER
158 .d_flag = D_OTHER
159 #else
160 .d_flag = 0
161 #endif
162 };
163 #if (__NetBSD_Version__ >= 799003000)
164 kmutex_t ipf_ref_mutex;
165 int ipf_active;
166 #endif
167
168 ipf_main_softc_t ipfmain;
169
170 static u_short ipid = 0;
171 static int (*ipf_savep)(void *, ip_t *, int, void *, int, struct mbuf **);
172 static int ipf_send_ip(fr_info_t *, mb_t *);
173 #ifdef USE_INET6
174 static int ipf_fastroute6(struct mbuf *, struct mbuf **,
175 fr_info_t *, frdest_t *);
176 #endif
177
178 #if defined(NETBSD_PF)
179 # include <net/pfil.h>
180 /*
181 * We provide the ipf_checkp name just to minimize changes later.
182 */
183 int (*ipf_checkp)(void *, ip_t *ip, int hlen, void *ifp, int out, mb_t **mp);
184 #endif /* NETBSD_PF */
185
186 #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000)
187 # include <net/pfil.h>
188
189 static int ipf_check_wrapper(void *, struct mbuf **, struct ifnet *, int );
190
191 static int
192 ipf_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
193 {
194 struct ip *ip;
195 int rv, hlen;
196
197 #if __NetBSD_Version__ >= 200080000
198 /*
199 * ensure that mbufs are writable beforehand
200 * as it's assumed by ipf code.
201 * XXX inefficient
202 */
203 int error = m_makewritable(mp, 0, M_COPYALL, M_DONTWAIT);
204
205 if (error) {
206 m_freem(*mp);
207 *mp = NULL;
208 return error;
209 }
210 #endif
211 ip = mtod(*mp, struct ip *);
212 hlen = ip->ip_hl << 2;
213
214 #ifdef INET
215 #if defined(M_CSUM_TCPv4)
216 /*
217 * If the packet is out-bound, we can't delay checksums
218 * here. For in-bound, the checksum has already been
219 * validated.
220 */
221 if (dir == PFIL_OUT) {
222 if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) {
223 in_delayed_cksum(*mp);
224 (*mp)->m_pkthdr.csum_flags &=
225 ~(M_CSUM_TCPv4|M_CSUM_UDPv4);
226 }
227 }
228 #endif /* M_CSUM_TCPv4 */
229 #endif /* INET */
230
231 /*
232 * Note, we don't need to update the checksum, because
233 * it has already been verified.
234 */
235 rv = ipf_check(&ipfmain, ip, hlen, ifp, (dir == PFIL_OUT), mp);
236
237 return (rv);
238 }
239
240 # ifdef USE_INET6
241 # include <netinet/ip6.h>
242
243 static int ipf_check_wrapper6(void *, struct mbuf **, struct ifnet *, int );
244
245 static int
246 ipf_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
247 {
248 #if defined(INET6)
249 # if defined(M_CSUM_TCPv6) && (__NetBSD_Version__ > 200000000)
250 /*
251 * If the packet is out-bound, we can't delay checksums
252 * here. For in-bound, the checksum has already been
253 * validated.
254 */
255 if (dir == PFIL_OUT) {
256 if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv6|M_CSUM_UDPv6)) {
257 # if (__NetBSD_Version__ > 399000600)
258 in6_delayed_cksum(*mp);
259 # endif
260 (*mp)->m_pkthdr.csum_flags &= ~(M_CSUM_TCPv6|
261 M_CSUM_UDPv6);
262 }
263 }
264 # endif
265 #endif /* INET6 */
266
267 return (ipf_check(&ipfmain, mtod(*mp, struct ip *), sizeof(struct ip6_hdr),
268 ifp, (dir == PFIL_OUT), mp));
269 }
270 # endif
271
272
273 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
274
275 # if (__NetBSD_Version__ >= 799000400)
276
277 static void ipf_pfilsync(void *, unsigned long, void *);
278
279 static void
280 ipf_pfilsync(void *hdr, unsigned long cmd, void *arg2)
281 {
282 /*
283 * The interface pointer is useless for create (we have nothing to
284 * compare it to) and at detach, the interface name is still in the
285 * list of active NICs (albeit, down, but that's not any real
286 * indicator) and doing ifunit() on the name will still return the
287 * pointer, so it's not much use then, either.
288 */
289 ipf_sync(&ipfmain, NULL);
290 }
291
292 # else
293
294 static int ipf_pfilsync(void *, struct mbuf **, struct ifnet *, int);
295
296 static int
297 ipf_pfilsync(void *hdr, struct mbuf **mp, struct ifnet *ifp, int dir)
298 {
299 ipf_sync(&ipfmain, NULL);
300 return 0;
301 }
302
303 # endif
304 # endif
305
306 #endif /* __NetBSD_Version__ >= 105110000 */
307
308
309 #if defined(IPFILTER_LKM)
310 int
311 ipf_identify(s)
312 char *s;
313 {
314 if (strcmp(s, "ipl") == 0)
315 return 1;
316 return 0;
317 }
318 #endif /* IPFILTER_LKM */
319
320 #if (__NetBSD_Version__ >= 599002000)
321 static int
322 ipf_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
323 void *arg0, void *arg1, void *arg2, void *arg3)
324 {
325 int result;
326 enum kauth_network_req req;
327
328 result = KAUTH_RESULT_DEFER;
329 req = (enum kauth_network_req)arg0;
330
331 if (action != KAUTH_NETWORK_FIREWALL)
332 return result;
333
334 /* These must have came from device context. */
335 if ((req == KAUTH_REQ_NETWORK_FIREWALL_FW) ||
336 (req == KAUTH_REQ_NETWORK_FIREWALL_NAT))
337 result = KAUTH_RESULT_ALLOW;
338
339 return result;
340 }
341 #endif
342
343 /*
344 * Try to detect the case when compiling for NetBSD with pseudo-device
345 */
346 void
347 ipfilterattach(int count)
348 {
349
350 #if (__NetBSD_Version__ >= 799003000)
351 return;
352 #else
353 #if (__NetBSD_Version__ >= 599002000)
354 ipf_listener = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
355 ipf_listener_cb, NULL);
356 #endif
357
358 if (ipf_load_all() == 0)
359 (void) ipf_create_all(&ipfmain);
360 #endif
361 }
362
363
364 int
365 ipfattach(ipf_main_softc_t *softc)
366 {
367 SPL_INT(s);
368 #if (__NetBSD_Version__ >= 499005500)
369 int i;
370 #endif
371 #if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000)
372 int error = 0;
373 # if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000)
374 pfil_head_t *ph_inet;
375 # ifdef USE_INET6
376 pfil_head_t *ph_inet6;
377 # endif
378 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
379 pfil_head_t *ph_ifsync;
380 # endif
381 # endif
382 #endif
383
384 SPL_NET(s);
385 if ((softc->ipf_running > 0) || (ipf_checkp == ipf_check)) {
386 printf("IP Filter: already initialized\n");
387 SPL_X(s);
388 IPFERROR(130017);
389 return EBUSY;
390 }
391
392 if (ipf_init_all(softc) < 0) {
393 SPL_X(s);
394 IPFERROR(130015);
395 return EIO;
396 }
397
398 #ifdef NETBSD_PF
399 # if (__NetBSD_Version__ >= 104200000)
400 # if __NetBSD_Version__ >= 105110000
401 ph_inet = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET);
402 # ifdef USE_INET6
403 ph_inet6 = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET6);
404 # endif
405 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
406 ph_ifsync = pfil_head_get(PFIL_TYPE_IFNET, 0);
407 # endif
408
409 if (ph_inet == NULL
410 # ifdef USE_INET6
411 && ph_inet6 == NULL
412 # endif
413 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
414 && ph_ifsync == NULL
415 # endif
416 ) {
417 SPL_X(s);
418 IPFERROR(130016);
419 return ENODEV;
420 }
421
422 if (ph_inet != NULL)
423 error = pfil_add_hook((void *)ipf_check_wrapper, NULL,
424 PFIL_IN|PFIL_OUT, ph_inet);
425 else
426 error = 0;
427 # else
428 error = pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT,
429 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
430 # endif
431 if (error) {
432 IPFERROR(130013);
433 goto pfil_error;
434 }
435 # else
436 pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT);
437 # endif
438
439 # ifdef USE_INET6
440 # if __NetBSD_Version__ >= 105110000
441 if (ph_inet6 != NULL)
442 error = pfil_add_hook((void *)ipf_check_wrapper6, NULL,
443 PFIL_IN|PFIL_OUT, ph_inet6);
444 else
445 error = 0;
446 if (error) {
447 pfil_remove_hook((void *)ipf_check_wrapper6, NULL,
448 PFIL_IN|PFIL_OUT, ph_inet6);
449 ipfmain.ipf_interror = 130014;
450 goto pfil_error;
451 }
452 # else
453 error = pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT,
454 &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh);
455 if (error) {
456 pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT,
457 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
458 IPFERROR(130014);
459 goto pfil_error;
460 }
461 # endif
462 # endif
463
464 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
465 if (ph_ifsync != NULL)
466 #if (__NetBSD_Version__ >= 799000400)
467 (void) pfil_add_ihook((void *)ipf_pfilsync, NULL,
468 PFIL_IFNET, ph_ifsync);
469 #else
470 (void) pfil_add_hook((void *)ipf_pfilsync, NULL,
471 PFIL_IFNET, ph_ifsync);
472 #endif
473 # endif
474 #endif
475
476 #if (__NetBSD_Version__ >= 499005500)
477 for (i = 0; i < IPL_LOGSIZE; i++)
478 selinit(&ipfmain.ipf_selwait[i]);
479 #else
480 bzero((char *)ipfmain.ipf_selwait, sizeof(ipfmain.ipf_selwait));
481 #endif
482 ipf_savep = ipf_checkp;
483 ipf_checkp = ipf_check;
484
485 #ifdef INET
486 if (softc->ipf_control_forwarding & 1)
487 ipforwarding = 1;
488 #endif
489
490 ipid = 0;
491
492 SPL_X(s);
493
494 #if (__NetBSD_Version__ >= 104010000)
495 # if (__NetBSD_Version__ >= 499002000)
496 callout_init(&softc->ipf_slow_ch, 0);
497 # else
498 callout_init(&softc->ipf_slow_ch);
499 # endif
500 callout_reset(&softc->ipf_slow_ch, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT,
501 ipf_timer_func, softc);
502 #else
503 timeout(ipf_timer_func, softc, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT);
504 #endif
505
506 return 0;
507
508 #if __NetBSD_Version__ >= 105110000
509 pfil_error:
510 SPL_X(s);
511 ipf_fini_all(softc);
512 return error;
513 #endif
514 }
515
516 static void
517 ipf_timer_func(void *ptr)
518 {
519 ipf_main_softc_t *softc = ptr;
520 SPL_INT(s);
521
522 SPL_NET(s);
523 READ_ENTER(&softc->ipf_global);
524
525 if (softc->ipf_running > 0)
526 ipf_slowtimer(softc);
527
528 if (softc->ipf_running == -1 || softc->ipf_running == 1) {
529 #if NETBSD_GE_REV(104240000)
530 callout_reset(&softc->ipf_slow_ch, hz / 2,
531 ipf_timer_func, softc);
532 #else
533 timeout(ipf_timer_func, softc,
534 (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT);
535 #endif
536 }
537 RWLOCK_EXIT(&softc->ipf_global);
538 SPL_X(s);
539 }
540
541
542 /*
543 * Disable the filter by removing the hooks from the IP input/output
544 * stream.
545 */
546 int
547 ipfdetach(ipf_main_softc_t *softc)
548 {
549 SPL_INT(s);
550 #if (__NetBSD_Version__ >= 499005500)
551 int i;
552 #endif
553 #if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000)
554 int error = 0;
555 # if __NetBSD_Version__ >= 105150000
556 pfil_head_t *ph_inet = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET);
557 # ifdef USE_INET6
558 pfil_head_t *ph_inet6 = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET6);
559 # endif
560 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
561 struct pfil_head *ph_ifsync = pfil_head_get(PFIL_TYPE_IFNET, 0);
562 # endif
563 # endif
564 #endif
565
566 SPL_NET(s);
567
568 #if (__NetBSD_Version__ >= 104010000)
569 if (softc->ipf_running > 0)
570 callout_stop(&softc->ipf_slow_ch);
571 #else
572 untimeout(ipf_slowtimer, NULL);
573 #endif /* NetBSD */
574
575 ipf_checkp = ipf_savep;
576 (void) ipf_flush(softc, IPL_LOGIPF, FR_INQUE|FR_OUTQUE|FR_INACTIVE);
577 (void) ipf_flush(softc, IPL_LOGIPF, FR_INQUE|FR_OUTQUE);
578
579 #ifdef INET
580 if (softc->ipf_control_forwarding & 2)
581 ipforwarding = 0;
582 #endif
583
584 #ifdef NETBSD_PF
585 # if (__NetBSD_Version__ >= 104200000)
586 # if __NetBSD_Version__ >= 105110000
587 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
588 (void) pfil_remove_hook((void *)ipf_pfilsync, NULL,
589 PFIL_IFNET, ph_ifsync);
590 # endif
591
592 if (ph_inet != NULL)
593 error = pfil_remove_hook((void *)ipf_check_wrapper, NULL,
594 PFIL_IN|PFIL_OUT, ph_inet);
595 else
596 error = 0;
597 # else
598 error = pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT,
599 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
600 # endif
601 if (error) {
602 SPL_X(s);
603 IPFERROR(130011);
604 return error;
605 }
606 # else
607 pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT);
608 # endif
609 # ifdef USE_INET6
610 # if __NetBSD_Version__ >= 105110000
611 if (ph_inet6 != NULL)
612 error = pfil_remove_hook((void *)ipf_check_wrapper6, NULL,
613 PFIL_IN|PFIL_OUT, ph_inet6);
614 else
615 error = 0;
616 # else
617 error = pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT,
618 &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh);
619 # endif
620 if (error) {
621 SPL_X(s);
622 IPFERROR(130012);
623 return error;
624 }
625 # endif
626 #endif
627 SPL_X(s);
628
629 #if (__NetBSD_Version__ >= 499005500)
630 for (i = 0; i < IPL_LOGSIZE; i++)
631 seldestroy(&ipfmain.ipf_selwait[i]);
632 #endif
633
634 ipf_fini_all(softc);
635
636 return 0;
637 }
638
639
640 /*
641 * Filter ioctl interface.
642 */
643 int
644 ipfioctl(dev_t dev, u_long cmd,
645 #if (__NetBSD_Version__ >= 499001000)
646 void *data,
647 #else
648 caddr_t data,
649 #endif
650 int mode
651 #if (NetBSD >= 199511)
652 # if (__NetBSD_Version__ >= 399001400)
653 , struct lwp *p
654 # if (__NetBSD_Version__ >= 399002000)
655 # define UID(l) kauth_cred_getuid((l)->l_cred)
656 # else
657 # define UID(l) ((l)->l_proc->p_cred->p_ruid)
658 # endif
659 # else
660 , struct proc *p
661 # define UID(p) ((p)->p_cred->p_ruid)
662 # endif
663 #endif
664 )
665 {
666 int error = 0, unit = 0;
667 SPL_INT(s);
668
669 #if (__NetBSD_Version__ >= 399002000)
670 if ((mode & FWRITE) &&
671 kauth_authorize_network(p->l_cred, KAUTH_NETWORK_FIREWALL,
672 KAUTH_REQ_NETWORK_FIREWALL_FW, NULL,
673 NULL, NULL)) {
674 ipfmain.ipf_interror = 130005;
675 return EPERM;
676 }
677 #else
678 if ((securelevel >= 2) && (mode & FWRITE)) {
679 ipfmain.ipf_interror = 130001;
680 return EPERM;
681 }
682 #endif
683
684 unit = GET_MINOR(dev);
685 if ((IPL_LOGMAX < unit) || (unit < 0)) {
686 ipfmain.ipf_interror = 130002;
687 return ENXIO;
688 }
689
690 if (ipfmain.ipf_running <= 0) {
691 if (unit != IPL_LOGIPF && cmd != SIOCIPFINTERROR) {
692 ipfmain.ipf_interror = 130003;
693 return EIO;
694 }
695 if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET &&
696 cmd != SIOCIPFSET && cmd != SIOCFRENB &&
697 cmd != SIOCGETFS && cmd != SIOCGETFF &&
698 cmd != SIOCIPFINTERROR) {
699 ipfmain.ipf_interror = 130004;
700 return EIO;
701 }
702 }
703
704 SPL_NET(s);
705
706 error = ipf_ioctlswitch(&ipfmain, unit, data, cmd, mode, UID(p), p);
707 if (error != -1) {
708 SPL_X(s);
709 return error;
710 }
711
712 SPL_X(s);
713 return error;
714 }
715
716
717 /*
718 * ipf_send_reset - this could conceivably be a call to tcp_respond(), but that
719 * requires a large amount of setting up and isn't any more efficient.
720 */
721 int
722 ipf_send_reset(fr_info_t *fin)
723 {
724 struct tcphdr *tcp, *tcp2;
725 int tlen = 0, hlen;
726 struct mbuf *m;
727 #ifdef USE_INET6
728 ip6_t *ip6;
729 #endif
730 ip_t *ip;
731
732 tcp = fin->fin_dp;
733 if (tcp->th_flags & TH_RST)
734 return -1; /* feedback loop */
735
736 if (ipf_checkl4sum(fin) == -1)
737 return -1;
738
739 tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) +
740 ((tcp->th_flags & TH_SYN) ? 1 : 0) +
741 ((tcp->th_flags & TH_FIN) ? 1 : 0);
742
743 #ifdef USE_INET6
744 hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t);
745 #else
746 hlen = sizeof(ip_t);
747 #endif
748 #ifdef MGETHDR
749 MGETHDR(m, M_DONTWAIT, MT_HEADER);
750 #else
751 MGET(m, M_DONTWAIT, MT_HEADER);
752 #endif
753 if (m == NULL)
754 return -1;
755 if (sizeof(*tcp2) + hlen > MHLEN) {
756 MCLGET(m, M_DONTWAIT);
757 if (m == NULL)
758 return -1;
759 if ((m->m_flags & M_EXT) == 0) {
760 FREE_MB_T(m);
761 return -1;
762 }
763 }
764
765 m->m_len = sizeof(*tcp2) + hlen;
766 m->m_data += max_linkhdr;
767 m->m_pkthdr.len = m->m_len;
768 m_reset_rcvif(m);
769 ip = mtod(m, struct ip *);
770 bzero((char *)ip, hlen);
771 #ifdef USE_INET6
772 ip6 = (ip6_t *)ip;
773 #endif
774 bzero((char *)ip, sizeof(*tcp2) + hlen);
775 tcp2 = (struct tcphdr *)((char *)ip + hlen);
776 tcp2->th_sport = tcp->th_dport;
777 tcp2->th_dport = tcp->th_sport;
778
779 if (tcp->th_flags & TH_ACK) {
780 tcp2->th_seq = tcp->th_ack;
781 tcp2->th_flags = TH_RST;
782 tcp2->th_ack = 0;
783 } else {
784 tcp2->th_seq = 0;
785 tcp2->th_ack = ntohl(tcp->th_seq);
786 tcp2->th_ack += tlen;
787 tcp2->th_ack = htonl(tcp2->th_ack);
788 tcp2->th_flags = TH_RST|TH_ACK;
789 }
790 tcp2->th_x2 = 0;
791 TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2);
792 tcp2->th_win = tcp->th_win;
793 tcp2->th_sum = 0;
794 tcp2->th_urp = 0;
795
796 #ifdef USE_INET6
797 if (fin->fin_v == 6) {
798 ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow;
799 ip6->ip6_plen = htons(sizeof(struct tcphdr));
800 ip6->ip6_nxt = IPPROTO_TCP;
801 ip6->ip6_hlim = 0;
802 ip6->ip6_src = fin->fin_dst6.in6;
803 ip6->ip6_dst = fin->fin_src6.in6;
804 tcp2->th_sum = in6_cksum(m, IPPROTO_TCP,
805 sizeof(*ip6), sizeof(*tcp2));
806 return ipf_send_ip(fin, m);
807 }
808 #endif
809 #ifdef INET
810 ip->ip_p = IPPROTO_TCP;
811 ip->ip_len = htons(sizeof(struct tcphdr));
812 ip->ip_src.s_addr = fin->fin_daddr;
813 ip->ip_dst.s_addr = fin->fin_saddr;
814 tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2));
815 ip->ip_len = hlen + sizeof(*tcp2);
816 return ipf_send_ip(fin, m);
817 #else
818 return 0;
819 #endif
820 }
821
822
823 /*
824 * Expects ip_len to be in host byte order when called.
825 */
826 static int
827 ipf_send_ip(fr_info_t *fin, mb_t *m)
828 {
829 fr_info_t fnew;
830 #ifdef INET
831 ip_t *oip;
832 #endif
833 ip_t *ip;
834 int hlen;
835
836 ip = mtod(m, ip_t *);
837 bzero((char *)&fnew, sizeof(fnew));
838 fnew.fin_main_soft = fin->fin_main_soft;
839
840 IP_V_A(ip, fin->fin_v);
841 switch (fin->fin_v)
842 {
843 #ifdef INET
844 case 4 :
845 oip = fin->fin_ip;
846 hlen = sizeof(*oip);
847 fnew.fin_v = 4;
848 fnew.fin_p = ip->ip_p;
849 fnew.fin_plen = ntohs(ip->ip_len);
850 HTONS(ip->ip_len);
851 IP_HL_A(ip, sizeof(*oip) >> 2);
852 ip->ip_tos = oip->ip_tos;
853 ip->ip_id = ipf_nextipid(fin);
854 ip->ip_off = htons(ip_mtudisc ? IP_DF : 0);
855 ip->ip_ttl = ip_defttl;
856 ip->ip_sum = 0;
857 break;
858 #endif
859 #ifdef USE_INET6
860 case 6 :
861 {
862 ip6_t *ip6 = (ip6_t *)ip;
863
864 ip6->ip6_vfc = 0x60;
865 ip6->ip6_hlim = IPDEFTTL;
866
867 hlen = sizeof(*ip6);
868 fnew.fin_p = ip6->ip6_nxt;
869 fnew.fin_v = 6;
870 fnew.fin_plen = ntohs(ip6->ip6_plen) + hlen;
871 break;
872 }
873 #endif
874 default :
875 return EINVAL;
876 }
877 #ifdef KAME_IPSEC
878 m_reset_rcvif(m);
879 #endif
880
881 fnew.fin_ifp = fin->fin_ifp;
882 fnew.fin_flx = FI_NOCKSUM;
883 fnew.fin_m = m;
884 fnew.fin_ip = ip;
885 fnew.fin_mp = &m;
886 fnew.fin_hlen = hlen;
887 fnew.fin_dp = (char *)ip + hlen;
888 (void) ipf_makefrip(hlen, ip, &fnew);
889
890 return ipf_fastroute(m, &m, &fnew, NULL);
891 }
892
893
894 int
895 ipf_send_icmp_err(int type, fr_info_t *fin, int dst)
896 {
897 int err, hlen, xtra, iclen, ohlen, avail;
898 struct in_addr dst4;
899 struct icmp *icmp;
900 struct mbuf *m;
901 i6addr_t dst6;
902 void *ifp;
903 #ifdef USE_INET6
904 int code;
905 ip6_t *ip6;
906 #endif
907 ip_t *ip, *ip2;
908
909 if ((type < 0) || (type > ICMP_MAXTYPE))
910 return -1;
911
912 #ifdef USE_INET6
913 code = fin->fin_icode;
914 if ((code < 0) || (code >= sizeof(icmptoicmp6unreach)/sizeof(int)))
915 return -1;
916 #endif
917
918 if (ipf_checkl4sum(fin) == -1)
919 return -1;
920 #ifdef MGETHDR
921 MGETHDR(m, M_DONTWAIT, MT_HEADER);
922 #else
923 MGET(m, M_DONTWAIT, MT_HEADER);
924 #endif
925 if (m == NULL)
926 return -1;
927 avail = MHLEN;
928
929 xtra = 0;
930 hlen = 0;
931 ohlen = 0;
932 dst4.s_addr = 0;
933 ifp = fin->fin_ifp;
934 if (fin->fin_v == 4) {
935 if ((fin->fin_p == IPPROTO_ICMP) && !(fin->fin_flx & FI_SHORT))
936 switch (ntohs(fin->fin_data[0]) >> 8)
937 {
938 case ICMP_ECHO :
939 case ICMP_TSTAMP :
940 case ICMP_IREQ :
941 case ICMP_MASKREQ :
942 break;
943 default :
944 FREE_MB_T(m);
945 return 0;
946 }
947
948 if (dst == 0) {
949 if (ipf_ifpaddr(&ipfmain, 4, FRI_NORMAL, ifp,
950 &dst6, NULL) == -1) {
951 FREE_MB_T(m);
952 return -1;
953 }
954 dst4 = dst6.in4;
955 } else
956 dst4.s_addr = fin->fin_daddr;
957
958 hlen = sizeof(ip_t);
959 ohlen = fin->fin_hlen;
960 iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen;
961 if (fin->fin_hlen < fin->fin_plen)
962 xtra = MIN(fin->fin_dlen, 8);
963 else
964 xtra = 0;
965 }
966
967 #ifdef USE_INET6
968 else if (fin->fin_v == 6) {
969 hlen = sizeof(ip6_t);
970 ohlen = sizeof(ip6_t);
971 iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen;
972 type = icmptoicmp6types[type];
973 if (type == ICMP6_DST_UNREACH)
974 code = icmptoicmp6unreach[code];
975
976 if (iclen + max_linkhdr + fin->fin_plen > avail) {
977 MCLGET(m, M_DONTWAIT);
978 if (m == NULL)
979 return -1;
980 if ((m->m_flags & M_EXT) == 0) {
981 FREE_MB_T(m);
982 return -1;
983 }
984 avail = MCLBYTES;
985 }
986 xtra = MIN(fin->fin_plen, avail - iclen - max_linkhdr);
987 xtra = MIN(xtra, IPV6_MMTU - iclen);
988 if (dst == 0) {
989 if (ipf_ifpaddr(&ipfmain, 6, FRI_NORMAL, ifp,
990 &dst6, NULL) == -1) {
991 FREE_MB_T(m);
992 return -1;
993 }
994 } else
995 dst6 = fin->fin_dst6;
996 }
997 #endif
998 else {
999 FREE_MB_T(m);
1000 return -1;
1001 }
1002
1003 avail -= (max_linkhdr + iclen);
1004 if (avail < 0) {
1005 FREE_MB_T(m);
1006 return -1;
1007 }
1008 if (xtra > avail)
1009 xtra = avail;
1010 iclen += xtra;
1011 m->m_data += max_linkhdr;
1012 m_reset_rcvif(m);
1013 m->m_pkthdr.len = iclen;
1014 m->m_len = iclen;
1015 ip = mtod(m, ip_t *);
1016 icmp = (struct icmp *)((char *)ip + hlen);
1017 ip2 = (ip_t *)&icmp->icmp_ip;
1018
1019 icmp->icmp_type = type;
1020 icmp->icmp_code = fin->fin_icode;
1021 icmp->icmp_cksum = 0;
1022 #ifdef icmp_nextmtu
1023 if (type == ICMP_UNREACH && fin->fin_icode == ICMP_UNREACH_NEEDFRAG) {
1024 if (fin->fin_mtu != 0) {
1025 icmp->icmp_nextmtu = htons(fin->fin_mtu);
1026
1027 } else if (ifp != NULL) {
1028 icmp->icmp_nextmtu = htons(GETIFMTU_4(ifp));
1029
1030 } else { /* make up a number... */
1031 icmp->icmp_nextmtu = htons(fin->fin_plen - 20);
1032 }
1033 }
1034 #endif
1035
1036 bcopy((char *)fin->fin_ip, (char *)ip2, ohlen);
1037
1038 #if defined(M_CSUM_IPv4)
1039 /*
1040 * Clear any in-bound checksum flags for this packet.
1041 */
1042 m->m_pkthdr.csuminfo = 0;
1043 #endif /* __NetBSD__ && M_CSUM_IPv4 */
1044
1045 #ifdef USE_INET6
1046 ip6 = (ip6_t *)ip;
1047 if (fin->fin_v == 6) {
1048 ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow;
1049 ip6->ip6_plen = htons(iclen - hlen);
1050 ip6->ip6_nxt = IPPROTO_ICMPV6;
1051 ip6->ip6_hlim = 0;
1052 ip6->ip6_src = dst6.in6;
1053 ip6->ip6_dst = fin->fin_src6.in6;
1054 if (xtra > 0)
1055 bcopy((char *)fin->fin_ip + ohlen,
1056 (char *)&icmp->icmp_ip + ohlen, xtra);
1057 icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6,
1058 sizeof(*ip6), iclen - hlen);
1059 } else
1060 #endif
1061 {
1062 ip->ip_p = IPPROTO_ICMP;
1063 ip->ip_src.s_addr = dst4.s_addr;
1064 ip->ip_dst.s_addr = fin->fin_saddr;
1065
1066 if (xtra > 0)
1067 bcopy((char *)fin->fin_ip + ohlen,
1068 (char *)&icmp->icmp_ip + ohlen, xtra);
1069 icmp->icmp_cksum = ipf_cksum((u_short *)icmp,
1070 sizeof(*icmp) + 8);
1071 ip->ip_len = iclen;
1072 ip->ip_p = IPPROTO_ICMP;
1073 }
1074 err = ipf_send_ip(fin, m);
1075 return err;
1076 }
1077
1078
1079 /*
1080 * m0 - pointer to mbuf where the IP packet starts
1081 * mpp - pointer to the mbuf pointer that is the start of the mbuf chain
1082 */
1083 int
1084 ipf_fastroute(mb_t *m0, mb_t **mpp, fr_info_t *fin, frdest_t *fdp)
1085 {
1086 register struct ip *ip, *mhip;
1087 register struct mbuf *m = *mpp;
1088 register struct route *ro;
1089 int len, off, error = 0, hlen, code;
1090 struct ifnet *ifp, *sifp;
1091 ipf_main_softc_t *softc;
1092 #if __NetBSD_Version__ >= 499001100
1093 union {
1094 struct sockaddr dst;
1095 struct sockaddr_in dst4;
1096 } u;
1097 #else
1098 struct sockaddr_in *dst4;
1099 #endif
1100 struct sockaddr *dst;
1101 u_short ip_off, ip_len;
1102 struct route iproute;
1103 struct rtentry *rt;
1104 frdest_t node;
1105 frentry_t *fr;
1106
1107 if (fin->fin_v == 6) {
1108 #ifdef USE_INET6
1109 error = ipf_fastroute6(m0, mpp, fin, fdp);
1110 #else
1111 error = EPROTONOSUPPORT;
1112 #endif
1113 if ((error != 0) && (*mpp != NULL))
1114 FREE_MB_T(*mpp);
1115 return error;
1116 }
1117 #ifndef INET
1118 FREE_MB_T(*mpp);
1119 return EPROTONOSUPPORT;
1120 #else
1121
1122 hlen = fin->fin_hlen;
1123 ip = mtod(m0, struct ip *);
1124 softc = fin->fin_main_soft;
1125 rt = NULL;
1126 ifp = NULL;
1127
1128 # if defined(M_CSUM_IPv4)
1129 /*
1130 * Clear any in-bound checksum flags for this packet.
1131 */
1132 m0->m_pkthdr.csuminfo = 0;
1133 # endif /* __NetBSD__ && M_CSUM_IPv4 */
1134
1135 /*
1136 * Route packet.
1137 */
1138 ro = &iproute;
1139 memset(ro, 0, sizeof(*ro));
1140 fr = fin->fin_fr;
1141
1142 if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) &&
1143 (fdp->fd_type == FRD_DSTLIST)) {
1144 if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0)
1145 fdp = &node;
1146 }
1147 if (fdp != NULL)
1148 ifp = fdp->fd_ptr;
1149 else
1150 ifp = fin->fin_ifp;
1151
1152 if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE))) {
1153 error = -2;
1154 goto bad;
1155 }
1156
1157 # if __NetBSD_Version__ >= 499001100
1158 if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0))
1159 sockaddr_in_init(&u.dst4, &fdp->fd_ip, 0);
1160 else
1161 sockaddr_in_init(&u.dst4, &ip->ip_dst, 0);
1162 dst = &u.dst;
1163 rtcache_setdst(ro, dst);
1164 rt = rtcache_init(ro);
1165 # else
1166 dst4 = (struct sockaddr_in *)&ro->ro_dst;
1167 dst = (struct sockaddr *)dst4;
1168 dst4->sin_family = AF_INET;
1169 dst4->sin_addr = ip->ip_dst;
1170
1171 if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0))
1172 dst4->sin_addr = fdp->fd_ip;
1173
1174 dst4->sin_len = sizeof(*dst);
1175 rtalloc(ro);
1176 rt = ro->ro_rt;
1177 # endif
1178 if ((ifp == NULL) && (rt != NULL))
1179 ifp = rt->rt_ifp;
1180 if ((rt == NULL) || (ifp == NULL)) {
1181 #ifdef INET
1182 if (in_localaddr(ip->ip_dst))
1183 error = EHOSTUNREACH;
1184 else
1185 #endif
1186 error = ENETUNREACH;
1187 goto bad;
1188 }
1189
1190
1191 if (rt->rt_flags & RTF_GATEWAY)
1192 dst = rt->rt_gateway;
1193
1194 rt->rt_use++;
1195
1196 /*
1197 * For input packets which are being "fastrouted", they won't
1198 * go back through output filtering and miss their chance to get
1199 * NAT'd and counted. Duplicated packets aren't considered to be
1200 * part of the normal packet stream, so do not NAT them or pass
1201 * them through stateful checking, etc.
1202 */
1203 if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) {
1204 sifp = fin->fin_ifp;
1205 fin->fin_ifp = ifp;
1206 fin->fin_out = 1;
1207 (void) ipf_acctpkt(fin, NULL);
1208 fin->fin_fr = NULL;
1209 if (!fr || !(fr->fr_flags & FR_RETMASK)) {
1210 u_32_t pass;
1211
1212 (void) ipf_state_check(fin, &pass);
1213 }
1214
1215 switch (ipf_nat_checkout(fin, NULL))
1216 {
1217 case 0 :
1218 break;
1219 case 1 :
1220 ip->ip_sum = 0;
1221 break;
1222 case -1 :
1223 error = -1;
1224 goto bad;
1225 break;
1226 }
1227
1228 fin->fin_ifp = sifp;
1229 fin->fin_out = 0;
1230 } else
1231 ip->ip_sum = 0;
1232 /*
1233 * If small enough for interface, can just send directly.
1234 */
1235 m_set_rcvif(m, ifp);
1236
1237 ip_len = ntohs(ip->ip_len);
1238 if (ip_len <= ifp->if_mtu) {
1239 # if defined(M_CSUM_IPv4)
1240 # if (__NetBSD_Version__ >= 105009999)
1241 if (ifp->if_csum_flags_tx & M_CSUM_IPv4)
1242 m->m_pkthdr.csuminfo |= M_CSUM_IPv4;
1243 # else
1244 if (ifp->if_capabilities & IFCAP_CSUM_IPv4)
1245 m->m_pkthdr.csuminfo |= M_CSUM_IPv4;
1246 # endif /* (__NetBSD_Version__ >= 105009999) */
1247 else if (ip->ip_sum == 0)
1248 ip->ip_sum = in_cksum(m, hlen);
1249 # else
1250 if (!ip->ip_sum)
1251 ip->ip_sum = in_cksum(m, hlen);
1252 # endif /* M_CSUM_IPv4 */
1253
1254 error = if_output_lock(ifp, ifp, m, dst, rt);
1255 goto done;
1256 }
1257
1258 /*
1259 * Too large for interface; fragment if possible.
1260 * Must be able to put at least 8 bytes per fragment.
1261 */
1262 ip_off = ntohs(ip->ip_off);
1263 if (ip_off & IP_DF) {
1264 error = EMSGSIZE;
1265 goto bad;
1266 }
1267 len = (ifp->if_mtu - hlen) &~ 7;
1268 if (len < 8) {
1269 error = EMSGSIZE;
1270 goto bad;
1271 }
1272
1273 {
1274 int mhlen, firstlen = len;
1275 struct mbuf **mnext = &m->m_act;
1276
1277 /*
1278 * Loop through length of segment after first fragment,
1279 * make new header and copy data of each part and link onto chain.
1280 */
1281 m0 = m;
1282 mhlen = sizeof (struct ip);
1283 for (off = hlen + len; off < ip_len; off += len) {
1284 # ifdef MGETHDR
1285 MGETHDR(m, M_DONTWAIT, MT_HEADER);
1286 # else
1287 MGET(m, M_DONTWAIT, MT_HEADER);
1288 # endif
1289 if (m == 0) {
1290 m = m0;
1291 error = ENOBUFS;
1292 goto bad;
1293 }
1294 m->m_data += max_linkhdr;
1295 mhip = mtod(m, struct ip *);
1296 bcopy((char *)ip, (char *)mhip, sizeof(*ip));
1297 #ifdef INET
1298 if (hlen > sizeof (struct ip)) {
1299 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
1300 IP_HL_A(mhip, mhlen >> 2);
1301 }
1302 #endif
1303 m->m_len = mhlen;
1304 mhip->ip_off = ((off - hlen) >> 3) + ip_off;
1305 if (off + len >= ip_len)
1306 len = ip_len - off;
1307 else
1308 mhip->ip_off |= IP_MF;
1309 mhip->ip_len = htons((u_short)(len + mhlen));
1310 m->m_next = m_copy(m0, off, len);
1311 if (m->m_next == 0) {
1312 error = ENOBUFS; /* ??? */
1313 goto sendorfree;
1314 }
1315 m->m_pkthdr.len = mhlen + len;
1316 m_reset_rcvif(m);
1317 mhip->ip_off = htons((u_short)mhip->ip_off);
1318 mhip->ip_sum = 0;
1319 #ifdef INET
1320 mhip->ip_sum = in_cksum(m, mhlen);
1321 #endif
1322 *mnext = m;
1323 mnext = &m->m_act;
1324 }
1325 /*
1326 * Update first fragment by trimming what's been copied out
1327 * and updating header, then send each fragment (in order).
1328 */
1329 m_adj(m0, hlen + firstlen - ip_len);
1330 ip->ip_len = htons((u_short)(hlen + firstlen));
1331 ip->ip_off = htons((u_short)IP_MF);
1332 ip->ip_sum = 0;
1333 #ifdef INET
1334 ip->ip_sum = in_cksum(m0, hlen);
1335 #endif
1336 sendorfree:
1337 for (m = m0; m; m = m0) {
1338 m0 = m->m_act;
1339 m->m_act = 0;
1340 if (error == 0) {
1341 KERNEL_LOCK(1, NULL);
1342 error = (*ifp->if_output)(ifp, m, dst, rt);
1343 KERNEL_UNLOCK_ONE(NULL);
1344 } else {
1345 FREE_MB_T(m);
1346 }
1347 }
1348 }
1349 done:
1350 if (!error)
1351 softc->ipf_frouteok[0]++;
1352 else
1353 softc->ipf_frouteok[1]++;
1354
1355 # if __NetBSD_Version__ >= 499001100
1356 rtcache_unref(rt, ro);
1357 rtcache_free(ro);
1358 # else
1359 if (rt) {
1360 RTFREE(rt);
1361 }
1362 # endif
1363 return error;
1364 bad:
1365 if (error == EMSGSIZE) {
1366 sifp = fin->fin_ifp;
1367 code = fin->fin_icode;
1368 fin->fin_icode = ICMP_UNREACH_NEEDFRAG;
1369 fin->fin_ifp = ifp;
1370 (void) ipf_send_icmp_err(ICMP_UNREACH, fin, 1);
1371 fin->fin_ifp = sifp;
1372 fin->fin_icode = code;
1373 }
1374 FREE_MB_T(m);
1375 goto done;
1376 #endif /* INET */
1377 }
1378
1379
1380 #if defined(USE_INET6)
1381 /*
1382 * This is the IPv6 specific fastroute code. It doesn't clean up the mbuf's
1383 * or ensure that it is an IPv6 packet that is being forwarded, those are
1384 * expected to be done by the called (ipf_fastroute).
1385 */
1386 static int
1387 ipf_fastroute6(struct mbuf *m0, struct mbuf **mpp, fr_info_t *fin,
1388 frdest_t *fdp)
1389 {
1390 # if __NetBSD_Version__ >= 499001100
1391 struct route ip6route;
1392 const struct sockaddr *dst;
1393 union {
1394 struct sockaddr dst;
1395 struct sockaddr_in6 dst6;
1396 } u;
1397 struct route *ro;
1398 # else
1399 struct route_in6 ip6route;
1400 struct sockaddr_in6 *dst6;
1401 struct route_in6 *ro;
1402 # endif
1403 struct rtentry *rt;
1404 struct ifnet *ifp;
1405 u_long mtu;
1406 int error;
1407
1408 error = 0;
1409 ro = &ip6route;
1410
1411 if (fdp != NULL)
1412 ifp = fdp->fd_ptr;
1413 else
1414 ifp = fin->fin_ifp;
1415 memset(ro, 0, sizeof(*ro));
1416 # if __NetBSD_Version__ >= 499001100
1417 if (fdp != NULL && IP6_NOTZERO(&fdp->fd_ip6))
1418 sockaddr_in6_init(&u.dst6, &fdp->fd_ip6.in6, 0, 0, 0);
1419 else
1420 sockaddr_in6_init(&u.dst6, &fin->fin_fi.fi_dst.in6, 0, 0, 0);
1421 dst = &u.dst;
1422 rtcache_setdst(ro, dst);
1423
1424 rt = rtcache_init(ro);
1425 if ((ifp == NULL) && (rt != NULL))
1426 ifp = rt->rt_ifp;
1427 # else
1428 dst6 = (struct sockaddr_in6 *)&ro->ro_dst;
1429 dst6->sin6_family = AF_INET6;
1430 dst6->sin6_len = sizeof(struct sockaddr_in6);
1431 dst6->sin6_addr = fin->fin_fi.fi_dst.in6;
1432
1433 if (fdp != NULL) {
1434 if (IP6_NOTZERO(&fdp->fd_ip6))
1435 dst6->sin6_addr = fdp->fd_ip6.in6;
1436 }
1437
1438 rtalloc((struct route *)ro);
1439
1440 if ((ifp == NULL) && (ro->ro_rt != NULL))
1441 ifp = ro->ro_rt->rt_ifp;
1442 rt = ro->ro_rt;
1443 # endif
1444 if ((rt == NULL) || (ifp == NULL)) {
1445
1446 error = EHOSTUNREACH;
1447 goto bad;
1448 }
1449
1450 /* KAME */
1451 # if __NetBSD_Version__ >= 499001100
1452 if (IN6_IS_ADDR_LINKLOCAL(&u.dst6.sin6_addr))
1453 u.dst6.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
1454 # else
1455 if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr))
1456 dst6->sin6_addr.s6_addr16[1] = htons(ifp->if_index);
1457 # endif
1458
1459 {
1460 # if (__NetBSD_Version__ >= 106010000) && !defined(IN6_LINKMTU)
1461 struct in6_ifextra *ife;
1462 # endif
1463 if (rt->rt_flags & RTF_GATEWAY)
1464 # if __NetBSD_Version__ >= 499001100
1465 dst = rt->rt_gateway;
1466 # else
1467 dst6 = (struct sockaddr_in6 *)rt->rt_gateway;
1468 # endif
1469 rt->rt_use++;
1470
1471 /* Determine path MTU. */
1472 # if (__NetBSD_Version__ <= 106009999)
1473 mtu = nd_ifinfo[ifp->if_index].linkmtu;
1474 # else
1475 # ifdef IN6_LINKMTU
1476 mtu = IN6_LINKMTU(ifp);
1477 # else
1478 ife = (struct in6_ifextra *)(ifp)->if_afdata[AF_INET6];
1479 mtu = ife->nd_ifinfo[ifp->if_index].linkmtu;
1480 # endif
1481 # endif
1482 if ((error == 0) && (m0->m_pkthdr.len <= mtu)) {
1483 # if __NetBSD_Version__ >= 499001100
1484 error = ip6_if_output(ifp, ifp, m0, satocsin6(dst), rt);
1485 # else
1486 error = nd6_output(ifp, ifp, m0, dst6, rt);
1487 # endif
1488 } else {
1489 error = EMSGSIZE;
1490 }
1491 }
1492 bad:
1493 # if __NetBSD_Version__ >= 499001100
1494 rtcache_unref(rt, ro);
1495 rtcache_free(ro);
1496 # else
1497 if (ro->ro_rt != NULL) {
1498 RTFREE(((struct route *)ro)->ro_rt);
1499 }
1500 # endif
1501 return error;
1502 }
1503 #endif /* INET6 */
1504
1505
1506 int
1507 ipf_verifysrc(fr_info_t *fin)
1508 {
1509 #if __NetBSD_Version__ >= 499001100
1510 union {
1511 struct sockaddr dst;
1512 struct sockaddr_in dst4;
1513 } u;
1514 struct rtentry *rt;
1515 #else
1516 struct sockaddr_in *dst;
1517 #endif
1518 struct route iproute;
1519 int rc;
1520
1521 #if __NetBSD_Version__ >= 499001100
1522 sockaddr_in_init(&u.dst4, &fin->fin_src, 0);
1523 rtcache_setdst(&iproute, &u.dst);
1524 rt = rtcache_init(&iproute);
1525 if (rt == NULL)
1526 rc = 0;
1527 else
1528 rc = (fin->fin_ifp == rt->rt_ifp);
1529 rtcache_unref(rt, &iproute);
1530 rtcache_free(&iproute);
1531 #else
1532 dst = (struct sockaddr_in *)&iproute.ro_dst;
1533 dst->sin_len = sizeof(*dst);
1534 dst->sin_family = AF_INET;
1535 dst->sin_addr = fin->fin_src;
1536 rtalloc(&iproute);
1537 if (iproute.ro_rt == NULL)
1538 return 0;
1539 rc = (fin->fin_ifp == iproute.ro_rt->rt_ifp);
1540 RTFREE(iproute.ro_rt);
1541 #endif
1542 return rc;
1543 }
1544
1545
1546 /*
1547 * return the first IP Address associated with an interface
1548 */
1549 int
1550 ipf_ifpaddr(ipf_main_softc_t *softc, int v, int atype, void *ifptr,
1551 i6addr_t *inp, i6addr_t *inpmask)
1552 {
1553 #ifdef USE_INET6
1554 struct in6_addr *inp6 = NULL;
1555 #endif
1556 struct sockaddr *sock, *mask;
1557 struct sockaddr_in *sin;
1558 struct ifaddr *ifa;
1559 struct ifnet *ifp;
1560
1561 if ((ifptr == NULL) || (ifptr == (void *)-1))
1562 return -1;
1563
1564 ifp = ifptr;
1565 mask = NULL;
1566
1567 if (v == 4)
1568 inp->in4.s_addr = 0;
1569 #ifdef USE_INET6
1570 else if (v == 6)
1571 bzero((char *)inp, sizeof(*inp));
1572 #endif
1573
1574 ifa = IFADDR_READER_FIRST(ifp);
1575 sock = ifa ? ifa->ifa_addr : NULL;
1576 while (sock != NULL && ifa != NULL) {
1577 sin = (struct sockaddr_in *)sock;
1578 if ((v == 4) && (sin->sin_family == AF_INET))
1579 break;
1580 #ifdef USE_INET6
1581 if ((v == 6) && (sin->sin_family == AF_INET6)) {
1582 inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr;
1583 if (!IN6_IS_ADDR_LINKLOCAL(inp6) &&
1584 !IN6_IS_ADDR_LOOPBACK(inp6))
1585 break;
1586 }
1587 #endif
1588 ifa = IFADDR_READER_NEXT(ifa);
1589 if (ifa != NULL)
1590 sock = ifa->ifa_addr;
1591 }
1592 if (ifa == NULL || sock == NULL)
1593 return -1;
1594
1595 mask = ifa->ifa_netmask;
1596 if (atype == FRI_BROADCAST)
1597 sock = ifa->ifa_broadaddr;
1598 else if (atype == FRI_PEERADDR)
1599 sock = ifa->ifa_dstaddr;
1600
1601 #ifdef USE_INET6
1602 if (v == 6)
1603 return ipf_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock,
1604 (struct sockaddr_in6 *)mask,
1605 inp, inpmask);
1606 #endif
1607 return ipf_ifpfillv4addr(atype, (struct sockaddr_in *)sock,
1608 (struct sockaddr_in *)mask,
1609 &inp->in4, &inpmask->in4);
1610 }
1611
1612
1613 u_32_t
1614 ipf_newisn(fr_info_t *fin)
1615 {
1616 #if __NetBSD_Version__ >= 105190000 /* 1.5T */
1617 size_t asz;
1618
1619 if (fin->fin_v == 4)
1620 asz = sizeof(struct in_addr);
1621 else if (fin->fin_v == 6)
1622 asz = sizeof(fin->fin_src);
1623 else /* XXX: no way to return error */
1624 return 0;
1625 #ifdef INET
1626 return tcp_new_iss1((void *)&fin->fin_src, (void *)&fin->fin_dst,
1627 fin->fin_sport, fin->fin_dport, asz, 0);
1628 #else
1629 return ENOSYS;
1630 #endif
1631 #else
1632 static int iss_seq_off = 0;
1633 u_char hash[16];
1634 u_32_t newiss;
1635 MD5_CTX ctx;
1636
1637 /*
1638 * Compute the base value of the ISS. It is a hash
1639 * of (saddr, sport, daddr, dport, secret).
1640 */
1641 MD5Init(&ctx);
1642
1643 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
1644 sizeof(fin->fin_fi.fi_src));
1645 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
1646 sizeof(fin->fin_fi.fi_dst));
1647 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
1648
1649 MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret));
1650
1651 MD5Final(hash, &ctx);
1652
1653 memcpy(&newiss, hash, sizeof(newiss));
1654
1655 /*
1656 * Now increment our "timer", and add it in to
1657 * the computed value.
1658 *
1659 * XXX Use `addin'?
1660 * XXX TCP_ISSINCR too large to use?
1661 */
1662 iss_seq_off += 0x00010000;
1663 newiss += iss_seq_off;
1664 return newiss;
1665 #endif
1666 }
1667
1668
1669 /* ------------------------------------------------------------------------ */
1670 /* Function: ipf_nextipid */
1671 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */
1672 /* Parameters: fin(I) - pointer to packet information */
1673 /* */
1674 /* Returns the next IPv4 ID to use for this packet. */
1675 /* ------------------------------------------------------------------------ */
1676 u_short
1677 ipf_nextipid(fr_info_t *fin)
1678 {
1679 #ifdef USE_MUTEXES
1680 ipf_main_softc_t *softc = fin->fin_main_soft;
1681 #endif
1682 u_short id;
1683
1684 MUTEX_ENTER(&softc->ipf_rw);
1685 id = ipid++;
1686 MUTEX_EXIT(&softc->ipf_rw);
1687
1688 return id;
1689 }
1690
1691
1692 EXTERN_INLINE int
1693 ipf_checkv4sum(fr_info_t *fin)
1694 {
1695 #ifdef M_CSUM_TCP_UDP_BAD
1696 int manual, pflag, cflags, active;
1697 mb_t *m;
1698
1699 if ((fin->fin_flx & FI_NOCKSUM) != 0)
1700 return 0;
1701
1702 if ((fin->fin_flx & FI_SHORT) != 0)
1703 return 1;
1704
1705 if (fin->fin_cksum != FI_CK_NEEDED)
1706 return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1;
1707
1708 manual = 0;
1709 m = fin->fin_m;
1710 if (m == NULL) {
1711 manual = 1;
1712 goto skipauto;
1713 }
1714
1715 switch (fin->fin_p)
1716 {
1717 case IPPROTO_UDP :
1718 pflag = M_CSUM_UDPv4;
1719 break;
1720 case IPPROTO_TCP :
1721 pflag = M_CSUM_TCPv4;
1722 break;
1723 default :
1724 pflag = 0;
1725 manual = 1;
1726 break;
1727 }
1728
1729 active = ((struct ifnet *)fin->fin_ifp)->if_csum_flags_rx & pflag;
1730 active |= M_CSUM_TCP_UDP_BAD | M_CSUM_DATA;
1731 cflags = m->m_pkthdr.csum_flags & active;
1732
1733 if (pflag != 0) {
1734 if (cflags == (pflag | M_CSUM_TCP_UDP_BAD)) {
1735 fin->fin_flx |= FI_BAD;
1736 fin->fin_cksum = FI_CK_BAD;
1737 } else if (cflags == (pflag | M_CSUM_DATA)) {
1738 if ((m->m_pkthdr.csum_data ^ 0xffff) != 0) {
1739 fin->fin_flx |= FI_BAD;
1740 fin->fin_cksum = FI_CK_BAD;
1741 } else {
1742 fin->fin_cksum = FI_CK_SUMOK;
1743 }
1744 } else if (cflags == pflag) {
1745 fin->fin_cksum = FI_CK_SUMOK;
1746 } else {
1747 manual = 1;
1748 }
1749 }
1750 skipauto:
1751 if (manual != 0) {
1752 if (ipf_checkl4sum(fin) == -1) {
1753 fin->fin_flx |= FI_BAD;
1754 return -1;
1755 }
1756 }
1757 #else
1758 if (ipf_checkl4sum(fin) == -1) {
1759 fin->fin_flx |= FI_BAD;
1760 return -1;
1761 }
1762 #endif
1763 return 0;
1764 }
1765
1766
1767 #ifdef USE_INET6
1768 EXTERN_INLINE int
1769 ipf_checkv6sum(fr_info_t *fin)
1770 {
1771 # ifdef M_CSUM_TCP_UDP_BAD
1772 int manual, pflag, cflags, active;
1773 mb_t *m;
1774
1775 if ((fin->fin_flx & FI_NOCKSUM) != 0)
1776 return 0;
1777
1778 if ((fin->fin_flx & FI_SHORT) != 0)
1779 return 1;
1780
1781 if (fin->fin_cksum != FI_CK_SUMOK)
1782 return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1;
1783
1784
1785 manual = 0;
1786 m = fin->fin_m;
1787
1788 switch (fin->fin_p)
1789 {
1790 case IPPROTO_UDP :
1791 pflag = M_CSUM_UDPv6;
1792 break;
1793 case IPPROTO_TCP :
1794 pflag = M_CSUM_TCPv6;
1795 break;
1796 default :
1797 pflag = 0;
1798 manual = 1;
1799 break;
1800 }
1801
1802 active = ((struct ifnet *)fin->fin_ifp)->if_csum_flags_rx & pflag;
1803 active |= M_CSUM_TCP_UDP_BAD | M_CSUM_DATA;
1804 cflags = m->m_pkthdr.csum_flags & active;
1805
1806 if (pflag != 0) {
1807 if (cflags == (pflag | M_CSUM_TCP_UDP_BAD)) {
1808 fin->fin_flx |= FI_BAD;
1809 } else if (cflags == (pflag | M_CSUM_DATA)) {
1810 if ((m->m_pkthdr.csum_data ^ 0xffff) != 0)
1811 fin->fin_flx |= FI_BAD;
1812 } else if (cflags == pflag) {
1813 ;
1814 } else {
1815 manual = 1;
1816 }
1817 }
1818 if (manual != 0) {
1819 if (ipf_checkl4sum(fin) == -1) {
1820 fin->fin_flx |= FI_BAD;
1821 return -1;
1822 }
1823 }
1824 # else
1825 if (ipf_checkl4sum(fin) == -1) {
1826 fin->fin_flx |= FI_BAD;
1827 return -1;
1828 }
1829 # endif
1830 return 0;
1831 }
1832 #endif /* USE_INET6 */
1833
1834
1835 size_t
1836 mbufchainlen(struct mbuf *m0)
1837 {
1838 size_t len;
1839
1840 if ((m0->m_flags & M_PKTHDR) != 0) {
1841 len = m0->m_pkthdr.len;
1842 } else {
1843 struct mbuf *m;
1844
1845 for (m = m0, len = 0; m != NULL; m = m->m_next)
1846 len += m->m_len;
1847 }
1848 return len;
1849 }
1850
1851
1852 /* ------------------------------------------------------------------------ */
1853 /* Function: ipf_pullup */
1854 /* Returns: NULL == pullup failed, else pointer to protocol header */
1855 /* Parameters: xmin(I)- pointer to buffer where data packet starts */
1856 /* fin(I) - pointer to packet information */
1857 /* len(I) - number of bytes to pullup */
1858 /* */
1859 /* Attempt to move at least len bytes (from the start of the buffer) into a */
1860 /* single buffer for ease of access. Operating system native functions are */
1861 /* used to manage buffers - if necessary. If the entire packet ends up in */
1862 /* a single buffer, set the FI_COALESCE flag even though ipf_coalesce() has */
1863 /* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */
1864 /* and ONLY if the pullup succeeds. */
1865 /* */
1866 /* We assume that 'xmin' is a pointer to a buffer that is part of the chain */
1867 /* of buffers that starts at *fin->fin_mp. */
1868 /* ------------------------------------------------------------------------ */
1869 void *
1870 ipf_pullup(mb_t *xmin, fr_info_t *fin, int len)
1871 {
1872 int dpoff, ipoff;
1873 mb_t *m = xmin;
1874 char *ip;
1875
1876 if (m == NULL)
1877 return NULL;
1878
1879 ip = (char *)fin->fin_ip;
1880 if ((fin->fin_flx & FI_COALESCE) != 0)
1881 return ip;
1882
1883 ipoff = fin->fin_ipoff;
1884 if (fin->fin_dp != NULL)
1885 dpoff = (char *)fin->fin_dp - (char *)ip;
1886 else
1887 dpoff = 0;
1888
1889 if (M_LEN(m) < len) {
1890 mb_t *n = *fin->fin_mp;
1891 /*
1892 * Assume that M_PKTHDR is set and just work with what is left
1893 * rather than check..
1894 * Should not make any real difference, anyway.
1895 */
1896 if (m != n) {
1897 /*
1898 * Record the mbuf that points to the mbuf that we're
1899 * about to go to work on so that we can update the
1900 * m_next appropriately later.
1901 */
1902 for (; n->m_next != m; n = n->m_next)
1903 ;
1904 } else {
1905 n = NULL;
1906 }
1907
1908 #ifdef MHLEN
1909 if (len > MHLEN)
1910 #else
1911 if (len > MLEN)
1912 #endif
1913 {
1914 #ifdef HAVE_M_PULLDOWN
1915 if (m_pulldown(m, 0, len, NULL) == NULL)
1916 m = NULL;
1917 #else
1918 FREE_MB_T(*fin->fin_mp);
1919 m = NULL;
1920 n = NULL;
1921 #endif
1922 } else
1923 {
1924 m = m_pullup(m, len);
1925 }
1926 if (n != NULL)
1927 n->m_next = m;
1928 if (m == NULL) {
1929 /*
1930 * When n is non-NULL, it indicates that m pointed to
1931 * a sub-chain (tail) of the mbuf and that the head
1932 * of this chain has not yet been free'd.
1933 */
1934 if (n != NULL) {
1935 FREE_MB_T(*fin->fin_mp);
1936 }
1937
1938 *fin->fin_mp = NULL;
1939 fin->fin_m = NULL;
1940 return NULL;
1941 }
1942
1943 if (n == NULL)
1944 *fin->fin_mp = m;
1945
1946 while (M_LEN(m) == 0) {
1947 m = m->m_next;
1948 }
1949 fin->fin_m = m;
1950 ip = MTOD(m, char *) + ipoff;
1951
1952 fin->fin_ip = (ip_t *)ip;
1953 if (fin->fin_dp != NULL)
1954 fin->fin_dp = (char *)fin->fin_ip + dpoff;
1955 if (fin->fin_fraghdr != NULL)
1956 fin->fin_fraghdr = (char *)ip +
1957 ((char *)fin->fin_fraghdr -
1958 (char *)fin->fin_ip);
1959 }
1960
1961 if (len == fin->fin_plen)
1962 fin->fin_flx |= FI_COALESCE;
1963 return ip;
1964 }
1965
1966
1967 int
1968 ipf_inject(fr_info_t *fin, mb_t *m)
1969 {
1970 int error;
1971
1972 if (fin->fin_out == 0) {
1973 if (__predict_false(!pktq_enqueue(ip_pktq, m, 0))) {
1974 FREE_MB_T(m);
1975 error = ENOBUFS;
1976 } else {
1977 error = 0;
1978 }
1979 } else {
1980 error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL);
1981 }
1982 return error;
1983 }
1984
1985
1986 u_32_t
1987 ipf_random(void)
1988 {
1989 int number;
1990
1991 #ifdef _CPRNG_H
1992 number = cprng_fast32();
1993 #else
1994 number = arc4random();
1995 #endif
1996 return number;
1997 }
1998
1999
2000 /*
2001 * routines below for saving IP headers to buffer
2002 */
2003 static int ipfopen(dev_t dev, int flags
2004 #if (NetBSD >= 199511)
2005 , int devtype, PROC_T *p
2006 #endif
2007 )
2008 {
2009 u_int unit = GET_MINOR(dev);
2010 int error;
2011
2012 if (IPL_LOGMAX < unit) {
2013 error = ENXIO;
2014 } else {
2015 switch (unit)
2016 {
2017 case IPL_LOGIPF :
2018 case IPL_LOGNAT :
2019 case IPL_LOGSTATE :
2020 case IPL_LOGAUTH :
2021 case IPL_LOGLOOKUP :
2022 case IPL_LOGSYNC :
2023 #ifdef IPFILTER_SCAN
2024 case IPL_LOGSCAN :
2025 #endif
2026 error = 0;
2027 break;
2028 default :
2029 error = ENXIO;
2030 break;
2031 }
2032 }
2033 #if (__NetBSD_Version__ >= 799003000)
2034 if (error == 0) {
2035 mutex_enter(&ipf_ref_mutex);
2036 ipf_active = 1;
2037 mutex_exit(&ipf_ref_mutex);
2038 }
2039 #endif
2040 return error;
2041 }
2042
2043
2044 static int ipfclose(dev_t dev, int flags
2045 #if (NetBSD >= 199511)
2046 , int devtype, PROC_T *p
2047 #endif
2048 )
2049 {
2050 u_int unit = GET_MINOR(dev);
2051
2052 if (IPL_LOGMAX < unit)
2053 return ENXIO;
2054 else {
2055 #if (__NetBSD_Version__ >= 799003000)
2056 mutex_enter(&ipf_ref_mutex);
2057 ipf_active = 0;
2058 mutex_exit(&ipf_ref_mutex);
2059 #endif
2060 return 0;
2061 }
2062 }
2063
2064 /*
2065 * ipfread/ipflog
2066 * both of these must operate with at least splnet() lest they be
2067 * called during packet processing and cause an inconsistancy to appear in
2068 * the filter lists.
2069 */
2070 static int ipfread(dev_t dev, struct uio *uio, int ioflag)
2071 {
2072
2073 if (ipfmain.ipf_running < 1) {
2074 ipfmain.ipf_interror = 130006;
2075 return EIO;
2076 }
2077
2078 if (GET_MINOR(dev) == IPL_LOGSYNC)
2079 return ipf_sync_read(&ipfmain, uio);
2080
2081 #ifdef IPFILTER_LOG
2082 return ipf_log_read(&ipfmain, GET_MINOR(dev), uio);
2083 #else
2084 ipfmain.ipf_interror = 130007;
2085 return ENXIO;
2086 #endif
2087 }
2088
2089
2090 /*
2091 * ipfwrite
2092 * both of these must operate with at least splnet() lest they be
2093 * called during packet processing and cause an inconsistancy to appear in
2094 * the filter lists.
2095 */
2096 static int ipfwrite(dev_t dev, struct uio *uio, int ioflag)
2097 {
2098
2099 if (ipfmain.ipf_running < 1) {
2100 ipfmain.ipf_interror = 130008;
2101 return EIO;
2102 }
2103
2104 if (GET_MINOR(dev) == IPL_LOGSYNC)
2105 return ipf_sync_write(&ipfmain, uio);
2106 ipfmain.ipf_interror = 130009;
2107 return ENXIO;
2108 }
2109
2110
2111 static int ipfpoll(dev_t dev, int events, PROC_T *p)
2112 {
2113 u_int unit = GET_MINOR(dev);
2114 int revents = 0;
2115
2116 if (IPL_LOGMAX < unit) {
2117 ipfmain.ipf_interror = 130010;
2118 return ENXIO;
2119 }
2120
2121 switch (unit)
2122 {
2123 case IPL_LOGIPF :
2124 case IPL_LOGNAT :
2125 case IPL_LOGSTATE :
2126 #ifdef IPFILTER_LOG
2127 if ((events & (POLLIN | POLLRDNORM)) &&
2128 ipf_log_canread(&ipfmain, unit))
2129 revents |= events & (POLLIN | POLLRDNORM);
2130 #endif
2131 break;
2132 case IPL_LOGAUTH :
2133 if ((events & (POLLIN | POLLRDNORM)) &&
2134 ipf_auth_waiting(&ipfmain))
2135 revents |= events & (POLLIN | POLLRDNORM);
2136 break;
2137 case IPL_LOGSYNC :
2138 if ((events & (POLLIN | POLLRDNORM)) &&
2139 ipf_sync_canread(&ipfmain))
2140 revents |= events & (POLLIN | POLLRDNORM);
2141 if ((events & (POLLOUT | POLLWRNORM)) &&
2142 ipf_sync_canwrite(&ipfmain))
2143 revents |= events & (POLLOUT | POLLWRNORM);
2144 break;
2145 case IPL_LOGSCAN :
2146 case IPL_LOGLOOKUP :
2147 default :
2148 break;
2149 }
2150
2151 if ((revents == 0) && (((events & (POLLIN|POLLRDNORM)) != 0)))
2152 selrecord(p, &ipfmain.ipf_selwait[unit]);
2153 return revents;
2154 }
2155
2156 u_int
2157 ipf_pcksum(fr_info_t *fin, int hlen, u_int sum)
2158 {
2159 struct mbuf *m;
2160 u_int sum2;
2161 int off;
2162
2163 m = fin->fin_m;
2164 off = (char *)fin->fin_dp - (char *)fin->fin_ip;
2165 m->m_data += hlen;
2166 m->m_len -= hlen;
2167 sum2 = in_cksum(fin->fin_m, fin->fin_plen - off);
2168 m->m_len += hlen;
2169 m->m_data -= hlen;
2170
2171 /*
2172 * Both sum and sum2 are partial sums, so combine them together.
2173 */
2174 sum += ~sum2 & 0xffff;
2175 while (sum > 0xffff)
2176 sum = (sum & 0xffff) + (sum >> 16);
2177 sum2 = ~sum & 0xffff;
2178 return sum2;
2179 }
2180
2181 #if (__NetBSD_Version__ >= 799003000)
2182
2183 /* NetBSD module interface */
2184
2185 MODULE(MODULE_CLASS_DRIVER, ipl, "bpf_filter");
2186
2187 static int ipl_init(void *);
2188 static int ipl_fini(void *);
2189 static int ipl_modcmd(modcmd_t, void *);
2190
2191 #ifdef _MODULE
2192 static devmajor_t ipl_cmaj = -1, ipl_bmaj = -1;
2193 #endif
2194
2195 static int
2196 ipl_modcmd(modcmd_t cmd, void *opaque)
2197 {
2198
2199 switch (cmd) {
2200 case MODULE_CMD_INIT:
2201 return ipl_init(opaque);
2202 case MODULE_CMD_FINI:
2203 return ipl_fini(opaque);
2204 default:
2205 return ENOTTY;
2206 }
2207 }
2208
2209 static int
2210 ipl_init(void *opaque)
2211 {
2212 int error;
2213
2214 ipf_listener = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
2215 ipf_listener_cb, NULL);
2216
2217 if ((error = ipf_load_all()) != 0)
2218 return error;
2219
2220 if (ipf_create_all(&ipfmain) == NULL) {
2221 ipf_unload_all();
2222 return ENODEV;
2223 }
2224
2225 /* Initialize our mutex and reference count */
2226 mutex_init(&ipf_ref_mutex, MUTEX_DEFAULT, IPL_NONE);
2227 ipf_active = 0;
2228
2229 #ifdef _MODULE
2230 /*
2231 * Insert ourself into the cdevsw list.
2232 */
2233 error = devsw_attach("ipl", NULL, &ipl_bmaj, &ipl_cdevsw, &ipl_cmaj);
2234 if (error)
2235 ipl_fini(opaque);
2236 #endif
2237
2238 return error;
2239 }
2240
2241 static int
2242 ipl_fini(void *opaque)
2243 {
2244
2245 #ifdef _MODULE
2246 (void)devsw_detach(NULL, &ipl_cdevsw);
2247 #endif
2248
2249 /*
2250 * Grab the mutex, verify that there are no references
2251 * and that there are no running filters. If either
2252 * of these exists, reinsert our cdevsw entry and return
2253 * an error.
2254 */
2255 mutex_enter(&ipf_ref_mutex);
2256 if (ipf_active != 0 || ipfmain.ipf_running > 0) {
2257 #ifdef _MODULE
2258 (void)devsw_attach("ipl", NULL, &ipl_bmaj,
2259 &ipl_cdevsw, &ipl_cmaj);
2260 #endif
2261 mutex_exit(&ipf_ref_mutex);
2262 return EBUSY;
2263 }
2264
2265 /* Clean up the rest of our state before being unloaded */
2266
2267 mutex_exit(&ipf_ref_mutex);
2268 mutex_destroy(&ipf_ref_mutex);
2269 ipf_destroy_all(&ipfmain);
2270 ipf_unload_all();
2271 kauth_unlisten_scope(ipf_listener);
2272
2273 return 0;
2274 }
2275 #endif /* (__NetBSD_Version__ >= 799003000) */
2276