line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Wireguard::WGmeta::Cli::Commands::Add; |
2
|
1
|
|
|
1
|
|
7
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
33
|
|
3
|
1
|
|
|
1
|
|
6
|
use warnings FATAL => 'all'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
32
|
|
4
|
|
|
|
|
|
|
|
5
|
1
|
|
|
1
|
|
6
|
use experimental 'signatures'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
5
|
|
6
|
|
|
|
|
|
|
|
7
|
1
|
|
|
1
|
|
88
|
use parent 'Wireguard::WGmeta::Cli::Commands::Command'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
4
|
|
8
|
|
|
|
|
|
|
|
9
|
1
|
|
|
1
|
|
194
|
use Wireguard::WGmeta::Wrapper::Bridge; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
119
|
|
10
|
1
|
|
|
1
|
|
44
|
use Wireguard::WGmeta::ValidAttributes; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
169
|
|
11
|
1
|
|
|
1
|
|
10
|
use Wireguard::WGmeta::Parser::Middleware; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
871
|
|
12
|
|
|
|
|
|
|
|
13
|
0
|
|
|
0
|
1
|
|
sub entry_point($self) { |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
14
|
0
|
0
|
|
|
|
|
if ($self->_retrieve_or_die($self->{input_args}, 0) eq 'help') { |
15
|
0
|
|
|
|
|
|
$self->cmd_help(); |
16
|
|
|
|
|
|
|
} |
17
|
0
|
|
|
|
|
|
$self->check_privileges(); |
18
|
|
|
|
|
|
|
# read input parameters |
19
|
0
|
|
|
|
|
|
my $len = @{$self->{input_args}}; |
|
0
|
|
|
|
|
|
|
20
|
0
|
|
|
|
|
|
$self->{interface} = $self->_retrieve_or_die($self->{input_args}, 0); |
21
|
0
|
|
|
|
|
|
$self->{ips} = $self->_retrieve_or_die($self->{input_args}, 1); |
22
|
0
|
0
|
|
|
|
|
if ($len > 2) { |
23
|
|
|
|
|
|
|
# We hav additional arguments |
24
|
0
|
|
|
|
|
|
my @additional_args = @{$self->{input_args}}[2 .. $len - 1]; |
|
0
|
|
|
|
|
|
|
25
|
0
|
0
|
|
|
|
|
die 'Uneven number of elements (one pair would be without value!)' if scalar @additional_args % 2 != 0; |
26
|
0
|
|
|
|
|
|
$self->{additional_args} = \@additional_args; |
27
|
|
|
|
|
|
|
} |
28
|
|
|
|
|
|
|
# generate private/public keypair |
29
|
0
|
|
|
|
|
|
my ($privkey, $pubkey) = gen_keypair(); |
30
|
0
|
|
|
|
|
|
$self->{pub_key} = $pubkey; |
31
|
0
|
|
|
|
|
|
$self->{priv_key} = $privkey; |
32
|
|
|
|
|
|
|
|
33
|
0
|
|
|
|
|
|
$self->_run_command(); |
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
|
37
|
0
|
|
|
0
|
|
|
sub _run_command($self) { |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
my ($iface_privkey, $iface_listen) = $self->wg_meta->add_peer( |
39
|
|
|
|
|
|
|
$self->{interface}, |
40
|
|
|
|
|
|
|
$self->{ips}, |
41
|
|
|
|
|
|
|
$self->{pub_key} |
42
|
0
|
|
|
|
|
|
); |
43
|
|
|
|
|
|
|
# get pubkey of iface priv-key |
44
|
0
|
|
|
|
|
|
my $iface_pubkey = get_pub_key($iface_privkey); |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# get interface config |
47
|
0
|
|
|
|
|
|
my %host_interface = $self->wg_meta->get_interface_section($self->{interface}, $self->{interface}); |
48
|
0
|
0
|
|
|
|
|
my $fqdn = exists($host_interface{FQDN}) ? $host_interface{FQDN} : 'insert.valid.fqdn.not.valid'; |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# lets create a temporary interface |
51
|
0
|
|
|
|
|
|
$self->wg_meta->add_interface('temp', $self->{ips}, 44544, $self->{priv_key}); |
52
|
0
|
|
|
|
|
|
$self->wg_meta->add_peer('temp', '0.0.0.0/0, ::/0', $iface_pubkey); |
53
|
0
|
|
|
|
|
|
$self->wg_meta->set('temp', $iface_pubkey, 'endpoint', "$fqdn:$iface_listen"); |
54
|
0
|
0
|
|
|
|
|
if (exists($host_interface{DNSHost})){ |
55
|
0
|
|
|
|
|
|
$self->wg_meta->set('temp', 'temp', 'dns', $host_interface{DNSHost}); |
56
|
|
|
|
|
|
|
} |
57
|
0
|
|
|
|
|
|
$self->wg_meta->set('temp', $iface_pubkey, 'persistent-keepalive', 25); |
58
|
|
|
|
|
|
|
|
59
|
0
|
|
|
0
|
|
|
my $unknown_handler_temp = sub($attribute, $value) { |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
60
|
0
|
|
|
|
|
|
my $prefix = substr $attribute, 0, 1; |
61
|
0
|
0
|
|
|
|
|
$prefix eq '+' ? return (substr $attribute, 1), $value : return $attribute, $value; |
62
|
0
|
|
|
|
|
|
}; |
63
|
|
|
|
|
|
|
|
64
|
0
|
0
|
|
|
|
|
if (defined $self->{additional_args}) { |
65
|
0
|
|
|
|
|
|
my @additional_args = @{$self->{additional_args}}; |
|
0
|
|
|
|
|
|
|
66
|
0
|
|
|
|
|
|
for (my $i = 0; $i < scalar @additional_args; $i += 2) { |
67
|
0
|
|
|
|
|
|
my $attribute = $additional_args[$i]; |
68
|
0
|
|
|
|
|
|
my $value = $additional_args[$i + 1]; |
69
|
0
|
|
|
|
|
|
my $attr_type = get_attr_type($attribute); |
70
|
0
|
0
|
|
|
|
|
if ($attr_type == ATTR_TYPE_IS_WG_META) { |
|
|
0
|
|
|
|
|
|
71
|
0
|
|
|
|
|
|
$self->wg_meta->set($self->{interface}, $self->{pub_key}, $attribute, $value); |
72
|
0
|
|
|
|
|
|
$self->wg_meta->set('temp', 'temp', $attribute, $value); |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
elsif ($attr_type == ATTR_TYPE_IS_WG_ORIG_INTERFACE) { |
75
|
0
|
|
|
|
|
|
$self->wg_meta->set('temp', 'temp', $attribute, $value); |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
else { |
78
|
0
|
|
|
|
|
|
$self->wg_meta->set($self->{interface}, $self->{pub_key}, $attribute, $value, \&Wireguard::WGmeta::Cli::Commands::Command::_unknown_attr_handler); |
79
|
0
|
0
|
|
|
|
|
$self->wg_meta->set('temp', 'temp', $attribute, $value, $unknown_handler_temp) if $attr_type != ATTR_TYPE_IS_WG_ORIG_PEER; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
0
|
|
|
|
|
|
print "#Generated by wg-meta\n" . $self->wg_meta->create_config('temp', 0); |
86
|
|
|
|
|
|
|
# remove our temp interface again |
87
|
0
|
|
|
|
|
|
$self->wg_meta->remove_interface('temp'); |
88
|
0
|
|
|
|
|
|
$self->wg_meta->commit(1); |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
0
|
|
|
0
|
1
|
|
sub cmd_help($self) { |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
92
|
0
|
|
|
|
|
|
print "Usage: wg-meta addpeer [attr1 value1] [attr2 value2] ...\n\n" |
93
|
|
|
|
|
|
|
. "Notes: \nAttributes meant to reside in the [Interface] section are only applied to the peer's interface\n" |
94
|
|
|
|
|
|
|
. "wg-meta attributes are applied to the host's peer config and the client interface config\n" |
95
|
|
|
|
|
|
|
. "and finally, attributes meant to be in the [Peer] section are only applied to the host's peer entry.\n\n" |
96
|
|
|
|
|
|
|
. "To automatically fill in dns and endpoint name, make sure #+DNSHost and #+FQDN is present in [Interface]\n" |
97
|
|
|
|
|
|
|
. "Do not forget to reload the configuration afterwards!\n"; |
98
|
|
|
|
|
|
|
|
99
|
0
|
|
|
|
|
|
exit(); |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
1; |