aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/send.c
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2016-10-19 15:46:28 +0900
committerJason A. Donenfeld <Jason@zx2c4.com>2016-10-19 17:22:13 +0900
commit09847c27d4b9af8ce296215ed270ebfb4d08b23c (patch)
tree3465992e6488c7b685a166e08387ddebeb53604d /src/send.c
parenttimers: always delay handshakes for responder (diff)
downloadwireguard-monolithic-historical-09847c27d4b9af8ce296215ed270ebfb4d08b23c.tar.xz
wireguard-monolithic-historical-09847c27d4b9af8ce296215ed270ebfb4d08b23c.zip
timers: only have initiator rekey
If it's time to rekey, and the responder sends a message, the initator will begin the rekeying when sending his response message. In the worst case, this response message will actually just be the keepalive. This generally works well, with the one edge case of the message arriving less than 10 seconds before key expiration, in which the keepalive is not sufficient. In this case, we simply rehandshake immediately.
Diffstat (limited to 'src/send.c')
-rw-r--r--src/send.c42
1 files changed, 15 insertions, 27 deletions
diff --git a/src/send.c b/src/send.c
index 90d5d14..a7d505d 100644
--- a/src/send.c
+++ b/src/send.c
@@ -31,6 +31,12 @@ void packet_send_handshake_initiation(struct wireguard_peer *peer)
}
}
+void packet_send_handshake_initiation_ratelimited(struct wireguard_peer *peer)
+{
+ if (time_is_before_jiffies64(peer->last_sent_handshake + REKEY_TIMEOUT))
+ packet_queue_send_handshake_initiation(peer);
+}
+
void packet_send_handshake_response(struct wireguard_peer *peer)
{
struct message_handshake_response packet;
@@ -68,12 +74,6 @@ void packet_queue_send_handshake_initiation(struct wireguard_peer *peer)
peer_put(peer); /* If the work was already queued, we want to drop the extra reference */
}
-static inline void ratelimit_packet_send_handshake_initiation(struct wireguard_peer *peer)
-{
- if (time_is_before_jiffies64(peer->last_sent_handshake + REKEY_TIMEOUT))
- packet_queue_send_handshake_initiation(peer);
-}
-
void packet_send_handshake_cookie(struct wireguard_device *wg, struct sk_buff *initiating_skb, void *data, size_t data_len, __le32 sender_index)
{
struct message_handshake_cookie packet;
@@ -90,30 +90,18 @@ void packet_send_handshake_cookie(struct wireguard_device *wg, struct sk_buff *i
static inline void keep_key_fresh(struct wireguard_peer *peer)
{
struct noise_keypair *keypair;
+ bool send = false;
rcu_read_lock();
keypair = rcu_dereference(peer->keypairs.current_keypair);
- if (unlikely(!keypair || !keypair->sending.is_valid)) {
- rcu_read_unlock();
- return;
- }
+ if (likely(keypair && keypair->sending.is_valid) &&
+ (unlikely(atomic64_read(&keypair->sending.counter.counter) > REKEY_AFTER_MESSAGES) ||
+ (keypair->i_am_the_initiator && unlikely(time_is_before_eq_jiffies64(keypair->sending.birthdate + REKEY_AFTER_TIME)))))
+ send = true;
+ rcu_read_unlock();
- if (atomic64_read(&keypair->sending.counter.counter) > REKEY_AFTER_MESSAGES ||
- time_is_before_eq_jiffies64(keypair->sending.birthdate + REKEY_AFTER_TIME)) {
- rcu_read_unlock();
- /* The initiator can try it immediately, but the responder has to wait a bit,
- * to prevent the thundering herd effect. */
- if (keypair->i_am_the_initiator)
- ratelimit_packet_send_handshake_initiation(peer);
- else {
- /* If it's going to be dead soon, we rekey early. */
- if (time_is_before_eq_jiffies64(keypair->sending.birthdate + REJECT_AFTER_TIME - KEEPALIVE_TIMEOUT - REKEY_TIMEOUT))
- timers_delay_handshake(peer, REKEY_TIMEOUT / 2);
- else /* Otherwise rekey at the usual staggered delay. */
- timers_delay_handshake(peer, REKEY_TIMEOUT / 2 + REKEY_TIMEOUT * 2);
- }
- } else
- rcu_read_unlock();
+ if (send)
+ packet_send_handshake_initiation_ratelimited(peer);
}
void packet_send_keepalive(struct wireguard_peer *peer)
@@ -233,7 +221,7 @@ int packet_send_queue(struct wireguard_peer *peer)
case -ENOKEY:
/* ENOKEY means that we don't have a valid session for the peer, which
* means we should initiate a session, and then requeue everything. */
- ratelimit_packet_send_handshake_initiation(peer);
+ packet_send_handshake_initiation_ratelimited(peer);
goto requeue;
case -EBUSY:
/* EBUSY happens when the parallel workers are all filled up, in which