本文整理汇总了C++中TIPC_SKB_CB函数的典型用法代码示例。如果您正苦于以下问题:C++ TIPC_SKB_CB函数的具体用法?C++ TIPC_SKB_CB怎么用?C++ TIPC_SKB_CB使用的例子?那么, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了TIPC_SKB_CB函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: filter_rcv
/**
* filter_rcv - validate incoming message
* @sk: socket
* @buf: message
*
* Enqueues message on receive queue if acceptable; optionally handles
* disconnect indication for a connected socket.
*
* Called with socket lock already taken; port lock may also be taken.
*
* Returns TIPC error status code (TIPC_OK if message is not to be rejected)
*/
static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
{
struct socket *sock = sk->sk_socket;
struct tipc_msg *msg = buf_msg(buf);
unsigned int limit = rcvbuf_limit(sk, buf);
u32 res = TIPC_OK;
/* Reject message if it is wrong sort of message for socket */
if (msg_type(msg) > TIPC_DIRECT_MSG)
return TIPC_ERR_NO_PORT;
if (sock->state == SS_READY) {
if (msg_connected(msg))
return TIPC_ERR_NO_PORT;
} else {
res = filter_connect(tipc_sk(sk), &buf);
if (res != TIPC_OK || buf == NULL)
return res;
}
/* Reject message if there isn't room to queue it */
if (sk_rmem_alloc_get(sk) + buf->truesize >= limit)
return TIPC_ERR_OVERLOAD;
/* Enqueue message */
TIPC_SKB_CB(buf)->handle = 0;
__skb_queue_tail(&sk->sk_receive_queue, buf);
skb_set_owner_r(buf, sk);
sk->sk_data_ready(sk, 0);
return TIPC_OK;
}
示例2: tipc_msg_bundle
/**
* tipc_msg_bundle(): Append contents of a buffer to tail of an existing one
* @list: the buffer chain of the existing buffer ("bundle")
* @skb: buffer to be appended
* @mtu: max allowable size for the bundle buffer
* Consumes buffer if successful
* Returns true if bundling could be performed, otherwise false
*/
bool tipc_msg_bundle(struct sk_buff_head *list, struct sk_buff *skb, u32 mtu)
{
struct sk_buff *bskb = skb_peek_tail(list);
struct tipc_msg *bmsg = buf_msg(bskb);
struct tipc_msg *msg = buf_msg(skb);
unsigned int bsz = msg_size(bmsg);
unsigned int msz = msg_size(msg);
u32 start = align(bsz);
u32 max = mtu - INT_H_SIZE;
u32 pad = start - bsz;
if (likely(msg_user(msg) == MSG_FRAGMENTER))
return false;
if (unlikely(msg_user(msg) == CHANGEOVER_PROTOCOL))
return false;
if (unlikely(msg_user(msg) == BCAST_PROTOCOL))
return false;
if (likely(msg_user(bmsg) != MSG_BUNDLER))
return false;
if (likely(!TIPC_SKB_CB(bskb)->bundling))
return false;
if (unlikely(skb_tailroom(bskb) < (pad + msz)))
return false;
if (unlikely(max < (start + msz)))
return false;
skb_put(bskb, pad + msz);
skb_copy_to_linear_data_offset(bskb, start, skb->data, msz);
msg_set_size(bmsg, start + msz);
msg_set_msgcnt(bmsg, msg_msgcnt(bmsg) + 1);
kfree_skb(skb);
return true;
}
示例3: tipc_msg_make_bundle
/**
* tipc_msg_make_bundle(): Create bundle buf and append message to its tail
* @list: the buffer chain
* @skb: buffer to be appended and replaced
* @mtu: max allowable size for the bundle buffer, inclusive header
* @dnode: destination node for message. (Not always present in header)
* Replaces buffer if successful
* Returns true if success, otherwise false
*/
bool tipc_msg_make_bundle(struct sk_buff_head *list, struct sk_buff *skb,
u32 mtu, u32 dnode)
{
struct sk_buff *bskb;
struct tipc_msg *bmsg;
struct tipc_msg *msg = buf_msg(skb);
u32 msz = msg_size(msg);
u32 max = mtu - INT_H_SIZE;
if (msg_user(msg) == MSG_FRAGMENTER)
return false;
if (msg_user(msg) == CHANGEOVER_PROTOCOL)
return false;
if (msg_user(msg) == BCAST_PROTOCOL)
return false;
if (msz > (max / 2))
return false;
bskb = tipc_buf_acquire(max);
if (!bskb)
return false;
skb_trim(bskb, INT_H_SIZE);
bmsg = buf_msg(bskb);
tipc_msg_init(bmsg, MSG_BUNDLER, 0, INT_H_SIZE, dnode);
msg_set_seqno(bmsg, msg_seqno(msg));
msg_set_ack(bmsg, msg_ack(msg));
msg_set_bcast_ack(bmsg, msg_bcast_ack(msg));
TIPC_SKB_CB(bskb)->bundling = true;
__skb_queue_tail(list, bskb);
return tipc_msg_bundle(list, skb, mtu);
}
示例4: release
/**
* release - destroy a TIPC socket
* @sock: socket to destroy
*
* This routine cleans up any messages that are still queued on the socket.
* For DGRAM and RDM socket types, all queued messages are rejected.
* For SEQPACKET and STREAM socket types, the first message is rejected
* and any others are discarded. (If the first message on a STREAM socket
* is partially-read, it is discarded and the next one is rejected instead.)
*
* NOTE: Rejected messages are not necessarily returned to the sender! They
* are returned or discarded according to the "destination droppable" setting
* specified for the message by the sender.
*
* Returns 0 on success, errno otherwise
*/
static int release(struct socket *sock)
{
struct sock *sk = sock->sk;
struct tipc_port *tport;
struct sk_buff *buf;
int res;
/*
* Exit if socket isn't fully initialized (occurs when a failed accept()
* releases a pre-allocated child socket that was never used)
*/
if (sk == NULL)
return 0;
tport = tipc_sk_port(sk);
lock_sock(sk);
/*
* Reject all unreceived messages, except on an active connection
* (which disconnects locally & sends a 'FIN+' to peer)
*/
while (sock->state != SS_DISCONNECTING) {
buf = __skb_dequeue(&sk->sk_receive_queue);
if (buf == NULL)
break;
atomic_dec(&tipc_queue_size);
if (TIPC_SKB_CB(buf)->handle != 0)
kfree_skb(buf);
else {
if ((sock->state == SS_CONNECTING) ||
(sock->state == SS_CONNECTED)) {
sock->state = SS_DISCONNECTING;
tipc_disconnect(tport->ref);
}
tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
}
}
/*
* Delete TIPC port; this ensures no more messages are queued
* (also disconnects an active connection & sends a 'FIN-' to peer)
*/
res = tipc_deleteport(tport->ref);
/* Discard any remaining (connection-based) messages in receive queue */
discard_rx_queue(sk);
/* Reject any messages that accumulated in backlog queue */
sock->state = SS_DISCONNECTING;
release_sock(sk);
sock_put(sk);
sock->sk = NULL;
return res;
}
示例5: shutdown
static int shutdown(struct socket *sock, int how)
{
struct sock *sk = sock->sk;
struct tipc_port *tport = tipc_sk_port(sk);
struct sk_buff *buf;
int res;
if (how != SHUT_RDWR)
return -EINVAL;
lock_sock(sk);
switch (sock->state) {
case SS_CONNECTING:
case SS_CONNECTED:
/* Disconnect and send a 'FIN+' or 'FIN-' message to peer */
restart:
buf = __skb_dequeue(&sk->sk_receive_queue);
if (buf) {
atomic_dec(&tipc_queue_size);
if (TIPC_SKB_CB(buf)->handle != 0) {
kfree_skb(buf);
goto restart;
}
tipc_disconnect(tport->ref);
tipc_reject_msg(buf, TIPC_CONN_SHUTDOWN);
} else {
tipc_shutdown(tport->ref);
}
sock->state = SS_DISCONNECTING;
/* fall through */
case SS_DISCONNECTING:
/* Discard any unreceived messages; wake up sleeping tasks */
discard_rx_queue(sk);
if (waitqueue_active(sk_sleep(sk)))
wake_up_interruptible(sk_sleep(sk));
res = 0;
break;
default:
res = -ENOTCONN;
}
release_sock(sk);
return res;
}
示例6: release
static int release(struct socket *sock)
{
struct tipc_sock *tsock = tipc_sk(sock->sk);
struct sock *sk = sock->sk;
int res = TIPC_OK;
struct sk_buff *buf;
dbg("sock_delete: %x\n",tsock);
if (!tsock)
return 0;
down_interruptible(&tsock->sem);
if (!sock->sk) {
up(&tsock->sem);
return 0;
}
/* Reject unreceived messages, unless no longer connected */
while (sock->state != SS_DISCONNECTING) {
sock_lock(tsock);
buf = skb_dequeue(&sk->sk_receive_queue);
if (!buf)
tsock->p->usr_handle = NULL;
sock_unlock(tsock);
if (!buf)
break;
if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf)))
buf_discard(buf);
else
tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
atomic_dec(&tipc_queue_size);
}
/* Delete TIPC port */
res = tipc_deleteport(tsock->p->ref);
sock->sk = NULL;
/* Discard any remaining messages */
while ((buf = skb_dequeue(&sk->sk_receive_queue))) {
buf_discard(buf);
atomic_dec(&tipc_queue_size);
}
up(&tsock->sem);
sock_put(sk);
atomic_dec(&tipc_user_count);
return res;
}
示例7: shutdown
/**
* shutdown - shutdown socket connection
* @sock: socket structure
* @how: direction to close (must be SHUT_RDWR)
*
* Terminates connection (if necessary), then purges socket's receive queue.
*
* Returns 0 on success, errno otherwise
*/
static int shutdown(struct socket *sock, int how)
{
struct sock *sk = sock->sk;
struct tipc_port *tport = tipc_sk_port(sk);
struct sk_buff *buf;
int res;
if (how != SHUT_RDWR)
return -EINVAL;
lock_sock(sk);
switch (sock->state) {
case SS_CONNECTING:
case SS_CONNECTED:
restart:
/* Disconnect and send a 'FIN+' or 'FIN-' message to peer */
buf = __skb_dequeue(&sk->sk_receive_queue);
if (buf) {
if (TIPC_SKB_CB(buf)->handle != 0) {
kfree_skb(buf);
goto restart;
}
tipc_disconnect(tport->ref);
tipc_reject_msg(buf, TIPC_CONN_SHUTDOWN);
} else {
tipc_shutdown(tport->ref);
}
sock->state = SS_DISCONNECTING;
/* fall through */
case SS_DISCONNECTING:
/* Discard any unreceived messages */
__skb_queue_purge(&sk->sk_receive_queue);
/* Wake up anyone sleeping in poll */
sk->sk_state_change(sk);
res = 0;
break;
default:
res = -ENOTCONN;
}
release_sock(sk);
return res;
}
示例8: filter_rcv
static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
{
struct socket *sock = sk->sk_socket;
struct tipc_msg *msg = buf_msg(buf);
u32 recv_q_len;
/* Reject message if it is wrong sort of message for socket */
/*
* WOULD IT BE BETTER TO JUST DISCARD THESE MESSAGES INSTEAD?
* "NO PORT" ISN'T REALLY THE RIGHT ERROR CODE, AND THERE MAY
* BE SECURITY IMPLICATIONS INHERENT IN REJECTING INVALID TRAFFIC
*/
if (sock->state == SS_READY) {
if (msg_connected(msg))
return TIPC_ERR_NO_PORT;
} else {
if (msg_mcast(msg))
return TIPC_ERR_NO_PORT;
if (sock->state == SS_CONNECTED) {
if (!msg_connected(msg))
return TIPC_ERR_NO_PORT;
} else if (sock->state == SS_CONNECTING) {
if (!msg_connected(msg) && (msg_errcode(msg) == 0))
return TIPC_ERR_NO_PORT;
} else if (sock->state == SS_LISTENING) {
if (msg_connected(msg) || msg_errcode(msg))
return TIPC_ERR_NO_PORT;
} else if (sock->state == SS_DISCONNECTING) {
return TIPC_ERR_NO_PORT;
} else /* (sock->state == SS_UNCONNECTED) */ {
if (msg_connected(msg) || msg_errcode(msg))
return TIPC_ERR_NO_PORT;
}
}
/* Reject message if there isn't room to queue it */
recv_q_len = (u32)atomic_read(&tipc_queue_size);
if (unlikely(recv_q_len >= OVERLOAD_LIMIT_BASE)) {
if (rx_queue_full(msg, recv_q_len, OVERLOAD_LIMIT_BASE))
return TIPC_ERR_OVERLOAD;
}
recv_q_len = skb_queue_len(&sk->sk_receive_queue);
if (unlikely(recv_q_len >= (OVERLOAD_LIMIT_BASE / 2))) {
if (rx_queue_full(msg, recv_q_len, OVERLOAD_LIMIT_BASE / 2))
return TIPC_ERR_OVERLOAD;
}
/* Enqueue message (finally!) */
TIPC_SKB_CB(buf)->handle = 0;
atomic_inc(&tipc_queue_size);
__skb_queue_tail(&sk->sk_receive_queue, buf);
/* Initiate connection termination for an incoming 'FIN' */
if (unlikely(msg_errcode(msg) && (sock->state == SS_CONNECTED))) {
sock->state = SS_DISCONNECTING;
tipc_disconnect_port(tipc_sk_port(sk));
}
if (waitqueue_active(sk_sleep(sk)))
wake_up_interruptible(sk_sleep(sk));
return TIPC_OK;
}
示例9: recv_stream
static int recv_stream(struct kiocb *iocb, struct socket *sock,
struct msghdr *m, size_t buf_len, int flags)
{
struct sock *sk = sock->sk;
struct tipc_port *tport = tipc_sk_port(sk);
struct sk_buff *buf;
struct tipc_msg *msg;
long timeout;
unsigned int sz;
int sz_to_copy, target, needed;
int sz_copied = 0;
u32 err;
int res = 0;
/* Catch invalid receive attempts */
if (unlikely(!buf_len))
return -EINVAL;
lock_sock(sk);
if (unlikely((sock->state == SS_UNCONNECTED) ||
(sock->state == SS_CONNECTING))) {
res = -ENOTCONN;
goto exit;
}
/* will be updated in set_orig_addr() if needed */
m->msg_namelen = 0;
target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
restart:
/* Look for a message in receive queue; wait if necessary */
while (skb_queue_empty(&sk->sk_receive_queue)) {
if (sock->state == SS_DISCONNECTING) {
res = -ENOTCONN;
goto exit;
}
if (timeout <= 0L) {
res = timeout ? timeout : -EWOULDBLOCK;
goto exit;
}
release_sock(sk);
timeout = wait_event_interruptible_timeout(*sk_sleep(sk),
tipc_rx_ready(sock),
timeout);
lock_sock(sk);
}
/* Look at first message in receive queue */
buf = skb_peek(&sk->sk_receive_queue);
msg = buf_msg(buf);
sz = msg_data_sz(msg);
err = msg_errcode(msg);
/* Discard an empty non-errored message & try again */
if ((!sz) && (!err)) {
advance_rx_queue(sk);
goto restart;
}
/* Optionally capture sender's address & ancillary data of first msg */
if (sz_copied == 0) {
set_orig_addr(m, msg);
res = anc_data_recv(m, msg, tport);
if (res)
goto exit;
}
/* Capture message data (if valid) & compute return value (always) */
if (!err) {
u32 offset = (u32)(unsigned long)(TIPC_SKB_CB(buf)->handle);
sz -= offset;
needed = (buf_len - sz_copied);
sz_to_copy = (sz <= needed) ? sz : needed;
res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg) + offset,
m->msg_iov, sz_to_copy);
if (res)
goto exit;
sz_copied += sz_to_copy;
if (sz_to_copy < sz) {
if (!(flags & MSG_PEEK))
TIPC_SKB_CB(buf)->handle =
(void *)(unsigned long)(offset + sz_to_copy);
goto exit;
}
} else {
if (sz_copied != 0)
goto exit; /* can't add error msg to valid data */
//.........这里部分代码省略.........
示例10: recv_stream
static int recv_stream(struct kiocb *iocb, struct socket *sock,
struct msghdr *m, size_t buf_len, int flags)
{
struct tipc_sock *tsock = tipc_sk(sock->sk);
struct sk_buff *buf;
struct tipc_msg *msg;
unsigned int q_len;
unsigned int sz;
int sz_to_copy;
int sz_copied = 0;
int needed;
char __user *crs = m->msg_iov->iov_base;
unsigned char *buf_crs;
u32 err;
int res;
/* Currently doesn't support receiving into multiple iovec entries */
if (m->msg_iovlen != 1)
return -EOPNOTSUPP;
/* Catch invalid receive attempts */
if (unlikely(!buf_len))
return -EINVAL;
if (unlikely(sock->state == SS_DISCONNECTING)) {
if (skb_queue_len(&sock->sk->sk_receive_queue) == 0)
return -ENOTCONN;
} else if (unlikely(sock->state != SS_CONNECTED))
return -ENOTCONN;
/* Look for a message in receive queue; wait if necessary */
if (unlikely(down_interruptible(&tsock->sem)))
return -ERESTARTSYS;
restart:
if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) &&
(flags & MSG_DONTWAIT))) {
res = -EWOULDBLOCK;
goto exit;
}
if ((res = wait_event_interruptible(
*sock->sk->sk_sleep,
((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) ||
(sock->state == SS_DISCONNECTING))) )) {
goto exit;
}
/* Catch attempt to receive on an already terminated connection */
/* [THIS CHECK MAY OVERLAP WITH AN EARLIER CHECK] */
if (!q_len) {
res = -ENOTCONN;
goto exit;
}
/* Get access to first message in receive queue */
buf = skb_peek(&sock->sk->sk_receive_queue);
msg = buf_msg(buf);
sz = msg_data_sz(msg);
err = msg_errcode(msg);
/* Discard an empty non-errored message & try again */
if ((!sz) && (!err)) {
advance_queue(tsock);
goto restart;
}
/* Optionally capture sender's address & ancillary data of first msg */
if (sz_copied == 0) {
set_orig_addr(m, msg);
if ((res = anc_data_recv(m, msg, tsock->p)))
goto exit;
}
/* Capture message data (if valid) & compute return value (always) */
if (!err) {
buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle);
sz = skb_tail_pointer(buf) - buf_crs;
needed = (buf_len - sz_copied);
sz_to_copy = (sz <= needed) ? sz : needed;
if (unlikely(copy_to_user(crs, buf_crs, sz_to_copy))) {
res = -EFAULT;
goto exit;
}
sz_copied += sz_to_copy;
if (sz_to_copy < sz) {
if (!(flags & MSG_PEEK))
TIPC_SKB_CB(buf)->handle = buf_crs + sz_to_copy;
goto exit;
}
//.........这里部分代码省略.........
示例11: shutdown
static int shutdown(struct socket *sock, int how)
{
struct tipc_sock* tsock = tipc_sk(sock->sk);
struct sk_buff *buf;
int res;
/* Could return -EINVAL for an invalid "how", but why bother? */
if (down_interruptible(&tsock->sem))
return -ERESTARTSYS;
sock_lock(tsock);
switch (sock->state) {
case SS_CONNECTED:
/* Send 'FIN+' or 'FIN-' message to peer */
sock_unlock(tsock);
restart:
if ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) {
atomic_dec(&tipc_queue_size);
if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) {
buf_discard(buf);
goto restart;
}
tipc_reject_msg(buf, TIPC_CONN_SHUTDOWN);
}
else {
tipc_shutdown(tsock->p->ref);
}
sock_lock(tsock);
/* fall through */
case SS_DISCONNECTING:
/* Discard any unreceived messages */
while ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) {
atomic_dec(&tipc_queue_size);
buf_discard(buf);
}
tsock->p->conn_unacked = 0;
/* fall through */
case SS_CONNECTING:
sock->state = SS_DISCONNECTING;
res = 0;
break;
default:
res = -ENOTCONN;
}
sock_unlock(tsock);
up(&tsock->sem);
return res;
}
示例12: dispatch
static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
{
struct tipc_msg *msg = buf_msg(buf);
struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle;
struct socket *sock;
u32 recv_q_len;
/* Reject message if socket is closing */
if (!tsock)
return TIPC_ERR_NO_PORT;
/* Reject message if it is wrong sort of message for socket */
/*
* WOULD IT BE BETTER TO JUST DISCARD THESE MESSAGES INSTEAD?
* "NO PORT" ISN'T REALLY THE RIGHT ERROR CODE, AND THERE MAY
* BE SECURITY IMPLICATIONS INHERENT IN REJECTING INVALID TRAFFIC
*/
sock = tsock->sk.sk_socket;
if (sock->state == SS_READY) {
if (msg_connected(msg)) {
msg_dbg(msg, "dispatch filter 1\n");
return TIPC_ERR_NO_PORT;
}
} else {
if (msg_mcast(msg)) {
msg_dbg(msg, "dispatch filter 2\n");
return TIPC_ERR_NO_PORT;
}
if (sock->state == SS_CONNECTED) {
if (!msg_connected(msg)) {
msg_dbg(msg, "dispatch filter 3\n");
return TIPC_ERR_NO_PORT;
}
}
else if (sock->state == SS_CONNECTING) {
if (!msg_connected(msg) && (msg_errcode(msg) == 0)) {
msg_dbg(msg, "dispatch filter 4\n");
return TIPC_ERR_NO_PORT;
}
}
else if (sock->state == SS_LISTENING) {
if (msg_connected(msg) || msg_errcode(msg)) {
msg_dbg(msg, "dispatch filter 5\n");
return TIPC_ERR_NO_PORT;
}
}
else if (sock->state == SS_DISCONNECTING) {
msg_dbg(msg, "dispatch filter 6\n");
return TIPC_ERR_NO_PORT;
}
else /* (sock->state == SS_UNCONNECTED) */ {
if (msg_connected(msg) || msg_errcode(msg)) {
msg_dbg(msg, "dispatch filter 7\n");
return TIPC_ERR_NO_PORT;
}
}
}
/* Reject message if there isn't room to queue it */
if (unlikely((u32)atomic_read(&tipc_queue_size) >
OVERLOAD_LIMIT_BASE)) {
if (queue_overloaded(atomic_read(&tipc_queue_size),
OVERLOAD_LIMIT_BASE, msg))
return TIPC_ERR_OVERLOAD;
}
recv_q_len = skb_queue_len(&tsock->sk.sk_receive_queue);
if (unlikely(recv_q_len > (OVERLOAD_LIMIT_BASE / 2))) {
if (queue_overloaded(recv_q_len,
OVERLOAD_LIMIT_BASE / 2, msg))
return TIPC_ERR_OVERLOAD;
}
/* Initiate connection termination for an incoming 'FIN' */
if (unlikely(msg_errcode(msg) && (sock->state == SS_CONNECTED))) {
sock->state = SS_DISCONNECTING;
/* Note: Use signal since port lock is already taken! */
tipc_k_signal((Handler)async_disconnect, tport->ref);
}
/* Enqueue message (finally!) */
msg_dbg(msg,"<DISP<: ");
TIPC_SKB_CB(buf)->handle = msg_data(msg);
atomic_inc(&tipc_queue_size);
skb_queue_tail(&sock->sk->sk_receive_queue, buf);
if (waitqueue_active(sock->sk->sk_sleep))
wake_up_interruptible(sock->sk->sk_sleep);
return TIPC_OK;
}
示例13: recv_stream
static int recv_stream(struct kiocb *iocb, struct socket *sock,
struct msghdr *m, size_t buf_len, int flags)
{
struct sock *sk = sock->sk;
struct tipc_port *tport = tipc_sk_port(sk);
struct sk_buff *buf;
struct tipc_msg *msg;
unsigned int sz;
int sz_to_copy, target, needed;
int sz_copied = 0;
char __user *crs = m->msg_iov->iov_base;
unsigned char *buf_crs;
u32 err;
int res = 0;
/* Catch invalid receive attempts */
if (m->msg_iovlen != 1)
return -EOPNOTSUPP; /* Don't do multiple iovec entries yet */
if (unlikely(!buf_len))
return -EINVAL;
lock_sock(sk);
if (unlikely((sock->state == SS_UNCONNECTED) ||
(sock->state == SS_CONNECTING))) {
res = -ENOTCONN;
goto exit;
}
target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
restart:
/* Look for a message in receive queue; wait if necessary */
while (skb_queue_empty(&sk->sk_receive_queue)) {
if (sock->state == SS_DISCONNECTING) {
res = -ENOTCONN;
goto exit;
}
if (flags & MSG_DONTWAIT) {
res = -EWOULDBLOCK;
goto exit;
}
release_sock(sk);
res = wait_event_interruptible(*sk_sleep(sk),
(!skb_queue_empty(&sk->sk_receive_queue) ||
(sock->state == SS_DISCONNECTING)));
lock_sock(sk);
if (res)
goto exit;
}
/* Look at first message in receive queue */
buf = skb_peek(&sk->sk_receive_queue);
msg = buf_msg(buf);
sz = msg_data_sz(msg);
err = msg_errcode(msg);
/* Discard an empty non-errored message & try again */
if ((!sz) && (!err)) {
advance_rx_queue(sk);
goto restart;
}
/* Optionally capture sender's address & ancillary data of first msg */
if (sz_copied == 0) {
set_orig_addr(m, msg);
res = anc_data_recv(m, msg, tport);
if (res)
goto exit;
}
/* Capture message data (if valid) & compute return value (always) */
if (!err) {
buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle);
sz = (unsigned char *)msg + msg_size(msg) - buf_crs;
needed = (buf_len - sz_copied);
sz_to_copy = (sz <= needed) ? sz : needed;
if (unlikely(copy_to_user(crs, buf_crs, sz_to_copy))) {
res = -EFAULT;
goto exit;
}
sz_copied += sz_to_copy;
if (sz_to_copy < sz) {
if (!(flags & MSG_PEEK))
TIPC_SKB_CB(buf)->handle = buf_crs + sz_to_copy;
goto exit;
}
crs += sz_to_copy;
} else {
//.........这里部分代码省略.........
示例14: filter_rcv
/**
* filter_rcv - validate incoming message
* @sk: socket
* @buf: message
*
* Enqueues message on receive queue if acceptable; optionally handles
* disconnect indication for a connected socket.
*
* Called with socket lock already taken; port lock may also be taken.
*
* Returns TIPC error status code (TIPC_OK if message is not to be rejected)
*/
static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
{
struct socket *sock = sk->sk_socket;
struct tipc_msg *msg = buf_msg(buf);
u32 recv_q_len;
/* Reject message if it is wrong sort of message for socket */
if (msg_type(msg) > TIPC_DIRECT_MSG)
return TIPC_ERR_NO_PORT;
if (sock->state == SS_READY) {
if (msg_connected(msg))
return TIPC_ERR_NO_PORT;
} else {
if (msg_mcast(msg))
return TIPC_ERR_NO_PORT;
if (sock->state == SS_CONNECTED) {
if (!msg_connected(msg) ||
!tipc_port_peer_msg(tipc_sk_port(sk), msg))
return TIPC_ERR_NO_PORT;
} else if (sock->state == SS_CONNECTING) {
if (!msg_connected(msg) && (msg_errcode(msg) == 0))
return TIPC_ERR_NO_PORT;
} else if (sock->state == SS_LISTENING) {
if (msg_connected(msg) || msg_errcode(msg))
return TIPC_ERR_NO_PORT;
} else if (sock->state == SS_DISCONNECTING) {
return TIPC_ERR_NO_PORT;
} else /* (sock->state == SS_UNCONNECTED) */ {
if (msg_connected(msg) || msg_errcode(msg))
return TIPC_ERR_NO_PORT;
}
}
/* Reject message if there isn't room to queue it */
recv_q_len = (u32)atomic_read(&tipc_queue_size);
if (unlikely(recv_q_len >= OVERLOAD_LIMIT_BASE)) {
if (rx_queue_full(msg, recv_q_len, OVERLOAD_LIMIT_BASE))
return TIPC_ERR_OVERLOAD;
}
recv_q_len = skb_queue_len(&sk->sk_receive_queue);
if (unlikely(recv_q_len >= (OVERLOAD_LIMIT_BASE / 2))) {
if (rx_queue_full(msg, recv_q_len, OVERLOAD_LIMIT_BASE / 2))
return TIPC_ERR_OVERLOAD;
}
/* Enqueue message (finally!) */
TIPC_SKB_CB(buf)->handle = 0;
atomic_inc(&tipc_queue_size);
__skb_queue_tail(&sk->sk_receive_queue, buf);
/* Initiate connection termination for an incoming 'FIN' */
if (unlikely(msg_errcode(msg) && (sock->state == SS_CONNECTED))) {
sock->state = SS_DISCONNECTING;
tipc_disconnect_port(tipc_sk_port(sk));
}
if (waitqueue_active(sk_sleep(sk)))
wake_up_interruptible(sk_sleep(sk));
return TIPC_OK;
}
示例15: tipc_buf_append
/* tipc_buf_append(): Append a buffer to the fragment list of another buffer
* @*headbuf: in: NULL for first frag, otherwise value returned from prev call
* out: set when successful non-complete reassembly, otherwise NULL
* @*buf: in: the buffer to append. Always defined
* out: head buf after successful complete reassembly, otherwise NULL
* Returns 1 when reassembly complete, otherwise 0
*/
int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
{
struct sk_buff *head = *headbuf;
struct sk_buff *frag = *buf;
struct sk_buff *tail;
struct tipc_msg *msg;
u32 fragid;
int delta;
bool headstolen;
if (!frag)
goto err;
msg = buf_msg(frag);
fragid = msg_type(msg);
frag->next = NULL;
skb_pull(frag, msg_hdr_sz(msg));
if (fragid == FIRST_FRAGMENT) {
if (unlikely(head))
goto err;
if (unlikely(skb_unclone(frag, GFP_ATOMIC)))
goto err;
head = *headbuf = frag;
skb_frag_list_init(head);
TIPC_SKB_CB(head)->tail = NULL;
*buf = NULL;
return 0;
}
if (!head)
goto err;
if (skb_try_coalesce(head, frag, &headstolen, &delta)) {
kfree_skb_partial(frag, headstolen);
} else {
tail = TIPC_SKB_CB(head)->tail;
if (!skb_has_frag_list(head))
skb_shinfo(head)->frag_list = frag;
else
tail->next = frag;
head->truesize += frag->truesize;
head->data_len += frag->len;
head->len += frag->len;
TIPC_SKB_CB(head)->tail = frag;
}
if (fragid == LAST_FRAGMENT) {
*buf = head;
TIPC_SKB_CB(head)->tail = NULL;
*headbuf = NULL;
return 1;
}
*buf = NULL;
return 0;
err:
pr_warn_ratelimited("Unable to build fragment list\n");
kfree_skb(*buf);
kfree_skb(*headbuf);
*buf = *headbuf = NULL;
return 0;
}