2015-06-05 13:58:00 +00:00
|
|
|
/* Copyright 2015-2016 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. */
|
|
|
|
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <net/if.h>
|
|
|
|
#include <resolv.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <netdb.h>
|
|
|
|
|
|
|
|
#include "subcommands.h"
|
|
|
|
#include "base64.h"
|
|
|
|
#include "kernel.h"
|
|
|
|
#include "../uapi.h"
|
|
|
|
|
|
|
|
int showconf_main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
static const uint8_t zero[WG_KEY_LEN] = { 0 };
|
|
|
|
char b64[b64_len(WG_KEY_LEN)] = { 0 };
|
|
|
|
char ip[INET6_ADDRSTRLEN];
|
|
|
|
struct wgdevice *device = NULL;
|
|
|
|
struct wgpeer *peer;
|
|
|
|
struct wgipmask *ipmask;
|
|
|
|
size_t i, j;
|
|
|
|
int ret = 1;
|
|
|
|
|
|
|
|
if (argc != 2) {
|
|
|
|
fprintf(stderr, "Usage: %s %s <interface>\n", PROG_NAME, argv[0]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
wg: first additions of userspace integration
This is designed to work with a server that follows this:
struct sockaddr_un addr = {
.sun_family = AF_UNIX,
.sun_path = "/var/run/wireguard/wguserspace0.sock"
};
int fd, ret;
ssize_t len;
socklen_t socklen;
struct wgdevice *device;
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd < 0)
exit(1);
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
exit(1);
for (;;) {
/* First we look at how big the next message is, so we know how much to
* allocate. Note on BSD you can instead use ioctl(fd, FIONREAD, &len). */
len = recv(fd, NULL, 0, MSG_PEEK | MSG_TRUNC);
if (len < 0) {
handle_error();
continue;
}
/* Next we allocate a buffer for the received data. */
device = NULL;
if (len) {
device = malloc(len);
if (!device) {
handle_error();
continue;
}
}
/* Finally we receive the data, storing too the return address. */
socklen = sizeof(addr);
len = recvfrom(fd, device, len, 0, (struct sockaddr *)&addr, (socklen_t *)&socklen);
if (len < 0) {
handle_error();
free(device);
continue;
}
if (!len) { /* If len is zero, it's a "get" request, so we send our device back. */
device = get_current_wireguard_device(&len);
sendto(fd, device, len, 0, (struct sockaddr *)&addr, socklen);
} else { /* Otherwise, we just received a wgdevice, so we should "set" and send back the return status. */
ret = set_current_wireguard_device(device);
sendto(fd, &ret, sizeof(ret), 0, (struct sockaddr *)&addr, socklen);
free(device);
}
}
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2016-07-19 13:26:56 +00:00
|
|
|
if (!has_wireguard_interface(argv[1])) {
|
2015-06-05 13:58:00 +00:00
|
|
|
fprintf(stderr, "`%s` is not a valid WireGuard interface\n", argv[1]);
|
|
|
|
fprintf(stderr, "Usage: %s %s <interface>\n", PROG_NAME, argv[0]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
wg: first additions of userspace integration
This is designed to work with a server that follows this:
struct sockaddr_un addr = {
.sun_family = AF_UNIX,
.sun_path = "/var/run/wireguard/wguserspace0.sock"
};
int fd, ret;
ssize_t len;
socklen_t socklen;
struct wgdevice *device;
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd < 0)
exit(1);
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
exit(1);
for (;;) {
/* First we look at how big the next message is, so we know how much to
* allocate. Note on BSD you can instead use ioctl(fd, FIONREAD, &len). */
len = recv(fd, NULL, 0, MSG_PEEK | MSG_TRUNC);
if (len < 0) {
handle_error();
continue;
}
/* Next we allocate a buffer for the received data. */
device = NULL;
if (len) {
device = malloc(len);
if (!device) {
handle_error();
continue;
}
}
/* Finally we receive the data, storing too the return address. */
socklen = sizeof(addr);
len = recvfrom(fd, device, len, 0, (struct sockaddr *)&addr, (socklen_t *)&socklen);
if (len < 0) {
handle_error();
free(device);
continue;
}
if (!len) { /* If len is zero, it's a "get" request, so we send our device back. */
device = get_current_wireguard_device(&len);
sendto(fd, device, len, 0, (struct sockaddr *)&addr, socklen);
} else { /* Otherwise, we just received a wgdevice, so we should "set" and send back the return status. */
ret = set_current_wireguard_device(device);
sendto(fd, &ret, sizeof(ret), 0, (struct sockaddr *)&addr, socklen);
free(device);
}
}
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2016-07-19 13:26:56 +00:00
|
|
|
if (get_device(&device, argv[1])) {
|
2015-06-05 13:58:00 +00:00
|
|
|
perror("Unable to get device");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("[Interface]\n");
|
|
|
|
if (device->port)
|
|
|
|
printf("ListenPort = %d\n", device->port);
|
|
|
|
if (memcmp(device->private_key, zero, WG_KEY_LEN)) {
|
|
|
|
b64_ntop(device->private_key, WG_KEY_LEN, b64, b64_len(WG_KEY_LEN));
|
|
|
|
printf("PrivateKey = %s\n", b64);
|
|
|
|
}
|
|
|
|
if (memcmp(device->preshared_key, zero, WG_KEY_LEN)) {
|
|
|
|
b64_ntop(device->preshared_key, WG_KEY_LEN, b64, b64_len(WG_KEY_LEN));
|
|
|
|
printf("PresharedKey = %s\n", b64);
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
for_each_wgpeer(device, peer, i) {
|
|
|
|
b64_ntop(peer->public_key, WG_KEY_LEN, b64, b64_len(WG_KEY_LEN));
|
|
|
|
printf("[Peer]\nPublicKey = %s\n", b64);
|
|
|
|
if (peer->num_ipmasks)
|
|
|
|
printf("AllowedIPs = ");
|
|
|
|
for_each_wgipmask(peer, ipmask, j) {
|
|
|
|
if (ipmask->family == AF_INET) {
|
|
|
|
if (!inet_ntop(AF_INET, &ipmask->ip4, ip, INET6_ADDRSTRLEN))
|
|
|
|
continue;
|
|
|
|
} else if (ipmask->family == AF_INET6) {
|
|
|
|
if (!inet_ntop(AF_INET6, &ipmask->ip6, ip, INET6_ADDRSTRLEN))
|
|
|
|
continue;
|
|
|
|
} else
|
|
|
|
continue;
|
|
|
|
printf("%s/%d", ip, ipmask->cidr);
|
|
|
|
if (j + 1 < (size_t)peer->num_ipmasks)
|
|
|
|
printf(", ");
|
|
|
|
}
|
|
|
|
if (peer->num_ipmasks)
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
if (peer->endpoint.ss_family == AF_INET || peer->endpoint.ss_family == AF_INET6) {
|
|
|
|
char host[4096 + 1];
|
|
|
|
char service[512 + 1];
|
|
|
|
static char buf[sizeof(host) + sizeof(service) + 4];
|
|
|
|
socklen_t addr_len = 0;
|
|
|
|
memset(buf, 0, sizeof(buf));
|
|
|
|
if (peer->endpoint.ss_family == AF_INET)
|
|
|
|
addr_len = sizeof(struct sockaddr_in);
|
|
|
|
else if (peer->endpoint.ss_family == AF_INET6)
|
|
|
|
addr_len = sizeof(struct sockaddr_in6);
|
|
|
|
if (!getnameinfo((struct sockaddr *)&peer->endpoint, addr_len, host, sizeof(host), service, sizeof(service), NI_DGRAM | NI_NUMERICSERV | NI_NUMERICHOST)) {
|
|
|
|
snprintf(buf, sizeof(buf) - 1, (peer->endpoint.ss_family == AF_INET6 && strchr(host, ':')) ? "[%s]:%s" : "%s:%s", host, service);
|
|
|
|
printf("Endpoint = %s\n", buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-08 00:30:03 +00:00
|
|
|
if (peer->persistent_keepalive_interval)
|
|
|
|
printf("PersistentKeepalive = %u\n", peer->persistent_keepalive_interval);
|
|
|
|
|
2015-06-05 13:58:00 +00:00
|
|
|
if (i + 1 < device->num_peers)
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
free(device);
|
|
|
|
return ret;
|
|
|
|
}
|