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