1 /* $NetBSD: ip_fil_netbsd.c,v 1.52 2009/10/03 00:37:02 elad Exp $ */
4 * Copyright (C) 1993-2003 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
9 #if defined(__NetBSD__)
10 #include <sys/cdefs.h>
11 __KERNEL_RCSID(0, "$NetBSD: ip_fil_netbsd.c,v 1.52 2009/10/03 00:37:02 elad Exp $");
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 2.55.2.66 2009/05/17 17:45:26 darrenr Exp";
18 #if defined(KERNEL) || defined(_KERNEL)
24 #include <sys/param.h>
25 #if (NetBSD >= 199905) && !defined(IPFILTER_LKM) && defined(_KERNEL)
26 # if (__NetBSD_Version__ < 399001400)
27 # include "opt_ipfilter_log.h"
29 # include "opt_ipfilter.h"
31 # include "opt_pfil_hooks.h"
32 # include "opt_ipsec.h"
34 #include <sys/errno.h>
35 #include <sys/types.h>
37 #include <sys/ioctl.h>
39 #include <sys/systm.h>
41 # include <sys/dirent.h>
46 #include <sys/protosw.h>
47 #include <sys/socket.h>
49 #if (__NetBSD_Version__ >= 399002000)
50 # include <sys/kauth.h>
54 #include <net/route.h>
55 #include <netinet/in.h>
56 #include <netinet/in_var.h>
57 #include <netinet/in_systm.h>
58 #include <netinet/ip.h>
59 #include <netinet/ip_var.h>
60 #include <netinet/tcp.h>
61 #if __NetBSD_Version__ >= 105190000 /* 1.5T */
62 # include <netinet/tcp_timer.h>
63 # include <netinet/tcp_var.h>
65 #include <netinet/udp.h>
66 #include <netinet/tcpip.h>
67 #include <netinet/ip_icmp.h>
68 #include "netinet/ip_compat.h"
70 # include <netinet/icmp6.h>
71 # if (__NetBSD_Version__ >= 106000000)
72 # include <netinet6/nd6.h>
75 #include "netinet/ip_fil.h"
76 #include "netinet/ip_nat.h"
77 #include "netinet/ip_frag.h"
78 #include "netinet/ip_state.h"
79 #include "netinet/ip_proxy.h"
80 #include "netinet/ip_auth.h"
82 #include "netinet/ip_sync.h"
85 #include "netinet/ip_scan.h"
87 #include "netinet/ip_pool.h"
89 #include <sys/kernel.h>
91 extern int ip_optcopy
__P((struct ip
*, struct ip
*));
95 ipfmutex_t ipl_mutex
, ipf_authmx
, ipf_rw
;
96 ipfmutex_t ipf_timeoutlock
, ipf_stinsert
, ipf_natio
, ipf_nat_new
;
97 ipfrwlock_t ipf_mutex
, ipf_global
, ipf_ipidfrag
;
98 ipfrwlock_t ipf_frag
, ipf_state
, ipf_nat
, ipf_natfrag
, ipf_auth
;
99 ipfrwlock_t ipf_frcache
, ipf_tokens
;
100 int ipf_locks_done
= 0;
103 #ifdef IPFILTER_M_IPFILTER
104 # ifdef MALLOC_DEFINE
105 MALLOC_DEFINE(M_IPFILTER
, "IP Filter", "IP Filter packet filter data structures");
107 MALLOC_DECLARE(M_IPFILTER
);
111 #if __NetBSD_Version__ >= 105009999
112 # define csuminfo csum_flags
115 #if __NetBSD_Version__ < 200000000
116 extern struct protosw inetsw
[];
119 #if (__NetBSD_Version__ >= 599002000)
120 static kauth_listener_t ipf_listener
;
123 #if (__NetBSD_Version__ < 399001400)
124 extern int ip6_getpmtu
__P((struct route_in6
*, struct route_in6
*,
125 struct ifnet
*, struct in6_addr
*, u_long
*,
129 static int (*fr_savep
) __P((ip_t
*, int, void *, int, struct mbuf
**));
130 static int fr_send_ip
__P((fr_info_t
*, mb_t
*, mb_t
**));
132 static int ipfr_fastroute6
__P((struct mbuf
*, struct mbuf
**,
133 fr_info_t
*, frdest_t
*));
136 #if (__NetBSD_Version__ >= 104040000)
137 # include <sys/callout.h>
138 struct callout fr_slowtimer_ch
;
141 #include <sys/conf.h>
142 #if defined(NETBSD_PF)
143 # include <net/pfil.h>
145 * We provide the fr_checkp name just to minimize changes later.
147 int (*fr_checkp
) __P((ip_t
*ip
, int hlen
, void *ifp
, int out
, mb_t
**mp
));
148 #endif /* NETBSD_PF */
150 #if (__NetBSD_Version__ >= 106080000) && defined(_KERNEL)
151 # include <sys/select.h>
153 # if (__NetBSD_Version__ >= 399001400)
154 int iplpoll
__P((dev_t dev
, int events
, struct lwp
*p
));
156 int iplpoll
__P((dev_t dev
, int events
, struct proc
*p
));
159 struct selinfo ipfselwait
[IPL_LOGSIZE
];
161 const struct cdevsw ipl_cdevsw
= {
162 iplopen
, iplclose
, iplread
, nowrite
, iplioctl
,
163 nostop
, notty
, iplpoll
, nommap
,
164 # if (__NetBSD_Version__ >= 200000000)
174 #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000)
175 # include <net/pfil.h>
177 static int fr_check_wrapper(void *, struct mbuf
**, struct ifnet
*, int );
180 fr_check_wrapper(void *arg
, struct mbuf
**mp
, struct ifnet
*ifp
,
186 #if __NetBSD_Version__ >= 200080000
188 * ensure that mbufs are writable beforehand
189 * as it's assumed by ipf code.
192 int error
= m_makewritable(mp
, 0, M_COPYALL
, M_DONTWAIT
);
200 ip
= mtod(*mp
, struct ip
*);
201 hlen
= ip
->ip_hl
<< 2;
204 #if defined(M_CSUM_TCPv4)
206 * If the packet is out-bound, we can't delay checksums
207 * here. For in-bound, the checksum has already been
210 if (dir
== PFIL_OUT
) {
211 if ((*mp
)->m_pkthdr
.csum_flags
& (M_CSUM_TCPv4
|M_CSUM_UDPv4
)) {
212 in_delayed_cksum(*mp
);
213 (*mp
)->m_pkthdr
.csum_flags
&=
214 ~(M_CSUM_TCPv4
|M_CSUM_UDPv4
);
217 #endif /* M_CSUM_TCPv4 */
221 * We get the packet with all fields in network byte
222 * order. We expect ip_len and ip_off to be in host
223 * order. We frob them, call the filter, then frob
226 * Note, we don't need to update the checksum, because
227 * it has already been verified.
232 rv
= fr_check(ip
, hlen
, ifp
, (dir
== PFIL_OUT
), mp
);
234 if (rv
== 0 && *mp
!= NULL
) {
235 ip
= mtod(*mp
, struct ip
*);
244 # include <netinet/ip6.h>
246 static int fr_check_wrapper6(void *, struct mbuf
**, struct ifnet
*, int );
249 fr_check_wrapper6(void *arg
, struct mbuf
**mp
, struct ifnet
*ifp
,
253 # if defined(M_CSUM_TCPv6) && (__NetBSD_Version__ > 200000000)
255 * If the packet is out-bound, we can't delay checksums
256 * here. For in-bound, the checksum has already been
259 if (dir
== PFIL_OUT
) {
260 if ((*mp
)->m_pkthdr
.csum_flags
& (M_CSUM_TCPv6
|M_CSUM_UDPv6
)) {
261 # if (__NetBSD_Version__ > 399000600)
262 in6_delayed_cksum(*mp
);
264 (*mp
)->m_pkthdr
.csum_flags
&= ~(M_CSUM_TCPv6
|
271 return (fr_check(mtod(*mp
, struct ip
*), sizeof(struct ip6_hdr
),
272 ifp
, (dir
== PFIL_OUT
), mp
));
277 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
278 static int ipf_pfilsync(void *, struct mbuf
**, struct ifnet
*, int);
280 static int ipf_pfilsync(void *hdr
, struct mbuf
**mp
,
281 struct ifnet
*ifp
, int dir
)
284 * The interface pointer is useless for create (we have nothing to
285 * compare it to) and at detach, the interface name is still in the
286 * list of active NICs (albeit, down, but that's not any real
287 * indicator) and doing ifunit() on the name will still return the
288 * pointer, so it's not much use then, either.
295 #endif /* __NetBSD_Version__ >= 105110000 */
298 #if defined(IPFILTER_LKM)
302 if (strcmp(s
, "ipl") == 0)
306 #endif /* IPFILTER_LKM */
308 #if (__NetBSD_Version__ >= 599002000)
310 ipf_listener_cb(kauth_cred_t cred
, kauth_action_t action
, void *cookie
,
311 void *arg0
, void *arg1
, void *arg2
, void *arg3
)
314 enum kauth_network_req req
;
316 result
= KAUTH_RESULT_DEFER
;
317 req
= (enum kauth_network_req
)arg0
;
319 if (action
!= KAUTH_NETWORK_FIREWALL
)
322 /* These must have came from device context. */
323 if ((req
== KAUTH_REQ_NETWORK_FIREWALL_FW
) ||
324 (req
== KAUTH_REQ_NETWORK_FIREWALL_NAT
))
325 result
= KAUTH_RESULT_ALLOW
;
332 * Try to detect the case when compiling for NetBSD with pseudo-device
334 #if defined(PFIL_HOOKS)
336 ipfilterattach(int count
)
339 RWLOCK_INIT(&ipf_global
, "ipf filter load/unload mutex");
340 RWLOCK_INIT(&ipf_mutex
, "ipf filter rwlock");
341 RWLOCK_INIT(&ipf_frcache
, "ipf cache rwlock");
344 #if (__NetBSD_Version__ >= 599002000)
345 ipf_listener
= kauth_listen_scope(KAUTH_SCOPE_NETWORK
,
346 ipf_listener_cb
, NULL
);
356 #if (__NetBSD_Version__ >= 499005500)
359 #if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000)
361 # if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000)
362 struct pfil_head
*ph_inet
;
364 struct pfil_head
*ph_inet6
;
366 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
367 struct pfil_head
*ph_ifsync
;
373 if ((fr_running
> 0) || (fr_checkp
== fr_check
)) {
374 printf("IP Filter: already initialized\n");
380 MUTEX_INIT(&ipf_rw
, "ipf rw mutex");
381 MUTEX_INIT(&ipf_timeoutlock
, "ipf timeout queue mutex");
382 RWLOCK_INIT(&ipf_ipidfrag
, "ipf IP NAT-Frag rwlock");
383 RWLOCK_INIT(&ipf_tokens
, "ipf token rwlock");
387 if (fr_initialise() < 0) {
393 # if (__NetBSD_Version__ >= 104200000)
394 # if __NetBSD_Version__ >= 105110000
395 ph_inet
= pfil_head_get(PFIL_TYPE_AF
, AF_INET
);
397 ph_inet6
= pfil_head_get(PFIL_TYPE_AF
, AF_INET6
);
399 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
400 ph_ifsync
= pfil_head_get(PFIL_TYPE_IFNET
, 0);
407 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
412 printf("pfil_head_get failed\n");
417 error
= pfil_add_hook((void *)fr_check_wrapper
, NULL
,
418 PFIL_IN
|PFIL_OUT
, ph_inet
);
422 error
= pfil_add_hook((void *)fr_check
, PFIL_IN
|PFIL_OUT
,
423 &inetsw
[ip_protox
[IPPROTO_IP
]].pr_pfh
);
428 pfil_add_hook((void *)fr_check
, PFIL_IN
|PFIL_OUT
);
432 # if __NetBSD_Version__ >= 105110000
433 if (ph_inet6
!= NULL
)
434 error
= pfil_add_hook((void *)fr_check_wrapper6
, NULL
,
435 PFIL_IN
|PFIL_OUT
, ph_inet6
);
439 pfil_remove_hook((void *)fr_check_wrapper6
, NULL
,
440 PFIL_IN
|PFIL_OUT
, ph_inet6
);
444 error
= pfil_add_hook((void *)fr_check
, PFIL_IN
|PFIL_OUT
,
445 &inetsw
[ip_protox
[IPPROTO_IPV6
]].pr_pfh
);
447 pfil_remove_hook((void *)fr_check
, PFIL_IN
|PFIL_OUT
,
448 &inetsw
[ip_protox
[IPPROTO_IP
]].pr_pfh
);
454 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
455 if (ph_ifsync
!= NULL
)
456 (void) pfil_add_hook((void *)ipf_pfilsync
, NULL
,
457 PFIL_IFNET
, ph_ifsync
);
461 #if (__NetBSD_Version__ >= 499005500)
462 for (i
= 0; i
< IPL_LOGSIZE
; i
++)
463 selinit(&ipfselwait
[i
]);
465 bzero((char *)ipfselwait
, sizeof(ipfselwait
));
467 bzero((char *)frcache
, sizeof(frcache
));
468 fr_savep
= fr_checkp
;
469 fr_checkp
= fr_check
;
472 if (fr_control_forwarding
& 1)
478 #if (__NetBSD_Version__ >= 104010000)
479 # if (__NetBSD_Version__ >= 499002000)
480 callout_init(&fr_slowtimer_ch
, 0);
482 callout_init(&fr_slowtimer_ch
);
484 callout_reset(&fr_slowtimer_ch
, (hz
/ IPF_HZ_DIVIDE
) * IPF_HZ_MULT
,
487 timeout(fr_slowtimer
, NULL
, (hz
/ IPF_HZ_DIVIDE
) * IPF_HZ_MULT
);
492 #if __NetBSD_Version__ >= 105110000
502 * Disable the filter by removing the hooks from the IP input/output
508 #if (__NetBSD_Version__ >= 499005500)
511 #if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000)
513 # if __NetBSD_Version__ >= 105150000
514 struct pfil_head
*ph_inet
= pfil_head_get(PFIL_TYPE_AF
, AF_INET
);
516 struct pfil_head
*ph_inet6
= pfil_head_get(PFIL_TYPE_AF
, AF_INET6
);
518 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
519 struct pfil_head
*ph_ifsync
= pfil_head_get(PFIL_TYPE_IFNET
, 0);
526 #if (__NetBSD_Version__ >= 104010000)
528 callout_stop(&fr_slowtimer_ch
);
530 untimeout(fr_slowtimer
, NULL
);
533 fr_checkp
= fr_savep
;
534 (void) frflush(IPL_LOGIPF
, 0, FR_INQUE
|FR_OUTQUE
|FR_INACTIVE
);
535 (void) frflush(IPL_LOGIPF
, 0, FR_INQUE
|FR_OUTQUE
);
538 if (fr_control_forwarding
& 2)
543 # if (__NetBSD_Version__ >= 104200000)
544 # if __NetBSD_Version__ >= 105110000
545 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
546 (void) pfil_remove_hook((void *)ipf_pfilsync
, NULL
,
547 PFIL_IFNET
, ph_ifsync
);
551 error
= pfil_remove_hook((void *)fr_check_wrapper
, NULL
,
552 PFIL_IN
|PFIL_OUT
, ph_inet
);
556 error
= pfil_remove_hook((void *)fr_check
, PFIL_IN
|PFIL_OUT
,
557 &inetsw
[ip_protox
[IPPROTO_IP
]].pr_pfh
);
564 pfil_remove_hook((void *)fr_check
, PFIL_IN
|PFIL_OUT
);
567 # if __NetBSD_Version__ >= 105110000
568 if (ph_inet6
!= NULL
)
569 error
= pfil_remove_hook((void *)fr_check_wrapper6
, NULL
,
570 PFIL_IN
|PFIL_OUT
, ph_inet6
);
574 error
= pfil_remove_hook((void *)fr_check
, PFIL_IN
|PFIL_OUT
,
575 &inetsw
[ip_protox
[IPPROTO_IPV6
]].pr_pfh
);
587 #if (__NetBSD_Version__ >= 499005500)
588 for (i
= 0; i
< IPL_LOGSIZE
; i
++)
589 seldestroy(&ipfselwait
[i
]);
592 if (ipf_locks_done
== 1) {
593 MUTEX_DESTROY(&ipf_rw
);
594 MUTEX_DESTROY(&ipf_timeoutlock
);
595 RW_DESTROY(&ipf_ipidfrag
);
596 RW_DESTROY(&ipf_tokens
);
605 * Filter ioctl interface.
607 int iplioctl(dev
, cmd
, data
, mode
608 #if (NetBSD >= 199511)
610 # if (__NetBSD_Version__ >= 399001400)
612 # if (__NetBSD_Version__ >= 399002000)
613 # define UID(l) kauth_cred_getuid((l)->l_cred)
615 # define UID(l) ((l)->l_proc->p_cred->p_ruid)
619 # define UID(p) ((p)->p_cred->p_ruid)
626 #if (__NetBSD_Version__ >= 499001000)
633 int error
= 0, unit
= 0;
636 #if (__NetBSD_Version__ >= 399002000)
637 if ((mode
& FWRITE
) &&
638 kauth_authorize_network(p
->l_cred
, KAUTH_NETWORK_FIREWALL
,
639 KAUTH_REQ_NETWORK_FIREWALL_FW
, NULL
,
644 if ((securelevel
>= 2) && (mode
& FWRITE
)) {
649 unit
= GET_MINOR(dev
);
650 if ((IPL_LOGMAX
< unit
) || (unit
< 0))
653 if (fr_running
<= 0) {
654 if (unit
!= IPL_LOGIPF
)
656 if (cmd
!= SIOCIPFGETNEXT
&& cmd
!= SIOCIPFGET
&&
657 cmd
!= SIOCIPFSET
&& cmd
!= SIOCFRENB
&&
658 cmd
!= SIOCGETFS
&& cmd
!= SIOCGETFF
)
664 error
= fr_ioctlswitch(unit
, data
, cmd
, mode
, UID(p
), p
);
672 void fr_forgetifp(ifp
)
675 register frentry_t
*f
;
677 WRITE_ENTER(&ipf_mutex
);
678 for (f
= ipacct
[0][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
679 if (f
->fr_ifa
== ifp
)
680 f
->fr_ifa
= (void *)-1;
681 for (f
= ipacct
[1][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
682 if (f
->fr_ifa
== ifp
)
683 f
->fr_ifa
= (void *)-1;
684 for (f
= ipfilter
[0][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
685 if (f
->fr_ifa
== ifp
)
686 f
->fr_ifa
= (void *)-1;
687 for (f
= ipfilter
[1][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
688 if (f
->fr_ifa
== ifp
)
689 f
->fr_ifa
= (void *)-1;
691 for (f
= ipacct6
[0][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
692 if (f
->fr_ifa
== ifp
)
693 f
->fr_ifa
= (void *)-1;
694 for (f
= ipacct6
[1][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
695 if (f
->fr_ifa
== ifp
)
696 f
->fr_ifa
= (void *)-1;
697 for (f
= ipfilter6
[0][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
698 if (f
->fr_ifa
== ifp
)
699 f
->fr_ifa
= (void *)-1;
700 for (f
= ipfilter6
[1][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
701 if (f
->fr_ifa
== ifp
)
702 f
->fr_ifa
= (void *)-1;
704 RWLOCK_EXIT(&ipf_mutex
);
711 * routines below for saving IP headers to buffer
716 #if (NetBSD >= 199511)
719 # if (__NetBSD_Version__ >= 399001400)
726 u_int unit
= GET_MINOR(dev
);
729 if (IPL_LOGMAX
< unit
)
738 #ifdef IPFILTER_LOOKUP
761 #if (NetBSD >= 199511)
764 # if (__NetBSD_Version__ >= 399001400)
771 u_int unit
= GET_MINOR(dev
);
773 if (IPL_LOGMAX
< unit
)
782 * both of these must operate with at least splnet() lest they be
783 * called during packet processing and cause an inconsistancy to appear in
798 # ifdef IPFILTER_SYNC
799 if (GET_MINOR(dev
) == IPL_LOGSYNC
)
800 return ipfsync_read(uio
);
804 return ipflog_read(GET_MINOR(dev
), uio
);
813 * both of these must operate with at least splnet() lest they be
814 * called during packet processing and cause an inconsistancy to appear in
830 if (GET_MINOR(dev
) == IPL_LOGSYNC
)
831 return ipfsync_write(uio
);
838 * fr_send_reset - this could conceivably be a call to tcp_respond(), but that
839 * requires a large amount of setting up and isn't any more efficient.
841 int fr_send_reset(fin
)
844 struct tcphdr
*tcp
, *tcp2
;
853 if (tcp
->th_flags
& TH_RST
)
854 return -1; /* feedback loop */
856 if (fr_checkl4sum(fin
) == -1)
859 tlen
= fin
->fin_dlen
- (TCP_OFF(tcp
) << 2) +
860 ((tcp
->th_flags
& TH_SYN
) ? 1 : 0) +
861 ((tcp
->th_flags
& TH_FIN
) ? 1 : 0);
864 hlen
= (fin
->fin_v
== 6) ? sizeof(ip6_t
) : sizeof(ip_t
);
869 MGETHDR(m
, M_DONTWAIT
, MT_HEADER
);
871 MGET(m
, M_DONTWAIT
, MT_HEADER
);
875 if (sizeof(*tcp2
) + hlen
> MHLEN
) {
876 MCLGET(m
, M_DONTWAIT
);
879 if ((m
->m_flags
& M_EXT
) == 0) {
885 m
->m_len
= sizeof(*tcp2
) + hlen
;
886 m
->m_data
+= max_linkhdr
;
887 m
->m_pkthdr
.len
= m
->m_len
;
888 m
->m_pkthdr
.rcvif
= (struct ifnet
*)0;
889 ip
= mtod(m
, struct ip
*);
890 bzero((char *)ip
, hlen
);
894 bzero((char *)ip
, sizeof(*tcp2
) + hlen
);
895 tcp2
= (struct tcphdr
*)((char *)ip
+ hlen
);
896 tcp2
->th_sport
= tcp
->th_dport
;
897 tcp2
->th_dport
= tcp
->th_sport
;
899 if (tcp
->th_flags
& TH_ACK
) {
900 tcp2
->th_seq
= tcp
->th_ack
;
901 tcp2
->th_flags
= TH_RST
;
905 tcp2
->th_ack
= ntohl(tcp
->th_seq
);
906 tcp2
->th_ack
+= tlen
;
907 tcp2
->th_ack
= htonl(tcp2
->th_ack
);
908 tcp2
->th_flags
= TH_RST
|TH_ACK
;
911 TCP_OFF_A(tcp2
, sizeof(*tcp2
) >> 2);
912 tcp2
->th_win
= tcp
->th_win
;
917 if (fin
->fin_v
== 6) {
918 ip6
->ip6_flow
= ((ip6_t
*)fin
->fin_ip
)->ip6_flow
;
919 ip6
->ip6_plen
= htons(sizeof(struct tcphdr
));
920 ip6
->ip6_nxt
= IPPROTO_TCP
;
922 ip6
->ip6_src
= fin
->fin_dst6
;
923 ip6
->ip6_dst
= fin
->fin_src6
;
924 tcp2
->th_sum
= in6_cksum(m
, IPPROTO_TCP
,
925 sizeof(*ip6
), sizeof(*tcp2
));
926 return fr_send_ip(fin
, m
, &m
);
930 ip
->ip_p
= IPPROTO_TCP
;
931 ip
->ip_len
= htons(sizeof(struct tcphdr
));
932 ip
->ip_src
.s_addr
= fin
->fin_daddr
;
933 ip
->ip_dst
.s_addr
= fin
->fin_saddr
;
934 tcp2
->th_sum
= in_cksum(m
, hlen
+ sizeof(*tcp2
));
935 ip
->ip_len
= hlen
+ sizeof(*tcp2
);
936 return fr_send_ip(fin
, m
, &m
);
943 static int fr_send_ip(fin
, m
, mpp
)
954 ip
= mtod(m
, ip_t
*);
955 bzero((char *)&fnew
, sizeof(fnew
));
957 IP_V_A(ip
, fin
->fin_v
);
964 IP_HL_A(ip
, sizeof(*oip
) >> 2);
965 ip
->ip_tos
= oip
->ip_tos
;
966 ip
->ip_id
= fr_nextipid(fin
);
967 ip
->ip_off
= ip_mtudisc
? IP_DF
: 0;
968 ip
->ip_ttl
= ip_defttl
;
976 ip6_t
*ip6
= (ip6_t
*)ip
;
979 ip6
->ip6_hlim
= IPDEFTTL
;
990 m
->m_pkthdr
.rcvif
= NULL
;
993 fnew
.fin_ifp
= fin
->fin_ifp
;
994 fnew
.fin_flx
= FI_NOCKSUM
;
998 fnew
.fin_hlen
= hlen
;
999 fnew
.fin_dp
= (char *)ip
+ hlen
;
1000 (void) fr_makefrip(hlen
, ip
, &fnew
);
1002 return fr_fastroute(m
, mpp
, &fnew
, NULL
);
1006 int fr_send_icmp_err(type
, fin
, dst
)
1011 int err
, hlen
, xtra
, iclen
, ohlen
, avail
, code
;
1012 struct in_addr dst4
;
1018 struct in6_addr dst6
;
1022 if ((type
< 0) || (type
> ICMP_MAXTYPE
))
1025 code
= fin
->fin_icode
;
1027 if ((code
< 0) || (code
> sizeof(icmptoicmp6unreach
)/sizeof(int)))
1031 if (fr_checkl4sum(fin
) == -1)
1034 MGETHDR(m
, M_DONTWAIT
, MT_HEADER
);
1036 MGET(m
, M_DONTWAIT
, MT_HEADER
);
1046 if (fin
->fin_v
== 4) {
1047 if ((fin
->fin_p
== IPPROTO_ICMP
) && !(fin
->fin_flx
& FI_SHORT
))
1048 switch (ntohs(fin
->fin_data
[0]) >> 8)
1061 if (fr_ifpaddr(4, FRI_NORMAL
, ifp
,
1062 &dst4
, NULL
) == -1) {
1067 dst4
.s_addr
= fin
->fin_daddr
;
1069 hlen
= sizeof(ip_t
);
1070 ohlen
= fin
->fin_hlen
;
1071 if (fin
->fin_hlen
< fin
->fin_plen
)
1072 xtra
= MIN(fin
->fin_dlen
, 8);
1078 else if (fin
->fin_v
== 6) {
1079 hlen
= sizeof(ip6_t
);
1080 ohlen
= sizeof(ip6_t
);
1081 type
= icmptoicmp6types
[type
];
1082 if (type
== ICMP6_DST_UNREACH
)
1083 code
= icmptoicmp6unreach
[code
];
1085 if (hlen
+ sizeof(*icmp
) + max_linkhdr
+
1086 fin
->fin_plen
> avail
) {
1087 MCLGET(m
, M_DONTWAIT
);
1090 if ((m
->m_flags
& M_EXT
) == 0) {
1096 xtra
= MIN(fin
->fin_plen
,
1097 avail
- hlen
- sizeof(*icmp
) - max_linkhdr
);
1099 if (fr_ifpaddr(6, FRI_NORMAL
, ifp
,
1100 (struct in_addr
*)&dst6
, NULL
) == -1) {
1105 dst6
= fin
->fin_dst6
;
1113 iclen
= hlen
+ sizeof(*icmp
);
1114 avail
-= (max_linkhdr
+ iclen
);
1122 m
->m_data
+= max_linkhdr
;
1123 m
->m_pkthdr
.rcvif
= (struct ifnet
*)0;
1124 m
->m_pkthdr
.len
= iclen
;
1126 ip
= mtod(m
, ip_t
*);
1127 icmp
= (struct icmp
*)((char *)ip
+ hlen
);
1128 ip2
= (ip_t
*)&icmp
->icmp_ip
;
1130 icmp
->icmp_type
= type
;
1131 icmp
->icmp_code
= fin
->fin_icode
;
1132 icmp
->icmp_cksum
= 0;
1134 if (type
== ICMP_UNREACH
&&
1135 fin
->fin_icode
== ICMP_UNREACH_NEEDFRAG
&& ifp
)
1136 icmp
->icmp_nextmtu
= htons(((struct ifnet
*)ifp
)->if_mtu
);
1139 bcopy((char *)fin
->fin_ip
, (char *)ip2
, ohlen
);
1141 #if defined(M_CSUM_IPv4)
1143 * Clear any in-bound checksum flags for this packet.
1145 m
->m_pkthdr
.csuminfo
= 0;
1146 #endif /* __NetBSD__ && M_CSUM_IPv4 */
1150 if (fin
->fin_v
== 6) {
1151 ip6
->ip6_flow
= ((ip6_t
*)fin
->fin_ip
)->ip6_flow
;
1152 ip6
->ip6_plen
= htons(iclen
- hlen
);
1153 ip6
->ip6_nxt
= IPPROTO_ICMPV6
;
1155 ip6
->ip6_src
= dst6
;
1156 ip6
->ip6_dst
= fin
->fin_src6
;
1158 bcopy((char *)fin
->fin_ip
+ ohlen
,
1159 (char *)&icmp
->icmp_ip
+ ohlen
, xtra
);
1160 icmp
->icmp_cksum
= in6_cksum(m
, IPPROTO_ICMPV6
,
1161 sizeof(*ip6
), iclen
- hlen
);
1165 ip2
->ip_len
= htons(ip2
->ip_len
);
1166 ip2
->ip_off
= htons(ip2
->ip_off
);
1167 ip
->ip_p
= IPPROTO_ICMP
;
1168 ip
->ip_src
.s_addr
= dst4
.s_addr
;
1169 ip
->ip_dst
.s_addr
= fin
->fin_saddr
;
1172 bcopy((char *)fin
->fin_ip
+ ohlen
,
1173 (char *)&icmp
->icmp_ip
+ ohlen
, xtra
);
1174 icmp
->icmp_cksum
= ipf_cksum((u_short
*)icmp
,
1177 ip
->ip_p
= IPPROTO_ICMP
;
1179 err
= fr_send_ip(fin
, m
, &m
);
1185 * m0 - pointer to mbuf where the IP packet starts
1186 * mpp - pointer to the mbuf pointer that is the start of the mbuf chain
1188 int fr_fastroute(m0
, mpp
, fin
, fdp
)
1195 struct ip
*ip
, *mhip
;
1196 struct mbuf
*m
= m0
;
1198 int len
, off
, hlen
, code
;
1199 struct ifnet
*ifp
, *sifp
;
1200 # if __NetBSD_Version__ >= 499001100
1202 struct sockaddr dst
;
1203 struct sockaddr_in dst4
;
1206 struct sockaddr_in
*dst4
;
1208 struct sockaddr
*dst
;
1209 struct route iproute
;
1215 if (fin
->fin_v
== 6) {
1217 error
= ipfr_fastroute6(m0
, mpp
, fin
, fdp
);
1219 error
= EPROTONOSUPPORT
;
1221 if ((error
!= 0) && (*mpp
!= NULL
)) {
1228 return EPROTONOSUPPORT
;
1231 hlen
= fin
->fin_hlen
;
1232 ip
= mtod(m0
, struct ip
*);
1235 # if defined(M_CSUM_IPv4)
1237 * Clear any in-bound checksum flags for this packet.
1239 m0
->m_pkthdr
.csuminfo
= 0;
1240 # endif /* __NetBSD__ && M_CSUM_IPv4 */
1246 memset(ro
, 0, sizeof(*ro
));
1254 if ((ifp
== NULL
) && (!fr
|| !(fr
->fr_flags
& FR_FASTROUTE
))) {
1259 # if __NetBSD_Version__ >= 499001100
1260 if ((fdp
!= NULL
) && (fdp
->fd_ip
.s_addr
!= 0))
1261 sockaddr_in_init(&u
.dst4
, &fdp
->fd_ip
, 0);
1263 sockaddr_in_init(&u
.dst4
, &ip
->ip_dst
, 0);
1265 rtcache_setdst(ro
, dst
);
1266 rt
= rtcache_init(ro
);
1268 dst4
= (struct sockaddr_in
*)&ro
->ro_dst
;
1269 dst4
->sin_family
= AF_INET
;
1270 dst4
->sin_addr
= ip
->ip_dst
;
1271 dst
= (struct sockaddr
*)dst4
;
1273 if ((fdp
!= NULL
) && (fdp
->fd_ip
.s_addr
!= 0))
1274 dst4
->sin_addr
= fdp
->fd_ip
;
1276 dst4
->sin_len
= sizeof(*dst4
);
1281 if ((ifp
== NULL
) && (rt
!= NULL
))
1283 if ((rt
== NULL
) || (ifp
== NULL
)) {
1285 if (in_localaddr(ip
->ip_dst
))
1286 error
= EHOSTUNREACH
;
1289 error
= ENETUNREACH
;
1293 if (rt
->rt_flags
& RTF_GATEWAY
)
1294 dst
= rt
->rt_gateway
;
1299 * For input packets which are being "fastrouted", they won't
1300 * go back through output filtering and miss their chance to get
1301 * NAT'd and counted. Duplicated packets aren't considered to be
1302 * part of the normal packet stream, so do not NAT them or pass
1303 * them through stateful checking, etc.
1305 if ((fdp
!= &fr
->fr_dif
) && (fin
->fin_out
== 0)) {
1306 sifp
= fin
->fin_ifp
;
1309 (void) fr_acctpkt(fin
, NULL
);
1311 if (!fr
|| !(fr
->fr_flags
& FR_RETMASK
)) {
1314 (void) fr_checkstate(fin
, &pass
);
1317 switch (fr_checknatout(fin
, NULL
))
1330 fin
->fin_ifp
= sifp
;
1335 * If small enough for interface, can just send directly.
1337 if (ip
->ip_len
<= ifp
->if_mtu
) {
1340 if (m
->m_flags
& M_EXT
)
1343 ip
->ip_len
= htons(ip
->ip_len
);
1344 ip
->ip_off
= htons(ip
->ip_off
);
1345 # if defined(M_CSUM_IPv4)
1346 # if (__NetBSD_Version__ >= 105009999)
1347 if (ifp
->if_csum_flags_tx
& M_CSUM_IPv4
)
1348 m
->m_pkthdr
.csuminfo
|= M_CSUM_IPv4
;
1350 if (ifp
->if_capabilities
& IFCAP_CSUM_IPv4
)
1351 m
->m_pkthdr
.csuminfo
|= M_CSUM_IPv4
;
1352 # endif /* (__NetBSD_Version__ >= 105009999) */
1353 else if (ip
->ip_sum
== 0)
1354 ip
->ip_sum
= in_cksum(m
, hlen
);
1357 ip
->ip_sum
= in_cksum(m
, hlen
);
1358 # endif /* M_CSUM_IPv4 */
1359 # if __NetBSD_Version__ >= 499001100
1360 error
= (*ifp
->if_output
)(ifp
, m
, dst
, rt
);
1362 error
= (*ifp
->if_output
)(ifp
, m
, (struct sockaddr
*)dst
, rt
);
1365 ip
->ip_len
= ntohs(ip
->ip_len
);
1366 ip
->ip_off
= ntohs(ip
->ip_off
);
1372 * Too large for interface; fragment if possible.
1373 * Must be able to put at least 8 bytes per fragment.
1375 ip_off
= ip
->ip_off
;
1376 if (ip_off
& IP_DF
) {
1380 len
= (ifp
->if_mtu
- hlen
) &~ 7;
1387 int mhlen
, firstlen
= len
;
1388 struct mbuf
**mnext
= &m
->m_act
;
1391 * Loop through length of segment after first fragment,
1392 * make new header and copy data of each part and link onto chain.
1395 mhlen
= sizeof (struct ip
);
1396 for (off
= hlen
+ len
; off
< ip
->ip_len
; off
+= len
) {
1398 MGETHDR(m
, M_DONTWAIT
, MT_HEADER
);
1400 MGET(m
, M_DONTWAIT
, MT_HEADER
);
1407 m
->m_data
+= max_linkhdr
;
1408 mhip
= mtod(m
, struct ip
*);
1409 bcopy((char *)ip
, (char *)mhip
, sizeof(*ip
));
1411 if (hlen
> sizeof (struct ip
)) {
1412 mhlen
= ip_optcopy(ip
, mhip
) + sizeof (struct ip
);
1413 IP_HL_A(mhip
, mhlen
>> 2);
1417 mhip
->ip_off
= ((off
- hlen
) >> 3) + ip_off
;
1418 if (off
+ len
>= ip
->ip_len
)
1419 len
= ip
->ip_len
- off
;
1421 mhip
->ip_off
|= IP_MF
;
1422 mhip
->ip_len
= htons((u_short
)(len
+ mhlen
));
1423 m
->m_next
= m_copy(m0
, off
, len
);
1424 if (m
->m_next
== 0) {
1425 error
= ENOBUFS
; /* ??? */
1428 m
->m_pkthdr
.len
= mhlen
+ len
;
1429 m
->m_pkthdr
.rcvif
= NULL
;
1430 mhip
->ip_off
= htons((u_short
)mhip
->ip_off
);
1433 mhip
->ip_sum
= in_cksum(m
, mhlen
);
1439 * Update first fragment by trimming what's been copied out
1440 * and updating header, then send each fragment (in order).
1442 m_adj(m0
, hlen
+ firstlen
- ip
->ip_len
);
1443 ip
->ip_len
= htons((u_short
)(hlen
+ firstlen
));
1444 ip
->ip_off
= htons((u_short
)IP_MF
);
1447 ip
->ip_sum
= in_cksum(m0
, hlen
);
1450 for (m
= m0
; m
; m
= m0
) {
1453 # if __NetBSD_Version__ >= 499001100
1455 error
= (*ifp
->if_output
)(ifp
, m
, dst
, rt
);
1460 error
= (*ifp
->if_output
)(ifp
, m
,
1461 (struct sockaddr
*)dst
, rt
);
1473 # if __NetBSD_Version__ >= 499001100
1477 RTFREE(((struct route
*)ro
)->ro_rt
);
1483 if (error
== EMSGSIZE
) {
1484 sifp
= fin
->fin_ifp
;
1485 code
= fin
->fin_icode
;
1486 fin
->fin_icode
= ICMP_UNREACH_NEEDFRAG
;
1488 (void) fr_send_icmp_err(ICMP_UNREACH
, fin
, 1);
1489 fin
->fin_ifp
= sifp
;
1490 fin
->fin_icode
= code
;
1498 #if defined(USE_INET6)
1500 * This is the IPv6 specific fastroute code. It doesn't clean up the mbuf's
1501 * or ensure that it is an IPv6 packet that is being forwarded, those are
1502 * expected to be done by the called (ipfr_fastroute).
1504 static int ipfr_fastroute6(m0
, mpp
, fin
, fdp
)
1505 struct mbuf
*m0
, **mpp
;
1509 # if __NetBSD_Version__ >= 499001100
1510 struct route ip6route
;
1511 const struct sockaddr
*dst
;
1513 struct sockaddr dst
;
1514 struct sockaddr_in6 dst6
;
1518 struct route_in6 ip6route
;
1519 struct sockaddr_in6
*dst6
;
1520 struct route_in6
*ro
;
1536 memset(ro
, 0, sizeof(*ro
));
1537 # if __NetBSD_Version__ >= 499001100
1538 if (fdp
!= NULL
&& IP6_NOTZERO(&fdp
->fd_ip6
))
1539 sockaddr_in6_init(&u
.dst6
, &fdp
->fd_ip6
.in6
, 0, 0, 0);
1541 sockaddr_in6_init(&u
.dst6
, &fin
->fin_fi
.fi_dst
.in6
, 0, 0, 0);
1543 rtcache_setdst(ro
, dst
);
1544 rt
= rtcache_init(ro
);
1546 dst6
= (struct sockaddr_in6
*)&ro
->ro_dst
;
1547 dst6
->sin6_family
= AF_INET6
;
1548 dst6
->sin6_len
= sizeof(struct sockaddr_in6
);
1549 dst6
->sin6_addr
= fin
->fin_fi
.fi_dst
.in6
;
1552 if (IP6_NOTZERO(&fdp
->fd_ip6
))
1553 dst6
->sin6_addr
= fdp
->fd_ip6
.in6
;
1556 rtalloc((struct route
*)ro
);
1560 if ((ifp
== NULL
) && (rt
!= NULL
))
1563 if ((rt
== NULL
) || (ifp
== NULL
)) {
1564 error
= EHOSTUNREACH
;
1569 # if __NetBSD_Version__ >= 499001100
1570 if (IN6_IS_ADDR_LINKLOCAL(&u
.dst6
.sin6_addr
))
1571 u
.dst6
.sin6_addr
.s6_addr16
[1] = htons(ifp
->if_index
);
1573 if (IN6_IS_ADDR_LINKLOCAL(&dst6
->sin6_addr
))
1574 dst6
->sin6_addr
.s6_addr16
[1] = htons(ifp
->if_index
);
1578 # if (__NetBSD_Version__ >= 106010000)
1579 # if (__NetBSD_Version__ >= 399001400)
1580 struct in6_ifextra
*ife
;
1582 struct in6_addr finaldst
= fin
->fin_dst6
;
1586 if (rt
->rt_flags
& RTF_GATEWAY
) {
1587 # if __NetBSD_Version__ >= 499001100
1588 dst
= rt
->rt_gateway
;
1590 dst6
= (struct sockaddr_in6
*)rt
->rt_gateway
;
1595 /* Determine path MTU. */
1596 # if (__NetBSD_Version__ <= 106009999)
1597 mtu
= nd_ifinfo
[ifp
->if_index
].linkmtu
;
1599 # if (__NetBSD_Version__ >= 399001400)
1600 ife
= (struct in6_ifextra
*)(ifp
)->if_afdata
[AF_INET6
];
1601 mtu
= ife
->nd_ifinfo
[ifp
->if_index
].linkmtu
;
1603 error
= ip6_getpmtu(ro
, ro
, ifp
, &finaldst
, &mtu
, &frag
);
1606 if ((error
== 0) && (m0
->m_pkthdr
.len
<= mtu
)) {
1607 # if __NetBSD_Version__ >= 499001100
1608 error
= nd6_output(ifp
, ifp
, m0
, satocsin6(dst
), rt
);
1610 error
= nd6_output(ifp
, ifp
, m0
, dst6
, rt
);
1618 # if __NetBSD_Version__ >= 499001100
1630 int fr_verifysrc(fin
)
1633 #if __NetBSD_Version__ >= 499001100
1636 struct sockaddr dst
;
1637 struct sockaddr_in dst4
;
1640 struct sockaddr_in
*dst
;
1642 struct route iproute
;
1645 #if __NetBSD_Version__ >= 499001100
1646 sockaddr_in_init(&u
.dst4
, &fin
->fin_src
, 0);
1647 rtcache_setdst(&iproute
, &u
.dst
);
1648 rt
= rtcache_init(&iproute
);
1652 rc
= (fin
->fin_ifp
== rt
->rt_ifp
);
1653 rtcache_free(&iproute
);
1655 dst
= (struct sockaddr_in
*)&iproute
.ro_dst
;
1656 dst
->sin_len
= sizeof(*dst
);
1657 dst
->sin_family
= AF_INET
;
1658 dst
->sin_addr
= fin
->fin_src
;
1660 if (iproute
.ro_rt
== NULL
)
1662 rc
= (fin
->fin_ifp
== iproute
.ro_rt
->rt_ifp
);
1663 RTFREE(iproute
.ro_rt
);
1670 * return the first IP Address associated with an interface
1672 int fr_ifpaddr(v
, atype
, ifptr
, inp
, inpmask
)
1675 struct in_addr
*inp
, *inpmask
;
1678 struct in6_addr
*inp6
= NULL
;
1680 struct sockaddr
*sock
, *mask
;
1681 struct sockaddr_in
*sin
;
1685 if ((ifptr
== NULL
) || (ifptr
== (void *)-1))
1695 bzero((char *)inp
, sizeof(struct in6_addr
));
1698 ifa
= IFADDR_FIRST(ifp
);
1699 sock
= ifa
? ifa
->ifa_addr
: NULL
;
1700 while (sock
!= NULL
&& ifa
!= NULL
) {
1701 sin
= (struct sockaddr_in
*)sock
;
1702 if ((v
== 4) && (sin
->sin_family
== AF_INET
))
1705 if ((v
== 6) && (sin
->sin_family
== AF_INET6
)) {
1706 inp6
= &((struct sockaddr_in6
*)sin
)->sin6_addr
;
1707 if (!IN6_IS_ADDR_LINKLOCAL(inp6
) &&
1708 !IN6_IS_ADDR_LOOPBACK(inp6
))
1712 ifa
= IFADDR_NEXT(ifa
);
1714 sock
= ifa
->ifa_addr
;
1716 if (ifa
== NULL
|| sock
== NULL
)
1719 mask
= ifa
->ifa_netmask
;
1720 if (atype
== FRI_BROADCAST
)
1721 sock
= ifa
->ifa_broadaddr
;
1722 else if (atype
== FRI_PEERADDR
)
1723 sock
= ifa
->ifa_dstaddr
;
1727 return fr_ifpfillv6addr(atype
, (struct sockaddr_in6
*)sock
,
1728 (struct sockaddr_in6
*)mask
,
1731 return fr_ifpfillv4addr(atype
, (struct sockaddr_in
*)sock
,
1732 (struct sockaddr_in
*)mask
, inp
, inpmask
);
1736 u_32_t
fr_newisn(fin
)
1739 #if __NetBSD_Version__ >= 105190000 /* 1.5T */
1742 if (fin
->fin_v
== 4)
1743 asz
= sizeof(struct in_addr
);
1744 else if (fin
->fin_v
== 6)
1745 asz
= sizeof(fin
->fin_src
);
1746 else /* XXX: no way to return error */
1749 return tcp_new_iss1((void *)&fin
->fin_src
, (void *)&fin
->fin_dst
,
1750 fin
->fin_sport
, fin
->fin_dport
, asz
, 0);
1755 static int iss_seq_off
= 0;
1761 * Compute the base value of the ISS. It is a hash
1762 * of (saddr, sport, daddr, dport, secret).
1766 MD5Update(&ctx
, (u_char
*) &fin
->fin_fi
.fi_src
,
1767 sizeof(fin
->fin_fi
.fi_src
));
1768 MD5Update(&ctx
, (u_char
*) &fin
->fin_fi
.fi_dst
,
1769 sizeof(fin
->fin_fi
.fi_dst
));
1770 MD5Update(&ctx
, (u_char
*) &fin
->fin_dat
, sizeof(fin
->fin_dat
));
1772 MD5Update(&ctx
, ipf_iss_secret
, sizeof(ipf_iss_secret
));
1774 MD5Final(hash
, &ctx
);
1776 memcpy(&newiss
, hash
, sizeof(newiss
));
1779 * Now increment our "timer", and add it in to
1780 * the computed value.
1783 * XXX TCP_ISSINCR too large to use?
1785 iss_seq_off
+= 0x00010000;
1786 newiss
+= iss_seq_off
;
1792 /* ------------------------------------------------------------------------ */
1793 /* Function: fr_nextipid */
1794 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */
1795 /* Parameters: fin(I) - pointer to packet information */
1797 /* Returns the next IPv4 ID to use for this packet. */
1798 /* ------------------------------------------------------------------------ */
1799 u_short
fr_nextipid(fr_info_t
*fin
)
1801 static u_short ipid
= 0;
1804 MUTEX_ENTER(&ipf_rw
);
1806 MUTEX_EXIT(&ipf_rw
);
1812 INLINE
void fr_checkv4sum(fin
)
1815 #ifdef M_CSUM_TCP_UDP_BAD
1816 int manual
, pflag
, cflags
, active
;
1819 if ((fin
->fin_flx
& FI_NOCKSUM
) != 0)
1822 if (fin
->fin_cksum
!= 0)
1835 pflag
= M_CSUM_UDPv4
;
1838 pflag
= M_CSUM_TCPv4
;
1846 active
= ((struct ifnet
*)fin
->fin_ifp
)->if_csum_flags_rx
& pflag
;
1847 active
|= M_CSUM_TCP_UDP_BAD
| M_CSUM_DATA
;
1848 cflags
= m
->m_pkthdr
.csum_flags
& active
;
1851 if (cflags
== (pflag
| M_CSUM_TCP_UDP_BAD
)) {
1852 fin
->fin_flx
|= FI_BAD
;
1853 fin
->fin_cksum
= -1;
1854 } else if (cflags
== (pflag
| M_CSUM_DATA
)) {
1855 if ((m
->m_pkthdr
.csum_data
^ 0xffff) != 0) {
1856 fin
->fin_flx
|= FI_BAD
;
1857 fin
->fin_cksum
= -1;
1861 } else if (cflags
== pflag
) {
1869 # ifdef IPFILTER_CKSUM
1871 if (fr_checkl4sum(fin
) == -1)
1872 fin
->fin_flx
|= FI_BAD
;
1877 # ifdef IPFILTER_CKSUM
1878 if (fr_checkl4sum(fin
) == -1)
1879 fin
->fin_flx
|= FI_BAD
;
1886 INLINE
void fr_checkv6sum(fin
)
1889 # ifdef M_CSUM_TCP_UDP_BAD
1890 int manual
, pflag
, cflags
, active
;
1893 if ((fin
->fin_flx
& FI_NOCKSUM
) != 0)
1902 pflag
= M_CSUM_UDPv6
;
1905 pflag
= M_CSUM_TCPv6
;
1913 active
= ((struct ifnet
*)fin
->fin_ifp
)->if_csum_flags_rx
& pflag
;
1914 active
|= M_CSUM_TCP_UDP_BAD
| M_CSUM_DATA
;
1915 cflags
= m
->m_pkthdr
.csum_flags
& active
;
1918 if (cflags
== (pflag
| M_CSUM_TCP_UDP_BAD
)) {
1919 fin
->fin_flx
|= FI_BAD
;
1920 } else if (cflags
== (pflag
| M_CSUM_DATA
)) {
1921 if ((m
->m_pkthdr
.csum_data
^ 0xffff) != 0)
1922 fin
->fin_flx
|= FI_BAD
;
1923 } else if (cflags
== pflag
) {
1929 # ifdef IPFILTER_CKSUM
1931 if (fr_checkl4sum(fin
) == -1)
1932 fin
->fin_flx
|= FI_BAD
;
1935 # ifdef IPFILTER_CKSUM
1936 if (fr_checkl4sum(fin
) == -1)
1937 fin
->fin_flx
|= FI_BAD
;
1941 #endif /* USE_INET6 */
1944 size_t mbufchainlen(m0
)
1949 if ((m0
->m_flags
& M_PKTHDR
) != 0) {
1950 len
= m0
->m_pkthdr
.len
;
1954 for (m
= m0
, len
= 0; m
!= NULL
; m
= m
->m_next
)
1961 /* ------------------------------------------------------------------------ */
1962 /* Function: fr_pullup */
1963 /* Returns: NULL == pullup failed, else pointer to protocol header */
1964 /* Parameters: m(I) - pointer to buffer where data packet starts */
1965 /* fin(I) - pointer to packet information */
1966 /* len(I) - number of bytes to pullup */
1968 /* Attempt to move at least len bytes (from the start of the buffer) into a */
1969 /* single buffer for ease of access. Operating system native functions are */
1970 /* used to manage buffers - if necessary. If the entire packet ends up in */
1971 /* a single buffer, set the FI_COALESCE flag even though fr_coalesce() has */
1972 /* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */
1973 /* and ONLY if the pullup succeeds. */
1975 /* We assume that 'xmin' is a pointer to a buffer that is part of the chain */
1976 /* of buffers that starts at *fin->fin_mp. */
1977 /* ------------------------------------------------------------------------ */
1978 void *fr_pullup(xmin
, fin
, len
)
1983 int out
= fin
->fin_out
, dpoff
, ipoff
;
1990 ip
= (char *)fin
->fin_ip
;
1991 if ((fin
->fin_flx
& FI_COALESCE
) != 0)
1994 ipoff
= fin
->fin_ipoff
;
1995 if (fin
->fin_dp
!= NULL
)
1996 dpoff
= (char *)fin
->fin_dp
- (char *)ip
;
2000 if (M_LEN(m
) < len
) {
2001 mb_t
*n
= *fin
->fin_mp
;
2003 * Assume that M_PKTHDR is set and just work with what is left
2004 * rather than check..
2005 * Should not make any real difference, anyway.
2009 * Record the mbuf that points to the mbuf that we're
2010 * about to go to work on so that we can update the
2011 * m_next appropriately later.
2013 for (; n
->m_next
!= m
; n
= n
->m_next
)
2025 #ifdef HAVE_M_PULLDOWN
2026 if (m_pulldown(m
, 0, len
, NULL
) == NULL
)
2029 FREE_MB_T(*fin
->fin_mp
);
2035 m
= m_pullup(m
, len
);
2041 * When n is non-NULL, it indicates that m pointed to
2042 * a sub-chain (tail) of the mbuf and that the head
2043 * of this chain has not yet been free'd.
2046 FREE_MB_T(*fin
->fin_mp
);
2049 *fin
->fin_mp
= NULL
;
2051 ATOMIC_INCL(frstats
[out
].fr_pull
[1]);
2058 while (M_LEN(m
) == 0) {
2062 ip
= MTOD(m
, char *) + ipoff
;
2064 ATOMIC_INCL(frstats
[out
].fr_pull
[0]);
2065 fin
->fin_ip
= (ip_t
*)ip
;
2066 if (fin
->fin_dp
!= NULL
)
2067 fin
->fin_dp
= (char *)fin
->fin_ip
+ dpoff
;
2070 if (len
== fin
->fin_plen
)
2071 fin
->fin_flx
|= FI_COALESCE
;
2076 int iplpoll(dev
, events
, p
)
2079 #if (__NetBSD_Version__ >= 399001400)
2085 u_int unit
= GET_MINOR(dev
);
2088 if (IPL_LOGMAX
< unit
)
2097 if ((events
& (POLLIN
| POLLRDNORM
)) && ipflog_canread(unit
))
2098 revents
|= events
& (POLLIN
| POLLRDNORM
);
2102 if ((events
& (POLLIN
| POLLRDNORM
)) && fr_auth_waiting())
2103 revents
|= events
& (POLLIN
| POLLRDNORM
);
2106 #ifdef IPFILTER_SYNC
2107 if ((events
& (POLLIN
| POLLRDNORM
)) && ipfsync_canread())
2108 revents
|= events
& (POLLIN
| POLLRDNORM
);
2109 if ((events
& (POLLOUT
| POLLWRNORM
)) && ipfsync_canwrite())
2110 revents
|= events
& (POLLOUT
| POLLOUTNORM
);
2114 case IPL_LOGLOOKUP
:
2119 if ((revents
== 0) && ((events
& (POLLIN
|POLLRDNORM
)) != 0))
2120 selrecord(p
, &ipfselwait
[unit
]);
2125 int ipf_inject(fin
, m
)
2131 if (fin
->fin_out
== 0) {
2132 struct ifqueue
*ifq
;
2136 if (IF_QFULL(ifq
)) {
2145 error
= ip_output(m
, NULL
, NULL
, IP_FORWARDING
, NULL
);