aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r--net/tipc/socket.c57
1 files changed, 37 insertions, 20 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 249500614568..ac08966f2858 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1442,39 +1442,56 @@ static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *buf)
1442 1442
1443/** 1443/**
1444 * tipc_sk_rcv - handle incoming message 1444 * tipc_sk_rcv - handle incoming message
1445 * @sk: socket receiving message 1445 * @buf: buffer containing arriving message
1446 * @buf: message 1446 * Consumes buffer
1447 * 1447 * Returns 0 if success, or errno: -EHOSTUNREACH
1448 * Called with port lock already taken.
1449 *
1450 * Returns TIPC error status code (TIPC_OK if message is not to be rejected)
1451 */ 1448 */
1452u32 tipc_sk_rcv(struct sock *sk, struct sk_buff *buf) 1449int tipc_sk_rcv(struct sk_buff *buf)
1453{ 1450{
1454 struct tipc_sock *tsk = tipc_sk(sk); 1451 struct tipc_sock *tsk;
1455 u32 res; 1452 struct tipc_port *port;
1453 struct sock *sk;
1454 u32 dport = msg_destport(buf_msg(buf));
1455 int err = TIPC_OK;
1456 uint limit; 1456 uint limit;
1457 /* 1457
1458 * Process message if socket is unlocked; otherwise add to backlog queue 1458 /* Forward unresolved named message */
1459 * 1459 if (unlikely(!dport)) {
1460 * This code is based on sk_receive_skb(), but must be distinct from it 1460 tipc_net_route_msg(buf);
1461 * since a TIPC-specific filter/reject mechanism is utilized 1461 return 0;
1462 */ 1462 }
1463
1464 /* Validate destination */
1465 port = tipc_port_lock(dport);
1466 if (unlikely(!port)) {
1467 err = TIPC_ERR_NO_PORT;
1468 goto exit;
1469 }
1470
1471 tsk = tipc_port_to_sock(port);
1472 sk = &tsk->sk;
1473
1474 /* Queue message */
1463 bh_lock_sock(sk); 1475 bh_lock_sock(sk);
1476
1464 if (!sock_owned_by_user(sk)) { 1477 if (!sock_owned_by_user(sk)) {
1465 res = filter_rcv(sk, buf); 1478 err = filter_rcv(sk, buf);
1466 } else { 1479 } else {
1467 if (sk->sk_backlog.len == 0) 1480 if (sk->sk_backlog.len == 0)
1468 atomic_set(&tsk->dupl_rcvcnt, 0); 1481 atomic_set(&tsk->dupl_rcvcnt, 0);
1469 limit = rcvbuf_limit(sk, buf) + atomic_read(&tsk->dupl_rcvcnt); 1482 limit = rcvbuf_limit(sk, buf) + atomic_read(&tsk->dupl_rcvcnt);
1470 if (sk_add_backlog(sk, buf, limit)) 1483 if (sk_add_backlog(sk, buf, limit))
1471 res = TIPC_ERR_OVERLOAD; 1484 err = TIPC_ERR_OVERLOAD;
1472 else
1473 res = TIPC_OK;
1474 } 1485 }
1486
1475 bh_unlock_sock(sk); 1487 bh_unlock_sock(sk);
1488 tipc_port_unlock(port);
1476 1489
1477 return res; 1490 if (likely(!err))
1491 return 0;
1492exit:
1493 tipc_reject_msg(buf, err);
1494 return -EHOSTUNREACH;
1478} 1495}
1479 1496
1480static int tipc_wait_for_connect(struct socket *sock, long *timeo_p) 1497static int tipc_wait_for_connect(struct socket *sock, long *timeo_p)