diff --git a/sbin/ifconfig/ifwg.c b/sbin/ifconfig/ifwg.c index 8956e3427dd..9e22576ae02 100644 --- a/sbin/ifconfig/ifwg.c +++ b/sbin/ifconfig/ifwg.c @@ -133,6 +133,33 @@ parse_endpoint(const char *endpoint_) free(base); } +static void +parse_local_endpoint(const char *endpoint_) +{ + int err; + char *base, *endpoint *tmp; + struct addrinfo hints, *res; + + endpoint = base = strdup(endpoint_); + + /* [::] */ + if (endpoint[0] == '[') { + endpoint++; + tmp = index(endpoint, ']'); + if (tmp == NULL) + errx(1, "bad endpoint format %s - '[' found with no matching ']'", endpoint); + *tmp = '\0'; + } + bzero(&hints, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + err = getaddrinfo(endpoint, 0, &hints, &res); + if (err) + errx(1, "%s", gai_strerror(err)); + nvlist_add_binary(nvl_params, "localendpoint", res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + free(base); +} + static void in_len2mask(struct in_addr *mask, u_int len) { @@ -526,6 +553,14 @@ DECL_CMD_FUNC(setendpoint, val, d) parse_endpoint(val); } +static +DECL_CMD_FUNC(setlocalendpoint, val, d) +{ + if (!do_peer) + errx(1, "setting endpoint only valid when adding peer"); + parse_local_endpoint(val); +} + static void wireguard_status(int s) { @@ -567,6 +602,7 @@ static struct cmd wireguard_cmds[] = { DEF_CMD_ARG("public-key", setwgpubkey), DEF_CMD_ARG("allowed-ips", setallowedips), DEF_CMD_ARG("endpoint", setendpoint), + DEF_CMD_ARG("localendpoint", setlocalendpoint), }; static struct afswtch af_wireguard = { diff --git a/sys/dev/if_wg/module/module.c b/sys/dev/if_wg/module/module.c index 76c7db01cba..2d3c0ea345e 100644 --- a/sys/dev/if_wg/module/module.c +++ b/sys/dev/if_wg/module/module.c @@ -595,6 +595,16 @@ wg_peer_add(struct wg_softc *sc, const nvlist_t *nvl) memcpy(&peer->p_endpoint.e_remote, endpoint, sizeof(peer->p_endpoint.e_remote)); } + if (nvlist_exists_binary(nvl, "local_endpoint")) { + endpoint = nvlist_get_binary(nvl, "local_endpoint", &size); + if (size != sizeof(*endpoint)) { + device_printf(dev, "%s bad length for local endpoint %zu\n", __func__, size); + err = EBADMSG; + goto out; + } + memcpy(&peer->p_endpoint.e_local, endpoint, + sizeof(peer->p_endpoint.e_local)); + } if (nvlist_exists_binary(nvl, "pre-shared-key")) { const void *key;