summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordarrenr <darrenr@FreeBSD.org>2000-05-24 03:17:16 +0000
committerdarrenr <darrenr@FreeBSD.org>2000-05-24 03:17:16 +0000
commite517ff28a4759f0bbeb5c846451323e3b55ababd (patch)
tree79e3da5aa40f4a410e0bab451990b9c288ead021 /sys
parent553f5accf7e7a2648d008eb8aa979068bf490f4f (diff)
downloadFreeBSD-src-e517ff28a4759f0bbeb5c846451323e3b55ababd.zip
FreeBSD-src-e517ff28a4759f0bbeb5c846451323e3b55ababd.tar.gz
fix conflicts
Diffstat (limited to 'sys')
-rw-r--r--sys/contrib/ipfilter/netinet/fil.c693
-rw-r--r--sys/contrib/ipfilter/netinet/ip_auth.c68
-rw-r--r--sys/contrib/ipfilter/netinet/ip_auth.h7
-rw-r--r--sys/netinet/fil.c693
-rw-r--r--sys/netinet/ip_auth.c68
-rw-r--r--sys/netinet/ip_auth.h7
6 files changed, 1156 insertions, 380 deletions
diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c
index 8dea84b..f16163e 100644
--- a/sys/contrib/ipfilter/netinet/fil.c
+++ b/sys/contrib/ipfilter/netinet/fil.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1993-1998 by Darren Reed.
+ * Copyright (C) 1993-2000 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
@@ -11,6 +11,10 @@ static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed";
static const char rcsid[] = "@(#)$FreeBSD$";
#endif
+#if defined(_KERNEL) && defined(__FreeBSD_version) && \
+ (__FreeBSD_version >= 400000) && !defined(KLD_MODULE)
+#include "opt_inet6.h"
+#endif
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/param.h>
@@ -20,7 +24,7 @@ static const char rcsid[] = "@(#)$FreeBSD$";
defined(_KERNEL)
# include "opt_ipfilter_log.h"
#endif
-#if defined(_KERNEL) && defined(__FreeBSD_version) && \
+#if (defined(KERNEL) || defined(_KERNEL)) && defined(__FreeBSD_version) && \
(__FreeBSD_version >= 220000)
# include <sys/filio.h>
# include <sys/fcntl.h>
@@ -69,6 +73,12 @@ static const char rcsid[] = "@(#)$FreeBSD$";
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include "netinet/ip_compat.h"
+#ifdef USE_INET6
+# include <netinet/icmp6.h>
+# if !SOLARIS && defined(_KERNEL)
+# include <netinet6/in6_var.h>
+# endif
+#endif
#include <netinet/tcpip.h>
#include "netinet/ip_fil.h"
#include "netinet/ip_proxy.h"
@@ -94,18 +104,10 @@ static const char rcsid[] = "@(#)$FreeBSD$";
# include "ipt.h"
extern int opts;
-# define FR_IFVERBOSE(ex,second,verb_pr) if (ex) { verbose verb_pr; \
- second; }
-# define FR_IFDEBUG(ex,second,verb_pr) if (ex) { debug verb_pr; \
- second; }
# define FR_VERBOSE(verb_pr) verbose verb_pr
# define FR_DEBUG(verb_pr) debug verb_pr
-# define SEND_RESET(ip, qif, if, m, fin) send_reset(ip, if)
# define IPLLOG(a, c, d, e) ipllog()
-# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip)
#else /* #ifndef _KERNEL */
-# define FR_IFVERBOSE(ex,second,verb_pr) ;
-# define FR_IFDEBUG(ex,second,verb_pr) ;
# define FR_VERBOSE(verb_pr)
# define FR_DEBUG(verb_pr)
# define IPLLOG(a, c, d, e) ipflog(a, c, d, e)
@@ -117,27 +119,24 @@ extern kmutex_t ipf_rw;
# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, \
ip, qif)
# define SEND_RESET(ip, qif, if, fin) send_reset(fin, ip, qif)
-# define ICMP_ERROR(b, ip, t, c, if, dst) \
- icmp_error(ip, t, c, if, dst)
# else /* SOLARIS */
# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip)
-# ifdef linux
-# define SEND_RESET(ip, qif, if, fin) send_reset(ip, ifp)
-# define ICMP_ERROR(b, ip, t, c, if, dst) icmp_send(b,t,c,0,if)
-# else
-# define SEND_RESET(ip, qif, if, fin) send_reset(fin, ip)
-# define ICMP_ERROR(b, ip, t, c, if, dst) \
- send_icmp_err(ip, t, c, if, dst)
-# endif /* linux */
+# define SEND_RESET(ip, qif, if, fin) send_reset(fin, ip)
# endif /* SOLARIS || __sgi */
#endif /* _KERNEL */
struct filterstats frstats[2] = {{0,0,0,0,0},{0,0,0,0,0}};
struct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } },
+#ifdef USE_INET6
+ *ipfilter6[2][2] = { { NULL, NULL }, { NULL, NULL } },
+ *ipacct6[2][2] = { { NULL, NULL }, { NULL, NULL } },
+#endif
*ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } };
struct frgroup *ipfgroups[3][2];
-int fr_flags = IPF_LOGGING, fr_active = 0;
+int fr_flags = IPF_LOGGING;
+int fr_active = 0;
+int fr_chksrc = 0;
#if defined(IPFILTER_DEFAULT_BLOCK)
int fr_pass = FR_NOMATCH|FR_BLOCK;
#else
@@ -147,7 +146,6 @@ char ipfilter_version[] = IPL_VERSION;
fr_info_t frcache[2];
-static int fr_tcpudpchk __P((frentry_t *, fr_info_t *));
static int frflushlist __P((int, minor_t, int *, frentry_t **));
#ifdef _KERNEL
static void frsynclist __P((frentry_t *));
@@ -204,12 +202,12 @@ int hlen;
ip_t *ip;
fr_info_t *fin;
{
- struct optlist *op;
- tcphdr_t *tcp;
- fr_ip_t *fi = &fin->fin_fi;
u_short optmsk = 0, secmsk = 0, auth = 0;
- int i, mv, ol, off;
+ int i, mv, ol, off, p, plen, v;
+ fr_ip_t *fi = &fin->fin_fi;
+ struct optlist *op;
u_char *s, opt;
+ tcphdr_t *tcp;
fin->fin_rev = 0;
fin->fin_fr = NULL;
@@ -218,25 +216,59 @@ fr_info_t *fin;
fin->fin_data[1] = 0;
fin->fin_rule = -1;
fin->fin_group = -1;
- fin->fin_id = ip->ip_id;
#ifdef _KERNEL
fin->fin_icode = ipl_unreach;
#endif
- fi->fi_v = ip->ip_v;
- fi->fi_tos = ip->ip_tos;
+ v = fin->fin_v;
+ fi->fi_v = v;
fin->fin_hlen = hlen;
- fin->fin_dlen = ip->ip_len - hlen;
- tcp = (tcphdr_t *)((char *)ip + hlen);
+ if (v == 4) {
+ fin->fin_id = ip->ip_id;
+ fi->fi_tos = ip->ip_tos;
+ off = (ip->ip_off & IP_OFFMASK) << 3;
+ tcp = (tcphdr_t *)((char *)ip + hlen);
+ (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4));
+ fi->fi_src.i6[1] = 0;
+ fi->fi_src.i6[2] = 0;
+ fi->fi_src.i6[3] = 0;
+ fi->fi_dst.i6[1] = 0;
+ fi->fi_dst.i6[2] = 0;
+ fi->fi_dst.i6[3] = 0;
+ fi->fi_saddr = ip->ip_src.s_addr;
+ fi->fi_daddr = ip->ip_dst.s_addr;
+ p = ip->ip_p;
+ fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0;
+ if (ip->ip_off & 0x3fff)
+ fi->fi_fl |= FI_FRAG;
+ plen = ip->ip_len;
+ fin->fin_dlen = plen - hlen;
+ }
+#ifdef USE_INET6
+ else if (v == 6) {
+ ip6_t *ip6 = (ip6_t *)ip;
+
+ off = 0;
+ p = ip6->ip6_nxt;
+ fi->fi_p = p;
+ fi->fi_ttl = ip6->ip6_hlim;
+ tcp = (tcphdr_t *)(ip6 + 1);
+ fi->fi_src.in6 = ip6->ip6_src;
+ fi->fi_dst.in6 = ip6->ip6_dst;
+ fin->fin_id = (u_short)(ip6->ip6_flow & 0xffff);
+ fi->fi_tos = 0;
+ fi->fi_fl = 0;
+ plen = ntohs(ip6->ip6_plen);
+ fin->fin_dlen = plen;
+ }
+#endif
+ else
+ return;
+
+ fin->fin_off = off;
+ fin->fin_plen = plen;
fin->fin_dp = (void *)tcp;
- (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4));
- fi->fi_src.s_addr = ip->ip_src.s_addr;
- fi->fi_dst.s_addr = ip->ip_dst.s_addr;
-
- fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0;
- off = (ip->ip_off & IP_OFFMASK) << 3;
- if (ip->ip_off & 0x3fff)
- fi->fi_fl |= FI_FRAG;
- switch (ip->ip_p)
+
+ switch (p)
{
case IPPROTO_ICMP :
{
@@ -248,13 +280,19 @@ fr_info_t *fin;
if (!off && (icmp->icmp_type == ICMP_ECHOREPLY ||
icmp->icmp_type == ICMP_ECHO))
minicmpsz = ICMP_MINLEN;
- if (!off && (icmp->icmp_type == ICMP_TSTAMP ||
- icmp->icmp_type == ICMP_TSTAMPREPLY))
- minicmpsz = 20; /* type(1) + code(1) + cksum(2) + id(2) + seq(2) + 3*timestamp(3*4) */
- if (!off && (icmp->icmp_type == ICMP_MASKREQ ||
- icmp->icmp_type == ICMP_MASKREPLY))
- minicmpsz = 12; /* type(1) + code(1) + cksum(2) + id(2) + seq(2) + mask(4) */
- if ((!(ip->ip_len >= hlen + minicmpsz) && !off) ||
+
+ /* type(1) + code(1) + cksum(2) + id(2) seq(2) +
+ * 3*timestamp(3*4) */
+ else if (!off && (icmp->icmp_type == ICMP_TSTAMP ||
+ icmp->icmp_type == ICMP_TSTAMPREPLY))
+ minicmpsz = 20;
+
+ /* type(1) + code(1) + cksum(2) + id(2) seq(2) + mask(4) */
+ else if (!off && (icmp->icmp_type == ICMP_MASKREQ ||
+ icmp->icmp_type == ICMP_MASKREPLY))
+ minicmpsz = 12;
+
+ if ((!(plen >= hlen + minicmpsz) && !off) ||
(off && off < sizeof(struct icmp)))
fi->fi_fl |= FI_SHORT;
if (fin->fin_dlen > 1)
@@ -263,17 +301,33 @@ fr_info_t *fin;
}
case IPPROTO_TCP :
fi->fi_fl |= FI_TCPUDP;
- if ((!IPMINLEN(ip, tcphdr) && !off) ||
- (off && off < sizeof(struct tcphdr)))
- fi->fi_fl |= FI_SHORT;
+#ifdef USE_INET6
+ if (v == 6) {
+ if (plen < sizeof(struct tcphdr))
+ fi->fi_fl |= FI_SHORT;
+ } else
+#endif
+ if (v == 4) {
+ if ((!IPMINLEN(ip, tcphdr) && !off) ||
+ (off && off < sizeof(struct tcphdr)))
+ fi->fi_fl |= FI_SHORT;
+ }
if (!(fi->fi_fl & FI_SHORT) && !off)
fin->fin_tcpf = tcp->th_flags;
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;
+#ifdef USE_INET6
+ if (v == 6) {
+ if (plen < sizeof(struct udphdr))
+ fi->fi_fl |= FI_SHORT;
+ } else
+#endif
+ if (v == 4) {
+ 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);
@@ -284,6 +338,14 @@ getports:
break;
}
+#ifdef USE_INET6
+ if (v == 6) {
+ fi->fi_optmsk = 0;
+ fi->fi_secmsk = 0;
+ fi->fi_auth = 0;
+ return;
+ }
+#endif
for (s = (u_char *)(ip + 1), hlen -= (int)sizeof(*ip); hlen > 0; ) {
opt = *s;
@@ -344,8 +406,8 @@ getports:
/*
* check an IP packet for TCP/UDP characteristics such as ports and flags.
*/
-static int fr_tcpudpchk(fr, fin)
-frentry_t *fr;
+int fr_tcpudpchk(ft, fin)
+frtuc_t *ft;
fr_info_t *fin;
{
register u_short po, tup;
@@ -358,8 +420,8 @@ fr_info_t *fin;
*
* compare destination ports
*/
- if ((i = (int)fr->fr_dcmp)) {
- po = fr->fr_dport;
+ if ((i = (int)ft->ftu_dcmp)) {
+ po = ft->ftu_dport;
tup = fin->fin_data[1];
/*
* Do opposite test to that required and
@@ -378,17 +440,17 @@ fr_info_t *fin;
else if (!--i && tup < po) /* GT or EQ */
err = 0;
else if (!--i && /* Out of range */
- (tup >= po && tup <= fr->fr_dtop))
+ (tup >= po && tup <= ft->ftu_dtop))
err = 0;
else if (!--i && /* In range */
- (tup <= po || tup >= fr->fr_dtop))
+ (tup <= po || tup >= ft->ftu_dtop))
err = 0;
}
/*
* compare source ports
*/
- if (err && (i = (int)fr->fr_scmp)) {
- po = fr->fr_sport;
+ if (err && (i = (int)ft->ftu_scmp)) {
+ po = ft->ftu_sport;
tup = fin->fin_data[0];
if (!--i && tup != po)
err = 0;
@@ -403,10 +465,10 @@ fr_info_t *fin;
else if (!--i && tup < po)
err = 0;
else if (!--i && /* Out of range */
- (tup >= po && tup <= fr->fr_stop))
+ (tup >= po && tup <= ft->ftu_stop))
err = 0;
else if (!--i && /* In range */
- (tup <= po || tup >= fr->fr_stop))
+ (tup <= po || tup >= ft->ftu_stop))
err = 0;
}
@@ -418,14 +480,14 @@ fr_info_t *fin;
*/
if (err && (fin->fin_fi.fi_p == IPPROTO_TCP)) {
if (fin->fin_fi.fi_fl & FI_SHORT)
- return !(fr->fr_tcpf | fr->fr_tcpfm);
+ return !(ft->ftu_tcpf | ft->ftu_tcpfm);
/*
* Match the flags ? If not, abort this match.
*/
- if (fr->fr_tcpfm &&
- fr->fr_tcpf != (fin->fin_tcpf & fr->fr_tcpfm)) {
+ if (ft->ftu_tcpfm &&
+ ft->ftu_tcpf != (fin->fin_tcpf & ft->ftu_tcpfm)) {
FR_DEBUG(("f. %#x & %#x != %#x\n", fin->fin_tcpf,
- fr->fr_tcpfm, fr->fr_tcpf));
+ ft->ftu_tcpfm, ft->ftu_tcpf));
err = 0;
}
}
@@ -452,7 +514,10 @@ void *m;
fin->fin_fr = NULL;
fin->fin_rule = 0;
fin->fin_group = 0;
- off = ip->ip_off & IP_OFFMASK;
+ if (fin->fin_v == 4)
+ off = ip->ip_off & IP_OFFMASK;
+ else
+ off = 0;
pass |= (fi->fi_fl << 24);
if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off)
@@ -496,23 +561,77 @@ void *m;
lip = (u_32_t *)fi;
lm = (u_32_t *)&fr->fr_mip;
ld = (u_32_t *)&fr->fr_ip;
- i = ((lip[0] & lm[0]) != ld[0]);
- FR_IFDEBUG(i,continue,("0. %#08x & %#08x != %#08x\n",
- lip[0], lm[0], ld[0]));
- i |= ((lip[1] & lm[1]) != ld[1]) << 19;
+ i = ((*lip & *lm) != *ld);
+ FR_DEBUG(("0. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ if (i)
+ continue;
+ /*
+ * We now know whether the packet version and the
+ * rule version match, along with protocol, ttl and
+ * tos.
+ */
+ lip++, lm++, ld++;
+ /*
+ * Unrolled loops (4 each, for 32 bits).
+ */
+ i |= ((*lip & *lm) != *ld) << 19;
+ FR_DEBUG(("1a. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ if (fi->fi_v == 6) {
+ lip++, lm++, ld++;
+ i |= ((*lip & *lm) != *ld) << 19;
+ FR_DEBUG(("1b. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ lip++, lm++, ld++;
+ i |= ((*lip & *lm) != *ld) << 19;
+ FR_DEBUG(("1c. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ lip++, lm++, ld++;
+ i |= ((*lip & *lm) != *ld) << 19;
+ FR_DEBUG(("1d. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ } else {
+ lip += 3;
+ lm += 3;
+ ld += 3;
+ }
i ^= (fr->fr_flags & FR_NOTSRCIP);
- FR_IFDEBUG(i,continue,("1. %#08x & %#08x != %#08x\n",
- lip[1], lm[1], ld[1]));
- i |= ((lip[2] & lm[2]) != ld[2]) << 20;
+ if (i)
+ continue;
+ lip++, lm++, ld++;
+ i |= ((*lip & *lm) != *ld) << 20;
+ FR_DEBUG(("2a. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ if (fi->fi_v == 6) {
+ lip++, lm++, ld++;
+ i |= ((*lip & *lm) != *ld) << 20;
+ FR_DEBUG(("2b. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ lip++, lm++, ld++;
+ i |= ((*lip & *lm) != *ld) << 20;
+ FR_DEBUG(("2c. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ lip++, lm++, ld++;
+ i |= ((*lip & *lm) != *ld) << 20;
+ FR_DEBUG(("2d. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ } else {
+ lip += 3;
+ lm += 3;
+ ld += 3;
+ }
i ^= (fr->fr_flags & FR_NOTDSTIP);
- FR_IFDEBUG(i,continue,("2. %#08x & %#08x != %#08x\n",
- lip[2], lm[2], ld[2]));
- i |= ((lip[3] & lm[3]) != ld[3]);
- FR_IFDEBUG(i,continue,("3. %#08x & %#08x != %#08x\n",
- lip[3], lm[3], ld[3]));
- i |= ((lip[4] & lm[4]) != ld[4]);
- FR_IFDEBUG(i,continue,("4. %#08x & %#08x != %#08x\n",
- lip[4], lm[4], ld[4]));
+ if (i)
+ continue;
+ lip++, lm++, ld++;
+ i |= ((*lip & *lm) != *ld);
+ FR_DEBUG(("3. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ lip++, lm++, ld++;
+ i |= ((*lip & *lm) != *ld);
+ FR_DEBUG(("4. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
if (i)
continue;
}
@@ -525,7 +644,7 @@ void *m;
fr->fr_tcpfm))
continue;
if (fi->fi_fl & FI_TCPUDP) {
- if (!fr_tcpudpchk(fr, fin))
+ if (!fr_tcpudpchk(&fr->fr_tuc, fin))
continue;
} else if (fr->fr_icmpm || fr->fr_icmp) {
if ((fi->fi_p != IPPROTO_ICMP) || off ||
@@ -549,16 +668,18 @@ void *m;
#ifdef IPFILTER_LOG
if ((passt & FR_LOGMASK) == FR_LOG) {
if (!IPLLOG(passt, ip, fin, m)) {
- ATOMIC_INC(frstats[fin->fin_out].fr_skip);
+ if (passt & FR_LOGORBLOCK)
+ passt |= FR_BLOCK|FR_QUICK;
+ ATOMIC_INCL(frstats[fin->fin_out].fr_skip);
}
- ATOMIC_INC(frstats[fin->fin_out].fr_pkl);
+ ATOMIC_INCL(frstats[fin->fin_out].fr_pkl);
logged = 1;
}
#endif /* IPFILTER_LOG */
if (!(skip = fr->fr_skip) && (passt & FR_LOGMASK) != FR_LOG)
pass = passt;
FR_DEBUG(("pass %#x\n", pass));
- ATOMIC_INC(fr->fr_hits);
+ ATOMIC_INCL(fr->fr_hits);
if (pass & FR_ACCOUNT)
fr->fr_bytes += (U_QUAD_T)ip->ip_len;
else
@@ -608,8 +729,8 @@ int out;
*/
fr_info_t frinfo, *fc;
register fr_info_t *fin = &frinfo;
- frentry_t *fr = NULL;
- int changed, error = EHOSTUNREACH;
+ int changed, error = EHOSTUNREACH, v = ip->ip_v;
+ frentry_t *fr = NULL, *list;
u_32_t pass, apass;
#if !SOLARIS || !defined(_KERNEL)
register mb_t *m = *mp;
@@ -631,7 +752,7 @@ int out;
*/
m->m_flags &= ~M_CANFASTFWD;
# endif /* M_CANFASTFWD */
-
+# ifdef CSUM_DELAY_DATA
/*
* disable delayed checksums.
*/
@@ -639,6 +760,8 @@ int out;
in_delayed_cksum(m);
m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
}
+# endif /* CSUM_DELAY_DATA */
+
if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ||
ip->ip_p == IPPROTO_ICMP)) {
@@ -664,19 +787,19 @@ int out;
# ifdef __sgi
/* Under IRIX, avoid m_pullup as it makes ping <hostname> panic */
if ((up > sizeof(hbuf)) || (m_length(m) < up)) {
- ATOMIC_INC(frstats[out].fr_pull[1]);
+ ATOMIC_INCL(frstats[out].fr_pull[1]);
return -1;
}
m_copydata(m, 0, up, hbuf);
- ATOMIC_INC(frstats[out].fr_pull[0]);
+ ATOMIC_INCL(frstats[out].fr_pull[0]);
ip = (ip_t *)hbuf;
# else /* __ sgi */
# ifndef linux
if ((*mp = m_pullup(m, up)) == 0) {
- ATOMIC_INC(frstats[out].fr_pull[1]);
+ ATOMIC_INCL(frstats[out].fr_pull[1]);
return -1;
} else {
- ATOMIC_INC(frstats[out].fr_pull[0]);
+ ATOMIC_INCL(frstats[out].fr_pull[0]);
m = *mp;
ip = mtod(m, ip_t *);
}
@@ -695,24 +818,43 @@ int out;
fin->fin_qfm = m;
fin->fin_qif = qif;
# endif
+# ifdef USE_INET6
+ if (v == 6) {
+ ATOMIC_INCL(frstats[0].fr_ipv6[out]);
+ } else
+# endif
+ if (!out && fr_chksrc && !fr_verifysrc(ip->ip_src, ifp)) {
+ ATOMIC_INCL(frstats[0].fr_badsrc);
+# if !SOLARIS
+ m_freem(m);
+# endif
+ return error;
+ }
#endif /* _KERNEL */
-
+
/*
* Be careful here: ip_id is in network byte order when called
* from ip_output()
*/
- if (out)
+ if ((out) && (v == 4))
ip->ip_id = ntohs(ip->ip_id);
- fr_makefrip(hlen, ip, fin);
+
+ changed = 0;
+ fin->fin_v = v;
fin->fin_ifp = ifp;
fin->fin_out = out;
fin->fin_mp = mp;
+ fr_makefrip(hlen, ip, fin);
pass = fr_pass;
+ if (fin->fin_fi.fi_fl & FI_SHORT) {
+ ATOMIC_INCL(frstats[out].fr_short);
+ }
+
READ_ENTER(&ipf_mutex);
if (fin->fin_fi.fi_fl & FI_SHORT)
- ATOMIC_INC(frstats[out].fr_short);
+ ATOMIC_INCL(frstats[out].fr_short);
/*
* Check auth now. This, combined with the check below to see if apass
@@ -724,10 +866,16 @@ int out;
apass = fr_checkauth(ip, fin);
if (!out) {
+#ifdef USE_INET6
+ if (v == 6)
+ list = ipacct6[0][fr_active];
+ else
+#endif
+ list = ipacct[0][fr_active];
changed = ip_natin(ip, fin);
- if (!apass && (fin->fin_fr = ipacct[0][fr_active]) &&
+ if (!apass && (fin->fin_fr = list) &&
(fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
- ATOMIC_INC(frstats[0].fr_acct);
+ ATOMIC_INCL(frstats[0].fr_acct);
}
}
@@ -746,19 +894,25 @@ int out;
* earlier.
*/
bcopy((char *)fc, (char *)fin, FI_COPYSIZE);
- ATOMIC_INC(frstats[out].fr_chit);
+ ATOMIC_INCL(frstats[out].fr_chit);
if ((fr = fin->fin_fr)) {
- ATOMIC_INC(fr->fr_hits);
+ ATOMIC_INCL(fr->fr_hits);
pass = fr->fr_flags;
}
} else {
- if ((fin->fin_fr = ipfilter[out][fr_active]))
+#ifdef USE_INET6
+ if (v == 6)
+ list = ipfilter6[out][fr_active];
+ else
+#endif
+ list = ipfilter[out][fr_active];
+ if ((fin->fin_fr = list))
pass = fr_scanlist(fr_pass, ip, fin, m);
if (!(pass & (FR_KEEPSTATE|FR_DONTCACHE)))
bcopy((char *)fin, (char *)fc,
FI_COPYSIZE);
if (pass & FR_NOMATCH) {
- ATOMIC_INC(frstats[out].fr_nom);
+ ATOMIC_INCL(frstats[out].fr_nom);
}
}
fr = fin->fin_fr;
@@ -771,7 +925,7 @@ int out;
* then pretend we've dropped it already.
*/
if ((pass & FR_AUTH))
- if (FR_NEWAUTH(m, fin, ip, qif) != 0)
+ if (fr_newauth((mb_t *)m, fin, ip) != 0)
#ifdef _KERNEL
m = *mp = NULL;
#else
@@ -782,9 +936,9 @@ int out;
READ_ENTER(&ipf_auth);
if ((fin->fin_fr = ipauth) &&
(pass = fr_scanlist(0, ip, fin, m))) {
- ATOMIC_INC(fr_authstats.fas_hits);
+ ATOMIC_INCL(fr_authstats.fas_hits);
} else {
- ATOMIC_INC(fr_authstats.fas_miss);
+ ATOMIC_INCL(fr_authstats.fas_miss);
}
RWLOCK_EXIT(&ipf_auth);
}
@@ -793,19 +947,19 @@ int out;
if ((pass & (FR_KEEPFRAG|FR_KEEPSTATE)) == FR_KEEPFRAG) {
if (fin->fin_fi.fi_fl & FI_FRAG) {
if (ipfr_newfrag(ip, fin, pass) == -1) {
- ATOMIC_INC(frstats[out].fr_bnfr);
+ ATOMIC_INCL(frstats[out].fr_bnfr);
} else {
- ATOMIC_INC(frstats[out].fr_nfr);
+ ATOMIC_INCL(frstats[out].fr_nfr);
}
} else {
- ATOMIC_INC(frstats[out].fr_cfr);
+ ATOMIC_INCL(frstats[out].fr_cfr);
}
}
if (pass & FR_KEEPSTATE) {
if (fr_addstate(ip, fin, 0) == NULL) {
- ATOMIC_INC(frstats[out].fr_bads);
+ ATOMIC_INCL(frstats[out].fr_bads);
} else {
- ATOMIC_INC(frstats[out].fr_ads);
+ ATOMIC_INCL(frstats[out].fr_ads);
}
}
} else if (fr != NULL) {
@@ -822,9 +976,15 @@ int out;
* interface.
*/
if (out && (pass & FR_PASS)) {
- if ((fin->fin_fr = ipacct[1][fr_active]) &&
+#ifdef USE_INET6
+ if (v == 6)
+ list = ipacct6[0][fr_active];
+ else
+#endif
+ list = ipacct[0][fr_active];
+ if ((fin->fin_fr = list) &&
(fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
- ATOMIC_INC(frstats[1].fr_acct);
+ ATOMIC_INCL(frstats[1].fr_acct);
}
fin->fin_fr = fr;
changed = ip_natout(ip, fin);
@@ -836,22 +996,22 @@ int out;
if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) {
if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) {
pass |= FF_LOGNOMATCH;
- ATOMIC_INC(frstats[out].fr_npkl);
+ ATOMIC_INCL(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;
- ATOMIC_INC(frstats[out].fr_ppkl);
+ ATOMIC_INCL(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;
- ATOMIC_INC(frstats[out].fr_bpkl);
+ ATOMIC_INCL(frstats[out].fr_bpkl);
logit:
if (!IPLLOG(pass, ip, fin, m)) {
- ATOMIC_INC(frstats[out].fr_skip);
+ ATOMIC_INCL(frstats[out].fr_skip);
if ((pass & (FR_PASS|FR_LOGORBLOCK)) ==
(FR_PASS|FR_LOGORBLOCK))
pass ^= FR_PASS|FR_BLOCK;
@@ -860,7 +1020,7 @@ logit:
}
#endif /* IPFILTER_LOG */
- if (out)
+ if ((out) && (v == 4))
ip->ip_id = htons(ip->ip_id);
#ifdef _KERNEL
@@ -881,9 +1041,9 @@ logit:
# endif
#endif
if (pass & FR_PASS) {
- ATOMIC_INC(frstats[out].fr_pass);
+ ATOMIC_INCL(frstats[out].fr_pass);
} else if (pass & FR_BLOCK) {
- ATOMIC_INC(frstats[out].fr_block);
+ ATOMIC_INCL(frstats[out].fr_block);
/*
* Should we return an ICMP packet to indicate error
* status passing through the packet filter ?
@@ -895,37 +1055,31 @@ logit:
if (!out) {
#ifdef _KERNEL
if (pass & FR_RETICMP) {
- struct in_addr dst;
+ int dst;
if ((pass & FR_RETMASK) == FR_FAKEICMP)
- dst = ip->ip_dst;
+ dst = 1;
else
- dst.s_addr = 0;
-# if SOLARIS
- ICMP_ERROR(q, ip, ICMP_UNREACH, fin->fin_icode,
- qif, dst);
-# else
- ICMP_ERROR(m, ip, ICMP_UNREACH, fin->fin_icode,
- ifp, dst);
-# endif
- ATOMIC_INC(frstats[0].fr_ret);
+ dst = 0;
+ send_icmp_err(ip, ICMP_UNREACH, fin, dst);
+ ATOMIC_INCL(frstats[0].fr_ret);
} else if (((pass & FR_RETMASK) == FR_RETRST) &&
!(fin->fin_fi.fi_fl & FI_SHORT)) {
- if (SEND_RESET(ip, qif, ifp, fin) == 0) {
- ATOMIC_INC(frstats[1].fr_ret);
+ if (send_reset(ip, fin) == 0) {
+ ATOMIC_INCL(frstats[1].fr_ret);
}
}
#else
if ((pass & FR_RETMASK) == FR_RETICMP) {
verbose("- ICMP unreachable sent\n");
- ATOMIC_INC(frstats[0].fr_ret);
+ ATOMIC_INCL(frstats[0].fr_ret);
} else if ((pass & FR_RETMASK) == FR_FAKEICMP) {
verbose("- forged ICMP unreachable sent\n");
- ATOMIC_INC(frstats[0].fr_ret);
+ ATOMIC_INCL(frstats[0].fr_ret);
} else if (((pass & FR_RETMASK) == FR_RETRST) &&
!(fin->fin_fi.fi_fl & FI_SHORT)) {
verbose("- TCP RST sent\n");
- ATOMIC_INC(frstats[1].fr_ret);
+ ATOMIC_INCL(frstats[1].fr_ret);
}
#endif
} else {
@@ -941,6 +1095,10 @@ logit:
* Once we're finished return to our caller, freeing the packet if
* we are dropping it (* BSD ONLY *).
*/
+ if ((changed == -1) && (pass & FR_PASS)) {
+ pass &= ~FR_PASS;
+ pass |= FR_BLOCK;
+ }
#if defined(_KERNEL)
# if !SOLARIS
# if !defined(linux)
@@ -1204,7 +1362,7 @@ nodata:
* SUCH DAMAGE.
*
* @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
- * $Id: fil.c,v 2.3.2.16 2000/01/27 08:49:37 darrenr Exp $
+ * $Id: fil.c,v 2.35.2.8 2000/05/22 10:26:09 darrenr Exp $
*/
/*
* Copy data from an mbuf chain starting "off" bytes from the beginning,
@@ -1304,8 +1462,7 @@ out:
frgroup_t *fr_findgroup(num, flags, which, set, fgpp)
-u_int num;
-u_32_t flags;
+u_32_t num, flags;
minor_t which;
int set;
frgroup_t ***fgpp;
@@ -1334,7 +1491,7 @@ frgroup_t ***fgpp;
frgroup_t *fr_addgroup(num, fp, which, set)
-u_int num;
+u_32_t num;
frentry_t *fp;
minor_t which;
int set;
@@ -1357,8 +1514,7 @@ int set;
void fr_delgroup(num, flags, which, set)
-u_int num;
-u_32_t flags;
+u_32_t num, flags;
minor_t which;
int set;
{
@@ -1396,11 +1552,11 @@ frentry_t **listp;
MUTEX_EXIT(&ipf_rw);
}
- ATOMIC_DEC(fp->fr_ref);
+ ATOMIC_DEC32(fp->fr_ref);
if (fp->fr_grhead) {
- fr_delgroup((u_int)fp->fr_grhead, fp->fr_flags,
+ fr_delgroup(fp->fr_grhead, fp->fr_flags,
unit, set);
- fp->fr_grhead = NULL;
+ fp->fr_grhead = 0;
}
if (fp->fr_ref == 0) {
KFREE(fp);
@@ -1429,10 +1585,18 @@ int flags;
set = 1 - set;
if (flags & FR_OUTQUE) {
+#ifdef USE_INET6
+ (void) frflushlist(set, unit, &flushed, &ipfilter6[1][set]);
+ (void) frflushlist(set, unit, &flushed, &ipacct6[1][set]);
+#endif
(void) frflushlist(set, unit, &flushed, &ipfilter[1][set]);
(void) frflushlist(set, unit, &flushed, &ipacct[1][set]);
}
if (flags & FR_INQUE) {
+#ifdef USE_INET6
+ (void) frflushlist(set, unit, &flushed, &ipfilter6[0][set]);
+ (void) frflushlist(set, unit, &flushed, &ipacct6[0][set]);
+#endif
(void) frflushlist(set, unit, &flushed, &ipfilter[0][set]);
(void) frflushlist(set, unit, &flushed, &ipacct[0][set]);
}
@@ -1511,10 +1675,14 @@ u_32_t ip;
/*
* return the first IP Address associated with an interface
*/
-int fr_ifpaddr(ifptr, inp)
+int fr_ifpaddr(v, ifptr, inp)
+int v;
void *ifptr;
struct in_addr *inp;
{
+# ifdef USE_INET6
+ struct in6_addr *inp6 = NULL;
+# endif
# if SOLARIS
ill_t *ill = ifptr;
# else
@@ -1523,13 +1691,30 @@ struct in_addr *inp;
struct in_addr in;
# if SOLARIS
- in.s_addr = ill->ill_ipif->ipif_local_addr;
+# ifdef USE_INET6
+ if (v == 6) {
+ struct in6_addr in6;
+
+ /*
+ * First is always link local.
+ */
+ if (ill->ill_ipif->ipif_next)
+ in6 = ill->ill_ipif->ipif_next->ipif_v6lcl_addr;
+ else
+ bzero((char *)&in6, sizeof(in6));
+ bcopy((char *)&in6, (char *)inp, sizeof(in6));
+ } else
+# endif
+ {
+ in.s_addr = ill->ill_ipif->ipif_local_addr;
+ *inp = in;
+ }
# else /* SOLARIS */
# if linux
;
# else /* linux */
- struct ifaddr *ifa;
struct sockaddr_in *sin;
+ struct ifaddr *ifa;
# if (__FreeBSD_version >= 300000)
ifa = TAILQ_FIRST(&ifp->if_addrhead);
@@ -1548,8 +1733,17 @@ struct in_addr *inp;
sin = (struct sockaddr_in *)&ifa->ifa_addr;
# else
sin = (struct sockaddr_in *)ifa->ifa_addr;
- while (sin && ifa &&
- sin->sin_family != AF_INET) {
+ while (sin && ifa) {
+ if ((v == 4) && (sin->sin_family == AF_INET))
+ break;
+# ifdef USE_INET6
+ if ((v == 6) && (sin->sin_family == AF_INET6)) {
+ inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr;
+ if (!IN6_IS_ADDR_LINKLOCAL(inp6) &&
+ !IN6_IS_ADDR_LOOPBACK(inp6))
+ break;
+ }
+# endif
# if (__FreeBSD_version >= 300000)
ifa = TAILQ_NEXT(ifa, ifa_link);
# else
@@ -1567,10 +1761,17 @@ struct in_addr *inp;
if (sin == NULL)
return -1;
# endif /* (BSD < 199306) && (!__sgi && IFF_DRVLOCK) */
- in = sin->sin_addr;
+# ifdef USE_INET6
+ if (v == 6)
+ bcopy((char *)inp6, (char *)inp, sizeof(*inp6));
+ else
+# endif
+ {
+ in = sin->sin_addr;
+ *inp = in;
+ }
# endif /* linux */
# endif /* SOLARIS */
- *inp = in;
return 0;
}
@@ -1580,7 +1781,7 @@ register frentry_t *fr;
{
for (; fr; fr = fr->fr_next) {
if (fr->fr_ifa != NULL) {
- fr->fr_ifa = GETUNIT(fr->fr_ifname);
+ fr->fr_ifa = GETUNIT(fr->fr_ifname, fr->fr_ip.fi_v);
if (fr->fr_ifa == NULL)
fr->fr_ifa = (void *)-1;
}
@@ -1592,9 +1793,9 @@ register frentry_t *fr;
void frsync()
{
+# if !SOLARIS
register struct ifnet *ifp;
-# if !SOLARIS
# if defined(__OpenBSD__) || ((NetBSD >= 199511) && (NetBSD < 1991011)) || \
(defined(__FreeBSD_version) && (__FreeBSD_version >= 300000))
# if (NetBSD >= 199905) || defined(__OpenBSD__)
@@ -1616,19 +1817,197 @@ void frsync()
frsynclist(ipacct[1][fr_active]);
frsynclist(ipfilter[0][fr_active]);
frsynclist(ipfilter[1][fr_active]);
+#ifdef USE_INET6
+ frsynclist(ipacct6[0][fr_active]);
+ frsynclist(ipacct6[1][fr_active]);
+ frsynclist(ipfilter6[0][fr_active]);
+ frsynclist(ipfilter6[1][fr_active]);
+#endif
RWLOCK_EXIT(&ipf_mutex);
}
+
+/*
+ * In the functions below, bcopy() is called because the pointer being
+ * copied _from_ in this instance is a pointer to a char buf (which could
+ * end up being unaligned) and on the kernel's local stack.
+ */
+int ircopyptr(a, b, c)
+void *a, *b;
+size_t c;
+{
+ caddr_t ca;
+ int err;
+
+#if SOLARIS
+ copyin(a, &ca, sizeof(ca));
+#else
+ bcopy(a, &ca, sizeof(ca));
+#endif
+ err = copyin(ca, b, c);
+ return err;
+}
+
+
+int iwcopyptr(a, b, c)
+void *a, *b;
+size_t c;
+{
+ caddr_t ca;
+ int err;
+
+#if SOLARIS
+ copyin(b, &ca, sizeof(ca));
#else
+ bcopy(b, &ca, sizeof(ca));
+#endif
+ err = copyout(a, ca, c);
+ return err;
+}
+
+#else /* _KERNEL */
/*
* return the first IP Address associated with an interface
*/
-int fr_ifpaddr(ifptr, inp)
+int fr_ifpaddr(v, ifptr, inp)
+int v;
void *ifptr;
struct in_addr *inp;
{
return 0;
}
-#endif
+
+
+int ircopyptr(a, b, c)
+void *a, *b;
+size_t c;
+{
+ caddr_t ca;
+
+ bcopy(a, &ca, sizeof(ca));
+ bcopy(ca, b, c);
+ return 0;
+}
+
+
+int iwcopyptr(a, b, c)
+void *a, *b;
+size_t c;
+{
+ caddr_t ca;
+
+ bcopy(b, &ca, sizeof(ca));
+ bcopy(a, ca, c);
+ return 0;
+}
+
+
+#endif
+
+
+int fr_lock(data, lockp)
+caddr_t data;
+int *lockp;
+{
+ int arg, error;
+
+ error = IRCOPY(data, (caddr_t)&arg, sizeof(arg));
+ if (!error) {
+ error = IWCOPY((caddr_t)lockp, data, sizeof(*lockp));
+ if (!error)
+ *lockp = arg;
+ }
+ return error;
+}
+
+
+void fr_getstat(fiop)
+friostat_t *fiop;
+{
+ bcopy((char *)frstats, (char *)fiop->f_st, sizeof(filterstats_t) * 2);
+ fiop->f_locks[0] = fr_state_lock;
+ fiop->f_locks[1] = fr_nat_lock;
+ fiop->f_locks[2] = fr_frag_lock;
+ fiop->f_locks[3] = fr_auth_lock;
+ fiop->f_fin[0] = ipfilter[0][0];
+ fiop->f_fin[1] = ipfilter[0][1];
+ fiop->f_fout[0] = ipfilter[1][0];
+ fiop->f_fout[1] = ipfilter[1][1];
+ fiop->f_acctin[0] = ipacct[0][0];
+ fiop->f_acctin[1] = ipacct[0][1];
+ fiop->f_acctout[0] = ipacct[1][0];
+ fiop->f_acctout[1] = ipacct[1][1];
+#ifdef USE_INET6
+ fiop->f_fin6[0] = ipfilter6[0][0];
+ fiop->f_fin6[1] = ipfilter6[0][1];
+ fiop->f_fout6[0] = ipfilter6[1][0];
+ fiop->f_fout6[1] = ipfilter6[1][1];
+ fiop->f_acctin6[0] = ipacct6[0][0];
+ fiop->f_acctin6[1] = ipacct6[0][1];
+ fiop->f_acctout6[0] = ipacct6[1][0];
+ fiop->f_acctout6[1] = ipacct6[1][1];
+#endif
+ fiop->f_active = fr_active;
+ fiop->f_froute[0] = ipl_frouteok[0];
+ fiop->f_froute[1] = ipl_frouteok[1];
+
+ fiop->f_running = fr_running;
+ fiop->f_groups[0][0] = ipfgroups[0][0];
+ fiop->f_groups[0][1] = ipfgroups[0][1];
+ fiop->f_groups[1][0] = ipfgroups[1][0];
+ fiop->f_groups[1][1] = ipfgroups[1][1];
+ fiop->f_groups[2][0] = ipfgroups[2][0];
+ fiop->f_groups[2][1] = ipfgroups[2][1];
+#ifdef IPFILTER_LOG
+ fiop->f_logging = 1;
+#else
+ fiop->f_logging = 0;
+#endif
+ fiop->f_defpass = fr_pass;
+ strncpy(fiop->f_version, ipfilter_version, sizeof(fiop->f_version));
+}
+
+
+#ifdef USE_INET6
+int icmptoicmp6types[ICMP_MAXTYPE+1] = {
+ ICMP6_ECHO_REPLY, /* 0: ICMP_ECHOREPLY */
+ -1, /* 1: UNUSED */
+ -1, /* 2: UNUSED */
+ ICMP6_DST_UNREACH, /* 3: ICMP_UNREACH */
+ -1, /* 4: ICMP_SOURCEQUENCH */
+ ND_REDIRECT, /* 5: ICMP_REDIRECT */
+ -1, /* 6: UNUSED */
+ -1, /* 7: UNUSED */
+ ICMP6_ECHO_REQUEST, /* 8: ICMP_ECHO */
+ -1, /* 9: UNUSED */
+ -1, /* 10: UNUSED */
+ ICMP6_TIME_EXCEEDED, /* 11: ICMP_TIMXCEED */
+ ICMP6_PARAM_PROB, /* 12: ICMP_PARAMPROB */
+ -1, /* 13: ICMP_TSTAMP */
+ -1, /* 14: ICMP_TSTAMPREPLY */
+ -1, /* 15: ICMP_IREQ */
+ -1, /* 16: ICMP_IREQREPLY */
+ -1, /* 17: ICMP_MASKREQ */
+ -1, /* 18: ICMP_MASKREPLY */
+};
+
+
+int icmptoicmp6unreach[ICMP_MAX_UNREACH] = {
+ ICMP6_DST_UNREACH_ADDR, /* 0: ICMP_UNREACH_NET */
+ ICMP6_DST_UNREACH_ADDR, /* 1: ICMP_UNREACH_HOST */
+ -1, /* 2: ICMP_UNREACH_PROTOCOL */
+ ICMP6_DST_UNREACH_NOPORT, /* 3: ICMP_UNREACH_PORT */
+ -1, /* 4: ICMP_UNREACH_NEEDFRAG */
+ ICMP6_DST_UNREACH_NOTNEIGHBOR, /* 5: ICMP_UNREACH_SRCFAIL */
+ ICMP6_DST_UNREACH_ADDR, /* 6: ICMP_UNREACH_NET_UNKNOWN */
+ ICMP6_DST_UNREACH_ADDR, /* 7: ICMP_UNREACH_HOST_UNKNOWN */
+ -1, /* 8: ICMP_UNREACH_ISOLATED */
+ ICMP6_DST_UNREACH_ADMIN, /* 9: ICMP_UNREACH_NET_PROHIB */
+ ICMP6_DST_UNREACH_ADMIN, /* 10: ICMP_UNREACH_HOST_PROHIB */
+ -1, /* 11: ICMP_UNREACH_TOSNET */
+ -1, /* 12: ICMP_UNREACH_TOSHOST */
+ ICMP6_DST_UNREACH_ADMIN, /* 13: ICMP_UNREACH_ADMIN_PROHIBIT */
+};
+#endif
diff --git a/sys/contrib/ipfilter/netinet/ip_auth.c b/sys/contrib/ipfilter/netinet/ip_auth.c
index 045edaa..6c61bfd 100644
--- a/sys/contrib/ipfilter/netinet/ip_auth.c
+++ b/sys/contrib/ipfilter/netinet/ip_auth.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1998 by Darren Reed & Guido van Rooij.
+ * Copyright (C) 1998-2000 by Darren Reed & Guido van Rooij.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
@@ -20,7 +20,7 @@ static const char rcsid[] = "@(#)$FreeBSD$";
# include <stdlib.h>
# include <string.h>
#endif
-#if defined(_KERNEL) && (__FreeBSD_version >= 220000)
+#if (defined(KERNEL) || defined(_KERNEL)) && (__FreeBSD_version >= 220000)
# include <sys/filio.h>
# include <sys/fcntl.h>
#else
@@ -124,11 +124,12 @@ static struct wait_queue *ipfauthwait = NULL;
int fr_authsize = FR_NUMAUTH;
int fr_authused = 0;
int fr_defaultauthage = 600;
+int fr_auth_lock = 0;
fr_authstat_t fr_authstats;
-frauth_t fr_auth[FR_NUMAUTH];
+static frauth_t fr_auth[FR_NUMAUTH];
mb_t *fr_authpkts[FR_NUMAUTH];
-int fr_authstart = 0, fr_authend = 0, fr_authnext = 0;
-frauthent_t *fae_list = NULL;
+static int fr_authstart = 0, fr_authend = 0, fr_authnext = 0;
+static frauthent_t *fae_list = NULL;
frentry_t *ipauth = NULL;
@@ -145,6 +146,9 @@ fr_info_t *fin;
u_32_t pass;
int i;
+ if (fr_auth_lock)
+ return 0;
+
READ_ENTER(&ipf_auth);
for (i = fr_authstart; i != fr_authend; ) {
/*
@@ -197,19 +201,19 @@ fr_info_t *fin;
* If we do, store it and wake up any user programs which are waiting to
* hear about these events.
*/
-int fr_newauth(m, fin, ip
-#if defined(_KERNEL) && SOLARIS
-, qif)
-qif_t *qif;
-#else
-)
-#endif
+int fr_newauth(m, fin, ip)
mb_t *m;
fr_info_t *fin;
ip_t *ip;
{
+#if defined(_KERNEL) && SOLARIS
+ qif_t *qif = fin->fin_qif;
+#endif
int i;
+ if (fr_auth_lock)
+ return 0;
+
WRITE_ENTER(&ipf_auth);
if (fr_authstart > fr_authend) {
fr_authstats.fas_nospace++;
@@ -239,14 +243,15 @@ ip_t *ip;
* them.
*/
# if SOLARIS && defined(_KERNEL)
- if (ip == (ip_t *)m->b_rptr)
+ if ((ip == (ip_t *)m->b_rptr) && (ip->ip_v == 4))
# endif
{
register u_short bo;
bo = ip->ip_len;
ip->ip_len = htons(bo);
-# if !SOLARIS /* 4.4BSD converts this ip_input.c, but I don't in solaris.c */
+# if !SOLARIS && !defined(__NetBSD__)
+ /* 4.4BSD converts this ip_input.c, but I don't in solaris.c */
bo = ip->ip_id;
ip->ip_id = htons(bo);
# endif
@@ -273,7 +278,7 @@ ip_t *ip;
int fr_auth_ioctl(data, cmd, fr, frptr)
caddr_t data;
-#if defined(__NetBSD__) || defined(__OpenBSD__)
+#if defined(__NetBSD__) || defined(__OpenBSD__) || (FreeBSD_version >= 300003)
u_long cmd;
#else
int cmd;
@@ -281,11 +286,8 @@ int cmd;
frentry_t *fr, **frptr;
{
mb_t *m;
-#if defined(_KERNEL)
-# if !SOLARIS
+#if defined(_KERNEL) && !SOLARIS
struct ifqueue *ifq;
- int s;
-# endif
#endif
frauth_t auth, *au = &auth;
frauthent_t *fae, **faep;
@@ -293,12 +295,17 @@ frentry_t *fr, **frptr;
switch (cmd)
{
+ case SIOCSTLCK :
+ error = fr_lock(data, &fr_auth_lock);
+ break;
case SIOCINIFR :
case SIOCRMIFR :
case SIOCADIFR :
error = EINVAL;
break;
case SIOCINAFR :
+ error = EINVAL;
+ break;
case SIOCRMAFR :
case SIOCADAFR :
for (faep = &fae_list; (fae = *faep); )
@@ -319,8 +326,8 @@ frentry_t *fr, **frptr;
} else {
KMALLOC(fae, frauthent_t *);
if (fae != NULL) {
- IRCOPY((char *)data, (char *)&fae->fae_fr,
- sizeof(fae->fae_fr));
+ bcopy((char *)fr, (char *)&fae->fae_fr,
+ sizeof(*fr));
WRITE_ENTER(&ipf_auth);
fae->fae_age = fr_defaultauthage;
fae->fae_fr.fr_hits = 0;
@@ -338,15 +345,18 @@ frentry_t *fr, **frptr;
READ_ENTER(&ipf_auth);
fr_authstats.fas_faelist = fae_list;
RWLOCK_EXIT(&ipf_auth);
- IWCOPY((char *)&fr_authstats, data, sizeof(fr_authstats));
+ error = IWCOPYPTR((char *)&fr_authstats, data,
+ sizeof(fr_authstats));
break;
case SIOCAUTHW:
fr_authioctlloop:
READ_ENTER(&ipf_auth);
if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) {
- IWCOPY((char *)&fr_auth[fr_authnext], data,
- sizeof(fr_info_t));
+ error = IWCOPYPTR((char *)&fr_auth[fr_authnext], data,
+ sizeof(fr_info_t));
RWLOCK_EXIT(&ipf_auth);
+ if (error)
+ break;
WRITE_ENTER(&ipf_auth);
fr_authnext++;
if (fr_authnext == FR_NUMAUTH)
@@ -377,9 +387,10 @@ fr_authioctlloop:
goto fr_authioctlloop;
break;
case SIOCAUTHR:
- IRCOPY(data, (caddr_t)&auth, sizeof(auth));
+ error = IRCOPYPTR(data, (caddr_t)&auth, sizeof(auth));
+ if (error)
+ return error;
WRITE_ENTER(&ipf_auth);
- i = au->fra_index;
if ((i < 0) || (i > FR_NUMAUTH) ||
(fr_auth[i].fra_info.fin_id != au->fra_info.fin_id)) {
RWLOCK_EXIT(&ipf_auth);
@@ -391,7 +402,6 @@ fr_authioctlloop:
fr_authpkts[i] = NULL;
#ifdef _KERNEL
RWLOCK_EXIT(&ipf_auth);
- SPL_NET(s);
# ifndef linux
if (m && au->fra_info.fin_out) {
# if SOLARIS
@@ -457,7 +467,6 @@ fr_authioctlloop:
}
}
# endif
- SPL_X(s);
#endif /* _KERNEL */
break;
default :
@@ -511,6 +520,9 @@ void fr_authexpire()
int s;
#endif
+ if (fr_auth_lock)
+ return;
+
SPL_NET(s);
WRITE_ENTER(&ipf_auth);
for (i = 0, fra = fr_auth; i < FR_NUMAUTH; i++, fra++) {
diff --git a/sys/contrib/ipfilter/netinet/ip_auth.h b/sys/contrib/ipfilter/netinet/ip_auth.h
index e6b5a59..8be860c 100644
--- a/sys/contrib/ipfilter/netinet/ip_auth.h
+++ b/sys/contrib/ipfilter/netinet/ip_auth.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1997-1998 by Darren Reed & Guido Van Rooij.
+ * Copyright (C) 1997-2000 by Darren Reed & Guido Van Rooij.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
@@ -51,15 +51,12 @@ extern int fr_authstart;
extern int fr_authend;
extern int fr_authsize;
extern int fr_authused;
+extern int fr_auth_lock;
extern u_32_t fr_checkauth __P((ip_t *, fr_info_t *));
extern void fr_authexpire __P((void));
extern void fr_authunload __P((void));
extern mb_t *fr_authpkts[];
-#if defined(_KERNEL) && SOLARIS
-extern int fr_newauth __P((mb_t *, fr_info_t *, ip_t *, qif_t *));
-#else
extern int fr_newauth __P((mb_t *, fr_info_t *, ip_t *));
-#endif
#if defined(__NetBSD__) || defined(__OpenBSD__)
extern int fr_auth_ioctl __P((caddr_t, u_long, frentry_t *, frentry_t **));
#else
diff --git a/sys/netinet/fil.c b/sys/netinet/fil.c
index 8dea84b..f16163e 100644
--- a/sys/netinet/fil.c
+++ b/sys/netinet/fil.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1993-1998 by Darren Reed.
+ * Copyright (C) 1993-2000 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
@@ -11,6 +11,10 @@ static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed";
static const char rcsid[] = "@(#)$FreeBSD$";
#endif
+#if defined(_KERNEL) && defined(__FreeBSD_version) && \
+ (__FreeBSD_version >= 400000) && !defined(KLD_MODULE)
+#include "opt_inet6.h"
+#endif
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/param.h>
@@ -20,7 +24,7 @@ static const char rcsid[] = "@(#)$FreeBSD$";
defined(_KERNEL)
# include "opt_ipfilter_log.h"
#endif
-#if defined(_KERNEL) && defined(__FreeBSD_version) && \
+#if (defined(KERNEL) || defined(_KERNEL)) && defined(__FreeBSD_version) && \
(__FreeBSD_version >= 220000)
# include <sys/filio.h>
# include <sys/fcntl.h>
@@ -69,6 +73,12 @@ static const char rcsid[] = "@(#)$FreeBSD$";
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include "netinet/ip_compat.h"
+#ifdef USE_INET6
+# include <netinet/icmp6.h>
+# if !SOLARIS && defined(_KERNEL)
+# include <netinet6/in6_var.h>
+# endif
+#endif
#include <netinet/tcpip.h>
#include "netinet/ip_fil.h"
#include "netinet/ip_proxy.h"
@@ -94,18 +104,10 @@ static const char rcsid[] = "@(#)$FreeBSD$";
# include "ipt.h"
extern int opts;
-# define FR_IFVERBOSE(ex,second,verb_pr) if (ex) { verbose verb_pr; \
- second; }
-# define FR_IFDEBUG(ex,second,verb_pr) if (ex) { debug verb_pr; \
- second; }
# define FR_VERBOSE(verb_pr) verbose verb_pr
# define FR_DEBUG(verb_pr) debug verb_pr
-# define SEND_RESET(ip, qif, if, m, fin) send_reset(ip, if)
# define IPLLOG(a, c, d, e) ipllog()
-# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip)
#else /* #ifndef _KERNEL */
-# define FR_IFVERBOSE(ex,second,verb_pr) ;
-# define FR_IFDEBUG(ex,second,verb_pr) ;
# define FR_VERBOSE(verb_pr)
# define FR_DEBUG(verb_pr)
# define IPLLOG(a, c, d, e) ipflog(a, c, d, e)
@@ -117,27 +119,24 @@ extern kmutex_t ipf_rw;
# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, \
ip, qif)
# define SEND_RESET(ip, qif, if, fin) send_reset(fin, ip, qif)
-# define ICMP_ERROR(b, ip, t, c, if, dst) \
- icmp_error(ip, t, c, if, dst)
# else /* SOLARIS */
# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip)
-# ifdef linux
-# define SEND_RESET(ip, qif, if, fin) send_reset(ip, ifp)
-# define ICMP_ERROR(b, ip, t, c, if, dst) icmp_send(b,t,c,0,if)
-# else
-# define SEND_RESET(ip, qif, if, fin) send_reset(fin, ip)
-# define ICMP_ERROR(b, ip, t, c, if, dst) \
- send_icmp_err(ip, t, c, if, dst)
-# endif /* linux */
+# define SEND_RESET(ip, qif, if, fin) send_reset(fin, ip)
# endif /* SOLARIS || __sgi */
#endif /* _KERNEL */
struct filterstats frstats[2] = {{0,0,0,0,0},{0,0,0,0,0}};
struct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } },
+#ifdef USE_INET6
+ *ipfilter6[2][2] = { { NULL, NULL }, { NULL, NULL } },
+ *ipacct6[2][2] = { { NULL, NULL }, { NULL, NULL } },
+#endif
*ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } };
struct frgroup *ipfgroups[3][2];
-int fr_flags = IPF_LOGGING, fr_active = 0;
+int fr_flags = IPF_LOGGING;
+int fr_active = 0;
+int fr_chksrc = 0;
#if defined(IPFILTER_DEFAULT_BLOCK)
int fr_pass = FR_NOMATCH|FR_BLOCK;
#else
@@ -147,7 +146,6 @@ char ipfilter_version[] = IPL_VERSION;
fr_info_t frcache[2];
-static int fr_tcpudpchk __P((frentry_t *, fr_info_t *));
static int frflushlist __P((int, minor_t, int *, frentry_t **));
#ifdef _KERNEL
static void frsynclist __P((frentry_t *));
@@ -204,12 +202,12 @@ int hlen;
ip_t *ip;
fr_info_t *fin;
{
- struct optlist *op;
- tcphdr_t *tcp;
- fr_ip_t *fi = &fin->fin_fi;
u_short optmsk = 0, secmsk = 0, auth = 0;
- int i, mv, ol, off;
+ int i, mv, ol, off, p, plen, v;
+ fr_ip_t *fi = &fin->fin_fi;
+ struct optlist *op;
u_char *s, opt;
+ tcphdr_t *tcp;
fin->fin_rev = 0;
fin->fin_fr = NULL;
@@ -218,25 +216,59 @@ fr_info_t *fin;
fin->fin_data[1] = 0;
fin->fin_rule = -1;
fin->fin_group = -1;
- fin->fin_id = ip->ip_id;
#ifdef _KERNEL
fin->fin_icode = ipl_unreach;
#endif
- fi->fi_v = ip->ip_v;
- fi->fi_tos = ip->ip_tos;
+ v = fin->fin_v;
+ fi->fi_v = v;
fin->fin_hlen = hlen;
- fin->fin_dlen = ip->ip_len - hlen;
- tcp = (tcphdr_t *)((char *)ip + hlen);
+ if (v == 4) {
+ fin->fin_id = ip->ip_id;
+ fi->fi_tos = ip->ip_tos;
+ off = (ip->ip_off & IP_OFFMASK) << 3;
+ tcp = (tcphdr_t *)((char *)ip + hlen);
+ (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4));
+ fi->fi_src.i6[1] = 0;
+ fi->fi_src.i6[2] = 0;
+ fi->fi_src.i6[3] = 0;
+ fi->fi_dst.i6[1] = 0;
+ fi->fi_dst.i6[2] = 0;
+ fi->fi_dst.i6[3] = 0;
+ fi->fi_saddr = ip->ip_src.s_addr;
+ fi->fi_daddr = ip->ip_dst.s_addr;
+ p = ip->ip_p;
+ fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0;
+ if (ip->ip_off & 0x3fff)
+ fi->fi_fl |= FI_FRAG;
+ plen = ip->ip_len;
+ fin->fin_dlen = plen - hlen;
+ }
+#ifdef USE_INET6
+ else if (v == 6) {
+ ip6_t *ip6 = (ip6_t *)ip;
+
+ off = 0;
+ p = ip6->ip6_nxt;
+ fi->fi_p = p;
+ fi->fi_ttl = ip6->ip6_hlim;
+ tcp = (tcphdr_t *)(ip6 + 1);
+ fi->fi_src.in6 = ip6->ip6_src;
+ fi->fi_dst.in6 = ip6->ip6_dst;
+ fin->fin_id = (u_short)(ip6->ip6_flow & 0xffff);
+ fi->fi_tos = 0;
+ fi->fi_fl = 0;
+ plen = ntohs(ip6->ip6_plen);
+ fin->fin_dlen = plen;
+ }
+#endif
+ else
+ return;
+
+ fin->fin_off = off;
+ fin->fin_plen = plen;
fin->fin_dp = (void *)tcp;
- (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4));
- fi->fi_src.s_addr = ip->ip_src.s_addr;
- fi->fi_dst.s_addr = ip->ip_dst.s_addr;
-
- fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0;
- off = (ip->ip_off & IP_OFFMASK) << 3;
- if (ip->ip_off & 0x3fff)
- fi->fi_fl |= FI_FRAG;
- switch (ip->ip_p)
+
+ switch (p)
{
case IPPROTO_ICMP :
{
@@ -248,13 +280,19 @@ fr_info_t *fin;
if (!off && (icmp->icmp_type == ICMP_ECHOREPLY ||
icmp->icmp_type == ICMP_ECHO))
minicmpsz = ICMP_MINLEN;
- if (!off && (icmp->icmp_type == ICMP_TSTAMP ||
- icmp->icmp_type == ICMP_TSTAMPREPLY))
- minicmpsz = 20; /* type(1) + code(1) + cksum(2) + id(2) + seq(2) + 3*timestamp(3*4) */
- if (!off && (icmp->icmp_type == ICMP_MASKREQ ||
- icmp->icmp_type == ICMP_MASKREPLY))
- minicmpsz = 12; /* type(1) + code(1) + cksum(2) + id(2) + seq(2) + mask(4) */
- if ((!(ip->ip_len >= hlen + minicmpsz) && !off) ||
+
+ /* type(1) + code(1) + cksum(2) + id(2) seq(2) +
+ * 3*timestamp(3*4) */
+ else if (!off && (icmp->icmp_type == ICMP_TSTAMP ||
+ icmp->icmp_type == ICMP_TSTAMPREPLY))
+ minicmpsz = 20;
+
+ /* type(1) + code(1) + cksum(2) + id(2) seq(2) + mask(4) */
+ else if (!off && (icmp->icmp_type == ICMP_MASKREQ ||
+ icmp->icmp_type == ICMP_MASKREPLY))
+ minicmpsz = 12;
+
+ if ((!(plen >= hlen + minicmpsz) && !off) ||
(off && off < sizeof(struct icmp)))
fi->fi_fl |= FI_SHORT;
if (fin->fin_dlen > 1)
@@ -263,17 +301,33 @@ fr_info_t *fin;
}
case IPPROTO_TCP :
fi->fi_fl |= FI_TCPUDP;
- if ((!IPMINLEN(ip, tcphdr) && !off) ||
- (off && off < sizeof(struct tcphdr)))
- fi->fi_fl |= FI_SHORT;
+#ifdef USE_INET6
+ if (v == 6) {
+ if (plen < sizeof(struct tcphdr))
+ fi->fi_fl |= FI_SHORT;
+ } else
+#endif
+ if (v == 4) {
+ if ((!IPMINLEN(ip, tcphdr) && !off) ||
+ (off && off < sizeof(struct tcphdr)))
+ fi->fi_fl |= FI_SHORT;
+ }
if (!(fi->fi_fl & FI_SHORT) && !off)
fin->fin_tcpf = tcp->th_flags;
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;
+#ifdef USE_INET6
+ if (v == 6) {
+ if (plen < sizeof(struct udphdr))
+ fi->fi_fl |= FI_SHORT;
+ } else
+#endif
+ if (v == 4) {
+ 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);
@@ -284,6 +338,14 @@ getports:
break;
}
+#ifdef USE_INET6
+ if (v == 6) {
+ fi->fi_optmsk = 0;
+ fi->fi_secmsk = 0;
+ fi->fi_auth = 0;
+ return;
+ }
+#endif
for (s = (u_char *)(ip + 1), hlen -= (int)sizeof(*ip); hlen > 0; ) {
opt = *s;
@@ -344,8 +406,8 @@ getports:
/*
* check an IP packet for TCP/UDP characteristics such as ports and flags.
*/
-static int fr_tcpudpchk(fr, fin)
-frentry_t *fr;
+int fr_tcpudpchk(ft, fin)
+frtuc_t *ft;
fr_info_t *fin;
{
register u_short po, tup;
@@ -358,8 +420,8 @@ fr_info_t *fin;
*
* compare destination ports
*/
- if ((i = (int)fr->fr_dcmp)) {
- po = fr->fr_dport;
+ if ((i = (int)ft->ftu_dcmp)) {
+ po = ft->ftu_dport;
tup = fin->fin_data[1];
/*
* Do opposite test to that required and
@@ -378,17 +440,17 @@ fr_info_t *fin;
else if (!--i && tup < po) /* GT or EQ */
err = 0;
else if (!--i && /* Out of range */
- (tup >= po && tup <= fr->fr_dtop))
+ (tup >= po && tup <= ft->ftu_dtop))
err = 0;
else if (!--i && /* In range */
- (tup <= po || tup >= fr->fr_dtop))
+ (tup <= po || tup >= ft->ftu_dtop))
err = 0;
}
/*
* compare source ports
*/
- if (err && (i = (int)fr->fr_scmp)) {
- po = fr->fr_sport;
+ if (err && (i = (int)ft->ftu_scmp)) {
+ po = ft->ftu_sport;
tup = fin->fin_data[0];
if (!--i && tup != po)
err = 0;
@@ -403,10 +465,10 @@ fr_info_t *fin;
else if (!--i && tup < po)
err = 0;
else if (!--i && /* Out of range */
- (tup >= po && tup <= fr->fr_stop))
+ (tup >= po && tup <= ft->ftu_stop))
err = 0;
else if (!--i && /* In range */
- (tup <= po || tup >= fr->fr_stop))
+ (tup <= po || tup >= ft->ftu_stop))
err = 0;
}
@@ -418,14 +480,14 @@ fr_info_t *fin;
*/
if (err && (fin->fin_fi.fi_p == IPPROTO_TCP)) {
if (fin->fin_fi.fi_fl & FI_SHORT)
- return !(fr->fr_tcpf | fr->fr_tcpfm);
+ return !(ft->ftu_tcpf | ft->ftu_tcpfm);
/*
* Match the flags ? If not, abort this match.
*/
- if (fr->fr_tcpfm &&
- fr->fr_tcpf != (fin->fin_tcpf & fr->fr_tcpfm)) {
+ if (ft->ftu_tcpfm &&
+ ft->ftu_tcpf != (fin->fin_tcpf & ft->ftu_tcpfm)) {
FR_DEBUG(("f. %#x & %#x != %#x\n", fin->fin_tcpf,
- fr->fr_tcpfm, fr->fr_tcpf));
+ ft->ftu_tcpfm, ft->ftu_tcpf));
err = 0;
}
}
@@ -452,7 +514,10 @@ void *m;
fin->fin_fr = NULL;
fin->fin_rule = 0;
fin->fin_group = 0;
- off = ip->ip_off & IP_OFFMASK;
+ if (fin->fin_v == 4)
+ off = ip->ip_off & IP_OFFMASK;
+ else
+ off = 0;
pass |= (fi->fi_fl << 24);
if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off)
@@ -496,23 +561,77 @@ void *m;
lip = (u_32_t *)fi;
lm = (u_32_t *)&fr->fr_mip;
ld = (u_32_t *)&fr->fr_ip;
- i = ((lip[0] & lm[0]) != ld[0]);
- FR_IFDEBUG(i,continue,("0. %#08x & %#08x != %#08x\n",
- lip[0], lm[0], ld[0]));
- i |= ((lip[1] & lm[1]) != ld[1]) << 19;
+ i = ((*lip & *lm) != *ld);
+ FR_DEBUG(("0. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ if (i)
+ continue;
+ /*
+ * We now know whether the packet version and the
+ * rule version match, along with protocol, ttl and
+ * tos.
+ */
+ lip++, lm++, ld++;
+ /*
+ * Unrolled loops (4 each, for 32 bits).
+ */
+ i |= ((*lip & *lm) != *ld) << 19;
+ FR_DEBUG(("1a. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ if (fi->fi_v == 6) {
+ lip++, lm++, ld++;
+ i |= ((*lip & *lm) != *ld) << 19;
+ FR_DEBUG(("1b. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ lip++, lm++, ld++;
+ i |= ((*lip & *lm) != *ld) << 19;
+ FR_DEBUG(("1c. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ lip++, lm++, ld++;
+ i |= ((*lip & *lm) != *ld) << 19;
+ FR_DEBUG(("1d. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ } else {
+ lip += 3;
+ lm += 3;
+ ld += 3;
+ }
i ^= (fr->fr_flags & FR_NOTSRCIP);
- FR_IFDEBUG(i,continue,("1. %#08x & %#08x != %#08x\n",
- lip[1], lm[1], ld[1]));
- i |= ((lip[2] & lm[2]) != ld[2]) << 20;
+ if (i)
+ continue;
+ lip++, lm++, ld++;
+ i |= ((*lip & *lm) != *ld) << 20;
+ FR_DEBUG(("2a. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ if (fi->fi_v == 6) {
+ lip++, lm++, ld++;
+ i |= ((*lip & *lm) != *ld) << 20;
+ FR_DEBUG(("2b. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ lip++, lm++, ld++;
+ i |= ((*lip & *lm) != *ld) << 20;
+ FR_DEBUG(("2c. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ lip++, lm++, ld++;
+ i |= ((*lip & *lm) != *ld) << 20;
+ FR_DEBUG(("2d. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ } else {
+ lip += 3;
+ lm += 3;
+ ld += 3;
+ }
i ^= (fr->fr_flags & FR_NOTDSTIP);
- FR_IFDEBUG(i,continue,("2. %#08x & %#08x != %#08x\n",
- lip[2], lm[2], ld[2]));
- i |= ((lip[3] & lm[3]) != ld[3]);
- FR_IFDEBUG(i,continue,("3. %#08x & %#08x != %#08x\n",
- lip[3], lm[3], ld[3]));
- i |= ((lip[4] & lm[4]) != ld[4]);
- FR_IFDEBUG(i,continue,("4. %#08x & %#08x != %#08x\n",
- lip[4], lm[4], ld[4]));
+ if (i)
+ continue;
+ lip++, lm++, ld++;
+ i |= ((*lip & *lm) != *ld);
+ FR_DEBUG(("3. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
+ lip++, lm++, ld++;
+ i |= ((*lip & *lm) != *ld);
+ FR_DEBUG(("4. %#08x & %#08x != %#08x\n",
+ *lip, *lm, *ld));
if (i)
continue;
}
@@ -525,7 +644,7 @@ void *m;
fr->fr_tcpfm))
continue;
if (fi->fi_fl & FI_TCPUDP) {
- if (!fr_tcpudpchk(fr, fin))
+ if (!fr_tcpudpchk(&fr->fr_tuc, fin))
continue;
} else if (fr->fr_icmpm || fr->fr_icmp) {
if ((fi->fi_p != IPPROTO_ICMP) || off ||
@@ -549,16 +668,18 @@ void *m;
#ifdef IPFILTER_LOG
if ((passt & FR_LOGMASK) == FR_LOG) {
if (!IPLLOG(passt, ip, fin, m)) {
- ATOMIC_INC(frstats[fin->fin_out].fr_skip);
+ if (passt & FR_LOGORBLOCK)
+ passt |= FR_BLOCK|FR_QUICK;
+ ATOMIC_INCL(frstats[fin->fin_out].fr_skip);
}
- ATOMIC_INC(frstats[fin->fin_out].fr_pkl);
+ ATOMIC_INCL(frstats[fin->fin_out].fr_pkl);
logged = 1;
}
#endif /* IPFILTER_LOG */
if (!(skip = fr->fr_skip) && (passt & FR_LOGMASK) != FR_LOG)
pass = passt;
FR_DEBUG(("pass %#x\n", pass));
- ATOMIC_INC(fr->fr_hits);
+ ATOMIC_INCL(fr->fr_hits);
if (pass & FR_ACCOUNT)
fr->fr_bytes += (U_QUAD_T)ip->ip_len;
else
@@ -608,8 +729,8 @@ int out;
*/
fr_info_t frinfo, *fc;
register fr_info_t *fin = &frinfo;
- frentry_t *fr = NULL;
- int changed, error = EHOSTUNREACH;
+ int changed, error = EHOSTUNREACH, v = ip->ip_v;
+ frentry_t *fr = NULL, *list;
u_32_t pass, apass;
#if !SOLARIS || !defined(_KERNEL)
register mb_t *m = *mp;
@@ -631,7 +752,7 @@ int out;
*/
m->m_flags &= ~M_CANFASTFWD;
# endif /* M_CANFASTFWD */
-
+# ifdef CSUM_DELAY_DATA
/*
* disable delayed checksums.
*/
@@ -639,6 +760,8 @@ int out;
in_delayed_cksum(m);
m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
}
+# endif /* CSUM_DELAY_DATA */
+
if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ||
ip->ip_p == IPPROTO_ICMP)) {
@@ -664,19 +787,19 @@ int out;
# ifdef __sgi
/* Under IRIX, avoid m_pullup as it makes ping <hostname> panic */
if ((up > sizeof(hbuf)) || (m_length(m) < up)) {
- ATOMIC_INC(frstats[out].fr_pull[1]);
+ ATOMIC_INCL(frstats[out].fr_pull[1]);
return -1;
}
m_copydata(m, 0, up, hbuf);
- ATOMIC_INC(frstats[out].fr_pull[0]);
+ ATOMIC_INCL(frstats[out].fr_pull[0]);
ip = (ip_t *)hbuf;
# else /* __ sgi */
# ifndef linux
if ((*mp = m_pullup(m, up)) == 0) {
- ATOMIC_INC(frstats[out].fr_pull[1]);
+ ATOMIC_INCL(frstats[out].fr_pull[1]);
return -1;
} else {
- ATOMIC_INC(frstats[out].fr_pull[0]);
+ ATOMIC_INCL(frstats[out].fr_pull[0]);
m = *mp;
ip = mtod(m, ip_t *);
}
@@ -695,24 +818,43 @@ int out;
fin->fin_qfm = m;
fin->fin_qif = qif;
# endif
+# ifdef USE_INET6
+ if (v == 6) {
+ ATOMIC_INCL(frstats[0].fr_ipv6[out]);
+ } else
+# endif
+ if (!out && fr_chksrc && !fr_verifysrc(ip->ip_src, ifp)) {
+ ATOMIC_INCL(frstats[0].fr_badsrc);
+# if !SOLARIS
+ m_freem(m);
+# endif
+ return error;
+ }
#endif /* _KERNEL */
-
+
/*
* Be careful here: ip_id is in network byte order when called
* from ip_output()
*/
- if (out)
+ if ((out) && (v == 4))
ip->ip_id = ntohs(ip->ip_id);
- fr_makefrip(hlen, ip, fin);
+
+ changed = 0;
+ fin->fin_v = v;
fin->fin_ifp = ifp;
fin->fin_out = out;
fin->fin_mp = mp;
+ fr_makefrip(hlen, ip, fin);
pass = fr_pass;
+ if (fin->fin_fi.fi_fl & FI_SHORT) {
+ ATOMIC_INCL(frstats[out].fr_short);
+ }
+
READ_ENTER(&ipf_mutex);
if (fin->fin_fi.fi_fl & FI_SHORT)
- ATOMIC_INC(frstats[out].fr_short);
+ ATOMIC_INCL(frstats[out].fr_short);
/*
* Check auth now. This, combined with the check below to see if apass
@@ -724,10 +866,16 @@ int out;
apass = fr_checkauth(ip, fin);
if (!out) {
+#ifdef USE_INET6
+ if (v == 6)
+ list = ipacct6[0][fr_active];
+ else
+#endif
+ list = ipacct[0][fr_active];
changed = ip_natin(ip, fin);
- if (!apass && (fin->fin_fr = ipacct[0][fr_active]) &&
+ if (!apass && (fin->fin_fr = list) &&
(fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
- ATOMIC_INC(frstats[0].fr_acct);
+ ATOMIC_INCL(frstats[0].fr_acct);
}
}
@@ -746,19 +894,25 @@ int out;
* earlier.
*/
bcopy((char *)fc, (char *)fin, FI_COPYSIZE);
- ATOMIC_INC(frstats[out].fr_chit);
+ ATOMIC_INCL(frstats[out].fr_chit);
if ((fr = fin->fin_fr)) {
- ATOMIC_INC(fr->fr_hits);
+ ATOMIC_INCL(fr->fr_hits);
pass = fr->fr_flags;
}
} else {
- if ((fin->fin_fr = ipfilter[out][fr_active]))
+#ifdef USE_INET6
+ if (v == 6)
+ list = ipfilter6[out][fr_active];
+ else
+#endif
+ list = ipfilter[out][fr_active];
+ if ((fin->fin_fr = list))
pass = fr_scanlist(fr_pass, ip, fin, m);
if (!(pass & (FR_KEEPSTATE|FR_DONTCACHE)))
bcopy((char *)fin, (char *)fc,
FI_COPYSIZE);
if (pass & FR_NOMATCH) {
- ATOMIC_INC(frstats[out].fr_nom);
+ ATOMIC_INCL(frstats[out].fr_nom);
}
}
fr = fin->fin_fr;
@@ -771,7 +925,7 @@ int out;
* then pretend we've dropped it already.
*/
if ((pass & FR_AUTH))
- if (FR_NEWAUTH(m, fin, ip, qif) != 0)
+ if (fr_newauth((mb_t *)m, fin, ip) != 0)
#ifdef _KERNEL
m = *mp = NULL;
#else
@@ -782,9 +936,9 @@ int out;
READ_ENTER(&ipf_auth);
if ((fin->fin_fr = ipauth) &&
(pass = fr_scanlist(0, ip, fin, m))) {
- ATOMIC_INC(fr_authstats.fas_hits);
+ ATOMIC_INCL(fr_authstats.fas_hits);
} else {
- ATOMIC_INC(fr_authstats.fas_miss);
+ ATOMIC_INCL(fr_authstats.fas_miss);
}
RWLOCK_EXIT(&ipf_auth);
}
@@ -793,19 +947,19 @@ int out;
if ((pass & (FR_KEEPFRAG|FR_KEEPSTATE)) == FR_KEEPFRAG) {
if (fin->fin_fi.fi_fl & FI_FRAG) {
if (ipfr_newfrag(ip, fin, pass) == -1) {
- ATOMIC_INC(frstats[out].fr_bnfr);
+ ATOMIC_INCL(frstats[out].fr_bnfr);
} else {
- ATOMIC_INC(frstats[out].fr_nfr);
+ ATOMIC_INCL(frstats[out].fr_nfr);
}
} else {
- ATOMIC_INC(frstats[out].fr_cfr);
+ ATOMIC_INCL(frstats[out].fr_cfr);
}
}
if (pass & FR_KEEPSTATE) {
if (fr_addstate(ip, fin, 0) == NULL) {
- ATOMIC_INC(frstats[out].fr_bads);
+ ATOMIC_INCL(frstats[out].fr_bads);
} else {
- ATOMIC_INC(frstats[out].fr_ads);
+ ATOMIC_INCL(frstats[out].fr_ads);
}
}
} else if (fr != NULL) {
@@ -822,9 +976,15 @@ int out;
* interface.
*/
if (out && (pass & FR_PASS)) {
- if ((fin->fin_fr = ipacct[1][fr_active]) &&
+#ifdef USE_INET6
+ if (v == 6)
+ list = ipacct6[0][fr_active];
+ else
+#endif
+ list = ipacct[0][fr_active];
+ if ((fin->fin_fr = list) &&
(fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
- ATOMIC_INC(frstats[1].fr_acct);
+ ATOMIC_INCL(frstats[1].fr_acct);
}
fin->fin_fr = fr;
changed = ip_natout(ip, fin);
@@ -836,22 +996,22 @@ int out;
if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) {
if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) {
pass |= FF_LOGNOMATCH;
- ATOMIC_INC(frstats[out].fr_npkl);
+ ATOMIC_INCL(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;
- ATOMIC_INC(frstats[out].fr_ppkl);
+ ATOMIC_INCL(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;
- ATOMIC_INC(frstats[out].fr_bpkl);
+ ATOMIC_INCL(frstats[out].fr_bpkl);
logit:
if (!IPLLOG(pass, ip, fin, m)) {
- ATOMIC_INC(frstats[out].fr_skip);
+ ATOMIC_INCL(frstats[out].fr_skip);
if ((pass & (FR_PASS|FR_LOGORBLOCK)) ==
(FR_PASS|FR_LOGORBLOCK))
pass ^= FR_PASS|FR_BLOCK;
@@ -860,7 +1020,7 @@ logit:
}
#endif /* IPFILTER_LOG */
- if (out)
+ if ((out) && (v == 4))
ip->ip_id = htons(ip->ip_id);
#ifdef _KERNEL
@@ -881,9 +1041,9 @@ logit:
# endif
#endif
if (pass & FR_PASS) {
- ATOMIC_INC(frstats[out].fr_pass);
+ ATOMIC_INCL(frstats[out].fr_pass);
} else if (pass & FR_BLOCK) {
- ATOMIC_INC(frstats[out].fr_block);
+ ATOMIC_INCL(frstats[out].fr_block);
/*
* Should we return an ICMP packet to indicate error
* status passing through the packet filter ?
@@ -895,37 +1055,31 @@ logit:
if (!out) {
#ifdef _KERNEL
if (pass & FR_RETICMP) {
- struct in_addr dst;
+ int dst;
if ((pass & FR_RETMASK) == FR_FAKEICMP)
- dst = ip->ip_dst;
+ dst = 1;
else
- dst.s_addr = 0;
-# if SOLARIS
- ICMP_ERROR(q, ip, ICMP_UNREACH, fin->fin_icode,
- qif, dst);
-# else
- ICMP_ERROR(m, ip, ICMP_UNREACH, fin->fin_icode,
- ifp, dst);
-# endif
- ATOMIC_INC(frstats[0].fr_ret);
+ dst = 0;
+ send_icmp_err(ip, ICMP_UNREACH, fin, dst);
+ ATOMIC_INCL(frstats[0].fr_ret);
} else if (((pass & FR_RETMASK) == FR_RETRST) &&
!(fin->fin_fi.fi_fl & FI_SHORT)) {
- if (SEND_RESET(ip, qif, ifp, fin) == 0) {
- ATOMIC_INC(frstats[1].fr_ret);
+ if (send_reset(ip, fin) == 0) {
+ ATOMIC_INCL(frstats[1].fr_ret);
}
}
#else
if ((pass & FR_RETMASK) == FR_RETICMP) {
verbose("- ICMP unreachable sent\n");
- ATOMIC_INC(frstats[0].fr_ret);
+ ATOMIC_INCL(frstats[0].fr_ret);
} else if ((pass & FR_RETMASK) == FR_FAKEICMP) {
verbose("- forged ICMP unreachable sent\n");
- ATOMIC_INC(frstats[0].fr_ret);
+ ATOMIC_INCL(frstats[0].fr_ret);
} else if (((pass & FR_RETMASK) == FR_RETRST) &&
!(fin->fin_fi.fi_fl & FI_SHORT)) {
verbose("- TCP RST sent\n");
- ATOMIC_INC(frstats[1].fr_ret);
+ ATOMIC_INCL(frstats[1].fr_ret);
}
#endif
} else {
@@ -941,6 +1095,10 @@ logit:
* Once we're finished return to our caller, freeing the packet if
* we are dropping it (* BSD ONLY *).
*/
+ if ((changed == -1) && (pass & FR_PASS)) {
+ pass &= ~FR_PASS;
+ pass |= FR_BLOCK;
+ }
#if defined(_KERNEL)
# if !SOLARIS
# if !defined(linux)
@@ -1204,7 +1362,7 @@ nodata:
* SUCH DAMAGE.
*
* @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
- * $Id: fil.c,v 2.3.2.16 2000/01/27 08:49:37 darrenr Exp $
+ * $Id: fil.c,v 2.35.2.8 2000/05/22 10:26:09 darrenr Exp $
*/
/*
* Copy data from an mbuf chain starting "off" bytes from the beginning,
@@ -1304,8 +1462,7 @@ out:
frgroup_t *fr_findgroup(num, flags, which, set, fgpp)
-u_int num;
-u_32_t flags;
+u_32_t num, flags;
minor_t which;
int set;
frgroup_t ***fgpp;
@@ -1334,7 +1491,7 @@ frgroup_t ***fgpp;
frgroup_t *fr_addgroup(num, fp, which, set)
-u_int num;
+u_32_t num;
frentry_t *fp;
minor_t which;
int set;
@@ -1357,8 +1514,7 @@ int set;
void fr_delgroup(num, flags, which, set)
-u_int num;
-u_32_t flags;
+u_32_t num, flags;
minor_t which;
int set;
{
@@ -1396,11 +1552,11 @@ frentry_t **listp;
MUTEX_EXIT(&ipf_rw);
}
- ATOMIC_DEC(fp->fr_ref);
+ ATOMIC_DEC32(fp->fr_ref);
if (fp->fr_grhead) {
- fr_delgroup((u_int)fp->fr_grhead, fp->fr_flags,
+ fr_delgroup(fp->fr_grhead, fp->fr_flags,
unit, set);
- fp->fr_grhead = NULL;
+ fp->fr_grhead = 0;
}
if (fp->fr_ref == 0) {
KFREE(fp);
@@ -1429,10 +1585,18 @@ int flags;
set = 1 - set;
if (flags & FR_OUTQUE) {
+#ifdef USE_INET6
+ (void) frflushlist(set, unit, &flushed, &ipfilter6[1][set]);
+ (void) frflushlist(set, unit, &flushed, &ipacct6[1][set]);
+#endif
(void) frflushlist(set, unit, &flushed, &ipfilter[1][set]);
(void) frflushlist(set, unit, &flushed, &ipacct[1][set]);
}
if (flags & FR_INQUE) {
+#ifdef USE_INET6
+ (void) frflushlist(set, unit, &flushed, &ipfilter6[0][set]);
+ (void) frflushlist(set, unit, &flushed, &ipacct6[0][set]);
+#endif
(void) frflushlist(set, unit, &flushed, &ipfilter[0][set]);
(void) frflushlist(set, unit, &flushed, &ipacct[0][set]);
}
@@ -1511,10 +1675,14 @@ u_32_t ip;
/*
* return the first IP Address associated with an interface
*/
-int fr_ifpaddr(ifptr, inp)
+int fr_ifpaddr(v, ifptr, inp)
+int v;
void *ifptr;
struct in_addr *inp;
{
+# ifdef USE_INET6
+ struct in6_addr *inp6 = NULL;
+# endif
# if SOLARIS
ill_t *ill = ifptr;
# else
@@ -1523,13 +1691,30 @@ struct in_addr *inp;
struct in_addr in;
# if SOLARIS
- in.s_addr = ill->ill_ipif->ipif_local_addr;
+# ifdef USE_INET6
+ if (v == 6) {
+ struct in6_addr in6;
+
+ /*
+ * First is always link local.
+ */
+ if (ill->ill_ipif->ipif_next)
+ in6 = ill->ill_ipif->ipif_next->ipif_v6lcl_addr;
+ else
+ bzero((char *)&in6, sizeof(in6));
+ bcopy((char *)&in6, (char *)inp, sizeof(in6));
+ } else
+# endif
+ {
+ in.s_addr = ill->ill_ipif->ipif_local_addr;
+ *inp = in;
+ }
# else /* SOLARIS */
# if linux
;
# else /* linux */
- struct ifaddr *ifa;
struct sockaddr_in *sin;
+ struct ifaddr *ifa;
# if (__FreeBSD_version >= 300000)
ifa = TAILQ_FIRST(&ifp->if_addrhead);
@@ -1548,8 +1733,17 @@ struct in_addr *inp;
sin = (struct sockaddr_in *)&ifa->ifa_addr;
# else
sin = (struct sockaddr_in *)ifa->ifa_addr;
- while (sin && ifa &&
- sin->sin_family != AF_INET) {
+ while (sin && ifa) {
+ if ((v == 4) && (sin->sin_family == AF_INET))
+ break;
+# ifdef USE_INET6
+ if ((v == 6) && (sin->sin_family == AF_INET6)) {
+ inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr;
+ if (!IN6_IS_ADDR_LINKLOCAL(inp6) &&
+ !IN6_IS_ADDR_LOOPBACK(inp6))
+ break;
+ }
+# endif
# if (__FreeBSD_version >= 300000)
ifa = TAILQ_NEXT(ifa, ifa_link);
# else
@@ -1567,10 +1761,17 @@ struct in_addr *inp;
if (sin == NULL)
return -1;
# endif /* (BSD < 199306) && (!__sgi && IFF_DRVLOCK) */
- in = sin->sin_addr;
+# ifdef USE_INET6
+ if (v == 6)
+ bcopy((char *)inp6, (char *)inp, sizeof(*inp6));
+ else
+# endif
+ {
+ in = sin->sin_addr;
+ *inp = in;
+ }
# endif /* linux */
# endif /* SOLARIS */
- *inp = in;
return 0;
}
@@ -1580,7 +1781,7 @@ register frentry_t *fr;
{
for (; fr; fr = fr->fr_next) {
if (fr->fr_ifa != NULL) {
- fr->fr_ifa = GETUNIT(fr->fr_ifname);
+ fr->fr_ifa = GETUNIT(fr->fr_ifname, fr->fr_ip.fi_v);
if (fr->fr_ifa == NULL)
fr->fr_ifa = (void *)-1;
}
@@ -1592,9 +1793,9 @@ register frentry_t *fr;
void frsync()
{
+# if !SOLARIS
register struct ifnet *ifp;
-# if !SOLARIS
# if defined(__OpenBSD__) || ((NetBSD >= 199511) && (NetBSD < 1991011)) || \
(defined(__FreeBSD_version) && (__FreeBSD_version >= 300000))
# if (NetBSD >= 199905) || defined(__OpenBSD__)
@@ -1616,19 +1817,197 @@ void frsync()
frsynclist(ipacct[1][fr_active]);
frsynclist(ipfilter[0][fr_active]);
frsynclist(ipfilter[1][fr_active]);
+#ifdef USE_INET6
+ frsynclist(ipacct6[0][fr_active]);
+ frsynclist(ipacct6[1][fr_active]);
+ frsynclist(ipfilter6[0][fr_active]);
+ frsynclist(ipfilter6[1][fr_active]);
+#endif
RWLOCK_EXIT(&ipf_mutex);
}
+
+/*
+ * In the functions below, bcopy() is called because the pointer being
+ * copied _from_ in this instance is a pointer to a char buf (which could
+ * end up being unaligned) and on the kernel's local stack.
+ */
+int ircopyptr(a, b, c)
+void *a, *b;
+size_t c;
+{
+ caddr_t ca;
+ int err;
+
+#if SOLARIS
+ copyin(a, &ca, sizeof(ca));
+#else
+ bcopy(a, &ca, sizeof(ca));
+#endif
+ err = copyin(ca, b, c);
+ return err;
+}
+
+
+int iwcopyptr(a, b, c)
+void *a, *b;
+size_t c;
+{
+ caddr_t ca;
+ int err;
+
+#if SOLARIS
+ copyin(b, &ca, sizeof(ca));
#else
+ bcopy(b, &ca, sizeof(ca));
+#endif
+ err = copyout(a, ca, c);
+ return err;
+}
+
+#else /* _KERNEL */
/*
* return the first IP Address associated with an interface
*/
-int fr_ifpaddr(ifptr, inp)
+int fr_ifpaddr(v, ifptr, inp)
+int v;
void *ifptr;
struct in_addr *inp;
{
return 0;
}
-#endif
+
+
+int ircopyptr(a, b, c)
+void *a, *b;
+size_t c;
+{
+ caddr_t ca;
+
+ bcopy(a, &ca, sizeof(ca));
+ bcopy(ca, b, c);
+ return 0;
+}
+
+
+int iwcopyptr(a, b, c)
+void *a, *b;
+size_t c;
+{
+ caddr_t ca;
+
+ bcopy(b, &ca, sizeof(ca));
+ bcopy(a, ca, c);
+ return 0;
+}
+
+
+#endif
+
+
+int fr_lock(data, lockp)
+caddr_t data;
+int *lockp;
+{
+ int arg, error;
+
+ error = IRCOPY(data, (caddr_t)&arg, sizeof(arg));
+ if (!error) {
+ error = IWCOPY((caddr_t)lockp, data, sizeof(*lockp));
+ if (!error)
+ *lockp = arg;
+ }
+ return error;
+}
+
+
+void fr_getstat(fiop)
+friostat_t *fiop;
+{
+ bcopy((char *)frstats, (char *)fiop->f_st, sizeof(filterstats_t) * 2);
+ fiop->f_locks[0] = fr_state_lock;
+ fiop->f_locks[1] = fr_nat_lock;
+ fiop->f_locks[2] = fr_frag_lock;
+ fiop->f_locks[3] = fr_auth_lock;
+ fiop->f_fin[0] = ipfilter[0][0];
+ fiop->f_fin[1] = ipfilter[0][1];
+ fiop->f_fout[0] = ipfilter[1][0];
+ fiop->f_fout[1] = ipfilter[1][1];
+ fiop->f_acctin[0] = ipacct[0][0];
+ fiop->f_acctin[1] = ipacct[0][1];
+ fiop->f_acctout[0] = ipacct[1][0];
+ fiop->f_acctout[1] = ipacct[1][1];
+#ifdef USE_INET6
+ fiop->f_fin6[0] = ipfilter6[0][0];
+ fiop->f_fin6[1] = ipfilter6[0][1];
+ fiop->f_fout6[0] = ipfilter6[1][0];
+ fiop->f_fout6[1] = ipfilter6[1][1];
+ fiop->f_acctin6[0] = ipacct6[0][0];
+ fiop->f_acctin6[1] = ipacct6[0][1];
+ fiop->f_acctout6[0] = ipacct6[1][0];
+ fiop->f_acctout6[1] = ipacct6[1][1];
+#endif
+ fiop->f_active = fr_active;
+ fiop->f_froute[0] = ipl_frouteok[0];
+ fiop->f_froute[1] = ipl_frouteok[1];
+
+ fiop->f_running = fr_running;
+ fiop->f_groups[0][0] = ipfgroups[0][0];
+ fiop->f_groups[0][1] = ipfgroups[0][1];
+ fiop->f_groups[1][0] = ipfgroups[1][0];
+ fiop->f_groups[1][1] = ipfgroups[1][1];
+ fiop->f_groups[2][0] = ipfgroups[2][0];
+ fiop->f_groups[2][1] = ipfgroups[2][1];
+#ifdef IPFILTER_LOG
+ fiop->f_logging = 1;
+#else
+ fiop->f_logging = 0;
+#endif
+ fiop->f_defpass = fr_pass;
+ strncpy(fiop->f_version, ipfilter_version, sizeof(fiop->f_version));
+}
+
+
+#ifdef USE_INET6
+int icmptoicmp6types[ICMP_MAXTYPE+1] = {
+ ICMP6_ECHO_REPLY, /* 0: ICMP_ECHOREPLY */
+ -1, /* 1: UNUSED */
+ -1, /* 2: UNUSED */
+ ICMP6_DST_UNREACH, /* 3: ICMP_UNREACH */
+ -1, /* 4: ICMP_SOURCEQUENCH */
+ ND_REDIRECT, /* 5: ICMP_REDIRECT */
+ -1, /* 6: UNUSED */
+ -1, /* 7: UNUSED */
+ ICMP6_ECHO_REQUEST, /* 8: ICMP_ECHO */
+ -1, /* 9: UNUSED */
+ -1, /* 10: UNUSED */
+ ICMP6_TIME_EXCEEDED, /* 11: ICMP_TIMXCEED */
+ ICMP6_PARAM_PROB, /* 12: ICMP_PARAMPROB */
+ -1, /* 13: ICMP_TSTAMP */
+ -1, /* 14: ICMP_TSTAMPREPLY */
+ -1, /* 15: ICMP_IREQ */
+ -1, /* 16: ICMP_IREQREPLY */
+ -1, /* 17: ICMP_MASKREQ */
+ -1, /* 18: ICMP_MASKREPLY */
+};
+
+
+int icmptoicmp6unreach[ICMP_MAX_UNREACH] = {
+ ICMP6_DST_UNREACH_ADDR, /* 0: ICMP_UNREACH_NET */
+ ICMP6_DST_UNREACH_ADDR, /* 1: ICMP_UNREACH_HOST */
+ -1, /* 2: ICMP_UNREACH_PROTOCOL */
+ ICMP6_DST_UNREACH_NOPORT, /* 3: ICMP_UNREACH_PORT */
+ -1, /* 4: ICMP_UNREACH_NEEDFRAG */
+ ICMP6_DST_UNREACH_NOTNEIGHBOR, /* 5: ICMP_UNREACH_SRCFAIL */
+ ICMP6_DST_UNREACH_ADDR, /* 6: ICMP_UNREACH_NET_UNKNOWN */
+ ICMP6_DST_UNREACH_ADDR, /* 7: ICMP_UNREACH_HOST_UNKNOWN */
+ -1, /* 8: ICMP_UNREACH_ISOLATED */
+ ICMP6_DST_UNREACH_ADMIN, /* 9: ICMP_UNREACH_NET_PROHIB */
+ ICMP6_DST_UNREACH_ADMIN, /* 10: ICMP_UNREACH_HOST_PROHIB */
+ -1, /* 11: ICMP_UNREACH_TOSNET */
+ -1, /* 12: ICMP_UNREACH_TOSHOST */
+ ICMP6_DST_UNREACH_ADMIN, /* 13: ICMP_UNREACH_ADMIN_PROHIBIT */
+};
+#endif
diff --git a/sys/netinet/ip_auth.c b/sys/netinet/ip_auth.c
index 045edaa..6c61bfd 100644
--- a/sys/netinet/ip_auth.c
+++ b/sys/netinet/ip_auth.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1998 by Darren Reed & Guido van Rooij.
+ * Copyright (C) 1998-2000 by Darren Reed & Guido van Rooij.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
@@ -20,7 +20,7 @@ static const char rcsid[] = "@(#)$FreeBSD$";
# include <stdlib.h>
# include <string.h>
#endif
-#if defined(_KERNEL) && (__FreeBSD_version >= 220000)
+#if (defined(KERNEL) || defined(_KERNEL)) && (__FreeBSD_version >= 220000)
# include <sys/filio.h>
# include <sys/fcntl.h>
#else
@@ -124,11 +124,12 @@ static struct wait_queue *ipfauthwait = NULL;
int fr_authsize = FR_NUMAUTH;
int fr_authused = 0;
int fr_defaultauthage = 600;
+int fr_auth_lock = 0;
fr_authstat_t fr_authstats;
-frauth_t fr_auth[FR_NUMAUTH];
+static frauth_t fr_auth[FR_NUMAUTH];
mb_t *fr_authpkts[FR_NUMAUTH];
-int fr_authstart = 0, fr_authend = 0, fr_authnext = 0;
-frauthent_t *fae_list = NULL;
+static int fr_authstart = 0, fr_authend = 0, fr_authnext = 0;
+static frauthent_t *fae_list = NULL;
frentry_t *ipauth = NULL;
@@ -145,6 +146,9 @@ fr_info_t *fin;
u_32_t pass;
int i;
+ if (fr_auth_lock)
+ return 0;
+
READ_ENTER(&ipf_auth);
for (i = fr_authstart; i != fr_authend; ) {
/*
@@ -197,19 +201,19 @@ fr_info_t *fin;
* If we do, store it and wake up any user programs which are waiting to
* hear about these events.
*/
-int fr_newauth(m, fin, ip
-#if defined(_KERNEL) && SOLARIS
-, qif)
-qif_t *qif;
-#else
-)
-#endif
+int fr_newauth(m, fin, ip)
mb_t *m;
fr_info_t *fin;
ip_t *ip;
{
+#if defined(_KERNEL) && SOLARIS
+ qif_t *qif = fin->fin_qif;
+#endif
int i;
+ if (fr_auth_lock)
+ return 0;
+
WRITE_ENTER(&ipf_auth);
if (fr_authstart > fr_authend) {
fr_authstats.fas_nospace++;
@@ -239,14 +243,15 @@ ip_t *ip;
* them.
*/
# if SOLARIS && defined(_KERNEL)
- if (ip == (ip_t *)m->b_rptr)
+ if ((ip == (ip_t *)m->b_rptr) && (ip->ip_v == 4))
# endif
{
register u_short bo;
bo = ip->ip_len;
ip->ip_len = htons(bo);
-# if !SOLARIS /* 4.4BSD converts this ip_input.c, but I don't in solaris.c */
+# if !SOLARIS && !defined(__NetBSD__)
+ /* 4.4BSD converts this ip_input.c, but I don't in solaris.c */
bo = ip->ip_id;
ip->ip_id = htons(bo);
# endif
@@ -273,7 +278,7 @@ ip_t *ip;
int fr_auth_ioctl(data, cmd, fr, frptr)
caddr_t data;
-#if defined(__NetBSD__) || defined(__OpenBSD__)
+#if defined(__NetBSD__) || defined(__OpenBSD__) || (FreeBSD_version >= 300003)
u_long cmd;
#else
int cmd;
@@ -281,11 +286,8 @@ int cmd;
frentry_t *fr, **frptr;
{
mb_t *m;
-#if defined(_KERNEL)
-# if !SOLARIS
+#if defined(_KERNEL) && !SOLARIS
struct ifqueue *ifq;
- int s;
-# endif
#endif
frauth_t auth, *au = &auth;
frauthent_t *fae, **faep;
@@ -293,12 +295,17 @@ frentry_t *fr, **frptr;
switch (cmd)
{
+ case SIOCSTLCK :
+ error = fr_lock(data, &fr_auth_lock);
+ break;
case SIOCINIFR :
case SIOCRMIFR :
case SIOCADIFR :
error = EINVAL;
break;
case SIOCINAFR :
+ error = EINVAL;
+ break;
case SIOCRMAFR :
case SIOCADAFR :
for (faep = &fae_list; (fae = *faep); )
@@ -319,8 +326,8 @@ frentry_t *fr, **frptr;
} else {
KMALLOC(fae, frauthent_t *);
if (fae != NULL) {
- IRCOPY((char *)data, (char *)&fae->fae_fr,
- sizeof(fae->fae_fr));
+ bcopy((char *)fr, (char *)&fae->fae_fr,
+ sizeof(*fr));
WRITE_ENTER(&ipf_auth);
fae->fae_age = fr_defaultauthage;
fae->fae_fr.fr_hits = 0;
@@ -338,15 +345,18 @@ frentry_t *fr, **frptr;
READ_ENTER(&ipf_auth);
fr_authstats.fas_faelist = fae_list;
RWLOCK_EXIT(&ipf_auth);
- IWCOPY((char *)&fr_authstats, data, sizeof(fr_authstats));
+ error = IWCOPYPTR((char *)&fr_authstats, data,
+ sizeof(fr_authstats));
break;
case SIOCAUTHW:
fr_authioctlloop:
READ_ENTER(&ipf_auth);
if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) {
- IWCOPY((char *)&fr_auth[fr_authnext], data,
- sizeof(fr_info_t));
+ error = IWCOPYPTR((char *)&fr_auth[fr_authnext], data,
+ sizeof(fr_info_t));
RWLOCK_EXIT(&ipf_auth);
+ if (error)
+ break;
WRITE_ENTER(&ipf_auth);
fr_authnext++;
if (fr_authnext == FR_NUMAUTH)
@@ -377,9 +387,10 @@ fr_authioctlloop:
goto fr_authioctlloop;
break;
case SIOCAUTHR:
- IRCOPY(data, (caddr_t)&auth, sizeof(auth));
+ error = IRCOPYPTR(data, (caddr_t)&auth, sizeof(auth));
+ if (error)
+ return error;
WRITE_ENTER(&ipf_auth);
- i = au->fra_index;
if ((i < 0) || (i > FR_NUMAUTH) ||
(fr_auth[i].fra_info.fin_id != au->fra_info.fin_id)) {
RWLOCK_EXIT(&ipf_auth);
@@ -391,7 +402,6 @@ fr_authioctlloop:
fr_authpkts[i] = NULL;
#ifdef _KERNEL
RWLOCK_EXIT(&ipf_auth);
- SPL_NET(s);
# ifndef linux
if (m && au->fra_info.fin_out) {
# if SOLARIS
@@ -457,7 +467,6 @@ fr_authioctlloop:
}
}
# endif
- SPL_X(s);
#endif /* _KERNEL */
break;
default :
@@ -511,6 +520,9 @@ void fr_authexpire()
int s;
#endif
+ if (fr_auth_lock)
+ return;
+
SPL_NET(s);
WRITE_ENTER(&ipf_auth);
for (i = 0, fra = fr_auth; i < FR_NUMAUTH; i++, fra++) {
diff --git a/sys/netinet/ip_auth.h b/sys/netinet/ip_auth.h
index e6b5a59..8be860c 100644
--- a/sys/netinet/ip_auth.h
+++ b/sys/netinet/ip_auth.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1997-1998 by Darren Reed & Guido Van Rooij.
+ * Copyright (C) 1997-2000 by Darren Reed & Guido Van Rooij.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
@@ -51,15 +51,12 @@ extern int fr_authstart;
extern int fr_authend;
extern int fr_authsize;
extern int fr_authused;
+extern int fr_auth_lock;
extern u_32_t fr_checkauth __P((ip_t *, fr_info_t *));
extern void fr_authexpire __P((void));
extern void fr_authunload __P((void));
extern mb_t *fr_authpkts[];
-#if defined(_KERNEL) && SOLARIS
-extern int fr_newauth __P((mb_t *, fr_info_t *, ip_t *, qif_t *));
-#else
extern int fr_newauth __P((mb_t *, fr_info_t *, ip_t *));
-#endif
#if defined(__NetBSD__) || defined(__OpenBSD__)
extern int fr_auth_ioctl __P((caddr_t, u_long, frentry_t *, frentry_t **));
#else
OpenPOWER on IntegriCloud