aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDinesh Kumar Sharma <dinesh.sharma@stericsson.com>2011-11-17 20:22:05 -0500
committerDavid S. Miller <davem@davemloft.net>2011-11-18 14:37:40 -0500
commitbdb6e697b2a76c541960b86ab8fda88f3de1adf2 (patch)
tree0bd09da4195a4059ab8e353278c2a58757126eff
parent805dc1d60fb0d4a8b7730748a11dc2688b8f6cf6 (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>
-rw-r--r--include/linux/phonet.h2
-rw-r--r--net/phonet/pep.c106
2 files changed, 97 insertions, 11 deletions
diff --git a/include/linux/phonet.h b/include/linux/phonet.h
index f53a4167c5f4..f48bfc80cb4b 100644
--- a/include/linux/phonet.h
+++ b/include/linux/phonet.h
@@ -38,6 +38,7 @@
38#define PNPIPE_ENCAP 1 38#define PNPIPE_ENCAP 1
39#define PNPIPE_IFINDEX 2 39#define PNPIPE_IFINDEX 2
40#define PNPIPE_HANDLE 3 40#define PNPIPE_HANDLE 3
41#define PNPIPE_INITSTATE 4
41 42
42#define PNADDR_ANY 0 43#define PNADDR_ANY 0
43#define PNADDR_BROADCAST 0xFC 44#define PNADDR_BROADCAST 0xFC
@@ -49,6 +50,7 @@
49 50
50/* ioctls */ 51/* ioctls */
51#define SIOCPNGETOBJECT (SIOCPROTOPRIVATE + 0) 52#define SIOCPNGETOBJECT (SIOCPROTOPRIVATE + 0)
53#define SIOCPNENABLEPIPE (SIOCPROTOPRIVATE + 13)
52#define SIOCPNADDRESOURCE (SIOCPROTOPRIVATE + 14) 54#define SIOCPNADDRESOURCE (SIOCPROTOPRIVATE + 14)
53#define SIOCPNDELRESOURCE (SIOCPROTOPRIVATE + 15) 55#define SIOCPNDELRESOURCE (SIOCPROTOPRIVATE + 15)
54 56
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
537static 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
549static 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. */
539static int pipe_handler_do_rcv(struct sock *sk, struct sk_buff *skb) 562static 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
917static 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
903static int pep_init(struct sock *sk) 971static 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 }