Bugs in Net code

Alan Cox (iialan@iifeak.swan.ac.uk)
Tue, 16 Jul 96 12:37 BST


Can people having problems with multicast routing and tunnels try this diff and
see how it goes. Its a combo of patches several people have sent in. Also
contains the extra bridge fix.

Alan

diff --new-file --unified --exclude-from exclude --recursive linux.vanilla/drivers/net/new_tunnel.c linux/drivers/net/new_tunnel.c
--- linux.vanilla/drivers/net/new_tunnel.c Sun Jun 9 13:12:13 1996
+++ linux/drivers/net/new_tunnel.c Mon Jul 15 22:53:01 1996
@@ -233,8 +233,9 @@
printk("Room left at tail: %d\n", skb_tailroom(skb));
printk("Required room: %d, Tunnel hlen: %d\n", max_headroom, TUNL_HLEN);
#endif
- if (skb_headroom(skb) >= max_headroom) {
+ if (skb_headroom(skb) >= max_headroom && skb->free) {
skb->h.iph = (struct iphdr *) skb_push(skb, tunnel_hlen);
+ skb_device_unlock(skb);
} else {
struct sk_buff *new_skb;

@@ -289,7 +290,7 @@
iph->tot_len = htons(skb->len);
iph->id = htons(ip_id_count++); /* Race condition here? */
ip_send_check(iph);
- skb->ip_hdr = skb->h.iph;
+ skb->ip_hdr = skb->h.iph;
skb->protocol = htons(ETH_P_IP);
#ifdef TUNNEL_DEBUG
printk("New IP Header....\n");
@@ -303,7 +304,7 @@
*/

#ifdef CONFIG_IP_FORWARD
- if (ip_forward(skb, dev, 0, target))
+ if (ip_forward(skb, dev, IPFWD_NOTTLDEC, target))
#endif
kfree_skb(skb, FREE_WRITE);

diff --new-file --unified --exclude-from exclude --recursive linux.vanilla/include/net/ip_forward.h linux/include/net/ip_forward.h
--- linux.vanilla/include/net/ip_forward.h Sun Jun 9 13:11:55 1996
+++ linux/include/net/ip_forward.h Mon Jul 15 22:53:06 1996
@@ -5,6 +5,7 @@
#define IPFWD_LASTFRAG 2
#define IPFWD_MASQUERADED 4
#define IPFWD_MULTICASTING 8
-#define IPFWD_MULTITUNNEL 16
+#define IPFWD_MULTITUNNEL 0x10
+#define IPFWD_NOTTLDEC 0x20

#endif
diff --new-file --unified --exclude-from exclude --recursive linux.vanilla/include/net/netlink.h linux/include/net/netlink.h
--- linux.vanilla/include/net/netlink.h Sun Jun 9 13:11:55 1996
+++ linux/include/net/netlink.h Mon Jul 15 23:40:11 1996
@@ -2,8 +2,9 @@
#define __NET_NETLINK_H

#define NET_MAJOR 36 /* Major 18 is reserved for networking */
-#define MAX_LINKS 10 /* 18,0 for route updates, 18,1 for SKIP, 18,2 debug tap 18,3 PPP reserved */
+#define MAX_LINKS 11 /* 18,0 for route updates, 18,1 for SKIP, 18,2 debug tap 18,3 PPP reserved */
/* 4-7 are psi0-psi3 8 is arpd 9 is ppp */
+ /* 10 is for IPSEC <John Ioannidis> */
#define MAX_QBYTES 32768 /* Maximum bytes in the queue */

#include <linux/config.h>
@@ -21,6 +22,7 @@
#define NETLINK_PSI 4 /* PSI devices - 4 to 7 */
#define NETLINK_ARPD 8
#define NETLINK_NET_PPP 9 /* Non tty PPP devices */
+#define NETLINK_IPSEC 10 /* IPSEC */

#ifdef CONFIG_RTNETLINK
extern void ip_netlink_msg(unsigned long, __u32, __u32, __u32, short, short, char *);
diff --new-file --unified --exclude-from exclude --recursive linux.vanilla/net/bridge/br.c linux/net/bridge/br.c
--- linux.vanilla/net/bridge/br.c Mon Jul 15 22:29:32 1996
+++ linux/net/bridge/br.c Mon Jul 15 22:37:05 1996
@@ -1307,7 +1307,7 @@
/*
* Sending
*/
- if (port_info[f->port].state == Forwarding) {
+ if (f->port!=port && port_info[f->port].state == Forwarding) {
/* has entry expired? */
if (f->timer + fdb_aging_time < CURRENT_TIME) {
/* timer expired, invalidate entry */
diff --new-file --unified --exclude-from exclude --recursive linux.vanilla/net/ipv4/ip_forward.c linux/net/ipv4/ip_forward.c
--- linux.vanilla/net/ipv4/ip_forward.c Thu Jul 4 00:23:35 1996
+++ linux/net/ipv4/ip_forward.c Mon Jul 15 22:53:44 1996
@@ -57,8 +57,11 @@
* 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;
@@ -67,17 +70,26 @@
iph->saddr = out->pa_addr;
iph->protocol = IPPROTO_IPIP;
iph->ihl = 5;
- iph->tot_len = htons(skb->len);
+ iph->tot_len = htons(skb->len + len); /* Anand, ernet */
iph->id = htons(ip_id_count++);
ip_send_check(iph);

skb->dev = out;
skb->arp = 1;
- skb->raddr=daddr;
+ skb->raddr=daddr; /* Router address is not destination address. The
+ * correct value is given eventually. I have not
+ * removed this statement. But could have.
+ * Anand, ernet.
+ */
/*
* 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)
+
+ /* The last parameter of out->hard_header() needed skb->len + len.
+ * Anand, ernet.
+ */
+ if (out->hard_header && out->hard_header(skb, out, ETH_P_IP, NULL, NULL,
+ skb->len + len)<0)
skb->arp=0;
/*
* Read to queue for transmission.
@@ -121,18 +133,21 @@
*/

iph = skb->h.iph;
- iph->ttl--;
+ if (!(is_frag&IPFWD_NOTTLDEC))
+ {
+ iph->ttl--;

/*
* Re-compute the IP header checksum.
- * This is inefficient. We know what has happened to the header
- * and could thus adjust the checksum as Phil Karn does in KA9Q
+ * This is efficient. We know what has happened to the header
+ * and can thus adjust the checksum as Phil Karn does in KA9Q
*/

- iph->check = ntohs(iph->check) + 0x0100;
- if ((iph->check & 0xFF00) == 0)
- iph->check++; /* carry overflow */
- iph->check = htons(iph->check);
+ iph->check = ntohs(iph->check) + 0x0100;
+ if ((iph->check & 0xFF00) == 0)
+ iph->check++; /* carry overflow */
+ iph->check = htons(iph->check);
+ }

if (iph->ttl <= 0)
{
@@ -141,8 +156,14 @@
return -1;
}

+ /* If IPFWD_MULTITUNNEL flag is set, then we have to perform routing
+ * decision so as to reach the other end of the tunnel. This condition
+ * also means that we are dealing with a unicast IP packet "in a way".
+ * Anand, ernet.
+ */
+
#ifdef CONFIG_IP_MROUTE
- if(!(is_frag&IPFWD_MULTICASTING))
+ if(!(is_frag&IPFWD_MULTICASTING) || is_frag&IPFWD_MULTITUNNEL)
{
#endif
/*
@@ -205,6 +226,12 @@
icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, raddr, dev);
#endif
#ifdef CONFIG_IP_MROUTE
+
+ /* This is for ip encap. Anand, ernet.*/
+
+ if (is_frag&IPFWD_MULTITUNNEL) {
+ encap=20;
+ }
}
else
{
@@ -326,8 +353,21 @@
#ifdef CONFIG_IP_MROUTE
if(is_frag&IPFWD_MULTITUNNEL)
{
- skb_reserve(skb2,(encap+dev2->hard_header_len+15)&~15); /* 16 byte aligned IP headers are good */
- ip_encap(skb2,skb->len, dev2, raddr);
+ skb_reserve(skb2,(encap+dev->hard_header_len+15)&~15); /* 16 byte aligned IP headers are good */
+
+/* We need to pass on IP information of the incoming packet to ip_encap()
+ * to fillin ttl, and tos fields.The destination should be target_addr.
+ * Anand, ernet.
+ */
+
+ skb2->ip_hdr = skb->ip_hdr;
+
+ ip_encap(skb2,skb->len, dev2, target_addr);
+
+/* The router address is got earlier that to take us to the remote tunnel
+ * Anand, ernet.
+ */
+ skb2->raddr = rt->rt_gateway;
}
else
#endif
@@ -341,7 +381,6 @@
ptr = skb_put(skb2,skb->len);
skb2->free = 1;
skb2->h.raw = ptr;
-
/*
* Copy the packet data into the new buffer.
*/
@@ -517,3 +556,6 @@


#endif
+
+
+
diff --new-file --unified --exclude-from exclude --recursive linux.vanilla/net/ipv4/ip_fragment.c linux/net/ipv4/ip_fragment.c
--- linux.vanilla/net/ipv4/ip_fragment.c Sun Jun 9 13:12:00 1996
+++ linux/net/ipv4/ip_fragment.c Mon Jul 15 22:55:44 1996
@@ -706,8 +706,10 @@
*/

skb2->arp = skb->arp;
+#if 0
if(skb->free==0)
printk(KERN_ERR "IP fragmenter: BUG free!=1 in fragmenter\n");
+#endif
skb2->free = 1;
skb_put(skb2,len + hlen);
skb2->h.raw=(char *) skb2->data;
diff --new-file --unified --exclude-from exclude --recursive linux.vanilla/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c
--- linux.vanilla/net/ipv4/ipmr.c Sun Jun 9 13:12:00 1996
+++ linux/net/ipv4/ipmr.c Mon Jul 15 22:51:24 1996
@@ -1,5 +1,5 @@
/*
- * IP multicast routing support for mrouted 3.6
+ * IP multicast routing support for mrouted 3.6/3.8
*
* (c) 1995 Alan Cox, <alan@cymru.net>
* Linux Consultancy and Custom Driver Development
@@ -12,8 +12,11 @@
*
* Fixes:
* Michael Chastain : Incorrect size of copying.
- * Alan Cox : Added the cache manager code
+ * Alan Cox : Added the cache manager code.
* Alan Cox : Fixed the clone/copy bug and device race.
+ * Malcolm Beattie : Buffer handling fixes.
+ * Alexey Kuznetsov : Double buffer free and other fixes.
+ * SVR Anand : Fixed several multicast bugs and problems.
*
* Status:
* Cache manager under test. Forwarding in vague test mode
@@ -736,7 +739,14 @@
kfree_skb(skb, FREE_WRITE);
return;
}
+
+ /*
+ * Without the following addition, skb->h.iph points to something
+ * different that is not the ip header.
+ */

+ skb->h.iph = skb->ip_hdr; /* Anand, ernet. */
+
vif_table[vif].pkt_in++;
vif_table[vif].bytes_in+=skb->len;

@@ -909,7 +919,7 @@

void ip_mr_init(void)
{
- printk(KERN_INFO "Linux IP multicast router 0.05.\n");
+ printk(KERN_INFO "Linux IP multicast router 0.06.\n");
register_netdevice_notifier(&ip_mr_notifier);
#ifdef CONFIG_PROC_FS
proc_net_register(&(struct proc_dir_entry) {