summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Wagner <wagi@monom.org>2020-10-09 09:28:00 +0200
committerNishant Chaprana <n.chaprana@samsung.com>2021-07-13 11:50:29 +0530
commit9c394d387dc4dc546972dcae50a227dc6a9989ae (patch)
treebe03bf4b27f8be97f7d6bded9b944faff639b495
parentcce6ed197cf6503e5ff068c2a25ad8f435b12068 (diff)
downloadconnman-9c394d387dc4dc546972dcae50a227dc6a9989ae.tar.gz
connman-9c394d387dc4dc546972dcae50a227dc6a9989ae.tar.bz2
connman-9c394d387dc4dc546972dcae50a227dc6a9989ae.zip
wireguard: Fix struct sockaddr usage
wg_dns_reresolve_cb() tries to read 16 bytes from the addr variable in case of IPv6 but struct sockaddr has size of 8 bytes. Introduce a helper struct containing IPv4 and IPv6 sockaddr as superset of all IP based sockaddr. This helper struct is identically to the 'union endpoint' in wireguard.h. But we don't want to touch this header file as it is 100% copy from the upstream WireGuard project. Fixes: 90592f7a5835 ("wireguard: Regular reresolve endpoint address") Change-Id: I2b262e61e52c795ab0cab4b206bd25df8ae57738 Signed-off-by: Nishant Chaprana <n.chaprana@samsung.com>
-rw-r--r--vpn/plugins/wireguard.c47
1 files changed, 25 insertions, 22 deletions
diff --git a/vpn/plugins/wireguard.c b/vpn/plugins/wireguard.c
index 536adbf1..7541dd6e 100644
--- a/vpn/plugins/wireguard.c
+++ b/vpn/plugins/wireguard.c
@@ -59,6 +59,14 @@ struct wireguard_info {
int reresolve_id;
};
+struct sockaddr_u {
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ };
+};
+
static int parse_key(const char *str, wg_key key)
{
unsigned char *buf;
@@ -126,7 +134,7 @@ static int parse_allowed_ips(const char *allowed_ips, wg_peer *peer)
return 0;
}
-static int parse_endpoint(const char *host, const char *port, struct sockaddr *addr)
+static int parse_endpoint(const char *host, const char *port, struct sockaddr_u *addr)
{
struct addrinfo hints;
struct addrinfo *result, *rp;
@@ -246,24 +254,17 @@ static char *get_ifname(void)
return NULL;
}
-static bool sockaddr_cmp_addr(struct sockaddr *a, struct sockaddr *b)
+static bool sockaddr_cmp_addr(struct sockaddr_u *a, struct sockaddr_u *b)
{
- if (a->sa_family != b->sa_family)
+ if (a->sa.sa_family != b->sa.sa_family)
return false;
- if (a->sa_family == AF_INET) {
- struct sockaddr_in *a4 = (struct sockaddr_in *)a;
- struct sockaddr_in *b4 = (struct sockaddr_in *)b;
-
- return !memcmp(a4, b4, sizeof(struct sockaddr_in));
- } else if (a->sa_family == AF_INET6) {
- struct sockaddr_in6 *a6 = (struct sockaddr_in6 *)a;
- struct sockaddr_in6 *b6 = (struct sockaddr_in6 *)b;
-
- return !memcmp(a6->sin6_addr.s6_addr,
- b6->sin6_addr.s6_addr,
- sizeof(a6->sin6_addr.s6_addr));
- }
+ if (a->sa.sa_family == AF_INET)
+ return !memcmp(&a->sin, &b->sin, sizeof(struct sockaddr_in));
+ else if (a->sa.sa_family == AF_INET6)
+ return !memcmp(a->sin6.sin6_addr.s6_addr,
+ b->sin6.sin6_addr.s6_addr,
+ sizeof(a->sin6.sin6_addr.s6_addr));
return false;
}
@@ -271,8 +272,8 @@ static bool sockaddr_cmp_addr(struct sockaddr *a, struct sockaddr *b)
static gboolean wg_dns_reresolve_cb(gpointer user_data)
{
struct wireguard_info *info = user_data;
+ struct sockaddr_u addr;
int err;
- struct sockaddr addr;
DBG("");
@@ -281,14 +282,15 @@ static gboolean wg_dns_reresolve_cb(gpointer user_data)
if (err)
return TRUE;
- if (sockaddr_cmp_addr(&addr, &info->peer.endpoint.addr))
+ if (sockaddr_cmp_addr(&addr,
+ (struct sockaddr_u *)&info->peer.endpoint.addr))
return TRUE;
- if (addr.sa_family == AF_INET)
- memcpy(&info->peer.endpoint.addr, &addr,
+ if (addr.sa.sa_family == AF_INET)
+ memcpy(&info->peer.endpoint.addr, &addr.sin,
sizeof(info->peer.endpoint.addr4));
else
- memcpy(&info->peer.endpoint.addr, &addr,
+ memcpy(&info->peer.endpoint.addr, &addr.sin6,
sizeof(info->peer.endpoint.addr6));
DBG("Endpoint address has changed, udpate WireGuard device");
@@ -382,7 +384,8 @@ static int wg_connect(struct vpn_provider *provider,
option = "51820";
gateway = vpn_provider_get_string(provider, "Host");
- err = parse_endpoint(gateway, option, &info->peer.endpoint.addr);
+ err = parse_endpoint(gateway, option,
+ (struct sockaddr_u *)&info->peer.endpoint.addr);
if (err)
goto done;