diff options
Diffstat (limited to 'net/phonet/pep.c')
-rw-r--r-- | net/phonet/pep.c | 65 |
1 files changed, 41 insertions, 24 deletions
diff --git a/net/phonet/pep.c b/net/phonet/pep.c index 5f32d217535b..e2a95762abd3 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c | |||
@@ -23,6 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/slab.h> | ||
26 | #include <linux/socket.h> | 27 | #include <linux/socket.h> |
27 | #include <net/sock.h> | 28 | #include <net/sock.h> |
28 | #include <net/tcp_states.h> | 29 | #include <net/tcp_states.h> |
@@ -354,14 +355,15 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
354 | queue = &pn->ctrlreq_queue; | 355 | queue = &pn->ctrlreq_queue; |
355 | goto queue; | 356 | goto queue; |
356 | 357 | ||
358 | case PNS_PIPE_ALIGNED_DATA: | ||
359 | __skb_pull(skb, 1); | ||
360 | /* fall through */ | ||
357 | case PNS_PIPE_DATA: | 361 | case PNS_PIPE_DATA: |
358 | __skb_pull(skb, 3); /* Pipe data header */ | 362 | __skb_pull(skb, 3); /* Pipe data header */ |
359 | if (!pn_flow_safe(pn->rx_fc)) { | 363 | if (!pn_flow_safe(pn->rx_fc)) { |
360 | err = sock_queue_rcv_skb(sk, skb); | 364 | err = sock_queue_rcv_skb(sk, skb); |
361 | if (!err) | 365 | if (!err) |
362 | return 0; | 366 | return 0; |
363 | if (err == -ENOMEM) | ||
364 | atomic_inc(&sk->sk_drops); | ||
365 | break; | 367 | break; |
366 | } | 368 | } |
367 | 369 | ||
@@ -443,6 +445,7 @@ static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb) | |||
443 | struct sockaddr_pn dst; | 445 | struct sockaddr_pn dst; |
444 | u16 peer_type; | 446 | u16 peer_type; |
445 | u8 pipe_handle, enabled, n_sb; | 447 | u8 pipe_handle, enabled, n_sb; |
448 | u8 aligned = 0; | ||
446 | 449 | ||
447 | if (!pskb_pull(skb, sizeof(*hdr) + 4)) | 450 | if (!pskb_pull(skb, sizeof(*hdr) + 4)) |
448 | return -EINVAL; | 451 | return -EINVAL; |
@@ -481,6 +484,9 @@ static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb) | |||
481 | return -EINVAL; | 484 | return -EINVAL; |
482 | peer_type = (peer_type & 0xff00) | data[0]; | 485 | peer_type = (peer_type & 0xff00) | data[0]; |
483 | break; | 486 | break; |
487 | case PN_PIPE_SB_ALIGNED_DATA: | ||
488 | aligned = data[0] != 0; | ||
489 | break; | ||
484 | } | 490 | } |
485 | n_sb--; | 491 | n_sb--; |
486 | } | 492 | } |
@@ -512,6 +518,7 @@ static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb) | |||
512 | newpn->rx_credits = 0; | 518 | newpn->rx_credits = 0; |
513 | newpn->rx_fc = newpn->tx_fc = PN_LEGACY_FLOW_CONTROL; | 519 | newpn->rx_fc = newpn->tx_fc = PN_LEGACY_FLOW_CONTROL; |
514 | newpn->init_enable = enabled; | 520 | newpn->init_enable = enabled; |
521 | newpn->aligned = aligned; | ||
515 | 522 | ||
516 | BUG_ON(!skb_queue_empty(&newsk->sk_receive_queue)); | 523 | BUG_ON(!skb_queue_empty(&newsk->sk_receive_queue)); |
517 | skb_queue_head(&newsk->sk_receive_queue, skb); | 524 | skb_queue_head(&newsk->sk_receive_queue, skb); |
@@ -716,8 +723,8 @@ static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg) | |||
716 | return -EINVAL; | 723 | return -EINVAL; |
717 | 724 | ||
718 | lock_sock(sk); | 725 | lock_sock(sk); |
719 | if (sock_flag(sk, SOCK_URGINLINE) | 726 | if (sock_flag(sk, SOCK_URGINLINE) && |
720 | && !skb_queue_empty(&pn->ctrlreq_queue)) | 727 | !skb_queue_empty(&pn->ctrlreq_queue)) |
721 | answ = skb_peek(&pn->ctrlreq_queue)->len; | 728 | answ = skb_peek(&pn->ctrlreq_queue)->len; |
722 | else if (!skb_queue_empty(&sk->sk_receive_queue)) | 729 | else if (!skb_queue_empty(&sk->sk_receive_queue)) |
723 | answ = skb_peek(&sk->sk_receive_queue)->len; | 730 | answ = skb_peek(&sk->sk_receive_queue)->len; |
@@ -831,11 +838,15 @@ static int pipe_skb_send(struct sock *sk, struct sk_buff *skb) | |||
831 | return -ENOBUFS; | 838 | return -ENOBUFS; |
832 | } | 839 | } |
833 | 840 | ||
834 | skb_push(skb, 3); | 841 | skb_push(skb, 3 + pn->aligned); |
835 | skb_reset_transport_header(skb); | 842 | skb_reset_transport_header(skb); |
836 | ph = pnp_hdr(skb); | 843 | ph = pnp_hdr(skb); |
837 | ph->utid = 0; | 844 | ph->utid = 0; |
838 | ph->message_id = PNS_PIPE_DATA; | 845 | if (pn->aligned) { |
846 | ph->message_id = PNS_PIPE_ALIGNED_DATA; | ||
847 | ph->data[0] = 0; /* padding */ | ||
848 | } else | ||
849 | ph->message_id = PNS_PIPE_DATA; | ||
839 | ph->pipe_handle = pn->pipe_handle; | 850 | ph->pipe_handle = pn->pipe_handle; |
840 | 851 | ||
841 | return pn_skb_send(sk, skb, &pipe_srv); | 852 | return pn_skb_send(sk, skb, &pipe_srv); |
@@ -845,14 +856,26 @@ static int pep_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
845 | struct msghdr *msg, size_t len) | 856 | struct msghdr *msg, size_t len) |
846 | { | 857 | { |
847 | struct pep_sock *pn = pep_sk(sk); | 858 | struct pep_sock *pn = pep_sk(sk); |
848 | struct sk_buff *skb = NULL; | 859 | struct sk_buff *skb; |
849 | long timeo; | 860 | long timeo; |
850 | int flags = msg->msg_flags; | 861 | int flags = msg->msg_flags; |
851 | int err, done; | 862 | int err, done; |
852 | 863 | ||
853 | if (msg->msg_flags & MSG_OOB || !(msg->msg_flags & MSG_EOR)) | 864 | if ((msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL| |
865 | MSG_CMSG_COMPAT)) || | ||
866 | !(msg->msg_flags & MSG_EOR)) | ||
854 | return -EOPNOTSUPP; | 867 | return -EOPNOTSUPP; |
855 | 868 | ||
869 | skb = sock_alloc_send_skb(sk, MAX_PNPIPE_HEADER + len, | ||
870 | flags & MSG_DONTWAIT, &err); | ||
871 | if (!skb) | ||
872 | return -ENOBUFS; | ||
873 | |||
874 | skb_reserve(skb, MAX_PHONET_HEADER + 3); | ||
875 | err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); | ||
876 | if (err < 0) | ||
877 | goto outfree; | ||
878 | |||
856 | lock_sock(sk); | 879 | lock_sock(sk); |
857 | timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); | 880 | timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); |
858 | if ((1 << sk->sk_state) & (TCPF_LISTEN|TCPF_CLOSE)) { | 881 | if ((1 << sk->sk_state) & (TCPF_LISTEN|TCPF_CLOSE)) { |
@@ -896,28 +919,13 @@ disabled: | |||
896 | goto disabled; | 919 | goto disabled; |
897 | } | 920 | } |
898 | 921 | ||
899 | if (!skb) { | ||
900 | skb = sock_alloc_send_skb(sk, MAX_PNPIPE_HEADER + len, | ||
901 | flags & MSG_DONTWAIT, &err); | ||
902 | if (skb == NULL) | ||
903 | goto out; | ||
904 | skb_reserve(skb, MAX_PHONET_HEADER + 3); | ||
905 | |||
906 | if (sk->sk_state != TCP_ESTABLISHED || | ||
907 | !atomic_read(&pn->tx_credits)) | ||
908 | goto disabled; /* sock_alloc_send_skb might sleep */ | ||
909 | } | ||
910 | |||
911 | err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); | ||
912 | if (err < 0) | ||
913 | goto out; | ||
914 | |||
915 | err = pipe_skb_send(sk, skb); | 922 | err = pipe_skb_send(sk, skb); |
916 | if (err >= 0) | 923 | if (err >= 0) |
917 | err = len; /* success! */ | 924 | err = len; /* success! */ |
918 | skb = NULL; | 925 | skb = NULL; |
919 | out: | 926 | out: |
920 | release_sock(sk); | 927 | release_sock(sk); |
928 | outfree: | ||
921 | kfree_skb(skb); | 929 | kfree_skb(skb); |
922 | return err; | 930 | return err; |
923 | } | 931 | } |
@@ -934,6 +942,9 @@ int pep_write(struct sock *sk, struct sk_buff *skb) | |||
934 | struct sk_buff *rskb, *fs; | 942 | struct sk_buff *rskb, *fs; |
935 | int flen = 0; | 943 | int flen = 0; |
936 | 944 | ||
945 | if (pep_sk(sk)->aligned) | ||
946 | return pipe_skb_send(sk, skb); | ||
947 | |||
937 | rskb = alloc_skb(MAX_PNPIPE_HEADER, GFP_ATOMIC); | 948 | rskb = alloc_skb(MAX_PNPIPE_HEADER, GFP_ATOMIC); |
938 | if (!rskb) { | 949 | if (!rskb) { |
939 | kfree_skb(skb); | 950 | kfree_skb(skb); |
@@ -973,6 +984,10 @@ static int pep_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
973 | struct sk_buff *skb; | 984 | struct sk_buff *skb; |
974 | int err; | 985 | int err; |
975 | 986 | ||
987 | if (flags & ~(MSG_OOB|MSG_PEEK|MSG_TRUNC|MSG_DONTWAIT|MSG_WAITALL| | ||
988 | MSG_NOSIGNAL|MSG_CMSG_COMPAT)) | ||
989 | return -EOPNOTSUPP; | ||
990 | |||
976 | if (unlikely(1 << sk->sk_state & (TCPF_LISTEN | TCPF_CLOSE))) | 991 | if (unlikely(1 << sk->sk_state & (TCPF_LISTEN | TCPF_CLOSE))) |
977 | return -ENOTCONN; | 992 | return -ENOTCONN; |
978 | 993 | ||
@@ -980,6 +995,8 @@ static int pep_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
980 | /* Dequeue and acknowledge control request */ | 995 | /* Dequeue and acknowledge control request */ |
981 | struct pep_sock *pn = pep_sk(sk); | 996 | struct pep_sock *pn = pep_sk(sk); |
982 | 997 | ||
998 | if (flags & MSG_PEEK) | ||
999 | return -EOPNOTSUPP; | ||
983 | skb = skb_dequeue(&pn->ctrlreq_queue); | 1000 | skb = skb_dequeue(&pn->ctrlreq_queue); |
984 | if (skb) { | 1001 | if (skb) { |
985 | pep_ctrlreq_error(sk, skb, PN_PIPE_NO_ERROR, | 1002 | pep_ctrlreq_error(sk, skb, PN_PIPE_NO_ERROR, |