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.c296
1 files changed, 148 insertions, 148 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index bdce99f9407a..0d4f2f455a7c 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -51,6 +51,7 @@
51#define TIPC_FWD_MSG 1 51#define TIPC_FWD_MSG 1
52#define TIPC_MAX_PORT 0xffffffff 52#define TIPC_MAX_PORT 0xffffffff
53#define TIPC_MIN_PORT 1 53#define TIPC_MIN_PORT 1
54#define TIPC_ACK_RATE 4 /* ACK at 1/4 of of rcv window size */
54 55
55enum { 56enum {
56 TIPC_LISTEN = TCP_LISTEN, 57 TIPC_LISTEN = TCP_LISTEN,
@@ -1305,7 +1306,7 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
1305/** 1306/**
1306 * tipc_recvmsg - receive packet-oriented message 1307 * tipc_recvmsg - receive packet-oriented message
1307 * @m: descriptor for message info 1308 * @m: descriptor for message info
1308 * @buf_len: total size of user buffer area 1309 * @buflen: length of user buffer area
1309 * @flags: receive flags 1310 * @flags: receive flags
1310 * 1311 *
1311 * Used for SOCK_DGRAM, SOCK_RDM, and SOCK_SEQPACKET messages. 1312 * Used for SOCK_DGRAM, SOCK_RDM, and SOCK_SEQPACKET messages.
@@ -1313,95 +1314,85 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
1313 * 1314 *
1314 * Returns size of returned message data, errno otherwise 1315 * Returns size of returned message data, errno otherwise
1315 */ 1316 */
1316static int tipc_recvmsg(struct socket *sock, struct msghdr *m, size_t buf_len, 1317static int tipc_recvmsg(struct socket *sock, struct msghdr *m,
1317 int flags) 1318 size_t buflen, int flags)
1318{ 1319{
1319 struct sock *sk = sock->sk; 1320 struct sock *sk = sock->sk;
1320 struct tipc_sock *tsk = tipc_sk(sk); 1321 struct tipc_sock *tsk = tipc_sk(sk);
1321 struct sk_buff *buf; 1322 struct sk_buff *skb;
1322 struct tipc_msg *msg; 1323 struct tipc_msg *hdr;
1323 bool is_connectionless = tipc_sk_type_connectionless(sk); 1324 bool connected = !tipc_sk_type_connectionless(sk);
1324 long timeo; 1325 int rc, err, hlen, dlen, copy;
1325 unsigned int sz; 1326 long timeout;
1326 u32 err;
1327 int res, hlen;
1328 1327
1329 /* Catch invalid receive requests */ 1328 /* Catch invalid receive requests */
1330 if (unlikely(!buf_len)) 1329 if (unlikely(!buflen))
1331 return -EINVAL; 1330 return -EINVAL;
1332 1331
1333 lock_sock(sk); 1332 lock_sock(sk);
1334 1333 if (unlikely(connected && sk->sk_state == TIPC_OPEN)) {
1335 if (!is_connectionless && unlikely(sk->sk_state == TIPC_OPEN)) { 1334 rc = -ENOTCONN;
1336 res = -ENOTCONN;
1337 goto exit; 1335 goto exit;
1338 } 1336 }
1337 timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
1339 1338
1340 timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); 1339 do {
1341restart: 1340 /* Look at first msg in receive queue; wait if necessary */
1342 1341 rc = tipc_wait_for_rcvmsg(sock, &timeout);
1343 /* Look for a message in receive queue; wait if necessary */ 1342 if (unlikely(rc))
1344 res = tipc_wait_for_rcvmsg(sock, &timeo); 1343 goto exit;
1345 if (res) 1344 skb = skb_peek(&sk->sk_receive_queue);
1346 goto exit; 1345 hdr = buf_msg(skb);
1347 1346 dlen = msg_data_sz(hdr);
1348 /* Look at first message in receive queue */ 1347 hlen = msg_hdr_sz(hdr);
1349 buf = skb_peek(&sk->sk_receive_queue); 1348 err = msg_errcode(hdr);
1350 msg = buf_msg(buf); 1349 if (likely(dlen || err))
1351 sz = msg_data_sz(msg); 1350 break;
1352 hlen = msg_hdr_sz(msg);
1353 err = msg_errcode(msg);
1354
1355 /* Discard an empty non-errored message & try again */
1356 if ((!sz) && (!err)) {
1357 tsk_advance_rx_queue(sk); 1351 tsk_advance_rx_queue(sk);
1358 goto restart; 1352 } while (1);
1359 }
1360
1361 /* Capture sender's address (optional) */
1362 set_orig_addr(m, msg);
1363 1353
1364 /* Capture ancillary data (optional) */ 1354 /* Collect msg meta data, including error code and rejected data */
1365 res = tipc_sk_anc_data_recv(m, msg, tsk); 1355 set_orig_addr(m, hdr);
1366 if (res) 1356 rc = tipc_sk_anc_data_recv(m, hdr, tsk);
1357 if (unlikely(rc))
1367 goto exit; 1358 goto exit;
1368 1359
1369 /* Capture message data (if valid) & compute return value (always) */ 1360 /* Capture data if non-error msg, otherwise just set return value */
1370 if (!err) { 1361 if (likely(!err)) {
1371 if (unlikely(buf_len < sz)) { 1362 copy = min_t(int, dlen, buflen);
1372 sz = buf_len; 1363 if (unlikely(copy != dlen))
1373 m->msg_flags |= MSG_TRUNC; 1364 m->msg_flags |= MSG_TRUNC;
1374 } 1365 rc = skb_copy_datagram_msg(skb, hlen, m, copy);
1375 res = skb_copy_datagram_msg(buf, hlen, m, sz);
1376 if (res)
1377 goto exit;
1378 res = sz;
1379 } else { 1366 } else {
1380 if (is_connectionless || err == TIPC_CONN_SHUTDOWN || 1367 copy = 0;
1381 m->msg_control) 1368 rc = 0;
1382 res = 0; 1369 if (err != TIPC_CONN_SHUTDOWN && connected && !m->msg_control)
1383 else 1370 rc = -ECONNRESET;
1384 res = -ECONNRESET;
1385 } 1371 }
1372 if (unlikely(rc))
1373 goto exit;
1386 1374
1375 /* Caption of data or error code/rejected data was successful */
1387 if (unlikely(flags & MSG_PEEK)) 1376 if (unlikely(flags & MSG_PEEK))
1388 goto exit; 1377 goto exit;
1389 1378
1390 if (likely(!is_connectionless)) {
1391 tsk->rcv_unacked += tsk_inc(tsk, hlen + sz);
1392 if (unlikely(tsk->rcv_unacked >= (tsk->rcv_win / 4)))
1393 tipc_sk_send_ack(tsk);
1394 }
1395 tsk_advance_rx_queue(sk); 1379 tsk_advance_rx_queue(sk);
1380 if (likely(!connected))
1381 goto exit;
1382
1383 /* Send connection flow control ack when applicable */
1384 tsk->rcv_unacked += tsk_inc(tsk, hlen + dlen);
1385 if (tsk->rcv_unacked >= tsk->rcv_win / TIPC_ACK_RATE)
1386 tipc_sk_send_ack(tsk);
1396exit: 1387exit:
1397 release_sock(sk); 1388 release_sock(sk);
1398 return res; 1389 return rc ? rc : copy;
1399} 1390}
1400 1391
1401/** 1392/**
1402 * tipc_recv_stream - receive stream-oriented data 1393 * tipc_recvstream - receive stream-oriented data
1403 * @m: descriptor for message info 1394 * @m: descriptor for message info
1404 * @buf_len: total size of user buffer area 1395 * @buflen: total size of user buffer area
1405 * @flags: receive flags 1396 * @flags: receive flags
1406 * 1397 *
1407 * Used for SOCK_STREAM messages only. If not enough data is available 1398 * Used for SOCK_STREAM messages only. If not enough data is available
@@ -1409,111 +1400,98 @@ exit:
1409 * 1400 *
1410 * Returns size of returned message data, errno otherwise 1401 * Returns size of returned message data, errno otherwise
1411 */ 1402 */
1412static int tipc_recv_stream(struct socket *sock, struct msghdr *m, 1403static int tipc_recvstream(struct socket *sock, struct msghdr *m,
1413 size_t buf_len, int flags) 1404 size_t buflen, int flags)
1414{ 1405{
1415 struct sock *sk = sock->sk; 1406 struct sock *sk = sock->sk;
1416 struct tipc_sock *tsk = tipc_sk(sk); 1407 struct tipc_sock *tsk = tipc_sk(sk);
1417 struct sk_buff *buf; 1408 struct sk_buff *skb;
1418 struct tipc_msg *msg; 1409 struct tipc_msg *hdr;
1419 long timeo; 1410 struct tipc_skb_cb *skb_cb;
1420 unsigned int sz; 1411 bool peek = flags & MSG_PEEK;
1421 int target; 1412 int offset, required, copy, copied = 0;
1422 int sz_copied = 0; 1413 int hlen, dlen, err, rc;
1423 u32 err; 1414 long timeout;
1424 int res = 0, hlen;
1425 1415
1426 /* Catch invalid receive attempts */ 1416 /* Catch invalid receive attempts */
1427 if (unlikely(!buf_len)) 1417 if (unlikely(!buflen))
1428 return -EINVAL; 1418 return -EINVAL;
1429 1419
1430 lock_sock(sk); 1420 lock_sock(sk);
1431 1421
1432 if (unlikely(sk->sk_state == TIPC_OPEN)) { 1422 if (unlikely(sk->sk_state == TIPC_OPEN)) {
1433 res = -ENOTCONN; 1423 rc = -ENOTCONN;
1434 goto exit;
1435 }
1436
1437 target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
1438 timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
1439
1440restart:
1441 /* Look for a message in receive queue; wait if necessary */
1442 res = tipc_wait_for_rcvmsg(sock, &timeo);
1443 if (res)
1444 goto exit; 1424 goto exit;
1445
1446 /* Look at first message in receive queue */
1447 buf = skb_peek(&sk->sk_receive_queue);
1448 msg = buf_msg(buf);
1449 sz = msg_data_sz(msg);
1450 hlen = msg_hdr_sz(msg);
1451 err = msg_errcode(msg);
1452
1453 /* Discard an empty non-errored message & try again */
1454 if ((!sz) && (!err)) {
1455 tsk_advance_rx_queue(sk);
1456 goto restart;
1457 } 1425 }
1426 required = sock_rcvlowat(sk, flags & MSG_WAITALL, buflen);
1427 timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
1458 1428
1459 /* Optionally capture sender's address & ancillary data of first msg */ 1429 do {
1460 if (sz_copied == 0) { 1430 /* Look at first msg in receive queue; wait if necessary */
1461 set_orig_addr(m, msg); 1431 rc = tipc_wait_for_rcvmsg(sock, &timeout);
1462 res = tipc_sk_anc_data_recv(m, msg, tsk); 1432 if (unlikely(rc))
1463 if (res) 1433 break;
1464 goto exit; 1434 skb = skb_peek(&sk->sk_receive_queue);
1465 } 1435 skb_cb = TIPC_SKB_CB(skb);
1466 1436 hdr = buf_msg(skb);
1467 /* Capture message data (if valid) & compute return value (always) */ 1437 dlen = msg_data_sz(hdr);
1468 if (!err) { 1438 hlen = msg_hdr_sz(hdr);
1469 u32 offset = TIPC_SKB_CB(buf)->bytes_read; 1439 err = msg_errcode(hdr);
1470 u32 needed; 1440
1471 int sz_to_copy; 1441 /* Discard any empty non-errored (SYN-) message */
1472 1442 if (unlikely(!dlen && !err)) {
1473 sz -= offset; 1443 tsk_advance_rx_queue(sk);
1474 needed = (buf_len - sz_copied); 1444 continue;
1475 sz_to_copy = min(sz, needed); 1445 }
1476
1477 res = skb_copy_datagram_msg(buf, hlen + offset, m, sz_to_copy);
1478 if (res)
1479 goto exit;
1480 1446
1481 sz_copied += sz_to_copy; 1447 /* Collect msg meta data, incl. error code and rejected data */
1448 if (!copied) {
1449 set_orig_addr(m, hdr);
1450 rc = tipc_sk_anc_data_recv(m, hdr, tsk);
1451 if (rc)
1452 break;
1453 }
1482 1454
1483 if (sz_to_copy < sz) { 1455 /* Copy data if msg ok, otherwise return error/partial data */
1484 if (!(flags & MSG_PEEK)) 1456 if (likely(!err)) {
1485 TIPC_SKB_CB(buf)->bytes_read = 1457 offset = skb_cb->bytes_read;
1486 offset + sz_to_copy; 1458 copy = min_t(int, dlen - offset, buflen - copied);
1487 goto exit; 1459 rc = skb_copy_datagram_msg(skb, hlen + offset, m, copy);
1460 if (unlikely(rc))
1461 break;
1462 copied += copy;
1463 offset += copy;
1464 if (unlikely(offset < dlen)) {
1465 if (!peek)
1466 skb_cb->bytes_read = offset;
1467 break;
1468 }
1469 } else {
1470 rc = 0;
1471 if ((err != TIPC_CONN_SHUTDOWN) && !m->msg_control)
1472 rc = -ECONNRESET;
1473 if (copied || rc)
1474 break;
1488 } 1475 }
1489 } else {
1490 if (sz_copied != 0)
1491 goto exit; /* can't add error msg to valid data */
1492 1476
1493 if ((err == TIPC_CONN_SHUTDOWN) || m->msg_control) 1477 if (unlikely(peek))
1494 res = 0; 1478 break;
1495 else
1496 res = -ECONNRESET;
1497 }
1498 1479
1499 if (unlikely(flags & MSG_PEEK)) 1480 tsk_advance_rx_queue(sk);
1500 goto exit;
1501 1481
1502 tsk->rcv_unacked += tsk_inc(tsk, hlen + msg_data_sz(msg)); 1482 /* Send connection flow control advertisement when applicable */
1503 if (unlikely(tsk->rcv_unacked >= (tsk->rcv_win / 4))) 1483 tsk->rcv_unacked += tsk_inc(tsk, hlen + dlen);
1504 tipc_sk_send_ack(tsk); 1484 if (unlikely(tsk->rcv_unacked >= tsk->rcv_win / TIPC_ACK_RATE))
1505 tsk_advance_rx_queue(sk); 1485 tipc_sk_send_ack(tsk);
1506 1486
1507 /* Loop around if more data is required */ 1487 /* Exit if all requested data or FIN/error received */
1508 if ((sz_copied < buf_len) && /* didn't get all requested data */ 1488 if (copied == buflen || err)
1509 (!skb_queue_empty(&sk->sk_receive_queue) || 1489 break;
1510 (sz_copied < target)) && /* and more is ready or required */
1511 (!err)) /* and haven't reached a FIN */
1512 goto restart;
1513 1490
1491 } while (!skb_queue_empty(&sk->sk_receive_queue) || copied < required);
1514exit: 1492exit:
1515 release_sock(sk); 1493 release_sock(sk);
1516 return sz_copied ? sz_copied : res; 1494 return copied ? copied : rc;
1517} 1495}
1518 1496
1519/** 1497/**
@@ -2537,6 +2515,28 @@ static int tipc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
2537 } 2515 }
2538} 2516}
2539 2517
2518static int tipc_socketpair(struct socket *sock1, struct socket *sock2)
2519{
2520 struct tipc_sock *tsk2 = tipc_sk(sock2->sk);
2521 struct tipc_sock *tsk1 = tipc_sk(sock1->sk);
2522 u32 onode = tipc_own_addr(sock_net(sock1->sk));
2523
2524 tsk1->peer.family = AF_TIPC;
2525 tsk1->peer.addrtype = TIPC_ADDR_ID;
2526 tsk1->peer.scope = TIPC_NODE_SCOPE;
2527 tsk1->peer.addr.id.ref = tsk2->portid;
2528 tsk1->peer.addr.id.node = onode;
2529 tsk2->peer.family = AF_TIPC;
2530 tsk2->peer.addrtype = TIPC_ADDR_ID;
2531 tsk2->peer.scope = TIPC_NODE_SCOPE;
2532 tsk2->peer.addr.id.ref = tsk1->portid;
2533 tsk2->peer.addr.id.node = onode;
2534
2535 tipc_sk_finish_conn(tsk1, tsk2->portid, onode);
2536 tipc_sk_finish_conn(tsk2, tsk1->portid, onode);
2537 return 0;
2538}
2539
2540/* Protocol switches for the various types of TIPC sockets */ 2540/* Protocol switches for the various types of TIPC sockets */
2541 2541
2542static const struct proto_ops msg_ops = { 2542static const struct proto_ops msg_ops = {
@@ -2545,7 +2545,7 @@ static const struct proto_ops msg_ops = {
2545 .release = tipc_release, 2545 .release = tipc_release,
2546 .bind = tipc_bind, 2546 .bind = tipc_bind,
2547 .connect = tipc_connect, 2547 .connect = tipc_connect,
2548 .socketpair = sock_no_socketpair, 2548 .socketpair = tipc_socketpair,
2549 .accept = sock_no_accept, 2549 .accept = sock_no_accept,
2550 .getname = tipc_getname, 2550 .getname = tipc_getname,
2551 .poll = tipc_poll, 2551 .poll = tipc_poll,
@@ -2566,7 +2566,7 @@ static const struct proto_ops packet_ops = {
2566 .release = tipc_release, 2566 .release = tipc_release,
2567 .bind = tipc_bind, 2567 .bind = tipc_bind,
2568 .connect = tipc_connect, 2568 .connect = tipc_connect,
2569 .socketpair = sock_no_socketpair, 2569 .socketpair = tipc_socketpair,
2570 .accept = tipc_accept, 2570 .accept = tipc_accept,
2571 .getname = tipc_getname, 2571 .getname = tipc_getname,
2572 .poll = tipc_poll, 2572 .poll = tipc_poll,
@@ -2587,7 +2587,7 @@ static const struct proto_ops stream_ops = {
2587 .release = tipc_release, 2587 .release = tipc_release,
2588 .bind = tipc_bind, 2588 .bind = tipc_bind,
2589 .connect = tipc_connect, 2589 .connect = tipc_connect,
2590 .socketpair = sock_no_socketpair, 2590 .socketpair = tipc_socketpair,
2591 .accept = tipc_accept, 2591 .accept = tipc_accept,
2592 .getname = tipc_getname, 2592 .getname = tipc_getname,
2593 .poll = tipc_poll, 2593 .poll = tipc_poll,
@@ -2597,7 +2597,7 @@ static const struct proto_ops stream_ops = {
2597 .setsockopt = tipc_setsockopt, 2597 .setsockopt = tipc_setsockopt,
2598 .getsockopt = tipc_getsockopt, 2598 .getsockopt = tipc_getsockopt,
2599 .sendmsg = tipc_sendstream, 2599 .sendmsg = tipc_sendstream,
2600 .recvmsg = tipc_recv_stream, 2600 .recvmsg = tipc_recvstream,
2601 .mmap = sock_no_mmap, 2601 .mmap = sock_no_mmap,
2602 .sendpage = sock_no_sendpage 2602 .sendpage = sock_no_sendpage
2603}; 2603};
@@ -2870,7 +2870,7 @@ int tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb)
2870 2870
2871 err = nla_parse_nested(sock, TIPC_NLA_SOCK_MAX, 2871 err = nla_parse_nested(sock, TIPC_NLA_SOCK_MAX,
2872 attrs[TIPC_NLA_SOCK], 2872 attrs[TIPC_NLA_SOCK],
2873 tipc_nl_sock_policy); 2873 tipc_nl_sock_policy, NULL);
2874 if (err) 2874 if (err)
2875 return err; 2875 return err;
2876 2876