summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authordm <dm@cvs.openbsd.org>1996-07-18 05:01:10 +0000
committerdm <dm@cvs.openbsd.org>1996-07-18 05:01:10 +0000
commit746e8c40786f598f5da99fed9714ae7961393281 (patch)
tree7fa485ff1f4c0076948de7742853326232fa0cc1 /sys
parent6764f712dd3ffd42fd940f9e87d2a9109743c72d (diff)
ipfilter 3.1.0
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/fil.c135
-rw-r--r--sys/netinet/in_proto.c7
-rw-r--r--sys/netinet/ip_fil.c339
-rw-r--r--sys/netinet/ip_fil.h271
-rw-r--r--sys/netinet/ip_fil_compat.h216
-rw-r--r--sys/netinet/ip_frag.c2
-rw-r--r--sys/netinet/ip_frag.h6
-rw-r--r--sys/netinet/ip_input.c6
-rw-r--r--sys/netinet/ip_nat.c89
-rw-r--r--sys/netinet/ip_nat.h5
-rw-r--r--sys/netinet/ip_state.c27
-rw-r--r--sys/netinet/ip_state.h6
12 files changed, 750 insertions, 359 deletions
diff --git a/sys/netinet/fil.c b/sys/netinet/fil.c
index f84114c3239..4cba4d8af2d 100644
--- a/sys/netinet/fil.c
+++ b/sys/netinet/fil.c
@@ -6,7 +6,8 @@
* to the original author and the contributors.
*/
#ifndef lint
-static char sccsid[] = "@(#)fil.c 1.32 4/10/96 (C) 1993-1996 Darren Reed";
+static char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed";
+static char rcsid[] = "$Id: fil.c,v 1.5 1996/07/18 05:00:55 dm Exp $";
#endif
#include <sys/errno.h>
@@ -45,6 +46,7 @@ static char sccsid[] = "@(#)fil.c 1.32 4/10/96 (C) 1993-1996 Darren Reed";
#include <netinet/tcpip.h>
#include <netinet/ip_icmp.h>
#include "ip_fil.h"
+#include "ip_fil_compat.h"
#include "ip_nat.h"
#include "ip_frag.h"
#include "ip_state.h"
@@ -151,7 +153,7 @@ struct optlist secopt[8] = {
* compact the IP header into a structure which contains just the info.
* which is useful for comparing IP headers with.
*/
-fr_info_t *fr_makefrip(hlen, ip, fin)
+void fr_makefrip(hlen, ip, fin)
int hlen;
ip_t *ip;
fr_info_t *fin;
@@ -163,9 +165,7 @@ fr_info_t *fin;
int i, mv, ol, off;
u_char *s, opt;
- fin->fin_dp = ((char *)ip + hlen);
- tcp = (tcphdr_t *)fin->fin_dp;
- fi->fi_fl = 0;
+ fin->fin_fr = NULL;
fin->fin_tcpf = 0;
fin->fin_data[0] = 0;
fin->fin_data[1] = 0;
@@ -177,12 +177,13 @@ fr_info_t *fin;
fi->fi_tos = ip->ip_tos;
fin->fin_hlen = hlen;
fin->fin_dlen = ip->ip_len - hlen;
+ tcp = (tcphdr_t *)((char *)ip + hlen);
+ fin->fin_dp = (void *)tcp;
(*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4));
(*(((u_long *)fi) + 1)) = (*(((u_long *)ip) + 3));
(*(((u_long *)fi) + 2)) = (*(((u_long *)ip) + 4));
- if (hlen > sizeof(struct ip))
- fi->fi_fl |= FI_OPTIONS;
+ fi->fi_fl = (hlen > sizeof(struct ip)) ? FI_OPTIONS : 0;
off = (ip->ip_off & 0x1fff) << 3;
if (ip->ip_off & 0x3fff)
fi->fi_fl |= FI_FRAG;
@@ -202,21 +203,22 @@ fr_info_t *fin;
fi->fi_fl |= FI_SHORT;
if (!(fi->fi_fl & FI_SHORT) && !off)
fin->fin_tcpf = tcp->th_flags;
- break;
+ goto getports;
case IPPROTO_UDP :
fi->fi_fl |= FI_TCPUDP;
if ((!IPMINLEN(ip, udphdr) && !off) ||
(off && off < sizeof(struct udphdr)))
fi->fi_fl |= FI_SHORT;
+getports:
+ if (!off && (fin->fin_dlen > 3)) {
+ fin->fin_data[0] = ntohs(tcp->th_sport);
+ fin->fin_data[1] = ntohs(tcp->th_dport);
+ }
break;
default :
break;
}
- if ((fi->fi_fl & FI_TCPUDP) && !off && (fin->fin_dlen > 3)) {
- fin->fin_data[0] = ntohs(tcp->th_sport);
- fin->fin_data[1] = ntohs(tcp->th_dport);
- }
for (s = (u_char *)(ip + 1), hlen -= sizeof(*ip); hlen; ) {
if (!(opt = *s))
@@ -264,7 +266,6 @@ fr_info_t *fin;
fi->fi_optmsk = optmsk;
fi->fi_secmsk = secmsk;
fi->fi_auth = auth;
- return fin;
}
@@ -438,10 +439,10 @@ void *m;
continue;
} else if (fi->fi_p == IPPROTO_ICMP) {
if (!off && (fin->fin_dlen > 1)) {
- if ((*(u_short *)fin->fin_dp & fr->fr_icmpm) !=
+ if ((fin->fin_data[0] & fr->fr_icmpm) !=
fr->fr_icmp) {
FR_DEBUG(("i. %#x & %#x != %#x\n",
- *(u_short *)fin->fin_dp,
+ fin->fin_data[0],
fr->fr_icmpm, fr->fr_icmp));
continue;
}
@@ -453,8 +454,10 @@ void *m;
* Just log this packet...
*/
pass = fr->fr_flags;
+ if ((pass & FR_CALLNOW) && fr->fr_func)
+ pass = (*fr->fr_func)(ip, fin);
#ifdef IPFILTER_LOG
- if (pass & FR_LOG) {
+ if ((pass & FR_LOGMASK) == FR_LOG) {
if (!IPLLOG(fr->fr_flags, ip, fin, m))
frstats[fin->fin_out].fr_skip++;
frstats[fin->fin_out].fr_pkl++;
@@ -462,8 +465,6 @@ void *m;
#endif /* IPFILTER_LOG */
FR_DEBUG(("pass %#x\n", pass));
fr->fr_hits++;
- fin->fin_fr = fr;
- fin->fin_rule = rulen;
if (pass & FR_ACCOUNT)
fr->fr_bytes += ip->ip_len;
else
@@ -471,6 +472,8 @@ void *m;
if (pass & FR_QUICK)
break;
}
+ fin->fin_rule = rulen;
+ fin->fin_fr = fr;
return pass;
}
@@ -483,9 +486,10 @@ void *m;
int fr_check(ip, hlen, ifp, out
#ifdef _KERNEL
# if SOLARIS
-, qif, q)
+, qif, q, mb)
qif_t *qif;
queue_t *q;
+mblk_t *mb;
# else
, mp)
struct mbuf **mp;
@@ -501,12 +505,14 @@ int out;
/*
* The above really sucks, but short of writing a diff
*/
- register fr_info_t *fin;
fr_info_t frinfo, *fc;
+ register fr_info_t *fin = &frinfo;
+ frentry_t *fr;
int pass;
#if !defined(__SVR4) && !defined(__svr4__) && defined(_KERNEL)
register struct mbuf *m = *mp;
+ struct mbuf *mc = NULL;
if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ||
ip->ip_p == IPPROTO_ICMP)) {
@@ -522,7 +528,10 @@ int out;
}
}
#endif
- fin = fr_makefrip(hlen, ip, &frinfo);
+#if SOLARIS
+ mblk_t *mc = NULL;
+#endif
+ fr_makefrip(hlen, ip, fin);
fin->fin_ifp = ifp;
fin->fin_out = out;
@@ -552,9 +561,13 @@ int out;
frstats[out].fr_cfr++;
}
} else {
- fc = frcache+out;
+ fc = frcache + out;
if (fc->fin_fr && !bcmp((char *)fin, (char *)fc, FI_CSIZE)) {
- fin = fc;
+ /*
+ * copy cached data so we can unlock the mutex
+ * earlier.
+ */
+ bcopy((char *)fc, (char *)fin, sizeof(*fin));
frstats[out].fr_chit++;
pass = fin->fin_fr->fr_flags;
} else {
@@ -580,13 +593,18 @@ int out;
frstats[out].fr_cfr++;
}
if (pass & FR_KEEPSTATE) {
- if (fr_addstate(ip, hlen, pass) == -1)
+ if (fr_addstate(ip, fin, pass) == -1)
frstats[out].fr_bads++;
else
frstats[out].fr_ads++;
}
}
+ fr = fin->fin_fr;
+
+ if (fr && fr->fr_func)
+ pass = (*fr->fr_func)(pass, ip, fin);
+
if (out) {
if ((fin->fin_fr = ipacct[1][fr_active]) &&
(FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT))
@@ -596,25 +614,26 @@ int out;
MUTEX_EXIT(&ipf_mutex);
#ifdef IPFILTER_LOG
- if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) {
- pass |= FF_LOGNOMATCH;
- if (!IPLLOG(pass, ip, fin, m))
- frstats[out].fr_skip++;
- frstats[out].fr_npkl++;
- } else if (((pass & FR_LOGP) == FR_LOGP) ||
- ((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) {
- if ((pass & FR_LOGP) != FR_LOGP)
- pass |= FF_LOGPASS;
- if (!IPLLOG(pass, ip, fin, m))
- frstats[out].fr_skip++;
- frstats[out].fr_ppkl++;
- } else if (((pass & FR_LOGB) == FR_LOGB) ||
- ((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) {
- if ((pass & FR_LOGB) != FR_LOGB)
- pass |= FF_LOGBLOCK;
- if (!IPLLOG(pass, ip, fin, m))
- frstats[out].fr_skip++;
- frstats[out].fr_bpkl++;
+ if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) {
+ if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) {
+ pass |= FF_LOGNOMATCH;
+ frstats[out].fr_npkl++;
+ goto logit;
+ } else if (((pass & FR_LOGMASK) == FR_LOGP) ||
+ ((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) {
+ if ((pass & FR_LOGMASK) != FR_LOGP)
+ pass |= FF_LOGPASS;
+ frstats[out].fr_ppkl++;
+ goto logit;
+ } else if (((pass & FR_LOGMASK) == FR_LOGB) ||
+ ((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) {
+ if ((pass & FR_LOGMASK) != FR_LOGB)
+ pass |= FF_LOGBLOCK;
+ frstats[out].fr_bpkl++;
+logit:
+ if (!IPLLOG(pass, ip, fin, m))
+ frstats[out].fr_skip++;
+ }
}
#endif /* IPFILTER_LOG */
@@ -638,7 +657,7 @@ int out;
# endif
frstats[0].fr_ret++;
- } else if (pass & FR_RETRST &&
+ } else if ((pass & FR_RETRST) &&
!(fin->fin_fi.fi_fl & FI_SHORT)) {
if (SEND_RESET(ip, qif, q) == 0)
frstats[1].fr_ret++;
@@ -647,7 +666,8 @@ int out;
if (pass & FR_RETICMP) {
verbose("- ICMP unreachable sent\n");
frstats[0].fr_ret++;
- } else if (pass & FR_RETRST && IPMINLEN(ip, tcphdr)) {
+ } else if ((pass & FR_RETRST) &&
+ !(fin->fin_fi.fi_fl & FI_SHORT)) {
verbose("- TCP RST sent\n");
frstats[1].fr_ret++;
}
@@ -655,8 +675,33 @@ int out;
}
#ifdef _KERNEL
# if !SOLARIS
+ if (pass & FR_DUP)
+ mc = m_copy(m, 0, M_COPYALL);
+ if (fr) {
+ frdest_t *fdp = &fr->fr_tif;
+
+ if ((pass & FR_FASTROUTE) ||
+ (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1))
+ ipfr_fastroute(m, fin, fdp);
+ if (mc)
+ ipfr_fastroute(mc, fin, &fr->fr_dif);
+ }
if (!(pass & FR_PASS) && m)
m_freem(m);
+# else
+ /*
+ if (pass & FR_DUP)
+ mc = dupmsg(mb);
+ if (fr) {
+ frdest_t *fdp = &fr->fr_tif;
+
+ if ((pass & FR_FASTROUTE) ||
+ (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1))
+ ipfr_fastroute(mb, fin, fdp);
+ if (mc)
+ ipfr_fastroute(mc, fin, &fr->fr_dif);
+ }
+ */
# endif
return (pass & FR_PASS) ? 0 : -1;
#else
diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c
index 28cca9a2fae..56387aaa7ca 100644
--- a/sys/netinet/in_proto.c
+++ b/sys/netinet/in_proto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_proto.c,v 1.4 1996/04/24 06:00:43 mickey Exp $ */
+/* $OpenBSD: in_proto.c,v 1.5 1996/07/18 05:00:57 dm Exp $ */
/* $NetBSD: in_proto.c,v 1.14 1996/02/18 18:58:32 christos Exp $ */
/*
@@ -89,6 +89,11 @@
#include <netinet/ip_mroute.h>
#endif /* MROUTING */
+#ifdef IPFILTER
+void iplinit();
+#define ip_init iplinit
+#endif
+
extern struct domain inetdomain;
struct protosw inetsw[] = {
diff --git a/sys/netinet/ip_fil.c b/sys/netinet/ip_fil.c
index 9964e1ca030..14379a2c868 100644
--- a/sys/netinet/ip_fil.c
+++ b/sys/netinet/ip_fil.c
@@ -6,7 +6,8 @@
* to the original author and the contributors.
*/
#ifndef lint
-static char sccsid[] = "@(#)ip_fil.c 2.37 4/10/96 (C) 1993-1995 Darren Reed";
+static char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-1995 Darren Reed";
+static char rcsid[] = "$Id: ip_fil.c,v 1.4 1996/07/18 05:00:58 dm Exp $";
#endif
#ifndef linux
@@ -28,6 +29,7 @@ static char sccsid[] = "@(#)ip_fil.c 2.37 4/10/96 (C) 1993-1995 Darren Reed";
#endif
#include <net/route.h>
#include <netinet/in.h>
+#include <netinet/in_var.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
@@ -38,6 +40,7 @@ static char sccsid[] = "@(#)ip_fil.c 2.37 4/10/96 (C) 1993-1995 Darren Reed";
#include <syslog.h>
#endif
#include "ip_fil.h"
+#include "ip_fil_compat.h"
#include "ip_frag.h"
#include "ip_nat.h"
#include "ip_state.h"
@@ -62,7 +65,7 @@ int ipl_unreach = ICMP_UNREACH_FILTER;
int send_reset();
#ifdef IPFILTER_LOG
-#define LOGSIZE 8192
+# define LOGSIZE 8192
int ipllog();
static char iplbuf[LOGSIZE];
static caddr_t iplh = iplbuf, iplt = iplbuf;
@@ -74,17 +77,17 @@ static int iplbusy = 0;
static int (*fr_savep)();
#if _BSDI_VERSION >= 199510
-#include <sys/device.h>
-#include <sys/conf.h>
+# include <sys/device.h>
+# include <sys/conf.h>
int iplioctl __P((dev_t, int, caddr_t, int, struct proc *));
int iplopen __P((dev_t, int, int, struct proc *));
int iplclose __P((dev_t, int, int, struct proc *));
-#ifdef IPFILTER_LOG
+# ifdef IPFILTER_LOG
int iplread __P((dev_t, struct uio *, int));
-#else
-#define iplread noread
-#endif
+# else
+# define iplread noread
+# endif
int iplioctl __P((dev_t, int, caddr_t, int, struct proc *));
struct cfdriver iplcd = {
@@ -97,7 +100,7 @@ struct devsw iplsw = {
nostrat, nodump, nopsize, 0,
nostop
};
-#endif
+#endif /* _BSDI_VERSION >= 199510 */
#ifdef IPFILTER_LKM
int iplidentify(s)
@@ -243,23 +246,32 @@ int mode;
SPLNET(s);
switch (cmd) {
case FIONREAD :
+#ifdef IPFILTER_LOG
*(int *)data = iplused;
+#endif
break;
#ifndef IPFILTER_LKM
case SIOCFRENB :
{
u_int enable;
- IRCOPY(data, (caddr_t)&enable, sizeof(enable));
- if (enable)
- error = iplattach();
- else
- error = ipldetach();
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else {
+ IRCOPY(data, (caddr_t)&enable, sizeof(enable));
+ if (enable)
+ error = iplattach();
+ else
+ error = ipldetach();
+ }
break;
}
#endif
case SIOCSETFF :
- IRCOPY(data, (caddr_t)&fr_flags, sizeof(fr_flags));
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else
+ IRCOPY(data, (caddr_t)&fr_flags, sizeof(fr_flags));
break;
case SIOCGETFF :
IWCOPY((caddr_t)&fr_flags, data, sizeof(fr_flags));
@@ -267,17 +279,28 @@ int mode;
case SIOCINAFR :
case SIOCRMAFR :
case SIOCADAFR :
- error = frrequest(cmd, (struct frentry *)data, fr_active);
+ case SIOCZRLST :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else
+ error = frrequest(cmd, data, fr_active);
break;
case SIOCINIFR :
case SIOCRMIFR :
case SIOCADIFR :
- error = frrequest(cmd, (struct frentry *)data, 1-fr_active);
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else
+ error = frrequest(cmd, data, 1 - fr_active);
break;
case SIOCSWAPA :
- bzero((char *)frcache, sizeof(frcache[0]) * 2);
- *(u_int *)data = fr_active;
- fr_active = 1 - fr_active;
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else {
+ bzero((char *)frcache, sizeof(frcache[0]) * 2);
+ *(u_int *)data = fr_active;
+ fr_active = 1 - fr_active;
+ }
break;
case SIOCGETFS :
{
@@ -298,23 +321,35 @@ int mode;
break;
}
case SIOCFRZST :
- frzerostats(data);
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else
+ frzerostats(data);
break;
case SIOCIPFFL :
- frflush(data);
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else
+ frflush(data);
break;
#ifdef IPFILTER_LOG
case SIOCIPFFB :
- *(int *)data = iplused;
- iplh = iplt = iplbuf;
- iplused = 0;
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else {
+ *(int *)data = iplused;
+ iplh = iplt = iplbuf;
+ iplused = 0;
+ }
break;
#endif /* IPFILTER_LOG */
case SIOCADNAT :
case SIOCRMNAT :
case SIOCGNATS :
case SIOCGNATL :
- error = nat_ioctl(data, cmd);
+ case SIOCFLNAT :
+ case SIOCCNATL :
+ error = nat_ioctl(data, cmd, mode);
break;
case SIOCGFRST :
IWCOPY((caddr_t)ipfr_fragstats(), data, sizeof(ipfrstat_t));
@@ -323,7 +358,7 @@ int mode;
IWCOPY((caddr_t)fr_statetstats(), data, sizeof(ips_stat_t));
break;
default :
- error = -EINVAL;
+ error = EINVAL;
break;
}
SPLX(s);
@@ -331,15 +366,20 @@ int mode;
}
-static int frrequest(req, fp, set)
+static int frrequest(req, data, set)
int req, set;
-register struct frentry *fp;
+caddr_t data;
{
- register struct frentry *f, **fprev;
- register struct frentry **ftail;
+ register frentry_t *fp, *f, **fprev;
+ register frentry_t **ftail;
+ frentry_t fr;
+ frdest_t *fdp;
struct frentry frd;
int error = 0, in;
+ fp = &fr;
+ IRCOPY(data, (caddr_t)fp, sizeof(*fp));
+
bzero((char *)frcache, sizeof(frcache[0]) * 2);
in = (fp->fr_flags & FR_INQUE) ? 0 : 1;
@@ -357,6 +397,24 @@ register struct frentry *fp;
if (!fp->fr_ifa)
fp->fr_ifa = (struct ifnet *)-1;
}
+
+ fdp = &fp->fr_dif;
+ fp->fr_flags &= ~FR_DUP;
+ if (*fdp->fd_ifname) {
+ fdp->fd_ifp = GETUNIT(fdp->fd_ifname);
+ if (!fdp->fd_ifp)
+ fdp->fd_ifp = (struct ifnet *)-1;
+ else
+ fp->fr_flags |= FR_DUP;
+ }
+
+ fdp = &fp->fr_tif;
+ if (*fdp->fd_ifname) {
+ fdp->fd_ifp = GETUNIT(fdp->fd_ifname);
+ if (!fdp->fd_ifp)
+ fdp->fd_ifp = (struct ifnet *)-1;
+ }
+
/*
* Look for a matching filter rule, but don't include the next or
* interface pointer in the comparison (fr_next, fr_ifa).
@@ -365,6 +423,19 @@ register struct frentry *fp;
if (bcmp((char *)&f->fr_ip, (char *)&fp->fr_ip,
FR_CMPSIZ) == 0)
break;
+
+ /*
+ * If zero'ing statistics, copy current to caller and zero.
+ */
+ if (req == SIOCZRLST) {
+ if (!f)
+ return ESRCH;
+ IWCOPY((caddr_t)f, data, sizeof(*f));
+ f->fr_hits = 0;
+ f->fr_bytes = 0;
+ return 0;
+ }
+
if (!f) {
ftail = fprev;
if (req != SIOCINAFR && req != SIOCINIFR)
@@ -417,10 +488,8 @@ int flags;
{
u_int min = minor(dev);
- if ((flags & FWRITE) || min)
+ if (min)
min = ENXIO;
- else
- iplbusy++;
return min;
}
@@ -440,8 +509,6 @@ int flags;
if (min)
min = ENXIO;
- else if (iplbusy > 0)
- iplbusy--;
return min;
}
@@ -467,12 +534,14 @@ register struct uio *uio;
if (!uio->uio_resid)
return 0;
+ iplbusy++;
while (!iplused) {
error = SLEEP(iplbuf, "ipl sleep");
- if (error)
+ if (error) {
+ iplbusy--;
return error;
+ }
}
-
SPLNET(s);
sx = sz = MIN(uio->uio_resid, iplused);
@@ -499,6 +568,7 @@ register struct uio *uio;
iplh = iplt = iplbuf;
}
SPLX(s);
+ iplbusy--;
return ret;
}
# endif /* IPFILTER_LOG */
@@ -553,16 +623,15 @@ struct mbuf *m;
iplci.hlen = (u_char)hlen;
iplci.plen = (flags & FR_LOGBODY) ? (u_char)mlen : 0 ;
iplci.rule = fin->fin_rule;
-#if !defined (__OpenBSD__) && !defined (__NetBSD__)
+# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606))
+ strcpy(iplci.ifname, ifp->if_xname);
+# else
iplci.unit = (u_char)ifp->if_unit;
- iplci.ifname[0] = ifp->if_name[0];
- iplci.ifname[1] = ifp->if_name[1];
- iplci.ifname[2] = ifp->if_name[2];
- iplci.ifname[3] = ifp->if_name[3];
-#else /* OpenBSD or NetBSD */
- bcopy (ifp->if_xname, iplci.ifname, IFNAMSIZ);
-#endif /* OpenBSD or NetBSD */
-
+ if ((iplci.ifname[0] = ifp->if_name[0]))
+ if ((iplci.ifname[1] = ifp->if_name[1]))
+ if ((iplci.ifname[2] = ifp->if_name[2]))
+ iplci.ifname[3] = ifp->if_name[3];
+# endif
if (iplh == iplbuf + LOGSIZE)
iplh = iplbuf;
tail = (iplh >= iplt) ? (iplbuf + LOGSIZE - iplh) : (iplt - iplh);
@@ -665,11 +734,7 @@ struct tcpiphdr *ti;
tp->ti_len = htons(sizeof(struct tcphdr));
tcp->th_sum = in_cksum(m, sizeof(struct tcpiphdr));
- ip->ip_hl = sizeof(struct ip) >> 2;
- ip->ip_v = IPVERSION;
ip->ip_tos = ((struct ip *)ti)->ip_tos;
- ip->ip_id = ((struct ip *)ti)->ip_id;
- ip->ip_off = ((struct ip *)ti)->ip_off;
ip->ip_p = ((struct ip *)ti)->ip_p;
ip->ip_len = sizeof (struct tcpiphdr);
#if BSD < 199306
@@ -681,7 +746,7 @@ struct tcpiphdr *ti;
/*
* extra 0 in case of multicast
*/
- (void) ip_output(m, (struct mbuf *)0, 0, IP_FORWARDING, 0);
+ (void) ip_output(m, (struct mbuf *)0, 0, 0, 0);
return 0;
}
@@ -689,7 +754,175 @@ struct tcpiphdr *ti;
#ifndef IPFILTER_LKM
iplinit()
{
- (void) iplattach();
+ /* (void) iplattach(); */
ip_init();
}
#endif
+
+
+void ipfr_fastroute(m0, fin, fdp)
+struct mbuf *m0;
+fr_info_t *fin;
+frdest_t *fdp;
+{
+ register struct ip *ip, *mhip;
+ register struct mbuf *m = m0;
+ register struct route *ro;
+ struct ifnet *ifp = fdp->fd_ifp;
+ int len, off, error = 0, s;
+ int hlen = fin->fin_hlen;
+ struct route iproute;
+ struct sockaddr_in *dst;
+
+ ip = mtod(m0, struct ip *);
+ /*
+ * Route packet.
+ */
+ ro = &iproute;
+ bzero((caddr_t)ro, sizeof (*ro));
+ dst = (struct sockaddr_in *)&ro->ro_dst;
+ dst->sin_family = AF_INET;
+ dst->sin_addr = fdp->fd_ip.s_addr ? fdp->fd_ip : ip->ip_dst;
+#if BSD >= 199306 && !(defined(__NetBSD__))
+# ifdef RTF_CLONING
+ rtalloc_ign(ro, RTF_CLONING);
+# else
+ rtalloc_ign(ro, RTF_PRCLONING);
+# endif
+#else
+ rtalloc(ro);
+#endif
+ if (!ifp) {
+ if (!(fin->fin_fr->fr_flags & FR_FASTROUTE)) {
+ error = -2;
+ goto bad;
+ }
+ if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) {
+ if (in_localaddr(ip->ip_dst))
+ error = EHOSTUNREACH;
+ else
+ error = ENETUNREACH;
+ goto bad;
+ }
+ if (ro->ro_rt->rt_flags & RTF_GATEWAY)
+ dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway;
+ }
+ ro->ro_rt->rt_use++;
+
+ /*
+ * If small enough for interface, can just send directly.
+ */
+ if (ip->ip_len <= ifp->if_mtu) {
+#ifndef sparc
+ ip->ip_id = htons(ip->ip_id);
+ ip->ip_len = htons(ip->ip_len);
+ ip->ip_off = htons(ip->ip_off);
+#endif
+ if (!ip->ip_sum)
+ ip->ip_sum = in_cksum(m, hlen);
+#if BSD >= 199306
+ error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
+ ro->ro_rt);
+
+#else
+ error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst);
+#endif
+ goto done;
+ }
+ /*
+ * Too large for interface; fragment if possible.
+ * Must be able to put at least 8 bytes per fragment.
+ */
+ if (ip->ip_off & IP_DF) {
+ error = EMSGSIZE;
+ goto bad;
+ }
+ len = (ifp->if_mtu - hlen) &~ 7;
+ if (len < 8) {
+ error = EMSGSIZE;
+ goto bad;
+ }
+
+ {
+ int mhlen, firstlen = len;
+ struct mbuf **mnext = &m->m_act;
+
+ /*
+ * Loop through length of segment after first fragment,
+ * make new header and copy data of each part and link onto chain.
+ */
+ m0 = m;
+ mhlen = sizeof (struct ip);
+ for (off = hlen + len; off < ip->ip_len; off += len) {
+ MGET(m, M_DONTWAIT, MT_HEADER);
+ if (m == 0) {
+ error = ENOBUFS;
+ goto bad;
+ }
+#if BSD >= 199306
+ m->m_data += max_linkhdr;
+#else
+ m->m_off = MMAXOFF - hlen;
+#endif
+ mhip = mtod(m, struct ip *);
+ bcopy((char *)ip, (char *)mhip, sizeof(*ip));
+ if (hlen > sizeof (struct ip)) {
+ mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
+ mhip->ip_hl = mhlen >> 2;
+ }
+ m->m_len = mhlen;
+ mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
+ if (ip->ip_off & IP_MF)
+ mhip->ip_off |= IP_MF;
+ if (off + len >= ip->ip_len)
+ len = ip->ip_len - off;
+ else
+ mhip->ip_off |= IP_MF;
+ mhip->ip_len = htons((u_short)(len + mhlen));
+ m->m_next = m_copy(m0, off, len);
+ if (m->m_next == 0) {
+ error = ENOBUFS; /* ??? */
+ goto sendorfree;
+ }
+#ifndef sparc
+ mhip->ip_off = htons((u_short)mhip->ip_off);
+#endif
+ mhip->ip_sum = 0;
+ mhip->ip_sum = in_cksum(m, mhlen);
+ *mnext = m;
+ mnext = &m->m_act;
+ }
+ /*
+ * Update first fragment by trimming what's been copied out
+ * and updating header, then send each fragment (in order).
+ */
+ m_adj(m0, hlen + firstlen - ip->ip_len);
+ ip->ip_len = htons((u_short)(hlen + firstlen));
+ ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
+ ip->ip_sum = 0;
+ ip->ip_sum = in_cksum(m0, hlen);
+sendorfree:
+ for (m = m0; m; m = m0) {
+ m0 = m->m_act;
+ m->m_act = 0;
+ if (error == 0)
+#if BSD >= 199306
+ error = (*ifp->if_output)(ifp, m,
+ (struct sockaddr *)dst, ro->ro_rt);
+#else
+ error = (*ifp->if_output)(ifp, m,
+ (struct sockaddr *)dst);
+#endif
+ else
+ m_freem(m);
+ }
+ }
+done:
+ if (ro->ro_rt) {
+ RTFREE(ro->ro_rt);
+ }
+ return;
+bad:
+ m_freem(m);
+ goto done;
+}
diff --git a/sys/netinet/ip_fil.h b/sys/netinet/ip_fil.h
index e80d977445e..29b5a1df2aa 100644
--- a/sys/netinet/ip_fil.h
+++ b/sys/netinet/ip_fil.h
@@ -5,7 +5,8 @@
* provided that this notice is preserved and due credit is given
* to the original author and the contributors.
*
- * @(#)ip_fil.h 1.32 3/24/96
+ * @(#)ip_fil.h 1.35 6/5/96
+ * $Id: ip_fil.h,v 1.4 1996/07/18 05:00:59 dm Exp $
*/
#ifndef __IP_FIL_H__
@@ -18,207 +19,6 @@
#ifndef SOLARIS
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
#endif
-#define IPMINLEN(i, h) ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h)))
-
-#ifndef IP_OFFMASK
-#define IP_OFFMASK 0x1fff
-#endif
-
-#ifndef MAX
-#define MAX(a,b) (((a) > (b)) ? (a) : (b))
-#endif
-
-#ifdef _KERNEL
-# if SOLARIS
-# define MUTEX_ENTER(x) mutex_enter(x)
-# define MUTEX_EXIT(x) mutex_exit(x)
-# define MTOD(m,t) (t)((m)->b_rptr)
-# define IRCOPY(a,b,c) copyin((a), (b), (c))
-# define IWCOPY(a,b,c) copyout((a), (b), (c))
-# else
-# define MUTEX_ENTER(x) ;
-# define MUTEX_EXIT(x) ;
-# ifndef linux
-# define MTOD(m,t) mtod(m,t)
-# define IRCOPY(a,b,c) bcopy((a), (b), (c))
-# define IWCOPY(a,b,c) bcopy((a), (b), (c))
-# endif
-# endif /* SOLARIS */
-
-# ifdef sun
-# if defined(__svr4__) || defined(__SVR4)
-# define GETUNIT(n) get_unit((n))
-# else
-# include <sys/kmem_alloc.h>
-# define GETUNIT(n) ifunit((n), IFNAMSIZ)
-# endif
-# else
-# define GETUNIT(n) ifunit((n))
-# endif /* sun */
-
-# if defined(sun) && !defined(linux)
-# define UIOMOVE(a,b,c,d) uiomove(a,b,c,d)
-# define SLEEP(id, n) sleep((id), PZERO+1)
-# define KFREE(x) kmem_free((char *)(x), sizeof(*(x)))
-# if SOLARIS
-typedef struct qif {
- struct qif *qf_next;
- ill_t *qf_ill;
- kmutex_t qf_lock;
- void *qf_iptr;
- void *qf_optr;
- queue_t *qf_in;
- queue_t *qf_out;
- void *qf_wqinfo;
- void *qf_rqinfo;
- char qf_name[8];
- int (*qf_inp)();
- int (*qf_outp)();
- /*
- * in case the ILL has disappeared...
- */
- int qf_hl; /* header length */
-} qif_t;
-# define SPLNET(x) ;
-# undef SPLX
-# define SPLX(x) ;
-# ifdef sparc
-# define ntohs(x) (x)
-# define ntohl(x) (x)
-# define htons(x) (x)
-# define htonl(x) (x)
-# endif
-# define KMALLOC(x) kmem_alloc((x), KM_SLEEP)
-# define GET_MINOR(x) getminor(x)
-# else
-# define KMALLOC(x) new_kmem_alloc((x), KMEM_SLEEP)
-# endif /* __svr4__ */
-# endif /* sun && !linux */
-# ifndef GET_MINOR
-# define GET_MINOR(x) minor(x)
-# endif
-# if BSD >= 199306 || defined(__FreeBSD__)
-# include <vm/vm.h>
-# if !defined(__FreeBSD__)
-# include <vm/vm_extern.h>
-# include <sys/proc.h>
-extern vm_map_t kmem_map;
-# else
-# include <vm/vm_kern.h>
-# endif /* __FreeBSD__ */
-# define KMALLOC(x) kmem_alloc(kmem_map, (x))
-# define KFREE(x) kmem_free(kmem_map, (vm_offset_t)(x), \
- sizeof(*(x)))
-# define UIOMOVE(a,b,c,d) uiomove(a,b,d)
-# define SLEEP(id, n) tsleep((id), PPAUSE|PCATCH, n, 0)
-# endif /* BSD */
-# if defined(NetBSD1_0) && (NetBSD1_0 > 1)
-# define SPLNET(x) x = splsoftnet()
-# else
-# if !SOLARIS
-# define SPLNET(x) x = splnet()
-# define SPLX(x) (void) splx(x)
-# endif
-# endif
-#else
-# define MUTEX_ENTER(x) ;
-# define MUTEX_EXIT(x) ;
-# define SPLNET(x) ;
-# define SPLX(x) ;
-# define KMALLOC(x) malloc(x)
-# define KFREE(x) free(x)
-# define GETUNIT(x) (x)
-# define IRCOPY(a,b,c) bcopy((a), (b), (c))
-# define IWCOPY(a,b,c) bcopy((a), (b), (c))
-#endif /* KERNEL */
-
-#ifdef linux
-# define ICMP_UNREACH ICMP_DEST_UNREACH
-# define ICMP_SOURCEQUENCH ICMP_SOURCE_QUENCH
-# define ICMP_TIMXCEED ICMP_TIME_EXCEEDED
-# define ICMP_PARAMPROB ICMP_PARAMETERPROB
-# define icmp icmphdr
-# define icmp_type type
-# define icmp_code code
-
-# define TH_FIN 0x01
-# define TH_SYN 0x02
-# define TH_RST 0x04
-# define TH_PUSH 0x08
-# define TH_ACK 0x10
-# define TH_URG 0x20
-
-typedef struct {
- __u16 th_sport;
- __u16 th_dport;
- __u32 th_seq;
- __u32 th_ack;
- __u8 th_x;
- __u8 th_flags;
- __u16 th_win;
- __u16 th_sum;
- __u16 th_urp;
-} tcphdr_t;
-
-typedef struct {
- __u16 uh_sport;
- __u16 uh_dport;
- __u16 uh_ulen;
- __u16 uh_sun;
-} udphdr_t;
-
-typedef struct {
-# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\
- defined(vax)
- __u8 ip_hl:4;
- __u8 ip_v:4;
-# else
- __u8 ip_hl:4;
- __u8 ip_v:4;
-# endif
- __u8 ip_tos;
- __u16 ip_len;
- __u16 ip_id;
- __u16 ip_off;
- __u8 ip_ttl;
- __u8 ip_p;
- __u16 ip_sum;
- __u32 ip_src;
- __u32 ip_dst;
-} ip_t;
-
-# define SPLX(x) (void)
-# define SPLNET(x) (void)
-
-# define bcopy(a,b,c) memmove(b,a,c)
-# define bcmp(a,b,c) memcmp(a,b,c)
-
-# define UNITNAME(n) dev_get((n))
-# define ifnet device
-
-# define KMALLOC(x) kmalloc((x), GFP_ATOMIC)
-# define KFREE(x) kfree_s((x), sizeof(*(x)))
-# define IRCOPY(a,b,c) { \
- error = verify_area(VERIFY_READ, \
- (b) ,sizeof((b))); \
- if (!error) \
- memcpy_fromfs((b), (a), (c)); \
- }
-# define IWCOPY(a,b,c) { \
- error = verify_area(VERIFY_WRITE, \
- (b) ,sizeof((b))); \
- if (!error) \
- memcpy_tofs((b), (a), (c)); \
- }
-#else
-typedef struct tcphdr tcphdr_t;
-typedef struct udphdr udphdr_t;
-typedef struct ip ip_t;
-#endif /* linux */
-
-#ifndef SOLARIS
-#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
-#endif
#if defined(KERNEL) && !defined(_KERNEL)
#define _KERNEL
@@ -256,6 +56,9 @@ typedef struct ip ip_t;
#define SIOCFRENB _IOW('r', 72, u_int)
#define SIOCFRSYN _IOW('r', 73, u_int)
#define SIOCFRZST _IOWR('r', 74, struct friostat)
+#define SIOCFLNAT _IOWR('r', 75, int)
+#define SIOCCNATL _IOWR('r', 76, int)
+#define SIOCZRLST _IOWR('r', 77, struct frentry)
#else
#define SIOCADAFR _IOW(r, 60, struct frentry)
#define SIOCRMAFR _IOW(r, 61, struct frentry)
@@ -272,6 +75,9 @@ typedef struct ip ip_t;
#define SIOCFRENB _IOW(r, 72, u_int)
#define SIOCFRSYN _IOW(r, 73, u_int)
#define SIOCFRZST _IOWR(r, 74, struct friostat)
+#define SIOCFLNAT _IOWR(r, 75, int)
+#define SIOCCNATL _IOWR(r, 76, int)
+#define SIOCZRLST _IOWR(r, 77, struct frentry)
#endif
#define SIOCADDFR SIOCADAFR
#define SIOCDELFR SIOCRMAFR
@@ -311,6 +117,12 @@ typedef struct fr_info {
#define FI_CSIZE (sizeof(struct fr_ip) + 11)
+typedef struct frdest {
+ void *fd_ifp;
+ struct in_addr fd_ip;
+ char fd_ifname[IFNAMSIZ];
+} frdest_t;
+
typedef struct frentry {
struct frentry *fr_next;
struct ifnet *fr_ifa;
@@ -336,8 +148,11 @@ typedef struct frentry {
u_short fr_stop; /* top port for <> and >< */
u_short fr_dtop; /* top port for <> and >< */
u_long fr_flags; /* per-rule flags && options (see below) */
+ int (*fr_func)(); /* call this function */
char fr_icode; /* return ICMP code */
char fr_ifname[IFNAMSIZ];
+ struct frdest fr_tif; /* "to" interface */
+ struct frdest fr_dif; /* duplicate packet interfaces */
} frentry_t;
#define fr_proto fr_ip.fi_p
@@ -356,29 +171,35 @@ typedef struct frentry {
/*
* fr_flags
*/
-#define FR_BLOCK 0x0001
-#define FR_PASS 0x0002
-#define FR_OUTQUE 0x0004
-#define FR_INQUE 0x0008
-#define FR_LOG 0x0010 /* Log */
-#define FR_LOGB 0x0021 /* Log-fail */
-#define FR_LOGP 0x0022 /* Log-pass */
-#define FR_LOGBODY 0x0040 /* Log the body */
-#define FR_LOGFIRST 0x0080
-#define FR_RETRST 0x0100
-#define FR_RETICMP 0x0200
-#define FR_NOMATCH 0x0400
-#define FR_ACCOUNT 0x0800 /* count packet bytes */
-#define FR_KEEPFRAG 0x1000
-#define FR_KEEPSTATE 0x2000
-#define FR_INACTIVE 0x4000
-#define FR_QUICK 0x8000
+#define FR_BLOCK 0x00001
+#define FR_PASS 0x00002
+#define FR_OUTQUE 0x00004
+#define FR_INQUE 0x00008
+#define FR_LOG 0x00010 /* Log */
+#define FR_LOGB 0x00011 /* Log-fail */
+#define FR_LOGP 0x00012 /* Log-pass */
+#define FR_LOGBODY 0x00020 /* Log the body */
+#define FR_LOGFIRST 0x00040
+#define FR_RETRST 0x00080
+#define FR_RETICMP 0x00100
+#define FR_NOMATCH 0x00200
+#define FR_ACCOUNT 0x00400 /* count packet bytes */
+#define FR_KEEPFRAG 0x00800
+#define FR_KEEPSTATE 0x01000
+#define FR_INACTIVE 0x02000
+#define FR_QUICK 0x04000
+#define FR_FASTROUTE 0x08000
+#define FR_CALLNOW 0x10000
+#define FR_DUP 0x20000
+
+#define FR_LOGMASK (FR_LOG|FR_LOGP|FR_LOGB)
/*
* recognized flags for SIOCGETFF and SIOCSETFF
*/
#define FF_LOGPASS 0x100000
#define FF_LOGBLOCK 0x200000
#define FF_LOGNOMATCH 0x400000
+#define FF_LOGGING (FF_LOGPASS|FF_LOGBLOCK|FF_LOGNOMATCH)
#define FR_NONE 0
#define FR_EQUAL 1
@@ -437,14 +258,14 @@ typedef struct ipl_ci {
u_char hlen;
u_char plen;
u_short rule;
- u_long flags:24;
-#if !defined (__OpenBSD__) && !defined (__NetBSD__)
+ u_long flags:24; /* XXX FIXME do we care about the extra bytes? */
+#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606))
+ u_long filler:8; /* XXX FIXME do we care? */
+ u_char ifname[IFNAMSIZ];
+#else
u_long unit:8;
u_char ifname[4];
-#else /* OpenBSD or NetBSD */
- u_long : 0;
- u_char ifname[IFNAMSIZ];
-#endif /* OpenBSD or NetBSD */
+#endif
} ipl_ci_t;
diff --git a/sys/netinet/ip_fil_compat.h b/sys/netinet/ip_fil_compat.h
new file mode 100644
index 00000000000..70e30d11d8f
--- /dev/null
+++ b/sys/netinet/ip_fil_compat.h
@@ -0,0 +1,216 @@
+/*
+ * (C)opyright 1993, 1994, 1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ *
+ * @(#)ip_fil_compat.h 1.8 1/14/96
+ * $Id: ip_fil_compat.h,v 1.1 1996/07/18 05:01:00 dm Exp $
+ */
+
+#ifndef __IP_COMPAT_H_
+#define __IP_COMPAT_H__
+
+#ifndef SOLARIS
+#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
+#endif
+#define IPMINLEN(i, h) ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h)))
+
+#ifndef IP_OFFMASK
+#define IP_OFFMASK 0x1fff
+#endif
+
+#ifndef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifdef _KERNEL
+# if SOLARIS
+# define MUTEX_ENTER(x) mutex_enter(x)
+# define MUTEX_EXIT(x) mutex_exit(x)
+# define MTOD(m,t) (t)((m)->b_rptr)
+# define IRCOPY(a,b,c) copyin((a), (b), (c))
+# define IWCOPY(a,b,c) copyout((a), (b), (c))
+# else
+# define MUTEX_ENTER(x) ;
+# define MUTEX_EXIT(x) ;
+# ifndef linux
+# define MTOD(m,t) mtod(m,t)
+# define IRCOPY(a,b,c) bcopy((a), (b), (c))
+# define IWCOPY(a,b,c) bcopy((a), (b), (c))
+# endif
+# endif /* SOLARIS */
+
+# ifdef sun
+# if defined(__svr4__) || defined(__SVR4)
+# define GETUNIT(n) get_unit((n))
+# else
+# include <sys/kmem_alloc.h>
+# define GETUNIT(n) ifunit((n), IFNAMSIZ)
+# endif
+# else
+# define GETUNIT(n) ifunit((n))
+# endif /* sun */
+
+# if defined(sun) && !defined(linux)
+# define UIOMOVE(a,b,c,d) uiomove(a,b,c,d)
+# define SLEEP(id, n) sleep((id), PZERO+1)
+# define KFREE(x) kmem_free((char *)(x), sizeof(*(x)))
+# if SOLARIS
+typedef struct qif {
+ struct qif *qf_next;
+ ill_t *qf_ill;
+ kmutex_t qf_lock;
+ void *qf_iptr;
+ void *qf_optr;
+ queue_t *qf_in;
+ queue_t *qf_out;
+ void *qf_wqinfo;
+ void *qf_rqinfo;
+ char qf_name[8];
+ int (*qf_inp)();
+ int (*qf_outp)();
+ /*
+ * in case the ILL has disappeared...
+ */
+ int qf_hl; /* header length */
+} qif_t;
+# define SPLNET(x) ;
+# undef SPLX
+# define SPLX(x) ;
+# ifdef sparc
+# define ntohs(x) (x)
+# define ntohl(x) (x)
+# define htons(x) (x)
+# define htonl(x) (x)
+# endif
+# define KMALLOC(x) kmem_alloc((x), KM_SLEEP)
+# define GET_MINOR(x) getminor(x)
+# else
+# define KMALLOC(x) new_kmem_alloc((x), KMEM_SLEEP)
+# endif /* __svr4__ */
+# endif /* sun && !linux */
+# ifndef GET_MINOR
+# define GET_MINOR(x) minor(x)
+# endif
+# if BSD >= 199306 || defined(__FreeBSD__)
+# include <vm/vm.h>
+# if !defined(__FreeBSD__)
+# include <vm/vm_extern.h>
+# include <sys/proc.h>
+extern vm_map_t kmem_map;
+# else
+# include <vm/vm_kern.h>
+# endif /* __FreeBSD__ */
+# define KMALLOC(x) kmem_alloc(kmem_map, (x))
+# define KFREE(x) kmem_free(kmem_map, (vm_offset_t)(x), \
+ sizeof(*(x)))
+# define UIOMOVE(a,b,c,d) uiomove(a,b,d)
+# define SLEEP(id, n) tsleep((id), PPAUSE|PCATCH, n, 0)
+# endif /* BSD */
+# if defined(NetBSD1_0) && (NetBSD1_0 > 1)
+# define SPLNET(x) x = splsoftnet()
+# else
+# if !SOLARIS
+# define SPLNET(x) x = splnet()
+# define SPLX(x) (void) splx(x)
+# endif
+# endif
+#else
+# define MUTEX_ENTER(x) ;
+# define MUTEX_EXIT(x) ;
+# define SPLNET(x) ;
+# define SPLX(x) ;
+# define KMALLOC(x) malloc(x)
+# define KFREE(x) free(x)
+# define GETUNIT(x) (x)
+# define IRCOPY(a,b,c) bcopy((a), (b), (c))
+# define IWCOPY(a,b,c) bcopy((a), (b), (c))
+#endif /* KERNEL */
+
+#ifdef linux
+# define ICMP_UNREACH ICMP_DEST_UNREACH
+# define ICMP_SOURCEQUENCH ICMP_SOURCE_QUENCH
+# define ICMP_TIMXCEED ICMP_TIME_EXCEEDED
+# define ICMP_PARAMPROB ICMP_PARAMETERPROB
+# define icmp icmphdr
+# define icmp_type type
+# define icmp_code code
+
+# define TH_FIN 0x01
+# define TH_SYN 0x02
+# define TH_RST 0x04
+# define TH_PUSH 0x08
+# define TH_ACK 0x10
+# define TH_URG 0x20
+
+typedef struct {
+ __u16 th_sport;
+ __u16 th_dport;
+ __u32 th_seq;
+ __u32 th_ack;
+ __u8 th_x;
+ __u8 th_flags;
+ __u16 th_win;
+ __u16 th_sum;
+ __u16 th_urp;
+} tcphdr_t;
+
+typedef struct {
+ __u16 uh_sport;
+ __u16 uh_dport;
+ __u16 uh_ulen;
+ __u16 uh_sun;
+} udphdr_t;
+
+typedef struct {
+# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\
+ defined(vax)
+ __u8 ip_hl:4;
+ __u8 ip_v:4;
+# else
+ __u8 ip_hl:4;
+ __u8 ip_v:4;
+# endif
+ __u8 ip_tos;
+ __u16 ip_len;
+ __u16 ip_id;
+ __u16 ip_off;
+ __u8 ip_ttl;
+ __u8 ip_p;
+ __u16 ip_sum;
+ __u32 ip_src;
+ __u32 ip_dst;
+} ip_t;
+
+# define SPLX(x) (void)
+# define SPLNET(x) (void)
+
+# define bcopy(a,b,c) memmove(b,a,c)
+# define bcmp(a,b,c) memcmp(a,b,c)
+
+# define UNITNAME(n) dev_get((n))
+# define ifnet device
+
+# define KMALLOC(x) kmalloc((x), GFP_ATOMIC)
+# define KFREE(x) kfree_s((x), sizeof(*(x)))
+# define IRCOPY(a,b,c) { \
+ error = verify_area(VERIFY_READ, \
+ (b) ,sizeof((b))); \
+ if (!error) \
+ memcpy_fromfs((b), (a), (c)); \
+ }
+# define IWCOPY(a,b,c) { \
+ error = verify_area(VERIFY_WRITE, \
+ (b) ,sizeof((b))); \
+ if (!error) \
+ memcpy_tofs((b), (a), (c)); \
+ }
+#else
+typedef struct tcphdr tcphdr_t;
+typedef struct udphdr udphdr_t;
+typedef struct ip ip_t;
+#endif /* linux */
+
+#endif /* __IP_COMPAT_H__ */
diff --git a/sys/netinet/ip_frag.c b/sys/netinet/ip_frag.c
index 243448177f3..b193febd3e1 100644
--- a/sys/netinet/ip_frag.c
+++ b/sys/netinet/ip_frag.c
@@ -7,6 +7,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-1995 Darren Reed";
+static char rcsid[] = "$Id: ip_frag.c,v 1.3 1996/07/18 05:01:02 dm Exp $";
#endif
#if !defined(_KERNEL) && !defined(KERNEL)
@@ -46,6 +47,7 @@ static char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-1995 Darren Reed";
#include <netinet/ip_icmp.h>
#include <syslog.h>
#include "ip_fil.h"
+#include "ip_fil_compat.h"
#include "ip_frag.h"
#include "ip_nat.h"
#include "ip_state.h"
diff --git a/sys/netinet/ip_frag.h b/sys/netinet/ip_frag.h
index 61c79af3f72..6780071aa6c 100644
--- a/sys/netinet/ip_frag.h
+++ b/sys/netinet/ip_frag.h
@@ -6,6 +6,7 @@
* to the original author and the contributors.
*
* @(#)ip_frag.h 1.5 3/24/96
+ * $Id: ip_frag.h,v 1.3 1996/07/18 05:01:03 dm Exp $
*/
#ifndef __IP_FRAG_H_
@@ -25,11 +26,6 @@ typedef struct ipfr {
u_char ipfr_pass;
} ipfr_t;
-#if defined(__STDC__) || defined(__GNUC__)
-#define SIOCGFRST _IOR('r', 76, struct ipfrstat)
-#else
-#define SIOCGFRST _IOR(r, 76, struct ipfrstat)
-#endif
typedef struct ipfrstat {
u_long ifs_exists; /* add & already exists */
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 94e0050aa85..5b8b0ba031f 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_input.c,v 1.12 1996/05/07 15:20:25 mickey Exp $ */
+/* $OpenBSD: ip_input.c,v 1.13 1996/07/18 05:01:04 dm Exp $ */
/* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */
/*
@@ -100,8 +100,8 @@ int ipqmaxlen = IFQ_MAXLEN;
struct in_ifaddrhead in_ifaddr;
struct ifqueue ipintrq;
#if defined(IPFILTER) || defined(IPFILTER_LKM)
-int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)
-);
+int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int,
+ struct mbuf **));
#endif
diff --git a/sys/netinet/ip_nat.c b/sys/netinet/ip_nat.c
index 34c91987124..b8b42874db4 100644
--- a/sys/netinet/ip_nat.c
+++ b/sys/netinet/ip_nat.c
@@ -17,9 +17,13 @@
* easy solution)
* 2) There needs to be a way to flush the NATs table completely. Either
* an ioctl, or an easy way of doing it from ipnat.c.
+ *
+ * Missing from RFC 1631: ICMP header checksum recalculations.
+ *
*/
#ifndef lint
-static char sccsid[] = "@(#)ip_nat.c 1.9 4/10/96 (C) 1995 Darren Reed";
+static char sccsid[] = "@(#)ip_nat.c 1.11 6/5/96 (C) 1995 Darren Reed";
+static char rcsid[] = "$Id: ip_nat.c,v 1.4 1996/07/18 05:01:05 dm Exp $";
#endif
#if !defined(_KERNEL) && !defined(KERNEL)
@@ -60,6 +64,7 @@ static char sccsid[] = "@(#)ip_nat.c 1.9 4/10/96 (C) 1995 Darren Reed";
#include <netinet/ip_icmp.h>
#include <syslog.h>
#include "ip_fil.h"
+#include "ip_fil_compat.h"
#include "ip_nat.h"
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
@@ -103,19 +108,21 @@ extern kmutex_t ipf_nat;
/*
* Handle ioctls which manipulate the NAT.
*/
-int nat_ioctl(data, cmd)
+int nat_ioctl(data, cmd, mode)
caddr_t data;
-int cmd;
+int cmd, mode;
{
register ipnat_t *nat, *n, **np;
- int error = 0;
+ ipnat_t natd;
+ int error = 0, ret;
/*
* For add/delete, look to see if the NAT entry is already present
*/
MUTEX_ENTER(&ipf_nat);
if ((cmd == SIOCADNAT) || (cmd == SIOCRMNAT)) {
- nat = (ipnat_t *)data;
+ IRCOPY(data, &natd, sizeof(natd));
+ nat = &natd;
for (np = &nat_list; (n = *np); np = &n->in_next)
if (!bcmp((char *)&nat->in_port, (char *)&n->in_port,
IPN_CMPSIZ))
@@ -125,6 +132,10 @@ int cmd;
switch (cmd)
{
case SIOCADNAT :
+ if (!(mode & FWRITE)) {
+ error = EPERM;
+ break;
+ }
if (n) {
error = EEXIST;
break;
@@ -148,6 +159,10 @@ int cmd;
*np = n;
break;
case SIOCRMNAT :
+ if (!(mode & FWRITE)) {
+ error = EPERM;
+ break;
+ }
if (!n) {
error = ESRCH;
break;
@@ -165,11 +180,7 @@ int cmd;
{
natlookup_t nl;
nat_t *na;
-#if !SOLARIS && defined(_KERNEL)
- int s;
-#endif
- SPLNET(s);
IRCOPY((char *)data, (char *)&nl, sizeof(nl));
if ((na = nat_lookupredir(&nl))) {
nl.nl_inip = na->nat_outip;
@@ -177,9 +188,24 @@ int cmd;
IWCOPY((char *)&nl, (char *)data, sizeof(nl));
} else
error = ESRCH;
- SPLX(s);
break;
}
+ case SIOCFLNAT :
+ if (!(mode & FWRITE)) {
+ error = EPERM;
+ break;
+ }
+ ret = flush_nattable();
+ IWCOPY((caddr_t)&ret, data, sizeof(ret));
+ break;
+ case SIOCCNATL :
+ if (!(mode & FWRITE)) {
+ error = EPERM;
+ break;
+ }
+ ret = clear_natlist();
+ IWCOPY((caddr_t)&ret, data, sizeof(ret));
+ break;
}
MUTEX_EXIT(&ipf_nat);
return error;
@@ -187,9 +213,49 @@ int cmd;
/*
- * Create a new NAT table entry.
+ * flush_nattable - clear the NAT table of all mapping entries.
+ */
+int flush_nattable()
+{
+ nat_t *nat, **natp;
+ int i, j = 0;
+
+ for (natp = &nat_table[0][0], i = NAT_SIZE - 1; i >= 0; i--, natp++)
+ while ((nat = *natp)) {
+ *natp = nat->nat_next;
+ KFREE((caddr_t)nat);
+ j++;
+ }
+
+ for (natp = &nat_table[1][0], i = NAT_SIZE - 1; i >= 0; i--, natp++)
+ while ((nat = *natp)) {
+ *natp = nat->nat_next;
+ KFREE((caddr_t)nat);
+ j++;
+ }
+ return j;
+}
+
+
+/*
+ * clear_natlist - delete all entries in the active NAT mapping list.
*/
+int clear_natlist()
+{
+ register ipnat_t *n, **np;
+ int i = 0;
+ for (np = &nat_list; (n = *np); i++) {
+ *np = n->in_next;
+ KFREE(n);
+ }
+ return i;
+}
+
+
+/*
+ * Create a new NAT table entry.
+ */
nat_t *nat_new(np, ip, hlen, flags, direction)
ipnat_t *np;
ip_t *ip;
@@ -213,7 +279,6 @@ int direction;
if (!(nat = (nat_t *)KMALLOC(sizeof(*nat))))
return NULL;
-
/*
* Search the current table for a match.
*/
diff --git a/sys/netinet/ip_nat.h b/sys/netinet/ip_nat.h
index e3785d421d7..19ce04caa5a 100644
--- a/sys/netinet/ip_nat.h
+++ b/sys/netinet/ip_nat.h
@@ -6,6 +6,7 @@
* to the original author and the contributors.
*
* @(#)ip_nat.h 1.5 2/4/96
+ * $Id: ip_nat.h,v 1.3 1996/07/18 05:01:06 dm Exp $
*/
#ifndef __IP_NAT_H_
@@ -20,11 +21,15 @@
#define SIOCRMNAT _IOW('r', 81, struct ipnat)
#define SIOCGNATS _IOR('r', 82, struct natstat)
#define SIOCGNATL _IOWR('r', 83, struct natlookup)
+#define SIOCGFRST _IOR('r', 84, struct ipfrstat)
+#define SIOCGIPST _IOR('r', 85, struct ips_stat)
#else
#define SIOCADNAT _IOW(r, 80, struct ipnat)
#define SIOCRMNAT _IOW(r, 81, struct ipnat)
#define SIOCGNATS _IOR(r, 82, struct natstat)
#define SIOCGNATL _IOWR(r, 83, struct natlookup)
+#define SIOCGFRST _IOR(r, 84, struct ipfrstat)
+#define SIOCGIPST _IOR(r, 85, struct ips_stat)
#endif
#define NAT_SIZE 367
diff --git a/sys/netinet/ip_state.c b/sys/netinet/ip_state.c
index c6d1eff2d5f..946312cf4d7 100644
--- a/sys/netinet/ip_state.c
+++ b/sys/netinet/ip_state.c
@@ -6,7 +6,8 @@
* to the original author and the contributors.
*/
#ifndef lint
-static char sccsid[] = "@(#)ip_state.c 1.6 3/24/96 (C) 1993-1995 Darren Reed";
+static char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-1995 Darren Reed";
+static char rcsid[] = "$Id: ip_state.c,v 1.3 1996/07/18 05:01:08 dm Exp $";
#endif
#if !defined(_KERNEL) && !defined(KERNEL)
@@ -48,6 +49,7 @@ static char sccsid[] = "@(#)ip_state.c 1.6 3/24/96 (C) 1993-1995 Darren Reed";
#include <syslog.h>
#endif
#include "ip_fil.h"
+#include "ip_fil_compat.h"
#include "ip_state.h"
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
@@ -82,9 +84,9 @@ ips_stat_t *fr_statetstats()
/*
* Create a new ipstate structure and hang it off the hash table.
*/
-int fr_addstate(ip, hlen, pass)
+int fr_addstate(ip, fin, pass)
ip_t *ip;
-int hlen;
+fr_info_t *fin;
u_int pass;
{
ipstate_t ips;
@@ -106,7 +108,7 @@ u_int pass;
{
case IPPROTO_ICMP :
{
- struct icmp *ic = (struct icmp *)((char *)ip + hlen);
+ struct icmp *ic = (struct icmp *)fin->fin_dp;
switch (ic->icmp_type)
{
@@ -129,7 +131,7 @@ u_int pass;
}
case IPPROTO_TCP :
{
- register tcphdr_t *tcp = (tcphdr_t *)((char *)ip + hlen);
+ register tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp;
/*
* The endian of the ports doesn't matter, but the ack and
@@ -154,7 +156,7 @@ u_int pass;
}
case IPPROTO_UDP :
{
- register tcphdr_t *tcp = (tcphdr_t *)((char *)ip + hlen);
+ register tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp;
hv += (is->is_dport = tcp->th_dport);
hv += (is->is_sport = tcp->th_sport);
@@ -175,7 +177,9 @@ u_int pass;
MUTEX_ENTER(&ipf_state);
is->is_next = ips_table[hv];
ips_table[hv] = is;
- is->is_pass = pass & ~(FR_LOGFIRST|FR_LOG);
+ is->is_pass = pass;
+ if (pass & FR_LOGFIRST)
+ is->is_pass &= ~(FR_LOGFIRST|FR_LOG);
ips_num++;
MUTEX_EXIT(&ipf_state);
return 0;
@@ -303,9 +307,12 @@ fr_info_t *fin;
* timeout.
*/
#ifdef _KERNEL
- if ((tcp->th_flags & TCP_CLOSE) &&
- !is->is_age)
- is->is_age = 120;
+ if (!is->is_age) {
+ if (tcp->th_flags & TH_FIN)
+ is->is_age = 120;
+ if (tcp->th_flags & TH_RST)
+ is->is_age = 1;
+ }
MUTEX_EXIT(&ipf_state);
return is->is_pass;
#else
diff --git a/sys/netinet/ip_state.h b/sys/netinet/ip_state.h
index d22c930504d..b4aee7a4e14 100644
--- a/sys/netinet/ip_state.h
+++ b/sys/netinet/ip_state.h
@@ -6,6 +6,7 @@
* to the original author and the contributors.
*
* @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed
+ * $Id: ip_state.h,v 1.2 1996/07/18 05:01:09 dm Exp $
*/
#ifndef __IP_STATE_H__
#define __IP_STATE_H__
@@ -55,11 +56,6 @@ typedef struct ipstate {
#define is_sport is_tcp.ts_sport
#define is_dport is_tcp.ts_dport
-#if defined(__STDC__) || defined(__GNUC__)
-#define SIOCGIPST _IOR('r', 75, struct ips_stat)
-#else
-#define SIOCGIPST _IOR(r, 75, struct ips_stat)
-#endif
typedef struct ips_stat {
u_long iss_hits;