diff options
author | Dinesh Kumar Sharma <dinesh.sharma@stericsson.com> | 2011-11-17 20:22:05 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-11-18 14:37:40 -0500 |
commit | bdb6e697b2a76c541960b86ab8fda88f3de1adf2 (patch) | |
tree | 0bd09da4195a4059ab8e353278c2a58757126eff /net/phonet | |
parent | 805dc1d60fb0d4a8b7730748a11dc2688b8f6cf6 (diff) |
Phonet: set the pipe handle using setsockopt
This provides flexibility to set the pipe handle
using setsockopt. The pipe can be enabled (if disabled) later
using ioctl.
Signed-off-by: Hemant Ramdasi <hemant.ramdasi@stericsson.com>
Signed-off-by: Dinesh Kumar Sharma <dinesh.sharma@stericsson.com>
Acked-by: RĂ©mi Denis-Courmont <remi.denis-courmont@nokia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/phonet')
-rw-r--r-- | net/phonet/pep.c | 106 |
1 files changed, 95 insertions, 11 deletions
diff --git a/net/phonet/pep.c b/net/phonet/pep.c index 2ba6e9fb4cbc..9f60008740e3 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c | |||
@@ -534,6 +534,29 @@ static int pep_connresp_rcv(struct sock *sk, struct sk_buff *skb) | |||
534 | return pipe_handler_send_created_ind(sk); | 534 | return pipe_handler_send_created_ind(sk); |
535 | } | 535 | } |
536 | 536 | ||
537 | static int pep_enableresp_rcv(struct sock *sk, struct sk_buff *skb) | ||
538 | { | ||
539 | struct pnpipehdr *hdr = pnp_hdr(skb); | ||
540 | |||
541 | if (hdr->error_code != PN_PIPE_NO_ERROR) | ||
542 | return -ECONNREFUSED; | ||
543 | |||
544 | return pep_indicate(sk, PNS_PIPE_ENABLED_IND, 0 /* sub-blocks */, | ||
545 | NULL, 0, GFP_ATOMIC); | ||
546 | |||
547 | } | ||
548 | |||
549 | static void pipe_start_flow_control(struct sock *sk) | ||
550 | { | ||
551 | struct pep_sock *pn = pep_sk(sk); | ||
552 | |||
553 | if (!pn_flow_safe(pn->tx_fc)) { | ||
554 | atomic_set(&pn->tx_credits, 1); | ||
555 | sk->sk_write_space(sk); | ||
556 | } | ||
557 | pipe_grant_credits(sk, GFP_ATOMIC); | ||
558 | } | ||
559 | |||
537 | /* Queue an skb to an actively connected sock. | 560 | /* Queue an skb to an actively connected sock. |
538 | * Socket lock must be held. */ | 561 | * Socket lock must be held. */ |
539 | static int pipe_handler_do_rcv(struct sock *sk, struct sk_buff *skb) | 562 | static int pipe_handler_do_rcv(struct sock *sk, struct sk_buff *skb) |
@@ -579,13 +602,25 @@ static int pipe_handler_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
579 | sk->sk_state = TCP_CLOSE_WAIT; | 602 | sk->sk_state = TCP_CLOSE_WAIT; |
580 | break; | 603 | break; |
581 | } | 604 | } |
605 | if (pn->init_enable == PN_PIPE_DISABLE) | ||
606 | sk->sk_state = TCP_SYN_RECV; | ||
607 | else { | ||
608 | sk->sk_state = TCP_ESTABLISHED; | ||
609 | pipe_start_flow_control(sk); | ||
610 | } | ||
611 | break; | ||
582 | 612 | ||
583 | sk->sk_state = TCP_ESTABLISHED; | 613 | case PNS_PEP_ENABLE_RESP: |
584 | if (!pn_flow_safe(pn->tx_fc)) { | 614 | if (sk->sk_state != TCP_SYN_SENT) |
585 | atomic_set(&pn->tx_credits, 1); | 615 | break; |
586 | sk->sk_write_space(sk); | 616 | |
617 | if (pep_enableresp_rcv(sk, skb)) { | ||
618 | sk->sk_state = TCP_CLOSE_WAIT; | ||
619 | break; | ||
587 | } | 620 | } |
588 | pipe_grant_credits(sk, GFP_ATOMIC); | 621 | |
622 | sk->sk_state = TCP_ESTABLISHED; | ||
623 | pipe_start_flow_control(sk); | ||
589 | break; | 624 | break; |
590 | 625 | ||
591 | case PNS_PEP_DISCONNECT_RESP: | 626 | case PNS_PEP_DISCONNECT_RESP: |
@@ -864,14 +899,32 @@ static int pep_sock_connect(struct sock *sk, struct sockaddr *addr, int len) | |||
864 | int err; | 899 | int err; |
865 | u8 data[4] = { 0 /* sub-blocks */, PAD, PAD, PAD }; | 900 | u8 data[4] = { 0 /* sub-blocks */, PAD, PAD, PAD }; |
866 | 901 | ||
867 | pn->pipe_handle = 1; /* anything but INVALID_HANDLE */ | 902 | if (pn->pipe_handle == PN_PIPE_INVALID_HANDLE) |
903 | pn->pipe_handle = 1; /* anything but INVALID_HANDLE */ | ||
904 | |||
868 | err = pipe_handler_request(sk, PNS_PEP_CONNECT_REQ, | 905 | err = pipe_handler_request(sk, PNS_PEP_CONNECT_REQ, |
869 | PN_PIPE_ENABLE, data, 4); | 906 | pn->init_enable, data, 4); |
870 | if (err) { | 907 | if (err) { |
871 | pn->pipe_handle = PN_PIPE_INVALID_HANDLE; | 908 | pn->pipe_handle = PN_PIPE_INVALID_HANDLE; |
872 | return err; | 909 | return err; |
873 | } | 910 | } |
911 | |||
874 | sk->sk_state = TCP_SYN_SENT; | 912 | sk->sk_state = TCP_SYN_SENT; |
913 | |||
914 | return 0; | ||
915 | } | ||
916 | |||
917 | static int pep_sock_enable(struct sock *sk, struct sockaddr *addr, int len) | ||
918 | { | ||
919 | int err; | ||
920 | |||
921 | err = pipe_handler_request(sk, PNS_PEP_ENABLE_REQ, PAD, | ||
922 | NULL, 0); | ||
923 | if (err) | ||
924 | return err; | ||
925 | |||
926 | sk->sk_state = TCP_SYN_SENT; | ||
927 | |||
875 | return 0; | 928 | return 0; |
876 | } | 929 | } |
877 | 930 | ||
@@ -879,11 +932,14 @@ static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg) | |||
879 | { | 932 | { |
880 | struct pep_sock *pn = pep_sk(sk); | 933 | struct pep_sock *pn = pep_sk(sk); |
881 | int answ; | 934 | int answ; |
935 | int ret = -ENOIOCTLCMD; | ||
882 | 936 | ||
883 | switch (cmd) { | 937 | switch (cmd) { |
884 | case SIOCINQ: | 938 | case SIOCINQ: |
885 | if (sk->sk_state == TCP_LISTEN) | 939 | if (sk->sk_state == TCP_LISTEN) { |
886 | return -EINVAL; | 940 | ret = -EINVAL; |
941 | break; | ||
942 | } | ||
887 | 943 | ||
888 | lock_sock(sk); | 944 | lock_sock(sk); |
889 | if (sock_flag(sk, SOCK_URGINLINE) && | 945 | if (sock_flag(sk, SOCK_URGINLINE) && |
@@ -894,10 +950,22 @@ static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg) | |||
894 | else | 950 | else |
895 | answ = 0; | 951 | answ = 0; |
896 | release_sock(sk); | 952 | release_sock(sk); |
897 | return put_user(answ, (int __user *)arg); | 953 | ret = put_user(answ, (int __user *)arg); |
954 | break; | ||
955 | |||
956 | case SIOCPNENABLEPIPE: | ||
957 | lock_sock(sk); | ||
958 | if (sk->sk_state == TCP_SYN_SENT) | ||
959 | ret = -EBUSY; | ||
960 | else if (sk->sk_state == TCP_ESTABLISHED) | ||
961 | ret = -EISCONN; | ||
962 | else | ||
963 | ret = pep_sock_enable(sk, NULL, 0); | ||
964 | release_sock(sk); | ||
965 | break; | ||
898 | } | 966 | } |
899 | 967 | ||
900 | return -ENOIOCTLCMD; | 968 | return ret; |
901 | } | 969 | } |
902 | 970 | ||
903 | static int pep_init(struct sock *sk) | 971 | static int pep_init(struct sock *sk) |
@@ -960,6 +1028,18 @@ static int pep_setsockopt(struct sock *sk, int level, int optname, | |||
960 | } | 1028 | } |
961 | goto out_norel; | 1029 | goto out_norel; |
962 | 1030 | ||
1031 | case PNPIPE_HANDLE: | ||
1032 | if ((sk->sk_state == TCP_CLOSE) && | ||
1033 | (val >= 0) && (val < PN_PIPE_INVALID_HANDLE)) | ||
1034 | pn->pipe_handle = val; | ||
1035 | else | ||
1036 | err = -EINVAL; | ||
1037 | break; | ||
1038 | |||
1039 | case PNPIPE_INITSTATE: | ||
1040 | pn->init_enable = !!val; | ||
1041 | break; | ||
1042 | |||
963 | default: | 1043 | default: |
964 | err = -ENOPROTOOPT; | 1044 | err = -ENOPROTOOPT; |
965 | } | 1045 | } |
@@ -995,6 +1075,10 @@ static int pep_getsockopt(struct sock *sk, int level, int optname, | |||
995 | return -EINVAL; | 1075 | return -EINVAL; |
996 | break; | 1076 | break; |
997 | 1077 | ||
1078 | case PNPIPE_INITSTATE: | ||
1079 | val = pn->init_enable; | ||
1080 | break; | ||
1081 | |||
998 | default: | 1082 | default: |
999 | return -ENOPROTOOPT; | 1083 | return -ENOPROTOOPT; |
1000 | } | 1084 | } |