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