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