diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8 index fe29f08947c6..f86f69170b94 100644 --- a/sbin/ipfw/ipfw.8 +++ b/sbin/ipfw/ipfw.8 @@ -195,7 +195,31 @@ Send a copy of packets matching this rule to the .Xr divert 4 socket bound to port .Ar port . -The search continues with the next rule. +The search continues with the next rule. This feature is not yet implemeted. +.It Ar fwd ipaddr Op ,port +Change the next-hop on matching packets to +.Ar ipaddr , +which can be an IP address in dotted quad or a host name. +If +.Ar ipaddr +is not a directly-reachable address, the route +as found in the local routing table for that IP is used +instead. +If +.Ar ipaddr +is a local address, then on a packet entering the system from a remote +host it will be diverted to +.Ar port +on the local machine, keeping the local address of the socket set +to the original IP address the packet was destined for. This is intended +for use with transparent proxy servers. If the IP is not +a local address then the port number (if specified) is ignored and +the rule only applies to packets leaving the system. This will +also map addresses to local ports when packets are generated locally. +The search terminates if this rule matches. If the port number is not +given then the port number in the packet is used, so that a packet for +an external machine port Y would be forwarded to local port Y. The kernel +must have been compiled with optiions IPFIREWALL_FORWARD. .It Ar skipto number Skip all subsequent rules numbered less than .Ar number . diff --git a/sbin/ipfw/ipfw.c b/sbin/ipfw/ipfw.c index 6e9a686d79d3..4f16279e7848 100644 --- a/sbin/ipfw/ipfw.c +++ b/sbin/ipfw/ipfw.c @@ -16,7 +16,7 @@ * * NEW command line interface for IP firewall facility * - * $Id: ipfw.c,v 1.56 1998/04/22 06:20:20 phk Exp $ + * $Id: ipfw.c,v 1.57 1998/05/15 12:38:07 danny Exp $ * */ @@ -224,6 +224,11 @@ show_ipfw(struct ip_fw *chain, int pcwidth, int bcwidth) print_reject_code(chain->fw_reject_code); } break; + case IP_FW_F_FWD: + printf("fwd %s", inet_ntoa(chain->fw_fwd_ip.sin_addr)); + if(chain->fw_fwd_ip.sin_port) + printf(",%d", chain->fw_fwd_ip.sin_port); + break; default: errx(EX_OSERR, "impossible"); } @@ -497,7 +502,7 @@ show_usage(const char *fmt, ...) " rule: action proto src dst extras...\n" " action:\n" " {allow|permit|accept|pass|deny|drop|reject|unreach code|\n" -" reset|count|skipto num|divert port|tee port} [log]\n" +" reset|count|skipto num|divert port|tee port|fwd ip} [log]\n" " proto: {ip|tcp|udp|icmp|}\n" " src: from [not] {any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n" " dst: to [not] {any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n" @@ -896,6 +901,30 @@ add(ac,av) else show_usage("illegal divert port"); } + } else if (!strncmp(*av,"fwd",strlen(*av)) || + !strncmp(*av,"forward",strlen(*av))) { + struct in_addr dummyip; + char *pp; + rule.fw_flg |= IP_FW_F_FWD; av++; ac--; + if (!ac) + show_usage("missing forwarding IP address"); + rule.fw_fwd_ip.sin_len = sizeof(struct sockaddr_in); + rule.fw_fwd_ip.sin_family = AF_INET; + rule.fw_fwd_ip.sin_port = 0; + pp = strchr(*av, ':'); + if(pp == NULL) + pp = strchr(*av, ','); + if(pp != NULL) + { + *(pp++) = '\0'; + rule.fw_fwd_ip.sin_port = lookup_port(pp, 1, 1); + if(rule.fw_fwd_ip.sin_port == (unsigned int)-1) + show_usage("illegal forwarding port"); + } + fill_ip(&(rule.fw_fwd_ip.sin_addr), &dummyip, &ac, &av); + if (rule.fw_fwd_ip.sin_addr.s_addr == 0) + show_usage("illegal forwarding IP address"); + } else if (!strncmp(*av,"skipto",strlen(*av))) { rule.fw_flg |= IP_FW_F_SKIPTO; av++; ac--; if (!ac) diff --git a/sys/netinet/in.h b/sys/netinet/in.h index bb6562cbb06c..145018558def 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 b79593cd2e5b..ec1a608f23ae 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 @@ ip_fw_chk(struct ip **pip, int hlen, #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 bfc8e7257afa..572d1b71fd9c 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 91b1c8e8fd74..32adbfdde215 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 @@ ip_input(struct mbuf *m) #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 @@ ip_input(struct mbuf *m) /* * 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) @@ -409,6 +425,16 @@ ip_input(struct mbuf *m) #ifdef BOOTP_COMPAT 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 == @@ -548,8 +574,12 @@ ip_input(struct mbuf *m) 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 @@ ip_input(struct mbuf *m) */ 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 c142887cd9bf..d85f36ba5c7f 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 @@ ip_output(m0, opt, ro, flags, imo) * 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 9559a3eb3d1c..827bd6910934 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 14b69b4148e2..75aef2aa8757 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 @@ -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 14b69b4148e2..75aef2aa8757 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 @@ -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);