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