diff options
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 100 |
1 files changed, 58 insertions, 42 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 648a734e6044..32d778448a00 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -169,12 +169,6 @@ static int tipc_create(struct socket *sock, int protocol) | |||
169 | struct sock *sk; | 169 | struct sock *sk; |
170 | u32 ref; | 170 | u32 ref; |
171 | 171 | ||
172 | if ((sock->type != SOCK_STREAM) && | ||
173 | (sock->type != SOCK_SEQPACKET) && | ||
174 | (sock->type != SOCK_DGRAM) && | ||
175 | (sock->type != SOCK_RDM)) | ||
176 | return -EPROTOTYPE; | ||
177 | |||
178 | if (unlikely(protocol != 0)) | 172 | if (unlikely(protocol != 0)) |
179 | return -EPROTONOSUPPORT; | 173 | return -EPROTONOSUPPORT; |
180 | 174 | ||
@@ -199,6 +193,9 @@ static int tipc_create(struct socket *sock, int protocol) | |||
199 | sock->ops = &msg_ops; | 193 | sock->ops = &msg_ops; |
200 | sock->state = SS_READY; | 194 | sock->state = SS_READY; |
201 | break; | 195 | break; |
196 | default: | ||
197 | tipc_deleteport(ref); | ||
198 | return -EPROTOTYPE; | ||
202 | } | 199 | } |
203 | 200 | ||
204 | sk = sk_alloc(AF_TIPC, GFP_KERNEL, &tipc_proto, 1); | 201 | sk = sk_alloc(AF_TIPC, GFP_KERNEL, &tipc_proto, 1); |
@@ -426,7 +423,7 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) | |||
426 | 423 | ||
427 | if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr))) | 424 | if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr))) |
428 | return -EFAULT; | 425 | return -EFAULT; |
429 | if ((ntohs(hdr.tcm_type) & 0xC000) & (!capable(CAP_NET_ADMIN))) | 426 | if ((ntohs(hdr.tcm_type) & 0xC000) && (!capable(CAP_NET_ADMIN))) |
430 | return -EACCES; | 427 | return -EACCES; |
431 | 428 | ||
432 | return 0; | 429 | return 0; |
@@ -437,7 +434,7 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) | |||
437 | * @iocb: (unused) | 434 | * @iocb: (unused) |
438 | * @sock: socket structure | 435 | * @sock: socket structure |
439 | * @m: message to send | 436 | * @m: message to send |
440 | * @total_len: (unused) | 437 | * @total_len: length of message |
441 | * | 438 | * |
442 | * Message must have an destination specified explicitly. | 439 | * Message must have an destination specified explicitly. |
443 | * Used for SOCK_RDM and SOCK_DGRAM messages, | 440 | * Used for SOCK_RDM and SOCK_DGRAM messages, |
@@ -458,7 +455,8 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
458 | 455 | ||
459 | if (unlikely(!dest)) | 456 | if (unlikely(!dest)) |
460 | return -EDESTADDRREQ; | 457 | return -EDESTADDRREQ; |
461 | if (unlikely(dest->family != AF_TIPC)) | 458 | if (unlikely((m->msg_namelen < sizeof(*dest)) || |
459 | (dest->family != AF_TIPC))) | ||
462 | return -EINVAL; | 460 | return -EINVAL; |
463 | 461 | ||
464 | needs_conn = (sock->state != SS_READY); | 462 | needs_conn = (sock->state != SS_READY); |
@@ -470,6 +468,10 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
470 | if ((tsock->p->published) || | 468 | if ((tsock->p->published) || |
471 | ((sock->type == SOCK_STREAM) && (total_len != 0))) | 469 | ((sock->type == SOCK_STREAM) && (total_len != 0))) |
472 | return -EOPNOTSUPP; | 470 | return -EOPNOTSUPP; |
471 | if (dest->addrtype == TIPC_ADDR_NAME) { | ||
472 | tsock->p->conn_type = dest->addr.name.name.type; | ||
473 | tsock->p->conn_instance = dest->addr.name.name.instance; | ||
474 | } | ||
473 | } | 475 | } |
474 | 476 | ||
475 | if (down_interruptible(&tsock->sem)) | 477 | if (down_interruptible(&tsock->sem)) |
@@ -538,7 +540,7 @@ exit: | |||
538 | * @iocb: (unused) | 540 | * @iocb: (unused) |
539 | * @sock: socket structure | 541 | * @sock: socket structure |
540 | * @m: message to send | 542 | * @m: message to send |
541 | * @total_len: (unused) | 543 | * @total_len: length of message |
542 | * | 544 | * |
543 | * Used for SOCK_SEQPACKET messages and SOCK_STREAM data. | 545 | * Used for SOCK_SEQPACKET messages and SOCK_STREAM data. |
544 | * | 546 | * |
@@ -561,15 +563,15 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
561 | return -ERESTARTSYS; | 563 | return -ERESTARTSYS; |
562 | } | 564 | } |
563 | 565 | ||
564 | if (unlikely(sock->state != SS_CONNECTED)) { | ||
565 | if (sock->state == SS_DISCONNECTING) | ||
566 | res = -EPIPE; | ||
567 | else | ||
568 | res = -ENOTCONN; | ||
569 | goto exit; | ||
570 | } | ||
571 | |||
572 | do { | 566 | do { |
567 | if (unlikely(sock->state != SS_CONNECTED)) { | ||
568 | if (sock->state == SS_DISCONNECTING) | ||
569 | res = -EPIPE; | ||
570 | else | ||
571 | res = -ENOTCONN; | ||
572 | goto exit; | ||
573 | } | ||
574 | |||
573 | res = tipc_send(tsock->p->ref, m->msg_iovlen, m->msg_iov); | 575 | res = tipc_send(tsock->p->ref, m->msg_iovlen, m->msg_iov); |
574 | if (likely(res != -ELINKCONG)) { | 576 | if (likely(res != -ELINKCONG)) { |
575 | exit: | 577 | exit: |
@@ -597,7 +599,8 @@ exit: | |||
597 | * | 599 | * |
598 | * Used for SOCK_STREAM data. | 600 | * Used for SOCK_STREAM data. |
599 | * | 601 | * |
600 | * Returns the number of bytes sent on success, or errno otherwise | 602 | * Returns the number of bytes sent on success (or partial success), |
603 | * or errno if no data sent | ||
601 | */ | 604 | */ |
602 | 605 | ||
603 | 606 | ||
@@ -611,6 +614,7 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, | |||
611 | char __user *curr_start; | 614 | char __user *curr_start; |
612 | int curr_left; | 615 | int curr_left; |
613 | int bytes_to_send; | 616 | int bytes_to_send; |
617 | int bytes_sent; | ||
614 | int res; | 618 | int res; |
615 | 619 | ||
616 | if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE)) | 620 | if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE)) |
@@ -633,11 +637,11 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, | |||
633 | * of small iovec entries into send_packet(). | 637 | * of small iovec entries into send_packet(). |
634 | */ | 638 | */ |
635 | 639 | ||
636 | my_msg = *m; | 640 | curr_iov = m->msg_iov; |
637 | curr_iov = my_msg.msg_iov; | 641 | curr_iovlen = m->msg_iovlen; |
638 | curr_iovlen = my_msg.msg_iovlen; | ||
639 | my_msg.msg_iov = &my_iov; | 642 | my_msg.msg_iov = &my_iov; |
640 | my_msg.msg_iovlen = 1; | 643 | my_msg.msg_iovlen = 1; |
644 | bytes_sent = 0; | ||
641 | 645 | ||
642 | while (curr_iovlen--) { | 646 | while (curr_iovlen--) { |
643 | curr_start = curr_iov->iov_base; | 647 | curr_start = curr_iov->iov_base; |
@@ -648,16 +652,18 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, | |||
648 | ? curr_left : TIPC_MAX_USER_MSG_SIZE; | 652 | ? curr_left : TIPC_MAX_USER_MSG_SIZE; |
649 | my_iov.iov_base = curr_start; | 653 | my_iov.iov_base = curr_start; |
650 | my_iov.iov_len = bytes_to_send; | 654 | my_iov.iov_len = bytes_to_send; |
651 | if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) | 655 | if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) { |
652 | return res; | 656 | return bytes_sent ? bytes_sent : res; |
657 | } | ||
653 | curr_left -= bytes_to_send; | 658 | curr_left -= bytes_to_send; |
654 | curr_start += bytes_to_send; | 659 | curr_start += bytes_to_send; |
660 | bytes_sent += bytes_to_send; | ||
655 | } | 661 | } |
656 | 662 | ||
657 | curr_iov++; | 663 | curr_iov++; |
658 | } | 664 | } |
659 | 665 | ||
660 | return total_len; | 666 | return bytes_sent; |
661 | } | 667 | } |
662 | 668 | ||
663 | /** | 669 | /** |
@@ -727,6 +733,7 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, | |||
727 | u32 anc_data[3]; | 733 | u32 anc_data[3]; |
728 | u32 err; | 734 | u32 err; |
729 | u32 dest_type; | 735 | u32 dest_type; |
736 | int has_name; | ||
730 | int res; | 737 | int res; |
731 | 738 | ||
732 | if (likely(m->msg_controllen == 0)) | 739 | if (likely(m->msg_controllen == 0)) |
@@ -738,10 +745,10 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, | |||
738 | if (unlikely(err)) { | 745 | if (unlikely(err)) { |
739 | anc_data[0] = err; | 746 | anc_data[0] = err; |
740 | anc_data[1] = msg_data_sz(msg); | 747 | anc_data[1] = msg_data_sz(msg); |
741 | if ((res = put_cmsg(m, SOL_SOCKET, TIPC_ERRINFO, 8, anc_data))) | 748 | if ((res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data))) |
742 | return res; | 749 | return res; |
743 | if (anc_data[1] && | 750 | if (anc_data[1] && |
744 | (res = put_cmsg(m, SOL_SOCKET, TIPC_RETDATA, anc_data[1], | 751 | (res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1], |
745 | msg_data(msg)))) | 752 | msg_data(msg)))) |
746 | return res; | 753 | return res; |
747 | } | 754 | } |
@@ -751,25 +758,28 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, | |||
751 | dest_type = msg ? msg_type(msg) : TIPC_DIRECT_MSG; | 758 | dest_type = msg ? msg_type(msg) : TIPC_DIRECT_MSG; |
752 | switch (dest_type) { | 759 | switch (dest_type) { |
753 | case TIPC_NAMED_MSG: | 760 | case TIPC_NAMED_MSG: |
761 | has_name = 1; | ||
754 | anc_data[0] = msg_nametype(msg); | 762 | anc_data[0] = msg_nametype(msg); |
755 | anc_data[1] = msg_namelower(msg); | 763 | anc_data[1] = msg_namelower(msg); |
756 | anc_data[2] = msg_namelower(msg); | 764 | anc_data[2] = msg_namelower(msg); |
757 | break; | 765 | break; |
758 | case TIPC_MCAST_MSG: | 766 | case TIPC_MCAST_MSG: |
767 | has_name = 1; | ||
759 | anc_data[0] = msg_nametype(msg); | 768 | anc_data[0] = msg_nametype(msg); |
760 | anc_data[1] = msg_namelower(msg); | 769 | anc_data[1] = msg_namelower(msg); |
761 | anc_data[2] = msg_nameupper(msg); | 770 | anc_data[2] = msg_nameupper(msg); |
762 | break; | 771 | break; |
763 | case TIPC_CONN_MSG: | 772 | case TIPC_CONN_MSG: |
773 | has_name = (tport->conn_type != 0); | ||
764 | anc_data[0] = tport->conn_type; | 774 | anc_data[0] = tport->conn_type; |
765 | anc_data[1] = tport->conn_instance; | 775 | anc_data[1] = tport->conn_instance; |
766 | anc_data[2] = tport->conn_instance; | 776 | anc_data[2] = tport->conn_instance; |
767 | break; | 777 | break; |
768 | default: | 778 | default: |
769 | anc_data[0] = 0; | 779 | has_name = 0; |
770 | } | 780 | } |
771 | if (anc_data[0] && | 781 | if (has_name && |
772 | (res = put_cmsg(m, SOL_SOCKET, TIPC_DESTNAME, 12, anc_data))) | 782 | (res = put_cmsg(m, SOL_TIPC, TIPC_DESTNAME, 12, anc_data))) |
773 | return res; | 783 | return res; |
774 | 784 | ||
775 | return 0; | 785 | return 0; |
@@ -960,7 +970,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, | |||
960 | restart: | 970 | restart: |
961 | if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) && | 971 | if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) && |
962 | (flags & MSG_DONTWAIT))) { | 972 | (flags & MSG_DONTWAIT))) { |
963 | res = (sz_copied == 0) ? -EWOULDBLOCK : 0; | 973 | res = -EWOULDBLOCK; |
964 | goto exit; | 974 | goto exit; |
965 | } | 975 | } |
966 | 976 | ||
@@ -1051,7 +1061,7 @@ restart: | |||
1051 | 1061 | ||
1052 | exit: | 1062 | exit: |
1053 | up(&tsock->sem); | 1063 | up(&tsock->sem); |
1054 | return res ? res : sz_copied; | 1064 | return sz_copied ? sz_copied : res; |
1055 | } | 1065 | } |
1056 | 1066 | ||
1057 | /** | 1067 | /** |
@@ -1236,7 +1246,8 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
1236 | if (sock->state == SS_READY) | 1246 | if (sock->state == SS_READY) |
1237 | return -EOPNOTSUPP; | 1247 | return -EOPNOTSUPP; |
1238 | 1248 | ||
1239 | /* MOVE THE REST OF THIS ERROR CHECKING TO send_msg()? */ | 1249 | /* Issue Posix-compliant error code if socket is in the wrong state */ |
1250 | |||
1240 | if (sock->state == SS_LISTENING) | 1251 | if (sock->state == SS_LISTENING) |
1241 | return -EOPNOTSUPP; | 1252 | return -EOPNOTSUPP; |
1242 | if (sock->state == SS_CONNECTING) | 1253 | if (sock->state == SS_CONNECTING) |
@@ -1244,13 +1255,20 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
1244 | if (sock->state != SS_UNCONNECTED) | 1255 | if (sock->state != SS_UNCONNECTED) |
1245 | return -EISCONN; | 1256 | return -EISCONN; |
1246 | 1257 | ||
1247 | if ((dst->family != AF_TIPC) || | 1258 | /* |
1248 | ((dst->addrtype != TIPC_ADDR_NAME) && (dst->addrtype != TIPC_ADDR_ID))) | 1259 | * Reject connection attempt using multicast address |
1260 | * | ||
1261 | * Note: send_msg() validates the rest of the address fields, | ||
1262 | * so there's no need to do it here | ||
1263 | */ | ||
1264 | |||
1265 | if (dst->addrtype == TIPC_ADDR_MCAST) | ||
1249 | return -EINVAL; | 1266 | return -EINVAL; |
1250 | 1267 | ||
1251 | /* Send a 'SYN-' to destination */ | 1268 | /* Send a 'SYN-' to destination */ |
1252 | 1269 | ||
1253 | m.msg_name = dest; | 1270 | m.msg_name = dest; |
1271 | m.msg_namelen = destlen; | ||
1254 | if ((res = send_msg(NULL, sock, &m, 0)) < 0) { | 1272 | if ((res = send_msg(NULL, sock, &m, 0)) < 0) { |
1255 | sock->state = SS_DISCONNECTING; | 1273 | sock->state = SS_DISCONNECTING; |
1256 | return res; | 1274 | return res; |
@@ -1269,10 +1287,6 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
1269 | msg = buf_msg(buf); | 1287 | msg = buf_msg(buf); |
1270 | res = auto_connect(sock, tsock, msg); | 1288 | res = auto_connect(sock, tsock, msg); |
1271 | if (!res) { | 1289 | if (!res) { |
1272 | if (dst->addrtype == TIPC_ADDR_NAME) { | ||
1273 | tsock->p->conn_type = dst->addr.name.name.type; | ||
1274 | tsock->p->conn_instance = dst->addr.name.name.instance; | ||
1275 | } | ||
1276 | if (!msg_data_sz(msg)) | 1290 | if (!msg_data_sz(msg)) |
1277 | advance_queue(tsock); | 1291 | advance_queue(tsock); |
1278 | } | 1292 | } |
@@ -1386,7 +1400,7 @@ exit: | |||
1386 | /** | 1400 | /** |
1387 | * shutdown - shutdown socket connection | 1401 | * shutdown - shutdown socket connection |
1388 | * @sock: socket structure | 1402 | * @sock: socket structure |
1389 | * @how: direction to close (always treated as read + write) | 1403 | * @how: direction to close (unused; always treated as read + write) |
1390 | * | 1404 | * |
1391 | * Terminates connection (if necessary), then purges socket's receive queue. | 1405 | * Terminates connection (if necessary), then purges socket's receive queue. |
1392 | * | 1406 | * |
@@ -1469,7 +1483,8 @@ restart: | |||
1469 | * Returns 0 on success, errno otherwise | 1483 | * Returns 0 on success, errno otherwise |
1470 | */ | 1484 | */ |
1471 | 1485 | ||
1472 | static int setsockopt(struct socket *sock, int lvl, int opt, char *ov, int ol) | 1486 | static int setsockopt(struct socket *sock, |
1487 | int lvl, int opt, char __user *ov, int ol) | ||
1473 | { | 1488 | { |
1474 | struct tipc_sock *tsock = tipc_sk(sock->sk); | 1489 | struct tipc_sock *tsock = tipc_sk(sock->sk); |
1475 | u32 value; | 1490 | u32 value; |
@@ -1525,7 +1540,8 @@ static int setsockopt(struct socket *sock, int lvl, int opt, char *ov, int ol) | |||
1525 | * Returns 0 on success, errno otherwise | 1540 | * Returns 0 on success, errno otherwise |
1526 | */ | 1541 | */ |
1527 | 1542 | ||
1528 | static int getsockopt(struct socket *sock, int lvl, int opt, char *ov, int *ol) | 1543 | static int getsockopt(struct socket *sock, |
1544 | int lvl, int opt, char __user *ov, int *ol) | ||
1529 | { | 1545 | { |
1530 | struct tipc_sock *tsock = tipc_sk(sock->sk); | 1546 | struct tipc_sock *tsock = tipc_sk(sock->sk); |
1531 | int len; | 1547 | int len; |