Skip to content

Commit

Permalink
Phonet: set the pipe handle using setsockopt
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Dinesh Kumar Sharma <[email protected]>
Acked-by: Rémi Denis-Courmont <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Dinesh Kumar Sharma authored and davem330 committed Nov 18, 2011
1 parent 805dc1d commit bdb6e69
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 11 deletions.
2 changes: 2 additions & 0 deletions include/linux/phonet.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#define PNPIPE_ENCAP 1
#define PNPIPE_IFINDEX 2
#define PNPIPE_HANDLE 3
#define PNPIPE_INITSTATE 4

#define PNADDR_ANY 0
#define PNADDR_BROADCAST 0xFC
Expand All @@ -49,6 +50,7 @@

/* ioctls */
#define SIOCPNGETOBJECT (SIOCPROTOPRIVATE + 0)
#define SIOCPNENABLEPIPE (SIOCPROTOPRIVATE + 13)
#define SIOCPNADDRESOURCE (SIOCPROTOPRIVATE + 14)
#define SIOCPNDELRESOURCE (SIOCPROTOPRIVATE + 15)

Expand Down
106 changes: 95 additions & 11 deletions net/phonet/pep.c
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,29 @@ static int pep_connresp_rcv(struct sock *sk, struct sk_buff *skb)
return pipe_handler_send_created_ind(sk);
}

static int pep_enableresp_rcv(struct sock *sk, struct sk_buff *skb)
{
struct pnpipehdr *hdr = pnp_hdr(skb);

if (hdr->error_code != PN_PIPE_NO_ERROR)
return -ECONNREFUSED;

return pep_indicate(sk, PNS_PIPE_ENABLED_IND, 0 /* sub-blocks */,
NULL, 0, GFP_ATOMIC);

}

static void pipe_start_flow_control(struct sock *sk)
{
struct pep_sock *pn = pep_sk(sk);

if (!pn_flow_safe(pn->tx_fc)) {
atomic_set(&pn->tx_credits, 1);
sk->sk_write_space(sk);
}
pipe_grant_credits(sk, GFP_ATOMIC);
}

/* Queue an skb to an actively connected sock.
* Socket lock must be held. */
static int pipe_handler_do_rcv(struct sock *sk, struct sk_buff *skb)
Expand Down Expand Up @@ -579,13 +602,25 @@ static int pipe_handler_do_rcv(struct sock *sk, struct sk_buff *skb)
sk->sk_state = TCP_CLOSE_WAIT;
break;
}
if (pn->init_enable == PN_PIPE_DISABLE)
sk->sk_state = TCP_SYN_RECV;
else {
sk->sk_state = TCP_ESTABLISHED;
pipe_start_flow_control(sk);
}
break;

sk->sk_state = TCP_ESTABLISHED;
if (!pn_flow_safe(pn->tx_fc)) {
atomic_set(&pn->tx_credits, 1);
sk->sk_write_space(sk);
case PNS_PEP_ENABLE_RESP:
if (sk->sk_state != TCP_SYN_SENT)
break;

if (pep_enableresp_rcv(sk, skb)) {
sk->sk_state = TCP_CLOSE_WAIT;
break;
}
pipe_grant_credits(sk, GFP_ATOMIC);

sk->sk_state = TCP_ESTABLISHED;
pipe_start_flow_control(sk);
break;

case PNS_PEP_DISCONNECT_RESP:
Expand Down Expand Up @@ -864,26 +899,47 @@ static int pep_sock_connect(struct sock *sk, struct sockaddr *addr, int len)
int err;
u8 data[4] = { 0 /* sub-blocks */, PAD, PAD, PAD };

pn->pipe_handle = 1; /* anything but INVALID_HANDLE */
if (pn->pipe_handle == PN_PIPE_INVALID_HANDLE)
pn->pipe_handle = 1; /* anything but INVALID_HANDLE */

err = pipe_handler_request(sk, PNS_PEP_CONNECT_REQ,
PN_PIPE_ENABLE, data, 4);
pn->init_enable, data, 4);
if (err) {
pn->pipe_handle = PN_PIPE_INVALID_HANDLE;
return err;
}

sk->sk_state = TCP_SYN_SENT;

return 0;
}

static int pep_sock_enable(struct sock *sk, struct sockaddr *addr, int len)
{
int err;

err = pipe_handler_request(sk, PNS_PEP_ENABLE_REQ, PAD,
NULL, 0);
if (err)
return err;

sk->sk_state = TCP_SYN_SENT;

return 0;
}

static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
struct pep_sock *pn = pep_sk(sk);
int answ;
int ret = -ENOIOCTLCMD;

switch (cmd) {
case SIOCINQ:
if (sk->sk_state == TCP_LISTEN)
return -EINVAL;
if (sk->sk_state == TCP_LISTEN) {
ret = -EINVAL;
break;
}

lock_sock(sk);
if (sock_flag(sk, SOCK_URGINLINE) &&
Expand All @@ -894,10 +950,22 @@ static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg)
else
answ = 0;
release_sock(sk);
return put_user(answ, (int __user *)arg);
ret = put_user(answ, (int __user *)arg);
break;

case SIOCPNENABLEPIPE:
lock_sock(sk);
if (sk->sk_state == TCP_SYN_SENT)
ret = -EBUSY;
else if (sk->sk_state == TCP_ESTABLISHED)
ret = -EISCONN;
else
ret = pep_sock_enable(sk, NULL, 0);
release_sock(sk);
break;
}

return -ENOIOCTLCMD;
return ret;
}

static int pep_init(struct sock *sk)
Expand Down Expand Up @@ -960,6 +1028,18 @@ static int pep_setsockopt(struct sock *sk, int level, int optname,
}
goto out_norel;

case PNPIPE_HANDLE:
if ((sk->sk_state == TCP_CLOSE) &&
(val >= 0) && (val < PN_PIPE_INVALID_HANDLE))
pn->pipe_handle = val;
else
err = -EINVAL;
break;

case PNPIPE_INITSTATE:
pn->init_enable = !!val;
break;

default:
err = -ENOPROTOOPT;
}
Expand Down Expand Up @@ -995,6 +1075,10 @@ static int pep_getsockopt(struct sock *sk, int level, int optname,
return -EINVAL;
break;

case PNPIPE_INITSTATE:
val = pn->init_enable;
break;

default:
return -ENOPROTOOPT;
}
Expand Down

0 comments on commit bdb6e69

Please sign in to comment.