patch-1.3.31 linux/net/ipv4/ip.c
Next file: linux/net/ipv4/ip_fw.c
Previous file: linux/net/ipv4/icmp.c
Back to the patch index
Back to the overall index
- Lines: 432
- Date:
Wed Oct 4 08:15:11 1995
- Orig file:
v1.3.30/linux/net/ipv4/ip.c
- Orig date:
Wed Sep 27 16:00:02 1995
diff -u --recursive --new-file v1.3.30/linux/net/ipv4/ip.c linux/net/ipv4/ip.c
@@ -93,6 +93,8 @@
* Werner Almesberger : Zero fragment bug
* Alan Cox : RAW IP frame length bug
* Alan Cox : Outgoing firewall on build_xmit
+ * A.N.Kuznetsov : IP_OPTIONS support throughout the kernel
+ * Alan Cox : Multicast routing hooks
*
*
*
@@ -1466,6 +1468,50 @@
#ifdef CONFIG_IP_FORWARD
+#ifdef CONFIG_IP_MROUTE
+
+/*
+ * Encapsulate a packet by attaching a valid IPIP header to it.
+ * This avoids tunnel drivers and other mess and gives us the speed so
+ * important for multicast video.
+ */
+
+static void ip_encap(struct sk_buff *skb, int len, struct device *out, __u32 daddr)
+{
+ /*
+ * There is space for the IPIP header and MAC left.
+ *
+ * Firstly push down and install the IPIP header.
+ */
+ struct iphdr *iph=(struct iphdr *)skb_push(skb,sizeof(struct iphdr));
+ if(len>65515)
+ len=65515;
+ iph->version = 4;
+ iph->tos = skb->ip_hdr->tos;
+ iph->ttl = skb->ip_hdr->ttl;
+ iph->frag_off = 0;
+ iph->daddr = daddr;
+ iph->saddr = out->pa_addr;
+ iph->protocol = IPPROTO_IPIP;
+ iph->ihl = 5;
+ iph->tot_len = htons(skb->len);
+ iph->id = htons(ip_id_count++);
+ ip_send_check(iph);
+
+ skb->dev = out;
+ skb->arp = 1;
+ skb->raddr=daddr;
+ /*
+ * Now add the physical header (driver will push it down).
+ */
+ if (out->hard_header && out->hard_header(skb, out, ETH_P_IP, NULL, NULL, len)<0)
+ skb->arp=0;
+ /*
+ * Read to queue for transmission.
+ */
+}
+
+#endif
/*
* Forward an IP datagram to its next destination.
@@ -1485,7 +1531,8 @@
int fw_res = 0; /* Forwarding result */
#ifdef CONFIG_IP_MASQUERADE
struct sk_buff *skb_in = skb; /* So we can remember if the masquerader did some swaps */
-#endif
+#endif
+ int encap = 0; /* Encap length */
/*
* See if we are allowed to forward this.
@@ -1542,83 +1589,86 @@
return -1;
}
- /*
- * OK, the packet is still valid. Fetch its destination address,
- * and give it to the IP sender for further processing.
- */
-
- rt = ip_rt_route(target_addr, NULL, NULL);
- if (rt == NULL)
- {
- /*
- * Tell the sender its packet cannot be delivered. Again
- * ICMP is screened later.
- */
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, 0, dev);
- return -1;
- }
-
-
- /*
- * Gosh. Not only is the packet valid; we even know how to
- * forward it onto its final destination. Can we say this
- * is being plain lucky?
- * If the router told us that there is no GW, use the dest.
- * IP address itself- we seem to be connected directly...
- */
-
- raddr = rt->rt_gateway;
-
- if (raddr != 0)
+#ifdef CONFIG_IP_MROUTE
+ if(!(is_frag&8))
{
+#endif
/*
- * Strict routing permits no gatewaying
+ * OK, the packet is still valid. Fetch its destination address,
+ * and give it to the IP sender for further processing.
*/
- if (opt->is_strictroute)
+ rt = ip_rt_route(target_addr, NULL, NULL);
+ if (rt == NULL)
{
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0, dev);
+ /*
+ * Tell the sender its packet cannot be delivered. Again
+ * ICMP is screened later.
+ */
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, 0, dev);
return -1;
}
+
/*
- * There is a gateway so find the correct route for it.
- * Gateways cannot in turn be gatewayed.
+ * Gosh. Not only is the packet valid; we even know how to
+ * forward it onto its final destination. Can we say this
+ * is being plain lucky?
+ * If the router told us that there is no GW, use the dest.
+ * IP address itself- we seem to be connected directly...
*/
-#if 0
- rt = ip_rt_route(raddr, NULL, NULL);
- if (rt == NULL)
+ raddr = rt->rt_gateway;
+
+ if (raddr != 0)
{
/*
- * Tell the sender its packet cannot be delivered...
+ * Strict routing permits no gatewaying
+ */
+
+ if (opt->is_strictroute)
+ {
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0, dev);
+ return -1;
+ }
+
+ /*
+ * There is a gateway so find the correct route for it.
+ * Gateways cannot in turn be gatewayed.
*/
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
- return -1;
}
- if (rt->rt_gateway != 0)
- raddr = rt->rt_gateway;
+ else
+ raddr = target_addr;
+
+ /*
+ * Having picked a route we can now send the frame out.
+ */
+
+ dev2 = rt->rt_dev;
+ /*
+ * In IP you never have to forward a frame on the interface that it
+ * arrived upon. We now generate an ICMP HOST REDIRECT giving the route
+ * we calculated.
+ */
+#ifndef CONFIG_IP_NO_ICMP_REDIRECT
+ if (dev == dev2 && !((iph->saddr^iph->daddr)&dev->pa_mask) &&
+ (rt->rt_flags&RTF_MODIFIED) && !opt->srr)
+ icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, raddr, dev);
#endif
+#ifdef CONFIG_IP_MROUTE
}
else
- raddr = target_addr;
-
- /*
- * Having picked a route we can now send the frame out.
- */
-
- dev2 = rt->rt_dev;
+ {
+ /*
+ * Multicast route forward. Routing is already done
+ */
+ dev2=skb->dev;
+ raddr=skb->raddr;
+ if(is_frag&16) /* VIFF_TUNNEL mode */
+ encap=20;
+ }
+#endif
- /*
- * In IP you never have to forward a frame on the interface that it
- * arrived upon. We now generate an ICMP HOST REDIRECT giving the route
- * we calculated.
- */
-#ifndef CONFIG_IP_NO_ICMP_REDIRECT
- if (dev == dev2 && !((iph->saddr^iph->daddr)&dev->pa_mask) &&
- (rt->rt_flags&RTF_MODIFIED) && !opt->srr)
- icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, raddr, dev);
-#endif
/*
* We now may allocate a new buffer, and copy the datagram into it.
@@ -1637,17 +1687,21 @@
#endif
IS_SKB(skb);
- if (skb->len > dev2->mtu && (ntohs(iph->frag_off) & IP_DF)) {
+ if (skb->len+encap > dev2->mtu && (ntohs(iph->frag_off) & IP_DF)) {
ip_statistics.IpFragFails++;
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, dev2->mtu, dev);
return -1;
}
+#ifdef CONFIG_IP_MROUTE
+ if(skb_headroom(skb)-encap<dev2->hard_header_len)
+ {
+ skb2 = alloc_skb(dev2->hard_header_len + skb->len + encap + 15, GFP_ATOMIC);
+#else
if(skb_headroom(skb)<dev2->hard_header_len)
{
skb2 = alloc_skb(dev2->hard_header_len + skb->len + 15, GFP_ATOMIC);
- IS_SKB(skb2);
-
+#endif
/*
* This is rare and since IP is tolerant of network failures
* quite harmless.
@@ -1659,11 +1713,19 @@
return -1;
}
+ IS_SKB(skb2);
/*
* Add the physical headers.
*/
-
- ip_send(skb2,raddr,skb->len,dev2,dev2->pa_addr);
+#ifdef CONFIG_IP_MROUTE
+ if(is_frag&16)
+ {
+ skb_reserve(skb,(encap+dev->hard_header_len+15)&~15); /* 16 byte aligned IP headers are good */
+ ip_encap(skb2,skb->len, dev2, raddr);
+ }
+ else
+#endif
+ ip_send(skb2,raddr,skb->len,dev2,dev2->pa_addr);
/*
* We have to copy the bytes over as the new header wouldn't fit
@@ -1689,13 +1751,22 @@
skb2 = skb;
skb2->dev=dev2;
- skb->arp=1;
- skb->raddr=raddr;
- if(dev2->hard_header)
+#ifdef CONFIG_IP_MROUTE
+ if(is_frag&16)
+ ip_encap(skb,skb->len, dev2, raddr);
+ else
{
- if(dev2->hard_header(skb, dev2, ETH_P_IP, NULL, NULL, skb->len)<0)
- skb->arp=0;
- }
+#endif
+ skb->arp=1;
+ skb->raddr=raddr;
+ if(dev2->hard_header)
+ {
+ if(dev2->hard_header(skb, dev2, ETH_P_IP, NULL, NULL, skb->len)<0)
+ skb->arp=0;
+ }
+#ifdef CONFIG_IP_MROUTE
+ }
+#endif
ip_statistics.IpForwDatagrams++;
}
@@ -1825,6 +1896,9 @@
#ifdef CONFIG_IP_FIREWALL
int err;
#endif
+#ifdef CONFIG_IP_MROUTE
+ int mroute_pkt=0;
+#endif
#ifdef CONFIG_NET_IPV6
/*
@@ -1944,9 +2018,11 @@
for ( srrptr=optptr[2], srrspace = optptr[1];
srrptr <= srrspace;
srrptr += 4
- ) {
+ )
+ {
int brd2;
- if (srrptr + 3 > srrspace) {
+ if (srrptr + 3 > srrspace)
+ {
icmp_send(skb, ICMP_PARAMETERPROB, 0, opt->srr+2,
skb->dev);
kfree_skb(skb, FREE_WRITE);
@@ -1954,21 +2030,26 @@
}
memcpy(&nexthop, &optptr[srrptr-1], 4);
if ((brd2 = ip_chk_addr(nexthop)) == 0)
- break;
- if (brd2 != IS_MYADDR) {
-/* ANK: should we implement weak tunneling of multicasts?
- * Are they obsolete? DVMRP specs (RFC-1075) is old enough...
- */
+ break;
+ if (brd2 != IS_MYADDR)
+ {
+
+ /*
+ * ANK: should we implement weak tunneling of multicasts?
+ * Are they obsolete? DVMRP specs (RFC-1075) is old enough...
+ * [They are obsolete]
+ */
kfree_skb(skb, FREE_WRITE);
return -EINVAL;
}
}
- if (srrptr <= srrspace) {
+ if (srrptr <= srrspace)
+ {
opt->srr_is_hit = 1;
opt->is_changed = 1;
#ifdef CONFIG_IP_FORWARD
if (ip_forward(skb, dev, is_frag, nexthop))
- kfree_skb(skb, FREE_WRITE);
+ kfree_skb(skb, FREE_WRITE);
#else
ip_statistics.IpInAddrErrors++;
kfree_skb(skb, FREE_WRITE);
@@ -2041,6 +2122,15 @@
skb->ip_hdr = iph;
skb->h.raw += iph->ihl*4;
+#ifdef CONFIG_IP_MROUTE
+ /*
+ * Check the state on multicast routing (multicast and not 224.0.0.z)
+ */
+
+ if(brd==IS_MULTICAST && (iph->daddr&htonl(0xFFFFFF00))!=htonl(0xE0000000))
+ mroute_pkt=1;
+
+#endif
/*
* Deliver to raw sockets. This is fun as to avoid copies we want to make no surplus copies.
*
@@ -2102,7 +2192,11 @@
* raw delivery wait for that
*/
+#ifdef CONFIG_IP_MROUTE
+ if (ipprot->copy || raw_sk || mroute_pkt)
+#else
if (ipprot->copy || raw_sk)
+#endif
{
skb2 = skb_clone(skb, GFP_ATOMIC);
if(skb2==NULL)
@@ -2132,6 +2226,30 @@
* ICMP reply messages get queued up for transmission...)
*/
+#ifdef CONFIG_IP_MROUTE
+ /*
+ * Forward the last copy to the multicast router. If
+ * there is a pending raw deliery however make a copy
+ * and forward that.
+ */
+
+ if(mroute_pkt)
+ {
+ flag=1;
+ if(raw_sk==NULL)
+ ipmr_forward(skb, is_frag);
+ else
+ {
+ struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC);
+ if(skb2)
+ {
+ skb2->free=1;
+ ipmr_forward(skb2, is_frag);
+ }
+ }
+ }
+#endif
+
if(raw_sk!=NULL) /* Shift to last raw user */
raw_rcv(raw_sk, skb, dev, iph->saddr, iph->daddr);
else if (!flag) /* Free and report errors */
@@ -2145,7 +2263,7 @@
}
/*
- * Do any IP forwarding required.
+ * Do any unicast IP forwarding required.
*/
/*
@@ -2266,14 +2384,7 @@
* header length problem
*/
-#if 0
- ptr = skb->data;
- ptr += dev->hard_header_len;
- iph = (struct iphdr *)ptr;
- skb->ip_hdr = iph;
-#else
iph = skb->ip_hdr;
-#endif
iph->tot_len = ntohs(skb->len-(((unsigned char *)iph)-skb->data));
#ifdef CONFIG_IP_FIREWALL
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