patch-2.1.68 linux/net/ipv4/ip_forward.c
Next file: linux/net/ipv4/ip_fragment.c
Previous file: linux/net/ipv4/ip_alias.c
Back to the patch index
Back to the overall index
- Lines: 176
- Date:
Sun Nov 30 14:00:39 1997
- Orig file:
v2.1.67/linux/net/ipv4/ip_forward.c
- Orig date:
Fri Apr 4 08:52:28 1997
diff -u --recursive --new-file v2.1.67/linux/net/ipv4/ip_forward.c linux/net/ipv4/ip_forward.c
@@ -5,6 +5,8 @@
*
* The IP forwarding functionality.
*
+ * Version: $Id: ip_forward.c,v 1.32 1997/10/24 17:16:06 kuznet Exp $
+ *
* Authors: see ip.c
*
* Fixes:
@@ -76,10 +78,13 @@
int fw_res = 0;
#endif
- if (skb->pkt_type != PACKET_HOST) {
- kfree_skb(skb,FREE_WRITE);
- return 0;
+ if (IPCB(skb)->opt.router_alert) {
+ if (ip_call_ra_chain(skb))
+ return 0;
}
+
+ if (skb->pkt_type != PACKET_HOST)
+ goto drop;
/*
* According to the RFC, we must first decrease the TTL field. If
@@ -90,27 +95,25 @@
iph = skb->nh.iph;
rt = (struct rtable*)skb->dst;
+#ifdef CONFIG_CPU_IS_SLOW
+ if (net_cpu_congestion > 1 && !(iph->tos&IPTOS_RELIABILITY) &&
+ IPTOS_PREC(iph->tos) < IPTOS_PREC_INTERNETCONTROL) {
+ if (((xtime.tv_usec&0xF)<<net_cpu_congestion) > 0x1C)
+ goto drop;
+ }
+#endif
+
+
#ifdef CONFIG_TRANSPARENT_PROXY
if (ip_chk_sock(skb))
- return ip_local_deliver(skb);
+ goto local_pkt;
#endif
- if (ip_decrease_ttl(iph) <= 0) {
- /* Tell the sender its packet died... */
- icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
- kfree_skb(skb, FREE_WRITE);
- return -1;
- }
-
- if (opt->is_strictroute && (rt->rt_flags&RTF_GATEWAY)) {
- /*
- * Strict routing permits no gatewaying
- */
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0);
- kfree_skb(skb, FREE_WRITE);
- return -1;
- }
+ if (ip_decrease_ttl(iph) <= 0)
+ goto too_many_hops;
+ if (opt->is_strictroute && (rt->rt_flags&RTF_GATEWAY))
+ goto sr_failed;
/*
* Having picked a route we can now send the frame out
@@ -139,19 +142,23 @@
*/
if (dev2->flags & IFF_UP) {
- if (skb->len > mtu && (ntohs(iph->frag_off) & IP_DF)) {
- ip_statistics.IpFragFails++;
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
- kfree_skb(skb, FREE_WRITE);
- return -1;
- }
+ if (skb->len > mtu && (ntohs(iph->frag_off) & IP_DF))
+ goto frag_needed;
- if (rt->rt_flags&RTCF_NAT) {
+#ifdef CONFIG_IP_ROUTE_NAT
+ if (rt->rt_flags & RTCF_NAT) {
+ if (skb_headroom(skb) < dev2->hard_header_len || skb_cloned(skb)) {
+ struct sk_buff *skb2;
+ skb2 = skb_realloc_headroom(skb, (dev2->hard_header_len + 15)&~15);
+ kfree_skb(skb, FREE_WRITE);
+ skb = skb2;
+ }
if (ip_do_nat(skb)) {
kfree_skb(skb, FREE_WRITE);
return -1;
}
}
+#endif
#ifdef CONFIG_IP_MASQUERADE
if(!(IPCB(skb)->flags&IPSKB_MASQUERADED)) {
@@ -168,7 +175,7 @@
* and skip the firewall checks
*/
if (iph->protocol == IPPROTO_ICMP) {
- if ((fw_res = ip_fw_masq_icmp(&skb, dev2)) < 0) {
+ if ((fw_res = ip_fw_masq_icmp(&skb)) < 0) {
kfree_skb(skb, FREE_READ);
return -1;
}
@@ -179,7 +186,8 @@
}
if (rt->rt_flags&RTCF_MASQ)
goto skip_call_fw_firewall;
-#endif
+#endif /* CONFIG_IP_MASQUERADE */
+
#ifdef CONFIG_FIREWALL
fw_res=call_fw_firewall(PF_INET, dev2, iph, NULL, &skb);
switch (fw_res) {
@@ -205,7 +213,16 @@
*/
if (!(IPCB(skb)->flags&IPSKB_MASQUERADED) &&
(fw_res==FW_MASQUERADE || rt->rt_flags&RTCF_MASQ)) {
- if (ip_fw_masquerade(&skb, dev2) < 0) {
+ u32 maddr;
+
+#ifdef CONFIG_IP_ROUTE_NAT
+ maddr = (rt->rt_flags&RTCF_MASQ) ? rt->rt_src_map : 0;
+
+ if (maddr == 0)
+#endif
+ maddr = inet_select_addr(dev2, rt->rt_gateway, RT_SCOPE_UNIVERSE);
+
+ if (ip_fw_masquerade(&skb, maddr) < 0) {
kfree_skb(skb, FREE_READ);
return -1;
}
@@ -238,10 +255,36 @@
ip_statistics.IpForwDatagrams++;
- if (opt->optlen)
- ip_forward_options(skb);
-
+ if (opt->optlen == 0) {
+ ip_send(skb);
+ return 0;
+ }
+ ip_forward_options(skb);
ip_send(skb);
}
return 0;
+
+#ifdef CONFIG_TRANSPARENT_PROXY
+local_pkt:
+#endif
+ return ip_local_deliver(skb);
+
+frag_needed:
+ ip_statistics.IpFragFails++;
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
+ goto drop;
+
+sr_failed:
+ /*
+ * Strict routing permits no gatewaying
+ */
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0);
+ goto drop;
+
+too_many_hops:
+ /* Tell the sender its packet died... */
+ icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
+drop:
+ kfree_skb(skb,FREE_WRITE);
+ return -1;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov