@@ -442,6 +442,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
442
442
}
443
443
msg_set_origport (msg , tsk -> portid );
444
444
setup_timer (& sk -> sk_timer , tipc_sk_timeout , (unsigned long )tsk );
445
+ sk -> sk_shutdown = 0 ;
445
446
sk -> sk_backlog_rcv = tipc_backlog_rcv ;
446
447
sk -> sk_rcvbuf = sysctl_tipc_rmem [1 ];
447
448
sk -> sk_data_ready = tipc_data_ready ;
@@ -470,6 +471,44 @@ static void tipc_sk_callback(struct rcu_head *head)
470
471
sock_put (& tsk -> sk );
471
472
}
472
473
474
+ /* Caller should hold socket lock for the socket. */
475
+ static void __tipc_shutdown (struct socket * sock , int error )
476
+ {
477
+ struct sock * sk = sock -> sk ;
478
+ struct tipc_sock * tsk = tipc_sk (sk );
479
+ struct net * net = sock_net (sk );
480
+ u32 dnode = tsk_peer_node (tsk );
481
+ struct sk_buff * skb ;
482
+
483
+ /* Reject all unreceived messages, except on an active connection
484
+ * (which disconnects locally & sends a 'FIN+' to peer).
485
+ */
486
+ while ((skb = __skb_dequeue (& sk -> sk_receive_queue )) != NULL ) {
487
+ if (TIPC_SKB_CB (skb )-> bytes_read ) {
488
+ kfree_skb (skb );
489
+ } else {
490
+ if (!tipc_sk_type_connectionless (sk ) &&
491
+ sk -> sk_state != TIPC_DISCONNECTING ) {
492
+ tipc_set_sk_state (sk , TIPC_DISCONNECTING );
493
+ tipc_node_remove_conn (net , dnode , tsk -> portid );
494
+ }
495
+ tipc_sk_respond (sk , skb , error );
496
+ }
497
+ }
498
+ if (sk -> sk_state != TIPC_DISCONNECTING ) {
499
+ skb = tipc_msg_create (TIPC_CRITICAL_IMPORTANCE ,
500
+ TIPC_CONN_MSG , SHORT_H_SIZE , 0 , dnode ,
501
+ tsk_own_node (tsk ), tsk_peer_port (tsk ),
502
+ tsk -> portid , error );
503
+ if (skb )
504
+ tipc_node_xmit_skb (net , skb , dnode , tsk -> portid );
505
+ if (!tipc_sk_type_connectionless (sk )) {
506
+ tipc_node_remove_conn (net , dnode , tsk -> portid );
507
+ tipc_set_sk_state (sk , TIPC_DISCONNECTING );
508
+ }
509
+ }
510
+ }
511
+
473
512
/**
474
513
* tipc_release - destroy a TIPC socket
475
514
* @sock: socket to destroy
@@ -489,10 +528,7 @@ static void tipc_sk_callback(struct rcu_head *head)
489
528
static int tipc_release (struct socket * sock )
490
529
{
491
530
struct sock * sk = sock -> sk ;
492
- struct net * net ;
493
531
struct tipc_sock * tsk ;
494
- struct sk_buff * skb ;
495
- u32 dnode ;
496
532
497
533
/*
498
534
* Exit if socket isn't fully initialized (occurs when a failed accept()
@@ -501,46 +537,16 @@ static int tipc_release(struct socket *sock)
501
537
if (sk == NULL )
502
538
return 0 ;
503
539
504
- net = sock_net (sk );
505
540
tsk = tipc_sk (sk );
506
541
lock_sock (sk );
507
542
508
- /*
509
- * Reject all unreceived messages, except on an active connection
510
- * (which disconnects locally & sends a 'FIN+' to peer)
511
- */
512
- dnode = tsk_peer_node (tsk );
513
- while (sock -> state != SS_DISCONNECTING ) {
514
- skb = __skb_dequeue (& sk -> sk_receive_queue );
515
- if (skb == NULL )
516
- break ;
517
- if (TIPC_SKB_CB (skb )-> bytes_read )
518
- kfree_skb (skb );
519
- else {
520
- if ((sock -> state == SS_CONNECTING ) ||
521
- (sock -> state == SS_CONNECTED )) {
522
- sock -> state = SS_DISCONNECTING ;
523
- tipc_node_remove_conn (net , dnode , tsk -> portid );
524
- }
525
- tipc_sk_respond (sk , skb , TIPC_ERR_NO_PORT );
526
- }
527
- }
528
-
543
+ __tipc_shutdown (sock , TIPC_ERR_NO_PORT );
544
+ sk -> sk_shutdown = SHUTDOWN_MASK ;
529
545
tipc_sk_withdraw (tsk , 0 , NULL );
530
546
sk_stop_timer (sk , & sk -> sk_timer );
531
547
tipc_sk_remove (tsk );
532
- if (tipc_sk_connected (sk )) {
533
- skb = tipc_msg_create (TIPC_CRITICAL_IMPORTANCE ,
534
- TIPC_CONN_MSG , SHORT_H_SIZE , 0 , dnode ,
535
- tsk_own_node (tsk ), tsk_peer_port (tsk ),
536
- tsk -> portid , TIPC_ERR_NO_PORT );
537
- if (skb )
538
- tipc_node_xmit_skb (net , skb , dnode , tsk -> portid );
539
- tipc_node_remove_conn (net , dnode , tsk -> portid );
540
- }
541
548
542
549
/* Reject any messages that accumulated in backlog queue */
543
- sock -> state = SS_DISCONNECTING ;
544
550
release_sock (sk );
545
551
546
552
call_rcu (& tsk -> rcu , tipc_sk_callback );
@@ -678,6 +684,11 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,
678
684
679
685
sock_poll_wait (file , sk_sleep (sk ), wait );
680
686
687
+ if (sk -> sk_shutdown & RCV_SHUTDOWN )
688
+ mask |= POLLRDHUP | POLLIN | POLLRDNORM ;
689
+ if (sk -> sk_shutdown == SHUTDOWN_MASK )
690
+ mask |= POLLHUP ;
691
+
681
692
switch ((int )sock -> state ) {
682
693
case SS_CONNECTED :
683
694
if (!tsk -> link_cong && !tsk_conn_cong (tsk ))
@@ -687,9 +698,6 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,
687
698
if (!skb_queue_empty (& sk -> sk_receive_queue ))
688
699
mask |= (POLLIN | POLLRDNORM );
689
700
break ;
690
- case SS_DISCONNECTING :
691
- mask = (POLLIN | POLLRDNORM | POLLHUP );
692
- break ;
693
701
default :
694
702
switch (sk -> sk_state ) {
695
703
case TIPC_OPEN :
@@ -882,7 +890,7 @@ static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p)
882
890
int err = sock_error (sk );
883
891
if (err )
884
892
return err ;
885
- if (sock -> state == SS_DISCONNECTING )
893
+ if (sk -> sk_shutdown & SEND_SHUTDOWN )
886
894
return - EPIPE ;
887
895
if (!* timeo_p )
888
896
return - EAGAIN ;
@@ -1335,7 +1343,7 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
1335
1343
for (;;) {
1336
1344
prepare_to_wait (sk_sleep (sk ), & wait , TASK_INTERRUPTIBLE );
1337
1345
if (timeo && skb_queue_empty (& sk -> sk_receive_queue )) {
1338
- if (sock -> state == SS_DISCONNECTING ) {
1346
+ if (sk -> sk_shutdown & RCV_SHUTDOWN ) {
1339
1347
err = - ENOTCONN ;
1340
1348
break ;
1341
1349
}
@@ -1676,9 +1684,6 @@ static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
1676
1684
/* 'ACK-' message is neither accepted nor rejected: */
1677
1685
msg_set_dest_droppable (hdr , 1 );
1678
1686
return false;
1679
-
1680
- case SS_DISCONNECTING :
1681
- break ;
1682
1687
}
1683
1688
1684
1689
switch (sk -> sk_state ) {
@@ -2191,57 +2196,24 @@ static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags)
2191
2196
static int tipc_shutdown (struct socket * sock , int how )
2192
2197
{
2193
2198
struct sock * sk = sock -> sk ;
2194
- struct net * net = sock_net (sk );
2195
- struct tipc_sock * tsk = tipc_sk (sk );
2196
- struct sk_buff * skb ;
2197
- u32 dnode = tsk_peer_node (tsk );
2198
- u32 dport = tsk_peer_port (tsk );
2199
- u32 onode = tipc_own_addr (net );
2200
- u32 oport = tsk -> portid ;
2201
2199
int res ;
2202
2200
2203
2201
if (how != SHUT_RDWR )
2204
2202
return - EINVAL ;
2205
2203
2206
2204
lock_sock (sk );
2207
2205
2208
- if (sock -> state == SS_CONNECTING || sock -> state == SS_CONNECTED ) {
2209
-
2210
- restart :
2211
- dnode = tsk_peer_node (tsk );
2212
-
2213
- /* Disconnect and send a 'FIN+' or 'FIN-' message to peer */
2214
- skb = __skb_dequeue (& sk -> sk_receive_queue );
2215
- if (skb ) {
2216
- if (TIPC_SKB_CB (skb )-> bytes_read ) {
2217
- kfree_skb (skb );
2218
- goto restart ;
2219
- }
2220
- tipc_sk_respond (sk , skb , TIPC_CONN_SHUTDOWN );
2221
- } else {
2222
- skb = tipc_msg_create (TIPC_CRITICAL_IMPORTANCE ,
2223
- TIPC_CONN_MSG , SHORT_H_SIZE ,
2224
- 0 , dnode , onode , dport , oport ,
2225
- TIPC_CONN_SHUTDOWN );
2226
- if (skb )
2227
- tipc_node_xmit_skb (net , skb , dnode , tsk -> portid );
2228
- }
2229
- tipc_set_sk_state (sk , TIPC_DISCONNECTING );
2230
- tipc_node_remove_conn (net , dnode , tsk -> portid );
2231
- }
2232
-
2233
- switch (sk -> sk_state ) {
2234
- case TIPC_DISCONNECTING :
2206
+ __tipc_shutdown (sock , TIPC_CONN_SHUTDOWN );
2207
+ sk -> sk_shutdown = SEND_SHUTDOWN ;
2235
2208
2209
+ if (sk -> sk_state == TIPC_DISCONNECTING ) {
2236
2210
/* Discard any unreceived messages */
2237
2211
__skb_queue_purge (& sk -> sk_receive_queue );
2238
2212
2239
2213
/* Wake up anyone sleeping in poll */
2240
2214
sk -> sk_state_change (sk );
2241
2215
res = 0 ;
2242
- break ;
2243
-
2244
- default :
2216
+ } else {
2245
2217
res = - ENOTCONN ;
2246
2218
}
2247
2219
0 commit comments