summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjulian <julian@FreeBSD.org>1998-07-06 03:20:19 +0000
committerjulian <julian@FreeBSD.org>1998-07-06 03:20:19 +0000
commit22a5d80812f1c709917ff24ff791b1f952f8d6f7 (patch)
treebcc03ee3bb48fe95754fcda4fea765a7925f1343 /sys
parent04d286f6479d77492b97067c0d09e9c982b707c0 (diff)
downloadFreeBSD-src-22a5d80812f1c709917ff24ff791b1f952f8d6f7.zip
FreeBSD-src-22a5d80812f1c709917ff24ff791b1f952f8d6f7.tar.gz
Support for IPFW based transparent forwarding.
Any packet that can be matched by a ipfw rule can be redirected transparently to another port or machine. Redirection to another port mostly makes sense with tcp, where a session can be set up between a proxy and an unsuspecting client. Redirection to another machine requires that the other machine also be expecting to receive the forwarded packets, as their headers will not have been modified. /sbin/ipfw must be recompiled!!! Reviewed by: Peter Wemm <peter@freebsd.org> Submitted by: Chrisy Luke <chrisy@flix.net>
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/in.h4
-rw-r--r--sys/netinet/ip_fw.c45
-rw-r--r--sys/netinet/ip_fw.h5
-rw-r--r--sys/netinet/ip_input.c60
-rw-r--r--sys/netinet/ip_output.c139
-rw-r--r--sys/netinet/ip_var.h5
-rw-r--r--sys/netinet/tcp_input.c30
-rw-r--r--sys/netinet/tcp_reass.c30
8 files changed, 288 insertions, 30 deletions
diff --git a/sys/netinet/in.h b/sys/netinet/in.h
index bb6562c..1450185 100644
--- a/sys/netinet/in.h
+++ b/sys/netinet/in.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)in.h 8.3 (Berkeley) 1/3/94
- * $Id: in.h,v 1.34 1998/06/06 19:39:08 julian Exp $
+ * $Id: in.h,v 1.35 1998/06/06 20:45:25 julian Exp $
*/
#ifndef _NETINET_IN_H_
@@ -431,7 +431,7 @@ char *inet_ntoa __P((struct in_addr)); /* in libkern */
/* Firewall hooks */
struct ip;
-typedef int ip_fw_chk_t __P((struct ip**, int, struct ifnet*, u_int16_t*, struct mbuf**));
+typedef int ip_fw_chk_t __P((struct ip**, int, struct ifnet*, u_int16_t*, struct mbuf**, struct sockaddr_in**));
typedef int ip_fw_ctl_t __P((int, struct mbuf**));
extern ip_fw_chk_t *ip_fw_chk_ptr;
extern ip_fw_ctl_t *ip_fw_ctl_ptr;
diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c
index b79593c..ec1a608 100644
--- a/sys/netinet/ip_fw.c
+++ b/sys/netinet/ip_fw.c
@@ -12,7 +12,7 @@
*
* This software is provided ``AS IS'' without any warranties of any kind.
*
- * $Id: ip_fw.c,v 1.90 1998/06/21 14:53:30 bde Exp $
+ * $Id: ip_fw.c,v 1.91 1998/07/02 05:49:08 julian Exp $
*/
/*
@@ -103,7 +103,8 @@ static ip_fw_ctl_t *old_ctl_ptr;
#endif
static int ip_fw_chk __P((struct ip **pip, int hlen,
- struct ifnet *oif, u_int16_t *cookie, struct mbuf **m));
+ struct ifnet *oif, u_int16_t *cookie, struct mbuf **m,
+ struct sockaddr_in **next_hop));
static int ip_fw_ctl __P((int stage, struct mbuf **mm));
static char err_prefix[] = "ip_fw_ctl:";
@@ -320,6 +321,14 @@ ipfw_report(struct ip_fw *f, struct ip *ip,
case IP_FW_F_SKIPTO:
printf("SkipTo %d", f->fw_skipto_rule);
break;
+#ifdef IPFIREWALL_FORWARD
+ case IP_FW_F_FWD:
+ printf("Forward to ");
+ print_ip(f->fw_fwd_ip.sin_addr);
+ if (f->fw_fwd_ip.sin_port)
+ printf(":%d", f->fw_fwd_ip.sin_port);
+ break;
+#endif
default:
printf("UNKNOWN");
break;
@@ -393,7 +402,8 @@ ipfw_report(struct ip_fw *f, struct ip *ip,
static int
ip_fw_chk(struct ip **pip, int hlen,
- struct ifnet *oif, u_int16_t *cookie, struct mbuf **m)
+ struct ifnet *oif, u_int16_t *cookie, struct mbuf **m,
+ struct sockaddr_in **next_hop)
{
struct ip_fw_chain *chain;
struct ip_fw *rule = NULL;
@@ -606,11 +616,28 @@ got_match:
#endif
chain = LIST_NEXT(chain, chain);
continue;
+#ifdef IPFIREWALL_FORWARD
+ case IP_FW_F_FWD:
+ /* Change the next-hop address for this packet.
+ * Initially we'll only worry about directly
+ * reachable next-hop's, but ultimately
+ * we will work out for next-hops that aren't
+ * direct the route we would take for it. We
+ * [cs]ould leave this latter problem to
+ * ip_output.c. We hope to high [name the abode of
+ * your favourite deity] that ip_output doesn't modify
+ * the new value of next_hop (which is dst there)
+ */
+ if (next_hop != NULL) /* Make sure, first... */
+ *next_hop = &(f->fw_fwd_ip);
+ return(0); /* Allow the packet */
+#endif
}
/* Deny/reject this packet using this rule */
rule = f;
break;
+
}
#ifdef DIAGNOSTIC
@@ -950,6 +977,9 @@ check_ipfw_struct(struct ip_fw *frwl)
case IP_FW_F_ACCEPT:
case IP_FW_F_COUNT:
case IP_FW_F_SKIPTO:
+#ifdef IPFIREWALL_FORWARD
+ case IP_FW_F_FWD:
+#endif
break;
default:
dprintf(("%s invalid command\n", err_prefix));
@@ -982,7 +1012,7 @@ ip_fw_ctl(int stage, struct mbuf **mm)
if (m == NULL)
return (ENOBUFS);
MCLGET(m, M_WAIT);
- if(!(m->m_flags & M_EXT)) {
+ if (!(m->m_flags & M_EXT)) {
abort: m_freem(*mm);
*mm = NULL;
return (ENOBUFS);
@@ -990,7 +1020,7 @@ abort: m_freem(*mm);
m->m_len = 0;
for (; fcp; fcp = LIST_NEXT(fcp, chain)) {
/* Will we need a new cluster? */
- if((m->m_len + sizeof *(fcp->rule)) > MCLBYTES) {
+ if ((m->m_len + sizeof *(fcp->rule)) > MCLBYTES) {
m = m->m_next = m_get(M_WAIT, MT_SOOPTS);
if (m == NULL) {
goto abort;
@@ -1094,6 +1124,11 @@ ip_fw_init(void)
#else
"divert disabled, ");
#endif
+#ifdef IPFIREWALL_FORWARD
+ printf("rule-based forwarding enabled, ");
+#else
+ printf("rule-based forwarding disabled, ");
+#endif
#ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
printf("default to accept, ");
#endif
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index bfc8e72..572d1b7 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -11,7 +11,7 @@
*
* This software is provided ``AS IS'' without any warranties of any kind.
*
- * $Id: ip_fw.h,v 1.31 1998/01/08 03:03:54 alex Exp $
+ * $Id: ip_fw.h,v 1.32 1998/02/03 22:15:03 bde Exp $
*/
#ifndef _IP_FW_H
@@ -71,6 +71,7 @@ struct ip_fw {
u_short fu_divert_port; /* Divert/tee port (options IPDIVERT) */
u_short fu_skipto_rule; /* SKIPTO command rule number */
u_short fu_reject_code; /* REJECT response code */
+ struct sockaddr_in fu_fwd_ip;
} fw_un;
u_char fw_prot; /* IP protocol */
u_char fw_nports; /* N'of src ports and # of dst ports */
@@ -93,6 +94,7 @@ struct ip_fw {
#define fw_divert_port fw_un.fu_divert_port
#define fw_skipto_rule fw_un.fu_skipto_rule
#define fw_reject_code fw_un.fu_reject_code
+#define fw_fwd_ip fw_un.fu_fwd_ip
struct ip_fw_chain {
LIST_ENTRY(ip_fw_chain) chain;
@@ -115,6 +117,7 @@ struct ip_fw_chain {
#define IP_FW_F_DIVERT 0x0040 /* This is a divert rule */
#define IP_FW_F_TEE 0x0050 /* This is a tee rule */
#define IP_FW_F_SKIPTO 0x0060 /* This is a skipto rule */
+#define IP_FW_F_FWD 0x0070 /* This is a "change forwarding address" rule */
#define IP_FW_F_PRN 0x0080 /* Print if this rule matches */
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 91b1c8e..32adbfd 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ip_input.c 8.2 (Berkeley) 1/4/94
- * $Id: ip_input.c,v 1.90 1998/06/12 03:48:16 julian Exp $
+ * $Id: ip_input.c,v 1.91 1998/07/02 05:49:12 julian Exp $
* $ANA: ip_input.c,v 1.5 1996/09/18 14:34:59 wollman Exp $
*/
@@ -181,6 +181,8 @@ static struct ip_srcrt {
static u_short frag_divert_port;
#endif
+struct sockaddr_in *ip_fw_fwd_addr;
+
static void save_rte __P((u_char *, struct in_addr));
static void ip_deq __P((struct ipasfrag *));
static int ip_dooptions __P((struct mbuf *));
@@ -354,30 +356,43 @@ tooshort:
#endif
#ifdef COMPAT_IPFW
if (ip_fw_chk_ptr) {
-#ifdef IPDIVERT
- u_short port;
+ u_int16_t port;
- port = (*ip_fw_chk_ptr)(&ip, hlen, NULL, &ip_divert_cookie, &m);
+#ifdef IPFIREWALL_FORWARD
+ /*
+ * If we've been forwarded from the output side, then
+ * skip the firewall a second time
+ */
+ if (ip_fw_fwd_addr)
+ goto ours;
+#endif /* IPFIREWALL_FORWARD */
+#ifdef IPDIVERT
+ port = (*ip_fw_chk_ptr)(&ip, hlen, NULL, &ip_divert_cookie,
+ &m, &ip_fw_fwd_addr);
if (port) {
/* Divert packet */
frag_divert_port = port;
goto ours;
}
-#else
- u_int16_t dummy = 0;
- /* If ipfw says divert, we have to just drop packet */
- if ((*ip_fw_chk_ptr)(&ip, hlen, NULL, &dummy, &m)) {
+#else /* !DIVERT */
+ /*
+ * If ipfw says divert, we have to just drop packet */
+ * Use port as a dummy argument.
+ */
+ port = 0;
+ if ((*ip_fw_chk_ptr)(&ip, hlen, NULL, &port,
+ &m, &ip_fw_fwd_addr)) {
m_freem(m);
m = NULL;
}
-#endif
+#endif /* !DIVERT */
if (!m)
return;
}
if (ip_nat_ptr && !(*ip_nat_ptr)(&ip, &m, m->m_pkthdr.rcvif, IP_NAT_IN))
return;
-#endif
+#endif /* !COMPAT_IPFW */
/*
* Process options and, if not destined for us,
@@ -401,7 +416,8 @@ tooshort:
/*
* Check our list of addresses, to see if the packet is for us.
*/
- for (ia = in_ifaddrhead.tqh_first; ia; ia = ia->ia_link.tqe_next) {
+ for (ia = TAILQ_FIRST(in_ifaddrhead); ia;
+ ia = TAILQ_NEXT(ia, ia_link)) {
#define satosin(sa) ((struct sockaddr_in *)(sa))
if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr)
@@ -410,6 +426,16 @@ tooshort:
if (IA_SIN(ia)->sin_addr.s_addr == INADDR_ANY)
goto ours;
#endif
+#ifdef IPFIREWALL_FORWARD
+ /*
+ * If the addr to forward to is one of ours, we pretend to
+ * be the destination for this packet.
+ */
+ if (ip_fw_fwd_addr != NULL &&
+ IA_SIN(ia)->sin_addr.s_addr ==
+ ip_fw_fwd_addr->sin_addr.s_addr)
+ goto ours;
+#endif
if (ia->ia_ifp && ia->ia_ifp->if_flags & IFF_BROADCAST) {
if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr ==
ip->ip_dst.s_addr)
@@ -548,8 +574,12 @@ found:
if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
ipstat.ips_fragments++;
ip = ip_reass((struct ipasfrag *)ip, fp, &ipq[sum]);
- if (ip == 0)
+ if (ip == 0) {
+#ifdef IPFIREWALL_FORWARD
+ ip_fw_fwd_addr = NULL;
+#endif
return;
+ }
/* Get the length of the reassembled packets header */
hlen = IP_VHL_HL(ip->ip_vhl) << 2;
ipstat.ips_reassembled++;
@@ -599,8 +629,14 @@ found:
*/
ipstat.ips_delivered++;
(*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen);
+#ifdef IPFIREWALL_FORWARD
+ ip_fw_fwd_addr = NULL; /* tcp needed it */
+#endif
return;
bad:
+#ifdef IPFIREWALL_FORWARD
+ ip_fw_fwd_addr = NULL;
+#endif
m_freem(m);
}
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index c142887..d85f36b 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ip_output.c 8.3 (Berkeley) 1/21/94
- * $Id: ip_output.c,v 1.74 1998/06/15 00:35:47 julian Exp $
+ * $Id: ip_output.c,v 1.75 1998/06/21 14:53:32 bde Exp $
*/
#define _IP_VHL
@@ -71,6 +71,13 @@ static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options");
#undef COMPAT_IPFW
#endif
+#ifdef IPFIREWALL_FORWARD_DEBUG
+#define print_ip(a) printf("%ld.%ld.%ld.%ld",(ntohl(a.s_addr)>>24)&0xFF,\
+ (ntohl(a.s_addr)>>16)&0xFF,\
+ (ntohl(a.s_addr)>>8)&0xFF,\
+ (ntohl(a.s_addr))&0xFF);
+#endif
+
u_short ip_id;
static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *));
@@ -114,6 +121,9 @@ ip_output(m0, opt, ro, flags, imo)
struct sockaddr_in *dst;
struct in_ifaddr *ia;
int isbroadcast;
+#ifdef IPFIREWALL_FORWARD
+ int fwd_rewrite_src = 0;
+#endif
#ifdef DIAGNOSTIC
if ((m->m_flags & M_PKTHDR) == 0)
@@ -304,9 +314,18 @@ ip_output(m0, opt, ro, flags, imo)
* If source address not specified yet, use address
* of outgoing interface.
*/
- if (ip->ip_src.s_addr == INADDR_ANY)
+ if (ip->ip_src.s_addr == INADDR_ANY) {
ip->ip_src = IA_SIN(ia)->sin_addr;
-#endif
+#ifdef IPFIREWALL_FORWARD
+ /* Keep note that we did this - if the firewall changes
+ * the next-hop, our interface may change, changing the
+ * default source IP. It's a shame so much effort happens
+ * twice. Oh well.
+ */
+ fwd_rewrite_src++;
+#endif /* IPFIREWALL_FORWARD */
+ }
+#endif /* notdef */
/*
* Verify that we have any chance at all of being able to queue
* the packet or packet fragments
@@ -369,28 +388,134 @@ sendit:
* Check with the firewall...
*/
if (ip_fw_chk_ptr) {
+#ifdef IPFIREWALL_FORWARD
+ struct sockaddr_in *old;
+ old = dst;
+#endif
#ifdef IPDIVERT
ip_divert_port = (*ip_fw_chk_ptr)(&ip,
- hlen, ifp, &ip_divert_cookie, &m);
+ hlen, ifp, &ip_divert_cookie, &m, &dst);
if (ip_divert_port) { /* Divert packet */
(*inetsw[ip_protox[IPPROTO_DIVERT]].pr_input)(m, 0);
goto done;
}
-#else
+#else /* !IPDIVERT */
u_int16_t dummy = 0;
/* If ipfw says divert, we have to just drop packet */
- if ((*ip_fw_chk_ptr)(&ip, hlen, ifp, &dummy, &m)) {
+ if ((*ip_fw_chk_ptr)(&ip, hlen, ifp, &dummy, &m, &dst)) {
m_freem(m);
goto done;
}
-#endif
+#endif /* !IPDIVERT */
if (!m) {
error = EACCES;
goto done;
}
+#ifdef IPFIREWALL_FORWARD
+ /* Here we check dst to make sure it's 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 (old != dst) {
+ struct in_ifaddr *ia;
+
+ /* It's changed... */
+ /* There must be a better way to do this next line... */
+ static struct route sro_fwd, *ro_fwd = &sro_fwd;
+#ifdef IPFIREWALL_FORWARD_DEBUG
+ printf("IPFIREWALL_FORWARD: New dst ip: ");
+ print_ip(dst->sin_addr);
+ printf("\n");
+#endif
+ /*
+ * 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 a ISR.
+ */
+ for (ia = TAILQ_FIRST(in_ifaddrhead); ia;
+ ia = TAILQ_NEXT(ia, ia_link)) {
+ /*
+ * 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" */
+ ip_fw_fwd_addr = dst;
+ if (m->m_pkthdr.rcvif == NULL)
+ m->m_pkthdr.rcvif = ifunit("lo0");
+ ip->ip_len = htons((u_short)ip->ip_len);
+ ip->ip_off = htons((u_short)ip->ip_off);
+ ip->ip_sum = 0;
+ if (ip->ip_vhl == IP_VHL_BORING) {
+ ip->ip_sum = in_cksum_hdr(ip);
+ } else {
+ ip->ip_sum = in_cksum(m, hlen);
+ }
+ ip_input(m);
+ goto done;
+ }
+ /* Some of the logic for this was
+ * nicked from above.
+ *
+ * This rewrites the cached route in a local PCB.
+ * Is this what we want to do?
+ */
+ bcopy(dst, &ro_fwd->ro_dst, sizeof(*dst));
+
+ ro_fwd->ro_rt = 0;
+ rtalloc_ign(ro_fwd, RTF_PRCLONING);
+
+ if (ro_fwd->ro_rt == 0) {
+ 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_use++;
+ 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);
+ RTFREE(ro->ro_rt);
+ ro->ro_rt = ro_fwd->ro_rt;
+ dst = (struct sockaddr_in *)&ro_fwd->ro_dst;
+
+ /*
+ * 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 (fwd_rewrite_src)
+ ip->ip_src = IA_SIN(ia)->sin_addr;
+ }
+#endif /* IPFIREWALL_FORWARD */
}
#endif /* COMPAT_IPFW */
+
/*
* If small enough for interface, can just send directly.
*/
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index 9559a3e..827bd69 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ip_var.h 8.2 (Berkeley) 1/9/95
- * $Id: ip_var.h,v 1.40 1998/06/06 19:39:10 julian Exp $
+ * $Id: ip_var.h,v 1.41 1998/06/08 09:47:42 bde Exp $
*/
#ifndef _NETINET_IP_VAR_H_
@@ -211,6 +211,9 @@ extern u_short ip_divert_port;
extern u_short ip_divert_cookie;
#endif /* IPDIVERT */
+struct sockaddr_in;
+extern struct sockaddr_in *ip_fw_fwd_addr;
+
#endif /* KERNEL */
#endif /* _NETINET_IP_VAR_H_ */
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 14b69b4..75aef2a 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -31,9 +31,10 @@
* SUCH DAMAGE.
*
* @(#)tcp_input.c 8.12 (Berkeley) 5/24/95
- * $Id: tcp_input.c,v 1.77 1998/05/18 17:11:24 guido Exp $
+ * $Id: tcp_input.c,v 1.78 1998/05/31 18:42:49 peter Exp $
*/
+#include "opt_ipfw.h" /* for ipfw_fwd */
#include "opt_tcpdebug.h"
#include <sys/param.h>
@@ -339,6 +340,33 @@ tcp_input(m, iphlen)
* Locate pcb for segment.
*/
findpcb:
+#ifdef IPFIREWALL_FORWARD
+ if (ip_fw_fwd_addr != NULL) {
+ /*
+ * Diverted. Pretend to be the destination.
+ * already got one like this?
+ */
+ inp = in_pcblookup_hash(&tcbinfo, ti->ti_src, ti->ti_sport,
+ ti->ti_dst, ti->ti_dport, 0);
+ if (!inp) {
+ /*
+ * No, then it's new. Try find the ambushing socket
+ */
+ if (!ip_fw_fwd_addr->sin_port) {
+ inp = in_pcblookup_hash(&tcbinfo, ti->ti_src,
+ ti->ti_sport, ip_fw_fwd_addr->sin_addr,
+ ti->ti_dport, 1);
+ } else {
+ inp = in_pcblookup_hash(&tcbinfo,
+ ti->ti_src, ti->ti_sport,
+ ip_fw_fwd_addr->sin_addr,
+ ntohs(ip_fw_fwd_addr->sin_port), 1);
+ }
+ }
+ ip_fw_fwd_addr = NULL;
+ } else
+#endif /* IPFIREWALL_FORWARD */
+
inp = in_pcblookup_hash(&tcbinfo, ti->ti_src, ti->ti_sport,
ti->ti_dst, ti->ti_dport, 1);
diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c
index 14b69b4..75aef2a 100644
--- a/sys/netinet/tcp_reass.c
+++ b/sys/netinet/tcp_reass.c
@@ -31,9 +31,10 @@
* SUCH DAMAGE.
*
* @(#)tcp_input.c 8.12 (Berkeley) 5/24/95
- * $Id: tcp_input.c,v 1.77 1998/05/18 17:11:24 guido Exp $
+ * $Id: tcp_input.c,v 1.78 1998/05/31 18:42:49 peter Exp $
*/
+#include "opt_ipfw.h" /* for ipfw_fwd */
#include "opt_tcpdebug.h"
#include <sys/param.h>
@@ -339,6 +340,33 @@ tcp_input(m, iphlen)
* Locate pcb for segment.
*/
findpcb:
+#ifdef IPFIREWALL_FORWARD
+ if (ip_fw_fwd_addr != NULL) {
+ /*
+ * Diverted. Pretend to be the destination.
+ * already got one like this?
+ */
+ inp = in_pcblookup_hash(&tcbinfo, ti->ti_src, ti->ti_sport,
+ ti->ti_dst, ti->ti_dport, 0);
+ if (!inp) {
+ /*
+ * No, then it's new. Try find the ambushing socket
+ */
+ if (!ip_fw_fwd_addr->sin_port) {
+ inp = in_pcblookup_hash(&tcbinfo, ti->ti_src,
+ ti->ti_sport, ip_fw_fwd_addr->sin_addr,
+ ti->ti_dport, 1);
+ } else {
+ inp = in_pcblookup_hash(&tcbinfo,
+ ti->ti_src, ti->ti_sport,
+ ip_fw_fwd_addr->sin_addr,
+ ntohs(ip_fw_fwd_addr->sin_port), 1);
+ }
+ }
+ ip_fw_fwd_addr = NULL;
+ } else
+#endif /* IPFIREWALL_FORWARD */
+
inp = in_pcblookup_hash(&tcbinfo, ti->ti_src, ti->ti_sport,
ti->ti_dst, ti->ti_dport, 1);
OpenPOWER on IntegriCloud