Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Dinesh Kumar Sharma and committed by
David S. Miller
bdb6e697 805dc1d6

+97 -11
+2
include/linux/phonet.h
··· 38 38 #define PNPIPE_ENCAP 1 39 39 #define PNPIPE_IFINDEX 2 40 40 #define PNPIPE_HANDLE 3 41 + #define PNPIPE_INITSTATE 4 41 42 42 43 #define PNADDR_ANY 0 43 44 #define PNADDR_BROADCAST 0xFC ··· 50 49 51 50 /* ioctls */ 52 51 #define SIOCPNGETOBJECT (SIOCPROTOPRIVATE + 0) 52 + #define SIOCPNENABLEPIPE (SIOCPROTOPRIVATE + 13) 53 53 #define SIOCPNADDRESOURCE (SIOCPROTOPRIVATE + 14) 54 54 #define SIOCPNDELRESOURCE (SIOCPROTOPRIVATE + 15) 55 55
+95 -11
net/phonet/pep.c
··· 534 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 560 /* Queue an skb to an actively connected sock. 538 561 * Socket lock must be held. */ 539 562 static int pipe_handler_do_rcv(struct sock *sk, struct sk_buff *skb) ··· 602 579 sk->sk_state = TCP_CLOSE_WAIT; 603 580 break; 604 581 } 582 + if (pn->init_enable == PN_PIPE_DISABLE) 583 + sk->sk_state = TCP_SYN_RECV; 584 + else { 585 + sk->sk_state = TCP_ESTABLISHED; 586 + pipe_start_flow_control(sk); 587 + } 588 + break; 589 + 590 + case PNS_PEP_ENABLE_RESP: 591 + if (sk->sk_state != TCP_SYN_SENT) 592 + break; 593 + 594 + if (pep_enableresp_rcv(sk, skb)) { 595 + sk->sk_state = TCP_CLOSE_WAIT; 596 + break; 597 + } 605 598 606 599 sk->sk_state = TCP_ESTABLISHED; 607 - if (!pn_flow_safe(pn->tx_fc)) { 608 - atomic_set(&pn->tx_credits, 1); 609 - sk->sk_write_space(sk); 610 - } 611 - pipe_grant_credits(sk, GFP_ATOMIC); 600 + pipe_start_flow_control(sk); 612 601 break; 613 602 614 603 case PNS_PEP_DISCONNECT_RESP: ··· 899 864 int err; 900 865 u8 data[4] = { 0 /* sub-blocks */, PAD, PAD, PAD }; 901 866 902 - pn->pipe_handle = 1; /* anything but INVALID_HANDLE */ 867 + if (pn->pipe_handle == PN_PIPE_INVALID_HANDLE) 868 + pn->pipe_handle = 1; /* anything but INVALID_HANDLE */ 869 + 903 870 err = pipe_handler_request(sk, PNS_PEP_CONNECT_REQ, 904 - PN_PIPE_ENABLE, data, 4); 871 + pn->init_enable, data, 4); 905 872 if (err) { 906 873 pn->pipe_handle = PN_PIPE_INVALID_HANDLE; 907 874 return err; 908 875 } 876 + 909 877 sk->sk_state = TCP_SYN_SENT; 878 + 879 + return 0; 880 + } 881 + 882 + static int pep_sock_enable(struct sock *sk, struct sockaddr *addr, int len) 883 + { 884 + int err; 885 + 886 + err = pipe_handler_request(sk, PNS_PEP_ENABLE_REQ, PAD, 887 + NULL, 0); 888 + if (err) 889 + return err; 890 + 891 + sk->sk_state = TCP_SYN_SENT; 892 + 910 893 return 0; 911 894 } 912 895 ··· 932 879 { 933 880 struct pep_sock *pn = pep_sk(sk); 934 881 int answ; 882 + int ret = -ENOIOCTLCMD; 935 883 936 884 switch (cmd) { 937 885 case SIOCINQ: 938 - if (sk->sk_state == TCP_LISTEN) 939 - return -EINVAL; 886 + if (sk->sk_state == TCP_LISTEN) { 887 + ret = -EINVAL; 888 + break; 889 + } 940 890 941 891 lock_sock(sk); 942 892 if (sock_flag(sk, SOCK_URGINLINE) && ··· 950 894 else 951 895 answ = 0; 952 896 release_sock(sk); 953 - return put_user(answ, (int __user *)arg); 897 + ret = put_user(answ, (int __user *)arg); 898 + break; 899 + 900 + case SIOCPNENABLEPIPE: 901 + lock_sock(sk); 902 + if (sk->sk_state == TCP_SYN_SENT) 903 + ret = -EBUSY; 904 + else if (sk->sk_state == TCP_ESTABLISHED) 905 + ret = -EISCONN; 906 + else 907 + ret = pep_sock_enable(sk, NULL, 0); 908 + release_sock(sk); 909 + break; 954 910 } 955 911 956 - return -ENOIOCTLCMD; 912 + return ret; 957 913 } 958 914 959 915 static int pep_init(struct sock *sk) ··· 1028 960 } 1029 961 goto out_norel; 1030 962 963 + case PNPIPE_HANDLE: 964 + if ((sk->sk_state == TCP_CLOSE) && 965 + (val >= 0) && (val < PN_PIPE_INVALID_HANDLE)) 966 + pn->pipe_handle = val; 967 + else 968 + err = -EINVAL; 969 + break; 970 + 971 + case PNPIPE_INITSTATE: 972 + pn->init_enable = !!val; 973 + break; 974 + 1031 975 default: 1032 976 err = -ENOPROTOOPT; 1033 977 } ··· 1073 993 val = pn->pipe_handle; 1074 994 if (val == PN_PIPE_INVALID_HANDLE) 1075 995 return -EINVAL; 996 + break; 997 + 998 + case PNPIPE_INITSTATE: 999 + val = pn->init_enable; 1076 1000 break; 1077 1001 1078 1002 default: