diff options
Diffstat (limited to 'net/caif/caif_socket.c')
-rw-r--r-- | net/caif/caif_socket.c | 61 |
1 files changed, 37 insertions, 24 deletions
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 3d0e09584fae..8ce904786116 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c | |||
@@ -28,8 +28,8 @@ | |||
28 | MODULE_LICENSE("GPL"); | 28 | MODULE_LICENSE("GPL"); |
29 | MODULE_ALIAS_NETPROTO(AF_CAIF); | 29 | MODULE_ALIAS_NETPROTO(AF_CAIF); |
30 | 30 | ||
31 | #define CAIF_DEF_SNDBUF (CAIF_MAX_PAYLOAD_SIZE*10) | 31 | #define CAIF_DEF_SNDBUF (4096*10) |
32 | #define CAIF_DEF_RCVBUF (CAIF_MAX_PAYLOAD_SIZE*100) | 32 | #define CAIF_DEF_RCVBUF (4096*100) |
33 | 33 | ||
34 | /* | 34 | /* |
35 | * CAIF state is re-using the TCP socket states. | 35 | * CAIF state is re-using the TCP socket states. |
@@ -76,6 +76,7 @@ struct caifsock { | |||
76 | struct caif_connect_request conn_req; | 76 | struct caif_connect_request conn_req; |
77 | struct mutex readlock; | 77 | struct mutex readlock; |
78 | struct dentry *debugfs_socket_dir; | 78 | struct dentry *debugfs_socket_dir; |
79 | int headroom, tailroom, maxframe; | ||
79 | }; | 80 | }; |
80 | 81 | ||
81 | static int rx_flow_is_on(struct caifsock *cf_sk) | 82 | static int rx_flow_is_on(struct caifsock *cf_sk) |
@@ -594,27 +595,32 @@ static int caif_seqpkt_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
594 | goto err; | 595 | goto err; |
595 | noblock = msg->msg_flags & MSG_DONTWAIT; | 596 | noblock = msg->msg_flags & MSG_DONTWAIT; |
596 | 597 | ||
597 | buffer_size = len + CAIF_NEEDED_HEADROOM + CAIF_NEEDED_TAILROOM; | ||
598 | |||
599 | ret = -EMSGSIZE; | ||
600 | if (buffer_size > CAIF_MAX_PAYLOAD_SIZE) | ||
601 | goto err; | ||
602 | |||
603 | timeo = sock_sndtimeo(sk, noblock); | 598 | timeo = sock_sndtimeo(sk, noblock); |
604 | timeo = caif_wait_for_flow_on(container_of(sk, struct caifsock, sk), | 599 | timeo = caif_wait_for_flow_on(container_of(sk, struct caifsock, sk), |
605 | 1, timeo, &ret); | 600 | 1, timeo, &ret); |
606 | 601 | ||
602 | if (ret) | ||
603 | goto err; | ||
607 | ret = -EPIPE; | 604 | ret = -EPIPE; |
608 | if (cf_sk->sk.sk_state != CAIF_CONNECTED || | 605 | if (cf_sk->sk.sk_state != CAIF_CONNECTED || |
609 | sock_flag(sk, SOCK_DEAD) || | 606 | sock_flag(sk, SOCK_DEAD) || |
610 | (sk->sk_shutdown & RCV_SHUTDOWN)) | 607 | (sk->sk_shutdown & RCV_SHUTDOWN)) |
611 | goto err; | 608 | goto err; |
612 | 609 | ||
610 | /* Error if trying to write more than maximum frame size. */ | ||
611 | ret = -EMSGSIZE; | ||
612 | if (len > cf_sk->maxframe && cf_sk->sk.sk_protocol != CAIFPROTO_RFM) | ||
613 | goto err; | ||
614 | |||
615 | buffer_size = len + cf_sk->headroom + cf_sk->tailroom; | ||
616 | |||
613 | ret = -ENOMEM; | 617 | ret = -ENOMEM; |
614 | skb = sock_alloc_send_skb(sk, buffer_size, noblock, &ret); | 618 | skb = sock_alloc_send_skb(sk, buffer_size, noblock, &ret); |
615 | if (!skb) | 619 | |
620 | if (!skb || skb_tailroom(skb) < buffer_size) | ||
616 | goto err; | 621 | goto err; |
617 | skb_reserve(skb, CAIF_NEEDED_HEADROOM); | 622 | |
623 | skb_reserve(skb, cf_sk->headroom); | ||
618 | 624 | ||
619 | ret = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); | 625 | ret = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); |
620 | 626 | ||
@@ -645,7 +651,6 @@ static int caif_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
645 | long timeo; | 651 | long timeo; |
646 | 652 | ||
647 | err = -EOPNOTSUPP; | 653 | err = -EOPNOTSUPP; |
648 | |||
649 | if (unlikely(msg->msg_flags&MSG_OOB)) | 654 | if (unlikely(msg->msg_flags&MSG_OOB)) |
650 | goto out_err; | 655 | goto out_err; |
651 | 656 | ||
@@ -662,8 +667,8 @@ static int caif_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
662 | 667 | ||
663 | size = len-sent; | 668 | size = len-sent; |
664 | 669 | ||
665 | if (size > CAIF_MAX_PAYLOAD_SIZE) | 670 | if (size > cf_sk->maxframe) |
666 | size = CAIF_MAX_PAYLOAD_SIZE; | 671 | size = cf_sk->maxframe; |
667 | 672 | ||
668 | /* If size is more than half of sndbuf, chop up message */ | 673 | /* If size is more than half of sndbuf, chop up message */ |
669 | if (size > ((sk->sk_sndbuf >> 1) - 64)) | 674 | if (size > ((sk->sk_sndbuf >> 1) - 64)) |
@@ -673,14 +678,14 @@ static int caif_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
673 | size = SKB_MAX_ALLOC; | 678 | size = SKB_MAX_ALLOC; |
674 | 679 | ||
675 | skb = sock_alloc_send_skb(sk, | 680 | skb = sock_alloc_send_skb(sk, |
676 | size + CAIF_NEEDED_HEADROOM | 681 | size + cf_sk->headroom + |
677 | + CAIF_NEEDED_TAILROOM, | 682 | cf_sk->tailroom, |
678 | msg->msg_flags&MSG_DONTWAIT, | 683 | msg->msg_flags&MSG_DONTWAIT, |
679 | &err); | 684 | &err); |
680 | if (skb == NULL) | 685 | if (skb == NULL) |
681 | goto out_err; | 686 | goto out_err; |
682 | 687 | ||
683 | skb_reserve(skb, CAIF_NEEDED_HEADROOM); | 688 | skb_reserve(skb, cf_sk->headroom); |
684 | /* | 689 | /* |
685 | * If you pass two values to the sock_alloc_send_skb | 690 | * If you pass two values to the sock_alloc_send_skb |
686 | * it tries to grab the large buffer with GFP_NOFS | 691 | * it tries to grab the large buffer with GFP_NOFS |
@@ -821,17 +826,15 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, | |||
821 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | 826 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); |
822 | long timeo; | 827 | long timeo; |
823 | int err; | 828 | int err; |
829 | int ifindex, headroom, tailroom; | ||
830 | struct net_device *dev; | ||
831 | |||
824 | lock_sock(sk); | 832 | lock_sock(sk); |
825 | 833 | ||
826 | err = -EAFNOSUPPORT; | 834 | err = -EAFNOSUPPORT; |
827 | if (uaddr->sa_family != AF_CAIF) | 835 | if (uaddr->sa_family != AF_CAIF) |
828 | goto out; | 836 | goto out; |
829 | 837 | ||
830 | err = -ESOCKTNOSUPPORT; | ||
831 | if (unlikely(!(sk->sk_type == SOCK_STREAM && | ||
832 | cf_sk->sk.sk_protocol == CAIFPROTO_AT) && | ||
833 | sk->sk_type != SOCK_SEQPACKET)) | ||
834 | goto out; | ||
835 | switch (sock->state) { | 838 | switch (sock->state) { |
836 | case SS_UNCONNECTED: | 839 | case SS_UNCONNECTED: |
837 | /* Normal case, a fresh connect */ | 840 | /* Normal case, a fresh connect */ |
@@ -874,8 +877,7 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, | |||
874 | sk_stream_kill_queues(&cf_sk->sk); | 877 | sk_stream_kill_queues(&cf_sk->sk); |
875 | 878 | ||
876 | err = -EINVAL; | 879 | err = -EINVAL; |
877 | if (addr_len != sizeof(struct sockaddr_caif) || | 880 | if (addr_len != sizeof(struct sockaddr_caif)) |
878 | !uaddr) | ||
879 | goto out; | 881 | goto out; |
880 | 882 | ||
881 | memcpy(&cf_sk->conn_req.sockaddr, uaddr, | 883 | memcpy(&cf_sk->conn_req.sockaddr, uaddr, |
@@ -888,12 +890,23 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, | |||
888 | dbfs_atomic_inc(&cnt.num_connect_req); | 890 | dbfs_atomic_inc(&cnt.num_connect_req); |
889 | cf_sk->layer.receive = caif_sktrecv_cb; | 891 | cf_sk->layer.receive = caif_sktrecv_cb; |
890 | err = caif_connect_client(&cf_sk->conn_req, | 892 | err = caif_connect_client(&cf_sk->conn_req, |
891 | &cf_sk->layer); | 893 | &cf_sk->layer, &ifindex, &headroom, &tailroom); |
892 | if (err < 0) { | 894 | if (err < 0) { |
893 | cf_sk->sk.sk_socket->state = SS_UNCONNECTED; | 895 | cf_sk->sk.sk_socket->state = SS_UNCONNECTED; |
894 | cf_sk->sk.sk_state = CAIF_DISCONNECTED; | 896 | cf_sk->sk.sk_state = CAIF_DISCONNECTED; |
895 | goto out; | 897 | goto out; |
896 | } | 898 | } |
899 | dev = dev_get_by_index(sock_net(sk), ifindex); | ||
900 | cf_sk->headroom = LL_RESERVED_SPACE_EXTRA(dev, headroom); | ||
901 | cf_sk->tailroom = tailroom; | ||
902 | cf_sk->maxframe = dev->mtu - (headroom + tailroom); | ||
903 | dev_put(dev); | ||
904 | if (cf_sk->maxframe < 1) { | ||
905 | pr_warning("CAIF: %s(): CAIF Interface MTU too small (%d)\n", | ||
906 | __func__, dev->mtu); | ||
907 | err = -ENODEV; | ||
908 | goto out; | ||
909 | } | ||
897 | 910 | ||
898 | err = -EINPROGRESS; | 911 | err = -EINPROGRESS; |
899 | wait_connect: | 912 | wait_connect: |