Release 4.11 net/phonet/pep.c
/*
* File: pep.c
*
* Phonet pipe protocol end point socket
*
* Copyright (C) 2008 Nokia Corporation.
*
* Author: Rémi Denis-Courmont
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <linux/kernel.h>
#include <linux/sched/signal.h>
#include <linux/slab.h>
#include <linux/socket.h>
#include <net/sock.h>
#include <net/tcp_states.h>
#include <asm/ioctls.h>
#include <linux/phonet.h>
#include <linux/module.h>
#include <net/phonet/phonet.h>
#include <net/phonet/pep.h>
#include <net/phonet/gprs.h>
/* sk_state values:
* TCP_CLOSE sock not in use yet
* TCP_CLOSE_WAIT disconnected pipe
* TCP_LISTEN listening pipe endpoint
* TCP_SYN_RECV connected pipe in disabled state
* TCP_ESTABLISHED connected pipe in enabled state
*
* pep_sock locking:
* - sk_state, hlist: sock lock needed
* - listener: read only
* - pipe_handle: read only
*/
#define CREDITS_MAX 10
#define CREDITS_THR 7
#define pep_sb_size(s) (((s) + 5) & ~3)
/* 2-bytes head, 32-bits aligned */
/* Get the next TLV sub-block. */
static unsigned char *pep_get_sb(struct sk_buff *skb, u8 *ptype, u8 *plen,
void *buf)
{
void *data = NULL;
struct {
u8 sb_type;
u8 sb_len;
} *ph, h;
int buflen = *plen;
ph = skb_header_pointer(skb, 0, 2, &h);
if (ph == NULL || ph->sb_len < 2 || !pskb_may_pull(skb, ph->sb_len))
return NULL;
ph->sb_len -= 2;
*ptype = ph->sb_type;
*plen = ph->sb_len;
if (buflen > ph->sb_len)
buflen = ph->sb_len;
data = skb_header_pointer(skb, 2, buflen, buf);
__skb_pull(skb, 2 + ph->sb_len);
return data;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Rémi Denis-Courmont | 151 | 100.00% | 1 | 100.00% |
Total | 151 | 100.00% | 1 | 100.00% |
static struct sk_buff *pep_alloc_skb(struct sock *sk, const void *payload,
int len, gfp_t priority)
{
struct sk_buff *skb = alloc_skb(MAX_PNPIPE_HEADER + len, priority);
if (!skb)
return NULL;
skb_set_owner_w(skb, sk);
skb_reserve(skb, MAX_PNPIPE_HEADER);
__skb_put(skb, len);
skb_copy_to_linear_data(skb, payload, len);
__skb_push(skb, sizeof(struct pnpipehdr));
skb_reset_transport_header(skb);
return skb;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Rémi Denis-Courmont | 95 | 100.00% | 2 | 100.00% |
Total | 95 | 100.00% | 2 | 100.00% |
static int pep_reply(struct sock *sk, struct sk_buff *oskb, u8 code,
const void *data, int len, gfp_t priority)
{
const struct pnpipehdr *oph = pnp_hdr(oskb);
struct pnpipehdr *ph;
struct sk_buff *skb;
struct sockaddr_pn peer;
skb = pep_alloc_skb(sk, data, len, priority);
if (!skb)
return -ENOMEM;
ph = pnp_hdr(skb);
ph->utid = oph->utid;
ph->message_id = oph->message_id + 1; /* REQ -> RESP */
ph->pipe_handle = oph->pipe_handle;
ph->error_code = code;
pn_skb_get_src_sockaddr(oskb, &peer);
return pn_skb_send(sk, skb, &peer);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Rémi Denis-Courmont | 136 | 100.00% | 3 | 100.00% |
Total | 136 | 100.00% | 3 | 100.00% |
static int pep_indicate(struct sock *sk, u8 id, u8 code,
const void *data, int len, gfp_t priority)
{
struct pep_sock *pn = pep_sk(sk);
struct pnpipehdr *ph;
struct sk_buff *skb;
skb = pep_alloc_skb(sk, data, len, priority);
if (!skb)
return -ENOMEM;
ph = pnp_hdr(skb);
ph->utid = 0;
ph->message_id = id;
ph->pipe_handle = pn->pipe_handle;
ph->data[0] = code;
return pn_skb_send(sk, skb, NULL);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kumar Sanghvi | 74 | 63.79% | 2 | 50.00% |
Rémi Denis-Courmont | 42 | 36.21% | 2 | 50.00% |
Total | 116 | 100.00% | 4 | 100.00% |
#define PAD 0x00
static int pipe_handler_request(struct sock *sk, u8 id, u8 code,
const void *data, int len)
{
struct pep_sock *pn = pep_sk(sk);
struct pnpipehdr *ph;
struct sk_buff *skb;
skb = pep_alloc_skb(sk, data, len, GFP_KERNEL);
if (!skb)
return -ENOMEM;
ph = pnp_hdr(skb);
ph->utid = id; /* whatever */
ph->message_id = id;
ph->pipe_handle = pn->pipe_handle;
ph->data[0] = code;
return pn_skb_send(sk, skb, NULL);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kumar Sanghvi | 77 | 67.54% | 2 | 50.00% |
Rémi Denis-Courmont | 37 | 32.46% | 2 | 50.00% |
Total | 114 | 100.00% | 4 | 100.00% |
static int pipe_handler_send_created_ind(struct sock *sk)
{
struct pep_sock *pn = pep_sk(sk);
u8 data[4] = {
PN_PIPE_SB_NEGOTIATED_FC, pep_sb_size(2),
pn->tx_fc, pn->rx_fc,
};
return pep_indicate(sk, PNS_PIPE_CREATED_IND, 1 /* sub-blocks */,
data, 4, GFP_ATOMIC);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Rémi Denis-Courmont | 33 | 54.10% | 1 | 33.33% |
Kumar Sanghvi | 28 | 45.90% | 2 | 66.67% |
Total | 61 | 100.00% | 3 | 100.00% |
static int pep_accept_conn(struct sock *sk, struct sk_buff *skb)
{
static const u8 data[20] = {
PAD, PAD, PAD, 2 /* sub-blocks */,
PN_PIPE_SB_REQUIRED_FC_TX, pep_sb_size(5), 3, PAD,
PN_MULTI_CREDIT_FLOW_CONTROL,
PN_ONE_CREDIT_FLOW_CONTROL,
PN_LEGACY_FLOW_CONTROL,
PAD,
PN_PIPE_SB_PREFERRED_FC_RX, pep_sb_size(5), 3, PAD,
PN_MULTI_CREDIT_FLOW_CONTROL,
PN_ONE_CREDIT_FLOW_CONTROL,
PN_LEGACY_FLOW_CONTROL,
PAD,
};
might_sleep();
return pep_reply(sk, skb, PN_PIPE_NO_ERROR, data, sizeof(data),
GFP_KERNEL);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kumar Sanghvi | 95 | 100.00% | 2 | 100.00% |
Total | 95 | 100.00% | 2 | 100.00% |
static int pep_reject_conn(struct sock *sk, struct sk_buff *skb, u8 code,
gfp_t priority)
{
static const u8 data[4] = { PAD, PAD, PAD, 0 /* sub-blocks */ };
WARN_ON(code == PN_PIPE_NO_ERROR);
return pep_reply(sk, skb, code, data, sizeof(data), priority);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kumar Sanghvi | 60 | 89.55% | 1 | 33.33% |
Rémi Denis-Courmont | 7 | 10.45% | 2 | 66.67% |
Total | 67 | 100.00% | 3 | 100.00% |
/* Control requests are not sent by the pipe service and have a specific
* message format. */
static int pep_ctrlreq_error(struct sock *sk, struct sk_buff *oskb, u8 code,
gfp_t priority)
{
const struct pnpipehdr *oph = pnp_hdr(oskb);
struct sk_buff *skb;
struct pnpipehdr *ph;
struct sockaddr_pn dst;
u8 data[4] = {
oph->data[0], /* PEP type */
code, /* error code, at an unusual offset */
PAD, PAD,
};
skb = pep_alloc_skb(sk, data, 4, priority);
if (!skb)
return -ENOMEM;
ph = pnp_hdr(skb);
ph->utid = oph->utid;
ph->message_id = PNS_PEP_CTRL_RESP;
ph->pipe_handle = oph->pipe_handle;
ph->data[0] = oph->data[1]; /* CTRL id */
pn_skb_get_src_sockaddr(oskb, &dst);
return pn_skb_send(sk, skb, &dst);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Rémi Denis-Courmont | 155 | 100.00% | 3 | 100.00% |
Total | 155 | 100.00% | 3 | 100.00% |
static int pipe_snd_status(struct sock *sk, u8 type, u8 status, gfp_t priority)
{
u8 data[4] = { type, PAD, PAD, status };
return pep_indicate(sk, PNS_PEP_STATUS_IND, PN_PEP_TYPE_COMMON,
data, 4, priority);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Rémi Denis-Courmont | 52 | 100.00% | 2 | 100.00% |
Total | 52 | 100.00% | 2 | 100.00% |
/* Send our RX flow control information to the sender.
* Socket must be locked. */
static void pipe_grant_credits(struct sock *sk, gfp_t priority)
{
struct pep_sock *pn = pep_sk(sk);
BUG_ON(sk->sk_state != TCP_ESTABLISHED);
switch (pn->rx_fc) {
case PN_LEGACY_FLOW_CONTROL: /* TODO */
break;
case PN_ONE_CREDIT_FLOW_CONTROL:
if (pipe_snd_status(sk, PN_PEP_IND_FLOW_CONTROL,
PEP_IND_READY, priority) == 0)
pn->rx_credits = 1;
break;
case PN_MULTI_CREDIT_FLOW_CONTROL:
if ((pn->rx_credits + CREDITS_THR) > CREDITS_MAX)
break;
if (pipe_snd_status(sk, PN_PEP_IND_ID_MCFC_GRANT_CREDITS,
CREDITS_MAX - pn->rx_credits,
priority) == 0)
pn->rx_credits = CREDITS_MAX;
break;
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Rémi Denis-Courmont | 113 | 100.00% | 2 | 100.00% |
Total | 113 | 100.00% | 2 | 100.00% |
static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)
{
struct pep_sock *pn = pep_sk(sk);
struct pnpipehdr *hdr;
int wake = 0;
if (!pskb_may_pull(skb, sizeof(*hdr) + 4))
return -EINVAL;
hdr = pnp_hdr(skb);
if (hdr->data[0] != PN_PEP_TYPE_COMMON) {
net_dbg_ratelimited("Phonet unknown PEP type: %u\n",
(unsigned int)hdr->data[0]);
return -EOPNOTSUPP;
}
switch (hdr->data[1]) {
case PN_PEP_IND_FLOW_CONTROL:
switch (pn->tx_fc) {
case PN_LEGACY_FLOW_CONTROL:
switch (hdr->data[4]) {
case PEP_IND_BUSY:
atomic_set(&pn->tx_credits, 0);
break;
case PEP_IND_READY:
atomic_set(&pn->tx_credits, wake = 1);
break;
}
break;
case PN_ONE_CREDIT_FLOW_CONTROL:
if (hdr->data[4] == PEP_IND_READY)
atomic_set(&pn->tx_credits, wake = 1);
break;
}
break;
case PN_PEP_IND_ID_MCFC_GRANT_CREDITS:
if (pn->tx_fc != PN_MULTI_CREDIT_FLOW_CONTROL)
break;
atomic_add(wake = hdr->data[4], &pn->tx_credits);
break;
default:
net_dbg_ratelimited("Phonet unknown PEP indication: %u\n",
(unsigned int)hdr->data[1]);
return -EOPNOTSUPP;
}
if (wake)
sk->sk_write_space(sk);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Rémi Denis-Courmont | 245 | 95.70% | 2 | 40.00% |
Kumar Sanghvi | 7 | 2.73% | 1 | 20.00% |
Joe Perches | 2 | 0.78% | 1 | 20.00% |
Eric Dumazet | 2 | 0.78% | 1 | 20.00% |
Total | 256 | 100.00% | 5 | 100.00% |
static int pipe_rcv_created(struct sock *sk, struct sk_buff *skb)
{
struct pep_sock *pn = pep_sk(sk);
struct pnpipehdr *hdr = pnp_hdr(skb);
u8 n_sb = hdr->data[0];
pn->rx_fc = pn->tx_fc = PN_LEGACY_FLOW_CONTROL;
__skb_pull(skb, sizeof(*hdr));
while (n_sb > 0) {
u8 type, buf[2], len = sizeof(buf);
u8 *data = pep_get_sb(skb, &type, &len, buf);
if (data == NULL)
return -EINVAL;
switch (type) {
case PN_PIPE_SB_NEGOTIATED_FC:
if (len < 2 || (data[0] | data[1]) > 3)
break;
pn->tx_fc = data[0] & 3;
pn->rx_fc = data[1] & 3;
break;
}
n_sb--;
}
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Rémi Denis-Courmont | 176 | 100.00% | 1 | 100.00% |
Total | 176 | 100.00% | 1 | 100.00% |
/* Queue an skb to a connected sock.
* Socket lock must be held. */
static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
{
struct pep_sock *pn = pep_sk(sk);
struct pnpipehdr *hdr = pnp_hdr(skb);
struct sk_buff_head *queue;
int err = 0;
BUG_ON(sk->sk_state == TCP_CLOSE_WAIT);
switch (hdr->message_id) {
case PNS_PEP_CONNECT_REQ:
pep_reject_conn(sk, skb, PN_PIPE_ERR_PEP_IN_USE, GFP_ATOMIC);
break;
case PNS_PEP_DISCONNECT_REQ:
pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC);
sk->sk_state = TCP_CLOSE_WAIT;
if (!sock_flag(sk, SOCK_DEAD))
sk->sk_state_change(sk);
break;
case PNS_PEP_ENABLE_REQ:
/* Wait for PNS_PIPE_(ENABLED|REDIRECTED)_IND */
pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC);
break;
case PNS_PEP_RESET_REQ:
switch (hdr->state_after_reset) {
case PN_PIPE_DISABLE:
pn->init_enable = 0;
break;
case PN_PIPE_ENABLE:
pn->init_enable = 1;
break;
default: /* not allowed to send an error here!? */
err = -EINVAL;
goto out;
}
/* fall through */
case PNS_PEP_DISABLE_REQ:
atomic_set(&pn->tx_credits, 0);
pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC);
break;
case PNS_PEP_CTRL_REQ:
if (skb_queue_len(&pn->ctrlreq_queue) >= PNPIPE_CTRLREQ_MAX) {
atomic_inc(&sk->sk_drops);
break;
}
__skb_pull(skb, 4);
queue = &pn->ctrlreq_queue;
goto queue;
case PNS_PIPE_ALIGNED_DATA:
__skb_pull(skb, 1);
/* fall through */
case PNS_PIPE_DATA:
__skb_pull(skb, 3); /* Pipe data header */
if (!pn_flow_safe(pn->rx_fc)) {
err = sock_queue_rcv_skb(sk, skb);
if (!err)
return NET_RX_SUCCESS;
err = -ENOBUFS;
break;
}
if (pn->rx_credits == 0) {
atomic_inc(&sk->sk_drops);
err = -ENOBUFS;
break;
}
pn->rx_credits--;
queue = &sk->sk_receive_queue;
goto queue;
case PNS_PEP_STATUS_IND:
pipe_rcv_status(sk, skb);
break;
case PNS_PIPE_REDIRECTED_IND:
err = pipe_rcv_created(sk, skb);
break;
case PNS_PIPE_CREATED_IND:
err = pipe_rcv_created(sk, skb);
if (err)
break;
/* fall through */
case PNS_PIPE_RESET_IND:
if (!pn->init_enable)
break;
/* fall through */
case PNS_PIPE_ENABLED_IND:
if (!pn_flow_safe(pn->tx_fc)) {
atomic_set(&pn->tx_credits, 1);
sk->sk_write_space(sk);
}
if (sk->sk_state == TCP_ESTABLISHED)
break; /* Nothing to do */
sk->sk_state = TCP_ESTABLISHED;
pipe_grant_credits(sk, GFP_ATOMIC);
break;
case PNS_PIPE_DISABLED_IND:
sk->sk_state = TCP_SYN_RECV;
pn->rx_credits = 0;
break;
default:
net_dbg_ratelimited("Phonet unknown PEP message: %u\n",
hdr->message_id);
err = -EINVAL;
}
out:
kfree_skb(skb);
return (err == -ENOBUFS) ? NET_RX_DROP : NET_RX_SUCCESS;
queue:
skb->dev = NULL;
skb_set_owner_r(skb, sk);
skb_queue_tail(queue, skb);
if (!sock_flag(sk, SOCK_DEAD))
sk->sk_data_ready(sk);
return NET_RX_SUCCESS;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Rémi Denis-Courmont | 445 | 80.62% | 8 | 72.73% |
Kumar Sanghvi | 106 | 19.20% | 2 | 18.18% |
Joe Perches | 1 | 0.18% | 1 | 9.09% |
Total | 552 | 100.00% | 11 | 100.00% |
/* Destroy connected sock. */
static void pipe_destruct(struct sock *sk)
{
struct pep_sock *pn = pep_sk(sk);
skb_queue_purge(&sk->sk_receive_queue);
skb_queue_purge(&pn->ctrlreq_queue);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Rémi Denis-Courmont | 37 | 100.00% | 2 | 100.00% |
Total | 37 | 100.00% | 2 | 100.00% |
static u8 pipe_negotiate_fc(const u8 *fcs, unsigned int n)
{
unsigned int i;
u8 final_fc = PN_NO_FLOW_CONTROL;
for (i = 0; i < n; i++) {
u8 fc = fcs[i];
if (fc > final_fc && fc < PN_MAX_FLOW_CONTROL)
final_fc = fc;
}
return final_fc;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Rémi Denis-Courmont | 62 | 96.88% | 1 | 50.00% |
Eric Dumazet | 2 | 3.12% | 1 | 50.00% |
Total | 64 | 100.00% | 2 | 100.00% |
static int pep_connresp_rcv(struct sock *sk, struct sk_buff *skb)
{
struct pep_sock *pn = pep_sk(sk);
struct pnpipehdr *hdr;
u8 n_sb;
if (!pskb_pull(skb, sizeof(*hdr) + 4))
return -EINVAL;
hdr = pnp_hdr(skb);
if (hdr->error_code != PN_PIPE_NO_ERROR)
return -ECONNREFUSED;
/* Parse sub-blocks */
n_sb = hdr->data[4];
while (n_sb > 0) {
u8 type, buf[6], len = sizeof(buf);
const u8 *data = pep_get_sb(skb, &type, &len, buf);
if (data == NULL)
return -EINVAL;
switch (type) {
case PN_PIPE_SB_REQUIRED_FC_TX:
if (len < 2 || len < data[0])
break;
pn->tx_fc = pipe_negotiate_fc(data + 2, len - 2);
break;
case PN_PIPE_SB_PREFERRED_FC_RX:
if (len < 2 || len < data[0])
break;
pn->rx_fc = pipe_negotiate_fc(data + 2, len - 2);
break;
}
n_sb--;
}
return pipe_handler_send_created_ind(sk);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Rémi Denis-Courmont | 162 | 75.35% | 2 | 66.67% |
Kumar Sanghvi | 53 | 24.65% | 1 | 33.33% |
Total | 215 | 100.00% | 3 | 100.00% |
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);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dinesh Kumar Sharma | 55 | 100.00% | 1 | 100.00% |
Total | 55 | 100.00% | 1 | 100.00% |
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);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dinesh Kumar Sharma | 57 | 100.00% | 1 | 100.00% |
Total | 57 | 100.00% | 1 | 100.00% |
/* 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)
{
struct pep_sock *pn = pep_sk(sk);
struct pnpipehdr *hdr = pnp_hdr(skb);
int err = NET_RX_SUCCESS;
switch (hdr->message_id) {
case PNS_PIPE_ALIGNED_DATA:
__skb_pull(skb, 1);
/* fall through */
case PNS_PIPE_DATA:
__skb_pull(skb, 3); /* Pipe data header */
if (!pn_flow_safe(pn->rx_fc)) {
err = sock_queue_rcv_skb(sk, skb);
if (!err)
return NET_RX_SUCCESS;
err = NET_RX_DROP;
break;
}
if (pn->rx_credits == 0) {
atomic_inc(&sk->sk_drops);
err = NET_RX_DROP;
break;
}
pn->rx_credits--;
skb->dev = NULL;
skb_set_owner_r(skb, sk);
skb_queue_tail(&sk->sk_receive_queue, skb);
if (!sock_flag(sk, SOCK_DEAD))
sk->sk_data_ready(sk);
return NET_RX_SUCCESS;
case PNS_PEP_CONNECT_RESP:
if (sk->sk_state != TCP_SYN_SENT)
break;
if (!sock_flag(sk, SOCK_DEAD))
sk->sk_state_change(sk);
if (pep_connresp_rcv(sk, 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;
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;
}
sk->sk_state = TCP_ESTABLISHED;
pipe_start_flow_control(sk);
break;
case PNS_PEP_DISCONNECT_RESP:
/* sock should already be dead, nothing to do */
break;
case PNS_PEP_STATUS_IND:
pipe_rcv_status(sk, skb);
break;
}