aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/tipc/socket.c158
1 files changed, 93 insertions, 65 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index d16a6de32ea1..dbce2745f0a8 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -775,16 +775,19 @@ exit:
775static int auto_connect(struct socket *sock, struct tipc_msg *msg) 775static int auto_connect(struct socket *sock, struct tipc_msg *msg)
776{ 776{
777 struct tipc_sock *tsock = tipc_sk(sock->sk); 777 struct tipc_sock *tsock = tipc_sk(sock->sk);
778 778 struct tipc_port *p_ptr;
779 if (msg_errcode(msg)) {
780 sock->state = SS_DISCONNECTING;
781 return -ECONNREFUSED;
782 }
783 779
784 tsock->peer_name.ref = msg_origport(msg); 780 tsock->peer_name.ref = msg_origport(msg);
785 tsock->peer_name.node = msg_orignode(msg); 781 tsock->peer_name.node = msg_orignode(msg);
786 tipc_connect(tsock->p->ref, &tsock->peer_name); 782 p_ptr = tipc_port_deref(tsock->p->ref);
787 tipc_set_portimportance(tsock->p->ref, msg_importance(msg)); 783 if (!p_ptr)
784 return -EINVAL;
785
786 __tipc_connect(tsock->p->ref, p_ptr, &tsock->peer_name);
787
788 if (msg_importance(msg) > TIPC_CRITICAL_IMPORTANCE)
789 return -EINVAL;
790 msg_set_importance(&p_ptr->phdr, (u32)msg_importance(msg));
788 sock->state = SS_CONNECTED; 791 sock->state = SS_CONNECTED;
789 return 0; 792 return 0;
790} 793}
@@ -1198,7 +1201,9 @@ static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf)
1198{ 1201{
1199 struct socket *sock = tsock->sk.sk_socket; 1202 struct socket *sock = tsock->sk.sk_socket;
1200 struct tipc_msg *msg = buf_msg(*buf); 1203 struct tipc_msg *msg = buf_msg(*buf);
1204 struct sock *sk = &tsock->sk;
1201 u32 retval = TIPC_ERR_NO_PORT; 1205 u32 retval = TIPC_ERR_NO_PORT;
1206 int res;
1202 1207
1203 if (msg_mcast(msg)) 1208 if (msg_mcast(msg))
1204 return retval; 1209 return retval;
@@ -1216,8 +1221,36 @@ static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf)
1216 break; 1221 break;
1217 case SS_CONNECTING: 1222 case SS_CONNECTING:
1218 /* Accept only ACK or NACK message */ 1223 /* Accept only ACK or NACK message */
1219 if (msg_connected(msg) || (msg_errcode(msg))) 1224 if (unlikely(msg_errcode(msg))) {
1225 sock->state = SS_DISCONNECTING;
1226 sk->sk_err = -ECONNREFUSED;
1227 retval = TIPC_OK;
1228 break;
1229 }
1230
1231 if (unlikely(!msg_connected(msg)))
1232 break;
1233
1234 res = auto_connect(sock, msg);
1235 if (res) {
1236 sock->state = SS_DISCONNECTING;
1237 sk->sk_err = res;
1220 retval = TIPC_OK; 1238 retval = TIPC_OK;
1239 break;
1240 }
1241
1242 /* If an incoming message is an 'ACK-', it should be
1243 * discarded here because it doesn't contain useful
1244 * data. In addition, we should try to wake up
1245 * connect() routine if sleeping.
1246 */
1247 if (msg_data_sz(msg) == 0) {
1248 kfree_skb(*buf);
1249 *buf = NULL;
1250 if (waitqueue_active(sk_sleep(sk)))
1251 wake_up_interruptible(sk_sleep(sk));
1252 }
1253 retval = TIPC_OK;
1221 break; 1254 break;
1222 case SS_LISTENING: 1255 case SS_LISTENING:
1223 case SS_UNCONNECTED: 1256 case SS_UNCONNECTED:
@@ -1361,8 +1394,6 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
1361 struct sock *sk = sock->sk; 1394 struct sock *sk = sock->sk;
1362 struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; 1395 struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
1363 struct msghdr m = {NULL,}; 1396 struct msghdr m = {NULL,};
1364 struct sk_buff *buf;
1365 struct tipc_msg *msg;
1366 unsigned int timeout; 1397 unsigned int timeout;
1367 int res; 1398 int res;
1368 1399
@@ -1374,26 +1405,6 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
1374 goto exit; 1405 goto exit;
1375 } 1406 }
1376 1407
1377 /* For now, TIPC does not support the non-blocking form of connect() */
1378 if (flags & O_NONBLOCK) {
1379 res = -EOPNOTSUPP;
1380 goto exit;
1381 }
1382
1383 /* Issue Posix-compliant error code if socket is in the wrong state */
1384 if (sock->state == SS_LISTENING) {
1385 res = -EOPNOTSUPP;
1386 goto exit;
1387 }
1388 if (sock->state == SS_CONNECTING) {
1389 res = -EALREADY;
1390 goto exit;
1391 }
1392 if (sock->state != SS_UNCONNECTED) {
1393 res = -EISCONN;
1394 goto exit;
1395 }
1396
1397 /* 1408 /*
1398 * Reject connection attempt using multicast address 1409 * Reject connection attempt using multicast address
1399 * 1410 *
@@ -1405,49 +1416,66 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
1405 goto exit; 1416 goto exit;
1406 } 1417 }
1407 1418
1408 /* Reject any messages already in receive queue (very unlikely) */ 1419 timeout = (flags & O_NONBLOCK) ? 0 : tipc_sk(sk)->conn_timeout;
1409 reject_rx_queue(sk); 1420
1421 switch (sock->state) {
1422 case SS_UNCONNECTED:
1423 /* Send a 'SYN-' to destination */
1424 m.msg_name = dest;
1425 m.msg_namelen = destlen;
1426
1427 /* If connect is in non-blocking case, set MSG_DONTWAIT to
1428 * indicate send_msg() is never blocked.
1429 */
1430 if (!timeout)
1431 m.msg_flags = MSG_DONTWAIT;
1432
1433 res = send_msg(NULL, sock, &m, 0);
1434 if ((res < 0) && (res != -EWOULDBLOCK))
1435 goto exit;
1410 1436
1411 /* Send a 'SYN-' to destination */ 1437 /* Just entered SS_CONNECTING state; the only
1412 m.msg_name = dest; 1438 * difference is that return value in non-blocking
1413 m.msg_namelen = destlen; 1439 * case is EINPROGRESS, rather than EALREADY.
1414 res = send_msg(NULL, sock, &m, 0); 1440 */
1415 if (res < 0) 1441 res = -EINPROGRESS;
1442 break;
1443 case SS_CONNECTING:
1444 res = -EALREADY;
1445 break;
1446 case SS_CONNECTED:
1447 res = -EISCONN;
1448 break;
1449 default:
1450 res = -EINVAL;
1416 goto exit; 1451 goto exit;
1452 }
1417 1453
1418 /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */ 1454 if (sock->state == SS_CONNECTING) {
1419 timeout = tipc_sk(sk)->conn_timeout; 1455 if (!timeout)
1420 release_sock(sk); 1456 goto exit;
1421 res = wait_event_interruptible_timeout(*sk_sleep(sk),
1422 (!skb_queue_empty(&sk->sk_receive_queue) ||
1423 (sock->state != SS_CONNECTING)),
1424 timeout ? (long)msecs_to_jiffies(timeout)
1425 : MAX_SCHEDULE_TIMEOUT);
1426 lock_sock(sk);
1427 1457
1428 if (res > 0) { 1458 /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
1429 buf = skb_peek(&sk->sk_receive_queue); 1459 release_sock(sk);
1430 if (buf != NULL) { 1460 res = wait_event_interruptible_timeout(*sk_sleep(sk),
1431 msg = buf_msg(buf); 1461 sock->state != SS_CONNECTING,
1432 res = auto_connect(sock, msg); 1462 timeout ? (long)msecs_to_jiffies(timeout)
1433 if (!res) { 1463 : MAX_SCHEDULE_TIMEOUT);
1434 if (!msg_data_sz(msg)) 1464 lock_sock(sk);
1435 advance_rx_queue(sk); 1465 if (res <= 0) {
1436 } 1466 if (res == 0)
1437 } else { 1467 res = -ETIMEDOUT;
1438 if (sock->state == SS_CONNECTED)
1439 res = -EISCONN;
1440 else 1468 else
1441 res = -ECONNREFUSED; 1469 ; /* leave "res" unchanged */
1470 goto exit;
1442 } 1471 }
1443 } else {
1444 if (res == 0)
1445 res = -ETIMEDOUT;
1446 else
1447 ; /* leave "res" unchanged */
1448 sock->state = SS_DISCONNECTING;
1449 } 1472 }
1450 1473
1474 if (unlikely(sock->state == SS_DISCONNECTING))
1475 res = sock_error(sk);
1476 else
1477 res = 0;
1478
1451exit: 1479exit:
1452 release_sock(sk); 1480 release_sock(sk);
1453 return res; 1481 return res;