diff options
Diffstat (limited to 'net/ipv4/ipmr.c')
-rw-r--r-- | net/ipv4/ipmr.c | 22 |
1 files changed, 14 insertions, 8 deletions
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 2f4d8afd067c..c9ab47b966b5 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -184,6 +184,7 @@ struct net_device *ipmr_new_tunnel(struct vifctl *v) | |||
184 | 184 | ||
185 | if (dev_open(dev)) | 185 | if (dev_open(dev)) |
186 | goto failure; | 186 | goto failure; |
187 | dev_hold(dev); | ||
187 | } | 188 | } |
188 | } | 189 | } |
189 | return dev; | 190 | return dev; |
@@ -250,6 +251,8 @@ static struct net_device *ipmr_reg_vif(void) | |||
250 | if (dev_open(dev)) | 251 | if (dev_open(dev)) |
251 | goto failure; | 252 | goto failure; |
252 | 253 | ||
254 | dev_hold(dev); | ||
255 | |||
253 | return dev; | 256 | return dev; |
254 | 257 | ||
255 | failure: | 258 | failure: |
@@ -264,9 +267,10 @@ failure: | |||
264 | 267 | ||
265 | /* | 268 | /* |
266 | * Delete a VIF entry | 269 | * Delete a VIF entry |
270 | * @notify: Set to 1, if the caller is a notifier_call | ||
267 | */ | 271 | */ |
268 | 272 | ||
269 | static int vif_delete(int vifi) | 273 | static int vif_delete(int vifi, int notify) |
270 | { | 274 | { |
271 | struct vif_device *v; | 275 | struct vif_device *v; |
272 | struct net_device *dev; | 276 | struct net_device *dev; |
@@ -309,7 +313,7 @@ static int vif_delete(int vifi) | |||
309 | ip_rt_multicast_event(in_dev); | 313 | ip_rt_multicast_event(in_dev); |
310 | } | 314 | } |
311 | 315 | ||
312 | if (v->flags&(VIFF_TUNNEL|VIFF_REGISTER)) | 316 | if (v->flags&(VIFF_TUNNEL|VIFF_REGISTER) && !notify) |
313 | unregister_netdevice(dev); | 317 | unregister_netdevice(dev); |
314 | 318 | ||
315 | dev_put(dev); | 319 | dev_put(dev); |
@@ -435,6 +439,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock) | |||
435 | err = dev_set_allmulti(dev, 1); | 439 | err = dev_set_allmulti(dev, 1); |
436 | if (err) { | 440 | if (err) { |
437 | unregister_netdevice(dev); | 441 | unregister_netdevice(dev); |
442 | dev_put(dev); | ||
438 | return err; | 443 | return err; |
439 | } | 444 | } |
440 | break; | 445 | break; |
@@ -446,6 +451,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock) | |||
446 | err = dev_set_allmulti(dev, 1); | 451 | err = dev_set_allmulti(dev, 1); |
447 | if (err) { | 452 | if (err) { |
448 | ipmr_del_tunnel(dev, vifc); | 453 | ipmr_del_tunnel(dev, vifc); |
454 | dev_put(dev); | ||
449 | return err; | 455 | return err; |
450 | } | 456 | } |
451 | break; | 457 | break; |
@@ -453,10 +459,11 @@ static int vif_add(struct vifctl *vifc, int mrtsock) | |||
453 | dev = ip_dev_find(&init_net, vifc->vifc_lcl_addr.s_addr); | 459 | dev = ip_dev_find(&init_net, vifc->vifc_lcl_addr.s_addr); |
454 | if (!dev) | 460 | if (!dev) |
455 | return -EADDRNOTAVAIL; | 461 | return -EADDRNOTAVAIL; |
456 | dev_put(dev); | ||
457 | err = dev_set_allmulti(dev, 1); | 462 | err = dev_set_allmulti(dev, 1); |
458 | if (err) | 463 | if (err) { |
464 | dev_put(dev); | ||
459 | return err; | 465 | return err; |
466 | } | ||
460 | break; | 467 | break; |
461 | default: | 468 | default: |
462 | return -EINVAL; | 469 | return -EINVAL; |
@@ -487,7 +494,6 @@ static int vif_add(struct vifctl *vifc, int mrtsock) | |||
487 | 494 | ||
488 | /* And finish update writing critical data */ | 495 | /* And finish update writing critical data */ |
489 | write_lock_bh(&mrt_lock); | 496 | write_lock_bh(&mrt_lock); |
490 | dev_hold(dev); | ||
491 | v->dev=dev; | 497 | v->dev=dev; |
492 | #ifdef CONFIG_IP_PIMSM | 498 | #ifdef CONFIG_IP_PIMSM |
493 | if (v->flags&VIFF_REGISTER) | 499 | if (v->flags&VIFF_REGISTER) |
@@ -834,7 +840,7 @@ static void mroute_clean_tables(struct sock *sk) | |||
834 | */ | 840 | */ |
835 | for (i=0; i<maxvif; i++) { | 841 | for (i=0; i<maxvif; i++) { |
836 | if (!(vif_table[i].flags&VIFF_STATIC)) | 842 | if (!(vif_table[i].flags&VIFF_STATIC)) |
837 | vif_delete(i); | 843 | vif_delete(i, 0); |
838 | } | 844 | } |
839 | 845 | ||
840 | /* | 846 | /* |
@@ -947,7 +953,7 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char __user *optval,int opt | |||
947 | if (optname==MRT_ADD_VIF) { | 953 | if (optname==MRT_ADD_VIF) { |
948 | ret = vif_add(&vif, sk==mroute_socket); | 954 | ret = vif_add(&vif, sk==mroute_socket); |
949 | } else { | 955 | } else { |
950 | ret = vif_delete(vif.vifc_vifi); | 956 | ret = vif_delete(vif.vifc_vifi, 0); |
951 | } | 957 | } |
952 | rtnl_unlock(); | 958 | rtnl_unlock(); |
953 | return ret; | 959 | return ret; |
@@ -1126,7 +1132,7 @@ static int ipmr_device_event(struct notifier_block *this, unsigned long event, v | |||
1126 | v=&vif_table[0]; | 1132 | v=&vif_table[0]; |
1127 | for (ct=0;ct<maxvif;ct++,v++) { | 1133 | for (ct=0;ct<maxvif;ct++,v++) { |
1128 | if (v->dev==dev) | 1134 | if (v->dev==dev) |
1129 | vif_delete(ct); | 1135 | vif_delete(ct, 1); |
1130 | } | 1136 | } |
1131 | return NOTIFY_DONE; | 1137 | return NOTIFY_DONE; |
1132 | } | 1138 | } |