patch-2.3.15 linux/net/ipv4/ip_gre.c
Next file: linux/net/ipv4/ip_input.c
Previous file: linux/net/ipv4/ip_fw.c
Back to the patch index
Back to the overall index
- Lines: 207
- Date:
Mon Aug 23 10:01:02 1999
- Orig file:
v2.3.14/linux/net/ipv4/ip_gre.c
- Orig date:
Wed Aug 18 11:38:49 1999
diff -u --recursive --new-file v2.3.14/linux/net/ipv4/ip_gre.c linux/net/ipv4/ip_gre.c
@@ -153,6 +153,8 @@
#define tunnels_l (tunnels[1])
#define tunnels_wc (tunnels[0])
+static rwlock_t ipgre_lock = RW_LOCK_UNLOCKED;
+
/* Given src, dst and key, find approriate for input tunnel. */
static struct ip_tunnel * ipgre_tunnel_lookup(u32 remote, u32 local, u32 key)
@@ -212,8 +214,9 @@
struct ip_tunnel **tp = ipgre_bucket(t);
t->next = *tp;
- wmb();
+ write_lock_bh(&ipgre_lock);
*tp = t;
+ write_unlock_bh(&ipgre_lock);
}
static void ipgre_tunnel_unlink(struct ip_tunnel *t)
@@ -222,8 +225,9 @@
for (tp = ipgre_bucket(t); *tp; tp = &(*tp)->next) {
if (t == *tp) {
+ write_lock_bh(&ipgre_lock);
*tp = t->next;
- synchronize_bh();
+ write_unlock_bh(&ipgre_lock);
break;
}
}
@@ -266,12 +270,13 @@
nt->dev = dev;
dev->name = nt->parms.name;
dev->init = ipgre_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, "gre%d", i);
- if (dev_get(dev->name) == NULL)
+ if (__dev_get_by_name(dev->name) == NULL)
break;
}
if (i==100)
@@ -281,6 +286,7 @@
if (register_netdevice(dev) < 0)
goto failed;
+ dev_hold(dev);
ipgre_tunnel_link(nt);
/* Do not decrement MOD_USE_COUNT here. */
return nt;
@@ -291,16 +297,19 @@
return NULL;
}
-static void ipgre_tunnel_destroy(struct net_device *dev)
+static void ipgre_tunnel_destructor(struct net_device *dev)
{
- ipgre_tunnel_unlink((struct ip_tunnel*)dev->priv);
-
if (dev != &ipgre_fb_tunnel_dev) {
- kfree(dev);
MOD_DEC_USE_COUNT;
}
}
+static void ipgre_tunnel_uninit(struct net_device *dev)
+{
+ ipgre_tunnel_unlink((struct ip_tunnel*)dev->priv);
+ dev_put(dev);
+}
+
void ipgre_err(struct sk_buff *skb, unsigned char *dp, int len)
{
@@ -370,18 +379,21 @@
break;
}
+ read_lock(&ipgre_lock);
t = ipgre_tunnel_lookup(iph->daddr, iph->saddr, (flags&GRE_KEY) ? *(((u32*)p) + (grehlen>>2) - 1) : 0);
if (t == NULL || t->parms.iph.daddr == 0 || MULTICAST(t->parms.iph.daddr))
- 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(&ipgre_lock);
return;
#else
struct iphdr *iph = (struct iphdr*)dp;
@@ -533,7 +545,7 @@
- We do not support routing headers.
*/
if (flags&(GRE_VERSION|GRE_ROUTING))
- goto drop;
+ goto drop_nolock;
if (flags&GRE_CSUM) {
csum = ip_compute_csum(h, len);
@@ -549,6 +561,7 @@
}
}
+ read_lock(&ipgre_lock);
if ((tunnel = ipgre_tunnel_lookup(iph->saddr, iph->daddr, key)) != NULL) {
skb->mac.raw = skb->nh.raw;
skb->nh.raw = skb_pull(skb, h + offset - skb->data);
@@ -587,11 +600,14 @@
dst_release(skb->dst);
skb->dst = NULL;
netif_rx(skb);
+ read_unlock(&ipgre_lock);
return(0);
}
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
drop:
+ read_unlock(&ipgre_lock);
+drop_nolock:
kfree_skb(skb);
return(0);
}
@@ -890,7 +906,6 @@
err = -EINVAL;
break;
}
- start_bh_atomic();
ipgre_tunnel_unlink(t);
t->parms.iph.saddr = p.iph.saddr;
t->parms.iph.daddr = p.iph.daddr;
@@ -899,7 +914,6 @@
memcpy(dev->dev_addr, &p.iph.saddr, 4);
memcpy(dev->broadcast, &p.iph.daddr, 4);
ipgre_tunnel_link(t);
- end_bh_atomic();
netdev_state_change(dev);
}
}
@@ -1032,12 +1046,12 @@
}
dev = rt->u.dst.dev;
ip_rt_put(rt);
- if (dev->ip_ptr == NULL) {
+ if (__in_dev_get(dev) == NULL) {
MOD_DEC_USE_COUNT;
return -EADDRNOTAVAIL;
}
t->mlink = dev->ifindex;
- ip_mc_inc_group(dev->ip_ptr, t->parms.iph.daddr);
+ ip_mc_inc_group(__in_dev_get(dev), t->parms.iph.daddr);
}
return 0;
}
@@ -1046,9 +1060,11 @@
{
struct ip_tunnel *t = (struct ip_tunnel*)dev->priv;
if (MULTICAST(t->parms.iph.daddr) && t->mlink) {
- dev = dev_get_by_index(t->mlink);
- if (dev && dev->ip_ptr)
- ip_mc_dec_group(dev->ip_ptr, t->parms.iph.daddr);
+ struct in_device *in_dev = inetdev_by_index(t->mlink);
+ if (in_dev) {
+ ip_mc_dec_group(in_dev, t->parms.iph.daddr);
+ in_dev_put(in_dev);
+ }
}
MOD_DEC_USE_COUNT;
return 0;
@@ -1060,7 +1076,8 @@
{
struct ip_tunnel *t = (struct ip_tunnel*)dev->priv;
- dev->destructor = ipgre_tunnel_destroy;
+ dev->uninit = ipgre_tunnel_uninit;
+ dev->destructor = ipgre_tunnel_destructor;
dev->hard_start_xmit = ipgre_tunnel_xmit;
dev->get_stats = ipgre_tunnel_get_stats;
dev->do_ioctl = ipgre_tunnel_ioctl;
@@ -1116,7 +1133,7 @@
}
if (!tdev && tunnel->parms.link)
- tdev = dev_get_by_index(tunnel->parms.link);
+ tdev = __dev_get_by_index(tunnel->parms.link);
if (tdev) {
hlen = tdev->hard_header_len;
@@ -1170,6 +1187,7 @@
iph->ihl = 5;
tunnel->hlen = sizeof(struct iphdr) + 4;
+ dev_hold(dev);
tunnels_wc[0] = &ipgre_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)