aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ipmr.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-12-08 10:55:01 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-08 10:55:01 -0500
commitd7fc02c7bae7b1cf69269992cf880a43a350cdaa (patch)
treea43d56fa72913a1cc98a0bbebe054d08581b3a7c /net/ipv4/ipmr.c
parentee1262dbc65ce0b6234a915d8432171e8d77f518 (diff)
parent28b4d5cc17c20786848cdc07b7ea237a309776bb (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1815 commits) mac80211: fix reorder buffer release iwmc3200wifi: Enable wimax core through module parameter iwmc3200wifi: Add wifi-wimax coexistence mode as a module parameter iwmc3200wifi: Coex table command does not expect a response iwmc3200wifi: Update wiwi priority table iwlwifi: driver version track kernel version iwlwifi: indicate uCode type when fail dump error/event log iwl3945: remove duplicated event logging code b43: fix two warnings ipw2100: fix rebooting hang with driver loaded cfg80211: indent regulatory messages with spaces iwmc3200wifi: fix NULL pointer dereference in pmkid update mac80211: Fix TX status reporting for injected data frames ath9k: enable 2GHz band only if the device supports it airo: Fix integer overflow warning rt2x00: Fix padding bug on L2PAD devices. WE: Fix set events not propagated b43legacy: avoid PPC fault during resume b43: avoid PPC fault during resume tcp: fix a timewait refcnt race ... Fix up conflicts due to sysctl cleanups (dead sysctl_check code and CTL_UNNUMBERED removed) in kernel/sysctl_check.c net/ipv4/sysctl_net_ipv4.c net/ipv6/addrconf.c net/sctp/sysctl.c
Diffstat (limited to 'net/ipv4/ipmr.c')
-rw-r--r--net/ipv4/ipmr.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 99508d66a642..54596f73eff5 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -275,7 +275,8 @@ failure:
275 * @notify: Set to 1, if the caller is a notifier_call 275 * @notify: Set to 1, if the caller is a notifier_call
276 */ 276 */
277 277
278static int vif_delete(struct net *net, int vifi, int notify) 278static int vif_delete(struct net *net, int vifi, int notify,
279 struct list_head *head)
279{ 280{
280 struct vif_device *v; 281 struct vif_device *v;
281 struct net_device *dev; 282 struct net_device *dev;
@@ -319,7 +320,7 @@ static int vif_delete(struct net *net, int vifi, int notify)
319 } 320 }
320 321
321 if (v->flags&(VIFF_TUNNEL|VIFF_REGISTER) && !notify) 322 if (v->flags&(VIFF_TUNNEL|VIFF_REGISTER) && !notify)
322 unregister_netdevice(dev); 323 unregister_netdevice_queue(dev, head);
323 324
324 dev_put(dev); 325 dev_put(dev);
325 return 0; 326 return 0;
@@ -469,8 +470,18 @@ static int vif_add(struct net *net, struct vifctl *vifc, int mrtsock)
469 return err; 470 return err;
470 } 471 }
471 break; 472 break;
473
474 case VIFF_USE_IFINDEX:
472 case 0: 475 case 0:
473 dev = ip_dev_find(net, vifc->vifc_lcl_addr.s_addr); 476 if (vifc->vifc_flags == VIFF_USE_IFINDEX) {
477 dev = dev_get_by_index(net, vifc->vifc_lcl_ifindex);
478 if (dev && dev->ip_ptr == NULL) {
479 dev_put(dev);
480 return -EADDRNOTAVAIL;
481 }
482 } else
483 dev = ip_dev_find(net, vifc->vifc_lcl_addr.s_addr);
484
474 if (!dev) 485 if (!dev)
475 return -EADDRNOTAVAIL; 486 return -EADDRNOTAVAIL;
476 err = dev_set_allmulti(dev, 1); 487 err = dev_set_allmulti(dev, 1);
@@ -862,14 +873,16 @@ static int ipmr_mfc_add(struct net *net, struct mfcctl *mfc, int mrtsock)
862static void mroute_clean_tables(struct net *net) 873static void mroute_clean_tables(struct net *net)
863{ 874{
864 int i; 875 int i;
876 LIST_HEAD(list);
865 877
866 /* 878 /*
867 * Shut down all active vif entries 879 * Shut down all active vif entries
868 */ 880 */
869 for (i = 0; i < net->ipv4.maxvif; i++) { 881 for (i = 0; i < net->ipv4.maxvif; i++) {
870 if (!(net->ipv4.vif_table[i].flags&VIFF_STATIC)) 882 if (!(net->ipv4.vif_table[i].flags&VIFF_STATIC))
871 vif_delete(net, i, 0); 883 vif_delete(net, i, 0, &list);
872 } 884 }
885 unregister_netdevice_many(&list);
873 886
874 /* 887 /*
875 * Wipe the cache 888 * Wipe the cache
@@ -948,7 +961,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
948 switch (optname) { 961 switch (optname) {
949 case MRT_INIT: 962 case MRT_INIT:
950 if (sk->sk_type != SOCK_RAW || 963 if (sk->sk_type != SOCK_RAW ||
951 inet_sk(sk)->num != IPPROTO_IGMP) 964 inet_sk(sk)->inet_num != IPPROTO_IGMP)
952 return -EOPNOTSUPP; 965 return -EOPNOTSUPP;
953 if (optlen != sizeof(int)) 966 if (optlen != sizeof(int))
954 return -ENOPROTOOPT; 967 return -ENOPROTOOPT;
@@ -985,7 +998,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
985 if (optname == MRT_ADD_VIF) { 998 if (optname == MRT_ADD_VIF) {
986 ret = vif_add(net, &vif, sk == net->ipv4.mroute_sk); 999 ret = vif_add(net, &vif, sk == net->ipv4.mroute_sk);
987 } else { 1000 } else {
988 ret = vif_delete(net, vif.vifc_vifi, 0); 1001 ret = vif_delete(net, vif.vifc_vifi, 0, NULL);
989 } 1002 }
990 rtnl_unlock(); 1003 rtnl_unlock();
991 return ret; 1004 return ret;
@@ -1148,6 +1161,7 @@ static int ipmr_device_event(struct notifier_block *this, unsigned long event, v
1148 struct net *net = dev_net(dev); 1161 struct net *net = dev_net(dev);
1149 struct vif_device *v; 1162 struct vif_device *v;
1150 int ct; 1163 int ct;
1164 LIST_HEAD(list);
1151 1165
1152 if (!net_eq(dev_net(dev), net)) 1166 if (!net_eq(dev_net(dev), net))
1153 return NOTIFY_DONE; 1167 return NOTIFY_DONE;
@@ -1157,8 +1171,9 @@ static int ipmr_device_event(struct notifier_block *this, unsigned long event, v
1157 v = &net->ipv4.vif_table[0]; 1171 v = &net->ipv4.vif_table[0];
1158 for (ct = 0; ct < net->ipv4.maxvif; ct++, v++) { 1172 for (ct = 0; ct < net->ipv4.maxvif; ct++, v++) {
1159 if (v->dev == dev) 1173 if (v->dev == dev)
1160 vif_delete(net, ct, 1); 1174 vif_delete(net, ct, 1, &list);
1161 } 1175 }
1176 unregister_netdevice_many(&list);
1162 return NOTIFY_DONE; 1177 return NOTIFY_DONE;
1163} 1178}
1164 1179