diff options
author | David Howells <dhowells@redhat.com> | 2018-03-30 21:04:43 +0100 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2018-03-30 21:04:43 +0100 |
commit | ace45bec6d77bc061c3c3d8ad99e298ea9800c2b (patch) | |
tree | 3f87956bcdbccf8470eeb867ffe1760998b4bb0c /net/rxrpc/output.c | |
parent | c0b6edef0bf0e33c12eaf80c676ff09def011518 (diff) | |
download | linux-stable-ace45bec6d77bc061c3c3d8ad99e298ea9800c2b.tar.gz linux-stable-ace45bec6d77bc061c3c3d8ad99e298ea9800c2b.tar.bz2 linux-stable-ace45bec6d77bc061c3c3d8ad99e298ea9800c2b.zip |
rxrpc: Fix firewall route keepalive
Fix the firewall route keepalive part of AF_RXRPC which is currently
function incorrectly by replying to VERSION REPLY packets from the server
with VERSION REQUEST packets.
Instead, send VERSION REPLY packets to the peers of service connections to
act as keep-alives 20s after the latest packet was transmitted to that
peer.
Also, just discard VERSION REPLY packets rather than replying to them.
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'net/rxrpc/output.c')
-rw-r--r-- | net/rxrpc/output.c | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c index cf73dc006c3b..7f1fc04775b3 100644 --- a/net/rxrpc/output.c +++ b/net/rxrpc/output.c @@ -32,6 +32,8 @@ struct rxrpc_abort_buffer { __be32 abort_code; }; +static const char rxrpc_keepalive_string[] = ""; + /* * Arrange for a keepalive ping a certain time after we last transmitted. This * lets the far side know we're still interested in this call and helps keep @@ -122,6 +124,7 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping, struct kvec iov[2]; rxrpc_serial_t serial; rxrpc_seq_t hard_ack, top; + ktime_t now; size_t len, n; int ret; u8 reason; @@ -203,8 +206,10 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping, } ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len); + now = ktime_get_real(); if (ping) - call->ping_time = ktime_get_real(); + call->ping_time = now; + conn->params.peer->last_tx_at = ktime_get_real(); if (call->state < RXRPC_CALL_COMPLETE) { if (ret < 0) { @@ -288,6 +293,7 @@ int rxrpc_send_abort_packet(struct rxrpc_call *call) ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 1, sizeof(pkt)); + conn->params.peer->last_tx_at = ktime_get_real(); rxrpc_put_connection(conn); return ret; @@ -378,6 +384,7 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb, * message and update the peer record */ ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len); + conn->params.peer->last_tx_at = ktime_get_real(); up_read(&conn->params.local->defrag_sem); if (ret == -EMSGSIZE) @@ -429,6 +436,7 @@ send_fragmentable: if (ret == 0) { ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len); + conn->params.peer->last_tx_at = ktime_get_real(); opt = IP_PMTUDISC_DO; kernel_setsockopt(conn->params.local->socket, SOL_IP, @@ -446,6 +454,7 @@ send_fragmentable: if (ret == 0) { ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len); + conn->params.peer->last_tx_at = ktime_get_real(); opt = IPV6_PMTUDISC_DO; kernel_setsockopt(conn->params.local->socket, @@ -515,3 +524,51 @@ void rxrpc_reject_packets(struct rxrpc_local *local) _leave(""); } + +/* + * Send a VERSION reply to a peer as a keepalive. + */ +void rxrpc_send_keepalive(struct rxrpc_peer *peer) +{ + struct rxrpc_wire_header whdr; + struct msghdr msg; + struct kvec iov[2]; + size_t len; + int ret; + + _enter(""); + + msg.msg_name = &peer->srx.transport; + msg.msg_namelen = peer->srx.transport_len; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + whdr.epoch = htonl(peer->local->rxnet->epoch); + whdr.cid = 0; + whdr.callNumber = 0; + whdr.seq = 0; + whdr.serial = 0; + whdr.type = RXRPC_PACKET_TYPE_VERSION; /* Not client-initiated */ + whdr.flags = RXRPC_LAST_PACKET; + whdr.userStatus = 0; + whdr.securityIndex = 0; + whdr._rsvd = 0; + whdr.serviceId = 0; + + iov[0].iov_base = &whdr; + iov[0].iov_len = sizeof(whdr); + iov[1].iov_base = (char *)rxrpc_keepalive_string; + iov[1].iov_len = sizeof(rxrpc_keepalive_string); + + len = iov[0].iov_len + iov[1].iov_len; + + _proto("Tx VERSION (keepalive)"); + + ret = kernel_sendmsg(peer->local->socket, &msg, iov, 2, len); + if (ret < 0) + _debug("sendmsg failed: %d", ret); + + peer->last_tx_at = ktime_get_real(); + _leave(""); +} |