patch-2.3.15 linux/net/ipv4/ipip.c
Next file: linux/net/ipv4/ipmr.c
Previous file: linux/net/ipv4/ipconfig.c
Back to the patch index
Back to the overall index
- Lines: 175
- Date:
Mon Aug 23 10:01:02 1999
- Orig file:
v2.3.14/linux/net/ipv4/ipip.c
- Orig date:
Wed Aug 18 11:38:48 1999
diff -u --recursive --new-file v2.3.14/linux/net/ipv4/ipip.c linux/net/ipv4/ipip.c
@@ -1,7 +1,7 @@
/*
* Linux NET3: IP/IP protocol decoder.
*
- * Version: $Id: ipip.c,v 1.26 1999/03/25 10:04:32 davem Exp $
+ * Version: $Id: ipip.c,v 1.28 1999/08/20 11:05:51 davem Exp $
*
* Authors:
* Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95
@@ -133,6 +133,8 @@
static struct ip_tunnel *tunnels_wc[1];
static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunnels_r_l };
+static rwlock_t ipip_lock = RW_LOCK_UNLOCKED;
+
static struct ip_tunnel * ipip_tunnel_lookup(u32 remote, u32 local)
{
unsigned h0 = HASH(remote);
@@ -182,8 +184,9 @@
for (tp = ipip_bucket(t); *tp; tp = &(*tp)->next) {
if (t == *tp) {
+ write_lock_bh(&ipip_lock);
*tp = t->next;
- synchronize_bh();
+ write_unlock_bh(&ipip_lock);
break;
}
}
@@ -194,8 +197,9 @@
struct ip_tunnel **tp = ipip_bucket(t);
t->next = *tp;
- wmb();
+ write_lock_bh(&ipip_lock);
*tp = t;
+ write_unlock_bh(&ipip_lock);
}
struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int create)
@@ -234,12 +238,13 @@
nt->dev = dev;
dev->name = nt->parms.name;
dev->init = ipip_tunnel_init;
+ dev->new_style = 1;
memcpy(&nt->parms, parms, sizeof(*parms));
if (dev->name[0] == 0) {
int i;
for (i=1; i<100; i++) {
sprintf(dev->name, "tunl%d", i);
- if (dev_get(dev->name) == NULL)
+ if (__dev_get_by_name(dev->name) == NULL)
break;
}
if (i==100)
@@ -249,6 +254,7 @@
if (register_netdevice(dev) < 0)
goto failed;
+ dev_hold(dev);
ipip_tunnel_link(nt);
/* Do not decrement MOD_USE_COUNT here. */
return nt;
@@ -259,16 +265,23 @@
return NULL;
}
+static void ipip_tunnel_destructor(struct net_device *dev)
+{
+ if (dev != &ipip_fb_tunnel_dev) {
+ MOD_DEC_USE_COUNT;
+ }
+}
-static void ipip_tunnel_destroy(struct net_device *dev)
+static void ipip_tunnel_uninit(struct net_device *dev)
{
if (dev == &ipip_fb_tunnel_dev) {
+ write_lock_bh(&ipip_lock);
tunnels_wc[0] = NULL;
- synchronize_bh();
+ write_unlock_bh(&ipip_lock);
+ dev_put(dev);
} else {
ipip_tunnel_unlink((struct ip_tunnel*)dev->priv);
- kfree(dev);
- MOD_DEC_USE_COUNT;
+ dev_put(dev);
}
}
@@ -316,17 +329,20 @@
break;
}
+ read_lock(&ipip_lock);
t = ipip_tunnel_lookup(iph->daddr, iph->saddr);
if (t == NULL || t->parms.iph.daddr == 0)
- return;
+ goto out;
if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
- return;
+ goto out;
if (jiffies - t->err_time < IPTUNNEL_ERR_TIMEO)
t->err_count++;
else
t->err_count = 1;
t->err_time = jiffies;
+out:
+ read_unlock(&ipip_lock);
return;
#else
struct iphdr *iph = (struct iphdr*)dp;
@@ -460,6 +476,7 @@
skb->ip_summed = 0;
skb->pkt_type = PACKET_HOST;
+ read_lock(&ipip_lock);
if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
tunnel->stat.rx_packets++;
tunnel->stat.rx_bytes += skb->len;
@@ -467,8 +484,10 @@
dst_release(skb->dst);
skb->dst = NULL;
netif_rx(skb);
+ read_unlock(&ipip_lock);
return 0;
}
+ read_unlock(&ipip_lock);
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
kfree_skb(skb);
@@ -674,14 +693,12 @@
break;
}
t = (struct ip_tunnel*)dev->priv;
- start_bh_atomic();
ipip_tunnel_unlink(t);
t->parms.iph.saddr = p.iph.saddr;
t->parms.iph.daddr = p.iph.daddr;
memcpy(dev->dev_addr, &p.iph.saddr, 4);
memcpy(dev->broadcast, &p.iph.daddr, 4);
ipip_tunnel_link(t);
- end_bh_atomic();
netdev_state_change(dev);
}
}
@@ -744,7 +761,8 @@
{
struct ip_tunnel *t = (struct ip_tunnel*)dev->priv;
- dev->destructor = ipip_tunnel_destroy;
+ dev->uninit = ipip_tunnel_uninit;
+ dev->destructor = ipip_tunnel_destructor;
dev->hard_start_xmit = ipip_tunnel_xmit;
dev->get_stats = ipip_tunnel_get_stats;
dev->do_ioctl = ipip_tunnel_ioctl;
@@ -783,7 +801,7 @@
}
if (!tdev && tunnel->parms.link)
- tdev = dev_get_by_index(tunnel->parms.link);
+ tdev = __dev_get_by_index(tunnel->parms.link);
if (tdev) {
dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
@@ -823,6 +841,7 @@
iph->protocol = IPPROTO_IPIP;
iph->ihl = 5;
+ dev_hold(dev);
tunnels_wc[0] = &ipip_fb_tunnel;
return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)