aboutsummaryrefslogtreecommitdiffstats
path: root/net/rose/af_rose.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2007-03-12 18:53:33 -0400
committerDavid S. Miller <davem@davemloft.net>2007-03-12 18:53:33 -0400
commit2536b94a2d2e37dd6c14171d6251f63bbda47293 (patch)
tree963a1b750e0844bbd90b42b7e55c728b3abb3629 /net/rose/af_rose.c
parent6cee77dbf29e3c4c2cf2ce16621759accc76891e (diff)
[ROSE]: Socket locking is a great invention.
Especially if you actually try to do it ;-) Signed-off-by: Ralf Baechle <ralf@linux-mips.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/rose/af_rose.c')
-rw-r--r--net/rose/af_rose.c78
1 files changed, 50 insertions, 28 deletions
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 596b302d0e47..f92d5310847b 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -700,23 +700,7 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
700 unsigned char cause, diagnostic; 700 unsigned char cause, diagnostic;
701 struct net_device *dev; 701 struct net_device *dev;
702 ax25_uid_assoc *user; 702 ax25_uid_assoc *user;
703 int n; 703 int n, err = 0;
704
705 if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
706 sock->state = SS_CONNECTED;
707 return 0; /* Connect completed during a ERESTARTSYS event */
708 }
709
710 if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) {
711 sock->state = SS_UNCONNECTED;
712 return -ECONNREFUSED;
713 }
714
715 if (sk->sk_state == TCP_ESTABLISHED)
716 return -EISCONN; /* No reconnect on a seqpacket socket */
717
718 sk->sk_state = TCP_CLOSE;
719 sock->state = SS_UNCONNECTED;
720 704
721 if (addr_len != sizeof(struct sockaddr_rose) && addr_len != sizeof(struct full_sockaddr_rose)) 705 if (addr_len != sizeof(struct sockaddr_rose) && addr_len != sizeof(struct full_sockaddr_rose))
722 return -EINVAL; 706 return -EINVAL;
@@ -734,24 +718,53 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
734 if ((rose->source_ndigis + addr->srose_ndigis) > ROSE_MAX_DIGIS) 718 if ((rose->source_ndigis + addr->srose_ndigis) > ROSE_MAX_DIGIS)
735 return -EINVAL; 719 return -EINVAL;
736 720
721 lock_sock(sk);
722
723 if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
724 /* Connect completed during a ERESTARTSYS event */
725 sock->state = SS_CONNECTED;
726 goto out_release;
727 }
728
729 if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) {
730 sock->state = SS_UNCONNECTED;
731 err = -ECONNREFUSED;
732 goto out_release;
733 }
734
735 if (sk->sk_state == TCP_ESTABLISHED) {
736 /* No reconnect on a seqpacket socket */
737 err = -EISCONN;
738 goto out_release;
739 }
740
741 sk->sk_state = TCP_CLOSE;
742 sock->state = SS_UNCONNECTED;
743
737 rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, 744 rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause,
738 &diagnostic); 745 &diagnostic);
739 if (!rose->neighbour) 746 if (!rose->neighbour)
740 return -ENETUNREACH; 747 return -ENETUNREACH;
741 748
742 rose->lci = rose_new_lci(rose->neighbour); 749 rose->lci = rose_new_lci(rose->neighbour);
743 if (!rose->lci) 750 if (!rose->lci) {
744 return -ENETUNREACH; 751 err = -ENETUNREACH;
752 goto out_release;
753 }
745 754
746 if (sock_flag(sk, SOCK_ZAPPED)) { /* Must bind first - autobinding in this may or may not work */ 755 if (sock_flag(sk, SOCK_ZAPPED)) { /* Must bind first - autobinding in this may or may not work */
747 sock_reset_flag(sk, SOCK_ZAPPED); 756 sock_reset_flag(sk, SOCK_ZAPPED);
748 757
749 if ((dev = rose_dev_first()) == NULL) 758 if ((dev = rose_dev_first()) == NULL) {
750 return -ENETUNREACH; 759 err = -ENETUNREACH;
760 goto out_release;
761 }
751 762
752 user = ax25_findbyuid(current->euid); 763 user = ax25_findbyuid(current->euid);
753 if (!user) 764 if (!user) {
754 return -EINVAL; 765 err = -EINVAL;
766 goto out_release;
767 }
755 768
756 memcpy(&rose->source_addr, dev->dev_addr, ROSE_ADDR_LEN); 769 memcpy(&rose->source_addr, dev->dev_addr, ROSE_ADDR_LEN);
757 rose->source_call = user->call; 770 rose->source_call = user->call;
@@ -789,8 +802,10 @@ rose_try_next_neigh:
789 rose_start_t1timer(sk); 802 rose_start_t1timer(sk);
790 803
791 /* Now the loop */ 804 /* Now the loop */
792 if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) 805 if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) {
793 return -EINPROGRESS; 806 err = -EINPROGRESS;
807 goto out_release;
808 }
794 809
795 /* 810 /*
796 * A Connect Ack with Choke or timeout or failed routing will go to 811 * A Connect Ack with Choke or timeout or failed routing will go to
@@ -805,8 +820,10 @@ rose_try_next_neigh:
805 set_current_state(TASK_INTERRUPTIBLE); 820 set_current_state(TASK_INTERRUPTIBLE);
806 if (sk->sk_state != TCP_SYN_SENT) 821 if (sk->sk_state != TCP_SYN_SENT)
807 break; 822 break;
823 release_sock(sk);
808 if (!signal_pending(tsk)) { 824 if (!signal_pending(tsk)) {
809 schedule(); 825 schedule();
826 lock_sock(sk);
810 continue; 827 continue;
811 } 828 }
812 current->state = TASK_RUNNING; 829 current->state = TASK_RUNNING;
@@ -822,14 +839,19 @@ rose_try_next_neigh:
822 rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, &diagnostic); 839 rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, &diagnostic);
823 if (rose->neighbour) 840 if (rose->neighbour)
824 goto rose_try_next_neigh; 841 goto rose_try_next_neigh;
825 /* No more neighbour */ 842
843 /* No more neighbours */
826 sock->state = SS_UNCONNECTED; 844 sock->state = SS_UNCONNECTED;
827 return sock_error(sk); /* Always set at this point */ 845 err = sock_error(sk); /* Always set at this point */
846 goto out_release;
828 } 847 }
829 848
830 sock->state = SS_CONNECTED; 849 sock->state = SS_CONNECTED;
831 850
832 return 0; 851out_release:
852 release_sock(sk);
853
854 return err;
833} 855}
834 856
835static int rose_accept(struct socket *sock, struct socket *newsock, int flags) 857static int rose_accept(struct socket *sock, struct socket *newsock, int flags)