patch-pre2.0.7 linux/net/ipv4/ip_input.c
Next file: linux/net/ipv4/ip_output.c
Previous file: linux/net/ipv4/ip_fw.c
Back to the patch index
Back to the overall index
- Lines: 234
- Date:
Mon May 20 09:17:34 1996
- Orig file:
pre2.0.6/linux/net/ipv4/ip_input.c
- Orig date:
Fri Apr 12 15:52:12 1996
diff -u --recursive --new-file pre2.0.6/linux/net/ipv4/ip_input.c linux/net/ipv4/ip_input.c
@@ -96,6 +96,7 @@
* A.N.Kuznetsov : IP_OPTIONS support throughout the kernel
* Alan Cox : Multicast routing hooks
* Jos Vos : Do accounting *before* call_in_firewall
+ * Willy Konynenberg : Transparent proxying support
*
*
*
@@ -189,6 +190,27 @@
}
}
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+/*
+ * Check the packet against our socket administration to see
+ * if it is related to a connection on our system.
+ * Needed for transparent proxying.
+ */
+
+int ip_chksock(struct sk_buff *skb)
+{
+ switch (skb->h.iph->protocol) {
+ case IPPROTO_ICMP:
+ return icmp_chkaddr(skb);
+ case IPPROTO_TCP:
+ return tcp_chkaddr(skb);
+ case IPPROTO_UDP:
+ return udp_chkaddr(skb);
+ default:
+ return 0;
+ }
+}
+#endif
/*
@@ -211,7 +233,8 @@
__u32 daddr;
#ifdef CONFIG_FIREWALL
- int err;
+ int fwres;
+ __u16 rport;
#endif
#ifdef CONFIG_IP_MROUTE
int mroute_pkt=0;
@@ -229,6 +252,15 @@
ip_statistics.IpInReceives++;
/*
+ * Account for the packet (even if the packet is
+ * not accepted by the firewall!).
+ */
+
+#ifdef CONFIG_IP_ACCT
+ ip_fw_chk(iph,dev,NULL,ip_acct_chain,IP_FW_F_ACCEPT,IP_FW_MODE_ACCT_IN);
+#endif
+
+ /*
* Tag the ip header of this packet so we can find it
*/
@@ -289,31 +321,82 @@
#endif
}
+#if defined(CONFIG_IP_TRANSPARENT_PROXY) && !defined(CONFIG_IP_ALWAYS_DEFRAG)
+#define CONFIG_IP_ALWAYS_DEFRAG 1
+#endif
+#ifdef CONFIG_IP_ALWAYS_DEFRAG
/*
- * Account for the packet (even if the packet is
- * not accepted by the firewall!).
+ * Defragment all incoming traffic before even looking at it.
+ * If you have forwarding enabled, this makes the system a
+ * defragmenting router. Not a common thing.
+ * You probably DON'T want to enable this unless you have to.
+ * You NEED to use this if you want to use transparent proxying,
+ * otherwise, we can't vouch for your sanity.
*/
-#ifdef CONFIG_IP_ACCT
- ip_fw_chk(iph,dev,ip_acct_chain,IP_FW_F_ACCEPT,1);
-#endif
+ /*
+ * See if the frame is fragmented.
+ */
+
+ if(iph->frag_off)
+ {
+ if (iph->frag_off & htons(IP_MF))
+ is_frag|=IPFWD_FRAGMENT;
+ /*
+ * Last fragment ?
+ */
+
+ if (iph->frag_off & htons(IP_OFFSET))
+ is_frag|=IPFWD_LASTFRAG;
+
+ /*
+ * Reassemble IP fragments.
+ */
+ if(is_frag)
+ {
+ /* Defragment. Obtain the complete packet if there is one */
+ skb=ip_defrag(iph,skb,dev);
+ if(skb==NULL)
+ return 0;
+ skb->dev = dev;
+ iph=skb->h.iph;
+ is_frag = 0;
+ /*
+ * When the reassembled packet gets forwarded, the ip
+ * header checksum should be correct.
+ * For better performance, this should actually only
+ * be done in that particular case, i.e. set a flag
+ * here and calculate the checksum in ip_forward.
+ */
+ ip_send_check(iph);
+ }
+ }
+
+#endif
/*
* See if the firewall wants to dispose of the packet.
*/
#ifdef CONFIG_FIREWALL
- if ((err=call_in_firewall(PF_INET, skb->dev, iph))<FW_ACCEPT)
+ if ((fwres=call_in_firewall(PF_INET, skb->dev, iph, &rport))<FW_ACCEPT)
{
- if(err==FW_REJECT)
+ if(fwres==FW_REJECT)
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);
kfree_skb(skb, FREE_WRITE);
return 0;
}
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ if (fwres==FW_REDIRECT)
+ skb->redirport = rport;
+ else
+#endif
+ skb->redirport = 0;
#endif
+#ifndef CONFIG_IP_ALWAYS_DEFRAG
/*
* Remember if the frame is fragmented.
*/
@@ -330,6 +413,7 @@
is_frag|=IPFWD_LASTFRAG;
}
+#endif
/*
* Do any IP forwarding required. chk_addr() is expensive -- avoid it someday.
*
@@ -342,7 +426,14 @@
* function entry.
*/
daddr = iph->daddr;
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ /*
+ * ip_chksock adds still more overhead for forwarded traffic...
+ */
+ if ( iph->daddr == skb->dev->pa_addr || skb->redirport || (brd = ip_chk_addr(iph->daddr)) != 0 || ip_chksock(skb))
+#else
if ( iph->daddr == skb->dev->pa_addr || (brd = ip_chk_addr(iph->daddr)) != 0)
+#endif
{
if (opt && opt->srr)
{
@@ -422,19 +513,7 @@
}
#endif
-#ifdef CONFIG_IP_MASQUERADE
- /*
- * Do we need to de-masquerade this fragment?
- */
- if (ip_fw_demasquerade(&skb,dev))
- {
- struct iphdr *iph=skb->h.iph;
- if (ip_forward(skb, dev, is_frag|IPFWD_MASQUERADED, iph->daddr))
- kfree_skb(skb, FREE_WRITE);
- return(0);
- }
-#endif
-
+#ifndef CONFIG_IP_ALWAYS_DEFRAG
/*
* Reassemble IP fragments.
*/
@@ -447,16 +526,29 @@
return 0;
skb->dev = dev;
iph=skb->h.iph;
-#ifdef CONFIG_IP_MASQUERADE
- if (ip_fw_demasquerade(&skb,dev))
- {
- struct iphdr *iph=skb->h.iph;
- if (ip_forward(skb, dev, IPFWD_MASQUERADED, iph->daddr))
- kfree_skb(skb, FREE_WRITE);
- return 0;
- }
+ }
+
#endif
+#ifdef CONFIG_IP_MASQUERADE
+ {
+ /*
+ * Do we need to de-masquerade this packet?
+ */
+ int ret = ip_fw_demasquerade(&skb,dev);
+ if (ret < 0) {
+ kfree_skb(skb, FREE_WRITE);
+ return 0;
+ }
+
+ if (ret)
+ {
+ struct iphdr *iph=skb->h.iph;
+ if (ip_forward(skb, dev, IPFWD_MASQUERADED, iph->daddr))
+ kfree_skb(skb, FREE_WRITE);
+ return 0;
}
+ }
+#endif
/*
* Point into the IP datagram, just past the header.
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this