diff options
Diffstat (limited to 'net/decnet/dn_dev.c')
-rw-r--r-- | net/decnet/dn_dev.c | 117 |
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 | ||
71 | static DEFINE_RWLOCK(dndev_lock); | 71 | static DEFINE_SPINLOCK(dndev_lock); |
72 | static struct net_device *decnet_default_device; | 72 | static struct net_device *decnet_default_device; |
73 | static BLOCKING_NOTIFIER_HEAD(dnaddr_chain); | 73 | static 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 | ||
167 | static int dn_forwarding_proc(ctl_table *, int, | 161 | static int dn_forwarding_proc(ctl_table *, int, |
168 | void __user *, size_t *, loff_t *); | 162 | void __user *, size_t *, loff_t *); |
169 | static int dn_forwarding_sysctl(ctl_table *table, | ||
170 | void __user *oldval, size_t __user *oldlenp, | ||
171 | void __user *newval, size_t newlen); | ||
172 | |||
173 | static struct dn_dev_sysctl_table { | 163 | static 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 | ||
320 | static 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 */ |
359 | static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms) | 301 | static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms) |
360 | { | 302 | { |
@@ -557,7 +499,8 @@ rarok: | |||
557 | struct net_device *dn_dev_get_default(void) | 499 | struct 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 | ||
590 | static void dn_dev_check_default(struct net_device *dev) | 536 | static 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 | */ | ||
603 | static struct dn_dev *dn_dev_by_index(int ifindex) | 553 | static 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(); | ||
836 | out: | 789 | out: |
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(); |
855 | last_chance: | 808 | last_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 | ||
1323 | static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos) | 1274 | static 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 | ||
1366 | static void dn_dev_seq_stop(struct seq_file *seq, void *v) | 1317 | static 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 | ||
1372 | static char *dn_type2asc(char type) | 1323 | static char *dn_type2asc(char type) |