diff options
-rw-r--r-- | net/iucv/af_iucv.c | 163 |
1 files changed, 81 insertions, 82 deletions
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index a9b3a6f9ea95..42b7198a6883 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
@@ -747,108 +747,107 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
747 | goto out; | 747 | goto out; |
748 | } | 748 | } |
749 | 749 | ||
750 | if (sk->sk_state == IUCV_CONNECTED) { | 750 | /* Return if the socket is not in connected state */ |
751 | /* initialize defaults */ | 751 | if (sk->sk_state != IUCV_CONNECTED) { |
752 | cmsg_done = 0; /* check for duplicate headers */ | 752 | err = -ENOTCONN; |
753 | txmsg.class = 0; | 753 | goto out; |
754 | 754 | } | |
755 | /* iterate over control messages */ | ||
756 | for (cmsg = CMSG_FIRSTHDR(msg); cmsg; | ||
757 | cmsg = CMSG_NXTHDR(msg, cmsg)) { | ||
758 | |||
759 | if (!CMSG_OK(msg, cmsg)) { | ||
760 | err = -EINVAL; | ||
761 | goto out; | ||
762 | } | ||
763 | 755 | ||
764 | if (cmsg->cmsg_level != SOL_IUCV) | 756 | /* initialize defaults */ |
765 | continue; | 757 | cmsg_done = 0; /* check for duplicate headers */ |
758 | txmsg.class = 0; | ||
766 | 759 | ||
767 | if (cmsg->cmsg_type & cmsg_done) { | 760 | /* iterate over control messages */ |
768 | err = -EINVAL; | 761 | for (cmsg = CMSG_FIRSTHDR(msg); cmsg; |
769 | goto out; | 762 | cmsg = CMSG_NXTHDR(msg, cmsg)) { |
770 | } | ||
771 | cmsg_done |= cmsg->cmsg_type; | ||
772 | 763 | ||
773 | switch (cmsg->cmsg_type) { | 764 | if (!CMSG_OK(msg, cmsg)) { |
774 | case SCM_IUCV_TRGCLS: | 765 | err = -EINVAL; |
775 | if (cmsg->cmsg_len != CMSG_LEN(TRGCLS_SIZE)) { | 766 | goto out; |
776 | err = -EINVAL; | 767 | } |
777 | goto out; | ||
778 | } | ||
779 | 768 | ||
780 | /* set iucv message target class */ | 769 | if (cmsg->cmsg_level != SOL_IUCV) |
781 | memcpy(&txmsg.class, | 770 | continue; |
782 | (void *) CMSG_DATA(cmsg), TRGCLS_SIZE); | ||
783 | 771 | ||
784 | break; | 772 | if (cmsg->cmsg_type & cmsg_done) { |
773 | err = -EINVAL; | ||
774 | goto out; | ||
775 | } | ||
776 | cmsg_done |= cmsg->cmsg_type; | ||
785 | 777 | ||
786 | default: | 778 | switch (cmsg->cmsg_type) { |
779 | case SCM_IUCV_TRGCLS: | ||
780 | if (cmsg->cmsg_len != CMSG_LEN(TRGCLS_SIZE)) { | ||
787 | err = -EINVAL; | 781 | err = -EINVAL; |
788 | goto out; | 782 | goto out; |
789 | break; | ||
790 | } | 783 | } |
791 | } | ||
792 | 784 | ||
793 | /* allocate one skb for each iucv message: | 785 | /* set iucv message target class */ |
794 | * this is fine for SOCK_SEQPACKET (unless we want to support | 786 | memcpy(&txmsg.class, |
795 | * segmented records using the MSG_EOR flag), but | 787 | (void *) CMSG_DATA(cmsg), TRGCLS_SIZE); |
796 | * for SOCK_STREAM we might want to improve it in future */ | ||
797 | if (!(skb = sock_alloc_send_skb(sk, len, | ||
798 | msg->msg_flags & MSG_DONTWAIT, | ||
799 | &err))) | ||
800 | goto out; | ||
801 | 788 | ||
802 | if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { | 789 | break; |
803 | err = -EFAULT; | 790 | |
804 | goto fail; | 791 | default: |
792 | err = -EINVAL; | ||
793 | goto out; | ||
794 | break; | ||
805 | } | 795 | } |
796 | } | ||
806 | 797 | ||
807 | /* increment and save iucv message tag for msg_completion cbk */ | 798 | /* allocate one skb for each iucv message: |
808 | txmsg.tag = iucv->send_tag++; | 799 | * this is fine for SOCK_SEQPACKET (unless we want to support |
809 | memcpy(CB_TAG(skb), &txmsg.tag, CB_TAG_LEN); | 800 | * segmented records using the MSG_EOR flag), but |
810 | skb_queue_tail(&iucv->send_skb_q, skb); | 801 | * for SOCK_STREAM we might want to improve it in future */ |
802 | skb = sock_alloc_send_skb(sk, len, msg->msg_flags & MSG_DONTWAIT, | ||
803 | &err); | ||
804 | if (!skb) | ||
805 | goto out; | ||
806 | if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { | ||
807 | err = -EFAULT; | ||
808 | goto fail; | ||
809 | } | ||
811 | 810 | ||
812 | if (((iucv->path->flags & IUCV_IPRMDATA) & iucv->flags) | 811 | /* increment and save iucv message tag for msg_completion cbk */ |
813 | && skb->len <= 7) { | 812 | txmsg.tag = iucv->send_tag++; |
814 | err = iucv_send_iprm(iucv->path, &txmsg, skb); | 813 | memcpy(CB_TAG(skb), &txmsg.tag, CB_TAG_LEN); |
814 | skb_queue_tail(&iucv->send_skb_q, skb); | ||
815 | 815 | ||
816 | /* on success: there is no message_complete callback | 816 | if (((iucv->path->flags & IUCV_IPRMDATA) & iucv->flags) |
817 | * for an IPRMDATA msg; remove skb from send queue */ | 817 | && skb->len <= 7) { |
818 | if (err == 0) { | 818 | err = iucv_send_iprm(iucv->path, &txmsg, skb); |
819 | skb_unlink(skb, &iucv->send_skb_q); | ||
820 | kfree_skb(skb); | ||
821 | } | ||
822 | 819 | ||
823 | /* this error should never happen since the | 820 | /* on success: there is no message_complete callback |
824 | * IUCV_IPRMDATA path flag is set... sever path */ | 821 | * for an IPRMDATA msg; remove skb from send queue */ |
825 | if (err == 0x15) { | 822 | if (err == 0) { |
826 | iucv_path_sever(iucv->path, NULL); | 823 | skb_unlink(skb, &iucv->send_skb_q); |
827 | skb_unlink(skb, &iucv->send_skb_q); | 824 | kfree_skb(skb); |
828 | err = -EPIPE; | 825 | } |
829 | goto fail; | 826 | |
830 | } | 827 | /* this error should never happen since the |
831 | } else | 828 | * IUCV_IPRMDATA path flag is set... sever path */ |
832 | err = iucv_message_send(iucv->path, &txmsg, 0, 0, | 829 | if (err == 0x15) { |
833 | (void *) skb->data, skb->len); | 830 | iucv_path_sever(iucv->path, NULL); |
834 | if (err) { | ||
835 | if (err == 3) { | ||
836 | user_id[8] = 0; | ||
837 | memcpy(user_id, iucv->dst_user_id, 8); | ||
838 | appl_id[8] = 0; | ||
839 | memcpy(appl_id, iucv->dst_name, 8); | ||
840 | pr_err("Application %s on z/VM guest %s" | ||
841 | " exceeds message limit\n", | ||
842 | user_id, appl_id); | ||
843 | } | ||
844 | skb_unlink(skb, &iucv->send_skb_q); | 831 | skb_unlink(skb, &iucv->send_skb_q); |
845 | err = -EPIPE; | 832 | err = -EPIPE; |
846 | goto fail; | 833 | goto fail; |
847 | } | 834 | } |
848 | 835 | } else | |
849 | } else { | 836 | err = iucv_message_send(iucv->path, &txmsg, 0, 0, |
850 | err = -ENOTCONN; | 837 | (void *) skb->data, skb->len); |
851 | goto out; | 838 | if (err) { |
839 | if (err == 3) { | ||
840 | user_id[8] = 0; | ||
841 | memcpy(user_id, iucv->dst_user_id, 8); | ||
842 | appl_id[8] = 0; | ||
843 | memcpy(appl_id, iucv->dst_name, 8); | ||
844 | pr_err("Application %s on z/VM guest %s" | ||
845 | " exceeds message limit\n", | ||
846 | appl_id, user_id); | ||
847 | } | ||
848 | skb_unlink(skb, &iucv->send_skb_q); | ||
849 | err = -EPIPE; | ||
850 | goto fail; | ||
852 | } | 851 | } |
853 | 852 | ||
854 | release_sock(sk); | 853 | release_sock(sk); |