4 * Copyright (C) 1993-2003 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
9 static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
10 static const char rcsid[] = "@(#)$Id: ip_fil_freebsd.c,v 2.53.2.50 2007/09/20 12:51:50 darrenr Exp $";
13 #if defined(KERNEL) || defined(_KERNEL)
19 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 400000) && \
20 !defined(KLD_MODULE) && !defined(IPFILTER_LKM)
21 # include "opt_inet6.h"
23 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 440000) && \
24 !defined(KLD_MODULE) && !defined(IPFILTER_LKM)
25 # include "opt_random_ip_id.h"
27 #include <sys/param.h>
28 #if defined(__FreeBSD__) && !defined(__FreeBSD_version)
29 # if defined(IPFILTER_LKM)
30 # ifndef __FreeBSD_cc_version
31 # include <osreldate.h>
33 # if __FreeBSD_cc_version < 430000
34 # include <osreldate.h>
39 #include <sys/errno.h>
40 #include <sys/types.h>
42 #if __FreeBSD_version >= 220000
43 # include <sys/fcntl.h>
44 # include <sys/filio.h>
46 # include <sys/ioctl.h>
49 #include <sys/systm.h>
50 #if (__FreeBSD_version >= 300000)
51 # include <sys/dirent.h>
56 # include <sys/mbuf.h>
58 #include <sys/protosw.h>
59 #include <sys/socket.h>
60 #if __FreeBSD_version >= 500043
61 # include <sys/selinfo.h>
63 # include <sys/select.h>
65 #if __FreeBSD_version >= 800044
66 # include <netinet/tcp_var.h>
68 #define V_path_mtu_discovery path_mtu_discovery
69 #define V_ipforwarding ipforwarding
73 #if __FreeBSD_version >= 300000
74 # include <net/if_var.h>
75 # if __FreeBSD_version >= 500043
76 # include <net/netisr.h>
78 # if !defined(IPFILTER_LKM)
79 # include "opt_ipfilter.h"
82 #include <net/route.h>
83 #include <netinet/in.h>
84 #include <netinet/in_var.h>
85 #include <netinet/in_systm.h>
86 #include <netinet/ip.h>
87 #include <netinet/ip_var.h>
88 #include <netinet/tcp.h>
90 # include <netinet/tcp_timer.h>
92 #include <netinet/udp.h>
93 #include <netinet/tcpip.h>
94 #include <netinet/ip_icmp.h>
96 # include "netinet/ipf.h"
98 #include "netinet/ip_compat.h"
100 # include <netinet/icmp6.h>
102 #include "netinet/ip_fil.h"
103 #include "netinet/ip_nat.h"
104 #include "netinet/ip_frag.h"
105 #include "netinet/ip_state.h"
106 #include "netinet/ip_proxy.h"
107 #include "netinet/ip_auth.h"
109 #include "netinet/ip_sync.h"
112 #include "netinet/ip_scan.h"
114 #include "netinet/ip_pool.h"
115 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
116 # include <sys/malloc.h>
118 #include <sys/kernel.h>
119 #ifdef CSUM_DATA_VALID
120 #include <machine/in_cksum.h>
122 extern int ip_optcopy __P((struct ip *, struct ip *));
124 #if (__FreeBSD_version > 460000) && (__FreeBSD_version < 800055)
125 extern int path_mtu_discovery;
128 # ifdef IPFILTER_M_IPFILTER
129 MALLOC_DEFINE(M_IPFILTER, "ipfilter", "IP Filter packet filter data structures");
133 #if !defined(__osf__)
134 extern struct protosw inetsw[];
137 static int (*fr_savep) __P((ip_t *, int, void *, int, struct mbuf **));
138 static int fr_send_ip __P((fr_info_t *, mb_t *, mb_t **));
140 ipfmutex_t ipl_mutex, ipf_authmx, ipf_rw, ipf_stinsert;
141 ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock;
142 ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ipf_frcache, ipf_tokens;
143 ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth;
145 int ipf_locks_done = 0;
147 #if (__FreeBSD_version >= 300000)
148 struct callout_handle fr_slowtimer_ch;
150 struct selinfo ipfselwait[IPL_LOGSIZE];
152 #if (__FreeBSD_version >= 500011)
153 # include <sys/conf.h>
154 # if defined(NETBSD_PF)
155 # include <net/pfil.h>
156 # if (__FreeBSD_version < 501108)
157 # include <netinet/ipprotosw.h>
160 * We provide the fr_checkp name just to minimize changes later.
162 int (*fr_checkp) __P((ip_t *ip, int hlen, void *ifp, int out, mb_t **mp));
163 # endif /* NETBSD_PF */
164 #endif /* __FreeBSD_version >= 500011 */
167 #if (__FreeBSD_version >= 502103)
168 static eventhandler_tag ipf_arrivetag, ipf_departtag, ipf_clonetag;
170 static void ipf_ifevent(void *arg);
172 static void ipf_ifevent(arg)
180 #if (__FreeBSD_version >= 501108) && defined(_KERNEL)
183 fr_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
185 struct ip *ip = mtod(*mp, struct ip *);
186 return fr_check(ip, ip->ip_hl << 2, ifp, (dir == PFIL_OUT), mp);
190 # include <netinet/ip6.h>
193 fr_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
195 return (fr_check(mtod(*mp, struct ip *), sizeof(struct ip6_hdr),
196 ifp, (dir == PFIL_OUT), mp));
199 #endif /* __FreeBSD_version >= 501108 */
200 #if defined(IPFILTER_LKM)
204 if (strcmp(s, "ipl") == 0)
208 #endif /* IPFILTER_LKM */
218 if (fr_running > 0) {
223 MUTEX_INIT(&ipf_rw, "ipf rw mutex");
224 MUTEX_INIT(&ipf_timeoutlock, "ipf timeout queue mutex");
225 RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock");
226 RWLOCK_INIT(&ipf_tokens, "ipf token rwlock");
229 if (fr_initialise() < 0) {
235 if (fr_checkp != fr_check) {
236 fr_savep = fr_checkp;
237 fr_checkp = fr_check;
240 bzero((char *)ipfselwait, sizeof(ipfselwait));
241 bzero((char *)frcache, sizeof(frcache));
244 if (fr_control_forwarding & 1)
248 #if (__FreeBSD_version >= 300000)
249 fr_slowtimer_ch = timeout(fr_slowtimer, NULL,
250 (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT);
252 timeout(fr_slowtimer, NULL, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT);
259 * Disable the filter by removing the hooks from the IP input/output
267 if (fr_control_forwarding & 2)
272 #if (__FreeBSD_version >= 300000)
273 if (fr_slowtimer_ch.callout != NULL)
274 untimeout(fr_slowtimer, NULL, fr_slowtimer_ch);
275 bzero(&fr_slowtimer_ch, sizeof(fr_slowtimer_ch));
277 untimeout(fr_slowtimer, NULL);
281 if (fr_checkp != NULL)
282 fr_checkp = fr_savep;
290 (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE);
291 (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE);
293 if (ipf_locks_done == 1) {
294 MUTEX_DESTROY(&ipf_timeoutlock);
295 MUTEX_DESTROY(&ipf_rw);
296 RW_DESTROY(&ipf_ipidfrag);
297 RW_DESTROY(&ipf_tokens);
308 * Filter ioctl interface.
310 int iplioctl(dev, cmd, data, mode
311 # if defined(_KERNEL) && ((BSD >= 199506) || (__FreeBSD_version >= 220000))
313 # if (__FreeBSD_version >= 500024)
315 # if (__FreeBSD_version >= 500043)
316 # define p_cred td_ucred
317 # define p_uid td_ucred->cr_ruid
319 # define p_cred t_proc->p_cred
320 # define p_uid t_proc->p_cred->p_ruid
324 # define p_uid p_cred->p_ruid
325 # endif /* __FreeBSD_version >= 500024 */
329 #if defined(_KERNEL) && (__FreeBSD_version >= 502116)
338 int error = 0, unit = 0;
341 #if (BSD >= 199306) && defined(_KERNEL)
342 # if (__FreeBSD_version >= 500034)
343 if (securelevel_ge(p->p_cred, 3) && (mode & FWRITE))
345 if ((securelevel >= 3) && (mode & FWRITE))
350 unit = GET_MINOR(dev);
351 if ((IPL_LOGMAX < unit) || (unit < 0))
354 if (fr_running <= 0) {
355 if (unit != IPL_LOGIPF)
357 if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET &&
358 cmd != SIOCIPFSET && cmd != SIOCFRENB &&
359 cmd != SIOCGETFS && cmd != SIOCGETFF)
365 error = fr_ioctlswitch(unit, data, cmd, mode, p->p_uid, p);
378 void fr_forgetifp(ifp)
381 register frentry_t *f;
383 WRITE_ENTER(&ipf_mutex);
384 for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next)
385 if (f->fr_ifa == ifp)
386 f->fr_ifa = (void *)-1;
387 for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next)
388 if (f->fr_ifa == ifp)
389 f->fr_ifa = (void *)-1;
390 for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next)
391 if (f->fr_ifa == ifp)
392 f->fr_ifa = (void *)-1;
393 for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next)
394 if (f->fr_ifa == ifp)
395 f->fr_ifa = (void *)-1;
397 for (f = ipacct6[0][fr_active]; (f != NULL); f = f->fr_next)
398 if (f->fr_ifa == ifp)
399 f->fr_ifa = (void *)-1;
400 for (f = ipacct6[1][fr_active]; (f != NULL); f = f->fr_next)
401 if (f->fr_ifa == ifp)
402 f->fr_ifa = (void *)-1;
403 for (f = ipfilter6[0][fr_active]; (f != NULL); f = f->fr_next)
404 if (f->fr_ifa == ifp)
405 f->fr_ifa = (void *)-1;
406 for (f = ipfilter6[1][fr_active]; (f != NULL); f = f->fr_next)
407 if (f->fr_ifa == ifp)
408 f->fr_ifa = (void *)-1;
410 RWLOCK_EXIT(&ipf_mutex);
417 * routines below for saving IP headers to buffer
419 int iplopen(dev, flags
420 #if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) && defined(_KERNEL)
423 # if (__FreeBSD_version >= 500024)
427 # endif /* __FreeBSD_version >= 500024 */
431 #if defined(_KERNEL) && (__FreeBSD_version >= 502116)
438 u_int min = GET_MINOR(dev);
440 if (IPL_LOGMAX < min)
448 int iplclose(dev, flags
449 #if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) && defined(_KERNEL)
452 # if (__FreeBSD_version >= 500024)
456 # endif /* __FreeBSD_version >= 500024 */
460 #if defined(_KERNEL) && (__FreeBSD_version >= 502116)
467 u_int min = GET_MINOR(dev);
469 if (IPL_LOGMAX < min)
478 * both of these must operate with at least splnet() lest they be
479 * called during packet processing and cause an inconsistancy to appear in
483 int iplread(dev, uio, ioflag)
486 int iplread(dev, uio)
488 #if defined(_KERNEL) && (__FreeBSD_version >= 502116)
493 register struct uio *uio;
495 u_int xmin = GET_MINOR(dev);
503 # ifdef IPFILTER_SYNC
504 if (xmin == IPL_LOGSYNC)
505 return ipfsync_read(uio);
509 return ipflog_read(xmin, uio);
518 * both of these must operate with at least splnet() lest they be
519 * called during packet processing and cause an inconsistancy to appear in
523 int iplwrite(dev, uio, ioflag)
526 int iplwrite(dev, uio)
528 #if defined(_KERNEL) && (__FreeBSD_version >= 502116)
533 register struct uio *uio;
540 if (GET_MINOR(dev) == IPL_LOGSYNC)
541 return ipfsync_write(uio);
548 * fr_send_reset - this could conceivably be a call to tcp_respond(), but that
549 * requires a large amount of setting up and isn't any more efficient.
551 int fr_send_reset(fin)
554 struct tcphdr *tcp, *tcp2;
563 if (tcp->th_flags & TH_RST)
564 return -1; /* feedback loop */
566 if (fr_checkl4sum(fin) == -1)
569 tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) +
570 ((tcp->th_flags & TH_SYN) ? 1 : 0) +
571 ((tcp->th_flags & TH_FIN) ? 1 : 0);
574 hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t);
579 MGETHDR(m, M_DONTWAIT, MT_HEADER);
581 MGET(m, M_DONTWAIT, MT_HEADER);
585 if (sizeof(*tcp2) + hlen > MLEN) {
586 MCLGET(m, M_DONTWAIT);
587 if ((m->m_flags & M_EXT) == 0) {
593 m->m_len = sizeof(*tcp2) + hlen;
595 m->m_data += max_linkhdr;
596 m->m_pkthdr.len = m->m_len;
597 m->m_pkthdr.rcvif = (struct ifnet *)0;
599 ip = mtod(m, struct ip *);
600 bzero((char *)ip, hlen);
604 tcp2 = (struct tcphdr *)((char *)ip + hlen);
605 tcp2->th_sport = tcp->th_dport;
606 tcp2->th_dport = tcp->th_sport;
608 if (tcp->th_flags & TH_ACK) {
609 tcp2->th_seq = tcp->th_ack;
610 tcp2->th_flags = TH_RST;
614 tcp2->th_ack = ntohl(tcp->th_seq);
615 tcp2->th_ack += tlen;
616 tcp2->th_ack = htonl(tcp2->th_ack);
617 tcp2->th_flags = TH_RST|TH_ACK;
620 TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2);
621 tcp2->th_win = tcp->th_win;
626 if (fin->fin_v == 6) {
627 ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow;
628 ip6->ip6_plen = htons(sizeof(struct tcphdr));
629 ip6->ip6_nxt = IPPROTO_TCP;
631 ip6->ip6_src = fin->fin_dst6;
632 ip6->ip6_dst = fin->fin_src6;
633 tcp2->th_sum = in6_cksum(m, IPPROTO_TCP,
634 sizeof(*ip6), sizeof(*tcp2));
635 return fr_send_ip(fin, m, &m);
638 ip->ip_p = IPPROTO_TCP;
639 ip->ip_len = htons(sizeof(struct tcphdr));
640 ip->ip_src.s_addr = fin->fin_daddr;
641 ip->ip_dst.s_addr = fin->fin_saddr;
642 tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2));
643 ip->ip_len = hlen + sizeof(*tcp2);
644 return fr_send_ip(fin, m, &m);
648 static int fr_send_ip(fin, m, mpp)
656 ip = mtod(m, ip_t *);
657 bzero((char *)&fnew, sizeof(fnew));
659 IP_V_A(ip, fin->fin_v);
665 IP_HL_A(ip, sizeof(*oip) >> 2);
666 ip->ip_tos = oip->ip_tos;
667 ip->ip_id = fin->fin_ip->ip_id;
668 #if (__FreeBSD_version > 460000)
669 ip->ip_off = V_path_mtu_discovery ? IP_DF : 0;
673 ip->ip_ttl = V_ip_defttl;
680 ip6_t *ip6 = (ip6_t *)ip;
683 ip6->ip6_hlim = IPDEFTTL;
694 m->m_pkthdr.rcvif = NULL;
697 fnew.fin_ifp = fin->fin_ifp;
698 fnew.fin_flx = FI_NOCKSUM;
702 fnew.fin_hlen = hlen;
703 fnew.fin_dp = (char *)ip + hlen;
704 (void) fr_makefrip(hlen, ip, &fnew);
706 return fr_fastroute(m, mpp, &fnew, NULL);
710 int fr_send_icmp_err(type, fin, dst)
715 int err, hlen, xtra, iclen, ohlen, avail, code;
722 struct in6_addr dst6;
726 if ((type < 0) || (type >= ICMP_MAXTYPE))
729 code = fin->fin_icode;
731 if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int)))
735 if (fr_checkl4sum(fin) == -1)
738 MGETHDR(m, M_DONTWAIT, MT_HEADER);
740 MGET(m, M_DONTWAIT, MT_HEADER);
750 if (fin->fin_v == 4) {
751 if ((fin->fin_p == IPPROTO_ICMP) &&
752 !(fin->fin_flx & FI_SHORT))
753 switch (ntohs(fin->fin_data[0]) >> 8)
766 if (fr_ifpaddr(4, FRI_NORMAL, ifp,
767 &dst4, NULL) == -1) {
772 dst4.s_addr = fin->fin_daddr;
775 ohlen = fin->fin_hlen;
776 if (fin->fin_hlen < fin->fin_plen)
777 xtra = MIN(fin->fin_dlen, 8);
783 else if (fin->fin_v == 6) {
784 hlen = sizeof(ip6_t);
785 ohlen = sizeof(ip6_t);
786 type = icmptoicmp6types[type];
787 if (type == ICMP6_DST_UNREACH)
788 code = icmptoicmp6unreach[code];
790 if (hlen + sizeof(*icmp) + max_linkhdr +
791 fin->fin_plen > avail) {
792 MCLGET(m, M_DONTWAIT);
793 if ((m->m_flags & M_EXT) == 0) {
799 xtra = MIN(fin->fin_plen,
800 avail - hlen - sizeof(*icmp) - max_linkhdr);
802 if (fr_ifpaddr(6, FRI_NORMAL, ifp,
803 (struct in_addr *)&dst6, NULL) == -1) {
808 dst6 = fin->fin_dst6;
816 iclen = hlen + sizeof(*icmp);
817 avail -= (max_linkhdr + iclen);
825 m->m_data += max_linkhdr;
826 m->m_pkthdr.rcvif = (struct ifnet *)0;
827 m->m_pkthdr.len = iclen;
829 ip = mtod(m, ip_t *);
830 icmp = (struct icmp *)((char *)ip + hlen);
831 ip2 = (ip_t *)&icmp->icmp_ip;
833 icmp->icmp_type = type;
834 icmp->icmp_code = fin->fin_icode;
835 icmp->icmp_cksum = 0;
837 if (type == ICMP_UNREACH &&
838 fin->fin_icode == ICMP_UNREACH_NEEDFRAG && ifp)
839 icmp->icmp_nextmtu = htons(((struct ifnet *)ifp)->if_mtu);
842 bcopy((char *)fin->fin_ip, (char *)ip2, ohlen);
846 if (fin->fin_v == 6) {
847 ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow;
848 ip6->ip6_plen = htons(iclen - hlen);
849 ip6->ip6_nxt = IPPROTO_ICMPV6;
852 ip6->ip6_dst = fin->fin_src6;
854 bcopy((char *)fin->fin_ip + ohlen,
855 (char *)&icmp->icmp_ip + ohlen, xtra);
856 icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6,
857 sizeof(*ip6), iclen - hlen);
861 ip2->ip_len = htons(ip2->ip_len);
862 ip2->ip_off = htons(ip2->ip_off);
863 ip->ip_p = IPPROTO_ICMP;
864 ip->ip_src.s_addr = dst4.s_addr;
865 ip->ip_dst.s_addr = fin->fin_saddr;
868 bcopy((char *)fin->fin_ip + ohlen,
869 (char *)&icmp->icmp_ip + ohlen, xtra);
870 icmp->icmp_cksum = ipf_cksum((u_short *)icmp,
873 ip->ip_p = IPPROTO_ICMP;
875 err = fr_send_ip(fin, m, &m);
880 #if !defined(IPFILTER_LKM) && (__FreeBSD_version < 300000)
882 int iplinit __P((void));
886 void iplinit __P((void));
892 if (ipfattach() != 0)
893 printf("IP Filter failed to attach\n");
896 #endif /* __FreeBSD_version < 300000 */
900 * m0 - pointer to mbuf where the IP packet starts
901 * mpp - pointer to the mbuf pointer that is the start of the mbuf chain
903 int fr_fastroute(m0, mpp, fin, fdp)
908 register struct ip *ip, *mhip;
909 register struct mbuf *m = *mpp;
910 register struct route *ro;
911 int len, off, error = 0, hlen, code;
912 struct ifnet *ifp, *sifp;
913 struct sockaddr_in *dst;
914 struct route iproute;
924 * If the mbuf we're about to send is not writable (because of
925 * a cluster reference, for example) we'll need to make a copy
926 * of it since this routine modifies the contents.
928 * If you have non-crappy network hardware that can transmit data
929 * from the mbuf, rather than making a copy, this is gonna be a
932 if (M_WRITABLE(m) == 0) {
933 m0 = m_dup(m, M_DONTWAIT);
947 if (fin->fin_v == 6) {
949 * currently "to <if>" and "to <if>:ip#" are not supported
952 #if (__FreeBSD_version >= 490000)
953 return ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL);
955 return ip6_output(m0, NULL, NULL, 0, NULL, NULL);
960 hlen = fin->fin_hlen;
961 ip = mtod(m0, struct ip *);
967 bzero((caddr_t)ro, sizeof (*ro));
968 dst = (struct sockaddr_in *)&ro->ro_dst;
969 dst->sin_family = AF_INET;
970 dst->sin_addr = ip->ip_dst;
978 if ((ifp == NULL) && (!fr || !(fr->fr_flags & FR_FASTROUTE))) {
983 if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0))
984 dst->sin_addr = fdp->fd_ip;
986 dst->sin_len = sizeof(*dst);
989 if ((ifp == NULL) && (ro->ro_rt != NULL))
990 ifp = ro->ro_rt->rt_ifp;
992 if ((ro->ro_rt == NULL) || (ifp == NULL)) {
993 if (in_localaddr(ip->ip_dst))
994 error = EHOSTUNREACH;
999 if (ro->ro_rt->rt_flags & RTF_GATEWAY)
1000 dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
1002 ro->ro_rt->rt_use++;
1005 * For input packets which are being "fastrouted", they won't
1006 * go back through output filtering and miss their chance to get
1007 * NAT'd and counted. Duplicated packets aren't considered to be
1008 * part of the normal packet stream, so do not NAT them or pass
1009 * them through stateful checking, etc.
1011 if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) {
1012 sifp = fin->fin_ifp;
1015 (void) fr_acctpkt(fin, NULL);
1017 if (!fr || !(fr->fr_flags & FR_RETMASK)) {
1020 if (fr_checkstate(fin, &pass) != NULL)
1021 fr_statederef((ipstate_t **)&fin->fin_state);
1024 switch (fr_checknatout(fin, NULL))
1029 fr_natderef((nat_t **)&fin->fin_nat);
1038 fin->fin_ifp = sifp;
1043 * If small enough for interface, can just send directly.
1045 if (ip->ip_len <= ifp->if_mtu) {
1046 ip->ip_len = htons(ip->ip_len);
1047 ip->ip_off = htons(ip->ip_off);
1050 ip->ip_sum = in_cksum(m, hlen);
1051 error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
1056 * Too large for interface; fragment if possible.
1057 * Must be able to put at least 8 bytes per fragment.
1059 ip_off = ntohs(ip->ip_off);
1060 if (ip_off & IP_DF) {
1064 len = (ifp->if_mtu - hlen) &~ 7;
1071 int mhlen, firstlen = len;
1072 struct mbuf **mnext = &m->m_act;
1075 * Loop through length of segment after first fragment,
1076 * make new header and copy data of each part and link onto chain.
1079 mhlen = sizeof (struct ip);
1080 for (off = hlen + len; off < ip->ip_len; off += len) {
1082 MGETHDR(m, M_DONTWAIT, MT_HEADER);
1084 MGET(m, M_DONTWAIT, MT_HEADER);
1091 m->m_data += max_linkhdr;
1092 mhip = mtod(m, struct ip *);
1093 bcopy((char *)ip, (char *)mhip, sizeof(*ip));
1094 if (hlen > sizeof (struct ip)) {
1095 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
1096 IP_HL_A(mhip, mhlen >> 2);
1099 mhip->ip_off = ((off - hlen) >> 3) + ip_off;
1100 if (off + len >= ip->ip_len)
1101 len = ip->ip_len - off;
1103 mhip->ip_off |= IP_MF;
1104 mhip->ip_len = htons((u_short)(len + mhlen));
1106 m->m_next = m_copy(m0, off, len);
1107 if (m->m_next == 0) {
1108 error = ENOBUFS; /* ??? */
1111 m->m_pkthdr.len = mhlen + len;
1112 m->m_pkthdr.rcvif = NULL;
1113 mhip->ip_off = htons((u_short)mhip->ip_off);
1115 mhip->ip_sum = in_cksum(m, mhlen);
1119 * Update first fragment by trimming what's been copied out
1120 * and updating header, then send each fragment (in order).
1122 m_adj(m0, hlen + firstlen - ip->ip_len);
1123 ip->ip_len = htons((u_short)(hlen + firstlen));
1124 ip->ip_off = htons((u_short)IP_MF);
1126 ip->ip_sum = in_cksum(m0, hlen);
1128 for (m = m0; m; m = m0) {
1132 error = (*ifp->if_output)(ifp, m,
1133 (struct sockaddr *)dst, ro);
1144 if ((ro != NULL) && (ro->ro_rt != NULL)) {
1150 if (error == EMSGSIZE) {
1151 sifp = fin->fin_ifp;
1152 code = fin->fin_icode;
1153 fin->fin_icode = ICMP_UNREACH_NEEDFRAG;
1155 (void) fr_send_icmp_err(ICMP_UNREACH, fin, 1);
1156 fin->fin_ifp = sifp;
1157 fin->fin_icode = code;
1164 int fr_verifysrc(fin)
1167 struct sockaddr_in *dst;
1168 struct route iproute;
1170 bzero((char *)&iproute, sizeof(iproute));
1171 dst = (struct sockaddr_in *)&iproute.ro_dst;
1172 dst->sin_len = sizeof(*dst);
1173 dst->sin_family = AF_INET;
1174 dst->sin_addr = fin->fin_src;
1175 in_rtalloc(&iproute, 0);
1176 if (iproute.ro_rt == NULL)
1178 return (fin->fin_ifp == iproute.ro_rt->rt_ifp);
1183 * return the first IP Address associated with an interface
1185 int fr_ifpaddr(v, atype, ifptr, inp, inpmask)
1188 struct in_addr *inp, *inpmask;
1191 struct in6_addr *inp6 = NULL;
1193 struct sockaddr *sock, *mask;
1194 struct sockaddr_in *sin;
1198 if ((ifptr == NULL) || (ifptr == (void *)-1))
1208 bzero((char *)inp, sizeof(struct in6_addr));
1210 #if (__FreeBSD_version >= 300000)
1211 ifa = TAILQ_FIRST(&ifp->if_addrhead);
1213 ifa = ifp->if_addrlist;
1214 #endif /* __FreeBSD_version >= 300000 */
1216 sock = ifa->ifa_addr;
1217 while (sock != NULL && ifa != NULL) {
1218 sin = (struct sockaddr_in *)sock;
1219 if ((v == 4) && (sin->sin_family == AF_INET))
1222 if ((v == 6) && (sin->sin_family == AF_INET6)) {
1223 inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr;
1224 if (!IN6_IS_ADDR_LINKLOCAL(inp6) &&
1225 !IN6_IS_ADDR_LOOPBACK(inp6))
1229 #if (__FreeBSD_version >= 300000)
1230 ifa = TAILQ_NEXT(ifa, ifa_link);
1232 ifa = ifa->ifa_next;
1233 #endif /* __FreeBSD_version >= 300000 */
1235 sock = ifa->ifa_addr;
1238 if (ifa == NULL || sin == NULL)
1241 mask = ifa->ifa_netmask;
1242 if (atype == FRI_BROADCAST)
1243 sock = ifa->ifa_broadaddr;
1244 else if (atype == FRI_PEERADDR)
1245 sock = ifa->ifa_dstaddr;
1252 return fr_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock,
1253 (struct sockaddr_in6 *)mask,
1257 return fr_ifpfillv4addr(atype, (struct sockaddr_in *)sock,
1258 (struct sockaddr_in *)mask, inp, inpmask);
1262 u_32_t fr_newisn(fin)
1266 #if (__FreeBSD_version >= 400000)
1267 newiss = arc4random();
1269 static iss_seq_off = 0;
1274 * Compute the base value of the ISS. It is a hash
1275 * of (saddr, sport, daddr, dport, secret).
1279 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
1280 sizeof(fin->fin_fi.fi_src));
1281 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
1282 sizeof(fin->fin_fi.fi_dst));
1283 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
1285 MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret));
1287 MD5Final(hash, &ctx);
1289 memcpy(&newiss, hash, sizeof(newiss));
1292 * Now increment our "timer", and add it in to
1293 * the computed value.
1296 * XXX TCP_ISSINCR too large to use?
1298 iss_seq_off += 0x00010000;
1299 newiss += iss_seq_off;
1305 /* ------------------------------------------------------------------------ */
1306 /* Function: fr_nextipid */
1307 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */
1308 /* Parameters: fin(I) - pointer to packet information */
1310 /* Returns the next IPv4 ID to use for this packet. */
1311 /* ------------------------------------------------------------------------ */
1312 u_short fr_nextipid(fin)
1315 #ifndef RANDOM_IP_ID
1316 static u_short ipid = 0;
1319 MUTEX_ENTER(&ipf_rw);
1321 MUTEX_EXIT(&ipf_rw);
1332 INLINE void fr_checkv4sum(fin)
1335 #ifdef CSUM_DATA_VALID
1341 if ((fin->fin_flx & FI_NOCKSUM) != 0)
1344 if (fin->fin_cksum != 0)
1354 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
1355 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
1356 sum = m->m_pkthdr.csum_data;
1358 sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
1359 htonl(m->m_pkthdr.csum_data +
1360 fin->fin_ip->ip_len -
1361 (fin->fin_ip->ip_hl << 2) +
1365 fin->fin_flx |= FI_BAD;
1366 fin->fin_cksum = -1;
1373 # ifdef IPFILTER_CKSUM
1375 if (fr_checkl4sum(fin) == -1)
1376 fin->fin_flx |= FI_BAD;
1381 # ifdef IPFILTER_CKSUM
1382 if (fr_checkl4sum(fin) == -1)
1383 fin->fin_flx |= FI_BAD;
1390 INLINE void fr_checkv6sum(fin)
1393 # ifdef IPFILTER_CKSUM
1394 if (fr_checkl4sum(fin) == -1)
1395 fin->fin_flx |= FI_BAD;
1398 #endif /* USE_INET6 */
1401 size_t mbufchainlen(m0)
1406 if ((m0->m_flags & M_PKTHDR) != 0) {
1407 len = m0->m_pkthdr.len;
1411 for (m = m0, len = 0; m != NULL; m = m->m_next)
1418 /* ------------------------------------------------------------------------ */
1419 /* Function: fr_pullup */
1420 /* Returns: NULL == pullup failed, else pointer to protocol header */
1421 /* Parameters: m(I) - pointer to buffer where data packet starts */
1422 /* fin(I) - pointer to packet information */
1423 /* len(I) - number of bytes to pullup */
1425 /* Attempt to move at least len bytes (from the start of the buffer) into a */
1426 /* single buffer for ease of access. Operating system native functions are */
1427 /* used to manage buffers - if necessary. If the entire packet ends up in */
1428 /* a single buffer, set the FI_COALESCE flag even though fr_coalesce() has */
1429 /* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */
1430 /* and ONLY if the pullup succeeds. */
1432 /* We assume that 'min' is a pointer to a buffer that is part of the chain */
1433 /* of buffers that starts at *fin->fin_mp. */
1434 /* ------------------------------------------------------------------------ */
1435 void *fr_pullup(min, fin, len)
1440 int out = fin->fin_out, dpoff, ipoff;
1447 ip = (char *)fin->fin_ip;
1448 if ((fin->fin_flx & FI_COALESCE) != 0)
1451 ipoff = fin->fin_ipoff;
1452 if (fin->fin_dp != NULL)
1453 dpoff = (char *)fin->fin_dp - (char *)ip;
1457 if (M_LEN(m) < len) {
1460 * Assume that M_PKTHDR is set and just work with what is left
1461 * rather than check..
1462 * Should not make any real difference, anyway.
1469 #ifdef HAVE_M_PULLDOWN
1470 if (m_pulldown(m, 0, len, NULL) == NULL)
1473 FREE_MB_T(*fin->fin_mp);
1478 m = m_pullup(m, len);
1483 ATOMIC_INCL(frstats[out].fr_pull[1]);
1487 while (M_LEN(m) == 0) {
1491 ip = MTOD(m, char *) + ipoff;
1494 ATOMIC_INCL(frstats[out].fr_pull[0]);
1495 fin->fin_ip = (ip_t *)ip;
1496 if (fin->fin_dp != NULL)
1497 fin->fin_dp = (char *)fin->fin_ip + dpoff;
1499 if (len == fin->fin_plen)
1500 fin->fin_flx |= FI_COALESCE;
1505 int ipf_inject(fin, m)
1511 if (fin->fin_out == 0) {
1512 #if (__FreeBSD_version >= 501000)
1513 netisr_dispatch(NETISR_IP, m);
1515 struct ifqueue *ifq;
1537 fin->fin_ip->ip_len = ntohs(fin->fin_ip->ip_len);
1538 fin->fin_ip->ip_off = ntohs(fin->fin_ip->ip_off);
1539 #if (__FreeBSD_version >= 470102)
1540 error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL);
1542 error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL);
1549 int ipf_pfil_unhook(void) {
1550 #if defined(NETBSD_PF) && (__FreeBSD_version >= 500011)
1551 # if __FreeBSD_version >= 501108
1552 struct pfil_head *ph_inet;
1554 struct pfil_head *ph_inet6;
1560 # if (__FreeBSD_version >= 500011)
1561 # if (__FreeBSD_version >= 501108)
1562 ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
1563 if (ph_inet != NULL)
1564 pfil_remove_hook((void *)fr_check_wrapper, NULL,
1565 PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet);
1567 pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK,
1568 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
1571 pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK);
1574 # if (__FreeBSD_version >= 501108)
1575 ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
1576 if (ph_inet6 != NULL)
1577 pfil_remove_hook((void *)fr_check_wrapper6, NULL,
1578 PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet6);
1580 pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK,
1581 &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
1589 int ipf_pfil_hook(void) {
1590 #if defined(NETBSD_PF) && (__FreeBSD_version >= 500011)
1591 # if __FreeBSD_version >= 501108
1592 struct pfil_head *ph_inet;
1594 struct pfil_head *ph_inet6;
1600 # if __FreeBSD_version >= 500011
1601 # if __FreeBSD_version >= 501108
1602 ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
1604 ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
1613 if (ph_inet != NULL)
1614 pfil_add_hook((void *)fr_check_wrapper, NULL,
1615 PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet);
1617 pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK,
1618 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
1621 pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK);
1624 # if __FreeBSD_version >= 501108
1625 if (ph_inet6 != NULL)
1626 pfil_add_hook((void *)fr_check_wrapper6, NULL,
1627 PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet6);
1629 pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK,
1630 &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
1640 #if (__FreeBSD_version >= 502103)
1641 ipf_arrivetag = EVENTHANDLER_REGISTER(ifnet_arrival_event, \
1642 ipf_ifevent, NULL, \
1643 EVENTHANDLER_PRI_ANY);
1644 ipf_departtag = EVENTHANDLER_REGISTER(ifnet_departure_event, \
1645 ipf_ifevent, NULL, \
1646 EVENTHANDLER_PRI_ANY);
1647 ipf_clonetag = EVENTHANDLER_REGISTER(if_clone_event, ipf_ifevent, \
1648 NULL, EVENTHANDLER_PRI_ANY);
1653 ipf_event_dereg(void)
1655 #if (__FreeBSD_version >= 502103)
1656 if (ipf_arrivetag != NULL) {
1657 EVENTHANDLER_DEREGISTER(ifnet_arrival_event, ipf_arrivetag);
1659 if (ipf_departtag != NULL) {
1660 EVENTHANDLER_DEREGISTER(ifnet_departure_event, ipf_departtag);
1662 if (ipf_clonetag != NULL) {
1663 EVENTHANDLER_DEREGISTER(if_clone_event, ipf_clonetag);