2 * Copyright (C) 1993-1998 by Darren Reed.
4 * Redistribution and use in source and binary forms are permitted
5 * provided that this notice is preserved and due credit is given
6 * to the original author and the contributors.
9 static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-1995 Darren Reed";
10 static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.4.2.7 1999/10/15 13:49:43 darrenr Exp $";
14 #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
17 #if defined(KERNEL) && !defined(_KERNEL)
20 #include <sys/param.h>
21 #if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
23 # include "opt_ipfilter_log.h"
26 # if defined(_KERNEL) && !defined(IPFILTER_LKM)
27 # include <sys/osreldate.h>
29 # include <osreldate.h>
39 #include <sys/errno.h>
40 #include <sys/types.h>
42 #if __FreeBSD_version >= 220000 && defined(_KERNEL)
43 # include <sys/fcntl.h>
44 # include <sys/filio.h>
46 # include <sys/ioctl.h>
50 # include <sys/systm.h>
54 # if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000)
55 # include <sys/dirent.h>
59 # include <sys/mbuf.h>
61 # include <sys/filio.h>
63 #include <sys/protosw.h>
64 #include <sys/socket.h>
70 #if __FreeBSD_version >= 300000
71 # include <net/if_var.h>
72 # if defined(_KERNEL) && !defined(IPFILTER_LKM)
73 # include "opt_ipfilter.h"
77 #include <sys/debug.h>
78 # ifdef IFF_DRVRLOCK /* IRIX6 */
79 #include <sys/hashing.h>
82 #include <net/route.h>
83 #include <netinet/in.h>
84 #if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */
85 # include <netinet/in_var.h>
87 #include <netinet/in_systm.h>
88 #include <netinet/ip.h>
89 #include <netinet/ip_var.h>
90 #include <netinet/tcp.h>
91 #include <netinet/udp.h>
92 #include <netinet/tcpip.h>
93 #include <netinet/ip_icmp.h>
98 #include "netinet/ip_compat.h"
99 #include "netinet/ip_fil.h"
100 #include "netinet/ip_proxy.h"
101 #include "netinet/ip_nat.h"
102 #include "netinet/ip_frag.h"
103 #include "netinet/ip_state.h"
104 #include "netinet/ip_auth.h"
105 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
106 # include <sys/malloc.h>
109 # define MIN(a,b) (((a)<(b))?(a):(b))
111 #if !SOLARIS && defined(_KERNEL) && !defined(__sgi)
112 # include <sys/kernel.h>
113 extern int ip_optcopy __P((struct ip *, struct ip *));
117 extern struct protosw inetsw[];
121 static struct ifnet **ifneta = NULL;
124 # if (BSD < 199306) || defined(__sgi)
130 int ipl_unreach = ICMP_UNREACH_FILTER;
131 u_long ipl_frouteok[2] = {0, 0};
133 static void frzerostats __P((caddr_t));
134 #if defined(__NetBSD__) || defined(__OpenBSD__)
135 static int frrequest __P((int, u_long, caddr_t, int));
137 static int frrequest __P((int, int, caddr_t, int));
140 static int (*fr_savep) __P((ip_t *, int, void *, int, struct mbuf **));
141 static int send_ip __P((struct mbuf *, ip_t *));
143 extern kmutex_t ipf_rw;
146 int ipllog __P((void));
147 void init_ifp __P((void));
149 static int no_output __P((struct ifnet *, struct mbuf *,
151 static int write_output __P((struct ifnet *, struct mbuf *,
154 static int no_output __P((struct ifnet *, struct mbuf *,
155 struct sockaddr *, struct rtentry *));
156 static int write_output __P((struct ifnet *, struct mbuf *,
157 struct sockaddr *, struct rtentry *));
160 #if defined(IPFILTER_LKM)
166 #if (__FreeBSD_version >= 300000) && defined(_KERNEL)
167 struct callout_handle ipfr_slowtimer_ch;
170 #if (_BSDI_VERSION >= 199510) && defined(_KERNEL)
171 # include <sys/device.h>
172 # include <sys/conf.h>
174 struct cfdriver iplcd = {
175 NULL, "ipl", NULL, NULL, DV_DULL, 0
178 struct devsw iplsw = {
180 iplopen, iplclose, iplread, nowrite, iplioctl, noselect, nommap,
181 nostrat, nodump, nopsize, 0,
184 #endif /* _BSDI_VERSION >= 199510 && _KERNEL */
186 #if defined(__NetBSD__) || defined(__OpenBSD__) || (_BSDI_VERSION >= 199701)
187 # include <sys/conf.h>
188 # if defined(NETBSD_PF)
189 # include <net/pfil.h>
191 * We provide the fr_checkp name just to minimize changes later.
193 int (*fr_checkp) __P((ip_t *ip, int hlen, void *ifp, int out, mb_t **mp));
194 # endif /* NETBSD_PF */
195 #endif /* __NetBSD__ */
198 # if defined(IPFILTER_LKM) && !defined(__sgi)
202 if (strcmp(s, "ipl") == 0)
206 # endif /* IPFILTER_LKM */
210 * Try to detect the case when compiling for NetBSD with pseudo-device
212 # if defined(__NetBSD__) && defined(PFIL_HOOKS)
214 ipfilterattach(count)
217 if (iplattach() != 0)
218 printf("IP Filter failed to attach\n");
232 if (ipl_inited || (fr_checkp == fr_check)) {
233 printf("IP Filter: already initialized\n");
241 if (nat_init() == -1)
243 if (fr_stateinit() == -1)
245 if (appr_init() == -1)
249 pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
253 error = ipfilter_sgi_attach();
261 bzero((char *)frcache, sizeof(frcache));
262 fr_savep = fr_checkp;
263 fr_checkp = fr_check;
266 if (fr_pass & FR_PASS)
268 else if (fr_pass & FR_BLOCK)
271 defpass = "no-match -> block";
273 printf("IP Filter: initialized. Default = %s all, Logging = %s\n",
280 printf("%s\n", ipfilter_version);
282 # if (__FreeBSD_version >= 300000) && defined(_KERNEL)
283 ipfr_slowtimer_ch = timeout(ipfr_slowtimer, NULL, hz/2);
285 timeout(ipfr_slowtimer, NULL, hz/2);
293 * Disable the filter by removing the hooks from the IP input/output
298 int s, i = FR_INQUE|FR_OUTQUE;
301 # if (__FreeBSD_version >= 300000)
302 untimeout(ipfr_slowtimer, NULL, ipfr_slowtimer_ch);
305 untimeout(ipfr_slowtimer);
307 untimeout(ipfr_slowtimer, NULL);
314 printf("IP Filter: not initialized\n");
319 fr_checkp = fr_savep;
320 i = frflush(IPL_LOGIPF, i);
324 pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
328 ipfilter_sgi_detach();
342 static void frzerostats(data)
347 bcopy((char *)frstats, (char *)fio.f_st,
348 sizeof(struct filterstats) * 2);
349 fio.f_fin[0] = ipfilter[0][0];
350 fio.f_fin[1] = ipfilter[0][1];
351 fio.f_fout[0] = ipfilter[1][0];
352 fio.f_fout[1] = ipfilter[1][1];
353 fio.f_acctin[0] = ipacct[0][0];
354 fio.f_acctin[1] = ipacct[0][1];
355 fio.f_acctout[0] = ipacct[1][0];
356 fio.f_acctout[1] = ipacct[1][1];
357 fio.f_active = fr_active;
358 fio.f_froute[0] = ipl_frouteok[0];
359 fio.f_froute[1] = ipl_frouteok[1];
360 IWCOPY((caddr_t)&fio, data, sizeof(fio));
361 bzero((char *)frstats, sizeof(*frstats) * 2);
366 * Filter ioctl interface.
369 int IPL_EXTERN(ioctl)(dev_t dev, int cmd, caddr_t data, int mode
371 , cred_t *cp, int *rp
375 int IPL_EXTERN(ioctl)(dev, cmd, data, mode
376 #if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \
377 (__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL)
384 #if defined(__NetBSD__) || defined(__OpenBSD__) || \
385 (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000)
394 #if defined(_KERNEL) && !SOLARIS
397 int error = 0, unit = 0, tmp;
399 #if (BSD >= 199306) && defined(_KERNEL)
400 if ((securelevel >= 2) && (mode & FWRITE))
404 unit = GET_MINOR(dev);
405 if ((IPL_LOGMAX < unit) || (unit < 0))
413 if (unit == IPL_LOGNAT) {
414 error = nat_ioctl(data, cmd, mode);
418 if (unit == IPL_LOGSTATE) {
419 error = fr_state_ioctl(data, cmd, mode);
426 IWCOPY((caddr_t)&iplused[IPL_LOGIPF], (caddr_t)data,
427 sizeof(iplused[IPL_LOGIPF]));
430 #if !defined(IPFILTER_LKM) && defined(_KERNEL)
435 if (!(mode & FWRITE))
438 IRCOPY(data, (caddr_t)&enable, sizeof(enable));
453 if (!(mode & FWRITE))
456 IRCOPY(data, (caddr_t)&fr_flags, sizeof(fr_flags));
459 IWCOPY((caddr_t)&fr_flags, data, sizeof(fr_flags));
465 if (!(mode & FWRITE))
468 error = frrequest(unit, cmd, data, fr_active);
473 if (!(mode & FWRITE))
476 error = frrequest(unit, cmd, data, 1 - fr_active);
479 if (!(mode & FWRITE))
482 bzero((char *)frcache, sizeof(frcache[0]) * 2);
483 *(u_int *)data = fr_active;
484 fr_active = 1 - fr_active;
491 bcopy((char *)frstats, (char *)fio.f_st,
492 sizeof(struct filterstats) * 2);
493 fio.f_fin[0] = ipfilter[0][0];
494 fio.f_fin[1] = ipfilter[0][1];
495 fio.f_fout[0] = ipfilter[1][0];
496 fio.f_fout[1] = ipfilter[1][1];
497 fio.f_acctin[0] = ipacct[0][0];
498 fio.f_acctin[1] = ipacct[0][1];
499 fio.f_acctout[0] = ipacct[1][0];
500 fio.f_acctout[1] = ipacct[1][1];
502 fio.f_active = fr_active;
503 fio.f_froute[0] = ipl_frouteok[0];
504 fio.f_froute[1] = ipl_frouteok[1];
505 fio.f_running = fr_running;
506 fio.f_groups[0][0] = ipfgroups[0][0];
507 fio.f_groups[0][1] = ipfgroups[0][1];
508 fio.f_groups[1][0] = ipfgroups[1][0];
509 fio.f_groups[1][1] = ipfgroups[1][1];
510 fio.f_groups[2][0] = ipfgroups[2][0];
511 fio.f_groups[2][1] = ipfgroups[2][1];
517 fio.f_defpass = fr_pass;
518 strncpy(fio.f_version, ipfilter_version,
519 sizeof(fio.f_version));
520 IWCOPY((caddr_t)&fio, data, sizeof(fio));
524 if (!(mode & FWRITE))
530 if (!(mode & FWRITE))
533 IRCOPY(data, (caddr_t)&tmp, sizeof(tmp));
534 tmp = frflush(unit, tmp);
535 IWCOPY((caddr_t)&tmp, data, sizeof(tmp));
540 if (!(mode & FWRITE))
543 *(int *)data = ipflog_clear(unit);
545 #endif /* IPFILTER_LOG */
547 IWCOPY((caddr_t)ipfr_fragstats(), data, sizeof(ipfrstat_t));
551 if (!(mode & FWRITE)) {
556 error = fr_auth_ioctl(data, cmd, NULL, NULL);
559 if (!(mode & FWRITE))
562 #if defined(_KERNEL) && defined(__sgi)
580 register frentry_t *f;
581 register struct ifnet *ifp;
583 # if defined(__OpenBSD__) || ((NetBSD >= 199511) && (NetBSD < 1991011)) || \
584 (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000))
585 # if (NetBSD >= 199905) || defined(__OpenBSD__)
586 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
588 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
591 for (ifp = ifnet; ifp; ifp = ifp->if_next)
595 WRITE_ENTER(&ipf_mutex);
596 for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next)
597 if (f->fr_ifa == (void *)-1)
598 f->fr_ifa = GETUNIT(f->fr_ifname);
599 for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next)
600 if (f->fr_ifa == (void *)-1)
601 f->fr_ifa = GETUNIT(f->fr_ifname);
602 for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next)
603 if (f->fr_ifa == (void *)-1)
604 f->fr_ifa = GETUNIT(f->fr_ifname);
605 for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next)
606 if (f->fr_ifa == (void *)-1)
607 f->fr_ifa = GETUNIT(f->fr_ifname);
608 RWLOCK_EXIT(&ipf_mutex);
613 void fr_forgetifp(ifp)
616 register frentry_t *f;
618 WRITE_ENTER(&ipf_mutex);
619 for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next)
620 if (f->fr_ifa == ifp)
621 f->fr_ifa = (void *)-1;
622 for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next)
623 if (f->fr_ifa == ifp)
624 f->fr_ifa = (void *)-1;
625 for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next)
626 if (f->fr_ifa == ifp)
627 f->fr_ifa = (void *)-1;
628 for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next)
629 if (f->fr_ifa == ifp)
630 f->fr_ifa = (void *)-1;
631 RWLOCK_EXIT(&ipf_mutex);
636 static int frrequest(unit, req, data, set)
638 #if defined(__NetBSD__) || defined(__OpenBSD__)
646 register frentry_t *fp, *f, **fprev;
647 register frentry_t **ftail;
650 frgroup_t *fg = NULL;
655 IRCOPY(data, (caddr_t)fp, sizeof(*fp));
659 * Check that the group number does exist and that if a head group
660 * has been specified, doesn't exist.
662 if ((req != SIOCZRLST) && fp->fr_grhead &&
663 fr_findgroup((u_int)fp->fr_grhead, fp->fr_flags, unit, set, NULL))
665 if ((req != SIOCZRLST) && fp->fr_group &&
666 !fr_findgroup((u_int)fp->fr_group, fp->fr_flags, unit, set, NULL))
669 in = (fp->fr_flags & FR_INQUE) ? 0 : 1;
671 if (unit == IPL_LOGAUTH)
672 ftail = fprev = &ipauth;
673 else if (fp->fr_flags & FR_ACCOUNT)
674 ftail = fprev = &ipacct[in][set];
675 else if (fp->fr_flags & (FR_OUTQUE|FR_INQUE))
676 ftail = fprev = &ipfilter[in][set];
680 if ((group = fp->fr_group)) {
681 if (!(fg = fr_findgroup(group, fp->fr_flags, unit, set, NULL)))
683 ftail = fprev = fg->fg_start;
686 bzero((char *)frcache, sizeof(frcache[0]) * 2);
688 if (*fp->fr_ifname) {
689 fp->fr_ifa = GETUNIT(fp->fr_ifname);
691 fp->fr_ifa = (void *)-1;
694 if (*fp->fr_oifname) {
695 fp->fr_oifa = GETUNIT(fp->fr_oifname);
697 fp->fr_oifa = (void *)-1;
702 fp->fr_flags &= ~FR_DUP;
703 if (*fdp->fd_ifname) {
704 fdp->fd_ifp = GETUNIT(fdp->fd_ifname);
706 fdp->fd_ifp = (struct ifnet *)-1;
708 fp->fr_flags |= FR_DUP;
712 if (*fdp->fd_ifname) {
713 fdp->fd_ifp = GETUNIT(fdp->fd_ifname);
715 fdp->fd_ifp = (struct ifnet *)-1;
719 * Look for a matching filter rule, but don't include the next or
720 * interface pointer in the comparison (fr_next, fr_ifa).
722 for (; (f = *ftail); ftail = &f->fr_next)
723 if (bcmp((char *)&f->fr_ip, (char *)&fp->fr_ip,
728 * If zero'ing statistics, copy current to caller and zero.
730 if (req == SIOCZRLST) {
733 IWCOPY((caddr_t)f, data, sizeof(*f));
741 if (req != SIOCINAFR && req != SIOCINIFR)
744 else if (fp->fr_hits)
745 while (--fp->fr_hits && (f = *ftail))
750 if (req == SIOCDELFR || req == SIOCRMIFR) {
756 if (fg && fg->fg_head)
757 fg->fg_head->fr_ref--;
758 if (unit == IPL_LOGAUTH)
759 return fr_auth_ioctl(data, req, f, ftail);
761 fr_delgroup((u_int)f->fr_grhead, fp->fr_flags,
763 fixskip(fprev, f, -1);
771 if (unit == IPL_LOGAUTH)
772 return fr_auth_ioctl(data, req, f, ftail);
773 KMALLOC(f, frentry_t *);
775 if (fg && fg->fg_head)
776 fg->fg_head->fr_ref++;
777 bcopy((char *)fp, (char *)f, sizeof(*f));
782 if (req == SIOCINIFR || req == SIOCINAFR)
783 fixskip(fprev, f, 1);
785 if ((group = f->fr_grhead))
786 fg = fr_addgroup(group, f, unit, set);
797 * routines below for saving IP headers to buffer
801 int IPL_EXTERN(open)(dev_t *pdev, int flags, int devtype, cred_t *cp)
803 int IPL_EXTERN(open)(dev_t dev, int flags)
806 int IPL_EXTERN(open)(dev, flags
807 # if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \
808 (__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL)
819 # if defined(__sgi) && defined(_KERNEL)
820 u_int min = geteminor(*pdev);
822 u_int min = GET_MINOR(dev);
825 if (IPL_LOGMAX < min)
834 int IPL_EXTERN(close)(dev_t dev, int flags, int devtype, cred_t *cp)
836 int IPL_EXTERN(close)(dev, flags
837 # if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \
838 (__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL)
849 u_int min = GET_MINOR(dev);
851 if (IPL_LOGMAX < min)
860 * both of these must operate with at least splnet() lest they be
861 * called during packet processing and cause an inconsistancy to appear in
865 int IPL_EXTERN(read)(dev_t dev, uio_t *uio, cred_t *crp)
868 int IPL_EXTERN(read)(dev, uio, ioflag)
871 int IPL_EXTERN(read)(dev, uio)
874 register struct uio *uio;
878 return ipflog_read(GET_MINOR(dev), uio);
886 * send_reset - this could conceivably be a call to tcp_respond(), but that
887 * requires a large amount of setting up and isn't any more efficient.
889 int send_reset(fin, oip)
893 struct tcphdr *tcp, *tcp2;
899 tcp = (struct tcphdr *)fin->fin_dp;
900 if (tcp->th_flags & TH_RST)
901 return -1; /* feedback loop */
902 # if (BSD < 199306) || defined(__sgi)
903 m = m_get(M_DONTWAIT, MT_HEADER);
905 m = m_gethdr(M_DONTWAIT, MT_HEADER);
912 if (tcp->th_flags & TH_SYN)
914 m->m_len = sizeof(*tcp2) + sizeof(*ip);
916 m->m_data += max_linkhdr;
917 m->m_pkthdr.len = m->m_len;
918 m->m_pkthdr.rcvif = (struct ifnet *)0;
920 bzero(mtod(m, char *), sizeof(struct tcpiphdr));
921 ip = mtod(m, struct ip *);
922 tp = mtod(m, struct tcpiphdr *);
923 tcp2 = (struct tcphdr *)((char *)ip + sizeof(*ip));
925 ip->ip_src.s_addr = oip->ip_dst.s_addr;
926 ip->ip_dst.s_addr = oip->ip_src.s_addr;
927 tcp2->th_dport = tcp->th_sport;
928 tcp2->th_sport = tcp->th_dport;
929 tcp2->th_ack = ntohl(tcp->th_seq);
930 tcp2->th_ack += tlen;
931 tcp2->th_ack = htonl(tcp2->th_ack);
932 tcp2->th_off = sizeof(*tcp2) >> 2;
933 tcp2->th_flags = TH_RST|TH_ACK;
934 tp->ti_pr = oip->ip_p;
935 tp->ti_len = htons(sizeof(struct tcphdr));
936 tcp2->th_sum = in_cksum(m, sizeof(*ip) + sizeof(*tcp2));
938 ip->ip_tos = oip->ip_tos;
939 ip->ip_p = oip->ip_p;
940 ip->ip_len = sizeof(*ip) + sizeof(*tcp2);
942 return send_ip(m, ip);
946 static int send_ip(m, ip)
950 # if (defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)) || \
951 (defined(_BSDI_VERSION) && (_BSDI_VERSION >= 199802))
955 # if (BSD < 199306) || defined(__sgi)
956 ip->ip_ttl = tcp_ttl;
958 ip->ip_ttl = ip_defttl;
961 # if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
965 bzero((char *)&ro, sizeof(ro));
966 err = ip_output(m, (struct mbuf *)0, &ro, 0, 0);
973 * extra 0 in case of multicast
975 # if _BSDI_VERSION >= 199802
976 return ip_output(m, (struct mbuf *)0, &ro, 0, 0, NULL);
978 return ip_output(m, (struct mbuf *)0, 0, 0, 0);
984 int send_icmp_err(oip, type, code, ifp, dst)
994 # if (BSD < 199306) || defined(__sgi)
995 m = m_get(M_DONTWAIT, MT_HEADER);
997 m = m_gethdr(M_DONTWAIT, MT_HEADER);
1001 m->m_len = sizeof(*nip) + sizeof(*icmp) + 8;
1003 m->m_data += max_linkhdr;
1004 m->m_pkthdr.len = sizeof(*nip) + sizeof(*icmp) + 8;
1005 m->m_pkthdr.rcvif = (struct ifnet *)0;
1008 bzero(mtod(m, char *), (size_t)sizeof(*nip) + sizeof(*icmp) + 8);
1009 nip = mtod(m, ip_t *);
1010 icmp = (struct icmp *)(nip + 1);
1012 nip->ip_v = IPVERSION;
1013 nip->ip_hl = (sizeof(*nip) >> 2);
1014 nip->ip_p = IPPROTO_ICMP;
1015 nip->ip_id = oip->ip_id;
1018 nip->ip_tos = oip->ip_tos;
1019 nip->ip_len = sizeof(*nip) + sizeof(*icmp) + 8;
1020 if (dst.s_addr == 0) {
1021 if (fr_ifpaddr(ifp, &dst) == -1)
1023 dst.s_addr = htonl(dst.s_addr);
1026 nip->ip_dst = oip->ip_src;
1028 icmp->icmp_type = type;
1029 icmp->icmp_code = code;
1030 icmp->icmp_cksum = 0;
1031 bcopy((char *)oip, (char *)&icmp->icmp_ip, sizeof(*oip));
1032 bcopy((char *)oip + (oip->ip_hl << 2),
1033 (char *)&icmp->icmp_ip + sizeof(*oip), 8); /* 64 bits */
1036 register u_short __iplen, __ipoff;
1037 ip_t *ip = &icmp->icmp_ip;
1039 __iplen = ip->ip_len;
1040 __ipoff = ip->ip_off;
1041 ip->ip_len = htons(__iplen);
1042 ip->ip_off = htons(__ipoff);
1045 icmp->icmp_cksum = ipf_cksum((u_short *)icmp, sizeof(*icmp) + 8);
1046 return send_ip(m, nip);
1050 # if !defined(IPFILTER_LKM) && (__FreeBSD_version < 300000) && !defined(__sgi)
1052 int iplinit __P((void));
1056 void iplinit __P((void));
1062 if (iplattach() != 0)
1063 printf("IP Filter failed to attach\n");
1066 # endif /* ! __NetBSD__ */
1069 size_t mbufchainlen(m0)
1070 register struct mbuf *m0;
1072 register size_t len = 0;
1074 for (; m0; m0 = m0->m_next)
1080 int ipfr_fastroute(m0, fin, fdp)
1085 register struct ip *ip, *mhip;
1086 register struct mbuf *m = m0;
1087 register struct route *ro;
1088 int len, off, error = 0, hlen;
1089 struct sockaddr_in *dst;
1090 struct route iproute;
1094 hlen = fin->fin_hlen;
1095 ip = mtod(m0, struct ip *);
1100 bzero((caddr_t)ro, sizeof (*ro));
1101 dst = (struct sockaddr_in *)&ro->ro_dst;
1102 dst->sin_family = AF_INET;
1107 * In case we're here due to "to <if>" being used with "keep state",
1108 * check that we're going in the correct direction.
1110 if ((fr != NULL) && (ifp != NULL) && (fin->fin_rev != 0) &&
1111 (fdp == &fr->fr_tif))
1114 dst->sin_len = sizeof(*dst);
1116 # if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) && \
1117 !defined(__OpenBSD__)
1119 rtalloc_ign(ro, RTF_CLONING);
1121 rtalloc_ign(ro, RTF_PRCLONING);
1127 if (!(fin->fin_fr->fr_flags & FR_FASTROUTE)) {
1131 if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) {
1132 if (in_localaddr(ip->ip_dst))
1133 error = EHOSTUNREACH;
1135 error = ENETUNREACH;
1138 if (ro->ro_rt->rt_flags & RTF_GATEWAY)
1139 dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway;
1142 ro->ro_rt->rt_use++;
1145 * For input packets which are being "fastrouted", they won't
1146 * go back through output filtering and miss their chance to get
1147 * NAT'd and counted.
1150 if (fin->fin_out == 0) {
1152 if ((fin->fin_fr = ipacct[1][fr_active]) &&
1153 (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
1154 ATOMIC_INC(frstats[1].fr_acct);
1157 (void) fr_checkstate(ip, fin);
1158 (void) ip_natout(ip, fin);
1162 * If small enough for interface, can just send directly.
1164 if (ip->ip_len <= ifp->if_mtu) {
1166 ip->ip_id = htons(ip->ip_id);
1167 ip->ip_len = htons(ip->ip_len);
1168 ip->ip_off = htons(ip->ip_off);
1171 ip->ip_sum = in_cksum(m, hlen);
1173 error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
1176 error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst);
1181 * Too large for interface; fragment if possible.
1182 * Must be able to put at least 8 bytes per fragment.
1184 if (ip->ip_off & IP_DF) {
1188 len = (ifp->if_mtu - hlen) &~ 7;
1195 int mhlen, firstlen = len;
1196 struct mbuf **mnext = &m->m_act;
1199 * Loop through length of segment after first fragment,
1200 * make new header and copy data of each part and link onto chain.
1203 mhlen = sizeof (struct ip);
1204 for (off = hlen + len; off < ip->ip_len; off += len) {
1206 MGETHDR(m, M_DONTWAIT, MT_HEADER);
1208 MGET(m, M_DONTWAIT, MT_HEADER);
1215 m->m_data += max_linkhdr;
1217 m->m_off = MMAXOFF - hlen;
1219 mhip = mtod(m, struct ip *);
1220 bcopy((char *)ip, (char *)mhip, sizeof(*ip));
1221 if (hlen > sizeof (struct ip)) {
1222 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
1223 mhip->ip_hl = mhlen >> 2;
1226 mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
1227 if (ip->ip_off & IP_MF)
1228 mhip->ip_off |= IP_MF;
1229 if (off + len >= ip->ip_len)
1230 len = ip->ip_len - off;
1232 mhip->ip_off |= IP_MF;
1233 mhip->ip_len = htons((u_short)(len + mhlen));
1234 m->m_next = m_copy(m0, off, len);
1235 if (m->m_next == 0) {
1236 error = ENOBUFS; /* ??? */
1240 mhip->ip_off = htons((u_short)mhip->ip_off);
1243 mhip->ip_sum = in_cksum(m, mhlen);
1248 * Update first fragment by trimming what's been copied out
1249 * and updating header, then send each fragment (in order).
1251 m_adj(m0, hlen + firstlen - ip->ip_len);
1252 ip->ip_len = htons((u_short)(hlen + firstlen));
1253 ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
1255 ip->ip_sum = in_cksum(m0, hlen);
1257 for (m = m0; m; m = m0) {
1262 error = (*ifp->if_output)(ifp, m,
1263 (struct sockaddr *)dst, ro->ro_rt);
1265 error = (*ifp->if_output)(ifp, m,
1266 (struct sockaddr *)dst);
1285 #else /* #ifdef _KERNEL */
1289 static int no_output __P((struct ifnet *ifp, struct mbuf *m,
1290 struct sockaddr *s))
1292 static int no_output __P((struct ifnet *ifp, struct mbuf *m,
1293 struct sockaddr *s, struct rtentry *rt))
1302 static int write_output __P((struct ifnet *ifp, struct mbuf *m,
1303 struct sockaddr *s))
1305 static int write_output __P((struct ifnet *ifp, struct mbuf *m,
1306 struct sockaddr *s, struct rtentry *rt))
1309 ip_t *ip = (ip_t *)m;
1311 static int write_output(ifp, ip)
1319 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
1320 (defined(OpenBSD) && (OpenBSD >= 199603))
1321 sprintf(fname, "/tmp/%s", ifp->if_xname);
1323 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
1325 fd = open(fname, O_WRONLY|O_APPEND);
1330 write(fd, (char *)ip, ntohs(ip->ip_len));
1336 struct ifnet *get_unit(name)
1339 struct ifnet *ifp, **ifa;
1340 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
1341 (defined(OpenBSD) && (OpenBSD >= 199603))
1342 for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
1343 if (!strcmp(name, ifp->if_xname))
1347 char ifname[32], *s;
1349 for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
1350 (void) sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
1351 if (!strcmp(name, ifname))
1357 ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
1359 ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
1363 ifneta = (struct ifnet **)realloc(ifneta,
1364 (nifs + 1) * sizeof(*ifa));
1365 ifneta[nifs] = NULL;
1366 ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
1368 ifp = ifneta[nifs - 1];
1370 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
1371 (defined(OpenBSD) && (OpenBSD >= 199603))
1372 strncpy(ifp->if_xname, name, sizeof(ifp->if_xname));
1374 for (s = name; *s && !isdigit(*s); s++)
1376 if (*s && isdigit(*s)) {
1377 ifp->if_unit = atoi(s);
1378 ifp->if_name = (char *)malloc(s - name + 1);
1379 strncpy(ifp->if_name, name, s - name);
1380 ifp->if_name[s - name] = '\0';
1382 ifp->if_name = strdup(name);
1386 ifp->if_output = no_output;
1394 struct ifnet *ifp, **ifa;
1398 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
1399 (defined(OpenBSD) && (OpenBSD >= 199603))
1400 for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
1401 ifp->if_output = write_output;
1402 sprintf(fname, "/tmp/%s", ifp->if_xname);
1403 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
1411 for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
1412 ifp->if_output = write_output;
1413 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
1414 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
1424 int ipfr_fastroute(ip, fin, fdp)
1429 struct ifnet *ifp = fdp->fd_ifp;
1432 return 0; /* no routing table out here */
1434 ip->ip_len = htons((u_short)ip->ip_len);
1435 ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
1438 (*ifp->if_output)(ifp, (void *)ip, NULL);
1440 (*ifp->if_output)(ifp, (void *)ip, NULL, 0);
1446 int ipllog __P((void))
1453 int send_reset(ip, ifp)
1457 verbose("- TCP RST sent\n");
1462 int icmp_error(ip, ifp)
1466 verbose("- TCP RST sent\n");
1469 #endif /* _KERNEL */