aboutsummaryrefslogtreecommitdiffstats
path: root/net/econet
diff options
context:
space:
mode:
Diffstat (limited to 'net/econet')
-rw-r--r--net/econet/af_econet.c140
1 files changed, 85 insertions, 55 deletions
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index 0c4c83bb2a59..868265619dbb 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -42,6 +42,7 @@
42#include <linux/spinlock.h> 42#include <linux/spinlock.h>
43#include <linux/rcupdate.h> 43#include <linux/rcupdate.h>
44#include <linux/bitops.h> 44#include <linux/bitops.h>
45#include <linux/mutex.h>
45 46
46#include <asm/uaccess.h> 47#include <asm/uaccess.h>
47#include <asm/system.h> 48#include <asm/system.h>
@@ -49,6 +50,7 @@
49static const struct proto_ops econet_ops; 50static const struct proto_ops econet_ops;
50static struct hlist_head econet_sklist; 51static struct hlist_head econet_sklist;
51static DEFINE_RWLOCK(econet_lock); 52static DEFINE_RWLOCK(econet_lock);
53static DEFINE_MUTEX(econet_mutex);
52 54
53/* Since there are only 256 possible network numbers (or fewer, depends 55/* Since there are only 256 possible network numbers (or fewer, depends
54 how you count) it makes sense to use a simple lookup table. */ 56 how you count) it makes sense to use a simple lookup table. */
@@ -124,6 +126,8 @@ static int econet_recvmsg(struct kiocb *iocb, struct socket *sock,
124 126
125 msg->msg_namelen = sizeof(struct sockaddr_ec); 127 msg->msg_namelen = sizeof(struct sockaddr_ec);
126 128
129 mutex_lock(&econet_mutex);
130
127 /* 131 /*
128 * Call the generic datagram receiver. This handles all sorts 132 * Call the generic datagram receiver. This handles all sorts
129 * of horrible races and re-entrancy so we can forget about it 133 * of horrible races and re-entrancy so we can forget about it
@@ -174,6 +178,7 @@ static int econet_recvmsg(struct kiocb *iocb, struct socket *sock,
174out_free: 178out_free:
175 skb_free_datagram(sk, skb); 179 skb_free_datagram(sk, skb);
176out: 180out:
181 mutex_unlock(&econet_mutex);
177 return err; 182 return err;
178} 183}
179 184
@@ -184,8 +189,8 @@ out:
184static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) 189static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
185{ 190{
186 struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr; 191 struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
187 struct sock *sk=sock->sk; 192 struct sock *sk;
188 struct econet_sock *eo = ec_sk(sk); 193 struct econet_sock *eo;
189 194
190 /* 195 /*
191 * Check legality 196 * Check legality
@@ -195,11 +200,18 @@ static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len
195 sec->sec_family != AF_ECONET) 200 sec->sec_family != AF_ECONET)
196 return -EINVAL; 201 return -EINVAL;
197 202
203 mutex_lock(&econet_mutex);
204
205 sk = sock->sk;
206 eo = ec_sk(sk);
207
198 eo->cb = sec->cb; 208 eo->cb = sec->cb;
199 eo->port = sec->port; 209 eo->port = sec->port;
200 eo->station = sec->addr.station; 210 eo->station = sec->addr.station;
201 eo->net = sec->addr.net; 211 eo->net = sec->addr.net;
202 212
213 mutex_unlock(&econet_mutex);
214
203 return 0; 215 return 0;
204} 216}
205 217
@@ -284,6 +296,8 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
284 * Get and verify the address. 296 * Get and verify the address.
285 */ 297 */
286 298
299 mutex_lock(&econet_mutex);
300
287 if (saddr == NULL) { 301 if (saddr == NULL) {
288 struct econet_sock *eo = ec_sk(sk); 302 struct econet_sock *eo = ec_sk(sk);
289 303
@@ -292,8 +306,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
292 port = eo->port; 306 port = eo->port;
293 cb = eo->cb; 307 cb = eo->cb;
294 } else { 308 } else {
295 if (msg->msg_namelen < sizeof(struct sockaddr_ec)) 309 if (msg->msg_namelen < sizeof(struct sockaddr_ec)) {
310 mutex_unlock(&econet_mutex);
296 return -EINVAL; 311 return -EINVAL;
312 }
297 addr.station = saddr->addr.station; 313 addr.station = saddr->addr.station;
298 addr.net = saddr->addr.net; 314 addr.net = saddr->addr.net;
299 port = saddr->port; 315 port = saddr->port;
@@ -304,19 +320,21 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
304 dev = net2dev_map[addr.net]; 320 dev = net2dev_map[addr.net];
305 321
306 /* If not directly reachable, use some default */ 322 /* If not directly reachable, use some default */
307 if (dev == NULL) 323 if (dev == NULL) {
308 {
309 dev = net2dev_map[0]; 324 dev = net2dev_map[0];
310 /* No interfaces at all? */ 325 /* No interfaces at all? */
311 if (dev == NULL) 326 if (dev == NULL) {
327 mutex_unlock(&econet_mutex);
312 return -ENETDOWN; 328 return -ENETDOWN;
329 }
313 } 330 }
314 331
315 if (len + 15 > dev->mtu) 332 if (len + 15 > dev->mtu) {
333 mutex_unlock(&econet_mutex);
316 return -EMSGSIZE; 334 return -EMSGSIZE;
335 }
317 336
318 if (dev->type == ARPHRD_ECONET) 337 if (dev->type == ARPHRD_ECONET) {
319 {
320 /* Real hardware Econet. We're not worthy etc. */ 338 /* Real hardware Econet. We're not worthy etc. */
321#ifdef CONFIG_ECONET_NATIVE 339#ifdef CONFIG_ECONET_NATIVE
322 unsigned short proto = 0; 340 unsigned short proto = 0;
@@ -374,6 +392,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
374 392
375 dev_queue_xmit(skb); 393 dev_queue_xmit(skb);
376 dev_put(dev); 394 dev_put(dev);
395 mutex_unlock(&econet_mutex);
377 return(len); 396 return(len);
378 397
379 out_free: 398 out_free:
@@ -384,14 +403,18 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
384#else 403#else
385 err = -EPROTOTYPE; 404 err = -EPROTOTYPE;
386#endif 405#endif
406 mutex_unlock(&econet_mutex);
407
387 return err; 408 return err;
388 } 409 }
389 410
390#ifdef CONFIG_ECONET_AUNUDP 411#ifdef CONFIG_ECONET_AUNUDP
391 /* AUN virtual Econet. */ 412 /* AUN virtual Econet. */
392 413
393 if (udpsock == NULL) 414 if (udpsock == NULL) {
415 mutex_unlock(&econet_mutex);
394 return -ENETDOWN; /* No socket - can't send */ 416 return -ENETDOWN; /* No socket - can't send */
417 }
395 418
396 /* Make up a UDP datagram and hand it off to some higher intellect. */ 419 /* Make up a UDP datagram and hand it off to some higher intellect. */
397 420
@@ -438,8 +461,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
438 void __user *base = msg->msg_iov[i].iov_base; 461 void __user *base = msg->msg_iov[i].iov_base;
439 size_t len = msg->msg_iov[i].iov_len; 462 size_t len = msg->msg_iov[i].iov_len;
440 /* Check it now since we switch to KERNEL_DS later. */ 463 /* Check it now since we switch to KERNEL_DS later. */
441 if (!access_ok(VERIFY_READ, base, len)) 464 if (!access_ok(VERIFY_READ, base, len)) {
465 mutex_unlock(&econet_mutex);
442 return -EFAULT; 466 return -EFAULT;
467 }
443 iov[i+1].iov_base = base; 468 iov[i+1].iov_base = base;
444 iov[i+1].iov_len = len; 469 iov[i+1].iov_len = len;
445 size += len; 470 size += len;
@@ -447,8 +472,11 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
447 472
448 /* Get a skbuff (no data, just holds our cb information) */ 473 /* Get a skbuff (no data, just holds our cb information) */
449 if ((skb = sock_alloc_send_skb(sk, 0, 474 if ((skb = sock_alloc_send_skb(sk, 0,
450 msg->msg_flags & MSG_DONTWAIT, &err)) == NULL) 475 msg->msg_flags & MSG_DONTWAIT,
476 &err)) == NULL) {
477 mutex_unlock(&econet_mutex);
451 return err; 478 return err;
479 }
452 480
453 eb = (struct ec_cb *)&skb->cb; 481 eb = (struct ec_cb *)&skb->cb;
454 482
@@ -475,6 +503,8 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
475#else 503#else
476 err = -EPROTOTYPE; 504 err = -EPROTOTYPE;
477#endif 505#endif
506 mutex_unlock(&econet_mutex);
507
478 return err; 508 return err;
479} 509}
480 510
@@ -485,18 +515,25 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
485static int econet_getname(struct socket *sock, struct sockaddr *uaddr, 515static int econet_getname(struct socket *sock, struct sockaddr *uaddr,
486 int *uaddr_len, int peer) 516 int *uaddr_len, int peer)
487{ 517{
488 struct sock *sk = sock->sk; 518 struct sock *sk;
489 struct econet_sock *eo = ec_sk(sk); 519 struct econet_sock *eo;
490 struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr; 520 struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
491 521
492 if (peer) 522 if (peer)
493 return -EOPNOTSUPP; 523 return -EOPNOTSUPP;
494 524
525 mutex_lock(&econet_mutex);
526
527 sk = sock->sk;
528 eo = ec_sk(sk);
529
495 sec->sec_family = AF_ECONET; 530 sec->sec_family = AF_ECONET;
496 sec->port = eo->port; 531 sec->port = eo->port;
497 sec->addr.station = eo->station; 532 sec->addr.station = eo->station;
498 sec->addr.net = eo->net; 533 sec->addr.net = eo->net;
499 534
535 mutex_unlock(&econet_mutex);
536
500 *uaddr_len = sizeof(*sec); 537 *uaddr_len = sizeof(*sec);
501 return 0; 538 return 0;
502} 539}
@@ -522,10 +559,13 @@ static void econet_destroy_timer(unsigned long data)
522 559
523static int econet_release(struct socket *sock) 560static int econet_release(struct socket *sock)
524{ 561{
525 struct sock *sk = sock->sk; 562 struct sock *sk;
526 563
564 mutex_lock(&econet_mutex);
565
566 sk = sock->sk;
527 if (!sk) 567 if (!sk)
528 return 0; 568 goto out_unlock;
529 569
530 econet_remove_socket(&econet_sklist, sk); 570 econet_remove_socket(&econet_sklist, sk);
531 571
@@ -549,10 +589,14 @@ static int econet_release(struct socket *sock)
549 sk->sk_timer.expires = jiffies + HZ; 589 sk->sk_timer.expires = jiffies + HZ;
550 sk->sk_timer.function = econet_destroy_timer; 590 sk->sk_timer.function = econet_destroy_timer;
551 add_timer(&sk->sk_timer); 591 add_timer(&sk->sk_timer);
552 return 0; 592
593 goto out_unlock;
553 } 594 }
554 595
555 sk_free(sk); 596 sk_free(sk);
597
598out_unlock:
599 mutex_unlock(&econet_mutex);
556 return 0; 600 return 0;
557} 601}
558 602
@@ -608,6 +652,7 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
608 struct ec_device *edev; 652 struct ec_device *edev;
609 struct net_device *dev; 653 struct net_device *dev;
610 struct sockaddr_ec *sec; 654 struct sockaddr_ec *sec;
655 int err;
611 656
612 /* 657 /*
613 * Fetch the caller's info block into kernel space 658 * Fetch the caller's info block into kernel space
@@ -621,38 +666,35 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
621 666
622 sec = (struct sockaddr_ec *)&ifr.ifr_addr; 667 sec = (struct sockaddr_ec *)&ifr.ifr_addr;
623 668
624 switch (cmd) 669 mutex_lock(&econet_mutex);
625 { 670
671 err = 0;
672 switch (cmd) {
626 case SIOCSIFADDR: 673 case SIOCSIFADDR:
627 edev = dev->ec_ptr; 674 edev = dev->ec_ptr;
628 if (edev == NULL) 675 if (edev == NULL) {
629 {
630 /* Magic up a new one. */ 676 /* Magic up a new one. */
631 edev = kmalloc(sizeof(struct ec_device), GFP_KERNEL); 677 edev = kmalloc(sizeof(struct ec_device), GFP_KERNEL);
632 if (edev == NULL) { 678 if (edev == NULL) {
633 printk("af_ec: memory squeeze.\n"); 679 err = -ENOMEM;
634 dev_put(dev); 680 break;
635 return -ENOMEM;
636 } 681 }
637 memset(edev, 0, sizeof(struct ec_device)); 682 memset(edev, 0, sizeof(struct ec_device));
638 dev->ec_ptr = edev; 683 dev->ec_ptr = edev;
639 } 684 } else
640 else
641 net2dev_map[edev->net] = NULL; 685 net2dev_map[edev->net] = NULL;
642 edev->station = sec->addr.station; 686 edev->station = sec->addr.station;
643 edev->net = sec->addr.net; 687 edev->net = sec->addr.net;
644 net2dev_map[sec->addr.net] = dev; 688 net2dev_map[sec->addr.net] = dev;
645 if (!net2dev_map[0]) 689 if (!net2dev_map[0])
646 net2dev_map[0] = dev; 690 net2dev_map[0] = dev;
647 dev_put(dev); 691 break;
648 return 0;
649 692
650 case SIOCGIFADDR: 693 case SIOCGIFADDR:
651 edev = dev->ec_ptr; 694 edev = dev->ec_ptr;
652 if (edev == NULL) 695 if (edev == NULL) {
653 { 696 err = -ENODEV;
654 dev_put(dev); 697 break;
655 return -ENODEV;
656 } 698 }
657 memset(sec, 0, sizeof(struct sockaddr_ec)); 699 memset(sec, 0, sizeof(struct sockaddr_ec));
658 sec->addr.station = edev->station; 700 sec->addr.station = edev->station;
@@ -660,12 +702,19 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
660 sec->sec_family = AF_ECONET; 702 sec->sec_family = AF_ECONET;
661 dev_put(dev); 703 dev_put(dev);
662 if (copy_to_user(arg, &ifr, sizeof(struct ifreq))) 704 if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
663 return -EFAULT; 705 err = -EFAULT;
664 return 0; 706 break;
707
708 default:
709 err = -EINVAL;
710 break;
665 } 711 }
666 712
713 mutex_unlock(&econet_mutex);
714
667 dev_put(dev); 715 dev_put(dev);
668 return -EINVAL; 716
717 return err;
669} 718}
670 719
671/* 720/*
@@ -693,26 +742,13 @@ static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg
693 return 0; 742 return 0;
694} 743}
695 744
696#ifdef CONFIG_COMPAT
697static int econet_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
698{
699 /*
700 * All ioctls provided by econet are standard. There is one gotcha, sockaddr_ec
701 * differs between 32bit and 64bit. Fortunately nobody in kernel uses portion
702 * of sockaddr which differs between 32bit and 64bit, so we do not need special
703 * handling.
704 */
705 return -ENOIOCTLCMD;
706}
707#endif
708
709static struct net_proto_family econet_family_ops = { 745static struct net_proto_family econet_family_ops = {
710 .family = PF_ECONET, 746 .family = PF_ECONET,
711 .create = econet_create, 747 .create = econet_create,
712 .owner = THIS_MODULE, 748 .owner = THIS_MODULE,
713}; 749};
714 750
715static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = { 751static const struct proto_ops econet_ops = {
716 .family = PF_ECONET, 752 .family = PF_ECONET,
717 .owner = THIS_MODULE, 753 .owner = THIS_MODULE,
718 .release = econet_release, 754 .release = econet_release,
@@ -723,9 +759,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
723 .getname = econet_getname, 759 .getname = econet_getname,
724 .poll = datagram_poll, 760 .poll = datagram_poll,
725 .ioctl = econet_ioctl, 761 .ioctl = econet_ioctl,
726#ifdef CONFIG_COMPAT
727 .compat_ioctl = econet_compat_ioctl,
728#endif
729 .listen = sock_no_listen, 762 .listen = sock_no_listen,
730 .shutdown = sock_no_shutdown, 763 .shutdown = sock_no_shutdown,
731 .setsockopt = sock_no_setsockopt, 764 .setsockopt = sock_no_setsockopt,
@@ -736,9 +769,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
736 .sendpage = sock_no_sendpage, 769 .sendpage = sock_no_sendpage,
737}; 770};
738 771
739#include <linux/smp_lock.h>
740SOCKOPS_WRAP(econet, PF_ECONET);
741
742#if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE) 772#if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE)
743/* 773/*
744 * Find the listening socket, if any, for the given data. 774 * Find the listening socket, if any, for the given data.