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
|
|
|
|
|
|
|
SV* |
158
|
|
|
|
|
|
|
generate_private_key() |
159
|
|
|
|
|
|
|
ALIAS: |
160
|
|
|
|
|
|
|
generate_preshared_key = 1 |
161
|
|
|
|
|
|
|
CODE: |
162
|
|
|
|
|
|
|
wg_key key; |
163
|
|
|
|
|
|
|
|
164
|
4
|
100
|
|
|
|
|
if (ix) { |
165
|
2
|
|
|
|
|
|
wg_generate_preshared_key(key); |
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
else { |
168
|
2
|
|
|
|
|
|
wg_generate_private_key(key); |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
4
|
|
|
|
|
|
RETVAL = newSVpv((char*) key, sizeof(wg_key)); |
172
|
|
|
|
|
|
|
OUTPUT: |
173
|
|
|
|
|
|
|
RETVAL |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
SV* |
176
|
|
|
|
|
|
|
generate_public_key(SV* private_key_sv) |
177
|
|
|
|
|
|
|
CODE: |
178
|
|
|
|
|
|
|
wg_key public_key; |
179
|
|
|
|
|
|
|
|
180
|
2
|
50
|
|
|
|
|
if (SvROK(private_key_sv)) { |
181
|
0
|
|
|
|
|
|
croak("Reference is nonsensical here!"); |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
STRLEN keylen; |
185
|
2
|
50
|
|
|
|
|
const char* private_key_char = SvPVbyte(private_key_sv, keylen); |
186
|
|
|
|
|
|
|
|
187
|
2
|
50
|
|
|
|
|
if (keylen != sizeof(wg_key)) { |
188
|
0
|
|
|
|
|
|
croak("Key must be exactly %lu characters, not %lu!", sizeof(wg_key), keylen); |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
2
|
|
|
|
|
|
wg_generate_public_key(public_key, (const void*) private_key_char); |
192
|
|
|
|
|
|
|
|
193
|
2
|
|
|
|
|
|
RETVAL = newSVpv((char*) public_key, sizeof(wg_key)); |
194
|
|
|
|
|
|
|
OUTPUT: |
195
|
|
|
|
|
|
|
RETVAL |