summaryrefslogtreecommitdiffstats
path: root/sys/contrib/ipfilter/netinet/ip_fil.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/ipfilter/netinet/ip_fil.c')
-rw-r--r--sys/contrib/ipfilter/netinet/ip_fil.c215
1 files changed, 148 insertions, 67 deletions
diff --git a/sys/contrib/ipfilter/netinet/ip_fil.c b/sys/contrib/ipfilter/netinet/ip_fil.c
index 9253775..e15ff67 100644
--- a/sys/contrib/ipfilter/netinet/ip_fil.c
+++ b/sys/contrib/ipfilter/netinet/ip_fil.c
@@ -1,15 +1,8 @@
/*
- * Copyright (C) 1993-2000 by Darren Reed.
+ * Copyright (C) 1993-2001 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.
+ * See the IPFILTER.LICENCE file for details on licencing.
*/
-#if !defined(lint)
-static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.42.2.17 2000/10/19 15:39:42 darrenr Exp $";
-#endif
-
#ifndef SOLARIS
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
#endif
@@ -118,6 +111,11 @@ static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.42.2.17 2000/10/19 15:39:42 d
extern int ip_optcopy __P((struct ip *, struct ip *));
#endif
+#if !defined(lint)
+static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
+static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.42.2.34 2001/07/23 13:49:57 darrenr Exp $";
+#endif
+
extern struct protosw inetsw[];
@@ -131,7 +129,11 @@ extern int tcp_ttl;
# endif
#endif
+#ifdef ICMP_UNREACH_FILTER_PROHIB
+int ipl_unreach = ICMP_UNREACH_FILTER_PROHIB;
+#else
int ipl_unreach = ICMP_UNREACH_FILTER;
+#endif
u_long ipl_frouteok[2] = {0, 0};
static int frzerostats __P((caddr_t));
@@ -171,6 +173,10 @@ struct callout_handle ipfr_slowtimer_ch;
# include <sys/callout.h>
struct callout ipfr_slowtimer_ch;
#endif
+#if defined(__OpenBSD__)
+# include <sys/timeout.h>
+struct timeout ipfr_slowtimer_ch;
+#endif
#if defined(__sgi) && defined(_KERNEL)
toid_t ipfr_slowtimer_ch;
#endif
@@ -246,12 +252,18 @@ int iplattach()
# ifdef IPFILTER_LOG
ipflog_init();
# endif
- if (nat_init() == -1)
- return -1;
- if (fr_stateinit() == -1)
- return -1;
- if (appr_init() == -1)
- return -1;
+ if (nat_init() == -1) {
+ SPL_X(s);
+ return EIO;
+ }
+ if (fr_stateinit() == -1) {
+ SPL_X(s);
+ return EIO;
+ }
+ if (appr_init() == -1) {
+ SPL_X(s);
+ return EIO;
+ }
# ifdef NETBSD_PF
# if __NetBSD_Version__ >= 104200000
@@ -261,6 +273,7 @@ int iplattach()
# ifdef USE_INET6
goto pfil_error;
# else
+ SPL_X(s);
appr_unload();
ip_natunload();
fr_stateunload();
@@ -277,6 +290,7 @@ int iplattach()
pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
&inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
pfil_error:
+ SPL_X(s);
appr_unload();
ip_natunload();
fr_stateunload();
@@ -321,10 +335,15 @@ pfil_error:
callout_init(&ipfr_slowtimer_ch);
callout_reset(&ipfr_slowtimer_ch, hz / 2, ipfr_slowtimer, NULL);
# else
-# if (__FreeBSD_version >= 300000) || defined(__sgi)
- ipfr_slowtimer_ch = timeout(ipfr_slowtimer, NULL, hz/2);
+# if defined(__OpenBSD__)
+ timeout_set(&ipfr_slowtimer_ch, ipfr_slowtimer, NULL);
+ timeout_add(&ipfr_slowtimer_ch, hz/2);
# else
+# if (__FreeBSD_version >= 300000) || defined(__sgi)
+ ipfr_slowtimer_ch = timeout(ipfr_slowtimer, NULL, hz/2);
+# else
timeout(ipfr_slowtimer, NULL, hz/2);
+# endif
# endif
# endif
#endif
@@ -353,8 +372,12 @@ int ipldetach()
# ifdef __sgi
untimeout(ipfr_slowtimer_ch);
# else
+# if defined(__OpenBSD__)
+ timeout_del(&ipfr_slowtimer_ch);
+# else
untimeout(ipfr_slowtimer, NULL);
-# endif
+# endif /* OpenBSD */
+# endif /* __sgi */
# endif /* FreeBSD */
# endif /* NetBSD */
#endif
@@ -376,16 +399,20 @@ int ipldetach()
# if __NetBSD_Version__ >= 104200000
error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
&inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
- if (error)
+ if (error) {
+ SPL_X(s);
return error;
+ }
# else
pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
# endif
# ifdef USE_INET6
error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
&inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh);
- if (error)
+ if (error) {
+ SPL_X(s);
return error;
+ }
# endif
# endif
@@ -489,8 +516,9 @@ int mode;
}
if (unit == IPL_LOGAUTH) {
if (!fr_running)
- return EIO;
- error = fr_auth_ioctl(data, cmd, NULL, NULL);
+ error = EIO;
+ else
+ error = fr_auth_ioctl(data, mode, cmd, NULL, NULL);
SPL_X(s);
return error;
}
@@ -564,7 +592,7 @@ int mode;
fr_getstat(&fio);
error = IWCOPYPTR((caddr_t)&fio, data, sizeof(fio));
if (error)
- return EFAULT;
+ error = EFAULT;
break;
}
case SIOCFRZST :
@@ -607,7 +635,7 @@ int mode;
error = IWCOPYPTR((caddr_t)ipfr_fragstats(), data,
sizeof(ipfrstat_t));
if (error)
- return EFAULT;
+ error = EFAULT;
break;
case SIOCAUTHW :
case SIOCAUTHR :
@@ -820,8 +848,6 @@ caddr_t data;
return EBUSY;
if (fg && fg->fg_head)
fg->fg_head->fr_ref--;
- if (unit == IPL_LOGAUTH)
- return fr_auth_ioctl(data, req, f, ftail);
if (f->fr_grhead)
fr_delgroup((u_int)f->fr_grhead, fp->fr_flags,
unit, set);
@@ -835,8 +861,6 @@ caddr_t data;
if (f)
error = EEXIST;
else {
- if (unit == IPL_LOGAUTH)
- return fr_auth_ioctl(data, req, fp, ftail);
KMALLOC(f, frentry_t *);
if (f != NULL) {
if (fg && fg->fg_head)
@@ -1068,7 +1092,7 @@ struct mbuf *m;
# ifdef IPSEC
m->m_pkthdr.rcvif = NULL;
# endif
- return ipfr_fastroute(m, fin, NULL);
+ return ipfr_fastroute(m, fin->fin_mp, fin, NULL);
}
@@ -1079,6 +1103,7 @@ fr_info_t *fin;
int dst;
{
int err, hlen = 0, xtra = 0, iclen, ohlen = 0, avail, code;
+ u_short shlen, slen = 0, soff = 0;
struct in_addr dst4;
struct icmp *icmp;
struct mbuf *m;
@@ -1220,6 +1245,11 @@ int dst;
} else
#endif
{
+ slen = oip->ip_len;
+ oip->ip_len = htons(oip->ip_len);
+ soff = oip->ip_off;
+ oip->ip_off = htons(ip->ip_off);
+
ip->ip_src.s_addr = dst4.s_addr;
ip->ip_dst.s_addr = oip->ip_src.s_addr;
@@ -1233,7 +1263,18 @@ int dst;
ip->ip_len = iclen;
ip->ip_p = IPPROTO_ICMP;
}
+
+ shlen = fin->fin_hlen;
+ fin->fin_hlen = hlen;
err = send_ip(oip, fin, m);
+ fin->fin_hlen = shlen;
+#ifdef USE_INET6
+ if (fin->fin_v == 4)
+#endif
+ {
+ oip->ip_len = slen;
+ oip->ip_off = soff;
+ }
return err;
}
@@ -1268,8 +1309,8 @@ register struct mbuf *m0;
}
-int ipfr_fastroute(m0, fin, fdp)
-struct mbuf *m0;
+int ipfr_fastroute(m0, mpp, fin, fdp)
+struct mbuf *m0, **mpp;
fr_info_t *fin;
frdest_t *fdp;
{
@@ -1282,16 +1323,49 @@ frdest_t *fdp;
struct route iproute;
frentry_t *fr;
+#ifdef M_WRITABLE
+ /*
+ * HOT FIX/KLUDGE:
+ *
+ * If the mbuf we're about to send is not writable (because of
+ * a cluster reference, for example) we'll need to make a copy
+ * of it since this routine modifies the contents.
+ *
+ * If you have non-crappy network hardware that can transmit data
+ * from the mbuf, rather than making a copy, this is gonna be a
+ * problem.
+ */
+ if (M_WRITABLE(m) == 0) {
+ if ((m0 = m_dup(m, M_DONTWAIT)) != 0) {
+ m_freem(m);
+ m = m0;
+ } else {
+ error = ENOBUFS;
+ m_freem(m);
+ ipl_frouteok[1]++;
+ }
+ }
+#endif
+
hlen = fin->fin_hlen;
ip = mtod(m0, struct ip *);
+#if defined(__NetBSD__) && defined(M_CSUM_IPv4)
+ /*
+ * Clear any in-bound checksum flags for this packet.
+ */
+ m0->m_pkthdr.csuminfo = 0;
+#endif /* __NetBSD__ && M_CSUM_IPv4 */
+
#ifdef USE_INET6
if (ip->ip_v == 6) {
/*
* currently "to <if>" and "to <if>:ip#" are not supported
* for IPv6
*/
- return ip6_output(m0, NULL, NULL, 0, NULL, NULL);
+ error = ip6_output(m0, NULL, NULL, 0, NULL, NULL);
+ *mpp = NULL;
+ return error;
}
#endif
/*
@@ -1316,10 +1390,15 @@ frdest_t *fdp;
*/
if ((fr != NULL) && (fin->fin_rev != 0)) {
if ((ifp != NULL) && (fdp == &fr->fr_tif))
- return -1;
+ return 0;
dst->sin_addr = ip->ip_dst;
- } else if (fdp)
- dst->sin_addr = fdp->fd_ip.s_addr ? fdp->fd_ip : ip->ip_dst;
+ } else if (fdp) {
+ if (fdp->fd_ip.s_addr) {
+ dst->sin_addr = fdp->fd_ip;
+ ip->ip_dst = fdp->fd_ip;
+ } else
+ dst->sin_addr = ip->ip_dst;
+ }
# if BSD >= 199306
dst->sin_len = sizeof(*dst);
@@ -1374,36 +1453,44 @@ frdest_t *fdp;
* If small enough for interface, can just send directly.
*/
if (ip->ip_len <= ifp->if_mtu) {
-# if BSD >= 199306
+# if defined(MCLISREFERENCED) && !defined(sparc)
int i = 0;
-# ifdef MCLISREFERENCED
if ((m->m_flags & M_EXT) && MCLISREFERENCED(m))
-# else
- if (m->m_flags & M_EXT)
-# endif
i = 1;
# endif
# ifndef sparc
+# if !(_BSDI_VERSION >= 199510)
ip->ip_id = htons(ip->ip_id);
+# endif
ip->ip_len = htons(ip->ip_len);
ip->ip_off = htons(ip->ip_off);
# endif
+# if defined(__NetBSD__) && defined(M_CSUM_IPv4)
+ if (ifp->if_capabilities & IFCAP_CSUM_IPv4)
+ m->m_pkthdr.csuminfo |= M_CSUM_IPv4;
+ else if (ip->ip_sum == 0)
+ ip->ip_sum = in_cksum(m, hlen);
+# else
if (!ip->ip_sum)
ip->ip_sum = in_cksum(m, hlen);
+# endif /* __NetBSD__ && M_CSUM_IPv4 */
# if BSD >= 199306
error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
ro->ro_rt);
+# if defined(MCLISREFERENCED) && !defined(sparc)
if (i) {
ip->ip_id = ntohs(ip->ip_id);
ip->ip_len = ntohs(ip->ip_len);
ip->ip_off = ntohs(ip->ip_off);
}
+# endif
# 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.
@@ -1506,9 +1593,11 @@ done:
else
ipl_frouteok[1]++;
- if (ro->ro_rt)
+ if (ro->ro_rt) {
RTFREE(ro->ro_rt);
- return 0;
+ }
+ *mpp = NULL;
+ return error;
bad:
if (error == EMSGSIZE) {
sifp = fin->fin_ifp;
@@ -1550,6 +1639,18 @@ void *ifp;
return (ifp == iproute.ro_rt->rt_ifp);
}
+
+# ifdef USE_GETIFNAME
+char *
+get_ifname(ifp)
+struct ifnet *ifp;
+{
+ static char workbuf[64];
+
+ sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit);
+ return workbuf;
+}
+# endif
#else /* #ifdef _KERNEL */
@@ -1586,9 +1687,9 @@ ip_t *ip;
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
(defined(OpenBSD) && (OpenBSD >= 199603))
- sprintf(fname, "/tmp/%s", ifp->if_xname);
+ sprintf(fname, "%s", ifp->if_xname);
# else
- sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
+ sprintf(fname, "%s%d", ifp->if_name, ifp->if_unit);
# endif
fd = open(fname, O_WRONLY|O_APPEND);
if (fd == -1) {
@@ -1605,7 +1706,7 @@ struct ifnet *get_unit(name, v)
char *name;
int v;
{
- struct ifnet *ifp, **ifa;
+ struct ifnet *ifp, **ifa, **old_ifneta;
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
(defined(OpenBSD) && (OpenBSD >= 199603))
for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
@@ -1634,10 +1735,12 @@ int v;
}
nifs = 1;
} else {
+ old_ifneta = ifneta;
nifs++;
ifneta = (struct ifnet **)realloc(ifneta,
(nifs + 1) * sizeof(*ifa));
if (!ifneta) {
+ free(old_ifneta);
nifs = 0;
return NULL;
}
@@ -1704,28 +1807,6 @@ void init_ifp()
}
-int ipfr_fastroute(ip, fin, fdp)
-ip_t *ip;
-fr_info_t *fin;
-frdest_t *fdp;
-{
- struct ifnet *ifp = fdp->fd_ifp;
-
- if (!ifp)
- return 0; /* no routing table out here */
-
- ip->ip_len = htons((u_short)ip->ip_len);
- ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
- ip->ip_sum = 0;
-#ifdef __sgi
- (*ifp->if_output)(ifp, (void *)ip, NULL);
-#else
- (*ifp->if_output)(ifp, (void *)ip, NULL, 0);
-#endif
- return 0;
-}
-
-
int ipllog __P((void))
{
verbose("l");
OpenPOWER on IntegriCloud