2 * Copyright (C) 1993-2001 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
6 * @(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed
7 * @(#)$Id: ip_fil.c,v 2.42.2.60 2002/08/28 12:40:39 darrenr Exp $
8 * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_fil.c,v 1.25.2.7 2004/07/04 09:24:38 darrenr Exp $
9 * $DragonFly: src/sys/contrib/ipfilter/netinet/ip_fil.c,v 1.27 2008/05/14 11:59:18 sephe Exp $
12 #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
15 #if defined(KERNEL) && !defined(_KERNEL)
18 #if defined(_KERNEL) && (defined(__DragonFly__) || (defined(__FreeBSD_version) && \
19 (__FreeBSD_version >= 400000))) && !defined(KLD_MODULE)
20 #include "opt_inet6.h"
22 #include <sys/param.h>
23 #if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
24 defined(_KERNEL) && !defined(_LKM)
25 # include "opt_ipfilter_log.h"
27 #if defined(__FreeBSD__) && !defined(__FreeBSD_version)
28 # if !defined(_KERNEL) || defined(IPFILTER_LKM)
29 # include <osreldate.h>
32 #if defined(__sgi) && (IRIX > 602)
34 # include <sys/ptimers.h>
42 #define ksprintf sprintf
44 #include <sys/errno.h>
45 #include <sys/types.h>
47 #if (defined(__DragonFly__) || __FreeBSD_version >= 220000) && defined(_KERNEL)
48 # include <sys/fcntl.h>
49 # include <sys/filio.h>
51 # include <sys/ioctl.h>
55 # include <sys/systm.h>
58 # if defined(__DragonFly__) || (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000)
59 # include <sys/dirent.h>
63 # include <sys/mbuf.h>
65 # include <sys/filio.h>
67 #include <sys/protosw.h>
68 #include <sys/socket.h>
69 #if defined(__DragonFly__) && defined(_KERNEL)
70 # include <sys/thread2.h>
77 #if defined(__DragonFly__) || __FreeBSD_version >= 300000
78 # include <net/if_var.h>
79 # if defined(_KERNEL) && !defined(IPFILTER_LKM)
80 # include "opt_ipfilter.h"
84 #include <sys/debug.h>
85 # ifdef IFF_DRVRLOCK /* IRIX6 */
86 #include <sys/hashing.h>
89 #include <net/route.h>
90 #include <netinet/in.h>
91 #if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */
92 # include <netinet/in_var.h>
94 #include <netinet/in_systm.h>
95 #include <netinet/ip.h>
96 #include <netinet/ip_var.h>
97 #include <netinet/tcp.h>
98 #include <netinet/udp.h>
99 #include <netinet/tcpip.h>
100 #include <netinet/ip_icmp.h>
105 #include "ip_compat.h"
107 # include <netinet/icmp6.h>
109 # include <netinet6/ip6protosw.h>
110 # include <netinet6/nd6.h>
116 #include "ip_state.h"
117 #include "ip_proxy.h"
119 #if defined(__DragonFly__) || (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000))
120 # include <sys/malloc.h>
123 # define MIN(a,b) (((a)<(b))?(a):(b))
125 #if !SOLARIS && defined(_KERNEL) && !defined(__sgi)
126 # include <sys/kernel.h>
127 extern int ip_optcopy (struct ip
*, struct ip
*);
129 #if defined(OpenBSD) && (OpenBSD >= 200211) && defined(_KERNEL)
130 extern int ip6_getpmtu(struct route_in6
*, struct route_in6
*,
131 struct ifnet
*, struct in6_addr
*, u_long
*);
134 #include <sys/in_cksum.h>
136 static const char sccsid
[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
140 static struct ifnet
**ifneta
= NULL
;
143 # if (BSD < 199306) || defined(__sgi)
148 #ifdef ICMP_UNREACH_FILTER_PROHIB
149 int ipl_unreach
= ICMP_UNREACH_FILTER_PROHIB
;
151 int ipl_unreach
= ICMP_UNREACH_FILTER
;
153 u_long ipl_frouteok
[2] = {0, 0};
155 static int frzerostats (caddr_t
);
156 #if defined(__DragonFly__) || defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003)
157 static int frrequest (int, u_long
, caddr_t
, int);
159 static int frrequest (int, int, caddr_t
, int);
162 static int (*fr_savep
) (ip_t
*, int, void *, int, struct mbuf
**);
163 static int send_ip (ip_t
*, fr_info_t
*, struct mbuf
**);
165 static int ipfr_fastroute6 (struct mbuf
*, struct mbuf
**,
166 fr_info_t
*, frdest_t
*);
169 extern int tcp_mtudisc
;
170 extern kmutex_t ipf_rw
;
171 extern KRWLOCK_T ipf_mutex
;
174 void init_ifp (void);
175 # if defined(__sgi) && (IRIX < 605)
176 static int no_output (struct ifnet
*, struct mbuf
*,
178 static int write_output (struct ifnet
*, struct mbuf
*,
181 static int no_output (struct ifnet
*, struct mbuf
*,
182 struct sockaddr
*, struct rtentry
*);
183 static int write_output (struct ifnet
*, struct mbuf
*,
184 struct sockaddr
*, struct rtentry
*);
189 #if (defined(__DragonFly__) || __FreeBSD_version >= 300000) && defined(_KERNEL)
190 struct callout ipfr_slowtimer_ch
;
192 #if defined(__NetBSD__) && (__NetBSD_Version__ >= 104230000)
193 # include <sys/callout.h>
194 struct callout ipfr_slowtimer_ch
;
196 #if defined(__OpenBSD__)
197 # include <sys/timeout.h>
198 struct timeout ipfr_slowtimer_ch
;
200 #if defined(__sgi) && defined(_KERNEL)
201 toid_t ipfr_slowtimer_ch
;
204 #if defined(__NetBSD__) && (__NetBSD_Version__ >= 106080000) && \
206 # include <sys/conf.h>
207 const struct cdevsw ipl_cdevsw
= {
208 iplopen
, iplclose
, iplread
, nowrite
, iplioctl
,
209 nostop
, notty
, nopoll
, nommap
,
213 #if (_BSDI_VERSION >= 199510) && defined(_KERNEL)
214 # include <sys/device.h>
215 # include <sys/conf.h>
217 struct cfdriver iplcd
= {
218 NULL
, "ipl", NULL
, NULL
, DV_DULL
, 0
221 struct devsw iplsw
= {
223 iplopen
, iplclose
, iplread
, nowrite
, iplioctl
, noselect
, nommap
,
224 nostrat
, nodump
, nopsize
, 0,
227 #endif /* _BSDI_VERSION >= 199510 && _KERNEL */
229 #if defined(__NetBSD__) || defined(__OpenBSD__) || \
230 (_BSDI_VERSION >= 199701) || (defined(__DragonFly_version) && \
231 (__DragonFly_version >= 100000))
232 # include <sys/conf.h>
233 # if defined(NETBSD_PF)
234 # include <net/pfil.h>
236 * We provide the fr_checkp name just to minimize changes later.
238 int (*fr_checkp
) (ip_t
*ip
, int hlen
, void *ifp
, int out
, mb_t
**mp
);
239 # endif /* NETBSD_PF */
240 #endif /* __NetBSD__ */
243 #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000) && \
245 # include <net/pfil.h>
247 static int fr_check_wrapper(void *, struct mbuf
**, struct ifnet
*, int );
249 static int fr_check_wrapper(arg
, mp
, ifp
, dir
)
255 struct ip
*ip
= mtod(*mp
, struct ip
*);
256 int rv
, hlen
= ip
->ip_hl
<< 2;
258 #if defined(M_CSUM_TCPv4)
260 * If the packet is out-bound, we can't delay checksums
261 * here. For in-bound, the checksum has already been
264 if (dir
== PFIL_OUT
) {
265 if ((*mp
)->m_pkthdr
.csum_flags
& (M_CSUM_TCPv4
|M_CSUM_UDPv4
)) {
266 in_delayed_cksum(*mp
);
267 (*mp
)->m_pkthdr
.csum_flags
&=
268 ~(M_CSUM_TCPv4
|M_CSUM_UDPv4
);
271 #endif /* M_CSUM_TCPv4 */
274 * We get the packet with all fields in network byte
275 * order. We expect ip_len and ip_off to be in host
276 * order. We frob them, call the filter, then frob
279 * Note, we don't need to update the checksum, because
280 * it has already been verified.
282 ip
->ip_len
= ntohs(ip
->ip_len
);
283 ip
->ip_off
= ntohs(ip
->ip_off
);
285 rv
= fr_check(ip
, hlen
, ifp
, (dir
== PFIL_OUT
), mp
);
287 if (rv
== 0 && *mp
!= NULL
) {
288 ip
= mtod(*mp
, struct ip
*);
289 ip
->ip_len
= htons(ip
->ip_len
);
290 ip
->ip_off
= htnos(ip
->ip_off
);
297 # include <netinet/ip6.h>
299 static int fr_check_wrapper6(void *, struct mbuf
**, struct ifnet
*, int );
301 static int fr_check_wrapper6(arg
, mp
, ifp
, dir
)
308 return (fr_check(mtod(*mp
, struct ip
*), sizeof(struct ip6_hdr
),
309 ifp
, (dir
== PFIL_OUT
), mp
));
312 #endif /* __NetBSD_Version >= 105110000 && _KERNEL */
313 #if defined(__DragonFly_version) && (__DragonFly_version >= 100000) && \
317 fr_check_wrapper(void *arg
, struct mbuf
**mp
, struct ifnet
*ifp
, int dir
)
319 struct ip
*ip
= mtod(*mp
, struct ip
*);
320 return fr_check(ip
, ip
->ip_hl
<< 2, ifp
, (dir
== PFIL_OUT
), mp
);
324 # include <netinet/ip6.h>
327 fr_check_wrapper6(void *arg
, struct mbuf
**mp
, struct ifnet
*ifp
, int dir
)
329 return (fr_check(mtod(*mp
, struct ip
*), sizeof(struct ip6_hdr
),
330 ifp
, (dir
== PFIL_OUT
), mp
));
332 # endif /* USE_INET6 */
333 #endif /* __DragonFly_version >= 100000 && _KERNEL */
335 # if defined(IPFILTER_LKM) && !defined(__sgi)
339 if (strcmp(s
, "ipl") == 0)
343 # endif /* IPFILTER_LKM */
347 * Try to detect the case when compiling for NetBSD with pseudo-device
349 # if defined(__NetBSD__) && defined(PFIL_HOOKS)
351 ipfilterattach(count
)
356 * Do nothing here, really. The filter will be enabled
357 * by the SIOCFRENB ioctl.
363 # if defined(__NetBSD__) || defined(__OpenBSD__)
370 # if !defined(__DragonFly__)
373 # if defined(__sgi) || (defined(NETBSD_PF) && \
374 (__NetBSD_Version__ >= 104200000)) || \
375 (defined(__DragonFly_version) && (__DragonFly_version >= 100000))
378 #if (defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000)) || \
379 (defined(__DragonFly_version) && (__DragonFly_version >= 100000))
380 struct pfil_head
*ph_inet
;
382 struct pfil_head
*ph_inet6
;
387 if (fr_running
|| (fr_checkp
== fr_check
)) {
388 kprintf("IP Filter: already initialized\n");
396 if (nat_init() == -1) {
400 if (fr_stateinit() == -1) {
404 if (appr_init() == -1) {
410 # if (__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011) || \
411 (defined(__DragonFly_version) && (__DragonFly_version >= 100000))
412 # if (__NetBSD_Version__ >= 105110000) || (__DragonFly_version >= 100000)
413 ph_inet
= pfil_head_get(PFIL_TYPE_AF
, AF_INET
);
415 ph_inet6
= pfil_head_get(PFIL_TYPE_AF
, AF_INET6
);
425 error
= pfil_add_hook((void *)fr_check_wrapper
, NULL
,
426 PFIL_IN
|PFIL_OUT
, ph_inet
);
430 error
= pfil_add_hook((void *)fr_check
, PFIL_IN
|PFIL_OUT
,
431 &inetsw
[ip_protox
[IPPROTO_IP
]].pr_pfh
);
445 pfil_add_hook((void *)fr_check
, PFIL_IN
|PFIL_OUT
);
448 # if (__NetBSD_Version__ >= 105110000) || (__DragonFly_version >= 100000)
449 if (ph_inet6
!= NULL
)
450 error
= pfil_add_hook((void *)fr_check_wrapper6
, NULL
,
451 PFIL_IN
|PFIL_OUT
, ph_inet6
);
455 pfil_remove_hook((void *)fr_check_wrapper6
, NULL
,
456 PFIL_IN
|PFIL_OUT
, ph_inet6
);
458 error
= pfil_add_hook((void *)fr_check
, PFIL_IN
|PFIL_OUT
,
459 &inet6sw
[ip6_protox
[IPPROTO_IPV6
]].pr_pfh
);
461 pfil_remove_hook((void *)fr_check
, PFIL_IN
|PFIL_OUT
,
462 &inetsw
[ip_protox
[IPPROTO_IP
]].pr_pfh
);
475 error
= ipfilter_sgi_attach();
485 bzero((char *)frcache
, sizeof(frcache
));
486 fr_savep
= fr_checkp
;
487 fr_checkp
= fr_check
;
491 if (fr_pass
& FR_PASS
)
493 else if (fr_pass
& FR_BLOCK
)
496 defpass
= "no-match -> block";
498 kprintf("%s initialized. Default = %s all, Logging = %s\n",
499 ipfilter_version
, defpass
,
506 # if defined(__NetBSD__) && (__NetBSD_Version__ >= 104230000)
507 callout_init(&ipfr_slowtimer_ch
);
508 callout_reset(&ipfr_slowtimer_ch
, hz
/ 2, ipfr_slowtimer
, NULL
);
510 # if defined(__OpenBSD__)
511 timeout_set(&ipfr_slowtimer_ch
, ipfr_slowtimer
, NULL
);
512 timeout_add(&ipfr_slowtimer_ch
, hz
/2);
514 # if (defined(__DragonFly__) || __FreeBSD_version >= 300000) || defined(__sgi)
515 callout_init(&ipfr_slowtimer_ch
);
516 callout_reset(&ipfr_slowtimer_ch
, hz
/ 2, ipfr_slowtimer
, NULL
);
518 timeout(ipfr_slowtimer
, NULL
, hz
/2);
528 * Disable the filter by removing the hooks from the IP input/output
531 # if defined(__NetBSD__)
537 # if !defined(__DragonFly__)
541 #if defined(NETBSD_PF) && \
542 ((__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011) || \
543 (defined(__DragonFly_version) && (__DragonFly_version >= 100000)))
545 # if (__NetBSD_Version__ >= 105150000) || (__DragonFly_version >= 100000)
546 struct pfil_head
*ph_inet
= pfil_head_get(PFIL_TYPE_AF
, AF_INET
);
548 struct pfil_head
*ph_inet6
= pfil_head_get(PFIL_TYPE_AF
, AF_INET6
);
554 # if defined(__NetBSD__) && (__NetBSD_Version__ >= 104230000)
555 callout_stop(&ipfr_slowtimer_ch
);
557 # if (defined(__DragonFly__) || __FreeBSD_version >= 300000)
558 callout_stop(&ipfr_slowtimer_ch
);
561 untimeout(ipfr_slowtimer_ch
);
563 # if defined(__OpenBSD__)
564 timeout_del(&ipfr_slowtimer_ch
);
566 untimeout(ipfr_slowtimer
, NULL
);
567 # endif /* OpenBSD */
569 # endif /* FreeBSD */
575 kprintf("IP Filter: not initialized\n");
580 kprintf("%s unloaded\n", ipfilter_version
);
582 fr_checkp
= fr_savep
;
583 i
= frflush(IPL_LOGIPF
, 0, FR_INQUE
|FR_OUTQUE
|FR_INACTIVE
);
584 i
+= frflush(IPL_LOGIPF
, 0, FR_INQUE
|FR_OUTQUE
);
588 # if ((__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011) || \
589 (__DragonFly_version >= 100000))
590 # if (__NetBSD_Version__ >= 105110000) || (__DragonFly_version >= 100000)
592 error
= pfil_remove_hook((void *)fr_check_wrapper
, NULL
,
593 PFIL_IN
|PFIL_OUT
, ph_inet
);
597 error
= pfil_remove_hook((void *)fr_check
, PFIL_IN
|PFIL_OUT
,
598 &inetsw
[ip_protox
[IPPROTO_IP
]].pr_pfh
);
605 pfil_remove_hook((void *)fr_check
, PFIL_IN
|PFIL_OUT
);
608 # if (__NetBSD_Version__ >= 105110000) || (__DragonFly_version >= 100000)
609 if (ph_inet6
!= NULL
)
610 error
= pfil_remove_hook((void *)fr_check_wrapper6
, NULL
,
611 PFIL_IN
|PFIL_OUT
, ph_inet6
);
615 error
= pfil_remove_hook((void *)fr_check
, PFIL_IN
|PFIL_OUT
,
616 &inet6sw
[ip6_protox
[IPPROTO_IPV6
]].pr_pfh
);
626 ipfilter_sgi_detach();
641 static int frzerostats(data
)
648 error
= IWCOPYPTR((caddr_t
)&fio
, data
, sizeof(fio
));
652 bzero((char *)frstats
, sizeof(*frstats
) * 2);
659 * Filter ioctl interface.
662 int IPL_EXTERN(ioctl
)(dev_t dev
, int cmd
, caddr_t data
, int mode
664 , cred_t
*cp
, int *rp
668 #if defined(__DragonFly__)
669 # if defined(_KERNEL)
670 int IPL_EXTERN(ioctl
)(struct dev_ioctl_args
*ap
)
672 int IPL_EXTERN(ioctl
)(struct cdev
*dev
, u_long cmd
, caddr_t data
, int mode
)
675 int IPL_EXTERN(ioctl
)(dev
, cmd
, data
, mode
676 #if (defined(_KERNEL) && defined(__FreeBSD__))
679 # elif (defined(_KERNEL) && ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || \
680 (NetBSD >= 199511) || (__FreeBSD_version >= 220000) || \
681 defined(__OpenBSD__)))
688 # if defined(__NetBSD__) || defined(__OpenBSD__) || \
689 (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000)
696 #endif /* DragonFly */
699 #if (defined(_KERNEL) && defined(__DragonFly__))
700 struct cdev
*dev
= ap
->a_head
.a_dev
;
701 u_long cmd
= ap
->a_cmd
;
702 caddr_t data
= ap
->a_data
;
703 int mode
= ap
->a_fflag
;
705 #if defined(_KERNEL) && !SOLARIS && !defined(__DragonFly__)
708 int error
= 0, unit
= 0, tmp
;
710 #if (BSD >= 199306) && defined(_KERNEL)
711 if ((securelevel
>= 3) && (mode
& FWRITE
))
715 unit
= GET_MINOR(dev
);
716 if ((IPL_LOGMAX
< unit
) || (unit
< 0))
722 if (fr_running
== 0 && (cmd
!= SIOCFRENB
|| unit
!= IPL_LOGIPF
))
727 if (unit
== IPL_LOGNAT
) {
729 error
= nat_ioctl(data
, cmd
, mode
);
735 if (unit
== IPL_LOGSTATE
) {
737 error
= fr_state_ioctl(data
, cmd
, mode
);
743 if (unit
== IPL_LOGAUTH
) {
747 if ((cmd
== SIOCADAFR
) || (cmd
== SIOCRMAFR
)) {
748 if (!(mode
& FWRITE
)) {
751 error
= frrequest(unit
, cmd
, data
,
755 error
= fr_auth_ioctl(data
, mode
, cmd
);
764 error
= IWCOPY((caddr_t
)&iplused
[IPL_LOGIPF
], (caddr_t
)data
,
765 sizeof(iplused
[IPL_LOGIPF
]));
768 #if (!defined(IPFILTER_LKM) || defined(__NetBSD__)) && defined(_KERNEL)
773 if (!(mode
& FWRITE
))
776 error
= IRCOPY(data
, (caddr_t
)&enable
, sizeof(enable
));
780 # if defined(__NetBSD__) || defined(__OpenBSD__)
781 error
= ipl_enable();
786 # if defined(__NetBSD__)
787 error
= ipl_disable();
796 if (!(mode
& FWRITE
))
799 error
= IRCOPY(data
, (caddr_t
)&fr_flags
,
803 error
= IWCOPY((caddr_t
)&fr_flags
, data
, sizeof(fr_flags
));
809 if (!(mode
& FWRITE
))
812 error
= frrequest(unit
, cmd
, data
, fr_active
);
817 if (!(mode
& FWRITE
))
820 error
= frrequest(unit
, cmd
, data
, 1 - fr_active
);
823 if (!(mode
& FWRITE
))
826 bzero((char *)frcache
, sizeof(frcache
[0]) * 2);
827 *(u_int
*)data
= fr_active
;
828 fr_active
= 1 - fr_active
;
836 error
= IWCOPYPTR((caddr_t
)&fio
, data
, sizeof(fio
));
842 if (!(mode
& FWRITE
))
845 error
= frzerostats(data
);
848 if (!(mode
& FWRITE
))
851 error
= IRCOPY(data
, (caddr_t
)&tmp
, sizeof(tmp
));
853 tmp
= frflush(unit
, 4, tmp
);
854 error
= IWCOPY((caddr_t
)&tmp
, data
,
861 if (!(mode
& FWRITE
))
864 error
= IRCOPY(data
, (caddr_t
)&tmp
, sizeof(tmp
));
866 tmp
= frflush(unit
, 6, tmp
);
867 error
= IWCOPY((caddr_t
)&tmp
, data
,
874 error
= IRCOPY(data
, (caddr_t
)&tmp
, sizeof(tmp
));
885 if (!(mode
& FWRITE
))
888 *(int *)data
= ipflog_clear(unit
);
890 #endif /* IPFILTER_LOG */
892 error
= IWCOPYPTR((caddr_t
)ipfr_fragstats(), data
,
898 if (!(mode
& FWRITE
))
901 #if defined(_KERNEL) && defined(__sgi)
916 void fr_forgetifp(ifp
)
921 WRITE_ENTER(&ipf_mutex
);
922 for (f
= ipacct
[0][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
923 if (f
->fr_ifa
== ifp
)
924 f
->fr_ifa
= (void *)-1;
925 for (f
= ipacct
[1][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
926 if (f
->fr_ifa
== ifp
)
927 f
->fr_ifa
= (void *)-1;
928 for (f
= ipfilter
[0][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
929 if (f
->fr_ifa
== ifp
)
930 f
->fr_ifa
= (void *)-1;
931 for (f
= ipfilter
[1][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
932 if (f
->fr_ifa
== ifp
)
933 f
->fr_ifa
= (void *)-1;
935 for (f
= ipacct6
[0][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
936 if (f
->fr_ifa
== ifp
)
937 f
->fr_ifa
= (void *)-1;
938 for (f
= ipacct6
[1][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
939 if (f
->fr_ifa
== ifp
)
940 f
->fr_ifa
= (void *)-1;
941 for (f
= ipfilter6
[0][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
942 if (f
->fr_ifa
== ifp
)
943 f
->fr_ifa
= (void *)-1;
944 for (f
= ipfilter6
[1][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
945 if (f
->fr_ifa
== ifp
)
946 f
->fr_ifa
= (void *)-1;
948 RWLOCK_EXIT(&ipf_mutex
);
953 static int frrequest(unit
, req
, data
, set
)
955 #if defined(__DragonFly__) || defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003)
963 frentry_t
*fp
, *f
, **fprev
;
965 frgroup_t
*fg
= NULL
;
966 int error
= 0, in
, i
;
973 error
= IRCOPYPTR(data
, (caddr_t
)fp
, sizeof(*fp
));
977 #if (BSD >= 199306) && defined(_KERNEL)
978 if ((securelevel
> 0) && (fp
->fr_func
!= NULL
))
983 * Check that the group number does exist and that if a head group
984 * has been specified, doesn't exist.
986 if ((req
!= SIOCZRLST
) && ((req
== SIOCINAFR
) || (req
== SIOCINIFR
) ||
987 (req
== SIOCADAFR
) || (req
== SIOCADIFR
)) && fp
->fr_grhead
&&
988 fr_findgroup((u_int
)fp
->fr_grhead
, fp
->fr_flags
, unit
, set
, NULL
))
990 if ((req
!= SIOCZRLST
) && fp
->fr_group
&&
991 !fr_findgroup((u_int
)fp
->fr_group
, fp
->fr_flags
, unit
, set
, NULL
))
994 in
= (fp
->fr_flags
& FR_INQUE
) ? 0 : 1;
996 if (unit
== IPL_LOGAUTH
)
997 ftail
= fprev
= &ipauth
;
998 else if ((fp
->fr_flags
& FR_ACCOUNT
) && (fp
->fr_v
== 4))
999 ftail
= fprev
= &ipacct
[in
][set
];
1000 else if ((fp
->fr_flags
& (FR_OUTQUE
|FR_INQUE
)) && (fp
->fr_v
== 4))
1001 ftail
= fprev
= &ipfilter
[in
][set
];
1003 else if ((fp
->fr_flags
& FR_ACCOUNT
) && (fp
->fr_v
== 6))
1004 ftail
= fprev
= &ipacct6
[in
][set
];
1005 else if ((fp
->fr_flags
& (FR_OUTQUE
|FR_INQUE
)) && (fp
->fr_v
== 6))
1006 ftail
= fprev
= &ipfilter6
[in
][set
];
1011 if ((group
= fp
->fr_group
)) {
1012 if (!(fg
= fr_findgroup(group
, fp
->fr_flags
, unit
, set
, NULL
)))
1014 ftail
= fprev
= fg
->fg_start
;
1017 bzero((char *)frcache
, sizeof(frcache
[0]) * 2);
1019 for (i
= 0; i
< 4; i
++) {
1020 if ((fp
->fr_ifnames
[i
][1] == '\0') &&
1021 ((fp
->fr_ifnames
[i
][0] == '-') ||
1022 (fp
->fr_ifnames
[i
][0] == '*'))) {
1023 fp
->fr_ifas
[i
] = NULL
;
1024 } else if (*fp
->fr_ifnames
[i
]) {
1025 fp
->fr_ifas
[i
] = GETUNIT(fp
->fr_ifnames
[i
], fp
->fr_v
);
1026 if (!fp
->fr_ifas
[i
])
1027 fp
->fr_ifas
[i
] = (void *)-1;
1032 fp
->fr_flags
&= ~FR_DUP
;
1033 if (*fdp
->fd_ifname
) {
1034 fdp
->fd_ifp
= GETUNIT(fdp
->fd_ifname
, fp
->fr_v
);
1036 fdp
->fd_ifp
= (struct ifnet
*)-1;
1038 fp
->fr_flags
|= FR_DUP
;
1042 if (*fdp
->fd_ifname
) {
1043 fdp
->fd_ifp
= GETUNIT(fdp
->fd_ifname
, fp
->fr_v
);
1045 fdp
->fd_ifp
= (struct ifnet
*)-1;
1049 * Look for a matching filter rule, but don't include the next or
1050 * interface pointer in the comparison (fr_next, fr_ifa).
1052 for (fp
->fr_cksum
= 0, p
= (u_int
*)&fp
->fr_ip
, pp
= &fp
->fr_cksum
;
1056 for (; (f
= *ftail
); ftail
= &f
->fr_next
)
1057 if ((fp
->fr_cksum
== f
->fr_cksum
) &&
1058 !bcmp((char *)&f
->fr_ip
, (char *)&fp
->fr_ip
, FR_CMPSIZ
))
1062 * If zero'ing statistics, copy current to caller and zero.
1064 if (req
== SIOCZRLST
) {
1067 error
= IWCOPYPTR((caddr_t
)f
, data
, sizeof(*f
));
1076 if (req
!= SIOCINAFR
&& req
!= SIOCINIFR
)
1077 while ((f
= *ftail
))
1078 ftail
= &f
->fr_next
;
1082 while (--fp
->fr_hits
&& (f
= *ftail
))
1083 ftail
= &f
->fr_next
;
1089 if (req
== SIOCRMAFR
|| req
== SIOCRMIFR
) {
1094 * Only return EBUSY if there is a group list, else
1095 * it's probably just state information referencing
1098 if ((f
->fr_ref
> 1) && f
->fr_grp
)
1100 if (fg
&& fg
->fg_head
)
1101 fg
->fg_head
->fr_ref
--;
1102 if (unit
== IPL_LOGAUTH
) {
1103 return fr_preauthcmd(req
, f
, ftail
);
1106 fr_delgroup((u_int
)f
->fr_grhead
, fp
->fr_flags
,
1108 fixskip(fprev
, f
, -1);
1109 *ftail
= f
->fr_next
;
1119 if (unit
== IPL_LOGAUTH
) {
1120 return fr_preauthcmd(req
, fp
, ftail
);
1122 KMALLOC(f
, frentry_t
*);
1124 if (fg
&& fg
->fg_head
)
1125 fg
->fg_head
->fr_ref
++;
1126 bcopy((char *)fp
, (char *)f
, sizeof(*f
));
1129 f
->fr_next
= *ftail
;
1131 if (req
== SIOCINIFR
|| req
== SIOCINAFR
)
1132 fixskip(fprev
, f
, 1);
1134 if ((group
= f
->fr_grhead
))
1135 fg
= fr_addgroup(group
, f
, unit
, set
);
1146 * routines below for saving IP headers to buffer
1148 #ifdef __DragonFly__
1149 int IPL_EXTERN(open
)(struct dev_open_args
*ap
)
1152 int IPL_EXTERN(open
)(dev_t
*pdev
, int flags
, int devtype
, cred_t
*cp
)
1154 int IPL_EXTERN(open
)(dev
, flags
1155 #if defined(__FreeBSD__)
1159 #elif ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \
1160 (__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL)
1170 #endif /* DragonFly */
1172 #ifdef __DragonFly__
1173 struct cdev
*dev
= ap
->a_head
.a_dev
;
1175 # if defined(__sgi) && defined(_KERNEL)
1176 u_int min
= geteminor(*pdev
);
1178 u_int min
= GET_MINOR(dev
);
1181 if (IPL_LOGMAX
< min
)
1189 #ifdef __DragonFly__
1190 int IPL_EXTERN(close
)(struct dev_close_args
*ap
)
1193 int IPL_EXTERN(close
)(dev_t dev
, int flags
, int devtype
, cred_t
*cp
)
1195 int IPL_EXTERN(close
)(dev
, flags
1196 #if defined(__FreeBSD__)
1200 #elif ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \
1201 (__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL)
1211 #endif /* DragonFly */
1213 #ifdef __DragonFly__
1214 struct cdev
*dev
= ap
->a_head
.a_dev
;
1216 u_int min
= GET_MINOR(dev
);
1218 if (IPL_LOGMAX
< min
)
1227 * both of these must operate with at least splnet() lest they be
1228 * called during packet processing and cause an inconsistancy to appear in
1231 #ifdef __DragonFly__
1232 int IPL_EXTERN(read
)(struct dev_read_args
*ap
)
1235 int IPL_EXTERN(read
)(dev_t dev
, uio_t
*uio
, cred_t
*crp
)
1238 int IPL_EXTERN(read
)(dev
, uio
, ioflag
)
1241 int IPL_EXTERN(read
)(dev
, uio
)
1246 #endif /* DragonFly */
1248 #ifdef __DragonFly__
1249 struct cdev
*dev
= ap
->a_head
.a_dev
;
1250 struct uio
*uio
= ap
->a_uio
;
1252 # ifdef IPFILTER_LOG
1253 return ipflog_read(GET_MINOR(dev
), uio
);
1261 * send_reset - this could conceivably be a call to tcp_respond(), but that
1262 * requires a large amount of setting up and isn't any more efficient.
1264 int send_reset(oip
, fin
)
1268 struct tcphdr
*tcp
, *tcp2
;
1272 ip6_t
*ip6
, *oip6
= (ip6_t
*)oip
;
1276 tcp
= (struct tcphdr
*)fin
->fin_dp
;
1277 if (tcp
->th_flags
& TH_RST
)
1278 return -1; /* feedback loop */
1279 # if (BSD < 199306) || defined(__sgi)
1280 m
= m_get(M_DONTWAIT
, MT_HEADER
);
1281 # elif defined(__DragonFly__)
1282 m
= m_gethdr(MB_DONTWAIT
, MT_HEADER
);
1284 m
= m_gethdr(M_DONTWAIT
, MT_HEADER
);
1291 tlen
= fin
->fin_dlen
- (tcp
->th_off
<< 2) +
1292 ((tcp
->th_flags
& TH_SYN
) ? 1 : 0) +
1293 ((tcp
->th_flags
& TH_FIN
) ? 1 : 0);
1296 hlen
= (fin
->fin_v
== 6) ? sizeof(ip6_t
) : sizeof(ip_t
);
1298 hlen
= sizeof(ip_t
);
1300 m
->m_len
= sizeof(*tcp2
) + hlen
;
1302 m
->m_data
+= max_linkhdr
;
1303 m
->m_pkthdr
.len
= m
->m_len
;
1304 m
->m_pkthdr
.rcvif
= (struct ifnet
*)0;
1306 ip
= mtod(m
, struct ip
*);
1310 bzero((char *)ip
, sizeof(*tcp2
) + hlen
);
1311 tcp2
= (struct tcphdr
*)((char *)ip
+ hlen
);
1313 tcp2
->th_sport
= tcp
->th_dport
;
1314 tcp2
->th_dport
= tcp
->th_sport
;
1315 if (tcp
->th_flags
& TH_ACK
) {
1316 tcp2
->th_seq
= tcp
->th_ack
;
1317 tcp2
->th_flags
= TH_RST
;
1319 tcp2
->th_ack
= ntohl(tcp
->th_seq
);
1320 tcp2
->th_ack
+= tlen
;
1321 tcp2
->th_ack
= htonl(tcp2
->th_ack
);
1322 tcp2
->th_flags
= TH_RST
|TH_ACK
;
1324 tcp2
->th_off
= sizeof(*tcp2
) >> 2;
1326 if (fin
->fin_v
== 6) {
1327 ip6
->ip6_plen
= htons(sizeof(struct tcphdr
));
1328 ip6
->ip6_nxt
= IPPROTO_TCP
;
1329 ip6
->ip6_src
= oip6
->ip6_dst
;
1330 ip6
->ip6_dst
= oip6
->ip6_src
;
1331 tcp2
->th_sum
= in6_cksum(m
, IPPROTO_TCP
,
1332 sizeof(*ip6
), sizeof(*tcp2
));
1333 return send_ip(oip
, fin
, &m
);
1336 ip
->ip_p
= IPPROTO_TCP
;
1337 ip
->ip_len
= htons(sizeof(struct tcphdr
));
1338 ip
->ip_src
.s_addr
= oip
->ip_dst
.s_addr
;
1339 ip
->ip_dst
.s_addr
= oip
->ip_src
.s_addr
;
1340 tcp2
->th_sum
= in_cksum(m
, hlen
+ sizeof(*tcp2
));
1341 ip
->ip_len
= hlen
+ sizeof(*tcp2
);
1342 return send_ip(oip
, fin
, &m
);
1347 * Send an IP(v4/v6) datagram out into the network
1349 static int send_ip(oip
, fin
, mp
)
1354 struct mbuf
*m
= *mp
;
1359 bzero((char *)&frn
, sizeof(frn
));
1360 frn
.fin_ifp
= fin
->fin_ifp
;
1361 frn
.fin_v
= fin
->fin_v
;
1362 frn
.fin_out
= fin
->fin_out
;
1365 ip
= mtod(m
, ip_t
*);
1368 ip
->ip_v
= fin
->fin_v
;
1369 if (ip
->ip_v
== 4) {
1370 ip
->ip_hl
= (sizeof(*oip
) >> 2);
1371 ip
->ip_v
= IPVERSION
;
1372 ip
->ip_tos
= oip
->ip_tos
;
1373 ip
->ip_id
= oip
->ip_id
;
1375 # if defined(__NetBSD__) || \
1376 (defined(__OpenBSD__) && (OpenBSD >= 200012))
1377 if (ip_mtudisc
!= 0)
1381 if (ip
->ip_p
== IPPROTO_TCP
&& tcp_mtudisc
!= 0)
1386 # if (BSD < 199306) || defined(__sgi)
1387 ip
->ip_ttl
= tcp_ttl
;
1389 ip
->ip_ttl
= ip_defttl
;
1392 frn
.fin_dp
= (char *)(ip
+ 1);
1395 else if (ip
->ip_v
== 6) {
1396 ip6_t
*ip6
= (ip6_t
*)ip
;
1398 hlen
= sizeof(*ip6
);
1399 ip6
->ip6_hlim
= 127;
1400 frn
.fin_dp
= (char *)(ip6
+ 1);
1404 m
->m_pkthdr
.rcvif
= NULL
;
1407 if (fr_makefrip(hlen
, ip
, &frn
) == 0)
1408 error
= ipfr_fastroute(m
, mp
, &frn
, NULL
);
1415 int send_icmp_err(oip
, type
, fin
, dst
)
1421 int err
, hlen
= 0, xtra
= 0, iclen
, ohlen
= 0, avail
, code
;
1422 u_short shlen
, slen
= 0, soff
= 0;
1423 struct in_addr dst4
;
1428 ip6_t
*ip6
, *oip6
= (ip6_t
*)oip
;
1429 struct in6_addr dst6
;
1433 if ((type
< 0) || (type
> ICMP_MAXTYPE
))
1436 code
= fin
->fin_icode
;
1438 if ((code
< 0) || (code
> sizeof(icmptoicmp6unreach
)/sizeof(int)))
1445 if (fin
->fin_v
== 4) {
1446 if ((oip
->ip_p
== IPPROTO_ICMP
) &&
1447 !(fin
->fin_fi
.fi_fl
& FI_SHORT
))
1448 switch (ntohs(fin
->fin_data
[0]) >> 8)
1459 # if (BSD < 199306) || defined(__sgi)
1461 m
= m_get(M_DONTWAIT
, MT_HEADER
);
1462 # elif defined(__DragonFly__)
1464 m
= m_gethdr(MB_DONTWAIT
, MT_HEADER
);
1467 m
= m_gethdr(M_DONTWAIT
, MT_HEADER
);
1473 if (fr_ifpaddr(4, ifp
, &dst4
) == -1)
1476 dst4
.s_addr
= oip
->ip_dst
.s_addr
;
1478 hlen
= sizeof(ip_t
);
1479 ohlen
= oip
->ip_hl
<< 2;
1484 else if (fin
->fin_v
== 6) {
1485 hlen
= sizeof(ip6_t
);
1486 ohlen
= sizeof(ip6_t
);
1487 type
= icmptoicmp6types
[type
];
1488 if (type
== ICMP6_DST_UNREACH
)
1489 code
= icmptoicmp6unreach
[code
];
1491 #ifdef __DragonFly__
1492 MGETHDR(m
, MB_DONTWAIT
, MT_HEADER
);
1494 MGETHDR(m
, M_DONTWAIT
, MT_HEADER
);
1499 #ifdef __DragonFly__
1500 MCLGET(m
, MB_DONTWAIT
);
1502 MCLGET(m
, M_DONTWAIT
);
1504 if ((m
->m_flags
& M_EXT
) == 0) {
1508 # ifdef M_TRAILINGSPACE
1510 avail
= M_TRAILINGSPACE(m
);
1512 avail
= (m
->m_flags
& M_EXT
) ? MCLBYTES
: MHLEN
;
1514 xtra
= MIN(ntohs(oip6
->ip6_plen
) + sizeof(ip6_t
),
1515 avail
- hlen
- sizeof(*icmp
) - max_linkhdr
);
1517 if (fr_ifpaddr(6, ifp
, (struct in_addr
*)&dst6
) == -1)
1520 dst6
= oip6
->ip6_dst
;
1524 iclen
= hlen
+ sizeof(*icmp
);
1526 avail
-= (max_linkhdr
+ iclen
);
1527 m
->m_data
+= max_linkhdr
;
1528 m
->m_pkthdr
.rcvif
= (struct ifnet
*)0;
1532 m
->m_pkthdr
.len
= iclen
;
1534 avail
-= (m
->m_off
+ iclen
);
1540 ip
= mtod(m
, ip_t
*);
1541 icmp
= (struct icmp
*)((char *)ip
+ hlen
);
1542 bzero((char *)ip
, iclen
);
1544 icmp
->icmp_type
= type
;
1545 icmp
->icmp_code
= fin
->fin_icode
;
1546 icmp
->icmp_cksum
= 0;
1548 if (type
== ICMP_UNREACH
&&
1549 fin
->fin_icode
== ICMP_UNREACH_NEEDFRAG
&& ifp
)
1550 icmp
->icmp_nextmtu
= htons(((struct ifnet
*) ifp
)->if_mtu
);
1555 oip
->ip_len
= htons(oip
->ip_len
);
1557 oip
->ip_off
= htons(oip
->ip_off
);
1558 bcopy((char *)oip
, (char *)&icmp
->icmp_ip
, MIN(ohlen
, avail
));
1561 avail
-= MIN(ohlen
, avail
);
1566 if (fin
->fin_v
== 6) {
1568 ip6
->ip6_plen
= htons(iclen
- hlen
);
1569 ip6
->ip6_nxt
= IPPROTO_ICMPV6
;
1571 ip6
->ip6_src
= dst6
;
1572 ip6
->ip6_dst
= oip6
->ip6_src
;
1574 bcopy((char *)oip
+ ohlen
,
1575 (char *)&icmp
->icmp_ip
+ ohlen
, avail
);
1576 icmp
->icmp_cksum
= in6_cksum(m
, IPPROTO_ICMPV6
,
1577 sizeof(*ip6
), iclen
- hlen
);
1582 ip
->ip_src
.s_addr
= dst4
.s_addr
;
1583 ip
->ip_dst
.s_addr
= oip
->ip_src
.s_addr
;
1588 bcopy((char *)oip
+ ohlen
,
1589 (char *)&icmp
->icmp_ip
+ ohlen
, avail
);
1590 icmp
->icmp_cksum
= ipf_cksum((u_short
*)icmp
,
1593 ip
->ip_p
= IPPROTO_ICMP
;
1596 shlen
= fin
->fin_hlen
;
1597 fin
->fin_hlen
= hlen
;
1598 err
= send_ip(oip
, fin
, &m
);
1599 fin
->fin_hlen
= shlen
;
1605 # if !defined(IPFILTER_LKM) && !defined(__sgi) && \
1606 (!defined(__DragonFly__) || !defined(__FreeBSD_version) || (__FreeBSD_version < 300000))
1612 void iplinit (void);
1619 # if defined(__NetBSD__) || defined(__OpenBSD__)
1620 if (ipl_enable() != 0)
1622 if (iplattach() != 0)
1625 kprintf("IP Filter failed to attach\n");
1629 # endif /* ! __NetBSD__ */
1633 * Return the length of the entire mbuf.
1635 size_t mbufchainlen(m0
)
1639 return m0
->m_pkthdr
.len
;
1643 for (; m0
; m0
= m0
->m_next
)
1650 int ipfr_fastroute(m0
, mpp
, fin
, fdp
)
1651 struct mbuf
*m0
, **mpp
;
1655 struct ip
*ip
, *mhip
;
1656 struct mbuf
*m
= m0
;
1658 int len
, off
, error
= 0, hlen
, code
, sout
;
1659 struct ifnet
*ifp
, *sifp
;
1660 struct sockaddr_in
*dst
;
1661 struct route iproute
;
1671 if (fin
->fin_v
== 6) {
1672 error
= ipfr_fastroute6(m0
, mpp
, fin
, fdp
);
1678 if (fin
->fin_v
== 6)
1686 * If the mbuf we're about to send is not writable (because of
1687 * a cluster reference, for example) we'll need to make a copy
1688 * of it since this routine modifies the contents.
1690 * If you have non-crappy network hardware that can transmit data
1691 * from the mbuf, rather than making a copy, this is gonna be a
1694 if (M_WRITABLE(m
) == 0) {
1695 #ifdef __DragonFly__
1696 if ((m0
= m_dup(m
, MB_DONTWAIT
)) != NULL
) {
1698 if ((m0
= m_dup(m
, M_DONTWAIT
)) != NULL
) {
1711 hlen
= fin
->fin_hlen
;
1712 ip
= mtod(m0
, struct ip
*);
1714 #if defined(__NetBSD__) && defined(M_CSUM_IPv4)
1716 * Clear any in-bound checksum flags for this packet.
1718 # if (__NetBSD_Version__ > 105009999)
1719 m0
->m_pkthdr
.csum_flags
= 0;
1721 m0
->m_pkthdr
.csuminfo
= 0;
1723 #endif /* __NetBSD__ && M_CSUM_IPv4 */
1728 #if (defined(IRIX) && (IRIX >= 605))
1731 bzero((caddr_t
)ro
, sizeof (*ro
));
1732 dst
= (struct sockaddr_in
*)&ro
->ro_dst
;
1733 dst
->sin_family
= AF_INET
;
1734 dst
->sin_addr
= ip
->ip_dst
;
1743 * In case we're here due to "to <if>" being used with "keep state",
1744 * check that we're going in the correct direction.
1746 if ((fr
!= NULL
) && (fin
->fin_rev
!= 0)) {
1747 if ((ifp
!= NULL
) && (fdp
== &fr
->fr_tif
)) {
1748 # if (defined(IRIX) && (IRIX >= 605))
1753 } else if (fdp
!= NULL
) {
1754 if (fdp
->fd_ip
.s_addr
!= 0)
1755 dst
->sin_addr
= fdp
->fd_ip
;
1759 dst
->sin_len
= sizeof(*dst
);
1761 # if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) && \
1762 !defined(__OpenBSD__)
1764 rtalloc_ign(ro
, RTF_CLONING
);
1766 rtalloc_ign(ro
, RTF_PRCLONING
);
1773 if (!fr
|| !(fr
->fr_flags
& FR_FASTROUTE
)) {
1775 # if (defined(IRIX) && (IRIX >= 605))
1782 if ((ifp
== NULL
) && (ro
->ro_rt
!= NULL
))
1783 ifp
= ro
->ro_rt
->rt_ifp
;
1785 if ((ro
->ro_rt
== NULL
) || (ifp
== NULL
)) {
1786 if (in_localaddr(ip
->ip_dst
))
1787 error
= EHOSTUNREACH
;
1789 error
= ENETUNREACH
;
1790 # if (defined(IRIX) && (IRIX >= 605))
1796 if (ro
->ro_rt
->rt_flags
& RTF_GATEWAY
) {
1797 #if (BSD >= 199306) || (defined(IRIX) && (IRIX >= 605))
1798 dst
= (struct sockaddr_in
*)ro
->ro_rt
->rt_gateway
;
1800 dst
= (struct sockaddr_in
*)&ro
->ro_rt
->rt_gateway
;
1803 ro
->ro_rt
->rt_use
++;
1805 #if (defined(IRIX) && (IRIX > 602))
1810 * For input packets which are being "fastrouted", they won't
1811 * go back through output filtering and miss their chance to get
1812 * NAT'd and counted.
1814 if (fin
->fin_out
== 0) {
1815 sifp
= fin
->fin_ifp
;
1816 sout
= fin
->fin_out
;
1819 if ((fin
->fin_fr
= ipacct
[1][fr_active
]) &&
1820 (fr_scanlist(FR_NOMATCH
, ip
, fin
, m
) & FR_ACCOUNT
)) {
1821 ATOMIC_INCL(frstats
[1].fr_acct
);
1824 if (!fr
|| !(fr
->fr_flags
& FR_RETMASK
))
1825 (void) fr_checkstate(ip
, fin
);
1827 switch (ip_natout(ip
, fin
))
1840 fin
->fin_ifp
= sifp
;
1841 fin
->fin_out
= sout
;
1846 * If small enough for interface, can just send directly.
1848 if (ip
->ip_len
<= ifp
->if_mtu
) {
1850 # if (!defined(__DragonFly__) && !defined(__FreeBSD__) && !(_BSDI_VERSION >= 199510)) && \
1851 !(__NetBSD_Version__ >= 105110000)
1852 ip
->ip_id
= htons(ip
->ip_id
);
1854 ip
->ip_len
= htons(ip
->ip_len
);
1855 ip
->ip_off
= htons(ip
->ip_off
);
1857 # if defined(__NetBSD__) && defined(M_CSUM_IPv4)
1858 # if (__NetBSD_Version__ > 105009999)
1859 if (ifp
->if_csum_flags_tx
& IFCAP_CSUM_IPv4
)
1860 m
->m_pkthdr
.csum_flags
|= M_CSUM_IPv4
;
1861 else if (ip
->ip_sum
== 0)
1862 ip
->ip_sum
= in_cksum(m
, hlen
);
1864 if (ifp
->if_capabilities
& IFCAP_CSUM_IPv4
)
1865 m
->m_pkthdr
.csuminfo
|= M_CSUM_IPv4
;
1866 else if (ip
->ip_sum
== 0)
1867 ip
->ip_sum
= in_cksum(m
, hlen
);
1871 ip
->ip_sum
= in_cksum(m
, hlen
);
1872 # endif /* __NetBSD__ && M_CSUM_IPv4 */
1873 # if (BSD >= 199306) || (defined(IRIX) && (IRIX >= 605))
1875 IFNET_UPPERLOCK(ifp
);
1877 error
= ifp
->if_output(ifp
, m
, (struct sockaddr
*)dst
,
1880 IFNET_UPPERUNLOCK(ifp
);
1883 error
= ifp
->if_output(ifp
, m
, (struct sockaddr
*)dst
);
1889 * Too large for interface; fragment if possible.
1890 * Must be able to put at least 8 bytes per fragment.
1892 if (ip
->ip_off
& IP_DF
) {
1896 len
= (ifp
->if_mtu
- hlen
) &~ 7;
1903 int mhlen
, firstlen
= len
;
1904 struct mbuf
**mnext
= &m
->m_act
;
1907 * Loop through length of segment after first fragment,
1908 * make new header and copy data of each part and link onto chain.
1911 mhlen
= sizeof (struct ip
);
1912 for (off
= hlen
+ len
; off
< ip
->ip_len
; off
+= len
) {
1913 # ifdef __DragonFly__
1914 MGETHDR(m
, MB_DONTWAIT
, MT_HEADER
);
1915 # elif defined(MGETHDR)
1916 MGETHDR(m
, M_DONTWAIT
, MT_HEADER
);
1918 MGET(m
, M_DONTWAIT
, MT_HEADER
);
1925 m
->m_data
+= max_linkhdr
;
1927 m
->m_off
= MMAXOFF
- hlen
;
1929 mhip
= mtod(m
, struct ip
*);
1930 bcopy((char *)ip
, (char *)mhip
, sizeof(*ip
));
1931 if (hlen
> sizeof (struct ip
)) {
1932 mhlen
= ip_optcopy(ip
, mhip
) + sizeof (struct ip
);
1933 mhip
->ip_hl
= mhlen
>> 2;
1936 mhip
->ip_off
= ((off
- hlen
) >> 3) + (ip
->ip_off
& ~IP_MF
);
1937 if (ip
->ip_off
& IP_MF
)
1938 mhip
->ip_off
|= IP_MF
;
1939 if (off
+ len
>= ip
->ip_len
)
1940 len
= ip
->ip_len
- off
;
1942 mhip
->ip_off
|= IP_MF
;
1943 mhip
->ip_len
= htons((u_short
)(len
+ mhlen
));
1944 m
->m_next
= m_copy(m0
, off
, len
);
1945 if (m
->m_next
== 0) {
1946 error
= ENOBUFS
; /* ??? */
1950 m
->m_pkthdr
.len
= mhlen
+ len
;
1951 m
->m_pkthdr
.rcvif
= NULL
;
1953 mhip
->ip_off
= htons((u_short
)mhip
->ip_off
);
1955 mhip
->ip_sum
= in_cksum(m
, mhlen
);
1960 * Update first fragment by trimming what's been copied out
1961 * and updating header, then send each fragment (in order).
1963 m_adj(m0
, hlen
+ firstlen
- ip
->ip_len
);
1964 ip
->ip_len
= htons((u_short
)(hlen
+ firstlen
));
1965 ip
->ip_off
= htons((u_short
)(ip
->ip_off
| IP_MF
));
1967 ip
->ip_sum
= in_cksum(m0
, hlen
);
1969 for (m
= m0
; m
; m
= m0
) {
1973 # if (BSD >= 199306) || (defined(IRIX) && (IRIX >= 605))
1974 error
= ifp
->if_output(ifp
, m
,
1975 (struct sockaddr
*)dst
, ro
->ro_rt
);
1977 error
= ifp
->if_output(ifp
, m
,
1978 (struct sockaddr
*)dst
);
1991 if (ro
->ro_rt
!= NULL
) {
1997 if ((error
== EMSGSIZE
) && (fin
->fin_v
== 4)) {
1998 sifp
= fin
->fin_ifp
;
1999 code
= fin
->fin_icode
;
2000 fin
->fin_icode
= ICMP_UNREACH_NEEDFRAG
;
2002 (void) send_icmp_err(ip
, ICMP_UNREACH
, fin
, 1);
2003 fin
->fin_ifp
= sifp
;
2004 fin
->fin_icode
= code
;
2012 * Return true or false depending on whether the route to the
2013 * given IP address uses the same interface as the one passed.
2015 int fr_verifysrc(ipa
, ifp
)
2019 struct sockaddr_in
*dst
;
2020 struct route iproute
;
2022 bzero((char *)&iproute
, sizeof(iproute
));
2023 dst
= (struct sockaddr_in
*)&iproute
.ro_dst
;
2024 # if (BSD >= 199306)
2025 dst
->sin_len
= sizeof(*dst
);
2027 dst
->sin_family
= AF_INET
;
2028 dst
->sin_addr
= ipa
;
2029 # if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) && \
2030 !defined(__OpenBSD__)
2032 rtalloc_ign(&iproute
, RTF_CLONING
);
2034 rtalloc_ign(&iproute
, RTF_PRCLONING
);
2039 if (iproute
.ro_rt
== NULL
)
2041 return (ifp
== iproute
.ro_rt
->rt_ifp
);
2045 # ifdef USE_GETIFNAME
2050 static char workbuf
[64];
2052 ksprintf(workbuf
, "%s%d", ifp
->if_name
, ifp
->if_unit
);
2058 # if defined(USE_INET6)
2060 * This is the IPv6 specific fastroute code. It doesn't clean up the mbuf's
2061 * or ensure that it is an IPv6 packet that is being forwarded, those are
2062 * expected to be done by the called (ipfr_fastroute).
2064 static int ipfr_fastroute6(m0
, mpp
, fin
, fdp
)
2065 struct mbuf
*m0
, **mpp
;
2069 struct route_in6 ip6route
;
2070 struct sockaddr_in6
*dst6
;
2071 struct route_in6
*ro
;
2074 #if defined(OpenBSD) && (OpenBSD >= 200211)
2075 struct route_in6
*ro_pmtu
= NULL
;
2076 struct in6_addr finaldst
;
2084 bzero((caddr_t
)ro
, sizeof(*ro
));
2085 dst6
= (struct sockaddr_in6
*)&ro
->ro_dst
;
2086 dst6
->sin6_family
= AF_INET6
;
2087 dst6
->sin6_len
= sizeof(struct sockaddr_in6
);
2088 dst6
->sin6_addr
= fin
->fin_fi
.fi_dst
.in6
;
2095 if ((fr
!= NULL
) && (fin
->fin_rev
!= 0)) {
2096 if ((ifp
!= NULL
) && (fdp
== &fr
->fr_tif
))
2098 } else if (fdp
!= NULL
) {
2099 if (IP6_NOTZERO(&fdp
->fd_ip6
))
2100 dst6
->sin6_addr
= fdp
->fd_ip6
.in6
;
2105 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(__OpenBSD__)
2107 if (IN6_IS_ADDR_LINKLOCAL(&dst6
->sin6_addr
))
2108 dst6
->sin6_addr
.s6_addr16
[1] = htons(ifp
->if_index
);
2110 rtalloc((struct route
*)ro
);
2112 if ((ifp
== NULL
) && (ro
->ro_rt
!= NULL
))
2113 ifp
= ro
->ro_rt
->rt_ifp
;
2115 if ((ro
->ro_rt
== NULL
) || (ifp
== NULL
) ||
2116 (ifp
!= ro
->ro_rt
->rt_ifp
)) {
2117 error
= EHOSTUNREACH
;
2119 if (ro
->ro_rt
->rt_flags
& RTF_GATEWAY
)
2120 dst6
= (struct sockaddr_in6
*)ro
->ro_rt
->rt_gateway
;
2121 ro
->ro_rt
->rt_use
++;
2123 #if defined(OpenBSD) && (OpenBSD >= 200211)
2124 ip6
= mtod(m0
, ip6_t
*);
2126 finaldst
= ip6
->ip6_dst
;
2127 error
= ip6_getpmtu(ro_pmtu
, ro
, ifp
, &finaldst
, &mtu
);
2131 mtu
= ND_IFINFO(ifp
)->linkmtu
;
2133 mtu
= nd_ifinfo
[ifp
->if_index
].linkmtu
;
2136 if (m0
->m_pkthdr
.len
<= mtu
)
2137 error
= nd6_output(ifp
, fin
->fin_ifp
, m0
,
2141 #if defined(OpenBSD) && (OpenBSD >= 200211)
2146 if (ro
->ro_rt
!= NULL
) {
2152 #else /* #ifdef _KERNEL */
2155 # if defined(__sgi) && (IRIX < 605)
2156 static int no_output (struct ifnet
*ifp
, struct mbuf
*m
,
2159 static int no_output (struct ifnet
*ifp
, struct mbuf
*m
,
2160 struct sockaddr
*s
, struct rtentry
*rt
)
2168 # if defined(__sgi) && (IRIX < 605)
2169 static int write_output (struct ifnet
*ifp
, struct mbuf
*m
,
2172 static int write_output (struct ifnet
*ifp
, struct mbuf
*m
,
2173 struct sockaddr
*s
, struct rtentry
*rt
)
2176 ip_t
*ip
= (ip_t
*)m
;
2178 static int write_output(ifp
, ip
)
2186 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
2187 (defined(OpenBSD) && (OpenBSD >= 199603)) || \
2188 (defined(__DragonFly__))
2189 ksprintf(fname
, "%s", ifp
->if_xname
);
2191 ksprintf(fname
, "%s%d", ifp
->if_name
, ifp
->if_unit
);
2193 fd
= open(fname
, O_WRONLY
|O_APPEND
);
2198 write(fd
, (char *)ip
, ntohs(ip
->ip_len
));
2204 char *get_ifname(ifp
)
2207 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
2208 (defined(OpenBSD) && (OpenBSD >= 199603)) || \
2209 (defined(__DragonFly__))
2210 return ifp
->if_xname
;
2212 static char fullifname
[LIFNAMSIZ
];
2214 ksprintf(fullifname
, "%s%d", ifp
->if_name
, ifp
->if_unit
);
2220 struct ifnet
*get_unit(ifname
, v
)
2224 struct ifnet
*ifp
, **ifa
, **old_ifneta
;
2226 for (ifa
= ifneta
; ifa
&& (ifp
= *ifa
); ifa
++) {
2227 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
2228 (defined(OpenBSD) && (OpenBSD >= 199603)) || \
2229 (defined(__DragonFly__))
2230 if (!strncmp(ifname
, ifp
->if_xname
, sizeof(ifp
->if_xname
)))
2232 char fullname
[LIFNAMSIZ
];
2234 ksprintf(fullname
, "%s%d", ifp
->if_name
, ifp
->if_unit
);
2235 if (!strcmp(ifname
, fullname
))
2241 ifneta
= (struct ifnet
**)malloc(sizeof(ifp
) * 2);
2245 ifneta
[0] = (struct ifnet
*)calloc(1, sizeof(*ifp
));
2252 old_ifneta
= ifneta
;
2254 ifneta
= (struct ifnet
**)realloc(ifneta
,
2255 (nifs
+ 1) * sizeof(*ifa
));
2261 ifneta
[nifs
] = NULL
;
2262 ifneta
[nifs
- 1] = (struct ifnet
*)malloc(sizeof(*ifp
));
2263 if (!ifneta
[nifs
- 1]) {
2268 ifp
= ifneta
[nifs
- 1];
2270 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
2271 (defined(OpenBSD) && (OpenBSD >= 199603)) || \
2272 (defined(__DragonFly__))
2273 strncpy(ifp
->if_xname
, ifname
, sizeof(ifp
->if_xname
));
2275 ifp
->if_name
= strdup(ifname
);
2277 ifname
= ifp
->if_name
;
2278 while (*ifname
&& !isdigit(*ifname
))
2280 if (*ifname
&& isdigit(*ifname
)) {
2281 ifp
->if_unit
= atoi(ifname
);
2286 ifp
->if_output
= no_output
;
2294 struct ifnet
*ifp
, **ifa
;
2298 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
2299 (defined(OpenBSD) && (OpenBSD >= 199603)) || \
2300 (defined(__DragonFly__))
2301 for (ifa
= ifneta
; ifa
&& (ifp
= *ifa
); ifa
++) {
2302 ifp
->if_output
= write_output
;
2303 ksprintf(fname
, "/tmp/%s", ifp
->if_xname
);
2304 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_TRUNC
, 0600);
2312 for (ifa
= ifneta
; ifa
&& (ifp
= *ifa
); ifa
++) {
2313 ifp
->if_output
= write_output
;
2314 ksprintf(fname
, "/tmp/%s%d", ifp
->if_name
, ifp
->if_unit
);
2315 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_TRUNC
, 0600);
2325 int send_reset(ip
, fin
)
2329 verbose("- TCP RST sent\n");
2334 int send_icmp_err(ip
, code
, fin
, dst
)
2340 verbose("- ICMP UNREACHABLE sent\n");
2350 void m_copydata(m
, off
, len
, cp
)
2355 bcopy((char *)m
+ off
, cp
, len
);
2359 int ipfuiomove(buf
, len
, rwflag
, uio
)
2364 int left
, ioc
, num
, offset
;
2368 if (rwflag
== UIO_READ
) {
2372 offset
= uio
->uio_offset
;
2374 while ((left
> 0) && (ioc
< uio
->uio_iovcnt
)) {
2375 io
= uio
->uio_iov
+ ioc
;
2379 start
= (char *)io
->iov_base
+ offset
;
2380 if (start
> (char *)io
->iov_base
+ io
->iov_len
) {
2381 offset
-= io
->iov_len
;
2385 bcopy(buf
, start
, num
);
2386 uio
->uio_resid
-= num
;
2387 uio
->uio_offset
+= num
;
2397 #endif /* _KERNEL */