line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
=pod |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
WGmeta::Wrapper::Config - Class for interfacing the wireguard configuration |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 SYNOPSIS |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
use Wireguard::WGmeta::Wrapper::Config; |
10
|
|
|
|
|
|
|
my $wg_meta = Wireguard::WGmeta::Wrapper::Config->new(''); |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 DESCRIPTION |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
This class provides wrapper-functions around a wireguard configuration parsed by L which |
15
|
|
|
|
|
|
|
allow to edit, add and remove interfaces and peers. |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 CONCURRENCY |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
Please refer to L |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 EXAMPLES |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
use Wireguard::WGmeta::Wrapper::Config; |
24
|
|
|
|
|
|
|
my $wg-meta = Wireguard::WGmeta::Wrapper::Config->new(''); |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
# set an attribute (non wg-meta attributes forwarded to the original `wg set` command) |
27
|
|
|
|
|
|
|
wg_meta->set('wg0', 'WG_0_PEER_A_PUBLIC_KEY', '', ''); |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
# set an alias for a peer |
30
|
|
|
|
|
|
|
wg_meta->set('wg0', 'WG_0_PEER_A_PUBLIC_KEY', 'alias', 'some_fancy_alias'); |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# disable peer (this comments out the peer in the configuration file) |
33
|
|
|
|
|
|
|
wg_meta->disable('wg0', 'some_fancy_alias'); |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# write config (if parameter is set to True, the config is overwritten, if set to False the resulting file is suffixed with '.not_applied' |
36
|
|
|
|
|
|
|
wg_meta->commit(1); |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
=head1 METHODS |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=cut |
41
|
|
|
|
|
|
|
|
42
|
5
|
|
|
5
|
|
234893
|
use v5.20.0; |
|
5
|
|
|
|
|
46
|
|
43
|
|
|
|
|
|
|
package Wireguard::WGmeta::Wrapper::Config; |
44
|
5
|
|
|
5
|
|
27
|
use strict; |
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
113
|
|
45
|
5
|
|
|
5
|
|
23
|
use warnings; |
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
163
|
|
46
|
5
|
|
|
5
|
|
45
|
use experimental 'signatures'; |
|
5
|
|
|
|
|
8
|
|
|
5
|
|
|
|
|
38
|
|
47
|
5
|
|
|
5
|
|
3046
|
use Wireguard::WGmeta::Wrapper::Bridge; |
|
5
|
|
|
|
|
12
|
|
|
5
|
|
|
|
|
323
|
|
48
|
5
|
|
|
5
|
|
2469
|
use Wireguard::WGmeta::Parser::Middleware; |
|
5
|
|
|
|
|
15
|
|
|
5
|
|
|
|
|
288
|
|
49
|
5
|
|
|
5
|
|
37
|
use Wireguard::WGmeta::ValidAttributes; |
|
5
|
|
|
|
|
16
|
|
|
5
|
|
|
|
|
322
|
|
50
|
5
|
|
|
5
|
|
30
|
use Wireguard::WGmeta::Utils; |
|
5
|
|
|
|
|
12
|
|
|
5
|
|
|
|
|
286
|
|
51
|
5
|
|
|
5
|
|
106
|
use Wireguard::WGmeta::Parser::Conf qw(INTERNAL_KEY_PREFIX); |
|
5
|
|
|
|
|
14
|
|
|
5
|
|
|
|
|
264
|
|
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
our $VERSION = "0.3.4"; # do not change manually, this variable is updated when calling make |
54
|
|
|
|
|
|
|
|
55
|
5
|
|
|
5
|
|
29
|
use constant FALSE => 0; |
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
264
|
|
56
|
5
|
|
|
5
|
|
29
|
use constant TRUE => 1; |
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
23864
|
|
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=head3 new($wireguard_home [, $wg_meta_prefix, $wg_meta_disabled_prefix, $custom_attributes]) |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
Creates a new instance of this class. |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
B |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=over 1 |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=item * |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
C<$wireguard_home> Path to Wireguard configuration files. Make sure the path ends with a `/`. |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=item * |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
C<[$wg_meta_prefix]> A custom wg-meta comment prefix, has to begin with either `;` or `#`. |
73
|
|
|
|
|
|
|
It is recommended to not change this setting, especially in a already deployed installation. |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=item * |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
C<[$wg_meta_disabled_prefix]> A custom prefix for the commented out (disabled) sections, |
78
|
|
|
|
|
|
|
has to begin with either `;` or `#` and must not be equal with C<$wg_meta_prefix>! (This is enforced and an exception is thrown if violated) |
79
|
|
|
|
|
|
|
It is recommended to not change this setting, especially in an already deployed installation. |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=item * |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
C<[$not_applied_suffix]> Suffix to add if C is set to not override an existing config. |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
=item * |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
C<[$custom_attributes]> A reference to a hash defining custom attributes. Expects the following structure: |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
{ |
90
|
|
|
|
|
|
|
'attr_key' => { |
91
|
|
|
|
|
|
|
'validator' => 'Ref to validation function' |
92
|
|
|
|
|
|
|
}, |
93
|
|
|
|
|
|
|
'example' => { |
94
|
|
|
|
|
|
|
'validator' => sub ($attr, $value) { |
95
|
|
|
|
|
|
|
return ($attr eq 'example') ? 1 : 0; |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
}, |
98
|
|
|
|
|
|
|
... |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=back |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
B |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
An instance of WGmeta::Wrapper::Config |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=cut |
108
|
10
|
|
|
10
|
1
|
77
|
sub new($class, $wireguard_home, $wg_meta_prefix = '#+', $wg_meta_disabled_prefix = '#-', $not_applied_suffix = '.not_applied', $custom_attributes = undef) { |
|
10
|
|
|
|
|
19
|
|
|
10
|
|
|
|
|
20
|
|
|
10
|
|
|
|
|
18
|
|
|
10
|
|
|
|
|
27
|
|
|
10
|
|
|
|
|
20
|
|
|
10
|
|
|
|
|
20
|
|
|
10
|
|
|
|
|
15
|
|
109
|
|
|
|
|
|
|
|
110
|
10
|
50
|
|
|
|
39
|
if ($wg_meta_prefix eq $wg_meta_disabled_prefix) { |
111
|
0
|
|
|
|
|
0
|
die '`$wg_meta_prefix` and `$wg_meta_disabled_prefix` have to be different'; |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
10
|
100
|
|
|
|
107
|
my $self = { |
115
|
|
|
|
|
|
|
'wireguard_home' => $wireguard_home, |
116
|
|
|
|
|
|
|
'wg_meta_prefix' => $wg_meta_prefix, |
117
|
|
|
|
|
|
|
'wg_meta_disabled_prefix' => $wg_meta_disabled_prefix, |
118
|
|
|
|
|
|
|
'not_applied_suffix' => $not_applied_suffix, |
119
|
|
|
|
|
|
|
'n_conf_files' => {}, |
120
|
|
|
|
|
|
|
'parsed_config' => {}, |
121
|
|
|
|
|
|
|
'reload_listeners' => {}, |
122
|
|
|
|
|
|
|
'custom_attributes' => defined $custom_attributes ? $custom_attributes : {} |
123
|
|
|
|
|
|
|
}; |
124
|
|
|
|
|
|
|
|
125
|
10
|
|
|
|
|
39
|
_read_configs_from_folder2($self); |
126
|
|
|
|
|
|
|
|
127
|
10
|
|
|
|
|
53
|
bless $self, $class; |
128
|
10
|
|
|
|
|
35
|
return $self; |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
|
131
|
10
|
|
|
10
|
|
16
|
sub _read_configs_from_folder2($self) { |
|
10
|
|
|
|
|
24
|
|
|
10
|
|
|
|
|
16
|
|
132
|
10
|
|
|
|
|
31
|
my ($all_dot_conf, $count) = get_all_conf_files($self->{wireguard_home}); |
133
|
10
|
|
|
|
|
20
|
for my $possible_config_path (@{$all_dot_conf}) { |
|
10
|
|
|
|
|
33
|
|
134
|
40
|
|
|
|
|
73
|
my $interface = $possible_config_path; |
135
|
40
|
|
|
|
|
464
|
$interface =~ s/^\/|\\|.*\/|.*\\|.conf$//g; |
136
|
40
|
|
|
|
|
110
|
may_reload_from_disk($self, $interface, TRUE, TRUE, TRUE); |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=head3 set($interface, $identifier, $attribute, $value [, $unknown_callback]) |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
Sets a value on a specific interface section. If C == C<$value> this sub is essentially a No-Op. |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
B |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=over 1 |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=item * |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
C<$interface> Valid interface identifier (e.g 'wg0') |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
=item * |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
C<$identifier> Either an interface name, an alias or public-key of a peer |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
=item * |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
C<$attribute> Attribute name (case does matter!) |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
=item * |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
C<[$unknown_callback = undef]> A reference to a callback function which is fired when a previously unknown attribute is set. |
163
|
|
|
|
|
|
|
Expected signature: |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
sub my_unknown_callback($attribute, $value) { |
166
|
|
|
|
|
|
|
# Handling of this particular case |
167
|
|
|
|
|
|
|
return $attribute, $value; |
168
|
|
|
|
|
|
|
} |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
If not defined, a warning is emitted |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=back |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
B |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
Exception if: |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
=over 1 |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
=item * |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
Value is not defined |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
=item * |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
Interface is invalid |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
=item * |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
Identifier is invalid (also if alias translation fails) |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=item * |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
Attribute is not valid for target section (Interface, Peer) |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
=item * |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
Validation for the attribute value fails |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
=back |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
B |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
None |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
=cut |
207
|
41
|
|
|
41
|
1
|
2576
|
sub set($self, $interface, $identifier, $attribute, $value, $unknown_callback = undef) { |
|
41
|
|
|
|
|
67
|
|
|
41
|
|
|
|
|
64
|
|
|
41
|
|
|
|
|
64
|
|
|
41
|
|
|
|
|
61
|
|
|
41
|
|
|
|
|
60
|
|
|
41
|
|
|
|
|
69
|
|
|
41
|
|
|
|
|
50
|
|
208
|
|
|
|
|
|
|
# Assertions |
209
|
41
|
50
|
|
|
|
95
|
die "Undefined value for `$attribute` in interface `$interface` NOT SET" unless defined($value); |
210
|
41
|
50
|
|
|
|
107
|
die "Invalid interface name `$interface`" unless $self->is_valid_interface($interface); |
211
|
41
|
|
|
|
|
286
|
$identifier = $self->try_translate_alias($interface, $identifier); |
212
|
41
|
50
|
|
|
|
101
|
die "Invalid identifier `$identifier` for interface `$interface`" unless $self->is_valid_identifier($interface, $identifier); |
213
|
41
|
|
|
|
|
123
|
my $attr_type = get_attr_type($attribute); |
214
|
41
|
100
|
|
|
|
103
|
if ($interface eq $identifier) { |
215
|
|
|
|
|
|
|
# We have an interface |
216
|
6
|
100
|
|
|
|
24
|
die "Attribute `$attribute` it not valid for the interface section" if $attr_type == ATTR_TYPE_IS_WG_ORIG_PEER; |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
else { |
219
|
35
|
100
|
66
|
|
|
153
|
die "Attribute `$attribute` is not valid for a peer section" if $attr_type == ATTR_TYPE_IS_WG_ORIG_INTERFACE or $attr_type == ATTR_TYPE_IS_WG_QUICK; |
220
|
|
|
|
|
|
|
} |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
# skip if same value |
223
|
39
|
50
|
66
|
|
|
168
|
if (exists $self->{parsed_config}{$interface}{$identifier}{$attribute} && $self->{parsed_config}{$interface}{$identifier}{$attribute} eq $value) { |
224
|
0
|
|
|
|
|
0
|
return; |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
# Call attribute validation function |
228
|
39
|
100
|
|
|
|
92
|
die "Invalid attribute value `$value` for `$attribute`" unless $self->attr_value_is_valid($attribute, $value); |
229
|
|
|
|
|
|
|
|
230
|
38
|
100
|
|
|
|
106
|
unless (exists $self->{parsed_config}{$interface}{$identifier}{$attribute}) { |
231
|
|
|
|
|
|
|
|
232
|
25
|
100
|
|
|
|
65
|
if (not exists $self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'observed_wg_meta_attrs'}{$attribute}) { |
233
|
23
|
100
|
|
|
|
73
|
if (exists KNOWN_ATTRIBUTES->{$attribute}) { |
|
|
100
|
|
|
|
|
|
234
|
|
|
|
|
|
|
# we have to first occurrence of a known but yet unseen wg-meta attribute |
235
|
14
|
100
|
|
|
|
39
|
$self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'observed_wg_meta_attrs'}{$attribute} = 1 if KNOWN_ATTRIBUTES->{$attribute}{type} == ATTR_TYPE_IS_WG_META; |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
elsif (exists $self->{custom_attributes}{$attribute}) { |
238
|
|
|
|
|
|
|
# we have a registered custom attribute |
239
|
1
|
|
|
|
|
5
|
$self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'observed_wg_meta_attrs'}{$attribute} = 1 |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
else { |
242
|
|
|
|
|
|
|
# we have a completely new, unknown attribute |
243
|
8
|
50
|
|
|
|
29
|
if (defined $unknown_callback) { |
244
|
8
|
|
|
|
|
17
|
($attribute, $value) = &{$unknown_callback}($attribute, $value); |
|
8
|
|
|
|
|
23
|
|
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
else { |
247
|
0
|
|
|
|
|
0
|
warn "Attribute `$attribute` was previously not known on interface `$interface`"; |
248
|
|
|
|
|
|
|
} |
249
|
7
|
|
|
|
|
196
|
$self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'observed_wg_meta_attrs'}{$attribute} = 1; |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
# the attribute does not (yet) exist in the configuration, lets add it to the list |
253
|
24
|
|
|
|
|
41
|
push @{$self->{parsed_config}{$interface}{$identifier}{INTERNAL_KEY_PREFIX . 'order'}}, $attribute; |
|
24
|
|
|
|
|
85
|
|
254
|
|
|
|
|
|
|
} |
255
|
37
|
100
|
|
|
|
105
|
if ($attribute eq 'alias') { |
256
|
8
|
|
|
|
|
28
|
$self->_update_alias_map($interface, $identifier, $value); |
257
|
|
|
|
|
|
|
} |
258
|
36
|
|
|
|
|
84
|
$self->{parsed_config}{$interface}{$identifier}{$attribute} = $value; |
259
|
36
|
|
|
|
|
111
|
$self->_set_changed($interface); |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
=head3 attr_value_is_valid($attribute, $value, $ref_valid_attrs) |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
Simply calls the C function defined in L or C<$custom_attributs> |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
B |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
=over 1 |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=item |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
C<$attribute> Attribute name |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
=item |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
C<$value> Attribute value |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
=back |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
B |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
True if validation was successful (or no validator function present), False if not. |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
=cut |
285
|
39
|
|
|
39
|
1
|
54
|
sub attr_value_is_valid($self, $attribute, $value) { |
|
39
|
|
|
|
|
57
|
|
|
39
|
|
|
|
|
56
|
|
|
39
|
|
|
|
|
61
|
|
|
39
|
|
|
|
|
76
|
|
286
|
39
|
100
|
|
|
|
91
|
return &{KNOWN_ATTRIBUTES->{$attribute}{validator}}($value) if exists KNOWN_ATTRIBUTES->{$attribute}; |
|
27
|
|
|
|
|
78
|
|
287
|
12
|
100
|
|
|
|
43
|
return &{$self->{custom_attributes}{$attribute}{validator}}($value) if exists $self->{custom_attributes}{$attribute}; |
|
1
|
|
|
|
|
4
|
|
288
|
11
|
|
|
|
|
31
|
return 1; |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
|
291
|
8
|
|
|
8
|
|
13
|
sub _update_alias_map($self, $interface, $identifier, $alias) { |
|
8
|
|
|
|
|
20
|
|
|
8
|
|
|
|
|
15
|
|
|
8
|
|
|
|
|
11
|
|
|
8
|
|
|
|
|
12
|
|
|
8
|
|
|
|
|
18
|
|
292
|
8
|
100
|
|
|
|
24
|
unless (exists $self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'alias_map'}{$alias}) { |
293
|
7
|
|
|
|
|
27
|
$self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'alias_map'}{$alias} = $identifier; |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
else { |
296
|
1
|
|
|
|
|
22
|
die "Alias `$alias` is already defined on interface `$interface`"; |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
} |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
=head3 disable($interface, $identifier) |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
Disables an interface/peer and setting the wg-meta attribute `Disabled` to C<1>. |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
B |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
=over 1 |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
=item * |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
C<$interface> Valid interface name (e.g 'wg0'). |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
=item * |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
C<$identifier> A valid identifier (or alias): If the target section is a peer, this is usually the public key of this peer. If target is an interface, |
316
|
|
|
|
|
|
|
its again the interface name. |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
=back |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
B |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
None |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
=cut |
325
|
3
|
|
|
3
|
1
|
272
|
sub disable($self, $interface, $identifier,) { |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
10
|
|
326
|
3
|
|
|
|
|
9
|
$self->_toggle($interface, $identifier, TRUE); |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
=head3 enable($interface, $identifier) |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
Inverse method if L |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
=cut |
334
|
7
|
|
|
7
|
1
|
15
|
sub enable($self, $interface, $identifier) { |
|
7
|
|
|
|
|
11
|
|
|
7
|
|
|
|
|
10
|
|
|
7
|
|
|
|
|
14
|
|
|
7
|
|
|
|
|
13
|
|
335
|
7
|
|
|
|
|
25
|
$self->_toggle($interface, $identifier, FALSE); |
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
# internal toggle method (DRY) |
339
|
10
|
|
|
10
|
|
19
|
sub _toggle($self, $interface, $identifier, $enable) { |
|
10
|
|
|
|
|
16
|
|
|
10
|
|
|
|
|
15
|
|
|
10
|
|
|
|
|
15
|
|
|
10
|
|
|
|
|
16
|
|
|
10
|
|
|
|
|
11
|
|
340
|
10
|
|
|
|
|
29
|
$identifier = $self->try_translate_alias($interface, $identifier); |
341
|
|
|
|
|
|
|
# we can bypass an "expensive" set() here |
342
|
10
|
|
|
|
|
27
|
$self->{parsed_config}{$interface}{$identifier}{'disabled'} = $enable; |
343
|
10
|
|
|
|
|
23
|
$self->_set_changed($interface); |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
=head3 is_valid_interface($interface) |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
Checks if an interface name is valid (present in parsed config) |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
B |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
=over 1 |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
=item |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
C<$interface> An interface name |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
=back |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
B |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
True if present, undef if not. |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
=cut |
365
|
59
|
|
|
59
|
1
|
90
|
sub is_valid_interface($self, $interface) { |
|
59
|
|
|
|
|
89
|
|
|
59
|
|
|
|
|
88
|
|
|
59
|
|
|
|
|
87
|
|
366
|
59
|
|
|
|
|
222
|
return (exists $self->{parsed_config}{$interface}); |
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
=head3 is_valid_alias($interface, $alias) |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
Simply checks if an alias is valid for a given interface |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
=cut |
375
|
2
|
|
|
2
|
1
|
4
|
sub is_valid_alias($self, $interface, $alias) { |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
4
|
|
376
|
2
|
|
|
|
|
11
|
return exists $self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'alias_map'}{$alias} |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
=head3 is_valid_identifier($interface, $identifier) |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
Checks if an identifier is valid for a given interface |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
B |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
=over 1 |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
=item |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
C<$interface> An interface name |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
=item |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
C<$identifier> An identifier (no alias!) |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
=back |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
B |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
True if present, undef if not. |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
=cut |
402
|
51
|
|
|
51
|
1
|
69
|
sub is_valid_identifier($self, $interface, $identifier) { |
|
51
|
|
|
|
|
77
|
|
|
51
|
|
|
|
|
75
|
|
|
51
|
|
|
|
|
73
|
|
|
51
|
|
|
|
|
82
|
|
403
|
51
|
|
|
|
|
186
|
return (exists $self->{parsed_config}{$interface}{$identifier}); |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
=head3 try_translate_alias($interface, $may_alias) |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
Tries to translate an identifier (which may be an alias). |
409
|
|
|
|
|
|
|
no exception is thrown on failure, instead the C<$may_alias> is returned. |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
B |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
=over 1 |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
=item |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
C<$interface> A valid interface name |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
=item |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
C<$may_alias> An identifier which could be a valid alias for this interface |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
=back |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
B |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
If the alias is valid for the specified interface, the corresponding identifier is returned, else C<$may_alias> |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
=cut |
430
|
62
|
|
|
62
|
1
|
105
|
sub try_translate_alias($self, $interface, $may_alias) { |
|
62
|
|
|
|
|
104
|
|
|
62
|
|
|
|
|
95
|
|
|
62
|
|
|
|
|
88
|
|
|
62
|
|
|
|
|
81
|
|
431
|
62
|
100
|
|
|
|
159
|
if (exists $self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'alias_map'}{$may_alias}) { |
432
|
5
|
|
|
|
|
31
|
return $self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'alias_map'}{$may_alias}; |
433
|
|
|
|
|
|
|
} |
434
|
|
|
|
|
|
|
else { |
435
|
57
|
|
|
|
|
134
|
return $may_alias; |
436
|
|
|
|
|
|
|
} |
437
|
|
|
|
|
|
|
} |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
=head3 get_all_conf_files($wireguard_home) |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
Returns a list of all files in C<$wireguard_home> matching I. |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
B |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
=over 1 |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
=item |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
C<$wireguard_home> Path to a folder where wireguard configuration files are located |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
=back |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
B |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
A reference to a list with absolute paths to the config files (possibly empty) |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
=cut |
458
|
10
|
|
|
10
|
1
|
21
|
sub get_all_conf_files($wireguard_home) { |
|
10
|
|
|
|
|
17
|
|
|
10
|
|
|
|
|
15
|
|
459
|
10
|
|
|
|
|
60
|
my @config_files = read_dir($wireguard_home, qr/.*\.conf$/); |
460
|
10
|
50
|
|
|
|
45
|
if (@config_files == 0) { |
461
|
0
|
|
|
|
|
0
|
die "No matching interface configuration(s) in " . $wireguard_home; |
462
|
|
|
|
|
|
|
} |
463
|
10
|
|
|
|
|
21
|
my $count = @config_files; |
464
|
10
|
|
|
|
|
38
|
return \@config_files, $count; |
465
|
|
|
|
|
|
|
} |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
=head3 commit([$is_hot_config = FALSE, $no_checksum = FALSE]) |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
Writes down the parsed config to the wireguard configuration folder |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
B |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
=over 1 |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
=item |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
C<[$is_hot_config = FALSE])> If set to TRUE, the existing configuration is overwritten (and possibly existing, not applied configs are deleted). Otherwise, |
479
|
|
|
|
|
|
|
the suffix '.not_applied' is appended to the filename |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
=item |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
C<[$no_checksum = FALSE])> If set to TRUE, no checksum is written |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
=back |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
B |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
Exception if: Folder or file is not writeable |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
B |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
None |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
=cut |
496
|
7
|
|
|
7
|
1
|
292
|
sub commit($self, $is_hot_config = FALSE, $no_checksum = FALSE) { |
|
7
|
|
|
|
|
11
|
|
|
7
|
|
|
|
|
12
|
|
|
7
|
|
|
|
|
16
|
|
|
7
|
|
|
|
|
12
|
|
497
|
7
|
|
|
|
|
14
|
for my $interface (keys %{$self->{parsed_config}}) { |
|
7
|
|
|
|
|
30
|
|
498
|
14
|
100
|
|
|
|
36
|
if ($self->_has_changed($interface)) { |
499
|
7
|
|
|
|
|
32
|
my $new_config = create_wg_config2($self->{parsed_config}{$interface}, $self->{wg_meta_prefix}, $self->{wg_meta_disabled_prefix}, $no_checksum); |
500
|
7
|
|
|
|
|
14
|
my $fh; |
501
|
7
|
|
|
|
|
37
|
my $hot_path = $self->{wireguard_home} . $interface . '.conf'; |
502
|
7
|
|
|
|
|
22
|
my $safe_path = $self->{wireguard_home} . $interface . $self->{not_applied_suffix}; |
503
|
7
|
100
|
|
|
|
19
|
if ($is_hot_config == TRUE) { |
504
|
6
|
50
|
|
|
|
574
|
open $fh, '>', $hot_path or die $!; |
505
|
6
|
|
|
|
|
36
|
$self->{parsed_config}->{$interface}{INTERNAL_KEY_PREFIX . 'is_hot_config'} = 1; |
506
|
|
|
|
|
|
|
} |
507
|
|
|
|
|
|
|
else { |
508
|
1
|
50
|
|
|
|
120
|
open $fh, '>', $safe_path or die $!; |
509
|
1
|
|
|
|
|
6
|
$self->{parsed_config}->{$interface}{INTERNAL_KEY_PREFIX . 'is_hot_config'} = 0; |
510
|
|
|
|
|
|
|
} |
511
|
|
|
|
|
|
|
# write down to file |
512
|
7
|
|
|
|
|
92
|
print $fh $new_config; |
513
|
7
|
|
|
|
|
35
|
$self->_reset_changed($interface); |
514
|
7
|
50
|
|
|
|
778
|
close $fh or die $!; |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
# if there is an not applied version around delete it (if is_hot_config = True) |
517
|
7
|
100
|
100
|
|
|
126
|
if (-e $safe_path && $is_hot_config) { |
518
|
1
|
|
|
|
|
71
|
unlink $safe_path; |
519
|
|
|
|
|
|
|
} |
520
|
|
|
|
|
|
|
# Notify listeners about a file change |
521
|
7
|
|
|
|
|
33
|
$self->_call_reload_listeners($interface); |
522
|
|
|
|
|
|
|
} |
523
|
|
|
|
|
|
|
} |
524
|
|
|
|
|
|
|
} |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
=head3 get_interface_list() |
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
Return a list of all interfaces. |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
B |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
A list of all valid interface names. If no interfaces are available, an empty list is returned |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
=cut |
536
|
4
|
|
|
4
|
1
|
21
|
sub get_interface_list($self) { |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
5
|
|
537
|
4
|
|
|
|
|
7
|
return sort keys %{$self->{parsed_config}}; |
|
4
|
|
|
|
|
26
|
|
538
|
|
|
|
|
|
|
} |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
=head3 get_interface_section($interface, $identifier) |
541
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
Returns a hash representing a section of a given interface |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
B |
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
=over 1 |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
=item * |
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
C<$interface> Valid interface name |
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
=item * |
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
C<$identifier> Valid section identifier |
555
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
=back |
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
B |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
A hash containing the requested section. If the requested section/interface is not present, an empty hash is returned. |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
=cut |
563
|
3
|
|
|
3
|
1
|
26
|
sub get_interface_section($self, $interface, $identifier) { |
|
3
|
|
|
|
|
14
|
|
|
3
|
|
|
|
|
16
|
|
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
5
|
|
564
|
3
|
|
|
|
|
8
|
$identifier = $self->try_translate_alias($interface, $identifier); |
565
|
3
|
50
|
|
|
|
9
|
if (exists $self->{parsed_config}{$interface}{$identifier}) { |
566
|
3
|
|
|
|
|
6
|
my %r = %{$self->{parsed_config}{$interface}{$identifier}}; |
|
3
|
|
|
|
|
27
|
|
567
|
3
|
|
|
|
|
29
|
return %r; |
568
|
|
|
|
|
|
|
} |
569
|
|
|
|
|
|
|
else { |
570
|
0
|
|
|
|
|
0
|
return (); |
571
|
|
|
|
|
|
|
} |
572
|
|
|
|
|
|
|
} |
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
=head3 get_section_list($interface) |
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
Returns a list of valid sections of an interface (ordered as in the original config file). |
577
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
B |
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
=over 1 |
581
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
=item * |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
C<$interface> A valid interface name |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
=back |
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
B |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
A list of all sections of an interface. If interface is not present, an empty list is returned. |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
=cut |
593
|
5
|
|
|
5
|
1
|
1616
|
sub get_section_list($self, $interface) { |
|
5
|
|
|
|
|
14
|
|
|
5
|
|
|
|
|
11
|
|
|
5
|
|
|
|
|
7
|
|
594
|
5
|
100
|
|
|
|
13
|
if ($self->is_valid_interface($interface)) { |
595
|
4
|
|
|
|
|
87
|
return @{$self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'section_order'}}; |
|
4
|
|
|
|
|
44
|
|
596
|
|
|
|
|
|
|
} |
597
|
|
|
|
|
|
|
else { |
598
|
1
|
|
|
|
|
4
|
return (); |
599
|
|
|
|
|
|
|
} |
600
|
|
|
|
|
|
|
} |
601
|
|
|
|
|
|
|
|
602
|
0
|
|
|
0
|
0
|
0
|
sub get_wg_meta_prefix($self) { |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
603
|
0
|
|
|
|
|
0
|
return $self->{wg_meta_prefix}; |
604
|
|
|
|
|
|
|
} |
605
|
|
|
|
|
|
|
|
606
|
0
|
|
|
0
|
0
|
0
|
sub get_disabled_prefix($self) { |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
607
|
0
|
|
|
|
|
0
|
return $self->{wg_meta_disabled_prefix}; |
608
|
|
|
|
|
|
|
} |
609
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
=head3 add_interface($interface_name, $ip_address, $listen_port, $private_key) |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
Adds a (minimally configured) interface. If more attributes are needed, please set them using the C method. |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
B No validation is performed on the values! |
615
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
B |
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
=over 1 |
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
=item * |
621
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
C<$interface_name> A new interface name, must be unique. |
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
=item * |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
C<$ip_address> A string describing the ip net(s) (e.g '10.0.0.0/24, fdc9:281f:04d7:9ee9::2/64') |
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
=item * |
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
C<$listen_port> The listen port for this interface. |
631
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
=item * |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
C<$private_key> A private key for this interface |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
=back |
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
B |
639
|
|
|
|
|
|
|
|
640
|
|
|
|
|
|
|
An exception if the interface name already exists. |
641
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
B |
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
None |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
=cut |
647
|
1
|
|
|
1
|
1
|
5
|
sub add_interface($self, $interface_name, $ip_address, $listen_port, $private_key) { |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
2
|
|
648
|
1
|
50
|
|
|
|
4
|
if ($self->is_valid_interface($interface_name)) { |
649
|
0
|
|
|
|
|
0
|
die "Interface `$interface_name` already exists"; |
650
|
|
|
|
|
|
|
} |
651
|
1
|
|
|
|
|
10
|
my %interface = ( |
652
|
|
|
|
|
|
|
'address' => $ip_address, |
653
|
|
|
|
|
|
|
'listen-port' => $listen_port, |
654
|
|
|
|
|
|
|
'private-key' => $private_key, |
655
|
|
|
|
|
|
|
INTERNAL_KEY_PREFIX . 'type' => 'Interface', |
656
|
|
|
|
|
|
|
INTERNAL_KEY_PREFIX . 'order' => [ 'address', 'listen-port', 'private-key' ] |
657
|
|
|
|
|
|
|
); |
658
|
1
|
|
|
|
|
5
|
$self->{parsed_config}{$interface_name}{$interface_name} = \%interface; |
659
|
1
|
|
|
|
|
3
|
$self->{parsed_config}{$interface_name}{INTERNAL_KEY_PREFIX . 'alias_map'} = {}; |
660
|
1
|
|
|
|
|
4
|
$self->{parsed_config}{$interface_name}{INTERNAL_KEY_PREFIX . 'section_order'} = [ $interface_name ]; |
661
|
1
|
|
|
|
|
4
|
$self->{parsed_config}{$interface_name}{checksum} = 'none'; |
662
|
1
|
|
|
|
|
4
|
$self->{parsed_config}{$interface_name}{INTERNAL_KEY_PREFIX . 'mtime'} = 0.0; |
663
|
1
|
|
|
|
|
5
|
$self->{parsed_config}{$interface_name}{INTERNAL_KEY_PREFIX . 'config_path'} = $self->{wireguard_home} . $interface_name . '.conf'; |
664
|
1
|
|
|
|
|
4
|
$self->{parsed_config}{$interface_name}{has_changed} = 1; |
665
|
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
} |
667
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
=head3 add_peer($interface, $ip_address, $public_key [, $alias, $preshared_key]) |
669
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
Adds a peer to an exiting interface. |
671
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
B |
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
=over 1 |
675
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
=item * |
677
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
C<$interface> A valid interface. |
679
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
=item * |
681
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
C<$ip_address> A string describing the ip-address(es) of this this peer. |
683
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
=item * |
685
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
C<$public_key> Public-key for this interface. This becomes the identifier of this peer. |
687
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
=item * |
689
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
C<[$preshared_key]> Optional argument defining the psk. |
691
|
|
|
|
|
|
|
|
692
|
|
|
|
|
|
|
=item * |
693
|
|
|
|
|
|
|
|
694
|
|
|
|
|
|
|
C<[$alias]> Optional argument defining an alias for this peer (wg-meta) |
695
|
|
|
|
|
|
|
|
696
|
|
|
|
|
|
|
=back |
697
|
|
|
|
|
|
|
|
698
|
|
|
|
|
|
|
B |
699
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
An exception if either the interface is invalid, the alias is already assigned or the public-key is |
701
|
|
|
|
|
|
|
already present on an other peer. |
702
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
B |
704
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
A tuple consisting of the iface private-key and listen port |
706
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
=cut |
708
|
5
|
|
|
5
|
1
|
1235
|
sub add_peer($self, $interface, $ip_address, $public_key, $alias = undef, $preshared_key = undef) { |
|
5
|
|
|
|
|
8
|
|
|
5
|
|
|
|
|
11
|
|
|
5
|
|
|
|
|
7
|
|
|
5
|
|
|
|
|
8
|
|
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
8
|
|
|
5
|
|
|
|
|
9
|
|
709
|
|
|
|
|
|
|
# generate new key pair if not defined |
710
|
5
|
50
|
|
|
|
19
|
if ($self->is_valid_interface($interface)) { |
711
|
5
|
50
|
|
|
|
20
|
if ($self->is_valid_identifier($interface, $public_key)) { |
712
|
0
|
|
|
|
|
0
|
die "An interface with this public-key already exists on `$interface`"; |
713
|
|
|
|
|
|
|
} |
714
|
|
|
|
|
|
|
# generate peer config |
715
|
5
|
|
|
|
|
15
|
my %peer = (); |
716
|
5
|
|
|
|
|
16
|
$self->{parsed_config}{$interface}{$public_key} = \%peer; |
717
|
5
|
|
|
|
|
22
|
$self->set($interface, $public_key, 'public-key', $public_key); |
718
|
5
|
|
|
|
|
50
|
$self->set($interface, $public_key, 'allowed-ips', $ip_address); |
719
|
5
|
100
|
|
|
|
24
|
if (defined $alias) { |
720
|
4
|
|
|
|
|
12
|
$self->set($interface, $public_key, 'alias', $alias); |
721
|
|
|
|
|
|
|
} |
722
|
5
|
50
|
|
|
|
15
|
if (defined $preshared_key) { |
723
|
0
|
|
|
|
|
0
|
$self->set($interface, $public_key, 'preshared-key', $preshared_key); |
724
|
|
|
|
|
|
|
} |
725
|
5
|
|
|
|
|
20
|
$self->enable($interface, $public_key); |
726
|
|
|
|
|
|
|
# set type to to Peer |
727
|
5
|
|
|
|
|
14
|
$self->{parsed_config}{$interface}{$public_key}{INTERNAL_KEY_PREFIX . 'type'} = 'Peer'; |
728
|
|
|
|
|
|
|
# add section to global section list |
729
|
5
|
|
|
|
|
8
|
push @{$self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'section_order'}}, $public_key; |
|
5
|
|
|
|
|
14
|
|
730
|
5
|
|
|
|
|
24
|
return $self->{parsed_config}{$interface}{$interface}{'private-key'}, $self->{parsed_config}{$interface}{$interface}{'listen-port'}; |
731
|
|
|
|
|
|
|
} |
732
|
|
|
|
|
|
|
else { |
733
|
0
|
|
|
|
|
0
|
die "Invalid interface `$interface`"; |
734
|
|
|
|
|
|
|
} |
735
|
|
|
|
|
|
|
} |
736
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
=head3 remove_peer($interface, $identifier) |
738
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
Removes a peer (identified by it's public key or alias) from an interface. |
740
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
B |
742
|
|
|
|
|
|
|
|
743
|
|
|
|
|
|
|
=over 1 |
744
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
=item |
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
C<$interface> A valid interface name |
748
|
|
|
|
|
|
|
|
749
|
|
|
|
|
|
|
=item |
750
|
|
|
|
|
|
|
|
751
|
|
|
|
|
|
|
C<$identifier> A valid identifier (or an alias) |
752
|
|
|
|
|
|
|
|
753
|
|
|
|
|
|
|
=back |
754
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
B |
756
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
Exception if interface or identifier is invalid |
758
|
|
|
|
|
|
|
|
759
|
|
|
|
|
|
|
B |
760
|
|
|
|
|
|
|
|
761
|
|
|
|
|
|
|
None |
762
|
|
|
|
|
|
|
|
763
|
|
|
|
|
|
|
=cut |
764
|
2
|
|
|
2
|
1
|
505
|
sub remove_peer($self, $interface, $identifier) { |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
5
|
|
765
|
2
|
50
|
|
|
|
6
|
if ($self->is_valid_interface($interface)) { |
766
|
2
|
|
|
|
|
9
|
$identifier = $self->try_translate_alias($interface, $identifier); |
767
|
2
|
50
|
|
|
|
9
|
if ($self->is_valid_identifier($interface, $identifier)) { |
768
|
|
|
|
|
|
|
|
769
|
|
|
|
|
|
|
# delete section |
770
|
2
|
|
|
|
|
11
|
delete $self->{parsed_config}{$interface}{$identifier}; |
771
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
# delete from section list |
773
|
2
|
|
|
|
|
7
|
$self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'section_order'} = [ grep {$_ ne $identifier} @{$self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'section_order'}} ]; |
|
5
|
|
|
|
|
15
|
|
|
2
|
|
|
|
|
8
|
|
774
|
|
|
|
|
|
|
|
775
|
|
|
|
|
|
|
# decrease peer count |
776
|
2
|
|
|
|
|
5
|
$self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'n_peers'}--; |
777
|
|
|
|
|
|
|
|
778
|
|
|
|
|
|
|
# delete alias (if exists) |
779
|
2
|
|
|
|
|
6
|
while (my ($alias, $a_identifier) = each %{$self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'alias_map'}}) { |
|
5
|
|
|
|
|
32
|
|
780
|
3
|
100
|
|
|
|
12
|
if ($a_identifier eq $identifier) { |
781
|
2
|
|
|
|
|
8
|
delete $self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'alias_map'}{$alias}; |
782
|
|
|
|
|
|
|
} |
783
|
|
|
|
|
|
|
} |
784
|
2
|
|
|
|
|
11
|
$self->_set_changed($interface); |
785
|
|
|
|
|
|
|
} |
786
|
|
|
|
|
|
|
else { |
787
|
0
|
|
|
|
|
0
|
die "Invalid identifier `$identifier` for `$interface`"; |
788
|
|
|
|
|
|
|
} |
789
|
|
|
|
|
|
|
} |
790
|
|
|
|
|
|
|
else { |
791
|
0
|
|
|
|
|
0
|
die "Invalid interface `$interface`"; |
792
|
|
|
|
|
|
|
} |
793
|
|
|
|
|
|
|
} |
794
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
=head3 remove_interface($interface [, $keep_file = FALSE]) |
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
Removes an interface. This command deletes the config file immediately. I.e no rollback possible! |
798
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
B |
800
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
=over 1 |
802
|
|
|
|
|
|
|
|
803
|
|
|
|
|
|
|
=item |
804
|
|
|
|
|
|
|
|
805
|
|
|
|
|
|
|
C<$interface> A valid interface name |
806
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
=back |
808
|
|
|
|
|
|
|
|
809
|
|
|
|
|
|
|
B |
810
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
Exception if interface or identifier is invalid |
812
|
|
|
|
|
|
|
|
813
|
|
|
|
|
|
|
B |
814
|
|
|
|
|
|
|
|
815
|
|
|
|
|
|
|
None |
816
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
=cut |
818
|
3
|
|
|
3
|
1
|
807
|
sub remove_interface($self, $interface) { |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
5
|
|
819
|
3
|
50
|
|
|
|
19
|
if ($self->is_valid_interface($interface)) { |
820
|
|
|
|
|
|
|
# delete interface |
821
|
3
|
|
|
|
|
24
|
delete $self->{parsed_config}{$interface}; |
822
|
3
|
50
|
|
|
|
59
|
if (-e "$self->{wireguard_home}$interface.conf") { |
823
|
3
|
50
|
|
|
|
295
|
unlink "$self->{wireguard_home}$interface.conf" or warn "Could not delete `$self->{wireguard_home}$interface.conf` do you have the needed permissions?"; |
824
|
|
|
|
|
|
|
} |
825
|
3
|
|
|
|
|
20
|
$self->{n_conf_files}--; |
826
|
|
|
|
|
|
|
} |
827
|
|
|
|
|
|
|
} |
828
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
=head3 get_peer_count([$interface = undef]) |
830
|
|
|
|
|
|
|
|
831
|
|
|
|
|
|
|
Returns the number of peers. |
832
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
B Does return the count represented in the current (parsed) configuration state. |
834
|
|
|
|
|
|
|
|
835
|
|
|
|
|
|
|
B |
836
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
=over 1 |
838
|
|
|
|
|
|
|
|
839
|
|
|
|
|
|
|
=item |
840
|
|
|
|
|
|
|
|
841
|
|
|
|
|
|
|
C<[$interface = undef]> If defined and valid, only return counts for this specific interface |
842
|
|
|
|
|
|
|
|
843
|
|
|
|
|
|
|
=back |
844
|
|
|
|
|
|
|
|
845
|
|
|
|
|
|
|
B |
846
|
|
|
|
|
|
|
|
847
|
|
|
|
|
|
|
Number of peers |
848
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
=cut |
850
|
3
|
|
|
3
|
1
|
790
|
sub get_peer_count($self, $interface = undef) { |
|
3
|
|
|
|
|
4
|
|
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
5
|
|
851
|
3
|
100
|
66
|
|
|
15
|
if (defined $interface && $self->is_valid_interface($interface)) { |
852
|
2
|
|
|
|
|
12
|
return $self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'n_peers'}; |
853
|
|
|
|
|
|
|
} |
854
|
|
|
|
|
|
|
else { |
855
|
1
|
|
|
|
|
1
|
my $count = 0; |
856
|
1
|
|
|
|
|
3
|
for ($self->get_interface_list()) { |
857
|
2
|
|
|
|
|
5
|
$count += $self->{parsed_config}{$_}{INTERNAL_KEY_PREFIX . 'n_peers'}; |
858
|
|
|
|
|
|
|
} |
859
|
1
|
|
|
|
|
10
|
return $count; |
860
|
|
|
|
|
|
|
} |
861
|
|
|
|
|
|
|
} |
862
|
|
|
|
|
|
|
|
863
|
|
|
|
|
|
|
=head3 may_reload_from_disk($interface [, $new = FALSE]) |
864
|
|
|
|
|
|
|
|
865
|
|
|
|
|
|
|
Method to reload an interface configuration from disk. Also useful to add an new (externally) created |
866
|
|
|
|
|
|
|
interface on-the-fly. If a config file with a I<.not_applied> suffix is present (and its mtime is newer |
867
|
|
|
|
|
|
|
than the original one), it is taken as source for reloading the configuration data. |
868
|
|
|
|
|
|
|
|
869
|
|
|
|
|
|
|
B |
870
|
|
|
|
|
|
|
|
871
|
|
|
|
|
|
|
=over 1 |
872
|
|
|
|
|
|
|
|
873
|
|
|
|
|
|
|
=item * |
874
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
C<$interface> A valid interface name |
876
|
|
|
|
|
|
|
|
877
|
|
|
|
|
|
|
=item * |
878
|
|
|
|
|
|
|
|
879
|
|
|
|
|
|
|
C<[$new = FALSE]> If set to True, the parser looks at C<$wireguard_home> for this new interface config. |
880
|
|
|
|
|
|
|
|
881
|
|
|
|
|
|
|
=item * |
882
|
|
|
|
|
|
|
|
883
|
|
|
|
|
|
|
C<[$force = FALSE]> When set to True, the configuration is reloaded regardless of its mtime. |
884
|
|
|
|
|
|
|
|
885
|
|
|
|
|
|
|
=back |
886
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
B |
888
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
Exception: If the interface is invalid (or the config file is not found) |
890
|
|
|
|
|
|
|
|
891
|
|
|
|
|
|
|
B |
892
|
|
|
|
|
|
|
|
893
|
|
|
|
|
|
|
None, or undef if C<$new == True> and the interface is in fact not a wg config. |
894
|
|
|
|
|
|
|
|
895
|
|
|
|
|
|
|
=cut |
896
|
149
|
|
|
149
|
1
|
247
|
sub may_reload_from_disk($self, $interface, $new = FALSE, $force = FALSE, $_init = FALSE) { |
|
149
|
|
|
|
|
237
|
|
|
149
|
|
|
|
|
236
|
|
|
149
|
|
|
|
|
225
|
|
|
149
|
|
|
|
|
209
|
|
|
149
|
|
|
|
|
205
|
|
|
149
|
|
|
|
|
220
|
|
897
|
149
|
|
|
|
|
361
|
my $config_path = $self->{wireguard_home} . $interface . '.conf'; |
898
|
|
|
|
|
|
|
# check if there is a newer, not applied version, if yes prefer this version |
899
|
149
|
|
|
|
|
306
|
my $not_applied_path = $self->{wireguard_home} . $interface . $self->{not_applied_suffix}; |
900
|
149
|
100
|
|
|
|
1996
|
if (-e $not_applied_path) { |
901
|
1
|
50
|
|
|
|
6
|
if (get_mtime($not_applied_path) > get_mtime($config_path)) { |
902
|
1
|
|
|
|
|
3
|
$config_path = $not_applied_path; |
903
|
|
|
|
|
|
|
} |
904
|
|
|
|
|
|
|
} |
905
|
149
|
100
|
|
|
|
440
|
if ($new == FALSE) { |
906
|
|
|
|
|
|
|
# do not use is_valid_interface() here otherwise there is a risk of infinite recursion (in a concurrent environment) |
907
|
54
|
50
|
|
|
|
145
|
if (exists $self->{parsed_config}{$interface}) { |
908
|
|
|
|
|
|
|
# we only reload if the on-disk version is newer than our local one |
909
|
|
|
|
|
|
|
# There is however one exception: The local config is based on a not applied version and this file somehow |
910
|
|
|
|
|
|
|
# unexpectedly deleted (e.g by a sysadmin..) |
911
|
54
|
|
|
|
|
164
|
my $on_disk_mtime = get_mtime($config_path); |
912
|
|
|
|
|
|
|
my $unexpected_delete = (exists $self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'is_hot_config'} |
913
|
|
|
|
|
|
|
&& $self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'is_hot_config'} == 0 |
914
|
54
|
|
66
|
|
|
335
|
&& $self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'mtime'} > $on_disk_mtime); |
915
|
|
|
|
|
|
|
|
916
|
54
|
100
|
66
|
|
|
457
|
if ($force || $unexpected_delete || $self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'mtime'} < $on_disk_mtime) { |
|
|
|
100
|
|
|
|
|
917
|
11
|
|
|
|
|
38
|
my $contents = read_file($config_path); |
918
|
11
|
|
|
|
|
62
|
$self->{parsed_config}{$interface} = parse_wg_config2($contents, $interface, $self->{wg_meta_prefix}, $self->{wg_meta_disabled_prefix}, FALSE); |
919
|
11
|
|
|
|
|
33
|
$self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'config_path'} = $config_path; |
920
|
11
|
|
|
|
|
39
|
$self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'mtime'} = get_mtime($config_path); |
921
|
11
|
100
|
|
|
|
110
|
$self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'is_hot_config'} = ($config_path =~ /$self->{not_applied_suffix}/) ? 0 : 1; |
922
|
11
|
50
|
|
|
|
58
|
$self->_call_reload_listeners($interface) if $_init == FALSE; |
923
|
|
|
|
|
|
|
} |
924
|
|
|
|
|
|
|
} |
925
|
|
|
|
|
|
|
else { |
926
|
0
|
|
|
|
|
0
|
die "Invalid interface $interface - if this is a new interface, set `\$new` to True"; |
927
|
|
|
|
|
|
|
} |
928
|
|
|
|
|
|
|
} |
929
|
|
|
|
|
|
|
# We have a completely new interface |
930
|
|
|
|
|
|
|
else { |
931
|
95
|
50
|
|
|
|
1161
|
if (-e $config_path) { |
932
|
95
|
|
|
|
|
384
|
my $contents = read_file($config_path); |
933
|
95
|
|
|
|
|
488
|
my $maybe_new_config = parse_wg_config2($contents, $interface, $self->{wg_meta_prefix}, $self->{wg_meta_disabled_prefix}, FALSE); |
934
|
95
|
100
|
|
|
|
254
|
if (defined $maybe_new_config) { |
935
|
21
|
|
|
|
|
42
|
$self->{n_conf_files}++; |
936
|
21
|
|
|
|
|
48
|
$self->{parsed_config}{$interface} = $maybe_new_config; |
937
|
21
|
|
|
|
|
54
|
$self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'config_path'} = $config_path; |
938
|
21
|
|
|
|
|
89
|
$self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'mtime'} = get_mtime($config_path); |
939
|
21
|
50
|
|
|
|
170
|
$self->{parsed_config}{$interface}{INTERNAL_KEY_PREFIX . 'is_hot_config'} = ($config_path =~ /$self->{not_applied_suffix}/) ? 0 : 1; |
940
|
21
|
100
|
|
|
|
119
|
$self->_call_reload_listeners($interface) if $_init == FALSE;; |
941
|
|
|
|
|
|
|
} |
942
|
|
|
|
|
|
|
else { |
943
|
74
|
|
|
|
|
285
|
return undef; |
944
|
|
|
|
|
|
|
} |
945
|
|
|
|
|
|
|
} |
946
|
|
|
|
|
|
|
else { |
947
|
0
|
|
|
|
|
0
|
die "The interface $interface was not found in $self->{wireguard_home}"; |
948
|
|
|
|
|
|
|
} |
949
|
|
|
|
|
|
|
|
950
|
|
|
|
|
|
|
} |
951
|
|
|
|
|
|
|
|
952
|
|
|
|
|
|
|
} |
953
|
|
|
|
|
|
|
|
954
|
|
|
|
|
|
|
# internal method to create a configuration file (this method exists primarily for testing purposes) |
955
|
4
|
|
|
4
|
0
|
535
|
sub create_config($self, $interface, $plain = FALSE) { |
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
6
|
|
956
|
|
|
|
|
|
|
return create_wg_config2( |
957
|
|
|
|
|
|
|
$self->{parsed_config}{$interface}, |
958
|
|
|
|
|
|
|
$self->{wg_meta_prefix}, |
959
|
|
|
|
|
|
|
$self->{wg_meta_disabled_prefix}, |
960
|
4
|
|
|
|
|
17
|
$plain = $plain) |
961
|
|
|
|
|
|
|
} |
962
|
|
|
|
|
|
|
|
963
|
40
|
|
|
40
|
|
56
|
sub _has_changed($self, $interface) { |
|
40
|
|
|
|
|
61
|
|
|
40
|
|
|
|
|
63
|
|
|
40
|
|
|
|
|
64
|
|
964
|
40
|
|
|
|
|
199
|
return exists $self->{parsed_config}{$interface}{has_changed}; |
965
|
|
|
|
|
|
|
} |
966
|
|
|
|
|
|
|
|
967
|
48
|
|
|
48
|
|
69
|
sub _set_changed($self, $interface) { |
|
48
|
|
|
|
|
75
|
|
|
48
|
|
|
|
|
82
|
|
|
48
|
|
|
|
|
64
|
|
968
|
48
|
|
|
|
|
156
|
$self->{parsed_config}{$interface}{has_changed} = 1; |
969
|
|
|
|
|
|
|
} |
970
|
|
|
|
|
|
|
|
971
|
17
|
|
|
17
|
|
32
|
sub _reset_changed($self, $interface) { |
|
17
|
|
|
|
|
28
|
|
|
17
|
|
|
|
|
27
|
|
|
17
|
|
|
|
|
26
|
|
972
|
17
|
50
|
|
|
|
81
|
delete $self->{parsed_config}{$interface}{has_changed} if (exists $self->{parsed_config}{$interface}{has_changed}); |
973
|
|
|
|
|
|
|
} |
974
|
|
|
|
|
|
|
|
975
|
|
|
|
|
|
|
=head3 register_on_reload_listener($ref_handler, $handler_id [, $ref_listener_args = []]) |
976
|
|
|
|
|
|
|
|
977
|
|
|
|
|
|
|
Register your callback handlers for the C event here. Your handler is called |
978
|
|
|
|
|
|
|
B the reload happened, is blocking and exceptions are caught in an C environment. |
979
|
|
|
|
|
|
|
|
980
|
|
|
|
|
|
|
B |
981
|
|
|
|
|
|
|
|
982
|
|
|
|
|
|
|
=over 1 |
983
|
|
|
|
|
|
|
|
984
|
|
|
|
|
|
|
=item |
985
|
|
|
|
|
|
|
|
986
|
|
|
|
|
|
|
C<$ref_handler> Reference to a handler function. The following signature is expected: |
987
|
|
|
|
|
|
|
|
988
|
|
|
|
|
|
|
sub my_handler_function($interface, $ref_list_args){ |
989
|
|
|
|
|
|
|
... |
990
|
|
|
|
|
|
|
} |
991
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
=item |
993
|
|
|
|
|
|
|
|
994
|
|
|
|
|
|
|
C<$handler_id> An identifier for you handler function. Must be unique! |
995
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
=item |
997
|
|
|
|
|
|
|
|
998
|
|
|
|
|
|
|
C<[$ref_listener_args = []]> A reference to an argument list for your handler function |
999
|
|
|
|
|
|
|
|
1000
|
|
|
|
|
|
|
=back |
1001
|
|
|
|
|
|
|
|
1002
|
|
|
|
|
|
|
B |
1003
|
|
|
|
|
|
|
|
1004
|
|
|
|
|
|
|
None, exception if C<$handler_id> is already present. |
1005
|
|
|
|
|
|
|
|
1006
|
|
|
|
|
|
|
=cut |
1007
|
1
|
|
|
1
|
1
|
435
|
sub register_on_reload_listener($self, $ref_handler, $handler_id, $ref_listener_args = []) { |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1
|
|
1008
|
1
|
50
|
|
|
|
8
|
unless ($self->{reload_listeners}{$handler_id}) { |
1009
|
1
|
|
|
|
|
6
|
my $listener_data = { |
1010
|
|
|
|
|
|
|
'handler' => $ref_handler, |
1011
|
|
|
|
|
|
|
'args' => $ref_listener_args |
1012
|
|
|
|
|
|
|
}; |
1013
|
1
|
|
|
|
|
4
|
$self->{reload_listeners}{$handler_id} = $listener_data; |
1014
|
|
|
|
|
|
|
} |
1015
|
|
|
|
|
|
|
else { |
1016
|
0
|
|
|
|
|
0
|
die "Handler id $handler_id already present"; |
1017
|
|
|
|
|
|
|
} |
1018
|
|
|
|
|
|
|
|
1019
|
|
|
|
|
|
|
} |
1020
|
|
|
|
|
|
|
|
1021
|
|
|
|
|
|
|
=head3 remove_on_reload_listener($handler_id) |
1022
|
|
|
|
|
|
|
|
1023
|
|
|
|
|
|
|
Removes a reload callback handler by it's C<$handler_id>. |
1024
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
B |
1026
|
|
|
|
|
|
|
|
1027
|
|
|
|
|
|
|
=over 1 |
1028
|
|
|
|
|
|
|
|
1029
|
|
|
|
|
|
|
=item |
1030
|
|
|
|
|
|
|
|
1031
|
|
|
|
|
|
|
C<$handler_id> A valid handler id |
1032
|
|
|
|
|
|
|
|
1033
|
|
|
|
|
|
|
=back |
1034
|
|
|
|
|
|
|
|
1035
|
|
|
|
|
|
|
B |
1036
|
|
|
|
|
|
|
|
1037
|
|
|
|
|
|
|
1 on success, undef on failure. |
1038
|
|
|
|
|
|
|
|
1039
|
|
|
|
|
|
|
=cut |
1040
|
0
|
|
|
0
|
1
|
0
|
sub remove_on_reload_listener($self, $handler_id) { |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
1041
|
0
|
0
|
|
|
|
0
|
if (exists $self->{reload_listeners}{$handler_id}) { |
1042
|
0
|
|
|
|
|
0
|
delete $self->{reload_listeners}{$handler_id}; |
1043
|
0
|
|
|
|
|
0
|
return 1; |
1044
|
|
|
|
|
|
|
} |
1045
|
|
|
|
|
|
|
else { |
1046
|
0
|
|
|
|
|
0
|
return undef; |
1047
|
|
|
|
|
|
|
} |
1048
|
|
|
|
|
|
|
} |
1049
|
|
|
|
|
|
|
|
1050
|
29
|
|
|
29
|
|
47
|
sub _call_reload_listeners($self, $interface) { |
|
29
|
|
|
|
|
57
|
|
|
29
|
|
|
|
|
54
|
|
|
29
|
|
|
|
|
50
|
|
1051
|
29
|
|
|
|
|
42
|
for my $listener_id (keys %{$self->{reload_listeners}}) { |
|
29
|
|
|
|
|
266
|
|
1052
|
1
|
|
|
|
|
3
|
eval { |
1053
|
1
|
|
|
|
|
2
|
&{$self->{reload_listeners}{$listener_id}{handler}}($interface, $self->{reload_listeners}{$listener_id}{args}); |
|
1
|
|
|
|
|
4
|
|
1054
|
|
|
|
|
|
|
}; |
1055
|
1
|
50
|
|
|
|
18
|
if ($@) { |
1056
|
0
|
|
|
|
|
|
warn "Call to reload_listener $listener_id failed: $@"; |
1057
|
|
|
|
|
|
|
} |
1058
|
|
|
|
|
|
|
} |
1059
|
|
|
|
|
|
|
} |
1060
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
|
1062
|
|
|
|
|
|
|
1; |