patch-2.3.15 linux/net/ipv4/ip_input.c
Next file: linux/net/ipv4/ip_masq.c
Previous file: linux/net/ipv4/ip_gre.c
Back to the patch index
Back to the overall index
- Lines: 357
- Date:
Mon Aug 23 10:01:02 1999
- Orig file:
v2.3.14/linux/net/ipv4/ip_input.c
- Orig date:
Wed Aug 18 11:38:48 1999
diff -u --recursive --new-file v2.3.14/linux/net/ipv4/ip_input.c linux/net/ipv4/ip_input.c
@@ -5,7 +5,7 @@
*
* The Internet Protocol (IP) module.
*
- * Version: $Id: ip_input.c,v 1.40 1999/06/09 10:10:55 davem Exp $
+ * Version: $Id: ip_input.c,v 1.42 1999/08/20 11:05:27 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -140,11 +140,7 @@
#include <net/icmp.h>
#include <net/raw.h>
#include <net/checksum.h>
-#include <linux/ip_fw.h>
-#ifdef CONFIG_IP_MASQUERADE
-#include <net/ip_masq.h>
-#endif
-#include <linux/firewall.h>
+#include <linux/netfilter_ipv4.h>
#include <linux/mroute.h>
#include <linux/netlink.h>
@@ -154,10 +150,6 @@
struct ip_mib ip_statistics={2,IPDEFTTL,}; /* Forwarding=No, Default TTL=64 */
-#if defined(CONFIG_IP_TRANSPARENT_PROXY) && !defined(CONFIG_IP_ALWAYS_DEFRAG)
-#define CONFIG_IP_ALWAYS_DEFRAG 1
-#endif
-
/*
* Process Router Attention IP option
*/
@@ -167,13 +159,16 @@
u8 protocol = skb->nh.iph->protocol;
struct sock *last = NULL;
+ read_lock(&ip_ra_lock);
for (ra = ip_ra_chain; ra; ra = ra->next) {
struct sock *sk = ra->sk;
if (sk && sk->num == protocol) {
if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
skb = ip_defrag(skb);
- if (skb == NULL)
+ if (skb == NULL) {
+ read_unlock(&ip_ra_lock);
return 1;
+ }
}
if (last) {
struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
@@ -186,8 +181,10 @@
if (last) {
raw_rcv(last, skb);
+ read_unlock(&ip_ra_lock);
return 1;
}
+ read_unlock(&ip_ra_lock);
return 0;
}
@@ -214,59 +211,19 @@
return ret;
}
-extern struct sock *raw_v4_input(struct sk_buff *, struct iphdr *, int);
-
-/*
- * Deliver IP Packets to the higher protocol layers.
- */
-int ip_local_deliver(struct sk_buff *skb)
+static inline int ip_local_deliver_finish(struct sk_buff *skb)
{
struct iphdr *iph = skb->nh.iph;
-#ifndef CONFIG_IP_ALWAYS_DEFRAG
- /*
- * Reassemble IP fragments.
- */
-
- if (iph->frag_off & htons(IP_MF|IP_OFFSET)) {
- skb = ip_defrag(skb);
- if (!skb)
- return 0;
- iph = skb->nh.iph;
+#ifdef CONFIG_NETFILTER_DEBUG
+ nf_debug_ip_local_deliver(skb);
+#endif /*CONFIG_NETFILTER_DEBUG*/
+
+ /* Free rx_dev before enqueueing to sockets */
+ if (skb->rx_dev) {
+ dev_put(skb->rx_dev);
+ skb->rx_dev = NULL;
}
-#endif
-
-#ifdef CONFIG_IP_MASQUERADE
- /* Do we need to de-masquerade this packet? */
- if((IPCB(skb)->flags&IPSKB_MASQUERADED)) {
- /* Some masq modules can re-inject packets if
- * bad configured.
- */
- printk(KERN_DEBUG "ip_input(): demasq recursion detected. "
- "Check masq modules configuration\n");
- kfree_skb(skb);
- return 0;
- } else {
- int ret = ip_fw_demasquerade(&skb);
-
- if (ret < 0) {
- kfree_skb(skb);
- return 0;
- }
- if (ret) {
- iph = skb->nh.iph;
- IPCB(skb)->flags |= IPSKB_MASQUERADED;
- dst_release(skb->dst);
- skb->dst = NULL;
- if (ip_route_input(skb, iph->daddr, iph->saddr,
- iph->tos, skb->dev)) {
- kfree_skb(skb);
- return 0;
- }
- return skb->dst->input(skb);
- }
- }
-#endif
/* Point into the IP datagram, just past the header. */
skb->h.raw = skb->nh.raw + iph->ihl*4;
@@ -284,19 +241,26 @@
if(raw_sk != NULL)
raw_sk = raw_v4_input(skb, iph, hash);
+ read_lock(&inet_protocol_lock);
ipprot = (struct inet_protocol *) inet_protos[hash];
flag = 0;
if(ipprot != NULL) {
if(raw_sk == NULL &&
ipprot->next == NULL &&
ipprot->protocol == iph->protocol) {
+ int ret;
+
/* Fast path... */
- return ipprot->handler(skb, (ntohs(iph->tot_len) -
- (iph->ihl * 4)));
+ ret = ipprot->handler(skb, (ntohs(iph->tot_len) -
+ (iph->ihl * 4)));
+
+ read_unlock(&inet_protocol_lock);
+ return ret;
} else {
flag = ip_run_ipprot(skb, iph, ipprot, (raw_sk != NULL));
}
- }
+ }
+ read_unlock(&inet_protocol_lock);
/* All protocols checked.
* If this packet was a broadcast, we may *not* reply to it, since that
@@ -305,6 +269,7 @@
*/
if(raw_sk != NULL) { /* Shift to last raw user */
raw_rcv(raw_sk, skb);
+ sock_put(raw_sk);
} else if (!flag) { /* Free and report errors */
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
kfree_skb(skb);
@@ -315,75 +280,31 @@
}
/*
- * Main IP Receive routine.
+ * Deliver IP Packets to the higher protocol layers.
*/
-int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+int ip_local_deliver(struct sk_buff *skb)
{
struct iphdr *iph = skb->nh.iph;
-#ifdef CONFIG_FIREWALL
- int fwres;
- u16 rport;
-#endif /* CONFIG_FIREWALL */
-
- /* When the interface is in promisc. mode, drop all the crap
- * that it receives, do not try to analyse it.
- */
- if (skb->pkt_type == PACKET_OTHERHOST)
- goto drop;
-
- ip_statistics.IpInReceives++;
/*
- * RFC1122: 3.1.2.2 MUST silently discard any IP frame that fails the checksum.
- *
- * Is the datagram acceptable?
- *
- * 1. Length at least the size of an ip header
- * 2. Version of 4
- * 3. Checksums correctly. [Speed optimisation for later, skip loopback checksums]
- * 4. Doesn't have a bogus length
+ * Reassemble IP fragments.
*/
- if (skb->len < sizeof(struct iphdr))
- goto inhdr_error;
- if (iph->ihl < 5 || iph->version != 4 || ip_fast_csum((u8 *)iph, iph->ihl) != 0)
- goto inhdr_error;
-
- {
- __u32 len = ntohs(iph->tot_len);
- if (skb->len < len)
- goto inhdr_error;
-
- /* Our transport medium may have padded the buffer out. Now we know it
- * is IP we can trim to the true length of the frame.
- * Note this now means skb->len holds ntohs(iph->tot_len).
- */
- __skb_trim(skb, len);
- }
-
-#ifdef CONFIG_IP_ALWAYS_DEFRAG
- /* Won't send ICMP reply, since skb->dst == NULL. --RR */
if (iph->frag_off & htons(IP_MF|IP_OFFSET)) {
skb = ip_defrag(skb);
if (!skb)
return 0;
iph = skb->nh.iph;
- ip_send_check(iph);
}
-#endif
-#ifdef CONFIG_FIREWALL
- /*
- * See if the firewall wants to dispose of the packet.
- *
- * We can't do ICMP reply or local delivery before routing,
- * so we delay those decisions until after route. --RR
- */
- fwres = call_in_firewall(PF_INET, dev, iph, &rport, &skb);
- if (fwres < FW_ACCEPT && fwres != FW_REJECT)
- goto drop;
- iph = skb->nh.iph;
-#endif /* CONFIG_FIREWALL */
+ return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
+ ip_local_deliver_finish);
+}
+
+static inline int ip_rcv_finish(struct sk_buff *skb)
+{
+ struct net_device *dev = skb->dev;
+ struct iphdr *iph = skb->nh.iph;
/*
* Initialise the virtual path cache for the packet. It describes
@@ -428,36 +349,85 @@
opt = &(IPCB(skb)->opt);
if (opt->srr) {
- struct in_device *in_dev = dev->ip_ptr;
- if (in_dev && !IN_DEV_SOURCE_ROUTE(in_dev)) {
- if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
- printk(KERN_INFO "source route option %d.%d.%d.%d -> %d.%d.%d.%d\n",
- NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
- goto drop;
+ struct in_device *in_dev = in_dev_get(dev);
+ if (in_dev) {
+ if (!IN_DEV_SOURCE_ROUTE(in_dev)) {
+ if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
+ printk(KERN_INFO "source route option %d.%d.%d.%d -> %d.%d.%d.%d\n",
+ NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
+ in_dev_put(in_dev);
+ goto drop;
+ }
+ in_dev_put(in_dev);
}
if (ip_options_rcv_srr(skb))
goto drop;
}
}
-#ifdef CONFIG_FIREWALL
-#ifdef CONFIG_IP_TRANSPARENT_PROXY
- if (fwres == FW_REDIRECT && (IPCB(skb)->redirport = rport) != 0)
- return ip_local_deliver(skb);
-#endif /* CONFIG_IP_TRANSPARENT_PROXY */
+ return skb->dst->input(skb);
- if (fwres == FW_REJECT) {
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+inhdr_error:
+ ip_statistics.IpInHdrErrors++;
+drop:
+ kfree_skb(skb);
+ return(0);
+}
+
+/*
+ * Main IP Receive routine.
+ */
+int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+{
+ struct iphdr *iph = skb->nh.iph;
+
+ /* When the interface is in promisc. mode, drop all the crap
+ * that it receives, do not try to analyse it.
+ */
+ if (skb->pkt_type == PACKET_OTHERHOST)
goto drop;
+
+ ip_statistics.IpInReceives++;
+
+ if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+ goto out;
+
+ /*
+ * RFC1122: 3.1.2.2 MUST silently discard any IP frame that fails the checksum.
+ *
+ * Is the datagram acceptable?
+ *
+ * 1. Length at least the size of an ip header
+ * 2. Version of 4
+ * 3. Checksums correctly. [Speed optimisation for later, skip loopback checksums]
+ * 4. Doesn't have a bogus length
+ */
+
+ if (skb->len < sizeof(struct iphdr))
+ goto inhdr_error;
+ if (iph->ihl < 5 || iph->version != 4 || ip_fast_csum((u8 *)iph, iph->ihl) != 0)
+ goto inhdr_error;
+
+ {
+ __u32 len = ntohs(iph->tot_len);
+ if (skb->len < len)
+ goto inhdr_error;
+
+ /* Our transport medium may have padded the buffer out. Now we know it
+ * is IP we can trim to the true length of the frame.
+ * Note this now means skb->len holds ntohs(iph->tot_len).
+ */
+ __skb_trim(skb, len);
}
-#endif /* CONFIG_FIREWALL */
- return skb->dst->input(skb);
+ return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
+ ip_rcv_finish);
inhdr_error:
ip_statistics.IpInHdrErrors++;
drop:
kfree_skb(skb);
+out:
return(0);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)