summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2017-01-24 05:59:17 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2017-02-13 21:55:17 +0100
commitc595161b6836d8e508d0047d4c5f823027833a68 (patch)
treec26477019861657722bd652ced6ad638dbffea34
parenttools: wg-quick: support v6 dual stack (diff)
downloadwireguard-monolithic-historical-c595161b6836d8e508d0047d4c5f823027833a68.tar.xz
wireguard-monolithic-historical-c595161b6836d8e508d0047d4c5f823027833a68.zip
socket: general ephemeral ports instead of name-based ports
-rw-r--r--src/socket.c69
-rw-r--r--src/tools/wg.86
2 files changed, 19 insertions, 56 deletions
diff --git a/src/socket.c b/src/socket.c
index 858967c..e26504d 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -280,45 +280,6 @@ err:
return 0;
}
-/* Generates a default port from the interface name.
- * wg0 --> 51820
- * wg1 --> 51821
- * wg2 --> 51822
- * wg100 --> 51920
- * wg60000 --> 46285
- * blahbla --> 51820
- * 50 --> 51870
- */
-static u16 generate_default_incoming_port(struct wireguard_device *wg)
-{
- u16 port = 51820;
- unsigned long parsed;
- char *name, *digit_begin;
- size_t len;
-
- ASSERT_RTNL();
-
- name = netdev_pub(wg)->name;
- len = strlen(name);
- if (!len)
- return port;
- digit_begin = name + len - 1;
- while (digit_begin >= name) {
- if (isdigit(*digit_begin))
- --digit_begin;
- else
- break;
- }
- ++digit_begin;
- if (!*digit_begin)
- return port;
- if (!kstrtoul(digit_begin, 10, &parsed))
- port += parsed;
- if (!port)
- ++port;
- return port;
-}
-
static inline void sock_free(struct sock *sock)
{
if (unlikely(!sock))
@@ -337,27 +298,31 @@ static inline void set_sock_opts(struct socket *sock)
int socket_init(struct wireguard_device *wg)
{
int ret = 0;
+ struct udp_tunnel_sock_cfg cfg = {
+ .sk_user_data = wg,
+ .encap_type = 1,
+ .encap_rcv = receive
+ };
struct socket *new4 = NULL;
struct udp_port_cfg port4 = {
.family = AF_INET,
.local_ip.s_addr = htonl(INADDR_ANY),
+ .local_udp_port = htons(wg->incoming_port),
.use_udp_checksums = true
};
#if IS_ENABLED(CONFIG_IPV6)
+ int retries = 0;
struct socket *new6 = NULL;
struct udp_port_cfg port6 = {
.family = AF_INET6,
.local_ip6 = IN6ADDR_ANY_INIT,
+ .local_udp_port = htons(wg->incoming_port),
.use_udp6_tx_checksums = true,
.use_udp6_rx_checksums = true,
.ipv6_v6only = true
};
+retry:
#endif
- struct udp_tunnel_sock_cfg cfg = {
- .sk_user_data = wg,
- .encap_type = 1,
- .encap_rcv = receive
- };
mutex_lock(&wg->socket_update_lock);
@@ -367,30 +332,28 @@ int socket_init(struct wireguard_device *wg)
goto out;
}
- if (!wg->incoming_port)
- wg->incoming_port = generate_default_incoming_port(wg);
- port4.local_udp_port =
-#if IS_ENABLED(CONFIG_IPV6)
- port6.local_udp_port =
-#endif
- htons(wg->incoming_port);
-
ret = udp_sock_create(wg->creating_net, &port4, &new4);
if (ret < 0) {
pr_err("Could not create IPv4 socket\n");
goto out;
}
+ wg->incoming_port = ntohs(inet_sk(new4->sk)->inet_sport);
set_sock_opts(new4);
setup_udp_tunnel_sock(wg->creating_net, new4, &cfg);
rcu_assign_pointer(wg->sock4, new4->sk);
#if IS_ENABLED(CONFIG_IPV6)
+ port6.local_udp_port = htons(wg->incoming_port);
ret = udp_sock_create(wg->creating_net, &port6, &new6);
if (ret < 0) {
- pr_err("Could not create IPv6 socket\n");
udp_tunnel_sock_release(new4);
rcu_assign_pointer(wg->sock4, NULL);
+ if (ret == -EADDRINUSE && !port4.local_udp_port && retries++ < 100)
+ goto retry;
+ if (!port4.local_udp_port)
+ wg->incoming_port = 0;
+ pr_err("Could not create IPv6 socket\n");
goto out;
}
set_sock_opts(new6);
diff --git a/src/tools/wg.8 b/src/tools/wg.8
index 2ec005c..be05acf 100644
--- a/src/tools/wg.8
+++ b/src/tools/wg.8
@@ -53,7 +53,7 @@ by \fICONFIGURATION FILE FORMAT\fP below.
Sets configuration values for the specified \fI<interface>\fP. Multiple
\fIpeer\fPs may be specified, and if the \fIremove\fP argument is given
for a peer, that peer is removed, not configured. If \fIlisten-port\fP
-is not specified, the port will be automatically generated when the
+is not specified, the port will be chosen randomly when the
interface comes up. Both \fIprivate-key\fP and \fIpreshared-key\fP must
be a files, because command line arguments are not considered private on
most systems but if you are using
@@ -123,8 +123,8 @@ and may be omitted. This option adds an additional layer of symmetric-key
cryptography to be mixed into the already existing public-key cryptography,
for post-quantum resistance.
.IP \(bu
-ListenPort \(em a 16-bit port for listening. Optional; if not specified,
-automatically generated based on interface name.
+ListenPort \(em a 16-bit port for listening. Optional; if not specified, chosen
+randomly.
.P
The \fIPeer\fP sections may contain the following fields:
.IP \(bu