1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/*
3 * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
4 */
5
6#include <arpa/inet.h>
7#include <netinet/in.h>
8#include <sys/socket.h>
9#include <net/if.h>
10#include <stddef.h>
11#include <stdio.h>
12#include <string.h>
13#include <stdlib.h>
14#include <netdb.h>
15
16#include "containers.h"
17#include "encoding.h"
18#include "ipc.h"
19#include "subcommands.h"
20
21int showconf_main(int argc, const char *argv[])
22{
23	char base64[WG_KEY_LEN_BASE64];
24	char ip[INET6_ADDRSTRLEN];
25	struct wgdevice *device = NULL;
26	struct wgpeer *peer;
27	struct wgallowedip *allowedip;
28	int ret = 1;
29
30	if (argc != 2) {
31		fprintf(stderr, "Usage: %s %s <interface>\n", PROG_NAME, argv[0]);
32		return 1;
33	}
34
35	if (ipc_get_device(&device, argv[1])) {
36		perror("Unable to access interface");
37		goto cleanup;
38	}
39
40	printf("[Interface]\n");
41	if (device->listen_port)
42		printf("ListenPort = %u\n", device->listen_port);
43	if (device->fwmark)
44		printf("FwMark = 0x%x\n", device->fwmark);
45	if (device->flags & WGDEVICE_HAS_PRIVATE_KEY) {
46		key_to_base64(base64, device->private_key);
47		printf("PrivateKey = %s\n", base64);
48	}
49	printf("\n");
50	for_each_wgpeer(device, peer) {
51		key_to_base64(base64, peer->public_key);
52		printf("[Peer]\nPublicKey = %s\n", base64);
53		if (peer->flags & WGPEER_HAS_PRESHARED_KEY) {
54			key_to_base64(base64, peer->preshared_key);
55			printf("PresharedKey = %s\n", base64);
56		}
57		if (peer->first_allowedip)
58			printf("AllowedIPs = ");
59		for_each_wgallowedip(peer, allowedip) {
60			if (allowedip->family == AF_INET) {
61				if (!inet_ntop(AF_INET, &allowedip->ip4, ip, INET6_ADDRSTRLEN))
62					continue;
63			} else if (allowedip->family == AF_INET6) {
64				if (!inet_ntop(AF_INET6, &allowedip->ip6, ip, INET6_ADDRSTRLEN))
65					continue;
66			} else
67				continue;
68			printf("%s/%d", ip, allowedip->cidr);
69			if (allowedip->next_allowedip)
70				printf(", ");
71		}
72		if (peer->first_allowedip)
73			printf("\n");
74
75		if (peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6) {
76			char host[4096 + 1];
77			char service[512 + 1];
78			socklen_t addr_len = 0;
79
80			if (peer->endpoint.addr.sa_family == AF_INET)
81				addr_len = sizeof(struct sockaddr_in);
82			else if (peer->endpoint.addr.sa_family == AF_INET6)
83				addr_len = sizeof(struct sockaddr_in6);
84			if (!getnameinfo(&peer->endpoint.addr, addr_len, host, sizeof(host), service, sizeof(service), NI_DGRAM | NI_NUMERICSERV | NI_NUMERICHOST)) {
85				if (peer->endpoint.addr.sa_family == AF_INET6 && strchr(host, ':'))
86					printf("Endpoint = [%s]:%s\n", host, service);
87				else
88					printf("Endpoint = %s:%s\n", host, service);
89			}
90		}
91
92		if (peer->persistent_keepalive_interval)
93			printf("PersistentKeepalive = %u\n", peer->persistent_keepalive_interval);
94
95		if (peer->next_peer)
96			printf("\n");
97	}
98	ret = 0;
99
100cleanup:
101	free_wgdevice(device);
102	return ret;
103}
104