aboutsummaryrefslogtreecommitdiffstats
path: root/net/decnet/dn_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/decnet/dn_dev.c')
-rw-r--r--net/decnet/dn_dev.c117
1 files changed, 34 insertions, 83 deletions
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index 6e1f085db06a..238af093495b 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -68,7 +68,7 @@ extern struct neigh_table dn_neigh_table;
68 */ 68 */
69__le16 decnet_address = 0; 69__le16 decnet_address = 0;
70 70
71static DEFINE_RWLOCK(dndev_lock); 71static DEFINE_SPINLOCK(dndev_lock);
72static struct net_device *decnet_default_device; 72static struct net_device *decnet_default_device;
73static BLOCKING_NOTIFIER_HEAD(dnaddr_chain); 73static BLOCKING_NOTIFIER_HEAD(dnaddr_chain);
74 74
@@ -89,7 +89,6 @@ static struct dn_dev_parms dn_dev_list[] = {
89 .t2 = 1, 89 .t2 = 1,
90 .t3 = 10, 90 .t3 = 10,
91 .name = "ethernet", 91 .name = "ethernet",
92 .ctl_name = NET_DECNET_CONF_ETHER,
93 .up = dn_eth_up, 92 .up = dn_eth_up,
94 .down = dn_eth_down, 93 .down = dn_eth_down,
95 .timer3 = dn_send_brd_hello, 94 .timer3 = dn_send_brd_hello,
@@ -101,7 +100,6 @@ static struct dn_dev_parms dn_dev_list[] = {
101 .t2 = 1, 100 .t2 = 1,
102 .t3 = 10, 101 .t3 = 10,
103 .name = "ipgre", 102 .name = "ipgre",
104 .ctl_name = NET_DECNET_CONF_GRE,
105 .timer3 = dn_send_brd_hello, 103 .timer3 = dn_send_brd_hello,
106}, 104},
107#if 0 105#if 0
@@ -112,7 +110,6 @@ static struct dn_dev_parms dn_dev_list[] = {
112 .t2 = 1, 110 .t2 = 1,
113 .t3 = 120, 111 .t3 = 120,
114 .name = "x25", 112 .name = "x25",
115 .ctl_name = NET_DECNET_CONF_X25,
116 .timer3 = dn_send_ptp_hello, 113 .timer3 = dn_send_ptp_hello,
117}, 114},
118#endif 115#endif
@@ -124,7 +121,6 @@ static struct dn_dev_parms dn_dev_list[] = {
124 .t2 = 1, 121 .t2 = 1,
125 .t3 = 10, 122 .t3 = 10,
126 .name = "ppp", 123 .name = "ppp",
127 .ctl_name = NET_DECNET_CONF_PPP,
128 .timer3 = dn_send_brd_hello, 124 .timer3 = dn_send_brd_hello,
129}, 125},
130#endif 126#endif
@@ -135,7 +131,6 @@ static struct dn_dev_parms dn_dev_list[] = {
135 .t2 = 1, 131 .t2 = 1,
136 .t3 = 120, 132 .t3 = 120,
137 .name = "ddcmp", 133 .name = "ddcmp",
138 .ctl_name = NET_DECNET_CONF_DDCMP,
139 .timer3 = dn_send_ptp_hello, 134 .timer3 = dn_send_ptp_hello,
140}, 135},
141{ 136{
@@ -145,7 +140,6 @@ static struct dn_dev_parms dn_dev_list[] = {
145 .t2 = 1, 140 .t2 = 1,
146 .t3 = 10, 141 .t3 = 10,
147 .name = "loopback", 142 .name = "loopback",
148 .ctl_name = NET_DECNET_CONF_LOOPBACK,
149 .timer3 = dn_send_brd_hello, 143 .timer3 = dn_send_brd_hello,
150} 144}
151}; 145};
@@ -166,10 +160,6 @@ static int max_priority[] = { 127 }; /* From DECnet spec */
166 160
167static int dn_forwarding_proc(ctl_table *, int, 161static int dn_forwarding_proc(ctl_table *, int,
168 void __user *, size_t *, loff_t *); 162 void __user *, size_t *, loff_t *);
169static int dn_forwarding_sysctl(ctl_table *table,
170 void __user *oldval, size_t __user *oldlenp,
171 void __user *newval, size_t newlen);
172
173static struct dn_dev_sysctl_table { 163static struct dn_dev_sysctl_table {
174 struct ctl_table_header *sysctl_header; 164 struct ctl_table_header *sysctl_header;
175 ctl_table dn_dev_vars[5]; 165 ctl_table dn_dev_vars[5];
@@ -177,44 +167,36 @@ static struct dn_dev_sysctl_table {
177 NULL, 167 NULL,
178 { 168 {
179 { 169 {
180 .ctl_name = NET_DECNET_CONF_DEV_FORWARDING,
181 .procname = "forwarding", 170 .procname = "forwarding",
182 .data = (void *)DN_DEV_PARMS_OFFSET(forwarding), 171 .data = (void *)DN_DEV_PARMS_OFFSET(forwarding),
183 .maxlen = sizeof(int), 172 .maxlen = sizeof(int),
184 .mode = 0644, 173 .mode = 0644,
185 .proc_handler = dn_forwarding_proc, 174 .proc_handler = dn_forwarding_proc,
186 .strategy = dn_forwarding_sysctl,
187 }, 175 },
188 { 176 {
189 .ctl_name = NET_DECNET_CONF_DEV_PRIORITY,
190 .procname = "priority", 177 .procname = "priority",
191 .data = (void *)DN_DEV_PARMS_OFFSET(priority), 178 .data = (void *)DN_DEV_PARMS_OFFSET(priority),
192 .maxlen = sizeof(int), 179 .maxlen = sizeof(int),
193 .mode = 0644, 180 .mode = 0644,
194 .proc_handler = proc_dointvec_minmax, 181 .proc_handler = proc_dointvec_minmax,
195 .strategy = sysctl_intvec,
196 .extra1 = &min_priority, 182 .extra1 = &min_priority,
197 .extra2 = &max_priority 183 .extra2 = &max_priority
198 }, 184 },
199 { 185 {
200 .ctl_name = NET_DECNET_CONF_DEV_T2,
201 .procname = "t2", 186 .procname = "t2",
202 .data = (void *)DN_DEV_PARMS_OFFSET(t2), 187 .data = (void *)DN_DEV_PARMS_OFFSET(t2),
203 .maxlen = sizeof(int), 188 .maxlen = sizeof(int),
204 .mode = 0644, 189 .mode = 0644,
205 .proc_handler = proc_dointvec_minmax, 190 .proc_handler = proc_dointvec_minmax,
206 .strategy = sysctl_intvec,
207 .extra1 = &min_t2, 191 .extra1 = &min_t2,
208 .extra2 = &max_t2 192 .extra2 = &max_t2
209 }, 193 },
210 { 194 {
211 .ctl_name = NET_DECNET_CONF_DEV_T3,
212 .procname = "t3", 195 .procname = "t3",
213 .data = (void *)DN_DEV_PARMS_OFFSET(t3), 196 .data = (void *)DN_DEV_PARMS_OFFSET(t3),
214 .maxlen = sizeof(int), 197 .maxlen = sizeof(int),
215 .mode = 0644, 198 .mode = 0644,
216 .proc_handler = proc_dointvec_minmax, 199 .proc_handler = proc_dointvec_minmax,
217 .strategy = sysctl_intvec,
218 .extra1 = &min_t3, 200 .extra1 = &min_t3,
219 .extra2 = &max_t3 201 .extra2 = &max_t3
220 }, 202 },
@@ -230,9 +212,9 @@ static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *
230#define DN_CTL_PATH_DEV 3 212#define DN_CTL_PATH_DEV 3
231 213
232 struct ctl_path dn_ctl_path[] = { 214 struct ctl_path dn_ctl_path[] = {
233 { .procname = "net", .ctl_name = CTL_NET, }, 215 { .procname = "net", },
234 { .procname = "decnet", .ctl_name = NET_DECNET, }, 216 { .procname = "decnet", },
235 { .procname = "conf", .ctl_name = NET_DECNET_CONF, }, 217 { .procname = "conf", },
236 { /* to be set */ }, 218 { /* to be set */ },
237 { }, 219 { },
238 }; 220 };
@@ -248,10 +230,8 @@ static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *
248 230
249 if (dev) { 231 if (dev) {
250 dn_ctl_path[DN_CTL_PATH_DEV].procname = dev->name; 232 dn_ctl_path[DN_CTL_PATH_DEV].procname = dev->name;
251 dn_ctl_path[DN_CTL_PATH_DEV].ctl_name = dev->ifindex;
252 } else { 233 } else {
253 dn_ctl_path[DN_CTL_PATH_DEV].procname = parms->name; 234 dn_ctl_path[DN_CTL_PATH_DEV].procname = parms->name;
254 dn_ctl_path[DN_CTL_PATH_DEV].ctl_name = parms->ctl_name;
255 } 235 }
256 236
257 t->dn_dev_vars[0].extra1 = (void *)dev; 237 t->dn_dev_vars[0].extra1 = (void *)dev;
@@ -317,44 +297,6 @@ static int dn_forwarding_proc(ctl_table *table, int write,
317#endif 297#endif
318} 298}
319 299
320static int dn_forwarding_sysctl(ctl_table *table,
321 void __user *oldval, size_t __user *oldlenp,
322 void __user *newval, size_t newlen)
323{
324#ifdef CONFIG_DECNET_ROUTER
325 struct net_device *dev = table->extra1;
326 struct dn_dev *dn_db;
327 int value;
328
329 if (table->extra1 == NULL)
330 return -EINVAL;
331
332 dn_db = dev->dn_ptr;
333
334 if (newval && newlen) {
335 if (newlen != sizeof(int))
336 return -EINVAL;
337
338 if (get_user(value, (int __user *)newval))
339 return -EFAULT;
340 if (value < 0)
341 return -EINVAL;
342 if (value > 2)
343 return -EINVAL;
344
345 if (dn_db->parms.down)
346 dn_db->parms.down(dev);
347 dn_db->parms.forwarding = value;
348 if (dn_db->parms.up)
349 dn_db->parms.up(dev);
350 }
351
352 return 0;
353#else
354 return -EINVAL;
355#endif
356}
357
358#else /* CONFIG_SYSCTL */ 300#else /* CONFIG_SYSCTL */
359static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms) 301static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms)
360{ 302{
@@ -557,7 +499,8 @@ rarok:
557struct net_device *dn_dev_get_default(void) 499struct net_device *dn_dev_get_default(void)
558{ 500{
559 struct net_device *dev; 501 struct net_device *dev;
560 read_lock(&dndev_lock); 502
503 spin_lock(&dndev_lock);
561 dev = decnet_default_device; 504 dev = decnet_default_device;
562 if (dev) { 505 if (dev) {
563 if (dev->dn_ptr) 506 if (dev->dn_ptr)
@@ -565,7 +508,8 @@ struct net_device *dn_dev_get_default(void)
565 else 508 else
566 dev = NULL; 509 dev = NULL;
567 } 510 }
568 read_unlock(&dndev_lock); 511 spin_unlock(&dndev_lock);
512
569 return dev; 513 return dev;
570} 514}
571 515
@@ -575,13 +519,15 @@ int dn_dev_set_default(struct net_device *dev, int force)
575 int rv = -EBUSY; 519 int rv = -EBUSY;
576 if (!dev->dn_ptr) 520 if (!dev->dn_ptr)
577 return -ENODEV; 521 return -ENODEV;
578 write_lock(&dndev_lock); 522
523 spin_lock(&dndev_lock);
579 if (force || decnet_default_device == NULL) { 524 if (force || decnet_default_device == NULL) {
580 old = decnet_default_device; 525 old = decnet_default_device;
581 decnet_default_device = dev; 526 decnet_default_device = dev;
582 rv = 0; 527 rv = 0;
583 } 528 }
584 write_unlock(&dndev_lock); 529 spin_unlock(&dndev_lock);
530
585 if (old) 531 if (old)
586 dev_put(old); 532 dev_put(old);
587 return rv; 533 return rv;
@@ -589,26 +535,29 @@ int dn_dev_set_default(struct net_device *dev, int force)
589 535
590static void dn_dev_check_default(struct net_device *dev) 536static void dn_dev_check_default(struct net_device *dev)
591{ 537{
592 write_lock(&dndev_lock); 538 spin_lock(&dndev_lock);
593 if (dev == decnet_default_device) { 539 if (dev == decnet_default_device) {
594 decnet_default_device = NULL; 540 decnet_default_device = NULL;
595 } else { 541 } else {
596 dev = NULL; 542 dev = NULL;
597 } 543 }
598 write_unlock(&dndev_lock); 544 spin_unlock(&dndev_lock);
545
599 if (dev) 546 if (dev)
600 dev_put(dev); 547 dev_put(dev);
601} 548}
602 549
550/*
551 * Called with RTNL
552 */
603static struct dn_dev *dn_dev_by_index(int ifindex) 553static struct dn_dev *dn_dev_by_index(int ifindex)
604{ 554{
605 struct net_device *dev; 555 struct net_device *dev;
606 struct dn_dev *dn_dev = NULL; 556 struct dn_dev *dn_dev = NULL;
607 dev = dev_get_by_index(&init_net, ifindex); 557
608 if (dev) { 558 dev = __dev_get_by_index(&init_net, ifindex);
559 if (dev)
609 dn_dev = dev->dn_ptr; 560 dn_dev = dev->dn_ptr;
610 dev_put(dev);
611 }
612 561
613 return dn_dev; 562 return dn_dev;
614} 563}
@@ -629,7 +578,7 @@ static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
629 struct dn_ifaddr *ifa, **ifap; 578 struct dn_ifaddr *ifa, **ifap;
630 int err = -EINVAL; 579 int err = -EINVAL;
631 580
632 if (net != &init_net) 581 if (!net_eq(net, &init_net))
633 goto errout; 582 goto errout;
634 583
635 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, dn_ifa_policy); 584 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, dn_ifa_policy);
@@ -668,7 +617,7 @@ static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
668 struct dn_ifaddr *ifa; 617 struct dn_ifaddr *ifa;
669 int err; 618 int err;
670 619
671 if (net != &init_net) 620 if (!net_eq(net, &init_net))
672 return -EINVAL; 621 return -EINVAL;
673 622
674 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, dn_ifa_policy); 623 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, dn_ifa_policy);
@@ -782,7 +731,7 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
782 struct dn_dev *dn_db; 731 struct dn_dev *dn_db;
783 struct dn_ifaddr *ifa; 732 struct dn_ifaddr *ifa;
784 733
785 if (net != &init_net) 734 if (!net_eq(net, &init_net))
786 return 0; 735 return 0;
787 736
788 skip_ndevs = cb->args[0]; 737 skip_ndevs = cb->args[0];
@@ -826,13 +775,17 @@ static int dn_dev_get_first(struct net_device *dev, __le16 *addr)
826 struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr; 775 struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
827 struct dn_ifaddr *ifa; 776 struct dn_ifaddr *ifa;
828 int rv = -ENODEV; 777 int rv = -ENODEV;
778
829 if (dn_db == NULL) 779 if (dn_db == NULL)
830 goto out; 780 goto out;
781
782 rtnl_lock();
831 ifa = dn_db->ifa_list; 783 ifa = dn_db->ifa_list;
832 if (ifa != NULL) { 784 if (ifa != NULL) {
833 *addr = ifa->ifa_local; 785 *addr = ifa->ifa_local;
834 rv = 0; 786 rv = 0;
835 } 787 }
788 rtnl_unlock();
836out: 789out:
837 return rv; 790 return rv;
838} 791}
@@ -854,9 +807,7 @@ int dn_dev_bind_default(__le16 *addr)
854 dev = dn_dev_get_default(); 807 dev = dn_dev_get_default();
855last_chance: 808last_chance:
856 if (dev) { 809 if (dev) {
857 read_lock(&dev_base_lock);
858 rv = dn_dev_get_first(dev, addr); 810 rv = dn_dev_get_first(dev, addr);
859 read_unlock(&dev_base_lock);
860 dev_put(dev); 811 dev_put(dev);
861 if (rv == 0 || dev == init_net.loopback_dev) 812 if (rv == 0 || dev == init_net.loopback_dev)
862 return rv; 813 return rv;
@@ -1321,18 +1272,18 @@ static inline int is_dn_dev(struct net_device *dev)
1321} 1272}
1322 1273
1323static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos) 1274static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos)
1324 __acquires(&dev_base_lock) 1275 __acquires(rcu)
1325{ 1276{
1326 int i; 1277 int i;
1327 struct net_device *dev; 1278 struct net_device *dev;
1328 1279
1329 read_lock(&dev_base_lock); 1280 rcu_read_lock();
1330 1281
1331 if (*pos == 0) 1282 if (*pos == 0)
1332 return SEQ_START_TOKEN; 1283 return SEQ_START_TOKEN;
1333 1284
1334 i = 1; 1285 i = 1;
1335 for_each_netdev(&init_net, dev) { 1286 for_each_netdev_rcu(&init_net, dev) {
1336 if (!is_dn_dev(dev)) 1287 if (!is_dn_dev(dev))
1337 continue; 1288 continue;
1338 1289
@@ -1353,7 +1304,7 @@ static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
1353 if (v == SEQ_START_TOKEN) 1304 if (v == SEQ_START_TOKEN)
1354 dev = net_device_entry(&init_net.dev_base_head); 1305 dev = net_device_entry(&init_net.dev_base_head);
1355 1306
1356 for_each_netdev_continue(&init_net, dev) { 1307 for_each_netdev_continue_rcu(&init_net, dev) {
1357 if (!is_dn_dev(dev)) 1308 if (!is_dn_dev(dev))
1358 continue; 1309 continue;
1359 1310
@@ -1364,9 +1315,9 @@ static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
1364} 1315}
1365 1316
1366static void dn_dev_seq_stop(struct seq_file *seq, void *v) 1317static void dn_dev_seq_stop(struct seq_file *seq, void *v)
1367 __releases(&dev_base_lock) 1318 __releases(rcu)
1368{ 1319{
1369 read_unlock(&dev_base_lock); 1320 rcu_read_unlock();
1370} 1321}
1371 1322
1372static char *dn_type2asc(char type) 1323static char *dn_type2asc(char type)