summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/ip_divert.c21
-rw-r--r--sys/netinet/ip_dummynet.c42
-rw-r--r--sys/netinet/ip_dummynet.h2
-rw-r--r--sys/netinet/ip_fastfwd.c232
-rw-r--r--sys/netinet/ip_fw.h22
-rw-r--r--sys/netinet/ip_fw2.c65
-rw-r--r--sys/netinet/ip_fw_pfil.c402
-rw-r--r--sys/netinet/ip_input.c282
-rw-r--r--sys/netinet/ip_output.c349
-rw-r--r--sys/netinet/ip_var.h2
-rw-r--r--sys/netinet/raw_ip.c12
-rw-r--r--sys/netinet/tcp_input.c26
-rw-r--r--sys/netinet/tcp_reass.c26
-rw-r--r--sys/netinet/tcp_sack.c1
14 files changed, 648 insertions, 836 deletions
diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c
index afd455e..106aa56 100644
--- a/sys/netinet/ip_divert.c
+++ b/sys/netinet/ip_divert.c
@@ -373,27 +373,6 @@ cantsend:
return error;
}
-/*
- * Return a copy of the specified packet, but without
- * the divert tag. This is used when packets are ``tee'd''
- * and we want the cloned copy to not have divert processing.
- */
-struct mbuf *
-divert_clone(struct mbuf *m)
-{
- struct mbuf *clone;
- struct m_tag *mtag;
-
- clone = m_dup(m, M_DONTWAIT);
- if (clone != NULL) {
- /* strip divert tag from copy */
- mtag = m_tag_find(clone, PACKET_TAG_DIVERT, NULL);
- if (mtag != NULL)
- m_tag_delete(clone, mtag);
- }
- return clone;
-}
-
static int
div_attach(struct socket *so, int proto, struct thread *td)
{
diff --git a/sys/netinet/ip_dummynet.c b/sys/netinet/ip_dummynet.c
index 40e17d4..6c419ed 100644
--- a/sys/netinet/ip_dummynet.c
+++ b/sys/netinet/ip_dummynet.c
@@ -179,7 +179,6 @@ static struct mtx dummynet_mtx;
static int config_pipe(struct dn_pipe *p);
static int ip_dn_ctl(struct sockopt *sopt);
-static void rt_unref(struct rtentry *, const char *);
static void dummynet(void *);
static void dummynet_flush(void);
void dummynet_drain(void);
@@ -188,19 +187,6 @@ static void dn_rule_delete(void *);
int if_tx_rdy(struct ifnet *ifp);
-static void
-rt_unref(struct rtentry *rt, const char *where)
-{
- if (rt == NULL)
- return ;
- RT_LOCK(rt);
- if (rt->rt_refcnt <= 0) {
- printf("dummynet: warning, refcnt now %ld, decreasing (%s)\n",
- rt->rt_refcnt, where);
- }
- RTFREE_LOCKED(rt);
-}
-
/*
* Heap management functions.
*
@@ -446,6 +432,7 @@ transmit_event(struct dn_pipe *pipe)
{
struct mbuf *m ;
struct dn_pkt_tag *pkt ;
+ struct ip *ip;
DUMMYNET_LOCK_ASSERT();
@@ -468,6 +455,9 @@ transmit_event(struct dn_pipe *pipe)
break ;
case DN_TO_IP_IN :
+ ip = mtod(m, struct ip *);
+ ip->ip_len = htons(ip->ip_len);
+ ip->ip_off = htons(ip->ip_off);
ip_input(m) ;
break ;
@@ -1127,8 +1117,6 @@ locate_flowset(int pipe_nr, struct ip_fw *rule)
* ifp the 'ifp' parameter from the caller.
* NULL in ip_input, destination interface in ip_output,
* real_dst in bdg_forward
- * ro route parameter (only used in ip_output, NULL otherwise)
- * dst destination address, only used by ip_output
* rule matching rule, in case of multiple passes
* flags flags from the caller, only used in ip_output
*
@@ -1214,23 +1202,8 @@ dummynet_io(struct mbuf *m, int pipe_nr, int dir, struct ip_fw_args *fwa)
pkt->dn_dir = dir ;
pkt->ifp = fwa->oif;
- if (dir == DN_TO_IP_OUT) {
- /*
- * We need to copy *ro because for ICMP pkts (and maybe others)
- * the caller passed a pointer into the stack; dst might also be
- * a pointer into *ro so it needs to be updated.
- */
- pkt->ro = *(fwa->ro);
- if (pkt->ro.ro_rt) {
- RT_LOCK(pkt->ro.ro_rt);
- RT_ADDREF(pkt->ro.ro_rt) ;
- RT_UNLOCK(pkt->ro.ro_rt);
- }
- if (fwa->dst == (struct sockaddr_in *)&fwa->ro->ro_dst) /* dst points into ro */
- fwa->dst = (struct sockaddr_in *)&(pkt->ro.ro_dst) ;
- pkt->dn_dst = fwa->dst;
+ if (dir == DN_TO_IP_OUT)
pkt->flags = fwa->flags;
- }
if (q->head == NULL)
q->head = m;
else
@@ -1327,7 +1300,6 @@ dropit:
* Doing this would probably save us the initial bzero of dn_pkt
*/
#define DN_FREE_PKT(_m) do { \
- rt_unref(dn_tag_get(_m)->ro.ro_rt, __func__); \
m_freem(_m); \
} while (0)
@@ -2091,6 +2063,6 @@ static moduledata_t dummynet_mod = {
dummynet_modevent,
NULL
};
-DECLARE_MODULE(dummynet, dummynet_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
-MODULE_DEPEND(dummynet, ipfw, 1, 1, 1);
+DECLARE_MODULE(dummynet, dummynet_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
+MODULE_DEPEND(dummynet, ipfw, 2, 2, 2);
MODULE_VERSION(dummynet, 1);
diff --git a/sys/netinet/ip_dummynet.h b/sys/netinet/ip_dummynet.h
index 28e85a9..f241dcd 100644
--- a/sys/netinet/ip_dummynet.h
+++ b/sys/netinet/ip_dummynet.h
@@ -127,8 +127,6 @@ struct dn_pkt_tag {
dn_key output_time; /* when the pkt is due for delivery */
struct ifnet *ifp; /* interface, for ip_output */
- struct sockaddr_in *dn_dst ;
- struct route ro; /* route, for ip_output. MUST COPY */
int flags ; /* flags, for ip_output (IPv6 ?) */
};
#endif /* _KERNEL */
diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c
index 78e46dd..bc7c359 100644
--- a/sys/netinet/ip_fastfwd.c
+++ b/sys/netinet/ip_fastfwd.c
@@ -76,9 +76,6 @@
*/
#include "opt_ipfw.h"
-#include "opt_ipdn.h"
-#include "opt_ipdivert.h"
-#include "opt_ipfilter.h"
#include "opt_ipstealth.h"
#include "opt_pfil_hooks.h"
@@ -107,10 +104,6 @@
#include <machine/in_cksum.h>
-#include <netinet/ip_fw.h>
-#include <netinet/ip_divert.h>
-#include <netinet/ip_dummynet.h>
-
static int ipfastforward_active = 0;
SYSCTL_INT(_net_inet_ip, OID_AUTO, fastforwarding, CTLFLAG_RW,
&ipfastforward_active, 0, "Enable fast IP forwarding");
@@ -163,20 +156,18 @@ ip_fastforward(struct mbuf *m)
{
struct ip *ip;
struct mbuf *m0 = NULL;
-#ifdef IPDIVERT
- struct ip *tip;
- struct mbuf *clone = NULL;
-#endif
struct route ro;
struct sockaddr_in *dst = NULL;
struct in_ifaddr *ia = NULL;
struct ifaddr *ifa = NULL;
struct ifnet *ifp;
- struct ip_fw_args args;
struct in_addr odest, dest;
u_short sum, ip_len;
int error = 0;
- int hlen, ipfw, mtu;
+ int hlen, mtu;
+#ifdef IPFIREWALL_FORWARD
+ struct m_tag *fwd_tag;
+#endif
/*
* Are we active and forwarding packets?
@@ -375,92 +366,6 @@ ip_fastforward(struct mbuf *m)
ip = mtod(m, struct ip *); /* m may have changed by pfil hook */
dest.s_addr = ip->ip_dst.s_addr;
-#endif
-
- /*
- * Run through ipfw for input packets
- */
- if (fw_enable && IPFW_LOADED) {
- bzero(&args, sizeof(args));
- args.m = m;
-
- ipfw = ip_fw_chk_ptr(&args);
- m = args.m;
-
- M_ASSERTVALID(m);
- M_ASSERTPKTHDR(m);
-
- /*
- * Packet denied, drop it
- */
- if ((ipfw & IP_FW_PORT_DENY_FLAG) || m == NULL)
- goto drop;
- /*
- * Send packet to the appropriate pipe
- */
- if (DUMMYNET_LOADED && (ipfw & IP_FW_PORT_DYNT_FLAG) != 0) {
- ip_dn_io_ptr(m, ipfw & 0xffff, DN_TO_IP_IN, &args);
- return 1;
- }
-#ifdef IPDIVERT
- /*
- * Divert packet
- */
- if (ipfw != 0 && (ipfw & IP_FW_PORT_DYNT_FLAG) == 0) {
- /*
- * See if this is a fragment
- */
- if (ip->ip_off & (IP_MF | IP_OFFMASK))
- goto droptoours;
- /*
- * Tee packet
- */
- if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0)
- clone = divert_clone(m);
- else
- clone = m;
- if (clone == NULL)
- goto passin;
-
- /*
- * Delayed checksums are not compatible
- */
- if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
- in_delayed_cksum(m);
- m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
- }
- /*
- * Restore packet header fields to original values
- */
- tip = mtod(m, struct ip *);
- tip->ip_len = htons(tip->ip_len);
- tip->ip_off = htons(tip->ip_off);
- /*
- * Deliver packet to divert input routine
- */
- divert_packet(m, 0);
- /*
- * If this was not tee, we are done
- */
- m = clone;
- if ((ipfw & IP_FW_PORT_TEE_FLAG) == 0)
- return 1;
- /* Continue if it was tee */
- goto passin;
- }
-#endif
- if (ipfw == 0 && args.next_hop != NULL) {
- dest.s_addr = args.next_hop->sin_addr.s_addr;
- goto passin;
- }
- /*
- * Let through or not?
- */
- if (ipfw != 0)
- goto drop;
- }
-passin:
- ip = mtod(m, struct ip *); /* if m changed during fw processing */
/*
* Destination address changed?
@@ -475,6 +380,15 @@ passin:
* Go on with new destination address
*/
}
+#ifdef IPFIREWALL_FORWARD
+ if (m->m_flags & M_FASTFWD_OURS) {
+ /*
+ * ipfw changed it for a local address on this host.
+ */
+ goto forwardlocal;
+ }
+#endif /* IPFIREWALL_FORWARD */
+#endif /* PFIL_HOOKS */
/*
* Step 4: decrement TTL and look up route
@@ -528,123 +442,32 @@ passin:
ip = mtod(m, struct ip *);
dest.s_addr = ip->ip_dst.s_addr;
-#endif
- if (fw_enable && IPFW_LOADED && !args.next_hop) {
- bzero(&args, sizeof(args));
- args.m = m;
- args.oif = ifp;
-
- ipfw = ip_fw_chk_ptr(&args);
- m = args.m;
-
- M_ASSERTVALID(m);
- M_ASSERTPKTHDR(m);
-
- if ((ipfw & IP_FW_PORT_DENY_FLAG) || m == NULL)
- goto drop;
-
- if (DUMMYNET_LOADED && (ipfw & IP_FW_PORT_DYNT_FLAG) != 0) {
- /*
- * XXX note: if the ifp or rt entry are deleted
- * while a pkt is in dummynet, we are in trouble!
- */
- args.ro = &ro; /* dummynet does not save it */
- args.dst = dst;
-
- ip_dn_io_ptr(m, ipfw & 0xffff, DN_TO_IP_OUT, &args);
- goto consumed;
- }
-#ifdef IPDIVERT
- if (ipfw != 0 && (ipfw & IP_FW_PORT_DYNT_FLAG) == 0) {
- /*
- * See if this is a fragment
- */
- if (ip->ip_off & (IP_MF | IP_OFFMASK))
- goto droptoours;
- /*
- * Tee packet
- */
- if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0)
- clone = divert_clone(m);
- else
- clone = m;
- if (clone == NULL)
- goto passout;
-
- /*
- * Delayed checksums are not compatible with divert
- */
- if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
- in_delayed_cksum(m);
- m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
- }
- /*
- * Restore packet header fields to original values
- */
- tip = mtod(m, struct ip *);
- tip->ip_len = htons(tip->ip_len);
- tip->ip_off = htons(tip->ip_off);
- /*
- * Deliver packet to divert input routine
- */
- divert_packet(m, 0);
- /*
- * If this was not tee, we are done
- */
- m = clone;
- if ((ipfw & IP_FW_PORT_TEE_FLAG) == 0) {
- goto consumed;
- }
- /* Continue if it was tee */
- goto passout;
- }
-#endif
- if (ipfw == 0 && args.next_hop != NULL) {
- dest.s_addr = args.next_hop->sin_addr.s_addr;
- goto passout;
- }
- /*
- * Let through or not?
- */
- if (ipfw != 0)
- goto drop;
- }
-passout:
- ip = mtod(m, struct ip *);
/*
* Destination address changed?
*/
+#ifndef IPFIREWALL_FORWARD
if (odest.s_addr != dest.s_addr) {
+#else
+ fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
+ if (odest.s_addr != dest.s_addr || fwd_tag != NULL) {
+#endif /* IPFIREWALL_FORWARD */
/*
* Is it now for a local address on this host?
*/
+#ifndef IPFIREWALL_FORWARD
if (in_localip(dest)) {
+#else
+ if (in_localip(dest) || m->m_flags & M_FASTFWD_OURS) {
+#endif /* IPFIREWALL_FORWARD */
forwardlocal:
- if (args.next_hop) {
- struct m_tag *mtag = m_tag_get(
- PACKET_TAG_IPFORWARD,
- sizeof(struct sockaddr_in *),
- M_NOWAIT);
- if (mtag == NULL) {
- goto drop;
- }
- *(struct sockaddr_in **)(mtag+1) =
- args.next_hop;
- m_tag_prepend(m, mtag);
- }
-#ifdef IPDIVERT
-droptoours: /* Used for DIVERT */
-#endif
/* for ip_input */
m->m_flags |= M_FASTFWD_OURS;
-
- /* ip still points to the real packet */
ip->ip_len = htons(ip->ip_len);
ip->ip_off = htons(ip->ip_off);
/*
- * Return packet for processing by ip_input
+ * Return packet for processing by ip_input()
*/
if (ro.ro_rt)
RTFREE(ro.ro_rt);
@@ -653,11 +476,20 @@ droptoours: /* Used for DIVERT */
/*
* Redo route lookup with new destination address
*/
+#ifdef IPFIREWALL_FORWARD
+ if (fwd_tag) {
+ if (!in_localip(ip->ip_src) && !in_localaddr(ip->ip_dst))
+ dest.s_addr = ((struct sockaddr_in *)(fwd_tag+1))->sin_addr.s_addr;
+ //bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in));
+ m_tag_delete(m, fwd_tag);
+ }
+#endif /* IPFIREWALL_FORWARD */
RTFREE(ro.ro_rt);
if ((dst = ip_findroute(&ro, dest, m)) == NULL)
return 1; /* icmp unreach already sent */
ifp = ro.ro_rt->rt_ifp;
}
+#endif /* PFIL_HOOKS */
/*
* Step 6: send off the packet
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index fa17599..add5289 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -28,6 +28,7 @@
#ifndef _IPFW2_H
#define _IPFW2_H
#define IPFW2 1
+
/*
* The kernel representation of ipfw rules is made of a list of
* 'instructions' (for all practical purposes equivalent to BPF
@@ -420,8 +421,6 @@ struct ip_fw_args {
struct ip_fw *rule; /* matching rule */
struct ether_header *eh; /* for bridged packets */
- struct route *ro; /* for dummynet */
- struct sockaddr_in *dst; /* for dummynet */
int flags; /* for dummynet */
struct ipfw_flow_id f_id; /* grabbed from IP header */
@@ -436,15 +435,24 @@ struct ip_fw_args {
struct sockopt;
struct dn_flow_set;
+int ipfw_check_in(void *, struct mbuf **, struct ifnet *, int);
+int ipfw_check_out(void *, struct mbuf **, struct ifnet *, int);
+
+int ipfw_chk(struct ip_fw_args *);
+
+int ipfw_init(void);
+void ipfw_destroy(void);
+
void flush_pipe_ptrs(struct dn_flow_set *match); /* used by dummynet */
-typedef int ip_fw_chk_t (struct ip_fw_args *args);
-typedef int ip_fw_ctl_t (struct sockopt *);
-extern ip_fw_chk_t *ip_fw_chk_ptr;
+typedef int ip_fw_ctl_t(struct sockopt *);
extern ip_fw_ctl_t *ip_fw_ctl_ptr;
extern int fw_one_pass;
-extern int fw_enable;
+
+/* For kernel ipfw_ether and ipfw_bridge. */
+typedef int ip_fw_chk_t(struct ip_fw_args *args);
+extern ip_fw_chk_t *ip_fw_chk_ptr;
#define IPFW_LOADED (ip_fw_chk_ptr != NULL)
-#endif /* _KERNEL */
+#endif /* _KERNEL */
#endif /* _IPFW2_H */
diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c
index 7559db7..c1ae851 100644
--- a/sys/netinet/ip_fw2.c
+++ b/sys/netinet/ip_fw2.c
@@ -156,9 +156,6 @@ static int autoinc_step = 100; /* bounded to 1..1000 in add_rule() */
#ifdef SYSCTL_NODE
SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, enable,
- CTLFLAG_RW | CTLFLAG_SECURE3,
- &fw_enable, 0, "Enable ipfw");
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, autoinc_step, CTLFLAG_RW,
&autoinc_step, 0, "Rule number autincrement step");
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, one_pass,
@@ -276,10 +273,6 @@ SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_keepalive, CTLFLAG_RW,
#endif /* SYSCTL_NODE */
-static ip_fw_chk_t ipfw_chk;
-
-ip_dn_ruledel_t *ip_dn_ruledel_ptr = NULL; /* hook into dummynet */
-
/*
* This macro maps an ip pointer into a layer3 header pointer of type T
*/
@@ -1653,7 +1646,7 @@ check_uidgid(ipfw_insn_u32 *insn,
* 16 bits as a dummynet pipe number instead of diverting
*/
-static int
+int
ipfw_chk(struct ip_fw_args *args)
{
/*
@@ -3348,7 +3341,7 @@ done:
callout_reset(&ipfw_timeout, dyn_keepalive_period*hz, ipfw_tick, NULL);
}
-static int
+int
ipfw_init(void)
{
struct ip_fw default_rule;
@@ -3384,7 +3377,13 @@ ipfw_init(void)
ip_fw_default_rule = layer3_chain.rules;
printf("ipfw2 initialized, divert %s, "
- "rule-based forwarding enabled, default to %s, logging ",
+ "rule-based forwarding "
+#ifdef IPFIREWALL_FORWARD
+ "enabled, "
+#else
+ "disabled, "
+#endif
+ "default to %s, logging ",
#ifdef IPDIVERT
"enabled",
#else
@@ -3406,22 +3405,23 @@ ipfw_init(void)
printf("limited to %d packets/entry by default\n",
verbose_limit);
- ip_fw_chk_ptr = ipfw_chk;
+ init_tables();
ip_fw_ctl_ptr = ipfw_ctl;
+ ip_fw_chk_ptr = ipfw_chk;
callout_reset(&ipfw_timeout, hz, ipfw_tick, NULL);
return (0);
}
-static void
+void
ipfw_destroy(void)
{
struct ip_fw *reap;
- IPFW_LOCK(&layer3_chain);
- callout_stop(&ipfw_timeout);
ip_fw_chk_ptr = NULL;
ip_fw_ctl_ptr = NULL;
+ IPFW_LOCK(&layer3_chain);
+ callout_stop(&ipfw_timeout);
layer3_chain.reap = NULL;
free_chain(&layer3_chain, 1 /* kill default rule */);
reap = layer3_chain.reap, layer3_chain.reap = NULL;
@@ -3434,41 +3434,4 @@ ipfw_destroy(void)
printf("IP firewall unloaded\n");
}
-static int
-ipfw_modevent(module_t mod, int type, void *unused)
-{
- int err = 0;
-
- switch (type) {
- case MOD_LOAD:
- if (IPFW_LOADED) {
- printf("IP firewall already loaded\n");
- err = EEXIST;
- } else {
- err = ipfw_init();
- }
- break;
-
- case MOD_UNLOAD:
- ipfw_destroy();
- err = 0;
- break;
- default:
- return EOPNOTSUPP;
- break;
- }
- return err;
-}
-
-static moduledata_t ipfwmod = {
- "ipfw",
- ipfw_modevent,
- 0
-};
-DECLARE_MODULE(ipfw, ipfwmod, SI_SUB_PSEUDO, SI_ORDER_ANY);
-MODULE_VERSION(ipfw, 1);
-
-/* Must be run after route_init(). */
-SYSINIT(ipfw, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, init_tables, 0)
-
#endif /* IPFW2 */
diff --git a/sys/netinet/ip_fw_pfil.c b/sys/netinet/ip_fw_pfil.c
new file mode 100644
index 0000000..9056ab6
--- /dev/null
+++ b/sys/netinet/ip_fw_pfil.c
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 2004 Andre Oppermann, Internet Business Solutions AG
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#if !defined(KLD_MODULE)
+#include "opt_ipfw.h"
+#include "opt_ipdn.h"
+#include "opt_ipdivert.h"
+#include "opt_inet.h"
+#ifndef INET
+#error IPFIREWALL requires INET.
+#endif /* INET */
+#endif
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/module.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/ucred.h>
+
+#include <net/if.h>
+#include <net/route.h>
+#include <net/pfil.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip_fw.h>
+#include <netinet/ip_divert.h>
+#include <netinet/ip_dummynet.h>
+
+#include <machine/in_cksum.h>
+
+static int ipfw_pfil_hooked = 0;
+
+/* Dummynet hooks. */
+ip_dn_ruledel_t *ip_dn_ruledel_ptr = NULL;
+
+#define DIV_DIR_IN 1
+#define DIV_DIR_OUT 0
+
+static int ipfw_divert(struct mbuf **, int, int);
+
+int
+ipfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
+{
+ struct ip_fw_args args;
+ struct m_tag *dn_tag;
+ int ipfw = 0;
+ int divert;
+#ifdef IPFIREWALL_FORWARD
+ struct m_tag *fwd_tag;
+#endif
+
+ KASSERT(dir == PFIL_IN, ("ipfw_check_in wrong direction!"));
+
+ bzero(&args, sizeof(args));
+
+ dn_tag = m_tag_find(*m0, PACKET_TAG_DUMMYNET, NULL);
+ if (dn_tag != NULL){
+ struct dn_pkt_tag *dt;
+
+ dt = (struct dn_pkt_tag *)(dn_tag+1);
+ args.rule = dt->rule;
+
+ m_tag_delete(*m0, dn_tag);
+ }
+
+ args.m = *m0;
+ ipfw = ipfw_chk(&args);
+ *m0 = args.m;
+
+ if ((ipfw & IP_FW_PORT_DENY_FLAG) || *m0 == NULL)
+ goto drop;
+
+ if (ipfw == 0 && args.next_hop == NULL)
+ goto pass;
+
+ if (DUMMYNET_LOADED && (ipfw & IP_FW_PORT_DYNT_FLAG) != 0) {
+ ip_dn_io_ptr(*m0, ipfw & 0xffff, DN_TO_IP_IN, &args);
+ *m0 = NULL;
+ return 0; /* packet consumed */
+ }
+
+ if (ipfw != 0 && (ipfw & IP_FW_PORT_DYNT_FLAG) == 0) {
+ if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0)
+ divert = ipfw_divert(m0, DIV_DIR_IN, 1);
+ else
+ divert = ipfw_divert(m0, DIV_DIR_IN, 0);
+
+ /* tee should continue again with the firewall. */
+ if (divert) {
+ *m0 = NULL;
+ return 0; /* packet consumed */
+ } else
+ goto pass; /* continue with packet */
+ }
+
+#ifdef IPFIREWALL_FORWARD
+ if (ipfw == 0 && args.next_hop != NULL) {
+ fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD,
+ sizeof(struct sockaddr_in), M_NOWAIT);
+ if (fwd_tag == NULL)
+ goto drop;
+ bcopy(args.next_hop, (fwd_tag+1), sizeof(struct sockaddr_in));
+ m_tag_prepend(*m0, fwd_tag);
+
+ if (in_localip(args.next_hop->sin_addr))
+ (*m0)->m_flags |= M_FASTFWD_OURS;
+ goto pass;
+ }
+#endif
+
+drop:
+ if (*m0)
+ m_freem(*m0);
+ *m0 = NULL;
+ return (EACCES);
+pass:
+ return 0; /* not filtered */
+}
+
+int
+ipfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
+{
+ struct ip_fw_args args;
+ struct m_tag *dn_tag;
+ int ipfw = 0;
+ int divert;
+#ifdef IPFIREWALL_FORWARD
+ struct m_tag *fwd_tag;
+#endif
+
+ KASSERT(dir == PFIL_OUT, ("ipfw_check_out wrong direction!"));
+
+ bzero(&args, sizeof(args));
+
+ dn_tag = m_tag_find(*m0, PACKET_TAG_DUMMYNET, NULL);
+ if (dn_tag != NULL) {
+ struct dn_pkt_tag *dt;
+
+ dt = (struct dn_pkt_tag *)(dn_tag+1);
+ args.rule = dt->rule;
+
+ m_tag_delete(*m0, dn_tag);
+ }
+
+ args.m = *m0;
+ args.oif = ifp;
+ ipfw = ipfw_chk(&args);
+ *m0 = args.m;
+
+ if ((ipfw & IP_FW_PORT_DENY_FLAG) || *m0 == NULL)
+ goto drop;
+
+ if (ipfw == 0 && args.next_hop == NULL)
+ goto pass;
+
+ if (DUMMYNET_LOADED && (ipfw & IP_FW_PORT_DYNT_FLAG) != 0) {
+ ip_dn_io_ptr(*m0, ipfw & 0xffff, DN_TO_IP_OUT, &args);
+ *m0 = NULL;
+ return 0; /* packet consumed */
+ }
+
+ if (ipfw != 0 && (ipfw & IP_FW_PORT_DYNT_FLAG) == 0) {
+ if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0)
+ divert = ipfw_divert(m0, DIV_DIR_OUT, 1);
+ else
+ divert = ipfw_divert(m0, DIV_DIR_OUT, 0);
+
+ if (divert) {
+ *m0 = NULL;
+ return 0; /* packet consumed */
+ } else
+ goto pass; /* continue with packet */
+ }
+
+#ifdef IPFIREWALL_FORWARD
+ if (ipfw == 0 && args.next_hop != NULL) {
+ /* Overwrite existing tag. */
+ fwd_tag = m_tag_find(*m0, PACKET_TAG_IPFORWARD, NULL);
+ if (fwd_tag == NULL)
+ fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD,
+ sizeof(struct sockaddr_in), M_NOWAIT);
+ if (fwd_tag == NULL)
+ goto drop;
+ bcopy(args.next_hop, (fwd_tag+1), sizeof(struct sockaddr_in));
+ m_tag_prepend(*m0, fwd_tag);
+
+ if (in_localip(args.next_hop->sin_addr))
+ (*m0)->m_flags |= M_FASTFWD_OURS;
+ goto pass;
+ }
+#endif
+
+drop:
+ if (*m0)
+ m_freem(*m0);
+ *m0 = NULL;
+ return (EACCES);
+pass:
+ return 0; /* not filtered */
+}
+
+static int
+ipfw_divert(struct mbuf **m, int incoming, int tee)
+{
+ /*
+ * ipfw_chk() has already tagged the packet with the divert
+ * tag. For tee we need to remove the tag.
+ * If tee is set, copy packet and return original.
+ * If not tee, consume packet and send it to divert socket.
+ */
+#ifdef IPDIVERT
+ struct mbuf *clone, *reass;
+ struct m_tag *mtag;
+ struct ip *ip;
+ int hlen;
+
+ reass = NULL;
+
+ /* Cloning needed for tee? */
+ if (tee)
+ clone = m_dup(*m, M_DONTWAIT);
+ else
+ clone = *m;
+
+ /* In case m_dup was unable to allocate mbufs. */
+ if (clone == NULL)
+ goto teeout;
+
+ /*
+ * Divert listeners can only handle non-fragmented packets.
+ * However when tee is set we will *not* de-fragment the packets;
+ * Doing do would put the reassembly into double-jeopardy. On top
+ * of that someone doing a tee will probably want to get the packet
+ * in its original form.
+ */
+ ip = mtod(clone, struct ip *);
+ if (!tee && ip->ip_off & (IP_MF | IP_OFFMASK)) {
+
+ /* Reassemble packet. */
+ reass = ip_reass(clone);
+
+ /*
+ * IP header checksum fixup after reassembly and leave header
+ * in network byte order.
+ */
+ if (reass != NULL) {
+ ip = mtod(reass, struct ip *);
+ hlen = ip->ip_hl << 2;
+ ip->ip_len = htons(ip->ip_len);
+ ip->ip_off = htons(ip->ip_off);
+ ip->ip_sum = 0;
+ if (hlen == sizeof(struct ip))
+ ip->ip_sum = in_cksum_hdr(ip);
+ else
+ ip->ip_sum = in_cksum(reass, hlen);
+ clone = reass;
+ } else
+ clone = NULL;
+ } else {
+ /* Convert header to network byte order. */
+ ip->ip_len = htons(ip->ip_len);
+ ip->ip_off = htons(ip->ip_off);
+ }
+
+ /* Do the dirty job... */
+ if (clone)
+ divert_packet(clone, incoming);
+
+teeout:
+ if (tee) {
+ mtag = m_tag_find(*m, PACKET_TAG_DIVERT, NULL);
+ if (mtag != NULL)
+ m_tag_delete(*m, mtag);
+ return 0; /* continue with original packet. */
+ }
+
+ /* Packet diverted and consumed */
+ return 1;
+#else
+ m_freem(*m);
+ return 1;
+#endif /* ipdivert */
+}
+
+static int
+ipfw_hook(void)
+{
+ struct pfil_head *pfh_inet;
+
+ if (ipfw_pfil_hooked)
+ return EEXIST;
+
+ pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
+ if (pfh_inet == NULL)
+ return ENOENT;
+
+ pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
+ pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet);
+
+ return 0;
+}
+
+static int
+ipfw_unhook(void)
+{
+ struct pfil_head *pfh_inet;
+
+ if (!ipfw_pfil_hooked)
+ return ENOENT;
+
+ pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
+ if (pfh_inet == NULL)
+ return ENOENT;
+
+ pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
+ pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet);
+
+ return 0;
+}
+
+static int
+ipfw_modevent(module_t mod, int type, void *unused)
+{
+ int err = 0;
+
+ switch (type) {
+ case MOD_LOAD:
+ if (ipfw_pfil_hooked) {
+ printf("IP firewall already loaded\n");
+ err = EEXIST;
+ } else {
+ if ((err = ipfw_init()) != 0) {
+ printf("ipfw_init() error\n");
+ break;
+ }
+ if ((err = ipfw_hook()) != 0) {
+ printf("ipfw_hook() error\n");
+ break;
+ }
+ ipfw_pfil_hooked = 1;
+ }
+ break;
+
+ case MOD_UNLOAD:
+ if (ipfw_pfil_hooked) {
+ if ((err = ipfw_unhook()) > 0);
+ break;
+ ipfw_destroy();
+ ipfw_pfil_hooked = 0;
+ } else {
+ printf("IP firewall already unloaded\n");
+ }
+ break;
+
+ default:
+ return EOPNOTSUPP;
+ break;
+ }
+ return err;
+}
+
+static moduledata_t ipfwmod = {
+ "ipfw",
+ ipfw_modevent,
+ 0
+};
+DECLARE_MODULE(ipfw, ipfwmod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
+MODULE_VERSION(ipfw, 2);
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 0ae3c16..fc4ab6e 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -32,9 +32,6 @@
#include "opt_bootp.h"
#include "opt_ipfw.h"
-#include "opt_ipdn.h"
-#include "opt_ipdivert.h"
-#include "opt_ipfilter.h"
#include "opt_ipstealth.h"
#include "opt_ipsec.h"
#include "opt_mac.h"
@@ -72,8 +69,8 @@
#include <sys/socketvar.h>
+/* XXX: Temporary until ipfw_ether and ipfw_bridge are converted. */
#include <netinet/ip_fw.h>
-#include <netinet/ip_divert.h>
#include <netinet/ip_dummynet.h>
#ifdef IPSEC
@@ -208,15 +205,14 @@ SYSCTL_INT(_net_inet_ip, OID_AUTO, stealth, CTLFLAG_RW,
&ipstealth, 0, "");
#endif
-
-/* Firewall hooks */
-ip_fw_chk_t *ip_fw_chk_ptr;
-int fw_enable = 1 ;
+/*
+ * ipfw_ether and ipfw_bridge hooks.
+ * XXX: Temporary until those are converted to pfil_hooks as well.
+ */
+ip_fw_chk_t *ip_fw_chk_ptr = NULL;
+ip_dn_io_t *ip_dn_io_ptr = NULL;
int fw_one_pass = 1;
-/* Dummynet hooks */
-ip_dn_io_t *ip_dn_io_ptr;
-
/*
* XXX this is ugly -- the following two global variables are
* used to store packet state while it travels through the stack.
@@ -240,12 +236,9 @@ static struct ip_srcrt {
} ip_srcrt;
static void save_rte(u_char *, struct in_addr);
-static int ip_dooptions(struct mbuf *m, int,
- struct sockaddr_in *next_hop);
-static void ip_forward(struct mbuf *m, int srcrt,
- struct sockaddr_in *next_hop);
+static int ip_dooptions(struct mbuf *m, int);
+static void ip_forward(struct mbuf *m, int srcrt);
static void ip_freef(struct ipqhead *, struct ipq *);
-static struct mbuf *ip_reass(struct mbuf *);
/*
* IP initialization: fill in IP protocol switch table.
@@ -301,13 +294,8 @@ ip_input(struct mbuf *m)
struct ip *ip = NULL;
struct in_ifaddr *ia = NULL;
struct ifaddr *ifa;
- int i, checkif, hlen = 0;
+ int checkif, hlen = 0;
u_short sum;
- struct in_addr pkt_dst;
-#ifdef IPDIVERT
- u_int32_t divert_info; /* packet divert/tee info */
-#endif
- struct ip_fw_args args;
int dchg = 0; /* dest changed after fw */
#ifdef PFIL_HOOKS
struct in_addr odst; /* original dst address */
@@ -319,26 +307,20 @@ ip_input(struct mbuf *m)
int s, error;
#endif /* FAST_IPSEC */
- args.eh = NULL;
- args.oif = NULL;
-
M_ASSERTPKTHDR(m);
- args.next_hop = m_claim_next(m, PACKET_TAG_IPFORWARD);
- args.rule = ip_dn_claim_rule(m);
-
if (m->m_flags & M_FASTFWD_OURS) {
- /* ip_fastforward firewall changed dest to local */
+ /*
+ * ip_fastforward firewall changed dest to local.
+ * We expect ip_len and ip_off in host byte order.
+ */
m->m_flags &= ~M_FASTFWD_OURS; /* for reflected mbufs */
+ /* Set up some basic stuff */
+ ip = mtod(m, struct ip *);
+ hlen = ip->ip_hl << 2;
goto ours;
}
- if (args.rule) { /* dummynet already filtered us */
- ip = mtod(m, struct ip *);
- hlen = ip->ip_hl << 2;
- goto iphack ;
- }
-
ipstat.ips_total++;
if (m->m_pkthdr.len < sizeof(struct ip))
@@ -441,20 +423,6 @@ tooshort:
goto pass;
#endif
- /*
- * IpHack's section.
- * Right now when no processing on packet has done
- * and it is still fresh out of network we do our black
- * deals with it.
- * - Firewall: deny/allow/divert
- * - Xlate: translate packet's addr/port (NAT).
- * - Pipe: pass pkt through dummynet.
- * - Wrap: fake packet's addr/port <unimpl.>
- * - Encapsulate: put it in another IP and send out. <unimp.>
- */
-
-iphack:
-
#ifdef PFIL_HOOKS
/*
* Run through list of hooks for input packets.
@@ -469,50 +437,23 @@ iphack:
return;
if (m == NULL) /* consumed by filter */
return;
+
ip = mtod(m, struct ip *);
dchg = (odst.s_addr != ip->ip_dst.s_addr);
-#endif /* PFIL_HOOKS */
- if (fw_enable && IPFW_LOADED) {
- /*
- * If we've been forwarded from the output side, then
- * skip the firewall a second time
- */
- if (args.next_hop)
- goto ours;
+#ifdef IPFIREWALL_FORWARD
+ if (m->m_flags & M_FASTFWD_OURS) {
+ m->m_flags &= ~M_FASTFWD_OURS;
+ goto ours;
+ }
+ dchg = (m_tag_find(m, PACKET_TAG_IPFORWARD, NULL) != NULL);
+#endif /* IPFIREWALL_FORWARD */
- args.m = m;
- i = ip_fw_chk_ptr(&args);
- m = args.m;
+#endif /* PFIL_HOOKS */
- if ( (i & IP_FW_PORT_DENY_FLAG) || m == NULL) { /* drop */
- if (m)
- m_freem(m);
- return;
- }
- ip = mtod(m, struct ip *); /* just in case m changed */
- if (i == 0 && args.next_hop == NULL) /* common case */
- goto pass;
- if (DUMMYNET_LOADED && (i & IP_FW_PORT_DYNT_FLAG) != 0) {
- /* Send packet to the appropriate pipe */
- ip_dn_io_ptr(m, i&0xffff, DN_TO_IP_IN, &args);
- return;
- }
-#ifdef IPDIVERT
- if (i != 0 && (i & IP_FW_PORT_DYNT_FLAG) == 0) {
- /* Divert or tee packet */
- goto ours;
- }
-#endif
- if (i == 0 && args.next_hop != NULL)
- goto pass;
- /*
- * if we get here, the packet must be dropped
- */
- m_freem(m);
- return;
- }
+#if defined(FAST_IPSEC) && !defined(IPSEC_FILTERGIF)
pass:
+#endif
/*
* Process options and, if not destined for us,
@@ -520,8 +461,7 @@ pass:
* error was detected (causing an icmp message
* to be sent and the original packet to be freed).
*/
- ip_nhops = 0; /* for source routed packets */
- if (hlen > sizeof (struct ip) && ip_dooptions(m, 0, args.next_hop))
+ if (hlen > sizeof (struct ip) && ip_dooptions(m, 0))
return;
/* greedy RSVP, snatches any PATH packet of the RSVP protocol and no
@@ -544,12 +484,6 @@ pass:
goto ours;
/*
- * Cache the destination address of the packet; this may be
- * changed by use of 'ipfw fwd'.
- */
- pkt_dst = args.next_hop ? args.next_hop->sin_addr : ip->ip_dst;
-
- /*
* Enable a consistency check between the destination address
* and the arrival interface for a unicast packet (the RFC 1122
* strong ES model) if IP forwarding is disabled and the packet
@@ -566,18 +500,18 @@ pass:
checkif = ip_checkinterface && (ipforwarding == 0) &&
m->m_pkthdr.rcvif != NULL &&
((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) &&
- (args.next_hop == NULL) && (dchg == 0);
+ (dchg == 0);
/*
* Check for exact addresses in the hash bucket.
*/
- LIST_FOREACH(ia, INADDR_HASH(pkt_dst.s_addr), ia_hash) {
+ LIST_FOREACH(ia, INADDR_HASH(ip->ip_dst.s_addr), ia_hash) {
/*
* If the address matches, verify that the packet
* arrived via the correct interface if checking is
* enabled.
*/
- if (IA_SIN(ia)->sin_addr.s_addr == pkt_dst.s_addr &&
+ if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr &&
(!checkif || ia->ia_ifp == m->m_pkthdr.rcvif))
goto ours;
}
@@ -596,9 +530,9 @@ pass:
continue;
ia = ifatoia(ifa);
if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr ==
- pkt_dst.s_addr)
+ ip->ip_dst.s_addr)
goto ours;
- if (ia->ia_netbroadcast.s_addr == pkt_dst.s_addr)
+ if (ia->ia_netbroadcast.s_addr == ip->ip_dst.s_addr)
goto ours;
#ifdef BOOTP_COMPAT
if (IA_SIN(ia)->sin_addr.s_addr == INADDR_ANY)
@@ -706,7 +640,7 @@ pass:
goto bad;
}
#endif /* FAST_IPSEC */
- ip_forward(m, dchg, args.next_hop);
+ ip_forward(m, dchg);
}
return;
@@ -717,7 +651,7 @@ ours:
* if the packet is destined for us.
*/
if (ipstealth && hlen > sizeof (struct ip) &&
- ip_dooptions(m, 1, args.next_hop))
+ ip_dooptions(m, 1))
return;
#endif /* IPSTEALTH */
@@ -738,20 +672,6 @@ ours:
ip = mtod(m, struct ip *);
/* Get the header length of the reassembled packet */
hlen = ip->ip_hl << 2;
-#ifdef IPDIVERT
- /* Restore original checksum before diverting packet */
- if (divert_find_info(m) != 0) {
- ip->ip_len = htons(ip->ip_len);
- ip->ip_off = htons(ip->ip_off);
- ip->ip_sum = 0;
- if (hlen == sizeof(struct ip))
- ip->ip_sum = in_cksum_hdr(ip);
- else
- ip->ip_sum = in_cksum(m, hlen);
- ip->ip_off = ntohs(ip->ip_off);
- ip->ip_len = ntohs(ip->ip_len);
- }
-#endif
}
/*
@@ -760,46 +680,6 @@ ours:
*/
ip->ip_len -= hlen;
-#ifdef IPDIVERT
- /*
- * Divert or tee packet to the divert protocol if required.
- */
- divert_info = divert_find_info(m);
- if (divert_info != 0) {
- struct mbuf *clone;
-
- /* Clone packet if we're doing a 'tee' */
- if ((divert_info & IP_FW_PORT_TEE_FLAG) != 0)
- clone = divert_clone(m);
- else
- clone = NULL;
-
- /* Restore packet header fields to original values */
- ip->ip_len += hlen;
- ip->ip_len = htons(ip->ip_len);
- ip->ip_off = htons(ip->ip_off);
-
- /* Deliver packet to divert input routine */
- divert_packet(m, 1);
- ipstat.ips_delivered++;
-
- /* If 'tee', continue with original packet */
- if (clone == NULL)
- return;
- m = clone;
- ip = mtod(m, struct ip *);
- ip->ip_len += hlen;
- /*
- * Jump backwards to complete processing of the
- * packet. We do not need to clear args.next_hop
- * as that will not be used again and the cloned packet
- * doesn't contain a divert packet tag so we won't
- * re-entry this block.
- */
- goto pass;
- }
-#endif
-
#ifdef IPSEC
/*
* enforce IPsec policy checking if we are seeing last header.
@@ -856,15 +736,7 @@ DPRINTF(("ip_input: no SP, packet discarded\n"));/*XXX*/
* Switch out to protocol's input routine.
*/
ipstat.ips_delivered++;
- if (args.next_hop && ip->ip_p == IPPROTO_TCP) {
- /* attach next hop info for TCP */
- struct m_tag *mtag = m_tag_get(PACKET_TAG_IPFORWARD,
- sizeof(struct sockaddr_in *), M_NOWAIT);
- if (mtag == NULL)
- goto bad;
- *(struct sockaddr_in **)(mtag+1) = args.next_hop;
- m_tag_prepend(m, mtag);
- }
+
(*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen);
return;
bad:
@@ -1092,18 +964,6 @@ found:
inserted:
-#ifdef IPDIVERT
- if (ip->ip_off != 0) {
- /*
- * Strip any divert information; only the info
- * on the first fragment is used/kept.
- */
- struct m_tag *mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL);
- if (mtag)
- m_tag_delete(m, mtag);
- }
-#endif
-
/*
* Check for complete reassembly and perform frag per packet
* limiting.
@@ -1298,7 +1158,7 @@ ip_drain()
* 0 if the packet should be processed further.
*/
static int
-ip_dooptions(struct mbuf *m, int pass, struct sockaddr_in *next_hop)
+ip_dooptions(struct mbuf *m, int pass)
{
struct ip *ip = mtod(m, struct ip *);
u_char *cp;
@@ -1557,7 +1417,7 @@ dropit:
}
}
if (forward && ipforwarding) {
- ip_forward(m, 1, next_hop);
+ ip_forward(m, 1);
return (1);
}
return (0);
@@ -1737,35 +1597,25 @@ u_char inetctlerrmap[PRC_NCMDS] = {
* The srcrt parameter indicates whether the packet is being forwarded
* via a source route.
*/
-static void
-ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop)
+void
+ip_forward(struct mbuf *m, int srcrt)
{
struct ip *ip = mtod(m, struct ip *);
- struct in_ifaddr *ia;
+ struct in_ifaddr *ia = NULL;
int error, type = 0, code = 0;
struct mbuf *mcopy;
- n_long dest;
- struct in_addr pkt_dst;
- struct ifnet *destifp;
-#if defined(IPSEC) || defined(FAST_IPSEC)
- struct ifnet dummyifp;
-#endif
-
- /*
- * Cache the destination address of the packet; this may be
- * changed by use of 'ipfw fwd'.
- */
- pkt_dst = next_hop ? next_hop->sin_addr : ip->ip_dst;
+ struct in_addr dest;
+ struct ifnet *destifp, dummyifp;
#ifdef DIAGNOSTIC
if (ipprintfs)
printf("forward: src %lx dst %lx ttl %x\n",
- (u_long)ip->ip_src.s_addr, (u_long)pkt_dst.s_addr,
+ (u_long)ip->ip_src.s_addr, (u_long)ip->ip_dst.s_addr,
ip->ip_ttl);
#endif
- if (m->m_flags & (M_BCAST|M_MCAST) || in_canforward(pkt_dst) == 0) {
+ if (m->m_flags & (M_BCAST|M_MCAST) || in_canforward(ip->ip_dst) == 0) {
ipstat.ips_cantforward++;
m_freem(m);
return;
@@ -1782,7 +1632,7 @@ ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop)
}
#endif
- if ((ia = ip_rtaddr(pkt_dst)) == NULL) {
+ if (!srcrt && (ia = ip_rtaddr(ip->ip_dst)) == NULL) {
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0);
return;
}
@@ -1837,8 +1687,8 @@ ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop)
* Also, don't send redirect if forwarding using a default route
* or a route modified by a redirect.
*/
- dest = 0;
- if (ipsendredirects && ia->ia_ifp == m->m_pkthdr.rcvif) {
+ dest.s_addr = 0;
+ if (!srcrt && ipsendredirects && ia->ia_ifp == m->m_pkthdr.rcvif) {
struct sockaddr_in *sin;
struct route ro;
struct rtentry *rt;
@@ -1847,29 +1697,28 @@ ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop)
sin = (struct sockaddr_in *)&ro.ro_dst;
sin->sin_family = AF_INET;
sin->sin_len = sizeof(*sin);
- sin->sin_addr = pkt_dst;
+ sin->sin_addr = ip->ip_dst;
rtalloc_ign(&ro, RTF_CLONING);
rt = ro.ro_rt;
if (rt && (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&
- satosin(rt_key(rt))->sin_addr.s_addr != 0 &&
- ipsendredirects && !srcrt && !next_hop) {
+ satosin(rt_key(rt))->sin_addr.s_addr != 0) {
#define RTA(rt) ((struct in_ifaddr *)(rt->rt_ifa))
u_long src = ntohl(ip->ip_src.s_addr);
if (RTA(rt) &&
(src & RTA(rt)->ia_subnetmask) == RTA(rt)->ia_subnet) {
if (rt->rt_flags & RTF_GATEWAY)
- dest = satosin(rt->rt_gateway)->sin_addr.s_addr;
+ dest.s_addr = satosin(rt->rt_gateway)->sin_addr.s_addr;
else
- dest = pkt_dst.s_addr;
+ dest.s_addr = ip->ip_dst.s_addr;
/* Router requirements says to only send host redirects */
type = ICMP_REDIRECT;
code = ICMP_REDIRECT_HOST;
#ifdef DIAGNOSTIC
if (ipprintfs)
- printf("redirect (%d) to %lx\n", code, (u_long)dest);
+ printf("redirect (%d) to %lx\n", code, (u_long)dest.s_addr);
#endif
}
}
@@ -1877,16 +1726,6 @@ ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop)
RTFREE(rt);
}
- if (next_hop) {
- struct m_tag *mtag = m_tag_get(PACKET_TAG_IPFORWARD,
- sizeof(struct sockaddr_in *), M_NOWAIT);
- if (mtag == NULL) {
- m_freem(m);
- return;
- }
- *(struct sockaddr_in **)(mtag+1) = next_hop;
- m_tag_prepend(m, mtag);
- }
error = ip_output(m, (struct mbuf *)0, NULL, IP_FORWARDING, 0, NULL);
if (error)
ipstat.ips_cantforward++;
@@ -1985,7 +1824,16 @@ ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop)
break;
} else
#endif /*IPSEC || FAST_IPSEC*/
- destifp = ia->ia_ifp;
+ /*
+ * When doing source routing 'ia' can be NULL. Fall back
+ * to the minimum guaranteed routeable packet size and use
+ * the same hack as IPSEC to setup a dummyifp for icmp.
+ */
+ if (ia == NULL) {
+ dummyifp.if_mtu = IP_MSS;
+ destifp = &dummyifp;
+ } else
+ destifp = ia->ia_ifp;
#if defined(IPSEC) || defined(FAST_IPSEC)
}
#endif /*IPSEC || FAST_IPSEC*/
@@ -2014,7 +1862,7 @@ ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop)
m_freem(mcopy);
return;
}
- icmp_error(mcopy, type, code, dest, destifp);
+ icmp_error(mcopy, type, code, dest.s_addr, destifp);
}
void
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 4946153..c40c682 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -31,9 +31,6 @@
*/
#include "opt_ipfw.h"
-#include "opt_ipdn.h"
-#include "opt_ipdivert.h"
-#include "opt_ipfilter.h"
#include "opt_ipsec.h"
#include "opt_mac.h"
#include "opt_pfil_hooks.h"
@@ -51,6 +48,7 @@
#include <sys/sysctl.h>
#include <net/if.h>
+#include <net/netisr.h>
#include <net/route.h>
#include <netinet/in.h>
@@ -84,10 +82,6 @@ static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options");
#include <netipsec/key.h>
#endif /*FAST_IPSEC*/
-#include <netinet/ip_fw.h>
-#include <netinet/ip_divert.h>
-#include <netinet/ip_dummynet.h>
-
#define print_ip(x, a, y) printf("%s %d.%d.%d.%d%s",\
x, (ntohl(a.s_addr)>>24)&0xFF,\
(ntohl(a.s_addr)>>16)&0xFF,\
@@ -133,49 +127,27 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
struct ifnet *ifp = NULL; /* keep compiler happy */
struct mbuf *m0;
int hlen = sizeof (struct ip);
- int len, off, error = 0;
+ int len, error = 0;
struct sockaddr_in *dst = NULL; /* keep compiler happy */
struct in_ifaddr *ia = NULL;
int isbroadcast, sw_csum;
- struct in_addr pkt_dst;
struct route iproute;
- struct m_tag *mtag, *dummytag;
+ struct in_addr odst;
+#ifdef IPFIREWALL_FORWARD
+ struct m_tag *fwd_tag = NULL;
+#endif
#ifdef IPSEC
struct secpolicy *sp = NULL;
#endif
#ifdef FAST_IPSEC
struct secpolicy *sp = NULL;
struct tdb_ident *tdbi;
+ struct m_tag *mtag;
int s;
#endif /* FAST_IPSEC */
- struct ip_fw_args args;
- int src_was_INADDR_ANY = 0; /* as the name says... */
-
- args.eh = NULL;
- args.rule = NULL;
M_ASSERTPKTHDR(m);
- args.next_hop = m_claim_next(m, PACKET_TAG_IPFORWARD);
- dummytag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
- if (dummytag != NULL) {
- struct dn_pkt_tag *dt = (struct dn_pkt_tag *)(dummytag+1);
- /*
- * Prevent lower layers from finding the tag
- * Cleanup and free is done below
- */
- m_tag_unlink(m, dummytag);
- /*
- * the packet was already tagged, so part of the
- * processing was already done, and we need to go down.
- * Get parameters from the header.
- */
- args.rule = dt->rule;
- ro = &(dt->ro);
- dst = dt->dn_dst;
- ifp = dt->ifp;
- }
-
if (ro == NULL) {
ro = &iproute;
bzero(ro, sizeof (*ro));
@@ -184,14 +156,6 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
if (inp != NULL)
INP_LOCK_ASSERT(inp);
- if (args.rule != NULL) { /* dummynet already saw us */
- ip = mtod(m, struct ip *);
- hlen = ip->ip_hl << 2 ;
- if (ro->ro_rt)
- ia = ifatoia(ro->ro_rt->rt_ifa);
- goto sendit;
- }
-
if (opt) {
len = 0;
m = ip_insertoptions(m, opt, &len);
@@ -199,7 +163,6 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
hlen = len;
}
ip = mtod(m, struct ip *);
- pkt_dst = args.next_hop ? args.next_hop->sin_addr : ip->ip_dst;
/*
* Fill in IP header. If we are not allowing fragmentation,
@@ -222,6 +185,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
}
dst = (struct sockaddr_in *)&ro->ro_dst;
+again:
/*
* If there is a cached route,
* check that it is to the same destination
@@ -231,15 +195,19 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
*/
if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
dst->sin_family != AF_INET ||
- dst->sin_addr.s_addr != pkt_dst.s_addr)) {
+ dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
RTFREE(ro->ro_rt);
ro->ro_rt = (struct rtentry *)0;
}
+#ifdef IPFIREWALL_FORWARD
+ if (ro->ro_rt == NULL && fwd_tag == NULL) {
+#else
if (ro->ro_rt == NULL) {
+#endif
bzero(dst, sizeof(*dst));
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
- dst->sin_addr = pkt_dst;
+ dst->sin_addr = ip->ip_dst;
}
/*
* If routing to interface only,
@@ -287,7 +255,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
else
isbroadcast = in_broadcast(dst->sin_addr, ifp);
}
- if (IN_MULTICAST(ntohl(pkt_dst.s_addr))) {
+ if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
struct in_multi *inm;
m->m_flags |= M_MCAST;
@@ -329,7 +297,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
ip->ip_src = IA_SIN(ia)->sin_addr;
}
- IN_LOOKUP_MULTI(pkt_dst, ifp, inm);
+ IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm);
if (inm != NULL &&
(imo == NULL || imo->imo_multicast_loop)) {
/*
@@ -395,7 +363,6 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
/* Interface may have no addresses. */
if (ia != NULL) {
ip->ip_src = IA_SIN(ia)->sin_addr;
- src_was_INADDR_ANY = 1;
}
}
#endif /* notdef */
@@ -693,250 +660,75 @@ skip_ipsec:
spd_done:
#endif /* FAST_IPSEC */
- /*
- * IpHack's section.
- * - Xlate: translate packet's addr/port (NAT).
- * - Firewall: deny/allow/etc.
- * - Wrap: fake packet's addr/port <unimpl.>
- * - Encapsulate: put it in another IP and send out. <unimp.>
- */
#ifdef PFIL_HOOKS
/*
* Run through list of hooks for output packets.
*/
+ odst.s_addr = ip->ip_dst.s_addr;
error = pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT);
if (error != 0 || m == NULL)
goto done;
- ip = mtod(m, struct ip *);
-#endif /* PFIL_HOOKS */
-
- /*
- * Check with the firewall...
- * but not if we are already being fwd'd from a firewall.
- */
- if (fw_enable && IPFW_LOADED && !args.next_hop) {
- struct sockaddr_in *old = dst;
-
- args.m = m;
- args.next_hop = dst;
- args.oif = ifp;
- off = ip_fw_chk_ptr(&args);
- m = args.m;
- dst = args.next_hop;
-
- /*
- * On return we must do the following:
- * m == NULL -> drop the pkt (old interface, deprecated)
- * (off & IP_FW_PORT_DENY_FLAG) -> drop the pkt (new interface)
- * 1<=off<= 0xffff -> DIVERT
- * (off & IP_FW_PORT_DYNT_FLAG) -> send to a DUMMYNET pipe
- * (off & IP_FW_PORT_TEE_FLAG) -> TEE the packet
- * dst != old -> IPFIREWALL_FORWARD
- * off==0, dst==old -> accept
- * If some of the above modules are not compiled in, then
- * we should't have to check the corresponding condition
- * (because the ipfw control socket should not accept
- * unsupported rules), but better play safe and drop
- * packets in case of doubt.
- */
- if ( (off & IP_FW_PORT_DENY_FLAG) || m == NULL) {
- if (m)
- m_freem(m);
- error = EACCES;
- goto done;
- }
- ip = mtod(m, struct ip *);
- if (off == 0 && dst == old) /* common case */
- goto pass;
- if (DUMMYNET_LOADED && (off & IP_FW_PORT_DYNT_FLAG) != 0) {
- /*
- * pass the pkt to dummynet. Need to include
- * pipe number, m, ifp, ro, dst because these are
- * not recomputed in the next pass.
- * All other parameters have been already used and
- * so they are not needed anymore.
- * XXX note: if the ifp or ro entry are deleted
- * while a pkt is in dummynet, we are in trouble!
- */
- args.ro = ro;
- args.dst = dst;
- args.flags = flags;
-
- error = ip_dn_io_ptr(m, off & 0xffff, DN_TO_IP_OUT,
- &args);
- goto done;
- }
-#ifdef IPDIVERT
- if (off != 0 && (off & IP_FW_PORT_DYNT_FLAG) == 0) {
- struct mbuf *clone;
-
- /* Clone packet if we're doing a 'tee' */
- if ((off & IP_FW_PORT_TEE_FLAG) != 0)
- clone = divert_clone(m);
- else
- clone = NULL;
-
- /* Restore packet header fields to original values */
- ip->ip_len = htons(ip->ip_len);
- ip->ip_off = htons(ip->ip_off);
-
- /* Deliver packet to divert input routine */
- divert_packet(m, 0);
-
- /* If 'tee', continue with original packet */
- if (clone != NULL) {
- m = clone;
- ip = mtod(m, struct ip *);
- goto pass;
- }
- goto done;
- }
-#endif
-
- /* IPFIREWALL_FORWARD */
- /*
- * Check dst to make sure it is directly reachable on the
- * interface we previously thought it was.
- * If it isn't (which may be likely in some situations) we have
- * to re-route it (ie, find a route for the next-hop and the
- * associated interface) and set them here. This is nested
- * forwarding which in most cases is undesirable, except where
- * such control is nigh impossible. So we do it here.
- * And I'm babbling.
- */
- if (off == 0 && old != dst) { /* FORWARD, dst has changed */
-#if 0
- /*
- * XXX To improve readability, this block should be
- * changed into a function call as below:
- */
- error = ip_ipforward(&m, &dst, &ifp);
- if (error)
- goto bad;
- if (m == NULL) /* ip_input consumed the mbuf */
- goto done;
-#else
- struct in_ifaddr *ia;
- /*
- * XXX sro_fwd below is static, and a pointer
- * to it gets passed to routines downstream.
- * This could have surprisingly bad results in
- * practice, because its content is overwritten
- * by subsequent packets.
- * XXX: Breaks on SMP and possibly preemption!
- */
- /* There must be a better way to do this next line... */
- static struct route sro_fwd;
- struct route *ro_fwd = &sro_fwd;
-
-#if 0
- print_ip("IPFIREWALL_FORWARD: New dst ip: ",
- dst->sin_addr, "\n");
-#endif
+ ip = mtod(m, struct ip *);
- /*
- * We need to figure out if we have been forwarded
- * to a local socket. If so, then we should somehow
- * "loop back" to ip_input, and get directed to the
- * PCB as if we had received this packet. This is
- * because it may be dificult to identify the packets
- * you want to forward until they are being output
- * and have selected an interface. (e.g. locally
- * initiated packets) If we used the loopback inteface,
- * we would not be able to control what happens
- * as the packet runs through ip_input() as
- * it is done through an ISR.
- */
- LIST_FOREACH(ia,
- INADDR_HASH(dst->sin_addr.s_addr), ia_hash) {
- /*
- * If the addr to forward to is one
- * of ours, we pretend to
- * be the destination for this packet.
- */
- if (IA_SIN(ia)->sin_addr.s_addr ==
- dst->sin_addr.s_addr)
- break;
- }
- if (ia) { /* tell ip_input "dont filter" */
- mtag = m_tag_get(
- PACKET_TAG_IPFORWARD,
- sizeof(struct sockaddr_in *), M_NOWAIT);
- if (mtag == NULL) {
- error = ENOBUFS;
- goto bad;
- }
- *(struct sockaddr_in **)(mtag+1) =
- args.next_hop;
- m_tag_prepend(m, mtag);
-
- if (m->m_pkthdr.rcvif == NULL)
- m->m_pkthdr.rcvif = ifunit("lo0");
- if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
- m->m_pkthdr.csum_flags |=
- CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
- m->m_pkthdr.csum_data = 0xffff;
- }
+ /* See if destination IP address was changed by packet filter. */
+ if (odst.s_addr != ip->ip_dst.s_addr) {
+ m->m_flags |= M_SKIP_FIREWALL;
+ if (in_localip(ip->ip_dst)) {
+ m->m_flags |= M_FASTFWD_OURS;
+ if (m->m_pkthdr.rcvif == NULL)
+ m->m_pkthdr.rcvif = ifunit("lo0");
+ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
m->m_pkthdr.csum_flags |=
- CSUM_IP_CHECKED | CSUM_IP_VALID;
- ip->ip_len = htons(ip->ip_len);
- ip->ip_off = htons(ip->ip_off);
- ip_input(m);
- goto done;
+ CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
+ m->m_pkthdr.csum_data = 0xffff;
}
- /*
- * Some of the logic for this was
- * nicked from above.
- */
- bcopy(dst, &ro_fwd->ro_dst, sizeof(*dst));
-
- ro_fwd->ro_rt = 0;
- rtalloc_ign(ro_fwd, RTF_CLONING);
+ m->m_pkthdr.csum_flags |=
+ CSUM_IP_CHECKED | CSUM_IP_VALID;
- if (ro_fwd->ro_rt == NULL) {
- ipstat.ips_noroute++;
- error = EHOSTUNREACH;
- goto bad;
- }
-
- ia = ifatoia(ro_fwd->ro_rt->rt_ifa);
- ifp = ro_fwd->ro_rt->rt_ifp;
- ro_fwd->ro_rt->rt_rmx.rmx_pksent++;
- if (ro_fwd->ro_rt->rt_flags & RTF_GATEWAY)
- dst = (struct sockaddr_in *)
- ro_fwd->ro_rt->rt_gateway;
- if (ro_fwd->ro_rt->rt_flags & RTF_HOST)
- isbroadcast =
- (ro_fwd->ro_rt->rt_flags & RTF_BROADCAST);
- else
- isbroadcast = in_broadcast(dst->sin_addr, ifp);
- if (ro->ro_rt)
- RTFREE(ro->ro_rt);
- ro->ro_rt = ro_fwd->ro_rt;
- dst = (struct sockaddr_in *)&ro_fwd->ro_dst;
+ error = netisr_queue(NETISR_IP, m);
+ goto done;
+ } else
+ goto again;
+ }
-#endif /* ... block to be put into a function */
- /*
- * If we added a default src ip earlier,
- * which would have been gotten from the-then
- * interface, do it again, from the new one.
- */
- if (src_was_INADDR_ANY)
- ip->ip_src = IA_SIN(ia)->sin_addr;
- goto pass ;
+#ifdef IPFIREWALL_FORWARD
+ /* See if local, if yes, send it to netisr with IP_FASTFWD_OURS. */
+ if (m->m_flags & M_FASTFWD_OURS) {
+ if (m->m_pkthdr.rcvif == NULL)
+ m->m_pkthdr.rcvif = ifunit("lo0");
+ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+ m->m_pkthdr.csum_flags |=
+ CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
+ m->m_pkthdr.csum_data = 0xffff;
}
+ m->m_pkthdr.csum_flags |=
+ CSUM_IP_CHECKED | CSUM_IP_VALID;
- /*
- * if we get here, none of the above matches, and
- * we have to drop the pkt
- */
- m_freem(m);
- error = EACCES; /* not sure this is the right error msg */
- goto done;
+ error = netisr_queue(NETISR_IP, m);
+ goto done;
}
+ /* Or forward to some other address? */
+ fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
+ if (fwd_tag) {
+ if (!in_localip(ip->ip_src) && !in_localaddr(ip->ip_dst)) {
+ dst = (struct sockaddr_in *)&ro->ro_dst;
+ bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in));
+ m->m_flags |= M_SKIP_FIREWALL;
+ m_tag_delete(m, fwd_tag);
+ goto again;
+ } else {
+ m_tag_delete(m, fwd_tag);
+ /* Continue. */
+ }
+ }
+#endif
+#endif /* PFIL_HOOKS */
+
+#if 0
pass:
+#endif
/* 127/8 must not appear on wire - RFC1122. */
if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
(ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
@@ -1037,13 +829,6 @@ pass:
done:
if (ro == &iproute && ro->ro_rt) {
RTFREE(ro->ro_rt);
- ro->ro_rt = NULL;
- }
- if (dummytag) {
- struct dn_pkt_tag *dt = (struct dn_pkt_tag *)(dummytag+1);
- if (dt->ro.ro_rt)
- RTFREE(dt->ro.ro_rt);
- m_tag_free(dummytag);
}
#ifdef IPSEC
if (sp != NULL) {
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index 66da695b..f557225 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -168,6 +168,8 @@ extern int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *,
int ip_output(struct mbuf *,
struct mbuf *, struct route *, int, struct ip_moptions *,
struct inpcb *);
+struct mbuf *
+ ip_reass(struct mbuf *);
struct in_ifaddr *
ip_rtaddr(struct in_addr);
void ip_savecontrol(struct inpcb *, struct mbuf **, struct ip *,
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index 50e1961..f8796f1 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -78,8 +78,8 @@ struct inpcbhead ripcb;
struct inpcbinfo ripcbinfo;
/* control hooks for ipfw and dummynet */
-ip_fw_ctl_t *ip_fw_ctl_ptr;
-ip_dn_ctl_t *ip_dn_ctl_ptr;
+ip_fw_ctl_t *ip_fw_ctl_ptr = NULL;
+ip_dn_ctl_t *ip_dn_ctl_ptr = NULL;
/*
* hooks for multicast routing. They all default to NULL,
@@ -358,14 +358,14 @@ rip_ctloutput(struct socket *so, struct sockopt *sopt)
case IP_FW_GET:
case IP_FW_TABLE_GETSIZE:
case IP_FW_TABLE_LIST:
- if (IPFW_LOADED)
+ if (ip_fw_ctl_ptr != NULL)
error = ip_fw_ctl_ptr(sopt);
else
error = ENOPROTOOPT;
break;
case IP_DUMMYNET_GET:
- if (DUMMYNET_LOADED)
+ if (ip_dn_ctl_ptr != NULL)
error = ip_dn_ctl_ptr(sopt);
else
error = ENOPROTOOPT;
@@ -414,7 +414,7 @@ rip_ctloutput(struct socket *so, struct sockopt *sopt)
case IP_FW_TABLE_ADD:
case IP_FW_TABLE_DEL:
case IP_FW_TABLE_FLUSH:
- if (IPFW_LOADED)
+ if (ip_fw_ctl_ptr != NULL)
error = ip_fw_ctl_ptr(sopt);
else
error = ENOPROTOOPT;
@@ -423,7 +423,7 @@ rip_ctloutput(struct socket *so, struct sockopt *sopt)
case IP_DUMMYNET_CONFIGURE:
case IP_DUMMYNET_DEL:
case IP_DUMMYNET_FLUSH:
- if (DUMMYNET_LOADED)
+ if (ip_dn_ctl_ptr != NULL)
error = ip_dn_ctl_ptr(sopt);
else
error = ENOPROTOOPT ;
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 902044b..3b70e99 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -429,7 +429,9 @@ tcp_input(m, off0)
struct tcpopt to; /* options in this segment */
struct rmxp_tao tao; /* our TAO cache entry */
int headlocked = 0;
- struct sockaddr_in *next_hop = NULL;
+#ifdef IPFIREWALL_FORWARD
+ struct m_tag *fwd_tag;
+#endif
int rstreason; /* For badport_bandlim accounting purposes */
struct ip6_hdr *ip6 = NULL;
@@ -449,8 +451,6 @@ tcp_input(m, off0)
short ostate = 0;
#endif
- /* Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain. */
- next_hop = m_claim_next(m, PACKET_TAG_IPFORWARD);
#ifdef INET6
isipv6 = (mtod(m, struct ip *)->ip_v == 6) ? 1 : 0;
#endif
@@ -611,17 +611,24 @@ tcp_input(m, off0)
INP_INFO_WLOCK(&tcbinfo);
headlocked = 1;
findpcb:
- /* IPFIREWALL_FORWARD section */
- if (next_hop != NULL && isipv6 == 0) { /* IPv6 support is not yet */
+#ifdef IPFIREWALL_FORWARD
+ /* Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain. */
+ fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
+
+ if (fwd_tag != NULL && isipv6 == 0) { /* IPv6 support is not yet */
+ struct sockaddr_in *next_hop;
+
+ next_hop = (struct sockaddr_in *)(fwd_tag+1);
/*
* Transparently forwarded. Pretend to be the destination.
* already got one like this?
*/
- inp = in_pcblookup_hash(&tcbinfo, ip->ip_src, th->th_sport,
+ inp = in_pcblookup_hash(&tcbinfo,
+ ip->ip_src, th->th_sport,
ip->ip_dst, th->th_dport,
0, m->m_pkthdr.rcvif);
if (!inp) {
- /* It's new. Try find the ambushing socket. */
+ /* It's new. Try to find the ambushing socket. */
inp = in_pcblookup_hash(&tcbinfo,
ip->ip_src, th->th_sport,
next_hop->sin_addr,
@@ -630,7 +637,10 @@ findpcb:
th->th_dport,
1, m->m_pkthdr.rcvif);
}
+ /* Remove the tag from the packet. We don't need it anymore. */
+ m_tag_delete(m, fwd_tag);
} else {
+#endif /* IPFIREWALL_FORWARD */
if (isipv6) {
#ifdef INET6
inp = in6_pcblookup_hash(&tcbinfo,
@@ -643,7 +653,9 @@ findpcb:
ip->ip_src, th->th_sport,
ip->ip_dst, th->th_dport,
1, m->m_pkthdr.rcvif);
+#ifdef IPFIREWALL_FORWARD
}
+#endif /* IPFIREWALL_FORWARD */
#if defined(IPSEC) || defined(FAST_IPSEC)
#ifdef INET6
diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c
index 902044b..3b70e99 100644
--- a/sys/netinet/tcp_reass.c
+++ b/sys/netinet/tcp_reass.c
@@ -429,7 +429,9 @@ tcp_input(m, off0)
struct tcpopt to; /* options in this segment */
struct rmxp_tao tao; /* our TAO cache entry */
int headlocked = 0;
- struct sockaddr_in *next_hop = NULL;
+#ifdef IPFIREWALL_FORWARD
+ struct m_tag *fwd_tag;
+#endif
int rstreason; /* For badport_bandlim accounting purposes */
struct ip6_hdr *ip6 = NULL;
@@ -449,8 +451,6 @@ tcp_input(m, off0)
short ostate = 0;
#endif
- /* Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain. */
- next_hop = m_claim_next(m, PACKET_TAG_IPFORWARD);
#ifdef INET6
isipv6 = (mtod(m, struct ip *)->ip_v == 6) ? 1 : 0;
#endif
@@ -611,17 +611,24 @@ tcp_input(m, off0)
INP_INFO_WLOCK(&tcbinfo);
headlocked = 1;
findpcb:
- /* IPFIREWALL_FORWARD section */
- if (next_hop != NULL && isipv6 == 0) { /* IPv6 support is not yet */
+#ifdef IPFIREWALL_FORWARD
+ /* Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain. */
+ fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
+
+ if (fwd_tag != NULL && isipv6 == 0) { /* IPv6 support is not yet */
+ struct sockaddr_in *next_hop;
+
+ next_hop = (struct sockaddr_in *)(fwd_tag+1);
/*
* Transparently forwarded. Pretend to be the destination.
* already got one like this?
*/
- inp = in_pcblookup_hash(&tcbinfo, ip->ip_src, th->th_sport,
+ inp = in_pcblookup_hash(&tcbinfo,
+ ip->ip_src, th->th_sport,
ip->ip_dst, th->th_dport,
0, m->m_pkthdr.rcvif);
if (!inp) {
- /* It's new. Try find the ambushing socket. */
+ /* It's new. Try to find the ambushing socket. */
inp = in_pcblookup_hash(&tcbinfo,
ip->ip_src, th->th_sport,
next_hop->sin_addr,
@@ -630,7 +637,10 @@ findpcb:
th->th_dport,
1, m->m_pkthdr.rcvif);
}
+ /* Remove the tag from the packet. We don't need it anymore. */
+ m_tag_delete(m, fwd_tag);
} else {
+#endif /* IPFIREWALL_FORWARD */
if (isipv6) {
#ifdef INET6
inp = in6_pcblookup_hash(&tcbinfo,
@@ -643,7 +653,9 @@ findpcb:
ip->ip_src, th->th_sport,
ip->ip_dst, th->th_dport,
1, m->m_pkthdr.rcvif);
+#ifdef IPFIREWALL_FORWARD
}
+#endif /* IPFIREWALL_FORWARD */
#if defined(IPSEC) || defined(FAST_IPSEC)
#ifdef INET6
diff --git a/sys/netinet/tcp_sack.c b/sys/netinet/tcp_sack.c
index 52c1980..1cf44f2 100644
--- a/sys/netinet/tcp_sack.c
+++ b/sys/netinet/tcp_sack.c
@@ -96,7 +96,6 @@
* official policies, either expressed or implied, of the US Naval
* Research Laboratory (NRL).
*/
-#include "opt_ipfw.h" /* for ipfw_fwd */
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_ipsec.h"
OpenPOWER on IntegriCloud