diff options
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 57 |
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 | */ |
1452 | u32 tipc_sk_rcv(struct sock *sk, struct sk_buff *buf) | 1449 | int 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; | ||
1492 | exit: | ||
1493 | tipc_reject_msg(buf, err); | ||
1494 | return -EHOSTUNREACH; | ||
1478 | } | 1495 | } |
1479 | 1496 | ||
1480 | static int tipc_wait_for_connect(struct socket *sock, long *timeo_p) | 1497 | static int tipc_wait_for_connect(struct socket *sock, long *timeo_p) |