File Coverage

WireGuard.xs
Criterion Covered Total %
statement 19 79 24.0
branch 10 42 23.8
condition n/a
subroutine n/a
pod n/a
total 29 121 23.9


line stmt bran cond sub pod time code
1             #include "easyxs/easyxs.h"
2              
3             #include "wireguard.h"
4              
5             #define PERL_NS "Linux::WireGuard"
6              
7             #define IPV4_STRLEN sizeof( ((struct sockaddr_in*) NULL)->sin_addr.s_addr)
8             #define IPV6_STRLEN sizeof( ((struct sockaddr_in6*) NULL)->sin6_addr)
9              
10 0           static HV* _wgallowedip_to_hv (pTHX_ wg_allowedip* allowedip) {
11 0           HV* ip_hv = newHV();
12              
13 0           hv_stores(ip_hv, "family", newSVuv(allowedip->family));
14              
15 0           SV* addr_sv = NULL;
16              
17 0           switch (allowedip->family) {
18             case AF_INET:
19 0           addr_sv = newSVpvn((char*) &allowedip->ip4.s_addr, IPV4_STRLEN);
20 0           break;
21             case AF_INET6:
22 0           addr_sv = newSVpvn((char*) &allowedip->ip6.s6_addr, IPV6_STRLEN);
23 0           break;
24             default:
25             assert(0);
26             }
27              
28 0           hv_stores(ip_hv, "addr", addr_sv);
29 0           hv_stores(ip_hv, "cidr", newSVuv(allowedip->cidr));
30              
31 0           return ip_hv;
32             }
33              
34 0           static HV* _wgpeer_to_hv (pTHX_ wg_peer *peer) {
35             wg_allowedip* allowedip;
36              
37 0           HV* hv = newHV();
38              
39             // hv_stores(hv, "flags", newSViv(peer->flags));
40              
41 0 0         hv_stores(hv, "public_key", (peer->flags & WGPEER_HAS_PUBLIC_KEY) ? newSVpvn((char*) peer->public_key, sizeof(peer->public_key)) : &PL_sv_undef);
42 0 0         hv_stores(hv, "preshared_key", (peer->flags & WGPEER_HAS_PRESHARED_KEY) ? newSVpvn( (char*) peer->preshared_key, sizeof(peer->preshared_key)) : &PL_sv_undef);
43              
44 0           unsigned endpoint_len = 0;
45 0           switch (peer->endpoint.addr.sa_family) {
46             case 0:
47 0           break;
48             case AF_INET:
49 0           endpoint_len = sizeof(struct sockaddr_in);
50 0           break;
51             case AF_INET6:
52 0           endpoint_len = sizeof(struct sockaddr_in6);
53 0           break;
54             default:
55             assert(0);
56             }
57              
58 0 0         hv_stores(hv, "endpoint", endpoint_len ? newSVpvn((char*) &peer->endpoint, endpoint_len) : &PL_sv_undef);
59              
60 0           hv_stores(hv, "rx_bytes", newSVuv(peer->rx_bytes));
61 0           hv_stores(hv, "tx_bytes", newSVuv(peer->tx_bytes));
62 0 0         hv_stores(hv, "persistent_keepalive_interval", (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) ? newSVuv(peer->persistent_keepalive_interval) : &PL_sv_undef);
63              
64 0           hv_stores(hv, "last_handshake_time_sec", newSViv(peer->last_handshake_time.tv_sec));
65 0           hv_stores(hv, "last_handshake_time_nsec", newSViv(peer->last_handshake_time.tv_nsec));
66              
67 0           AV* allowed_ips = newAV();
68 0           hv_stores(hv, "allowed_ips", newRV_noinc((SV*) allowed_ips));
69              
70 0 0         wg_for_each_allowedip(peer, allowedip) {
71 0           HV* ip_hv = _wgallowedip_to_hv(aTHX_ allowedip);
72 0           av_push(allowed_ips, newRV_noinc((SV*)ip_hv));
73             }
74              
75 0           return hv;
76             }
77              
78 0           static HV* _wgdev_to_hv (pTHX_ wg_device *dev) {
79             wg_peer *peer;
80              
81 0           HV* dev_hv = newHV();
82              
83 0           hv_stores(dev_hv, "name", newSVpv(dev->name, 0));
84 0           hv_stores(dev_hv, "ifindex", newSVuv(dev->ifindex));
85              
86             // hv_stores(dev_hv, "flags", newSViv(dev->flags));
87              
88 0 0         hv_stores(dev_hv, "public_key", dev->flags & WGDEVICE_HAS_PUBLIC_KEY ? newSVpvn((char*) dev->public_key, sizeof(dev->public_key)) : &PL_sv_undef);
89 0 0         hv_stores(dev_hv, "private_key", dev->flags & WGDEVICE_HAS_PRIVATE_KEY ? newSVpvn((char*) dev->private_key, sizeof(dev->private_key)) : &PL_sv_undef);
90              
91 0 0         hv_stores(dev_hv, "fwmark", dev->flags & WGDEVICE_HAS_FWMARK ? newSVuv(dev->fwmark) : &PL_sv_undef);
92 0 0         hv_stores(dev_hv, "listen_port", dev->flags & WGDEVICE_HAS_LISTEN_PORT ? newSVuv(dev->listen_port) : &PL_sv_undef);
93              
94 0           AV* peers = newAV();
95 0           hv_stores(dev_hv, "peers", newRV_noinc((SV*) peers));
96              
97 0 0         wg_for_each_peer(dev, peer) {
98 0           HV* peer_hv = _wgpeer_to_hv(aTHX_ peer);
99 0           av_push(peers, newRV_noinc((SV*) peer_hv));
100             }
101              
102 0           return dev_hv;
103             }
104              
105             // Doesn’t seem to be useful:
106             #define _LWG_CREATE_CONST_UV(ns, theconst) \
107             newCONSTSUB(gv_stashpv(ns, 0), #theconst, newSVuv(theconst));
108              
109             // ----------------------------------------------------------------------
110              
111             MODULE = Linux::WireGuard PACKAGE = Linux::WireGuard
112              
113             PROTOTYPES: DISABLE
114              
115             void
116             list_device_names()
117             PPCODE:
118             char *device_names, *device_name;
119             size_t len;
120              
121 1           device_names = wg_list_device_names();
122 1 50         if (!device_names) {
123 0           croak("Failed to retrieve device names: %s", strerror(errno));
124             }
125              
126 1           unsigned count=0;
127              
128 1 50         wg_for_each_device_name(device_names, device_name, len) {
129 0           count++;
130 0 0         mXPUSHp(device_name, len);
131             }
132              
133 1           free(device_names);
134              
135 1           XSRETURN(count);
136              
137             SV*
138             get_device (SV* name_sv)
139             CODE:
140             wg_device *dev;
141              
142 0           const char* devname = exs_SvPVbyte_nolen(name_sv);
143              
144 0 0         if (wg_get_device(&dev, devname) < 0) {
145 0           croak("Failed to retrieve device `%s`: %s", devname, strerror(errno));
146             }
147              
148 0           HV* dev_hv = _wgdev_to_hv(aTHX_ dev);
149              
150 0           wg_free_device(dev);
151              
152 0           RETVAL = newRV_noinc((SV*) dev_hv);
153              
154             OUTPUT:
155             RETVAL
156              
157             void
158             add_device (SV* name_sv)
159             ALIAS:
160             del_device = 1
161             CODE:
162 2           const char* devname = exs_SvPVbyte_nolen(name_sv);
163              
164 2 50         int result = ix ? wg_del_device(devname) : wg_add_device(devname);
165 2 50         if (result) {
166 2 50         croak("Failed to %s device `%s`: %s", ix ? "delete" : "add", devname, strerror(errno));
167             }
168              
169             SV*
170             generate_private_key()
171             ALIAS:
172             generate_preshared_key = 1
173             CODE:
174             wg_key key;
175              
176 4 100         if (ix) {
177 2           wg_generate_preshared_key(key);
178             }
179             else {
180 2           wg_generate_private_key(key);
181             }
182              
183 4           RETVAL = newSVpv((char*) key, sizeof(wg_key));
184             OUTPUT:
185             RETVAL
186              
187             SV*
188             generate_public_key(SV* private_key_sv)
189             CODE:
190             wg_key public_key;
191              
192 2 50         if (SvROK(private_key_sv)) {
193 0           croak("Reference is nonsensical here!");
194             }
195              
196             STRLEN keylen;
197 2 50         const char* private_key_char = SvPVbyte(private_key_sv, keylen);
198              
199 2 50         if (keylen != sizeof(wg_key)) {
200 0           croak("Key must be exactly %lu characters, not %lu!", sizeof(wg_key), keylen);
201             }
202              
203 2           wg_generate_public_key(public_key, (const void*) private_key_char);
204              
205 2           RETVAL = newSVpv((char*) public_key, sizeof(wg_key));
206             OUTPUT:
207             RETVAL