Skip to content

Commit ace45be

Browse files
committed
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>
1 parent c0b6ede commit ace45be

9 files changed

Lines changed: 204 additions & 4 deletions

File tree

net/rxrpc/af_rxrpc.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,7 @@ static __poll_t rxrpc_poll(struct file *file, struct socket *sock,
762762
static int rxrpc_create(struct net *net, struct socket *sock, int protocol,
763763
int kern)
764764
{
765+
struct rxrpc_net *rxnet;
765766
struct rxrpc_sock *rx;
766767
struct sock *sk;
767768

@@ -801,6 +802,9 @@ static int rxrpc_create(struct net *net, struct socket *sock, int protocol,
801802
rwlock_init(&rx->call_lock);
802803
memset(&rx->srx, 0, sizeof(rx->srx));
803804

805+
rxnet = rxrpc_net(sock_net(&rx->sk));
806+
timer_reduce(&rxnet->peer_keepalive_timer, jiffies + 1);
807+
804808
_leave(" = 0 [%p]", rx);
805809
return 0;
806810
}

net/rxrpc/ar-internal.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,16 @@ struct rxrpc_net {
9797
struct list_head local_endpoints;
9898
struct mutex local_mutex; /* Lock for ->local_endpoints */
9999

100-
spinlock_t peer_hash_lock; /* Lock for ->peer_hash */
101100
DECLARE_HASHTABLE (peer_hash, 10);
101+
spinlock_t peer_hash_lock; /* Lock for ->peer_hash */
102+
103+
#define RXRPC_KEEPALIVE_TIME 20 /* NAT keepalive time in seconds */
104+
u8 peer_keepalive_cursor;
105+
ktime_t peer_keepalive_base;
106+
struct hlist_head peer_keepalive[RXRPC_KEEPALIVE_TIME + 1];
107+
struct hlist_head peer_keepalive_new;
108+
struct timer_list peer_keepalive_timer;
109+
struct work_struct peer_keepalive_work;
102110
};
103111

104112
/*
@@ -285,6 +293,8 @@ struct rxrpc_peer {
285293
struct hlist_head error_targets; /* targets for net error distribution */
286294
struct work_struct error_distributor;
287295
struct rb_root service_conns; /* Service connections */
296+
struct hlist_node keepalive_link; /* Link in net->peer_keepalive[] */
297+
time64_t last_tx_at; /* Last time packet sent here */
288298
seqlock_t service_conn_lock;
289299
spinlock_t lock; /* access lock */
290300
unsigned int if_mtu; /* interface MTU for this peer */
@@ -1026,6 +1036,7 @@ int rxrpc_send_ack_packet(struct rxrpc_call *, bool, rxrpc_serial_t *);
10261036
int rxrpc_send_abort_packet(struct rxrpc_call *);
10271037
int rxrpc_send_data_packet(struct rxrpc_call *, struct sk_buff *, bool);
10281038
void rxrpc_reject_packets(struct rxrpc_local *);
1039+
void rxrpc_send_keepalive(struct rxrpc_peer *);
10291040

10301041
/*
10311042
* peer_event.c
@@ -1034,6 +1045,7 @@ void rxrpc_error_report(struct sock *);
10341045
void rxrpc_peer_error_distributor(struct work_struct *);
10351046
void rxrpc_peer_add_rtt(struct rxrpc_call *, enum rxrpc_rtt_rx_trace,
10361047
rxrpc_serial_t, rxrpc_serial_t, ktime_t, ktime_t);
1048+
void rxrpc_peer_keepalive_worker(struct work_struct *);
10371049

10381050
/*
10391051
* peer_object.c

net/rxrpc/conn_event.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ static void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
136136
}
137137

138138
kernel_sendmsg(conn->params.local->socket, &msg, iov, ioc, len);
139+
conn->params.peer->last_tx_at = ktime_get_real();
139140
_leave("");
140141
return;
141142
}
@@ -239,6 +240,8 @@ static int rxrpc_abort_connection(struct rxrpc_connection *conn,
239240
return -EAGAIN;
240241
}
241242

243+
conn->params.peer->last_tx_at = ktime_get_real();
244+
242245
_leave(" = 0");
243246
return 0;
244247
}

net/rxrpc/input.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,6 +1183,8 @@ void rxrpc_data_ready(struct sock *udp_sk)
11831183

11841184
switch (sp->hdr.type) {
11851185
case RXRPC_PACKET_TYPE_VERSION:
1186+
if (!(sp->hdr.flags & RXRPC_CLIENT_INITIATED))
1187+
goto discard;
11861188
rxrpc_post_packet_to_local(local, skb);
11871189
goto out;
11881190

net/rxrpc/net_ns.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,22 @@ static void rxrpc_service_conn_reap_timeout(struct timer_list *timer)
3232
rxrpc_queue_work(&rxnet->service_conn_reaper);
3333
}
3434

35+
static void rxrpc_peer_keepalive_timeout(struct timer_list *timer)
36+
{
37+
struct rxrpc_net *rxnet =
38+
container_of(timer, struct rxrpc_net, peer_keepalive_timer);
39+
40+
if (rxnet->live)
41+
rxrpc_queue_work(&rxnet->peer_keepalive_work);
42+
}
43+
3544
/*
3645
* Initialise a per-network namespace record.
3746
*/
3847
static __net_init int rxrpc_init_net(struct net *net)
3948
{
4049
struct rxrpc_net *rxnet = rxrpc_net(net);
41-
int ret;
50+
int ret, i;
4251

4352
rxnet->live = true;
4453
get_random_bytes(&rxnet->epoch, sizeof(rxnet->epoch));
@@ -70,8 +79,16 @@ static __net_init int rxrpc_init_net(struct net *net)
7079

7180
INIT_LIST_HEAD(&rxnet->local_endpoints);
7281
mutex_init(&rxnet->local_mutex);
82+
7383
hash_init(rxnet->peer_hash);
7484
spin_lock_init(&rxnet->peer_hash_lock);
85+
for (i = 0; i < ARRAY_SIZE(rxnet->peer_keepalive); i++)
86+
INIT_HLIST_HEAD(&rxnet->peer_keepalive[i]);
87+
INIT_HLIST_HEAD(&rxnet->peer_keepalive_new);
88+
timer_setup(&rxnet->peer_keepalive_timer,
89+
rxrpc_peer_keepalive_timeout, 0);
90+
INIT_WORK(&rxnet->peer_keepalive_work, rxrpc_peer_keepalive_worker);
91+
rxnet->peer_keepalive_base = ktime_add(ktime_get_real(), NSEC_PER_SEC);
7592

7693
ret = -ENOMEM;
7794
rxnet->proc_net = proc_net_mkdir(net, "rxrpc", net->proc_net);
@@ -95,6 +112,8 @@ static __net_exit void rxrpc_exit_net(struct net *net)
95112
struct rxrpc_net *rxnet = rxrpc_net(net);
96113

97114
rxnet->live = false;
115+
del_timer_sync(&rxnet->peer_keepalive_timer);
116+
cancel_work_sync(&rxnet->peer_keepalive_work);
98117
rxrpc_destroy_all_calls(rxnet);
99118
rxrpc_destroy_all_connections(rxnet);
100119
rxrpc_destroy_all_locals(rxnet);

net/rxrpc/output.c

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ struct rxrpc_abort_buffer {
3232
__be32 abort_code;
3333
};
3434

35+
static const char rxrpc_keepalive_string[] = "";
36+
3537
/*
3638
* Arrange for a keepalive ping a certain time after we last transmitted. This
3739
* 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,
122124
struct kvec iov[2];
123125
rxrpc_serial_t serial;
124126
rxrpc_seq_t hard_ack, top;
127+
ktime_t now;
125128
size_t len, n;
126129
int ret;
127130
u8 reason;
@@ -203,8 +206,10 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping,
203206
}
204207

205208
ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len);
209+
now = ktime_get_real();
206210
if (ping)
207-
call->ping_time = ktime_get_real();
211+
call->ping_time = now;
212+
conn->params.peer->last_tx_at = ktime_get_real();
208213

209214
if (call->state < RXRPC_CALL_COMPLETE) {
210215
if (ret < 0) {
@@ -288,6 +293,7 @@ int rxrpc_send_abort_packet(struct rxrpc_call *call)
288293

289294
ret = kernel_sendmsg(conn->params.local->socket,
290295
&msg, iov, 1, sizeof(pkt));
296+
conn->params.peer->last_tx_at = ktime_get_real();
291297

292298
rxrpc_put_connection(conn);
293299
return ret;
@@ -378,6 +384,7 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb,
378384
* message and update the peer record
379385
*/
380386
ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len);
387+
conn->params.peer->last_tx_at = ktime_get_real();
381388

382389
up_read(&conn->params.local->defrag_sem);
383390
if (ret == -EMSGSIZE)
@@ -429,6 +436,7 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb,
429436
if (ret == 0) {
430437
ret = kernel_sendmsg(conn->params.local->socket, &msg,
431438
iov, 2, len);
439+
conn->params.peer->last_tx_at = ktime_get_real();
432440

433441
opt = IP_PMTUDISC_DO;
434442
kernel_setsockopt(conn->params.local->socket, SOL_IP,
@@ -446,6 +454,7 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb,
446454
if (ret == 0) {
447455
ret = kernel_sendmsg(conn->params.local->socket, &msg,
448456
iov, 2, len);
457+
conn->params.peer->last_tx_at = ktime_get_real();
449458

450459
opt = IPV6_PMTUDISC_DO;
451460
kernel_setsockopt(conn->params.local->socket,
@@ -515,3 +524,51 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
515524

516525
_leave("");
517526
}
527+
528+
/*
529+
* Send a VERSION reply to a peer as a keepalive.
530+
*/
531+
void rxrpc_send_keepalive(struct rxrpc_peer *peer)
532+
{
533+
struct rxrpc_wire_header whdr;
534+
struct msghdr msg;
535+
struct kvec iov[2];
536+
size_t len;
537+
int ret;
538+
539+
_enter("");
540+
541+
msg.msg_name = &peer->srx.transport;
542+
msg.msg_namelen = peer->srx.transport_len;
543+
msg.msg_control = NULL;
544+
msg.msg_controllen = 0;
545+
msg.msg_flags = 0;
546+
547+
whdr.epoch = htonl(peer->local->rxnet->epoch);
548+
whdr.cid = 0;
549+
whdr.callNumber = 0;
550+
whdr.seq = 0;
551+
whdr.serial = 0;
552+
whdr.type = RXRPC_PACKET_TYPE_VERSION; /* Not client-initiated */
553+
whdr.flags = RXRPC_LAST_PACKET;
554+
whdr.userStatus = 0;
555+
whdr.securityIndex = 0;
556+
whdr._rsvd = 0;
557+
whdr.serviceId = 0;
558+
559+
iov[0].iov_base = &whdr;
560+
iov[0].iov_len = sizeof(whdr);
561+
iov[1].iov_base = (char *)rxrpc_keepalive_string;
562+
iov[1].iov_len = sizeof(rxrpc_keepalive_string);
563+
564+
len = iov[0].iov_len + iov[1].iov_len;
565+
566+
_proto("Tx VERSION (keepalive)");
567+
568+
ret = kernel_sendmsg(peer->local->socket, &msg, iov, 2, len);
569+
if (ret < 0)
570+
_debug("sendmsg failed: %d", ret);
571+
572+
peer->last_tx_at = ktime_get_real();
573+
_leave("");
574+
}

net/rxrpc/peer_event.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,3 +348,99 @@ void rxrpc_peer_add_rtt(struct rxrpc_call *call, enum rxrpc_rtt_rx_trace why,
348348
trace_rxrpc_rtt_rx(call, why, send_serial, resp_serial, rtt,
349349
usage, avg);
350350
}
351+
352+
/*
353+
* Perform keep-alive pings with VERSION packets to keep any NAT alive.
354+
*/
355+
void rxrpc_peer_keepalive_worker(struct work_struct *work)
356+
{
357+
struct rxrpc_net *rxnet =
358+
container_of(work, struct rxrpc_net, peer_keepalive_work);
359+
struct rxrpc_peer *peer;
360+
unsigned long delay;
361+
ktime_t base, now = ktime_get_real();
362+
s64 diff;
363+
u8 cursor, slot;
364+
365+
base = rxnet->peer_keepalive_base;
366+
cursor = rxnet->peer_keepalive_cursor;
367+
368+
_enter("%u,%lld", cursor, ktime_sub(now, base));
369+
370+
next_bucket:
371+
diff = ktime_to_ns(ktime_sub(now, base));
372+
if (diff < 0)
373+
goto resched;
374+
375+
_debug("at %u", cursor);
376+
spin_lock_bh(&rxnet->peer_hash_lock);
377+
next_peer:
378+
if (!rxnet->live) {
379+
spin_unlock_bh(&rxnet->peer_hash_lock);
380+
goto out;
381+
}
382+
383+
/* Everything in the bucket at the cursor is processed this second; the
384+
* bucket at cursor + 1 goes now + 1s and so on...
385+
*/
386+
if (hlist_empty(&rxnet->peer_keepalive[cursor])) {
387+
if (hlist_empty(&rxnet->peer_keepalive_new)) {
388+
spin_unlock_bh(&rxnet->peer_hash_lock);
389+
goto emptied_bucket;
390+
}
391+
392+
hlist_move_list(&rxnet->peer_keepalive_new,
393+
&rxnet->peer_keepalive[cursor]);
394+
}
395+
396+
peer = hlist_entry(rxnet->peer_keepalive[cursor].first,
397+
struct rxrpc_peer, keepalive_link);
398+
hlist_del_init(&peer->keepalive_link);
399+
if (!rxrpc_get_peer_maybe(peer))
400+
goto next_peer;
401+
402+
spin_unlock_bh(&rxnet->peer_hash_lock);
403+
404+
_debug("peer %u {%pISp}", peer->debug_id, &peer->srx.transport);
405+
406+
recalc:
407+
diff = ktime_divns(ktime_sub(peer->last_tx_at, base), NSEC_PER_SEC);
408+
if (diff < -30 || diff > 30)
409+
goto send; /* LSW of 64-bit time probably wrapped on 32-bit */
410+
diff += RXRPC_KEEPALIVE_TIME - 1;
411+
if (diff < 0)
412+
goto send;
413+
414+
slot = (diff > RXRPC_KEEPALIVE_TIME - 1) ? RXRPC_KEEPALIVE_TIME - 1 : diff;
415+
if (slot == 0)
416+
goto send;
417+
418+
/* A transmission to this peer occurred since last we examined it so
419+
* put it into the appropriate future bucket.
420+
*/
421+
slot = (slot + cursor) % ARRAY_SIZE(rxnet->peer_keepalive);
422+
spin_lock_bh(&rxnet->peer_hash_lock);
423+
hlist_add_head(&peer->keepalive_link, &rxnet->peer_keepalive[slot]);
424+
rxrpc_put_peer(peer);
425+
goto next_peer;
426+
427+
send:
428+
rxrpc_send_keepalive(peer);
429+
now = ktime_get_real();
430+
goto recalc;
431+
432+
emptied_bucket:
433+
cursor++;
434+
if (cursor >= ARRAY_SIZE(rxnet->peer_keepalive))
435+
cursor = 0;
436+
base = ktime_add_ns(base, NSEC_PER_SEC);
437+
goto next_bucket;
438+
439+
resched:
440+
rxnet->peer_keepalive_base = base;
441+
rxnet->peer_keepalive_cursor = cursor;
442+
delay = nsecs_to_jiffies(-diff) + 1;
443+
timer_reduce(&rxnet->peer_keepalive_timer, jiffies + delay);
444+
out:
445+
_leave("");
446+
}

net/rxrpc/peer_object.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ struct rxrpc_peer *rxrpc_lookup_incoming_peer(struct rxrpc_local *local,
322322
if (!peer) {
323323
peer = prealloc;
324324
hash_add_rcu(rxnet->peer_hash, &peer->hash_link, hash_key);
325+
hlist_add_head(&peer->keepalive_link, &rxnet->peer_keepalive_new);
325326
}
326327

327328
spin_unlock(&rxnet->peer_hash_lock);
@@ -363,9 +364,12 @@ struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_local *local,
363364
peer = __rxrpc_lookup_peer_rcu(local, srx, hash_key);
364365
if (peer && !rxrpc_get_peer_maybe(peer))
365366
peer = NULL;
366-
if (!peer)
367+
if (!peer) {
367368
hash_add_rcu(rxnet->peer_hash,
368369
&candidate->hash_link, hash_key);
370+
hlist_add_head(&candidate->keepalive_link,
371+
&rxnet->peer_keepalive_new);
372+
}
369373

370374
spin_unlock_bh(&rxnet->peer_hash_lock);
371375

@@ -392,6 +396,7 @@ void __rxrpc_put_peer(struct rxrpc_peer *peer)
392396

393397
spin_lock_bh(&rxnet->peer_hash_lock);
394398
hash_del_rcu(&peer->hash_link);
399+
hlist_del_init(&peer->keepalive_link);
395400
spin_unlock_bh(&rxnet->peer_hash_lock);
396401

397402
kfree_rcu(peer, rcu);

net/rxrpc/rxkad.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,7 @@ static int rxkad_issue_challenge(struct rxrpc_connection *conn)
668668
return -EAGAIN;
669669
}
670670

671+
conn->params.peer->last_tx_at = ktime_get_real();
671672
_leave(" = 0");
672673
return 0;
673674
}
@@ -722,6 +723,7 @@ static int rxkad_send_response(struct rxrpc_connection *conn,
722723
return -EAGAIN;
723724
}
724725

726+
conn->params.peer->last_tx_at = ktime_get_real();
725727
_leave(" = 0");
726728
return 0;
727729
}

0 commit comments

Comments
 (0)