diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /net/irda/af_irda.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'net/irda/af_irda.c')
-rw-r--r-- | net/irda/af_irda.c | 402 |
1 files changed, 213 insertions, 189 deletions
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index fd55b5135de5..cc616974a447 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #include <linux/capability.h> | 45 | #include <linux/capability.h> |
46 | #include <linux/module.h> | 46 | #include <linux/module.h> |
47 | #include <linux/types.h> | 47 | #include <linux/types.h> |
48 | #include <linux/smp_lock.h> | ||
49 | #include <linux/socket.h> | 48 | #include <linux/socket.h> |
50 | #include <linux/sockios.h> | 49 | #include <linux/sockios.h> |
51 | #include <linux/slab.h> | 50 | #include <linux/slab.h> |
@@ -573,9 +572,9 @@ static int irda_find_lsap_sel(struct irda_sock *self, char *name) | |||
573 | /* Requested object/attribute doesn't exist */ | 572 | /* Requested object/attribute doesn't exist */ |
574 | if((self->errno == IAS_CLASS_UNKNOWN) || | 573 | if((self->errno == IAS_CLASS_UNKNOWN) || |
575 | (self->errno == IAS_ATTRIB_UNKNOWN)) | 574 | (self->errno == IAS_ATTRIB_UNKNOWN)) |
576 | return (-EADDRNOTAVAIL); | 575 | return -EADDRNOTAVAIL; |
577 | else | 576 | else |
578 | return (-EHOSTUNREACH); | 577 | return -EHOSTUNREACH; |
579 | } | 578 | } |
580 | 579 | ||
581 | /* Get the remote TSAP selector */ | 580 | /* Get the remote TSAP selector */ |
@@ -663,7 +662,7 @@ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name) | |||
663 | __func__, name); | 662 | __func__, name); |
664 | self->daddr = DEV_ADDR_ANY; | 663 | self->daddr = DEV_ADDR_ANY; |
665 | kfree(discoveries); | 664 | kfree(discoveries); |
666 | return(-ENOTUNIQ); | 665 | return -ENOTUNIQ; |
667 | } | 666 | } |
668 | /* First time we found that one, save it ! */ | 667 | /* First time we found that one, save it ! */ |
669 | daddr = self->daddr; | 668 | daddr = self->daddr; |
@@ -677,7 +676,7 @@ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name) | |||
677 | IRDA_DEBUG(0, "%s(), unexpected IAS query failure\n", __func__); | 676 | IRDA_DEBUG(0, "%s(), unexpected IAS query failure\n", __func__); |
678 | self->daddr = DEV_ADDR_ANY; | 677 | self->daddr = DEV_ADDR_ANY; |
679 | kfree(discoveries); | 678 | kfree(discoveries); |
680 | return(-EHOSTUNREACH); | 679 | return -EHOSTUNREACH; |
681 | break; | 680 | break; |
682 | } | 681 | } |
683 | } | 682 | } |
@@ -689,7 +688,7 @@ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name) | |||
689 | IRDA_DEBUG(1, "%s(), cannot discover service ''%s'' in any device !!!\n", | 688 | IRDA_DEBUG(1, "%s(), cannot discover service ''%s'' in any device !!!\n", |
690 | __func__, name); | 689 | __func__, name); |
691 | self->daddr = DEV_ADDR_ANY; | 690 | self->daddr = DEV_ADDR_ANY; |
692 | return(-EADDRNOTAVAIL); | 691 | return -EADDRNOTAVAIL; |
693 | } | 692 | } |
694 | 693 | ||
695 | /* Revert back to discovered device & service */ | 694 | /* Revert back to discovered device & service */ |
@@ -715,14 +714,11 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr, | |||
715 | struct sockaddr_irda saddr; | 714 | struct sockaddr_irda saddr; |
716 | struct sock *sk = sock->sk; | 715 | struct sock *sk = sock->sk; |
717 | struct irda_sock *self = irda_sk(sk); | 716 | struct irda_sock *self = irda_sk(sk); |
718 | int err; | ||
719 | 717 | ||
720 | lock_kernel(); | ||
721 | memset(&saddr, 0, sizeof(saddr)); | 718 | memset(&saddr, 0, sizeof(saddr)); |
722 | if (peer) { | 719 | if (peer) { |
723 | err = -ENOTCONN; | ||
724 | if (sk->sk_state != TCP_ESTABLISHED) | 720 | if (sk->sk_state != TCP_ESTABLISHED) |
725 | goto out; | 721 | return -ENOTCONN; |
726 | 722 | ||
727 | saddr.sir_family = AF_IRDA; | 723 | saddr.sir_family = AF_IRDA; |
728 | saddr.sir_lsap_sel = self->dtsap_sel; | 724 | saddr.sir_lsap_sel = self->dtsap_sel; |
@@ -739,10 +735,8 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr, | |||
739 | /* uaddr_len come to us uninitialised */ | 735 | /* uaddr_len come to us uninitialised */ |
740 | *uaddr_len = sizeof (struct sockaddr_irda); | 736 | *uaddr_len = sizeof (struct sockaddr_irda); |
741 | memcpy(uaddr, &saddr, *uaddr_len); | 737 | memcpy(uaddr, &saddr, *uaddr_len); |
742 | err = 0; | 738 | |
743 | out: | 739 | return 0; |
744 | unlock_kernel(); | ||
745 | return err; | ||
746 | } | 740 | } |
747 | 741 | ||
748 | /* | 742 | /* |
@@ -758,7 +752,8 @@ static int irda_listen(struct socket *sock, int backlog) | |||
758 | 752 | ||
759 | IRDA_DEBUG(2, "%s()\n", __func__); | 753 | IRDA_DEBUG(2, "%s()\n", __func__); |
760 | 754 | ||
761 | lock_kernel(); | 755 | lock_sock(sk); |
756 | |||
762 | if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) && | 757 | if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) && |
763 | (sk->sk_type != SOCK_DGRAM)) | 758 | (sk->sk_type != SOCK_DGRAM)) |
764 | goto out; | 759 | goto out; |
@@ -770,7 +765,7 @@ static int irda_listen(struct socket *sock, int backlog) | |||
770 | err = 0; | 765 | err = 0; |
771 | } | 766 | } |
772 | out: | 767 | out: |
773 | unlock_kernel(); | 768 | release_sock(sk); |
774 | 769 | ||
775 | return err; | 770 | return err; |
776 | } | 771 | } |
@@ -793,7 +788,7 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
793 | if (addr_len != sizeof(struct sockaddr_irda)) | 788 | if (addr_len != sizeof(struct sockaddr_irda)) |
794 | return -EINVAL; | 789 | return -EINVAL; |
795 | 790 | ||
796 | lock_kernel(); | 791 | lock_sock(sk); |
797 | #ifdef CONFIG_IRDA_ULTRA | 792 | #ifdef CONFIG_IRDA_ULTRA |
798 | /* Special care for Ultra sockets */ | 793 | /* Special care for Ultra sockets */ |
799 | if ((sk->sk_type == SOCK_DGRAM) && | 794 | if ((sk->sk_type == SOCK_DGRAM) && |
@@ -836,7 +831,7 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
836 | 831 | ||
837 | err = 0; | 832 | err = 0; |
838 | out: | 833 | out: |
839 | unlock_kernel(); | 834 | release_sock(sk); |
840 | return err; | 835 | return err; |
841 | } | 836 | } |
842 | 837 | ||
@@ -856,12 +851,13 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) | |||
856 | 851 | ||
857 | IRDA_DEBUG(2, "%s()\n", __func__); | 852 | IRDA_DEBUG(2, "%s()\n", __func__); |
858 | 853 | ||
859 | lock_kernel(); | ||
860 | err = irda_create(sock_net(sk), newsock, sk->sk_protocol, 0); | 854 | err = irda_create(sock_net(sk), newsock, sk->sk_protocol, 0); |
861 | if (err) | 855 | if (err) |
862 | goto out; | 856 | return err; |
863 | 857 | ||
864 | err = -EINVAL; | 858 | err = -EINVAL; |
859 | |||
860 | lock_sock(sk); | ||
865 | if (sock->state != SS_UNCONNECTED) | 861 | if (sock->state != SS_UNCONNECTED) |
866 | goto out; | 862 | goto out; |
867 | 863 | ||
@@ -947,7 +943,7 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) | |||
947 | irda_connect_response(new); | 943 | irda_connect_response(new); |
948 | err = 0; | 944 | err = 0; |
949 | out: | 945 | out: |
950 | unlock_kernel(); | 946 | release_sock(sk); |
951 | return err; | 947 | return err; |
952 | } | 948 | } |
953 | 949 | ||
@@ -981,7 +977,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, | |||
981 | 977 | ||
982 | IRDA_DEBUG(2, "%s(%p)\n", __func__, self); | 978 | IRDA_DEBUG(2, "%s(%p)\n", __func__, self); |
983 | 979 | ||
984 | lock_kernel(); | 980 | lock_sock(sk); |
985 | /* Don't allow connect for Ultra sockets */ | 981 | /* Don't allow connect for Ultra sockets */ |
986 | err = -ESOCKTNOSUPPORT; | 982 | err = -ESOCKTNOSUPPORT; |
987 | if ((sk->sk_type == SOCK_DGRAM) && (sk->sk_protocol == IRDAPROTO_ULTRA)) | 983 | if ((sk->sk_type == SOCK_DGRAM) && (sk->sk_protocol == IRDAPROTO_ULTRA)) |
@@ -1072,6 +1068,8 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, | |||
1072 | 1068 | ||
1073 | if (sk->sk_state != TCP_ESTABLISHED) { | 1069 | if (sk->sk_state != TCP_ESTABLISHED) { |
1074 | sock->state = SS_UNCONNECTED; | 1070 | sock->state = SS_UNCONNECTED; |
1071 | if (sk->sk_prot->disconnect(sk, flags)) | ||
1072 | sock->state = SS_DISCONNECTING; | ||
1075 | err = sock_error(sk); | 1073 | err = sock_error(sk); |
1076 | if (!err) | 1074 | if (!err) |
1077 | err = -ECONNRESET; | 1075 | err = -ECONNRESET; |
@@ -1084,7 +1082,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, | |||
1084 | self->saddr = irttp_get_saddr(self->tsap); | 1082 | self->saddr = irttp_get_saddr(self->tsap); |
1085 | err = 0; | 1083 | err = 0; |
1086 | out: | 1084 | out: |
1087 | unlock_kernel(); | 1085 | release_sock(sk); |
1088 | return err; | 1086 | return err; |
1089 | } | 1087 | } |
1090 | 1088 | ||
@@ -1231,7 +1229,6 @@ static int irda_release(struct socket *sock) | |||
1231 | if (sk == NULL) | 1229 | if (sk == NULL) |
1232 | return 0; | 1230 | return 0; |
1233 | 1231 | ||
1234 | lock_kernel(); | ||
1235 | lock_sock(sk); | 1232 | lock_sock(sk); |
1236 | sk->sk_state = TCP_CLOSE; | 1233 | sk->sk_state = TCP_CLOSE; |
1237 | sk->sk_shutdown |= SEND_SHUTDOWN; | 1234 | sk->sk_shutdown |= SEND_SHUTDOWN; |
@@ -1250,7 +1247,6 @@ static int irda_release(struct socket *sock) | |||
1250 | /* Destroy networking socket if we are the last reference on it, | 1247 | /* Destroy networking socket if we are the last reference on it, |
1251 | * i.e. if(sk->sk_refcnt == 0) -> sk_free(sk) */ | 1248 | * i.e. if(sk->sk_refcnt == 0) -> sk_free(sk) */ |
1252 | sock_put(sk); | 1249 | sock_put(sk); |
1253 | unlock_kernel(); | ||
1254 | 1250 | ||
1255 | /* Notes on socket locking and deallocation... - Jean II | 1251 | /* Notes on socket locking and deallocation... - Jean II |
1256 | * In theory we should put pairs of sock_hold() / sock_put() to | 1252 | * In theory we should put pairs of sock_hold() / sock_put() to |
@@ -1298,14 +1294,14 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1298 | 1294 | ||
1299 | IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); | 1295 | IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); |
1300 | 1296 | ||
1301 | lock_kernel(); | ||
1302 | /* Note : socket.c set MSG_EOR on SEQPACKET sockets */ | 1297 | /* Note : socket.c set MSG_EOR on SEQPACKET sockets */ |
1303 | if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT | | 1298 | if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT | |
1304 | MSG_NOSIGNAL)) { | 1299 | MSG_NOSIGNAL)) { |
1305 | err = -EINVAL; | 1300 | return -EINVAL; |
1306 | goto out; | ||
1307 | } | 1301 | } |
1308 | 1302 | ||
1303 | lock_sock(sk); | ||
1304 | |||
1309 | if (sk->sk_shutdown & SEND_SHUTDOWN) | 1305 | if (sk->sk_shutdown & SEND_SHUTDOWN) |
1310 | goto out_err; | 1306 | goto out_err; |
1311 | 1307 | ||
@@ -1361,14 +1357,14 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1361 | goto out_err; | 1357 | goto out_err; |
1362 | } | 1358 | } |
1363 | 1359 | ||
1364 | unlock_kernel(); | 1360 | release_sock(sk); |
1365 | /* Tell client how much data we actually sent */ | 1361 | /* Tell client how much data we actually sent */ |
1366 | return len; | 1362 | return len; |
1367 | 1363 | ||
1368 | out_err: | 1364 | out_err: |
1369 | err = sk_stream_error(sk, msg->msg_flags, err); | 1365 | err = sk_stream_error(sk, msg->msg_flags, err); |
1370 | out: | 1366 | out: |
1371 | unlock_kernel(); | 1367 | release_sock(sk); |
1372 | return err; | 1368 | return err; |
1373 | 1369 | ||
1374 | } | 1370 | } |
@@ -1390,14 +1386,10 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, | |||
1390 | 1386 | ||
1391 | IRDA_DEBUG(4, "%s()\n", __func__); | 1387 | IRDA_DEBUG(4, "%s()\n", __func__); |
1392 | 1388 | ||
1393 | lock_kernel(); | ||
1394 | if ((err = sock_error(sk)) < 0) | ||
1395 | goto out; | ||
1396 | |||
1397 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, | 1389 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, |
1398 | flags & MSG_DONTWAIT, &err); | 1390 | flags & MSG_DONTWAIT, &err); |
1399 | if (!skb) | 1391 | if (!skb) |
1400 | goto out; | 1392 | return err; |
1401 | 1393 | ||
1402 | skb_reset_transport_header(skb); | 1394 | skb_reset_transport_header(skb); |
1403 | copied = skb->len; | 1395 | copied = skb->len; |
@@ -1425,12 +1417,8 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, | |||
1425 | irttp_flow_request(self->tsap, FLOW_START); | 1417 | irttp_flow_request(self->tsap, FLOW_START); |
1426 | } | 1418 | } |
1427 | } | 1419 | } |
1428 | unlock_kernel(); | ||
1429 | return copied; | ||
1430 | 1420 | ||
1431 | out: | 1421 | return copied; |
1432 | unlock_kernel(); | ||
1433 | return err; | ||
1434 | } | 1422 | } |
1435 | 1423 | ||
1436 | /* | 1424 | /* |
@@ -1448,17 +1436,15 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, | |||
1448 | 1436 | ||
1449 | IRDA_DEBUG(3, "%s()\n", __func__); | 1437 | IRDA_DEBUG(3, "%s()\n", __func__); |
1450 | 1438 | ||
1451 | lock_kernel(); | ||
1452 | if ((err = sock_error(sk)) < 0) | 1439 | if ((err = sock_error(sk)) < 0) |
1453 | goto out; | 1440 | return err; |
1454 | 1441 | ||
1455 | err = -EINVAL; | ||
1456 | if (sock->flags & __SO_ACCEPTCON) | 1442 | if (sock->flags & __SO_ACCEPTCON) |
1457 | goto out; | 1443 | return -EINVAL; |
1458 | 1444 | ||
1459 | err =-EOPNOTSUPP; | 1445 | err =-EOPNOTSUPP; |
1460 | if (flags & MSG_OOB) | 1446 | if (flags & MSG_OOB) |
1461 | goto out; | 1447 | return -EOPNOTSUPP; |
1462 | 1448 | ||
1463 | err = 0; | 1449 | err = 0; |
1464 | target = sock_rcvlowat(sk, flags & MSG_WAITALL, size); | 1450 | target = sock_rcvlowat(sk, flags & MSG_WAITALL, size); |
@@ -1500,7 +1486,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, | |||
1500 | finish_wait(sk_sleep(sk), &wait); | 1486 | finish_wait(sk_sleep(sk), &wait); |
1501 | 1487 | ||
1502 | if (err) | 1488 | if (err) |
1503 | goto out; | 1489 | return err; |
1504 | if (sk->sk_shutdown & RCV_SHUTDOWN) | 1490 | if (sk->sk_shutdown & RCV_SHUTDOWN) |
1505 | break; | 1491 | break; |
1506 | 1492 | ||
@@ -1553,9 +1539,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, | |||
1553 | } | 1539 | } |
1554 | } | 1540 | } |
1555 | 1541 | ||
1556 | out: | 1542 | return copied; |
1557 | unlock_kernel(); | ||
1558 | return err ? : copied; | ||
1559 | } | 1543 | } |
1560 | 1544 | ||
1561 | /* | 1545 | /* |
@@ -1573,13 +1557,12 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock, | |||
1573 | struct sk_buff *skb; | 1557 | struct sk_buff *skb; |
1574 | int err; | 1558 | int err; |
1575 | 1559 | ||
1576 | lock_kernel(); | ||
1577 | |||
1578 | IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); | 1560 | IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); |
1579 | 1561 | ||
1580 | err = -EINVAL; | ||
1581 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) | 1562 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) |
1582 | goto out; | 1563 | return -EINVAL; |
1564 | |||
1565 | lock_sock(sk); | ||
1583 | 1566 | ||
1584 | if (sk->sk_shutdown & SEND_SHUTDOWN) { | 1567 | if (sk->sk_shutdown & SEND_SHUTDOWN) { |
1585 | send_sig(SIGPIPE, current, 0); | 1568 | send_sig(SIGPIPE, current, 0); |
@@ -1630,10 +1613,12 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock, | |||
1630 | IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); | 1613 | IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); |
1631 | goto out; | 1614 | goto out; |
1632 | } | 1615 | } |
1633 | unlock_kernel(); | 1616 | |
1617 | release_sock(sk); | ||
1634 | return len; | 1618 | return len; |
1619 | |||
1635 | out: | 1620 | out: |
1636 | unlock_kernel(); | 1621 | release_sock(sk); |
1637 | return err; | 1622 | return err; |
1638 | } | 1623 | } |
1639 | 1624 | ||
@@ -1656,10 +1641,11 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, | |||
1656 | 1641 | ||
1657 | IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); | 1642 | IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); |
1658 | 1643 | ||
1659 | lock_kernel(); | ||
1660 | err = -EINVAL; | 1644 | err = -EINVAL; |
1661 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) | 1645 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) |
1662 | goto out; | 1646 | return -EINVAL; |
1647 | |||
1648 | lock_sock(sk); | ||
1663 | 1649 | ||
1664 | err = -EPIPE; | 1650 | err = -EPIPE; |
1665 | if (sk->sk_shutdown & SEND_SHUTDOWN) { | 1651 | if (sk->sk_shutdown & SEND_SHUTDOWN) { |
@@ -1732,7 +1718,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, | |||
1732 | if (err) | 1718 | if (err) |
1733 | IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); | 1719 | IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); |
1734 | out: | 1720 | out: |
1735 | unlock_kernel(); | 1721 | release_sock(sk); |
1736 | return err ? : len; | 1722 | return err ? : len; |
1737 | } | 1723 | } |
1738 | #endif /* CONFIG_IRDA_ULTRA */ | 1724 | #endif /* CONFIG_IRDA_ULTRA */ |
@@ -1747,7 +1733,7 @@ static int irda_shutdown(struct socket *sock, int how) | |||
1747 | 1733 | ||
1748 | IRDA_DEBUG(1, "%s(%p)\n", __func__, self); | 1734 | IRDA_DEBUG(1, "%s(%p)\n", __func__, self); |
1749 | 1735 | ||
1750 | lock_kernel(); | 1736 | lock_sock(sk); |
1751 | 1737 | ||
1752 | sk->sk_state = TCP_CLOSE; | 1738 | sk->sk_state = TCP_CLOSE; |
1753 | sk->sk_shutdown |= SEND_SHUTDOWN; | 1739 | sk->sk_shutdown |= SEND_SHUTDOWN; |
@@ -1769,7 +1755,7 @@ static int irda_shutdown(struct socket *sock, int how) | |||
1769 | self->daddr = DEV_ADDR_ANY; /* Until we get re-connected */ | 1755 | self->daddr = DEV_ADDR_ANY; /* Until we get re-connected */ |
1770 | self->saddr = 0x0; /* so IrLMP assign us any link */ | 1756 | self->saddr = 0x0; /* so IrLMP assign us any link */ |
1771 | 1757 | ||
1772 | unlock_kernel(); | 1758 | release_sock(sk); |
1773 | 1759 | ||
1774 | return 0; | 1760 | return 0; |
1775 | } | 1761 | } |
@@ -1786,7 +1772,6 @@ static unsigned int irda_poll(struct file * file, struct socket *sock, | |||
1786 | 1772 | ||
1787 | IRDA_DEBUG(4, "%s()\n", __func__); | 1773 | IRDA_DEBUG(4, "%s()\n", __func__); |
1788 | 1774 | ||
1789 | lock_kernel(); | ||
1790 | poll_wait(file, sk_sleep(sk), wait); | 1775 | poll_wait(file, sk_sleep(sk), wait); |
1791 | mask = 0; | 1776 | mask = 0; |
1792 | 1777 | ||
@@ -1834,20 +1819,8 @@ static unsigned int irda_poll(struct file * file, struct socket *sock, | |||
1834 | default: | 1819 | default: |
1835 | break; | 1820 | break; |
1836 | } | 1821 | } |
1837 | unlock_kernel(); | ||
1838 | return mask; | ||
1839 | } | ||
1840 | |||
1841 | static unsigned int irda_datagram_poll(struct file *file, struct socket *sock, | ||
1842 | poll_table *wait) | ||
1843 | { | ||
1844 | int err; | ||
1845 | 1822 | ||
1846 | lock_kernel(); | 1823 | return mask; |
1847 | err = datagram_poll(file, sock, wait); | ||
1848 | unlock_kernel(); | ||
1849 | |||
1850 | return err; | ||
1851 | } | 1824 | } |
1852 | 1825 | ||
1853 | /* | 1826 | /* |
@@ -1860,7 +1833,6 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1860 | 1833 | ||
1861 | IRDA_DEBUG(4, "%s(), cmd=%#x\n", __func__, cmd); | 1834 | IRDA_DEBUG(4, "%s(), cmd=%#x\n", __func__, cmd); |
1862 | 1835 | ||
1863 | lock_kernel(); | ||
1864 | err = -EINVAL; | 1836 | err = -EINVAL; |
1865 | switch (cmd) { | 1837 | switch (cmd) { |
1866 | case TIOCOUTQ: { | 1838 | case TIOCOUTQ: { |
@@ -1903,7 +1875,6 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1903 | IRDA_DEBUG(1, "%s(), doing device ioctl!\n", __func__); | 1875 | IRDA_DEBUG(1, "%s(), doing device ioctl!\n", __func__); |
1904 | err = -ENOIOCTLCMD; | 1876 | err = -ENOIOCTLCMD; |
1905 | } | 1877 | } |
1906 | unlock_kernel(); | ||
1907 | 1878 | ||
1908 | return err; | 1879 | return err; |
1909 | } | 1880 | } |
@@ -1927,7 +1898,7 @@ static int irda_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned lon | |||
1927 | * Set some options for the socket | 1898 | * Set some options for the socket |
1928 | * | 1899 | * |
1929 | */ | 1900 | */ |
1930 | static int __irda_setsockopt(struct socket *sock, int level, int optname, | 1901 | static int irda_setsockopt(struct socket *sock, int level, int optname, |
1931 | char __user *optval, unsigned int optlen) | 1902 | char __user *optval, unsigned int optlen) |
1932 | { | 1903 | { |
1933 | struct sock *sk = sock->sk; | 1904 | struct sock *sk = sock->sk; |
@@ -1935,13 +1906,15 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
1935 | struct irda_ias_set *ias_opt; | 1906 | struct irda_ias_set *ias_opt; |
1936 | struct ias_object *ias_obj; | 1907 | struct ias_object *ias_obj; |
1937 | struct ias_attrib * ias_attr; /* Attribute in IAS object */ | 1908 | struct ias_attrib * ias_attr; /* Attribute in IAS object */ |
1938 | int opt, free_ias = 0; | 1909 | int opt, free_ias = 0, err = 0; |
1939 | 1910 | ||
1940 | IRDA_DEBUG(2, "%s(%p)\n", __func__, self); | 1911 | IRDA_DEBUG(2, "%s(%p)\n", __func__, self); |
1941 | 1912 | ||
1942 | if (level != SOL_IRLMP) | 1913 | if (level != SOL_IRLMP) |
1943 | return -ENOPROTOOPT; | 1914 | return -ENOPROTOOPT; |
1944 | 1915 | ||
1916 | lock_sock(sk); | ||
1917 | |||
1945 | switch (optname) { | 1918 | switch (optname) { |
1946 | case IRLMP_IAS_SET: | 1919 | case IRLMP_IAS_SET: |
1947 | /* The user want to add an attribute to an existing IAS object | 1920 | /* The user want to add an attribute to an existing IAS object |
@@ -1951,17 +1924,22 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
1951 | * create the right attribute... | 1924 | * create the right attribute... |
1952 | */ | 1925 | */ |
1953 | 1926 | ||
1954 | if (optlen != sizeof(struct irda_ias_set)) | 1927 | if (optlen != sizeof(struct irda_ias_set)) { |
1955 | return -EINVAL; | 1928 | err = -EINVAL; |
1929 | goto out; | ||
1930 | } | ||
1956 | 1931 | ||
1957 | ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); | 1932 | ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); |
1958 | if (ias_opt == NULL) | 1933 | if (ias_opt == NULL) { |
1959 | return -ENOMEM; | 1934 | err = -ENOMEM; |
1935 | goto out; | ||
1936 | } | ||
1960 | 1937 | ||
1961 | /* Copy query to the driver. */ | 1938 | /* Copy query to the driver. */ |
1962 | if (copy_from_user(ias_opt, optval, optlen)) { | 1939 | if (copy_from_user(ias_opt, optval, optlen)) { |
1963 | kfree(ias_opt); | 1940 | kfree(ias_opt); |
1964 | return -EFAULT; | 1941 | err = -EFAULT; |
1942 | goto out; | ||
1965 | } | 1943 | } |
1966 | 1944 | ||
1967 | /* Find the object we target. | 1945 | /* Find the object we target. |
@@ -1971,7 +1949,8 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
1971 | if(ias_opt->irda_class_name[0] == '\0') { | 1949 | if(ias_opt->irda_class_name[0] == '\0') { |
1972 | if(self->ias_obj == NULL) { | 1950 | if(self->ias_obj == NULL) { |
1973 | kfree(ias_opt); | 1951 | kfree(ias_opt); |
1974 | return -EINVAL; | 1952 | err = -EINVAL; |
1953 | goto out; | ||
1975 | } | 1954 | } |
1976 | ias_obj = self->ias_obj; | 1955 | ias_obj = self->ias_obj; |
1977 | } else | 1956 | } else |
@@ -1983,7 +1962,8 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
1983 | if((!capable(CAP_NET_ADMIN)) && | 1962 | if((!capable(CAP_NET_ADMIN)) && |
1984 | ((ias_obj == NULL) || (ias_obj != self->ias_obj))) { | 1963 | ((ias_obj == NULL) || (ias_obj != self->ias_obj))) { |
1985 | kfree(ias_opt); | 1964 | kfree(ias_opt); |
1986 | return -EPERM; | 1965 | err = -EPERM; |
1966 | goto out; | ||
1987 | } | 1967 | } |
1988 | 1968 | ||
1989 | /* If the object doesn't exist, create it */ | 1969 | /* If the object doesn't exist, create it */ |
@@ -1993,7 +1973,8 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
1993 | jiffies); | 1973 | jiffies); |
1994 | if (ias_obj == NULL) { | 1974 | if (ias_obj == NULL) { |
1995 | kfree(ias_opt); | 1975 | kfree(ias_opt); |
1996 | return -ENOMEM; | 1976 | err = -ENOMEM; |
1977 | goto out; | ||
1997 | } | 1978 | } |
1998 | free_ias = 1; | 1979 | free_ias = 1; |
1999 | } | 1980 | } |
@@ -2005,7 +1986,8 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
2005 | kfree(ias_obj->name); | 1986 | kfree(ias_obj->name); |
2006 | kfree(ias_obj); | 1987 | kfree(ias_obj); |
2007 | } | 1988 | } |
2008 | return -EINVAL; | 1989 | err = -EINVAL; |
1990 | goto out; | ||
2009 | } | 1991 | } |
2010 | 1992 | ||
2011 | /* Look at the type */ | 1993 | /* Look at the type */ |
@@ -2028,7 +2010,8 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
2028 | kfree(ias_obj); | 2010 | kfree(ias_obj); |
2029 | } | 2011 | } |
2030 | 2012 | ||
2031 | return -EINVAL; | 2013 | err = -EINVAL; |
2014 | goto out; | ||
2032 | } | 2015 | } |
2033 | /* Add an octet sequence attribute */ | 2016 | /* Add an octet sequence attribute */ |
2034 | irias_add_octseq_attrib( | 2017 | irias_add_octseq_attrib( |
@@ -2060,7 +2043,8 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
2060 | kfree(ias_obj->name); | 2043 | kfree(ias_obj->name); |
2061 | kfree(ias_obj); | 2044 | kfree(ias_obj); |
2062 | } | 2045 | } |
2063 | return -EINVAL; | 2046 | err = -EINVAL; |
2047 | goto out; | ||
2064 | } | 2048 | } |
2065 | irias_insert_object(ias_obj); | 2049 | irias_insert_object(ias_obj); |
2066 | kfree(ias_opt); | 2050 | kfree(ias_opt); |
@@ -2071,17 +2055,22 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
2071 | * object is not owned by the kernel and delete it. | 2055 | * object is not owned by the kernel and delete it. |
2072 | */ | 2056 | */ |
2073 | 2057 | ||
2074 | if (optlen != sizeof(struct irda_ias_set)) | 2058 | if (optlen != sizeof(struct irda_ias_set)) { |
2075 | return -EINVAL; | 2059 | err = -EINVAL; |
2060 | goto out; | ||
2061 | } | ||
2076 | 2062 | ||
2077 | ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); | 2063 | ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); |
2078 | if (ias_opt == NULL) | 2064 | if (ias_opt == NULL) { |
2079 | return -ENOMEM; | 2065 | err = -ENOMEM; |
2066 | goto out; | ||
2067 | } | ||
2080 | 2068 | ||
2081 | /* Copy query to the driver. */ | 2069 | /* Copy query to the driver. */ |
2082 | if (copy_from_user(ias_opt, optval, optlen)) { | 2070 | if (copy_from_user(ias_opt, optval, optlen)) { |
2083 | kfree(ias_opt); | 2071 | kfree(ias_opt); |
2084 | return -EFAULT; | 2072 | err = -EFAULT; |
2073 | goto out; | ||
2085 | } | 2074 | } |
2086 | 2075 | ||
2087 | /* Find the object we target. | 2076 | /* Find the object we target. |
@@ -2094,7 +2083,8 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
2094 | ias_obj = irias_find_object(ias_opt->irda_class_name); | 2083 | ias_obj = irias_find_object(ias_opt->irda_class_name); |
2095 | if(ias_obj == (struct ias_object *) NULL) { | 2084 | if(ias_obj == (struct ias_object *) NULL) { |
2096 | kfree(ias_opt); | 2085 | kfree(ias_opt); |
2097 | return -EINVAL; | 2086 | err = -EINVAL; |
2087 | goto out; | ||
2098 | } | 2088 | } |
2099 | 2089 | ||
2100 | /* Only ROOT can mess with the global IAS database. | 2090 | /* Only ROOT can mess with the global IAS database. |
@@ -2103,7 +2093,8 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
2103 | if((!capable(CAP_NET_ADMIN)) && | 2093 | if((!capable(CAP_NET_ADMIN)) && |
2104 | ((ias_obj == NULL) || (ias_obj != self->ias_obj))) { | 2094 | ((ias_obj == NULL) || (ias_obj != self->ias_obj))) { |
2105 | kfree(ias_opt); | 2095 | kfree(ias_opt); |
2106 | return -EPERM; | 2096 | err = -EPERM; |
2097 | goto out; | ||
2107 | } | 2098 | } |
2108 | 2099 | ||
2109 | /* Find the attribute (in the object) we target */ | 2100 | /* Find the attribute (in the object) we target */ |
@@ -2111,14 +2102,16 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
2111 | ias_opt->irda_attrib_name); | 2102 | ias_opt->irda_attrib_name); |
2112 | if(ias_attr == (struct ias_attrib *) NULL) { | 2103 | if(ias_attr == (struct ias_attrib *) NULL) { |
2113 | kfree(ias_opt); | 2104 | kfree(ias_opt); |
2114 | return -EINVAL; | 2105 | err = -EINVAL; |
2106 | goto out; | ||
2115 | } | 2107 | } |
2116 | 2108 | ||
2117 | /* Check is the user space own the object */ | 2109 | /* Check is the user space own the object */ |
2118 | if(ias_attr->value->owner != IAS_USER_ATTR) { | 2110 | if(ias_attr->value->owner != IAS_USER_ATTR) { |
2119 | IRDA_DEBUG(1, "%s(), attempting to delete a kernel attribute\n", __func__); | 2111 | IRDA_DEBUG(1, "%s(), attempting to delete a kernel attribute\n", __func__); |
2120 | kfree(ias_opt); | 2112 | kfree(ias_opt); |
2121 | return -EPERM; | 2113 | err = -EPERM; |
2114 | goto out; | ||
2122 | } | 2115 | } |
2123 | 2116 | ||
2124 | /* Remove the attribute (and maybe the object) */ | 2117 | /* Remove the attribute (and maybe the object) */ |
@@ -2126,11 +2119,15 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
2126 | kfree(ias_opt); | 2119 | kfree(ias_opt); |
2127 | break; | 2120 | break; |
2128 | case IRLMP_MAX_SDU_SIZE: | 2121 | case IRLMP_MAX_SDU_SIZE: |
2129 | if (optlen < sizeof(int)) | 2122 | if (optlen < sizeof(int)) { |
2130 | return -EINVAL; | 2123 | err = -EINVAL; |
2124 | goto out; | ||
2125 | } | ||
2131 | 2126 | ||
2132 | if (get_user(opt, (int __user *)optval)) | 2127 | if (get_user(opt, (int __user *)optval)) { |
2133 | return -EFAULT; | 2128 | err = -EFAULT; |
2129 | goto out; | ||
2130 | } | ||
2134 | 2131 | ||
2135 | /* Only possible for a seqpacket service (TTP with SAR) */ | 2132 | /* Only possible for a seqpacket service (TTP with SAR) */ |
2136 | if (sk->sk_type != SOCK_SEQPACKET) { | 2133 | if (sk->sk_type != SOCK_SEQPACKET) { |
@@ -2140,16 +2137,21 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
2140 | } else { | 2137 | } else { |
2141 | IRDA_WARNING("%s: not allowed to set MAXSDUSIZE for this socket type!\n", | 2138 | IRDA_WARNING("%s: not allowed to set MAXSDUSIZE for this socket type!\n", |
2142 | __func__); | 2139 | __func__); |
2143 | return -ENOPROTOOPT; | 2140 | err = -ENOPROTOOPT; |
2141 | goto out; | ||
2144 | } | 2142 | } |
2145 | break; | 2143 | break; |
2146 | case IRLMP_HINTS_SET: | 2144 | case IRLMP_HINTS_SET: |
2147 | if (optlen < sizeof(int)) | 2145 | if (optlen < sizeof(int)) { |
2148 | return -EINVAL; | 2146 | err = -EINVAL; |
2147 | goto out; | ||
2148 | } | ||
2149 | 2149 | ||
2150 | /* The input is really a (__u8 hints[2]), easier as an int */ | 2150 | /* The input is really a (__u8 hints[2]), easier as an int */ |
2151 | if (get_user(opt, (int __user *)optval)) | 2151 | if (get_user(opt, (int __user *)optval)) { |
2152 | return -EFAULT; | 2152 | err = -EFAULT; |
2153 | goto out; | ||
2154 | } | ||
2153 | 2155 | ||
2154 | /* Unregister any old registration */ | 2156 | /* Unregister any old registration */ |
2155 | if (self->skey) | 2157 | if (self->skey) |
@@ -2163,12 +2165,16 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
2163 | * making a discovery (nodes which don't match any hint | 2165 | * making a discovery (nodes which don't match any hint |
2164 | * bit in the mask are not reported). | 2166 | * bit in the mask are not reported). |
2165 | */ | 2167 | */ |
2166 | if (optlen < sizeof(int)) | 2168 | if (optlen < sizeof(int)) { |
2167 | return -EINVAL; | 2169 | err = -EINVAL; |
2170 | goto out; | ||
2171 | } | ||
2168 | 2172 | ||
2169 | /* The input is really a (__u8 hints[2]), easier as an int */ | 2173 | /* The input is really a (__u8 hints[2]), easier as an int */ |
2170 | if (get_user(opt, (int __user *)optval)) | 2174 | if (get_user(opt, (int __user *)optval)) { |
2171 | return -EFAULT; | 2175 | err = -EFAULT; |
2176 | goto out; | ||
2177 | } | ||
2172 | 2178 | ||
2173 | /* Set the new hint mask */ | 2179 | /* Set the new hint mask */ |
2174 | self->mask.word = (__u16) opt; | 2180 | self->mask.word = (__u16) opt; |
@@ -2180,19 +2186,12 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, | |||
2180 | 2186 | ||
2181 | break; | 2187 | break; |
2182 | default: | 2188 | default: |
2183 | return -ENOPROTOOPT; | 2189 | err = -ENOPROTOOPT; |
2190 | break; | ||
2184 | } | 2191 | } |
2185 | return 0; | ||
2186 | } | ||
2187 | 2192 | ||
2188 | static int irda_setsockopt(struct socket *sock, int level, int optname, | 2193 | out: |
2189 | char __user *optval, unsigned int optlen) | 2194 | release_sock(sk); |
2190 | { | ||
2191 | int err; | ||
2192 | |||
2193 | lock_kernel(); | ||
2194 | err = __irda_setsockopt(sock, level, optname, optval, optlen); | ||
2195 | unlock_kernel(); | ||
2196 | 2195 | ||
2197 | return err; | 2196 | return err; |
2198 | } | 2197 | } |
@@ -2249,7 +2248,7 @@ static int irda_extract_ias_value(struct irda_ias_set *ias_opt, | |||
2249 | /* | 2248 | /* |
2250 | * Function irda_getsockopt (sock, level, optname, optval, optlen) | 2249 | * Function irda_getsockopt (sock, level, optname, optval, optlen) |
2251 | */ | 2250 | */ |
2252 | static int __irda_getsockopt(struct socket *sock, int level, int optname, | 2251 | static int irda_getsockopt(struct socket *sock, int level, int optname, |
2253 | char __user *optval, int __user *optlen) | 2252 | char __user *optval, int __user *optlen) |
2254 | { | 2253 | { |
2255 | struct sock *sk = sock->sk; | 2254 | struct sock *sk = sock->sk; |
@@ -2262,7 +2261,7 @@ static int __irda_getsockopt(struct socket *sock, int level, int optname, | |||
2262 | int daddr = DEV_ADDR_ANY; /* Dest address for IAS queries */ | 2261 | int daddr = DEV_ADDR_ANY; /* Dest address for IAS queries */ |
2263 | int val = 0; | 2262 | int val = 0; |
2264 | int len = 0; | 2263 | int len = 0; |
2265 | int err; | 2264 | int err = 0; |
2266 | int offset, total; | 2265 | int offset, total; |
2267 | 2266 | ||
2268 | IRDA_DEBUG(2, "%s(%p)\n", __func__, self); | 2267 | IRDA_DEBUG(2, "%s(%p)\n", __func__, self); |
@@ -2276,29 +2275,35 @@ static int __irda_getsockopt(struct socket *sock, int level, int optname, | |||
2276 | if(len < 0) | 2275 | if(len < 0) |
2277 | return -EINVAL; | 2276 | return -EINVAL; |
2278 | 2277 | ||
2278 | lock_sock(sk); | ||
2279 | |||
2279 | switch (optname) { | 2280 | switch (optname) { |
2280 | case IRLMP_ENUMDEVICES: | 2281 | case IRLMP_ENUMDEVICES: |
2282 | |||
2283 | /* Offset to first device entry */ | ||
2284 | offset = sizeof(struct irda_device_list) - | ||
2285 | sizeof(struct irda_device_info); | ||
2286 | |||
2287 | if (len < offset) { | ||
2288 | err = -EINVAL; | ||
2289 | goto out; | ||
2290 | } | ||
2291 | |||
2281 | /* Ask lmp for the current discovery log */ | 2292 | /* Ask lmp for the current discovery log */ |
2282 | discoveries = irlmp_get_discoveries(&list.len, self->mask.word, | 2293 | discoveries = irlmp_get_discoveries(&list.len, self->mask.word, |
2283 | self->nslots); | 2294 | self->nslots); |
2284 | /* Check if the we got some results */ | 2295 | /* Check if the we got some results */ |
2285 | if (discoveries == NULL) | 2296 | if (discoveries == NULL) { |
2286 | return -EAGAIN; /* Didn't find any devices */ | 2297 | err = -EAGAIN; |
2287 | err = 0; | 2298 | goto out; /* Didn't find any devices */ |
2299 | } | ||
2288 | 2300 | ||
2289 | /* Write total list length back to client */ | 2301 | /* Write total list length back to client */ |
2290 | if (copy_to_user(optval, &list, | 2302 | if (copy_to_user(optval, &list, offset)) |
2291 | sizeof(struct irda_device_list) - | ||
2292 | sizeof(struct irda_device_info))) | ||
2293 | err = -EFAULT; | 2303 | err = -EFAULT; |
2294 | 2304 | ||
2295 | /* Offset to first device entry */ | ||
2296 | offset = sizeof(struct irda_device_list) - | ||
2297 | sizeof(struct irda_device_info); | ||
2298 | |||
2299 | /* Copy the list itself - watch for overflow */ | 2305 | /* Copy the list itself - watch for overflow */ |
2300 | if(list.len > 2048) | 2306 | if (list.len > 2048) { |
2301 | { | ||
2302 | err = -EINVAL; | 2307 | err = -EINVAL; |
2303 | goto bed; | 2308 | goto bed; |
2304 | } | 2309 | } |
@@ -2314,17 +2319,20 @@ static int __irda_getsockopt(struct socket *sock, int level, int optname, | |||
2314 | bed: | 2319 | bed: |
2315 | /* Free up our buffer */ | 2320 | /* Free up our buffer */ |
2316 | kfree(discoveries); | 2321 | kfree(discoveries); |
2317 | if (err) | ||
2318 | return err; | ||
2319 | break; | 2322 | break; |
2320 | case IRLMP_MAX_SDU_SIZE: | 2323 | case IRLMP_MAX_SDU_SIZE: |
2321 | val = self->max_data_size; | 2324 | val = self->max_data_size; |
2322 | len = sizeof(int); | 2325 | len = sizeof(int); |
2323 | if (put_user(len, optlen)) | 2326 | if (put_user(len, optlen)) { |
2324 | return -EFAULT; | 2327 | err = -EFAULT; |
2328 | goto out; | ||
2329 | } | ||
2330 | |||
2331 | if (copy_to_user(optval, &val, len)) { | ||
2332 | err = -EFAULT; | ||
2333 | goto out; | ||
2334 | } | ||
2325 | 2335 | ||
2326 | if (copy_to_user(optval, &val, len)) | ||
2327 | return -EFAULT; | ||
2328 | break; | 2336 | break; |
2329 | case IRLMP_IAS_GET: | 2337 | case IRLMP_IAS_GET: |
2330 | /* The user want an object from our local IAS database. | 2338 | /* The user want an object from our local IAS database. |
@@ -2332,17 +2340,22 @@ bed: | |||
2332 | * that we found */ | 2340 | * that we found */ |
2333 | 2341 | ||
2334 | /* Check that the user has allocated the right space for us */ | 2342 | /* Check that the user has allocated the right space for us */ |
2335 | if (len != sizeof(struct irda_ias_set)) | 2343 | if (len != sizeof(struct irda_ias_set)) { |
2336 | return -EINVAL; | 2344 | err = -EINVAL; |
2345 | goto out; | ||
2346 | } | ||
2337 | 2347 | ||
2338 | ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); | 2348 | ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); |
2339 | if (ias_opt == NULL) | 2349 | if (ias_opt == NULL) { |
2340 | return -ENOMEM; | 2350 | err = -ENOMEM; |
2351 | goto out; | ||
2352 | } | ||
2341 | 2353 | ||
2342 | /* Copy query to the driver. */ | 2354 | /* Copy query to the driver. */ |
2343 | if (copy_from_user(ias_opt, optval, len)) { | 2355 | if (copy_from_user(ias_opt, optval, len)) { |
2344 | kfree(ias_opt); | 2356 | kfree(ias_opt); |
2345 | return -EFAULT; | 2357 | err = -EFAULT; |
2358 | goto out; | ||
2346 | } | 2359 | } |
2347 | 2360 | ||
2348 | /* Find the object we target. | 2361 | /* Find the object we target. |
@@ -2355,7 +2368,8 @@ bed: | |||
2355 | ias_obj = irias_find_object(ias_opt->irda_class_name); | 2368 | ias_obj = irias_find_object(ias_opt->irda_class_name); |
2356 | if(ias_obj == (struct ias_object *) NULL) { | 2369 | if(ias_obj == (struct ias_object *) NULL) { |
2357 | kfree(ias_opt); | 2370 | kfree(ias_opt); |
2358 | return -EINVAL; | 2371 | err = -EINVAL; |
2372 | goto out; | ||
2359 | } | 2373 | } |
2360 | 2374 | ||
2361 | /* Find the attribute (in the object) we target */ | 2375 | /* Find the attribute (in the object) we target */ |
@@ -2363,21 +2377,23 @@ bed: | |||
2363 | ias_opt->irda_attrib_name); | 2377 | ias_opt->irda_attrib_name); |
2364 | if(ias_attr == (struct ias_attrib *) NULL) { | 2378 | if(ias_attr == (struct ias_attrib *) NULL) { |
2365 | kfree(ias_opt); | 2379 | kfree(ias_opt); |
2366 | return -EINVAL; | 2380 | err = -EINVAL; |
2381 | goto out; | ||
2367 | } | 2382 | } |
2368 | 2383 | ||
2369 | /* Translate from internal to user structure */ | 2384 | /* Translate from internal to user structure */ |
2370 | err = irda_extract_ias_value(ias_opt, ias_attr->value); | 2385 | err = irda_extract_ias_value(ias_opt, ias_attr->value); |
2371 | if(err) { | 2386 | if(err) { |
2372 | kfree(ias_opt); | 2387 | kfree(ias_opt); |
2373 | return err; | 2388 | goto out; |
2374 | } | 2389 | } |
2375 | 2390 | ||
2376 | /* Copy reply to the user */ | 2391 | /* Copy reply to the user */ |
2377 | if (copy_to_user(optval, ias_opt, | 2392 | if (copy_to_user(optval, ias_opt, |
2378 | sizeof(struct irda_ias_set))) { | 2393 | sizeof(struct irda_ias_set))) { |
2379 | kfree(ias_opt); | 2394 | kfree(ias_opt); |
2380 | return -EFAULT; | 2395 | err = -EFAULT; |
2396 | goto out; | ||
2381 | } | 2397 | } |
2382 | /* Note : don't need to put optlen, we checked it */ | 2398 | /* Note : don't need to put optlen, we checked it */ |
2383 | kfree(ias_opt); | 2399 | kfree(ias_opt); |
@@ -2388,17 +2404,22 @@ bed: | |||
2388 | * then wait for the answer to come back. */ | 2404 | * then wait for the answer to come back. */ |
2389 | 2405 | ||
2390 | /* Check that the user has allocated the right space for us */ | 2406 | /* Check that the user has allocated the right space for us */ |
2391 | if (len != sizeof(struct irda_ias_set)) | 2407 | if (len != sizeof(struct irda_ias_set)) { |
2392 | return -EINVAL; | 2408 | err = -EINVAL; |
2409 | goto out; | ||
2410 | } | ||
2393 | 2411 | ||
2394 | ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); | 2412 | ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); |
2395 | if (ias_opt == NULL) | 2413 | if (ias_opt == NULL) { |
2396 | return -ENOMEM; | 2414 | err = -ENOMEM; |
2415 | goto out; | ||
2416 | } | ||
2397 | 2417 | ||
2398 | /* Copy query to the driver. */ | 2418 | /* Copy query to the driver. */ |
2399 | if (copy_from_user(ias_opt, optval, len)) { | 2419 | if (copy_from_user(ias_opt, optval, len)) { |
2400 | kfree(ias_opt); | 2420 | kfree(ias_opt); |
2401 | return -EFAULT; | 2421 | err = -EFAULT; |
2422 | goto out; | ||
2402 | } | 2423 | } |
2403 | 2424 | ||
2404 | /* At this point, there are two cases... | 2425 | /* At this point, there are two cases... |
@@ -2419,7 +2440,8 @@ bed: | |||
2419 | daddr = ias_opt->daddr; | 2440 | daddr = ias_opt->daddr; |
2420 | if((!daddr) || (daddr == DEV_ADDR_ANY)) { | 2441 | if((!daddr) || (daddr == DEV_ADDR_ANY)) { |
2421 | kfree(ias_opt); | 2442 | kfree(ias_opt); |
2422 | return -EINVAL; | 2443 | err = -EINVAL; |
2444 | goto out; | ||
2423 | } | 2445 | } |
2424 | } | 2446 | } |
2425 | 2447 | ||
@@ -2428,7 +2450,8 @@ bed: | |||
2428 | IRDA_WARNING("%s: busy with a previous query\n", | 2450 | IRDA_WARNING("%s: busy with a previous query\n", |
2429 | __func__); | 2451 | __func__); |
2430 | kfree(ias_opt); | 2452 | kfree(ias_opt); |
2431 | return -EBUSY; | 2453 | err = -EBUSY; |
2454 | goto out; | ||
2432 | } | 2455 | } |
2433 | 2456 | ||
2434 | self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self, | 2457 | self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self, |
@@ -2436,7 +2459,8 @@ bed: | |||
2436 | 2459 | ||
2437 | if (self->iriap == NULL) { | 2460 | if (self->iriap == NULL) { |
2438 | kfree(ias_opt); | 2461 | kfree(ias_opt); |
2439 | return -ENOMEM; | 2462 | err = -ENOMEM; |
2463 | goto out; | ||
2440 | } | 2464 | } |
2441 | 2465 | ||
2442 | /* Treat unexpected wakeup as disconnect */ | 2466 | /* Treat unexpected wakeup as disconnect */ |
@@ -2455,7 +2479,8 @@ bed: | |||
2455 | * we can free it regardless! */ | 2479 | * we can free it regardless! */ |
2456 | kfree(ias_opt); | 2480 | kfree(ias_opt); |
2457 | /* Treat signals as disconnect */ | 2481 | /* Treat signals as disconnect */ |
2458 | return -EHOSTUNREACH; | 2482 | err = -EHOSTUNREACH; |
2483 | goto out; | ||
2459 | } | 2484 | } |
2460 | 2485 | ||
2461 | /* Check what happened */ | 2486 | /* Check what happened */ |
@@ -2465,9 +2490,11 @@ bed: | |||
2465 | /* Requested object/attribute doesn't exist */ | 2490 | /* Requested object/attribute doesn't exist */ |
2466 | if((self->errno == IAS_CLASS_UNKNOWN) || | 2491 | if((self->errno == IAS_CLASS_UNKNOWN) || |
2467 | (self->errno == IAS_ATTRIB_UNKNOWN)) | 2492 | (self->errno == IAS_ATTRIB_UNKNOWN)) |
2468 | return (-EADDRNOTAVAIL); | 2493 | err = -EADDRNOTAVAIL; |
2469 | else | 2494 | else |
2470 | return (-EHOSTUNREACH); | 2495 | err = -EHOSTUNREACH; |
2496 | |||
2497 | goto out; | ||
2471 | } | 2498 | } |
2472 | 2499 | ||
2473 | /* Translate from internal to user structure */ | 2500 | /* Translate from internal to user structure */ |
@@ -2476,14 +2503,15 @@ bed: | |||
2476 | irias_delete_value(self->ias_result); | 2503 | irias_delete_value(self->ias_result); |
2477 | if (err) { | 2504 | if (err) { |
2478 | kfree(ias_opt); | 2505 | kfree(ias_opt); |
2479 | return err; | 2506 | goto out; |
2480 | } | 2507 | } |
2481 | 2508 | ||
2482 | /* Copy reply to the user */ | 2509 | /* Copy reply to the user */ |
2483 | if (copy_to_user(optval, ias_opt, | 2510 | if (copy_to_user(optval, ias_opt, |
2484 | sizeof(struct irda_ias_set))) { | 2511 | sizeof(struct irda_ias_set))) { |
2485 | kfree(ias_opt); | 2512 | kfree(ias_opt); |
2486 | return -EFAULT; | 2513 | err = -EFAULT; |
2514 | goto out; | ||
2487 | } | 2515 | } |
2488 | /* Note : don't need to put optlen, we checked it */ | 2516 | /* Note : don't need to put optlen, we checked it */ |
2489 | kfree(ias_opt); | 2517 | kfree(ias_opt); |
@@ -2504,11 +2532,15 @@ bed: | |||
2504 | */ | 2532 | */ |
2505 | 2533 | ||
2506 | /* Check that the user is passing us an int */ | 2534 | /* Check that the user is passing us an int */ |
2507 | if (len != sizeof(int)) | 2535 | if (len != sizeof(int)) { |
2508 | return -EINVAL; | 2536 | err = -EINVAL; |
2537 | goto out; | ||
2538 | } | ||
2509 | /* Get timeout in ms (max time we block the caller) */ | 2539 | /* Get timeout in ms (max time we block the caller) */ |
2510 | if (get_user(val, (int __user *)optval)) | 2540 | if (get_user(val, (int __user *)optval)) { |
2511 | return -EFAULT; | 2541 | err = -EFAULT; |
2542 | goto out; | ||
2543 | } | ||
2512 | 2544 | ||
2513 | /* Tell IrLMP we want to be notified */ | 2545 | /* Tell IrLMP we want to be notified */ |
2514 | irlmp_update_client(self->ckey, self->mask.word, | 2546 | irlmp_update_client(self->ckey, self->mask.word, |
@@ -2520,8 +2552,6 @@ bed: | |||
2520 | 2552 | ||
2521 | /* Wait until a node is discovered */ | 2553 | /* Wait until a node is discovered */ |
2522 | if (!self->cachedaddr) { | 2554 | if (!self->cachedaddr) { |
2523 | int ret = 0; | ||
2524 | |||
2525 | IRDA_DEBUG(1, "%s(), nothing discovered yet, going to sleep...\n", __func__); | 2555 | IRDA_DEBUG(1, "%s(), nothing discovered yet, going to sleep...\n", __func__); |
2526 | 2556 | ||
2527 | /* Set watchdog timer to expire in <val> ms. */ | 2557 | /* Set watchdog timer to expire in <val> ms. */ |
@@ -2534,7 +2564,7 @@ bed: | |||
2534 | /* Wait for IR-LMP to call us back */ | 2564 | /* Wait for IR-LMP to call us back */ |
2535 | __wait_event_interruptible(self->query_wait, | 2565 | __wait_event_interruptible(self->query_wait, |
2536 | (self->cachedaddr != 0 || self->errno == -ETIME), | 2566 | (self->cachedaddr != 0 || self->errno == -ETIME), |
2537 | ret); | 2567 | err); |
2538 | 2568 | ||
2539 | /* If watchdog is still activated, kill it! */ | 2569 | /* If watchdog is still activated, kill it! */ |
2540 | if(timer_pending(&(self->watchdog))) | 2570 | if(timer_pending(&(self->watchdog))) |
@@ -2542,8 +2572,8 @@ bed: | |||
2542 | 2572 | ||
2543 | IRDA_DEBUG(1, "%s(), ...waking up !\n", __func__); | 2573 | IRDA_DEBUG(1, "%s(), ...waking up !\n", __func__); |
2544 | 2574 | ||
2545 | if (ret != 0) | 2575 | if (err != 0) |
2546 | return ret; | 2576 | goto out; |
2547 | } | 2577 | } |
2548 | else | 2578 | else |
2549 | IRDA_DEBUG(1, "%s(), found immediately !\n", | 2579 | IRDA_DEBUG(1, "%s(), found immediately !\n", |
@@ -2566,25 +2596,19 @@ bed: | |||
2566 | * If the user want more details, he should query | 2596 | * If the user want more details, he should query |
2567 | * the whole discovery log and pick one device... | 2597 | * the whole discovery log and pick one device... |
2568 | */ | 2598 | */ |
2569 | if (put_user(daddr, (int __user *)optval)) | 2599 | if (put_user(daddr, (int __user *)optval)) { |
2570 | return -EFAULT; | 2600 | err = -EFAULT; |
2601 | goto out; | ||
2602 | } | ||
2571 | 2603 | ||
2572 | break; | 2604 | break; |
2573 | default: | 2605 | default: |
2574 | return -ENOPROTOOPT; | 2606 | err = -ENOPROTOOPT; |
2575 | } | 2607 | } |
2576 | 2608 | ||
2577 | return 0; | 2609 | out: |
2578 | } | ||
2579 | |||
2580 | static int irda_getsockopt(struct socket *sock, int level, int optname, | ||
2581 | char __user *optval, int __user *optlen) | ||
2582 | { | ||
2583 | int err; | ||
2584 | 2610 | ||
2585 | lock_kernel(); | 2611 | release_sock(sk); |
2586 | err = __irda_getsockopt(sock, level, optname, optval, optlen); | ||
2587 | unlock_kernel(); | ||
2588 | 2612 | ||
2589 | return err; | 2613 | return err; |
2590 | } | 2614 | } |
@@ -2628,7 +2652,7 @@ static const struct proto_ops irda_seqpacket_ops = { | |||
2628 | .socketpair = sock_no_socketpair, | 2652 | .socketpair = sock_no_socketpair, |
2629 | .accept = irda_accept, | 2653 | .accept = irda_accept, |
2630 | .getname = irda_getname, | 2654 | .getname = irda_getname, |
2631 | .poll = irda_datagram_poll, | 2655 | .poll = datagram_poll, |
2632 | .ioctl = irda_ioctl, | 2656 | .ioctl = irda_ioctl, |
2633 | #ifdef CONFIG_COMPAT | 2657 | #ifdef CONFIG_COMPAT |
2634 | .compat_ioctl = irda_compat_ioctl, | 2658 | .compat_ioctl = irda_compat_ioctl, |
@@ -2652,7 +2676,7 @@ static const struct proto_ops irda_dgram_ops = { | |||
2652 | .socketpair = sock_no_socketpair, | 2676 | .socketpair = sock_no_socketpair, |
2653 | .accept = irda_accept, | 2677 | .accept = irda_accept, |
2654 | .getname = irda_getname, | 2678 | .getname = irda_getname, |
2655 | .poll = irda_datagram_poll, | 2679 | .poll = datagram_poll, |
2656 | .ioctl = irda_ioctl, | 2680 | .ioctl = irda_ioctl, |
2657 | #ifdef CONFIG_COMPAT | 2681 | #ifdef CONFIG_COMPAT |
2658 | .compat_ioctl = irda_compat_ioctl, | 2682 | .compat_ioctl = irda_compat_ioctl, |
@@ -2677,7 +2701,7 @@ static const struct proto_ops irda_ultra_ops = { | |||
2677 | .socketpair = sock_no_socketpair, | 2701 | .socketpair = sock_no_socketpair, |
2678 | .accept = sock_no_accept, | 2702 | .accept = sock_no_accept, |
2679 | .getname = irda_getname, | 2703 | .getname = irda_getname, |
2680 | .poll = irda_datagram_poll, | 2704 | .poll = datagram_poll, |
2681 | .ioctl = irda_ioctl, | 2705 | .ioctl = irda_ioctl, |
2682 | #ifdef CONFIG_COMPAT | 2706 | #ifdef CONFIG_COMPAT |
2683 | .compat_ioctl = irda_compat_ioctl, | 2707 | .compat_ioctl = irda_compat_ioctl, |