From c870c7af53f44a37814dfc76ceb8ad88e290fcd8 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 22 Jan 2019 13:38:52 +0100 Subject: netlink: use __kernel_timespec for handshake time --- contrib/examples/embeddable-wg-library/wireguard.h | 8 +++++++- src/compat/compat.h | 16 +++++++++++++++- src/netlink.c | 10 +++++++--- src/peer.h | 2 +- src/tests/netns.sh | 4 +++- src/timers.c | 2 +- src/tools/containers.h | 8 +++++++- src/tools/ipc.c | 4 ++-- src/tools/show.c | 2 +- src/uapi/wireguard.h | 2 +- 10 files changed, 45 insertions(+), 13 deletions(-) diff --git a/contrib/examples/embeddable-wg-library/wireguard.h b/contrib/examples/embeddable-wg-library/wireguard.h index 9ebe47c..e7a1bbf 100644 --- a/contrib/examples/embeddable-wg-library/wireguard.h +++ b/contrib/examples/embeddable-wg-library/wireguard.h @@ -16,6 +16,12 @@ typedef uint8_t wg_key[32]; typedef char wg_key_b64_string[((sizeof(wg_key) + 2) / 3) * 4 + 1]; +/* Cross platform __kernel_timespec */ +struct timespec64 { + int64_t tv_sec; + int64_t tv_nsec; +}; + typedef struct wg_allowedip { uint16_t family; union { @@ -46,7 +52,7 @@ typedef struct wg_peer { struct sockaddr_in6 addr6; } endpoint; - struct timespec last_handshake_time; + struct timespec64 last_handshake_time; uint64_t rx_bytes, tx_bytes; uint16_t persistent_keepalive_interval; diff --git a/src/compat/compat.h b/src/compat/compat.h index 15cf8bb..19dd71a 100644 --- a/src/compat/compat.h +++ b/src/compat/compat.h @@ -748,10 +748,24 @@ static inline void crypto_xor_cpy(u8 *dst, const u8 *src1, const u8 *src2, #define hlist_add_behind(a, b) hlist_add_after(b, a) #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 21, 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0) #define totalram_pages() totalram_pages #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0) +struct __kernel_timespec { + int64_t tv_sec, tv_nsec; +}; +#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0) +#include +#ifdef __kernel_timespec +#undef __kernel_timespec +struct __kernel_timespec { + int64_t tv_sec, tv_nsec; +}; +#endif +#endif + /* https://github.com/ClangBuiltLinux/linux/issues/7 */ #if defined( __clang__) && (!defined(CONFIG_CLANG_VERSION) || CONFIG_CLANG_VERSION < 80000) #include diff --git a/src/netlink.c b/src/netlink.c index bdd3150..3458c81 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -33,7 +33,7 @@ static const struct nla_policy peer_policy[WGPEER_A_MAX + 1] = { [WGPEER_A_FLAGS] = { .type = NLA_U32 }, [WGPEER_A_ENDPOINT] = { .len = sizeof(struct sockaddr) }, [WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = { .type = NLA_U16 }, - [WGPEER_A_LAST_HANDSHAKE_TIME] = { .len = sizeof(struct timespec) }, + [WGPEER_A_LAST_HANDSHAKE_TIME] = { .len = sizeof(struct __kernel_timespec) }, [WGPEER_A_RX_BYTES] = { .type = NLA_U64 }, [WGPEER_A_TX_BYTES] = { .type = NLA_U64 }, [WGPEER_A_ALLOWEDIPS] = { .type = NLA_NESTED }, @@ -107,6 +107,11 @@ static int get_peer(struct wg_peer *peer, struct allowedips_cursor *rt_cursor, goto err; if (!rt_cursor->seq) { + const struct __kernel_timespec last_handshake = { + .tv_sec = peer->walltime_last_handshake.tv_sec, + .tv_nsec = peer->walltime_last_handshake.tv_nsec + }; + down_read(&peer->handshake.lock); fail = nla_put(skb, WGPEER_A_PRESHARED_KEY, NOISE_SYMMETRIC_KEY_LEN, @@ -116,8 +121,7 @@ static int get_peer(struct wg_peer *peer, struct allowedips_cursor *rt_cursor, goto err; if (nla_put(skb, WGPEER_A_LAST_HANDSHAKE_TIME, - sizeof(peer->walltime_last_handshake), - &peer->walltime_last_handshake) || + sizeof(last_handshake), &last_handshake) || nla_put_u16(skb, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, peer->persistent_keepalive_interval) || nla_put_u64_64bit(skb, WGPEER_A_TX_BYTES, peer->tx_bytes, diff --git a/src/peer.h b/src/peer.h index f3cf255..2e04262 100644 --- a/src/peer.h +++ b/src/peer.h @@ -56,7 +56,7 @@ struct wg_peer { u16 persistent_keepalive_interval; bool timer_need_another_keepalive; bool sent_lastminute_handshake; - struct timespec walltime_last_handshake; + struct timespec64 walltime_last_handshake; struct kref refcount; struct rcu_head rcu; struct list_head peer_list; diff --git a/src/tests/netns.sh b/src/tests/netns.sh index 6ef61a5..46c30e5 100755 --- a/src/tests/netns.sh +++ b/src/tests/netns.sh @@ -142,7 +142,7 @@ big_mtu=$(( 34816 - 1500 + $orig_mtu )) # Test using IPv4 as outer transport n1 wg set wg0 peer "$pub2" endpoint 127.0.0.1:2 n2 wg set wg0 peer "$pub1" endpoint 127.0.0.1:1 -# Before calling tests, we first make sure that the stats counters are working +# Before calling tests, we first make sure that the stats counters and timestamper are working n2 ping -c 10 -f -W 1 192.168.241.1 { read _; read _; read _; read rx_bytes _; read _; read tx_bytes _; } < <(ip2 -stats link show dev wg0) (( rx_bytes == 1372 && (tx_bytes == 1428 || tx_bytes == 1460) )) @@ -152,6 +152,8 @@ read _ rx_bytes tx_bytes < <(n2 wg show wg0 transfer) (( rx_bytes == 1372 && (tx_bytes == 1428 || tx_bytes == 1460) )) read _ rx_bytes tx_bytes < <(n1 wg show wg0 transfer) (( tx_bytes == 1372 && (rx_bytes == 1428 || rx_bytes == 1460) )) +read _ timestamp < <(n1 wg show wg0 latest-handshakes) +(( timestamp != 0 )) tests ip1 link set wg0 mtu $big_mtu diff --git a/src/timers.c b/src/timers.c index ee16c56..7614c85 100644 --- a/src/timers.c +++ b/src/timers.c @@ -192,7 +192,7 @@ void wg_timers_handshake_complete(struct wg_peer *peer) del_timer(&peer->timer_retransmit_handshake); peer->timer_handshake_attempts = 0; peer->sent_lastminute_handshake = false; - getnstimeofday(&peer->walltime_last_handshake); + ktime_get_real_ts64(&peer->walltime_last_handshake); } /* Should be called after an ephemeral key is created, which is before sending a diff --git a/src/tools/containers.h b/src/tools/containers.h index 2144052..59a213e 100644 --- a/src/tools/containers.h +++ b/src/tools/containers.h @@ -15,6 +15,12 @@ #include "../uapi/wireguard.h" +/* Cross platform __kernel_timespec */ +struct timespec64 { + int64_t tv_sec; + int64_t tv_nsec; +}; + struct wgallowedip { uint16_t family; union { @@ -45,7 +51,7 @@ struct wgpeer { struct sockaddr_in6 addr6; } endpoint; - struct timespec last_handshake_time; + struct timespec64 last_handshake_time; uint64_t rx_bytes, tx_bytes; uint16_t persistent_keepalive_interval; diff --git a/src/tools/ipc.c b/src/tools/ipc.c index da31eff..7ab3a62 100644 --- a/src/tools/ipc.c +++ b/src/tools/ipc.c @@ -420,9 +420,9 @@ static int userspace_get_device(struct wgdevice **out, const char *interface) if (*end || allowedip->family == AF_UNSPEC || (allowedip->family == AF_INET6 && allowedip->cidr > 128) || (allowedip->family == AF_INET && allowedip->cidr > 32)) break; } else if (peer && !strcmp(key, "last_handshake_time_sec")) - peer->last_handshake_time.tv_sec = NUM(0xffffffffffffffffULL); + peer->last_handshake_time.tv_sec = NUM(0x7fffffffffffffffULL); else if (peer && !strcmp(key, "last_handshake_time_nsec")) - peer->last_handshake_time.tv_nsec = NUM(0xffffffffffffffffULL); + peer->last_handshake_time.tv_nsec = NUM(0x7fffffffffffffffULL); else if (peer && !strcmp(key, "rx_bytes")) peer->rx_bytes = NUM(0xffffffffffffffffULL); else if (peer && !strcmp(key, "tx_bytes")) diff --git a/src/tools/show.c b/src/tools/show.c index ba6f115..4cc34ab 100644 --- a/src/tools/show.c +++ b/src/tools/show.c @@ -155,7 +155,7 @@ static size_t pretty_time(char *buf, const size_t len, unsigned long long left) return offset; } -static char *ago(const struct timespec *t) +static char *ago(const struct timespec64 *t) { static char buf[1024]; size_t offset; diff --git a/src/uapi/wireguard.h b/src/uapi/wireguard.h index 3db6ff8..071ce41 100644 --- a/src/uapi/wireguard.h +++ b/src/uapi/wireguard.h @@ -35,7 +35,7 @@ * WGPEER_A_PRESHARED_KEY: len WG_KEY_LEN * WGPEER_A_ENDPOINT: struct sockaddr_in or struct sockaddr_in6 * WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL: NLA_U16 - * WGPEER_A_LAST_HANDSHAKE_TIME: struct timespec + * WGPEER_A_LAST_HANDSHAKE_TIME: struct __kernel_timespec * WGPEER_A_RX_BYTES: NLA_U64 * WGPEER_A_TX_BYTES: NLA_U64 * WGPEER_A_ALLOWEDIPS: NLA_NESTED -- cgit v1.2.3-59-g8ed1b