diff options
| author | Wolfram Sang <wsa@the-dreams.de> | 2014-06-17 08:36:41 -0400 |
|---|---|---|
| committer | Wolfram Sang <wsa@the-dreams.de> | 2014-06-17 08:37:31 -0400 |
| commit | f0b1f6442b5090fed3529cb39f3acf8c91693d3d (patch) | |
| tree | bc5f62b017a82161c9a7f892f464813f6efd5bf3 /net/tipc/socket.c | |
| parent | 4632a93f015caf6d7db4352f37aab74a39e60d7a (diff) | |
| parent | 7171511eaec5bf23fb06078f59784a3a0626b38f (diff) | |
Merge tag 'v3.16-rc1' into i2c/for-next
Merge a stable base (Linux 3.16-rc1)
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'net/tipc/socket.c')
| -rw-r--r-- | net/tipc/socket.c | 121 |
1 files changed, 87 insertions, 34 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 3c0256962f7d..ef0475568f9e 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | 36 | ||
| 37 | #include "core.h" | 37 | #include "core.h" |
| 38 | #include "port.h" | 38 | #include "port.h" |
| 39 | #include "node.h" | ||
| 39 | 40 | ||
| 40 | #include <linux/export.h> | 41 | #include <linux/export.h> |
| 41 | 42 | ||
| @@ -44,7 +45,7 @@ | |||
| 44 | 45 | ||
| 45 | #define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */ | 46 | #define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */ |
| 46 | 47 | ||
| 47 | static int backlog_rcv(struct sock *sk, struct sk_buff *skb); | 48 | static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb); |
| 48 | static void tipc_data_ready(struct sock *sk); | 49 | static void tipc_data_ready(struct sock *sk); |
| 49 | static void tipc_write_space(struct sock *sk); | 50 | static void tipc_write_space(struct sock *sk); |
| 50 | static int tipc_release(struct socket *sock); | 51 | static int tipc_release(struct socket *sock); |
| @@ -195,11 +196,12 @@ static int tipc_sk_create(struct net *net, struct socket *sock, | |||
| 195 | sock->state = state; | 196 | sock->state = state; |
| 196 | 197 | ||
| 197 | sock_init_data(sock, sk); | 198 | sock_init_data(sock, sk); |
| 198 | sk->sk_backlog_rcv = backlog_rcv; | 199 | sk->sk_backlog_rcv = tipc_backlog_rcv; |
| 199 | sk->sk_rcvbuf = sysctl_tipc_rmem[1]; | 200 | sk->sk_rcvbuf = sysctl_tipc_rmem[1]; |
| 200 | sk->sk_data_ready = tipc_data_ready; | 201 | sk->sk_data_ready = tipc_data_ready; |
| 201 | sk->sk_write_space = tipc_write_space; | 202 | sk->sk_write_space = tipc_write_space; |
| 202 | tipc_sk(sk)->conn_timeout = CONN_TIMEOUT_DEFAULT; | 203 | tsk->conn_timeout = CONN_TIMEOUT_DEFAULT; |
| 204 | atomic_set(&tsk->dupl_rcvcnt, 0); | ||
| 203 | tipc_port_unlock(port); | 205 | tipc_port_unlock(port); |
| 204 | 206 | ||
| 205 | if (sock->state == SS_READY) { | 207 | if (sock->state == SS_READY) { |
| @@ -983,10 +985,11 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, | |||
| 983 | return 0; | 985 | return 0; |
| 984 | } | 986 | } |
| 985 | 987 | ||
| 986 | static int tipc_wait_for_rcvmsg(struct socket *sock, long timeo) | 988 | static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop) |
| 987 | { | 989 | { |
| 988 | struct sock *sk = sock->sk; | 990 | struct sock *sk = sock->sk; |
| 989 | DEFINE_WAIT(wait); | 991 | DEFINE_WAIT(wait); |
| 992 | long timeo = *timeop; | ||
| 990 | int err; | 993 | int err; |
| 991 | 994 | ||
| 992 | for (;;) { | 995 | for (;;) { |
| @@ -1011,6 +1014,7 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long timeo) | |||
| 1011 | break; | 1014 | break; |
| 1012 | } | 1015 | } |
| 1013 | finish_wait(sk_sleep(sk), &wait); | 1016 | finish_wait(sk_sleep(sk), &wait); |
| 1017 | *timeop = timeo; | ||
| 1014 | return err; | 1018 | return err; |
| 1015 | } | 1019 | } |
| 1016 | 1020 | ||
| @@ -1054,7 +1058,7 @@ static int tipc_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1054 | restart: | 1058 | restart: |
| 1055 | 1059 | ||
| 1056 | /* Look for a message in receive queue; wait if necessary */ | 1060 | /* Look for a message in receive queue; wait if necessary */ |
| 1057 | res = tipc_wait_for_rcvmsg(sock, timeo); | 1061 | res = tipc_wait_for_rcvmsg(sock, &timeo); |
| 1058 | if (res) | 1062 | if (res) |
| 1059 | goto exit; | 1063 | goto exit; |
| 1060 | 1064 | ||
| @@ -1100,7 +1104,7 @@ restart: | |||
| 1100 | /* Consume received message (optional) */ | 1104 | /* Consume received message (optional) */ |
| 1101 | if (likely(!(flags & MSG_PEEK))) { | 1105 | if (likely(!(flags & MSG_PEEK))) { |
| 1102 | if ((sock->state != SS_READY) && | 1106 | if ((sock->state != SS_READY) && |
| 1103 | (++port->conn_unacked >= TIPC_FLOW_CONTROL_WIN)) | 1107 | (++port->conn_unacked >= TIPC_CONNACK_INTV)) |
| 1104 | tipc_acknowledge(port->ref, port->conn_unacked); | 1108 | tipc_acknowledge(port->ref, port->conn_unacked); |
| 1105 | advance_rx_queue(sk); | 1109 | advance_rx_queue(sk); |
| 1106 | } | 1110 | } |
| @@ -1152,7 +1156,7 @@ static int tipc_recv_stream(struct kiocb *iocb, struct socket *sock, | |||
| 1152 | 1156 | ||
| 1153 | restart: | 1157 | restart: |
| 1154 | /* Look for a message in receive queue; wait if necessary */ | 1158 | /* Look for a message in receive queue; wait if necessary */ |
| 1155 | res = tipc_wait_for_rcvmsg(sock, timeo); | 1159 | res = tipc_wait_for_rcvmsg(sock, &timeo); |
| 1156 | if (res) | 1160 | if (res) |
| 1157 | goto exit; | 1161 | goto exit; |
| 1158 | 1162 | ||
| @@ -1209,7 +1213,7 @@ restart: | |||
| 1209 | 1213 | ||
| 1210 | /* Consume received message (optional) */ | 1214 | /* Consume received message (optional) */ |
| 1211 | if (likely(!(flags & MSG_PEEK))) { | 1215 | if (likely(!(flags & MSG_PEEK))) { |
| 1212 | if (unlikely(++port->conn_unacked >= TIPC_FLOW_CONTROL_WIN)) | 1216 | if (unlikely(++port->conn_unacked >= TIPC_CONNACK_INTV)) |
| 1213 | tipc_acknowledge(port->ref, port->conn_unacked); | 1217 | tipc_acknowledge(port->ref, port->conn_unacked); |
| 1214 | advance_rx_queue(sk); | 1218 | advance_rx_queue(sk); |
| 1215 | } | 1219 | } |
| @@ -1415,7 +1419,7 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf) | |||
| 1415 | } | 1419 | } |
| 1416 | 1420 | ||
| 1417 | /** | 1421 | /** |
| 1418 | * backlog_rcv - handle incoming message from backlog queue | 1422 | * tipc_backlog_rcv - handle incoming message from backlog queue |
| 1419 | * @sk: socket | 1423 | * @sk: socket |
| 1420 | * @buf: message | 1424 | * @buf: message |
| 1421 | * | 1425 | * |
| @@ -1423,47 +1427,74 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf) | |||
| 1423 | * | 1427 | * |
| 1424 | * Returns 0 | 1428 | * Returns 0 |
| 1425 | */ | 1429 | */ |
| 1426 | static int backlog_rcv(struct sock *sk, struct sk_buff *buf) | 1430 | static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *buf) |
| 1427 | { | 1431 | { |
| 1428 | u32 res; | 1432 | u32 res; |
| 1433 | struct tipc_sock *tsk = tipc_sk(sk); | ||
| 1434 | uint truesize = buf->truesize; | ||
| 1429 | 1435 | ||
| 1430 | res = filter_rcv(sk, buf); | 1436 | res = filter_rcv(sk, buf); |
| 1431 | if (res) | 1437 | if (unlikely(res)) |
| 1432 | tipc_reject_msg(buf, res); | 1438 | tipc_reject_msg(buf, res); |
| 1439 | |||
| 1440 | if (atomic_read(&tsk->dupl_rcvcnt) < TIPC_CONN_OVERLOAD_LIMIT) | ||
| 1441 | atomic_add(truesize, &tsk->dupl_rcvcnt); | ||
| 1442 | |||
| 1433 | return 0; | 1443 | return 0; |
| 1434 | } | 1444 | } |
| 1435 | 1445 | ||
| 1436 | /** | 1446 | /** |
| 1437 | * tipc_sk_rcv - handle incoming message | 1447 | * tipc_sk_rcv - handle incoming message |
| 1438 | * @sk: socket receiving message | 1448 | * @buf: buffer containing arriving message |
| 1439 | * @buf: message | 1449 | * Consumes buffer |
| 1440 | * | 1450 | * Returns 0 if success, or errno: -EHOSTUNREACH |
| 1441 | * Called with port lock already taken. | ||
| 1442 | * | ||
| 1443 | * Returns TIPC error status code (TIPC_OK if message is not to be rejected) | ||
| 1444 | */ | 1451 | */ |
| 1445 | u32 tipc_sk_rcv(struct sock *sk, struct sk_buff *buf) | 1452 | int tipc_sk_rcv(struct sk_buff *buf) |
| 1446 | { | 1453 | { |
| 1447 | u32 res; | 1454 | struct tipc_sock *tsk; |
| 1455 | struct tipc_port *port; | ||
| 1456 | struct sock *sk; | ||
| 1457 | u32 dport = msg_destport(buf_msg(buf)); | ||
| 1458 | int err = TIPC_OK; | ||
| 1459 | uint limit; | ||
| 1448 | 1460 | ||
| 1449 | /* | 1461 | /* Forward unresolved named message */ |
| 1450 | * Process message if socket is unlocked; otherwise add to backlog queue | 1462 | if (unlikely(!dport)) { |
| 1451 | * | 1463 | tipc_net_route_msg(buf); |
| 1452 | * This code is based on sk_receive_skb(), but must be distinct from it | 1464 | return 0; |
| 1453 | * since a TIPC-specific filter/reject mechanism is utilized | 1465 | } |
| 1454 | */ | 1466 | |
| 1467 | /* Validate destination */ | ||
| 1468 | port = tipc_port_lock(dport); | ||
| 1469 | if (unlikely(!port)) { | ||
| 1470 | err = TIPC_ERR_NO_PORT; | ||
| 1471 | goto exit; | ||
| 1472 | } | ||
| 1473 | |||
| 1474 | tsk = tipc_port_to_sock(port); | ||
| 1475 | sk = &tsk->sk; | ||
| 1476 | |||
| 1477 | /* Queue message */ | ||
| 1455 | bh_lock_sock(sk); | 1478 | bh_lock_sock(sk); |
| 1479 | |||
| 1456 | if (!sock_owned_by_user(sk)) { | 1480 | if (!sock_owned_by_user(sk)) { |
| 1457 | res = filter_rcv(sk, buf); | 1481 | err = filter_rcv(sk, buf); |
| 1458 | } else { | 1482 | } else { |
| 1459 | if (sk_add_backlog(sk, buf, rcvbuf_limit(sk, buf))) | 1483 | if (sk->sk_backlog.len == 0) |
| 1460 | res = TIPC_ERR_OVERLOAD; | 1484 | atomic_set(&tsk->dupl_rcvcnt, 0); |
| 1461 | else | 1485 | limit = rcvbuf_limit(sk, buf) + atomic_read(&tsk->dupl_rcvcnt); |
| 1462 | res = TIPC_OK; | 1486 | if (sk_add_backlog(sk, buf, limit)) |
| 1487 | err = TIPC_ERR_OVERLOAD; | ||
| 1463 | } | 1488 | } |
| 1489 | |||
| 1464 | bh_unlock_sock(sk); | 1490 | bh_unlock_sock(sk); |
| 1491 | tipc_port_unlock(port); | ||
| 1465 | 1492 | ||
| 1466 | return res; | 1493 | if (likely(!err)) |
| 1494 | return 0; | ||
| 1495 | exit: | ||
| 1496 | tipc_reject_msg(buf, err); | ||
| 1497 | return -EHOSTUNREACH; | ||
| 1467 | } | 1498 | } |
| 1468 | 1499 | ||
| 1469 | static int tipc_wait_for_connect(struct socket *sock, long *timeo_p) | 1500 | static int tipc_wait_for_connect(struct socket *sock, long *timeo_p) |
| @@ -1905,6 +1936,28 @@ static int tipc_getsockopt(struct socket *sock, int lvl, int opt, | |||
| 1905 | return put_user(sizeof(value), ol); | 1936 | return put_user(sizeof(value), ol); |
| 1906 | } | 1937 | } |
| 1907 | 1938 | ||
| 1939 | int tipc_ioctl(struct socket *sk, unsigned int cmd, unsigned long arg) | ||
| 1940 | { | ||
| 1941 | struct tipc_sioc_ln_req lnr; | ||
| 1942 | void __user *argp = (void __user *)arg; | ||
| 1943 | |||
| 1944 | switch (cmd) { | ||
| 1945 | case SIOCGETLINKNAME: | ||
| 1946 | if (copy_from_user(&lnr, argp, sizeof(lnr))) | ||
| 1947 | return -EFAULT; | ||
| 1948 | if (!tipc_node_get_linkname(lnr.bearer_id, lnr.peer, | ||
| 1949 | lnr.linkname, TIPC_MAX_LINK_NAME)) { | ||
| 1950 | if (copy_to_user(argp, &lnr, sizeof(lnr))) | ||
| 1951 | return -EFAULT; | ||
| 1952 | return 0; | ||
| 1953 | } | ||
| 1954 | return -EADDRNOTAVAIL; | ||
| 1955 | break; | ||
| 1956 | default: | ||
| 1957 | return -ENOIOCTLCMD; | ||
| 1958 | } | ||
| 1959 | } | ||
| 1960 | |||
| 1908 | /* Protocol switches for the various types of TIPC sockets */ | 1961 | /* Protocol switches for the various types of TIPC sockets */ |
| 1909 | 1962 | ||
| 1910 | static const struct proto_ops msg_ops = { | 1963 | static const struct proto_ops msg_ops = { |
| @@ -1917,7 +1970,7 @@ static const struct proto_ops msg_ops = { | |||
| 1917 | .accept = sock_no_accept, | 1970 | .accept = sock_no_accept, |
| 1918 | .getname = tipc_getname, | 1971 | .getname = tipc_getname, |
| 1919 | .poll = tipc_poll, | 1972 | .poll = tipc_poll, |
| 1920 | .ioctl = sock_no_ioctl, | 1973 | .ioctl = tipc_ioctl, |
| 1921 | .listen = sock_no_listen, | 1974 | .listen = sock_no_listen, |
| 1922 | .shutdown = tipc_shutdown, | 1975 | .shutdown = tipc_shutdown, |
| 1923 | .setsockopt = tipc_setsockopt, | 1976 | .setsockopt = tipc_setsockopt, |
| @@ -1938,7 +1991,7 @@ static const struct proto_ops packet_ops = { | |||
| 1938 | .accept = tipc_accept, | 1991 | .accept = tipc_accept, |
| 1939 | .getname = tipc_getname, | 1992 | .getname = tipc_getname, |
| 1940 | .poll = tipc_poll, | 1993 | .poll = tipc_poll, |
| 1941 | .ioctl = sock_no_ioctl, | 1994 | .ioctl = tipc_ioctl, |
| 1942 | .listen = tipc_listen, | 1995 | .listen = tipc_listen, |
| 1943 | .shutdown = tipc_shutdown, | 1996 | .shutdown = tipc_shutdown, |
| 1944 | .setsockopt = tipc_setsockopt, | 1997 | .setsockopt = tipc_setsockopt, |
| @@ -1959,7 +2012,7 @@ static const struct proto_ops stream_ops = { | |||
| 1959 | .accept = tipc_accept, | 2012 | .accept = tipc_accept, |
| 1960 | .getname = tipc_getname, | 2013 | .getname = tipc_getname, |
| 1961 | .poll = tipc_poll, | 2014 | .poll = tipc_poll, |
| 1962 | .ioctl = sock_no_ioctl, | 2015 | .ioctl = tipc_ioctl, |
| 1963 | .listen = tipc_listen, | 2016 | .listen = tipc_listen, |
| 1964 | .shutdown = tipc_shutdown, | 2017 | .shutdown = tipc_shutdown, |
| 1965 | .setsockopt = tipc_setsockopt, | 2018 | .setsockopt = tipc_setsockopt, |
