diff options
Diffstat (limited to 'net/appletalk/ddp.c')
-rw-r--r-- | net/appletalk/ddp.c | 105 |
1 files changed, 77 insertions, 28 deletions
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 7cd08b45c52b..31fca64d17a2 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c | |||
@@ -1055,11 +1055,13 @@ static int atalk_release(struct socket *sock) | |||
1055 | { | 1055 | { |
1056 | struct sock *sk = sock->sk; | 1056 | struct sock *sk = sock->sk; |
1057 | 1057 | ||
1058 | lock_kernel(); | ||
1058 | if (sk) { | 1059 | if (sk) { |
1059 | sock_orphan(sk); | 1060 | sock_orphan(sk); |
1060 | sock->sk = NULL; | 1061 | sock->sk = NULL; |
1061 | atalk_destroy_socket(sk); | 1062 | atalk_destroy_socket(sk); |
1062 | } | 1063 | } |
1064 | unlock_kernel(); | ||
1063 | return 0; | 1065 | return 0; |
1064 | } | 1066 | } |
1065 | 1067 | ||
@@ -1135,6 +1137,7 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
1135 | struct sockaddr_at *addr = (struct sockaddr_at *)uaddr; | 1137 | struct sockaddr_at *addr = (struct sockaddr_at *)uaddr; |
1136 | struct sock *sk = sock->sk; | 1138 | struct sock *sk = sock->sk; |
1137 | struct atalk_sock *at = at_sk(sk); | 1139 | struct atalk_sock *at = at_sk(sk); |
1140 | int err; | ||
1138 | 1141 | ||
1139 | if (!sock_flag(sk, SOCK_ZAPPED) || | 1142 | if (!sock_flag(sk, SOCK_ZAPPED) || |
1140 | addr_len != sizeof(struct sockaddr_at)) | 1143 | addr_len != sizeof(struct sockaddr_at)) |
@@ -1143,37 +1146,44 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
1143 | if (addr->sat_family != AF_APPLETALK) | 1146 | if (addr->sat_family != AF_APPLETALK) |
1144 | return -EAFNOSUPPORT; | 1147 | return -EAFNOSUPPORT; |
1145 | 1148 | ||
1149 | lock_kernel(); | ||
1146 | if (addr->sat_addr.s_net == htons(ATADDR_ANYNET)) { | 1150 | if (addr->sat_addr.s_net == htons(ATADDR_ANYNET)) { |
1147 | struct atalk_addr *ap = atalk_find_primary(); | 1151 | struct atalk_addr *ap = atalk_find_primary(); |
1148 | 1152 | ||
1153 | err = -EADDRNOTAVAIL; | ||
1149 | if (!ap) | 1154 | if (!ap) |
1150 | return -EADDRNOTAVAIL; | 1155 | goto out; |
1151 | 1156 | ||
1152 | at->src_net = addr->sat_addr.s_net = ap->s_net; | 1157 | at->src_net = addr->sat_addr.s_net = ap->s_net; |
1153 | at->src_node = addr->sat_addr.s_node= ap->s_node; | 1158 | at->src_node = addr->sat_addr.s_node= ap->s_node; |
1154 | } else { | 1159 | } else { |
1160 | err = -EADDRNOTAVAIL; | ||
1155 | if (!atalk_find_interface(addr->sat_addr.s_net, | 1161 | if (!atalk_find_interface(addr->sat_addr.s_net, |
1156 | addr->sat_addr.s_node)) | 1162 | addr->sat_addr.s_node)) |
1157 | return -EADDRNOTAVAIL; | 1163 | goto out; |
1158 | 1164 | ||
1159 | at->src_net = addr->sat_addr.s_net; | 1165 | at->src_net = addr->sat_addr.s_net; |
1160 | at->src_node = addr->sat_addr.s_node; | 1166 | at->src_node = addr->sat_addr.s_node; |
1161 | } | 1167 | } |
1162 | 1168 | ||
1163 | if (addr->sat_port == ATADDR_ANYPORT) { | 1169 | if (addr->sat_port == ATADDR_ANYPORT) { |
1164 | int n = atalk_pick_and_bind_port(sk, addr); | 1170 | err = atalk_pick_and_bind_port(sk, addr); |
1165 | 1171 | ||
1166 | if (n < 0) | 1172 | if (err < 0) |
1167 | return n; | 1173 | goto out; |
1168 | } else { | 1174 | } else { |
1169 | at->src_port = addr->sat_port; | 1175 | at->src_port = addr->sat_port; |
1170 | 1176 | ||
1177 | err = -EADDRINUSE; | ||
1171 | if (atalk_find_or_insert_socket(sk, addr)) | 1178 | if (atalk_find_or_insert_socket(sk, addr)) |
1172 | return -EADDRINUSE; | 1179 | goto out; |
1173 | } | 1180 | } |
1174 | 1181 | ||
1175 | sock_reset_flag(sk, SOCK_ZAPPED); | 1182 | sock_reset_flag(sk, SOCK_ZAPPED); |
1176 | return 0; | 1183 | err = 0; |
1184 | out: | ||
1185 | unlock_kernel(); | ||
1186 | return err; | ||
1177 | } | 1187 | } |
1178 | 1188 | ||
1179 | /* Set the address we talk to */ | 1189 | /* Set the address we talk to */ |
@@ -1183,6 +1193,7 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr, | |||
1183 | struct sock *sk = sock->sk; | 1193 | struct sock *sk = sock->sk; |
1184 | struct atalk_sock *at = at_sk(sk); | 1194 | struct atalk_sock *at = at_sk(sk); |
1185 | struct sockaddr_at *addr; | 1195 | struct sockaddr_at *addr; |
1196 | int err; | ||
1186 | 1197 | ||
1187 | sk->sk_state = TCP_CLOSE; | 1198 | sk->sk_state = TCP_CLOSE; |
1188 | sock->state = SS_UNCONNECTED; | 1199 | sock->state = SS_UNCONNECTED; |
@@ -1207,12 +1218,15 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr, | |||
1207 | #endif | 1218 | #endif |
1208 | } | 1219 | } |
1209 | 1220 | ||
1221 | lock_kernel(); | ||
1222 | err = -EBUSY; | ||
1210 | if (sock_flag(sk, SOCK_ZAPPED)) | 1223 | if (sock_flag(sk, SOCK_ZAPPED)) |
1211 | if (atalk_autobind(sk) < 0) | 1224 | if (atalk_autobind(sk) < 0) |
1212 | return -EBUSY; | 1225 | goto out; |
1213 | 1226 | ||
1227 | err = -ENETUNREACH; | ||
1214 | if (!atrtr_get_dev(&addr->sat_addr)) | 1228 | if (!atrtr_get_dev(&addr->sat_addr)) |
1215 | return -ENETUNREACH; | 1229 | goto out; |
1216 | 1230 | ||
1217 | at->dest_port = addr->sat_port; | 1231 | at->dest_port = addr->sat_port; |
1218 | at->dest_net = addr->sat_addr.s_net; | 1232 | at->dest_net = addr->sat_addr.s_net; |
@@ -1220,7 +1234,10 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr, | |||
1220 | 1234 | ||
1221 | sock->state = SS_CONNECTED; | 1235 | sock->state = SS_CONNECTED; |
1222 | sk->sk_state = TCP_ESTABLISHED; | 1236 | sk->sk_state = TCP_ESTABLISHED; |
1223 | return 0; | 1237 | err = 0; |
1238 | out: | ||
1239 | unlock_kernel(); | ||
1240 | return err; | ||
1224 | } | 1241 | } |
1225 | 1242 | ||
1226 | /* | 1243 | /* |
@@ -1233,17 +1250,21 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr, | |||
1233 | struct sockaddr_at sat; | 1250 | struct sockaddr_at sat; |
1234 | struct sock *sk = sock->sk; | 1251 | struct sock *sk = sock->sk; |
1235 | struct atalk_sock *at = at_sk(sk); | 1252 | struct atalk_sock *at = at_sk(sk); |
1253 | int err; | ||
1236 | 1254 | ||
1255 | lock_kernel(); | ||
1256 | err = -ENOBUFS; | ||
1237 | if (sock_flag(sk, SOCK_ZAPPED)) | 1257 | if (sock_flag(sk, SOCK_ZAPPED)) |
1238 | if (atalk_autobind(sk) < 0) | 1258 | if (atalk_autobind(sk) < 0) |
1239 | return -ENOBUFS; | 1259 | goto out; |
1240 | 1260 | ||
1241 | *uaddr_len = sizeof(struct sockaddr_at); | 1261 | *uaddr_len = sizeof(struct sockaddr_at); |
1242 | memset(&sat.sat_zero, 0, sizeof(sat.sat_zero)); | 1262 | memset(&sat.sat_zero, 0, sizeof(sat.sat_zero)); |
1243 | 1263 | ||
1244 | if (peer) { | 1264 | if (peer) { |
1265 | err = -ENOTCONN; | ||
1245 | if (sk->sk_state != TCP_ESTABLISHED) | 1266 | if (sk->sk_state != TCP_ESTABLISHED) |
1246 | return -ENOTCONN; | 1267 | goto out; |
1247 | 1268 | ||
1248 | sat.sat_addr.s_net = at->dest_net; | 1269 | sat.sat_addr.s_net = at->dest_net; |
1249 | sat.sat_addr.s_node = at->dest_node; | 1270 | sat.sat_addr.s_node = at->dest_node; |
@@ -1254,9 +1275,23 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr, | |||
1254 | sat.sat_port = at->src_port; | 1275 | sat.sat_port = at->src_port; |
1255 | } | 1276 | } |
1256 | 1277 | ||
1278 | err = 0; | ||
1257 | sat.sat_family = AF_APPLETALK; | 1279 | sat.sat_family = AF_APPLETALK; |
1258 | memcpy(uaddr, &sat, sizeof(sat)); | 1280 | memcpy(uaddr, &sat, sizeof(sat)); |
1259 | return 0; | 1281 | |
1282 | out: | ||
1283 | unlock_kernel(); | ||
1284 | return err; | ||
1285 | } | ||
1286 | |||
1287 | static unsigned int atalk_poll(struct file *file, struct socket *sock, | ||
1288 | poll_table *wait) | ||
1289 | { | ||
1290 | int err; | ||
1291 | lock_kernel(); | ||
1292 | err = datagram_poll(file, sock, wait); | ||
1293 | unlock_kernel(); | ||
1294 | return err; | ||
1260 | } | 1295 | } |
1261 | 1296 | ||
1262 | #if defined(CONFIG_IPDDP) || defined(CONFIG_IPDDP_MODULE) | 1297 | #if defined(CONFIG_IPDDP) || defined(CONFIG_IPDDP_MODULE) |
@@ -1564,23 +1599,28 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr | |||
1564 | if (len > DDP_MAXSZ) | 1599 | if (len > DDP_MAXSZ) |
1565 | return -EMSGSIZE; | 1600 | return -EMSGSIZE; |
1566 | 1601 | ||
1602 | lock_kernel(); | ||
1567 | if (usat) { | 1603 | if (usat) { |
1604 | err = -EBUSY; | ||
1568 | if (sock_flag(sk, SOCK_ZAPPED)) | 1605 | if (sock_flag(sk, SOCK_ZAPPED)) |
1569 | if (atalk_autobind(sk) < 0) | 1606 | if (atalk_autobind(sk) < 0) |
1570 | return -EBUSY; | 1607 | goto out; |
1571 | 1608 | ||
1609 | err = -EINVAL; | ||
1572 | if (msg->msg_namelen < sizeof(*usat) || | 1610 | if (msg->msg_namelen < sizeof(*usat) || |
1573 | usat->sat_family != AF_APPLETALK) | 1611 | usat->sat_family != AF_APPLETALK) |
1574 | return -EINVAL; | 1612 | goto out; |
1575 | 1613 | ||
1614 | err = -EPERM; | ||
1576 | /* netatalk didn't implement this check */ | 1615 | /* netatalk didn't implement this check */ |
1577 | if (usat->sat_addr.s_node == ATADDR_BCAST && | 1616 | if (usat->sat_addr.s_node == ATADDR_BCAST && |
1578 | !sock_flag(sk, SOCK_BROADCAST)) { | 1617 | !sock_flag(sk, SOCK_BROADCAST)) { |
1579 | return -EPERM; | 1618 | goto out; |
1580 | } | 1619 | } |
1581 | } else { | 1620 | } else { |
1621 | err = -ENOTCONN; | ||
1582 | if (sk->sk_state != TCP_ESTABLISHED) | 1622 | if (sk->sk_state != TCP_ESTABLISHED) |
1583 | return -ENOTCONN; | 1623 | goto out; |
1584 | usat = &local_satalk; | 1624 | usat = &local_satalk; |
1585 | usat->sat_family = AF_APPLETALK; | 1625 | usat->sat_family = AF_APPLETALK; |
1586 | usat->sat_port = at->dest_port; | 1626 | usat->sat_port = at->dest_port; |
@@ -1604,8 +1644,9 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr | |||
1604 | 1644 | ||
1605 | rt = atrtr_find(&at_hint); | 1645 | rt = atrtr_find(&at_hint); |
1606 | } | 1646 | } |
1647 | err = ENETUNREACH; | ||
1607 | if (!rt) | 1648 | if (!rt) |
1608 | return -ENETUNREACH; | 1649 | goto out; |
1609 | 1650 | ||
1610 | dev = rt->dev; | 1651 | dev = rt->dev; |
1611 | 1652 | ||
@@ -1615,7 +1656,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr | |||
1615 | size += dev->hard_header_len; | 1656 | size += dev->hard_header_len; |
1616 | skb = sock_alloc_send_skb(sk, size, (flags & MSG_DONTWAIT), &err); | 1657 | skb = sock_alloc_send_skb(sk, size, (flags & MSG_DONTWAIT), &err); |
1617 | if (!skb) | 1658 | if (!skb) |
1618 | return err; | 1659 | goto out; |
1619 | 1660 | ||
1620 | skb->sk = sk; | 1661 | skb->sk = sk; |
1621 | skb_reserve(skb, ddp_dl->header_length); | 1662 | skb_reserve(skb, ddp_dl->header_length); |
@@ -1638,7 +1679,8 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr | |||
1638 | err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); | 1679 | err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); |
1639 | if (err) { | 1680 | if (err) { |
1640 | kfree_skb(skb); | 1681 | kfree_skb(skb); |
1641 | return -EFAULT; | 1682 | err = -EFAULT; |
1683 | goto out; | ||
1642 | } | 1684 | } |
1643 | 1685 | ||
1644 | if (sk->sk_no_check == 1) | 1686 | if (sk->sk_no_check == 1) |
@@ -1677,7 +1719,8 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr | |||
1677 | rt = atrtr_find(&at_lo); | 1719 | rt = atrtr_find(&at_lo); |
1678 | if (!rt) { | 1720 | if (!rt) { |
1679 | kfree_skb(skb); | 1721 | kfree_skb(skb); |
1680 | return -ENETUNREACH; | 1722 | err = -ENETUNREACH; |
1723 | goto out; | ||
1681 | } | 1724 | } |
1682 | dev = rt->dev; | 1725 | dev = rt->dev; |
1683 | skb->dev = dev; | 1726 | skb->dev = dev; |
@@ -1697,7 +1740,9 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr | |||
1697 | } | 1740 | } |
1698 | SOCK_DEBUG(sk, "SK %p: Done write (%Zd).\n", sk, len); | 1741 | SOCK_DEBUG(sk, "SK %p: Done write (%Zd).\n", sk, len); |
1699 | 1742 | ||
1700 | return len; | 1743 | out: |
1744 | unlock_kernel(); | ||
1745 | return err ? : len; | ||
1701 | } | 1746 | } |
1702 | 1747 | ||
1703 | static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | 1748 | static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, |
@@ -1709,10 +1754,13 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr | |||
1709 | int copied = 0; | 1754 | int copied = 0; |
1710 | int offset = 0; | 1755 | int offset = 0; |
1711 | int err = 0; | 1756 | int err = 0; |
1712 | struct sk_buff *skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, | 1757 | struct sk_buff *skb; |
1758 | |||
1759 | lock_kernel(); | ||
1760 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, | ||
1713 | flags & MSG_DONTWAIT, &err); | 1761 | flags & MSG_DONTWAIT, &err); |
1714 | if (!skb) | 1762 | if (!skb) |
1715 | return err; | 1763 | goto out; |
1716 | 1764 | ||
1717 | /* FIXME: use skb->cb to be able to use shared skbs */ | 1765 | /* FIXME: use skb->cb to be able to use shared skbs */ |
1718 | ddp = ddp_hdr(skb); | 1766 | ddp = ddp_hdr(skb); |
@@ -1740,6 +1788,9 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr | |||
1740 | } | 1788 | } |
1741 | 1789 | ||
1742 | skb_free_datagram(sk, skb); /* Free the datagram. */ | 1790 | skb_free_datagram(sk, skb); /* Free the datagram. */ |
1791 | |||
1792 | out: | ||
1793 | unlock_kernel(); | ||
1743 | return err ? : copied; | 1794 | return err ? : copied; |
1744 | } | 1795 | } |
1745 | 1796 | ||
@@ -1830,7 +1881,7 @@ static const struct net_proto_family atalk_family_ops = { | |||
1830 | .owner = THIS_MODULE, | 1881 | .owner = THIS_MODULE, |
1831 | }; | 1882 | }; |
1832 | 1883 | ||
1833 | static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = { | 1884 | static const struct proto_ops atalk_dgram_ops = { |
1834 | .family = PF_APPLETALK, | 1885 | .family = PF_APPLETALK, |
1835 | .owner = THIS_MODULE, | 1886 | .owner = THIS_MODULE, |
1836 | .release = atalk_release, | 1887 | .release = atalk_release, |
@@ -1839,7 +1890,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = { | |||
1839 | .socketpair = sock_no_socketpair, | 1890 | .socketpair = sock_no_socketpair, |
1840 | .accept = sock_no_accept, | 1891 | .accept = sock_no_accept, |
1841 | .getname = atalk_getname, | 1892 | .getname = atalk_getname, |
1842 | .poll = datagram_poll, | 1893 | .poll = atalk_poll, |
1843 | .ioctl = atalk_ioctl, | 1894 | .ioctl = atalk_ioctl, |
1844 | #ifdef CONFIG_COMPAT | 1895 | #ifdef CONFIG_COMPAT |
1845 | .compat_ioctl = atalk_compat_ioctl, | 1896 | .compat_ioctl = atalk_compat_ioctl, |
@@ -1854,8 +1905,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = { | |||
1854 | .sendpage = sock_no_sendpage, | 1905 | .sendpage = sock_no_sendpage, |
1855 | }; | 1906 | }; |
1856 | 1907 | ||
1857 | SOCKOPS_WRAP(atalk_dgram, PF_APPLETALK); | ||
1858 | |||
1859 | static struct notifier_block ddp_notifier = { | 1908 | static struct notifier_block ddp_notifier = { |
1860 | .notifier_call = ddp_device_event, | 1909 | .notifier_call = ddp_device_event, |
1861 | }; | 1910 | }; |