patch-2.2.4 linux/net/ipv4/ipip.c
Next file: linux/net/ipv4/ipmr.c
Previous file: linux/net/ipv4/ip_sockglue.c
Back to the patch index
Back to the overall index
- Lines: 151
- Date:
Sun Mar 21 07:22:00 1999
- Orig file:
v2.2.3/linux/net/ipv4/ipip.c
- Orig date:
Mon Oct 5 13:13:48 1998
diff -u --recursive --new-file v2.2.3/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.24 1998/10/03 09:37:35 davem Exp $
+ * Version: $Id: ipip.c,v 1.25 1999/03/21 05:22:43 davem Exp $
*
* Authors:
* Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95
@@ -157,6 +157,49 @@
return NULL;
}
+static struct ip_tunnel **ipip_bucket(struct ip_tunnel *t)
+{
+ u32 remote = t->parms.iph.daddr;
+ u32 local = t->parms.iph.saddr;
+ unsigned h = 0;
+ int prio = 0;
+
+ if (remote) {
+ prio |= 2;
+ h ^= HASH(remote);
+ }
+ if (local) {
+ prio |= 1;
+ h ^= HASH(local);
+ }
+ return &tunnels[prio][h];
+}
+
+
+static void ipip_tunnel_unlink(struct ip_tunnel *t)
+{
+ struct ip_tunnel **tp;
+
+ for (tp = ipip_bucket(t); *tp; tp = &(*tp)->next) {
+ if (t == *tp) {
+ net_serialize_enter();
+ *tp = t->next;
+ net_serialize_leave();
+ break;
+ }
+ }
+}
+
+static void ipip_tunnel_link(struct ip_tunnel *t)
+{
+ struct ip_tunnel **tp = ipip_bucket(t);
+
+ net_serialize_enter();
+ t->next = *tp;
+ *tp = t;
+ net_serialize_leave();
+}
+
struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int create)
{
u32 remote = parms->iph.daddr;
@@ -208,10 +251,7 @@
if (register_netdevice(dev) < 0)
goto failed;
- start_bh_atomic();
- nt->next = t;
- *tp = nt;
- end_bh_atomic();
+ ipip_tunnel_link(nt);
/* Do not decrement MOD_USE_COUNT here. */
return nt;
@@ -221,39 +261,20 @@
return NULL;
}
+
static void ipip_tunnel_destroy(struct device *dev)
{
- struct ip_tunnel *t, **tp;
- struct ip_tunnel *t0 = (struct ip_tunnel*)dev->priv;
- u32 remote = t0->parms.iph.daddr;
- u32 local = t0->parms.iph.saddr;
- unsigned h = 0;
- int prio = 0;
-
if (dev == &ipip_fb_tunnel_dev) {
+ net_serialize_enter();
tunnels_wc[0] = NULL;
- return;
- }
-
- if (remote) {
- prio |= 2;
- h ^= HASH(remote);
- }
- if (local) {
- prio |= 1;
- h ^= HASH(local);
- }
- for (tp = &tunnels[prio][h]; (t = *tp) != NULL; tp = &t->next) {
- if (t == t0) {
- *tp = t->next;
- kfree(dev);
- MOD_DEC_USE_COUNT;
- break;
- }
+ net_serialize_leave();
+ } else {
+ ipip_tunnel_unlink((struct ip_tunnel*)dev->priv);
+ kfree(dev);
+ MOD_DEC_USE_COUNT;
}
}
-
void ipip_err(struct sk_buff *skb, unsigned char *dp, int len)
{
#ifndef I_WISH_WORLD_WERE_PERFECT
@@ -641,6 +662,32 @@
p.iph.frag_off |= __constant_htons(IP_DF);
t = ipip_tunnel_locate(&p, cmd == SIOCADDTUNNEL);
+
+ if (dev != &ipip_fb_tunnel_dev && cmd == SIOCCHGTUNNEL &&
+ t != &ipip_fb_tunnel) {
+ if (t != NULL) {
+ if (t->dev != dev) {
+ err = -EEXIST;
+ break;
+ }
+ } else {
+ if (((dev->flags&IFF_POINTOPOINT) && !p.iph.daddr) ||
+ (!(dev->flags&IFF_POINTOPOINT) && p.iph.daddr)) {
+ err = -EINVAL;
+ 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);
+ }
+ }
if (t) {
err = 0;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)