diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/tipc/socket.c | 89 |
1 files changed, 48 insertions, 41 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index b5c9795cf15..9b4e4833a48 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -1509,8 +1509,13 @@ static int listen(struct socket *sock, int len) | |||
1509 | */ | 1509 | */ |
1510 | static int accept(struct socket *sock, struct socket *new_sock, int flags) | 1510 | static int accept(struct socket *sock, struct socket *new_sock, int flags) |
1511 | { | 1511 | { |
1512 | struct sock *sk = sock->sk; | 1512 | struct sock *new_sk, *sk = sock->sk; |
1513 | struct sk_buff *buf; | 1513 | struct sk_buff *buf; |
1514 | struct tipc_sock *new_tsock; | ||
1515 | struct tipc_port *new_tport; | ||
1516 | struct tipc_msg *msg; | ||
1517 | u32 new_ref; | ||
1518 | |||
1514 | int res; | 1519 | int res; |
1515 | 1520 | ||
1516 | lock_sock(sk); | 1521 | lock_sock(sk); |
@@ -1536,49 +1541,51 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) | |||
1536 | buf = skb_peek(&sk->sk_receive_queue); | 1541 | buf = skb_peek(&sk->sk_receive_queue); |
1537 | 1542 | ||
1538 | res = tipc_create(sock_net(sock->sk), new_sock, 0, 0); | 1543 | res = tipc_create(sock_net(sock->sk), new_sock, 0, 0); |
1539 | if (!res) { | 1544 | if (res) |
1540 | struct sock *new_sk = new_sock->sk; | 1545 | goto exit; |
1541 | struct tipc_sock *new_tsock = tipc_sk(new_sk); | ||
1542 | struct tipc_port *new_tport = new_tsock->p; | ||
1543 | u32 new_ref = new_tport->ref; | ||
1544 | struct tipc_msg *msg = buf_msg(buf); | ||
1545 | |||
1546 | /* we lock on new_sk; but lockdep sees the lock on sk */ | ||
1547 | lock_sock_nested(new_sk, SINGLE_DEPTH_NESTING); | ||
1548 | |||
1549 | /* | ||
1550 | * Reject any stray messages received by new socket | ||
1551 | * before the socket lock was taken (very, very unlikely) | ||
1552 | */ | ||
1553 | reject_rx_queue(new_sk); | ||
1554 | |||
1555 | /* Connect new socket to it's peer */ | ||
1556 | new_tsock->peer_name.ref = msg_origport(msg); | ||
1557 | new_tsock->peer_name.node = msg_orignode(msg); | ||
1558 | tipc_connect(new_ref, &new_tsock->peer_name); | ||
1559 | new_sock->state = SS_CONNECTED; | ||
1560 | |||
1561 | tipc_set_portimportance(new_ref, msg_importance(msg)); | ||
1562 | if (msg_named(msg)) { | ||
1563 | new_tport->conn_type = msg_nametype(msg); | ||
1564 | new_tport->conn_instance = msg_nameinst(msg); | ||
1565 | } | ||
1566 | 1546 | ||
1567 | /* | 1547 | new_sk = new_sock->sk; |
1568 | * Respond to 'SYN-' by discarding it & returning 'ACK'-. | 1548 | new_tsock = tipc_sk(new_sk); |
1569 | * Respond to 'SYN+' by queuing it on new socket. | 1549 | new_tport = new_tsock->p; |
1570 | */ | 1550 | new_ref = new_tport->ref; |
1571 | if (!msg_data_sz(msg)) { | 1551 | msg = buf_msg(buf); |
1572 | struct msghdr m = {NULL,}; | ||
1573 | 1552 | ||
1574 | advance_rx_queue(sk); | 1553 | /* we lock on new_sk; but lockdep sees the lock on sk */ |
1575 | send_packet(NULL, new_sock, &m, 0); | 1554 | lock_sock_nested(new_sk, SINGLE_DEPTH_NESTING); |
1576 | } else { | 1555 | |
1577 | __skb_dequeue(&sk->sk_receive_queue); | 1556 | /* |
1578 | __skb_queue_head(&new_sk->sk_receive_queue, buf); | 1557 | * Reject any stray messages received by new socket |
1579 | } | 1558 | * before the socket lock was taken (very, very unlikely) |
1580 | release_sock(new_sk); | 1559 | */ |
1560 | reject_rx_queue(new_sk); | ||
1561 | |||
1562 | /* Connect new socket to it's peer */ | ||
1563 | new_tsock->peer_name.ref = msg_origport(msg); | ||
1564 | new_tsock->peer_name.node = msg_orignode(msg); | ||
1565 | tipc_connect(new_ref, &new_tsock->peer_name); | ||
1566 | new_sock->state = SS_CONNECTED; | ||
1567 | |||
1568 | tipc_set_portimportance(new_ref, msg_importance(msg)); | ||
1569 | if (msg_named(msg)) { | ||
1570 | new_tport->conn_type = msg_nametype(msg); | ||
1571 | new_tport->conn_instance = msg_nameinst(msg); | ||
1581 | } | 1572 | } |
1573 | |||
1574 | /* | ||
1575 | * Respond to 'SYN-' by discarding it & returning 'ACK'-. | ||
1576 | * Respond to 'SYN+' by queuing it on new socket. | ||
1577 | */ | ||
1578 | if (!msg_data_sz(msg)) { | ||
1579 | struct msghdr m = {NULL,}; | ||
1580 | |||
1581 | advance_rx_queue(sk); | ||
1582 | send_packet(NULL, new_sock, &m, 0); | ||
1583 | } else { | ||
1584 | __skb_dequeue(&sk->sk_receive_queue); | ||
1585 | __skb_queue_head(&new_sk->sk_receive_queue, buf); | ||
1586 | } | ||
1587 | release_sock(new_sk); | ||
1588 | |||
1582 | exit: | 1589 | exit: |
1583 | release_sock(sk); | 1590 | release_sock(sk); |
1584 | return res; | 1591 | return res; |