ifstate 1.13.7__py3-none-any.whl → 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ifstate/ifstate.py +15 -8
- {ifstate-1.13.7.dist-info → ifstate-2.0.0.dist-info}/METADATA +2 -2
- ifstate-2.0.0.dist-info/RECORD +39 -0
- libifstate/__init__.py +147 -78
- libifstate/address/__init__.py +1 -1
- libifstate/exception.py +6 -12
- libifstate/hook/__init__.py +195 -0
- libifstate/hook/wrapper.sh +50 -0
- libifstate/link/base.py +29 -34
- libifstate/link/dsa.py +1 -1
- libifstate/link/physical.py +3 -3
- libifstate/link/tun.py +3 -3
- libifstate/link/veth.py +2 -2
- libifstate/log.py +7 -4
- libifstate/netns/__init__.py +44 -6
- libifstate/parser/__init__.py +1 -1
- libifstate/parser/base.py +131 -85
- libifstate/routing/__init__.py +63 -17
- libifstate/schema/2/ifstate.conf.schema.json +4442 -0
- libifstate/sysctl/__init__.py +20 -2
- libifstate/tc/__init__.py +1 -1
- libifstate/util.py +153 -147
- libifstate/wireguard/__init__.py +82 -21
- ifstate-1.13.7.dist-info/RECORD +0 -37
- schema/ifstate.conf.schema.json +0 -4259
- {ifstate-1.13.7.dist-info → ifstate-2.0.0.dist-info}/WHEEL +0 -0
- {ifstate-1.13.7.dist-info → ifstate-2.0.0.dist-info}/entry_points.txt +0 -0
- {ifstate-1.13.7.dist-info → ifstate-2.0.0.dist-info}/licenses/LICENSE +0 -0
- {ifstate-1.13.7.dist-info → ifstate-2.0.0.dist-info}/top_level.txt +0 -0
libifstate/sysctl/__init__.py
CHANGED
@@ -3,15 +3,33 @@ import pyroute2.netns
|
|
3
3
|
|
4
4
|
import os
|
5
5
|
|
6
|
+
def deep_update(d, u):
|
7
|
+
"""update the nested dict `d` with values from `u`"""
|
8
|
+
for k, v in u.items():
|
9
|
+
if isinstance(v, dict):
|
10
|
+
d[k] = deep_update(d.get(k, {}), v)
|
11
|
+
else:
|
12
|
+
d[k] = v
|
13
|
+
return d
|
6
14
|
|
7
15
|
class Sysctl():
|
8
16
|
def __init__(self, netns):
|
9
|
-
self.sysctls = {
|
17
|
+
self.sysctls = {
|
18
|
+
"all": {
|
19
|
+
"ipv6": {
|
20
|
+
"optimistic_dad": 1
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
10
24
|
self.globals = {}
|
11
25
|
self.netns = netns
|
12
26
|
|
13
27
|
def add(self, iface, sysctl):
|
14
|
-
|
28
|
+
# deeply apply changes to the default/previously defined values
|
29
|
+
if iface in self.sysctls:
|
30
|
+
self.sysctls[iface] = deep_update(self.sysctls[iface], sysctl)
|
31
|
+
else:
|
32
|
+
self.sysctls[iface] = sysctl
|
15
33
|
|
16
34
|
def add_global(self, proto, sysctl):
|
17
35
|
self.globals[proto] = sysctl
|
libifstate/tc/__init__.py
CHANGED
@@ -254,7 +254,7 @@ class TC():
|
|
254
254
|
return changes
|
255
255
|
|
256
256
|
def apply(self, do_apply):
|
257
|
-
excpts = ExceptionCollector(
|
257
|
+
excpts = ExceptionCollector(self.iface, self.netns)
|
258
258
|
|
259
259
|
# get ifindex
|
260
260
|
self.idx = next(iter(self.netns.ipr.link_lookup(ifname=self.iface)), None)
|
libifstate/util.py
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
import libifstate.exception
|
2
2
|
from libifstate.log import logger, IfStateLogging
|
3
|
-
|
3
|
+
import pyroute2
|
4
|
+
from pyroute2 import IPRoute, IW, NetNS
|
4
5
|
|
6
|
+
from pyroute2 import NetlinkError
|
5
7
|
from pyroute2.netlink.rtnl.tcmsg import tcmsg
|
6
8
|
from pyroute2.netlink.rtnl import RTM_DELTFILTER, RTM_NEWNSID
|
7
9
|
from pyroute2.netlink.rtnl.nsidmsg import nsidmsg
|
@@ -17,33 +19,45 @@ except ModuleNotFoundError:
|
|
17
19
|
# pyroute2 >= 0.6
|
18
20
|
from pr2modules.ethtool.ioctl import SIOCETHTOOL
|
19
21
|
|
22
|
+
import atexit
|
20
23
|
import socket
|
21
24
|
import fcntl
|
25
|
+
import re
|
22
26
|
import struct
|
27
|
+
import subprocess
|
23
28
|
import array
|
24
29
|
import struct
|
30
|
+
import tempfile
|
25
31
|
import typing
|
26
32
|
import os
|
33
|
+
import yaml
|
27
34
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
"
|
42
|
-
"
|
43
|
-
)
|
44
|
-
|
45
|
-
|
46
|
-
|
35
|
+
def _get_of_node(netns, link):
|
36
|
+
if netns.netns is not None:
|
37
|
+
pyroute2.netns.pushns(netns.netns)
|
38
|
+
|
39
|
+
try:
|
40
|
+
return os.path.relpath(os.path.realpath(f"{netns.ipr.sysfs_path}/class/net/{link.get_attr('IFLA_IFNAME')}/of_node", strict=True), start=f"{netns.ipr.sysfs_path}/firmware/devicetree")
|
41
|
+
except FileNotFoundError:
|
42
|
+
return None
|
43
|
+
finally:
|
44
|
+
if netns.netns is not None:
|
45
|
+
pyroute2.netns.popns()
|
46
|
+
|
47
|
+
IDENTIFY_LOOKUPS = {
|
48
|
+
"perm_address": lambda netns, link: link.get_attr("IFLA_PERM_ADDRESS"),
|
49
|
+
"parent_dev_name": lambda netns, link: link.get_attr("IFLA_PARENT_DEV_NAME"),
|
50
|
+
"parent_dev_bus_name": lambda netns, link: link.get_attr("IFLA_PARENT_DEV_BUS_NAME"),
|
51
|
+
"phys_port_id": lambda netns, link: link.get_attr("IFLA_PHYS_PORT_ID"),
|
52
|
+
"phys_port_name": lambda netns, link: link.get_attr("IFLA_PHYS_PORT_NAME"),
|
53
|
+
"phys_switch_id": lambda netns, link: link.get_attr("IFLA_PHYS_SWITCH_ID"),
|
54
|
+
"of_node": _get_of_node,
|
55
|
+
}
|
56
|
+
|
57
|
+
|
58
|
+
REGEX_ETHER_BYTE = re.compile('[a-f0-9]{2}')
|
59
|
+
|
60
|
+
RUN_BASE_DIR = '/run/libifstate'
|
47
61
|
|
48
62
|
root_ipr = typing.NewType("IPRouteExt", IPRoute)
|
49
63
|
|
@@ -59,28 +73,103 @@ def filter_ifla_dump(showall, ifla, defaults, prefix="IFLA"):
|
|
59
73
|
|
60
74
|
return dump
|
61
75
|
|
76
|
+
def format_ether_address(address):
|
77
|
+
"""
|
78
|
+
Formats a ether address string canonical. Accepted formats:
|
79
|
+
|
80
|
+
xx:xx:xx:xx:xx:xx
|
81
|
+
xx-xx-xx-xx-xx-xx
|
82
|
+
xxxx.xxxx.xxxx
|
83
|
+
|
84
|
+
The hex digits may be lower and upper case.
|
85
|
+
"""
|
86
|
+
|
87
|
+
return ':'.join(REGEX_ETHER_BYTE.findall(address.lower()))
|
88
|
+
|
89
|
+
|
90
|
+
def get_run_dir(function, *args):
|
91
|
+
"""
|
92
|
+
Returns a deterministic directory under /run/libifstate for saving state
|
93
|
+
informations between ifstate calls. A hierarchy is build from the ifstate
|
94
|
+
function and additional distinguishers (i.e. ifname).
|
95
|
+
|
96
|
+
The directory will be created if it does not already exists.
|
97
|
+
"""
|
98
|
+
|
99
|
+
run_dir = os.path.join(RUN_BASE_DIR, function, *args)
|
100
|
+
|
101
|
+
try:
|
102
|
+
os.makedirs(run_dir, mode=0o700)
|
103
|
+
except FileExistsError:
|
104
|
+
pass
|
105
|
+
|
106
|
+
return run_dir
|
107
|
+
|
108
|
+
def get_netns_run_dir(function, netns, *args):
|
109
|
+
"""
|
110
|
+
Returns a deterministic directory under /run/libifstate for saving state
|
111
|
+
informations between ifstate calls. A hierarchy is build from the ifstate
|
112
|
+
function, the netns and optional additional distinguishers (i.e. ifname).
|
113
|
+
|
114
|
+
The directory will be created if it does not already exists.
|
115
|
+
"""
|
116
|
+
|
117
|
+
if netns.netns is None:
|
118
|
+
run_dir = os.path.join(RUN_BASE_DIR, function, 'root', *args)
|
119
|
+
else:
|
120
|
+
run_dir = os.path.join(RUN_BASE_DIR, function, 'netns', netns.netns, *args)
|
121
|
+
|
122
|
+
try:
|
123
|
+
os.makedirs(run_dir, mode=0o700)
|
124
|
+
except FileExistsError:
|
125
|
+
pass
|
126
|
+
|
127
|
+
return run_dir
|
128
|
+
|
129
|
+
def dump_yaml_file(fn, obj, opener=None):
|
130
|
+
"""
|
131
|
+
Dump obj to a YAML file, create directories if needed and catch file
|
132
|
+
I/O errors.
|
133
|
+
"""
|
134
|
+
try:
|
135
|
+
os.makedirs(os.path.dirname(fn), mode=0o700)
|
136
|
+
except FileExistsError:
|
137
|
+
pass
|
138
|
+
|
139
|
+
try:
|
140
|
+
with open(fn, "w", opener=opener) as fh:
|
141
|
+
yaml.dump(obj, fh)
|
142
|
+
except OSError as err:
|
143
|
+
logger.error('Writing {} failed: {}'.format(fn, err))
|
144
|
+
|
145
|
+
def slurp_yaml_file(fn, default=None):
|
146
|
+
"""
|
147
|
+
Read the content of a YAML file, returns *default* if the file could not be
|
148
|
+
found, read or parsed.
|
149
|
+
"""
|
150
|
+
try:
|
151
|
+
with open(fn) as fh:
|
152
|
+
return yaml.load(fh, Loader=yaml.SafeLoader)
|
153
|
+
except OSError as err:
|
154
|
+
logger.debug('Reading {} failed: {}'.format(fn, err))
|
155
|
+
except yaml.YAMLError as err:
|
156
|
+
logger.warning('Parsing {} failed: {}'.format(fn, err))
|
157
|
+
|
158
|
+
return default
|
159
|
+
|
160
|
+
def kind_has_identify(kind):
|
161
|
+
"""
|
162
|
+
Return True if the interface kind can be identified by some unique
|
163
|
+
properties. These are all types of physical interfaces.
|
164
|
+
"""
|
165
|
+
return kind is None or kind in ['dsa']
|
166
|
+
|
62
167
|
class IPRouteExt(IPRoute):
|
63
168
|
def __init__(self, *args, **kwargs):
|
64
169
|
super().__init__(*args, **kwargs)
|
65
170
|
|
66
171
|
self.__sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
# def fork_before():
|
71
|
-
# import sys
|
72
|
-
# print(f"FORK[{os.getpid()}] before", file=sys.stderr)
|
73
|
-
|
74
|
-
# def fork_parent():
|
75
|
-
# import sys
|
76
|
-
# print(f"FORK[{os.getpid()}] parent", file=sys.stderr)
|
77
|
-
|
78
|
-
# def fork_child():
|
79
|
-
# import sys
|
80
|
-
# print(f"FORK[{os.getpid()}] after", file=sys.stderr)
|
81
|
-
|
82
|
-
# os.register_at_fork(before=fork_before, after_in_parent=fork_parent, after_in_child=fork_child)
|
83
|
-
|
172
|
+
self.sysfs_path = "/sys"
|
84
173
|
|
85
174
|
def del_filter_by_info(self, index=0, handle=0, info=0, parent=0):
|
86
175
|
msg = tcmsg()
|
@@ -97,60 +186,6 @@ class IPRouteExt(IPRoute):
|
|
97
186
|
NLM_F_ACK
|
98
187
|
))
|
99
188
|
|
100
|
-
def get_businfo(self, ifname):
|
101
|
-
data = array.array("B", struct.pack(
|
102
|
-
"I", ETHTOOL_GDRVINFO))
|
103
|
-
data.extend(b'\x00' * (STRUCT_DRVINFO.size - len(data)))
|
104
|
-
|
105
|
-
ifr = struct.pack('16sP', ifname.encode(
|
106
|
-
"utf-8"), data.buffer_info()[0])
|
107
|
-
|
108
|
-
try:
|
109
|
-
r = fcntl.ioctl(self.__sock.fileno(), SIOCETHTOOL, ifr)
|
110
|
-
except OSError:
|
111
|
-
return None
|
112
|
-
|
113
|
-
drvinfo = STRUCT_DRVINFO.unpack(data)
|
114
|
-
|
115
|
-
return drvinfo[4].decode('ascii').split('\x00')[0]
|
116
|
-
|
117
|
-
def get_permaddr(self, ifname):
|
118
|
-
data = array.array("B", struct.pack(
|
119
|
-
"II", ETHTOOL_GPERMADDR, L2_ADDRLENGTH))
|
120
|
-
data.extend(b'\x00' * L2_ADDRLENGTH)
|
121
|
-
|
122
|
-
ifr = struct.pack('16sP', ifname.encode(
|
123
|
-
"utf-8"), data.buffer_info()[0])
|
124
|
-
|
125
|
-
try:
|
126
|
-
r = fcntl.ioctl(self.__sock.fileno(), SIOCETHTOOL, ifr)
|
127
|
-
except OSError:
|
128
|
-
return None
|
129
|
-
|
130
|
-
l2addr = ":".join(format(x, "02x") for x in data[8:])
|
131
|
-
if l2addr == "00:00:00:00:00:00":
|
132
|
-
return None
|
133
|
-
|
134
|
-
return l2addr
|
135
|
-
|
136
|
-
def get_iface_by_businfo(self, businfo):
|
137
|
-
for iface in iter(self.get_links()):
|
138
|
-
ifname = iface.get_attr('IFLA_IFNAME')
|
139
|
-
bi = self.get_businfo(ifname)
|
140
|
-
|
141
|
-
if bi and bi == businfo:
|
142
|
-
return iface['index']
|
143
|
-
|
144
|
-
def get_iface_by_permaddr(self, permaddr):
|
145
|
-
for iface in iter(self.get_links()):
|
146
|
-
ifname = iface.get_attr('IFLA_IFNAME')
|
147
|
-
addr = self.get_permaddr(ifname)
|
148
|
-
|
149
|
-
if addr and addr == permaddr:
|
150
|
-
return iface['index']
|
151
|
-
|
152
|
-
return None
|
153
|
-
|
154
189
|
def get_ifname_by_index(self, index):
|
155
190
|
link = next(iter(self.get_links(index)), None)
|
156
191
|
|
@@ -207,10 +242,31 @@ class NetNSExt(NetNS):
|
|
207
242
|
self.netns = self.status["netns"]
|
208
243
|
|
209
244
|
try:
|
210
|
-
netns.pushns(self.netns)
|
245
|
+
pyroute2.netns.pushns(self.netns)
|
211
246
|
self.__sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
247
|
+
|
248
|
+
os.makedirs("/run/libifstate/sysfs", exist_ok=True)
|
249
|
+
self.sysfs_path = tempfile.mkdtemp(prefix=self.netns, dir="/run/libifstate/sysfs")
|
250
|
+
rc = subprocess.run(['mount', '', self.sysfs_path, '-t', 'sysfs', '-o', 'ro,nosuid,nodev,noexec,noatime'])
|
251
|
+
if rc.returncode != 0:
|
252
|
+
logger.warning("Could not mount netns sysfs: {rc.stderr}")
|
253
|
+
else:
|
254
|
+
logger.debug('mounted sysfs for {} at {}'.format(self.netns, self.sysfs_path), extra={'netns': self.netns})
|
255
|
+
atexit.register(self.umount_sysfs)
|
212
256
|
finally:
|
213
|
-
netns.popns()
|
257
|
+
pyroute2.netns.popns()
|
258
|
+
|
259
|
+
def umount_sysfs(self):
|
260
|
+
rc = subprocess.run(['umount', self.sysfs_path, '-t', 'sysfs'])
|
261
|
+
if rc.returncode != 0:
|
262
|
+
logger.warning("Could not umount netns sysfs: {rc.stderr}")
|
263
|
+
else:
|
264
|
+
logger.debug('umounted sysfs for {} at {}'.format(self.netns, self.sysfs_path), extra={'netns': self.netns})
|
265
|
+
|
266
|
+
try:
|
267
|
+
os.rmdir(self.sysfs_path)
|
268
|
+
except OSError:
|
269
|
+
pass
|
214
270
|
|
215
271
|
def del_filter_by_info(self, index=0, handle=0, info=0, parent=0):
|
216
272
|
msg = tcmsg()
|
@@ -227,60 +283,6 @@ class NetNSExt(NetNS):
|
|
227
283
|
NLM_F_ACK
|
228
284
|
))
|
229
285
|
|
230
|
-
def get_businfo(self, ifname):
|
231
|
-
data = array.array("B", struct.pack(
|
232
|
-
"I", ETHTOOL_GDRVINFO))
|
233
|
-
data.extend(b'\x00' * (STRUCT_DRVINFO.size - len(data)))
|
234
|
-
|
235
|
-
ifr = struct.pack('16sP', ifname.encode(
|
236
|
-
"utf-8"), data.buffer_info()[0])
|
237
|
-
|
238
|
-
try:
|
239
|
-
r = fcntl.ioctl(self.__sock.fileno(), SIOCETHTOOL, ifr)
|
240
|
-
except OSError:
|
241
|
-
return None
|
242
|
-
|
243
|
-
drvinfo = STRUCT_DRVINFO.unpack(data)
|
244
|
-
|
245
|
-
return drvinfo[4].decode('ascii').split('\x00')[0]
|
246
|
-
|
247
|
-
def get_permaddr(self, ifname):
|
248
|
-
data = array.array("B", struct.pack(
|
249
|
-
"II", ETHTOOL_GPERMADDR, L2_ADDRLENGTH))
|
250
|
-
data.extend(b'\x00' * L2_ADDRLENGTH)
|
251
|
-
|
252
|
-
ifr = struct.pack('16sP', ifname.encode(
|
253
|
-
"utf-8"), data.buffer_info()[0])
|
254
|
-
|
255
|
-
try:
|
256
|
-
r = fcntl.ioctl(self.__sock.fileno(), SIOCETHTOOL, ifr)
|
257
|
-
except OSError:
|
258
|
-
return None
|
259
|
-
|
260
|
-
l2addr = ":".join(format(x, "02x") for x in data[8:])
|
261
|
-
if l2addr == "00:00:00:00:00:00":
|
262
|
-
return None
|
263
|
-
|
264
|
-
return l2addr
|
265
|
-
|
266
|
-
def get_iface_by_businfo(self, businfo):
|
267
|
-
for iface in iter(self.get_links()):
|
268
|
-
ifname = iface.get_attr('IFLA_IFNAME')
|
269
|
-
bi = self.get_businfo(ifname)
|
270
|
-
|
271
|
-
if bi and bi == businfo:
|
272
|
-
return iface['index']
|
273
|
-
|
274
|
-
def get_iface_by_permaddr(self, permaddr):
|
275
|
-
for iface in iter(self.get_links()):
|
276
|
-
ifname = iface.get_attr('IFLA_IFNAME')
|
277
|
-
addr = self.get_permaddr(ifname)
|
278
|
-
|
279
|
-
if addr and addr == permaddr:
|
280
|
-
return iface['index']
|
281
|
-
|
282
|
-
return None
|
283
|
-
|
284
286
|
def get_ifname_by_index(self, index):
|
285
287
|
link = next(iter(self.get_links(index)), None)
|
286
288
|
|
@@ -369,3 +371,7 @@ class LinkDependency:
|
|
369
371
|
|
370
372
|
|
371
373
|
root_ipr = IPRouteExt()
|
374
|
+
try:
|
375
|
+
root_iw = IW()
|
376
|
+
except NetlinkError:
|
377
|
+
root_iw = None
|
libifstate/wireguard/__init__.py
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
from libifstate.util import logger, IfStateLogging
|
2
2
|
from libifstate.exception import netlinkerror_classes, FeatureMissingError
|
3
|
-
|
4
|
-
|
3
|
+
import wgnlpy
|
4
|
+
import ipaddress
|
5
5
|
import collections
|
6
6
|
from copy import deepcopy
|
7
|
+
import os
|
7
8
|
import pyroute2.netns
|
9
|
+
from pyroute2 import NetlinkError
|
8
10
|
import socket
|
9
11
|
|
12
|
+
SECRET_SETTINGS = ['private_key', 'preshared_key']
|
13
|
+
|
10
14
|
class WireGuard():
|
11
15
|
def __init__(self, netns, iface, wireguard):
|
12
16
|
self.netns = netns
|
@@ -17,7 +21,7 @@ class WireGuard():
|
|
17
21
|
pyroute2.netns.pushns(self.netns.netns)
|
18
22
|
|
19
23
|
try:
|
20
|
-
self.wg =
|
24
|
+
self.wg = wgnlpy.WireGuard()
|
21
25
|
finally:
|
22
26
|
if self.netns.netns is not None:
|
23
27
|
pyroute2.netns.popns()
|
@@ -28,7 +32,7 @@ class WireGuard():
|
|
28
32
|
for i, peer in enumerate(self.wireguard['peers']):
|
29
33
|
if 'allowedips' in peer:
|
30
34
|
self.wireguard['peers'][i]['allowedips'] = set(
|
31
|
-
[ip_network(x) for x in self.wireguard['peers'][i]['allowedips']])
|
35
|
+
[ipaddress.ip_network(x) for x in self.wireguard['peers'][i]['allowedips']])
|
32
36
|
|
33
37
|
def __deepcopy__(self, memo):
|
34
38
|
'''
|
@@ -43,7 +47,7 @@ class WireGuard():
|
|
43
47
|
pyroute2.netns.pushns(self.netns.netns)
|
44
48
|
|
45
49
|
try:
|
46
|
-
setattr(result, k,
|
50
|
+
setattr(result, k, wgnlpy.WireGuard())
|
47
51
|
finally:
|
48
52
|
if self.netns.netns is not None:
|
49
53
|
pyroute2.netns.popns()
|
@@ -56,6 +60,9 @@ class WireGuard():
|
|
56
60
|
try:
|
57
61
|
state = self.wg.get_interface(
|
58
62
|
self.iface, spill_private_key=True, spill_preshared_keys=True)
|
63
|
+
except NetlinkError as err:
|
64
|
+
logger.warning('query wireguard details failed: {}'.format(os.strerror(err.code)), extra={'iface': self.iface, 'netns': self.netns})
|
65
|
+
return
|
59
66
|
except TypeError as err:
|
60
67
|
# wgnlpy 0.1.5 can triggger a TypeError exception
|
61
68
|
# if the WGPEER_A_LAST_HANDSHAKE_TIME NLA does not
|
@@ -94,15 +101,15 @@ class WireGuard():
|
|
94
101
|
has_pchanges = False
|
95
102
|
|
96
103
|
avail = []
|
97
|
-
for
|
98
|
-
avail.append(
|
104
|
+
for public_key, opts in self.wireguard['peers'].items():
|
105
|
+
avail.append(public_key)
|
99
106
|
pubkey = next(
|
100
|
-
iter([x for x in peers.keys() if x ==
|
107
|
+
iter([x for x in peers.keys() if x == public_key]), None)
|
101
108
|
if pubkey is None:
|
102
109
|
has_pchanges = True
|
103
110
|
if do_apply:
|
104
111
|
try:
|
105
|
-
self.safe_set_peer(
|
112
|
+
self.safe_set_peer(public_key, opts)
|
106
113
|
except Exception as err:
|
107
114
|
if not isinstance(err, netlinkerror_classes):
|
108
115
|
raise
|
@@ -110,23 +117,23 @@ class WireGuard():
|
|
110
117
|
self.iface, err.args[1]))
|
111
118
|
else:
|
112
119
|
pchange = False
|
113
|
-
for setting in
|
120
|
+
for setting in opts.keys():
|
114
121
|
attr = getattr(peers[pubkey], setting)
|
115
122
|
if setting == 'allowedips':
|
116
|
-
attr =
|
123
|
+
attr = [str(ip) for ip in attr]
|
117
124
|
logger.debug(' peer.%s: %s => %s', setting, attr,
|
118
|
-
|
119
|
-
if type(attr) ==
|
120
|
-
pchange |= not (attr ==
|
125
|
+
opts[setting], extra={'iface': self.iface})
|
126
|
+
if type(attr) == list:
|
127
|
+
pchange |= not (attr == opts[setting])
|
121
128
|
else:
|
122
|
-
pchange |= str(
|
129
|
+
pchange |= str(opts[setting]) != str(getattr(
|
123
130
|
peers[pubkey], setting))
|
124
131
|
|
125
132
|
if pchange:
|
126
133
|
has_pchanges = True
|
127
134
|
if do_apply:
|
128
135
|
try:
|
129
|
-
self.safe_set_peer(
|
136
|
+
self.safe_set_peer(public_key, opts)
|
130
137
|
except Exception as err:
|
131
138
|
if not isinstance(err, netlinkerror_classes):
|
132
139
|
raise
|
@@ -149,11 +156,65 @@ class WireGuard():
|
|
149
156
|
else:
|
150
157
|
logger.log_ok('wg.peers')
|
151
158
|
|
152
|
-
def safe_set_peer(self,
|
159
|
+
def safe_set_peer(self, public_key, opts):
|
153
160
|
try:
|
154
|
-
self.wg.set_peer(self.iface, **
|
161
|
+
self.wg.set_peer(self.iface, public_key=public_key, **opts)
|
155
162
|
except (socket.gaierror, ValueError) as err:
|
156
|
-
logger.warning('failed to set wireguard endpoint at {}: {}'.format(self.iface, err))
|
163
|
+
logger.warning('failed to set wireguard endpoint for peer {} at {}: {}'.format(public_key, self.iface, err))
|
164
|
+
|
165
|
+
del(opts['endpoint'])
|
166
|
+
self.wg.set_peer(self.iface, public_key=public_key, **opts)
|
167
|
+
|
168
|
+
def show(netns, show_all, show_secrets, name, config):
|
169
|
+
if netns.netns is not None:
|
170
|
+
pyroute2.netns.pushns(self.netns.netns)
|
171
|
+
|
172
|
+
try:
|
173
|
+
wg = wgnlpy.WireGuard()
|
174
|
+
finally:
|
175
|
+
if netns.netns is not None:
|
176
|
+
pyroute2.netns.popns()
|
177
|
+
|
178
|
+
state = wg.get_interface(
|
179
|
+
name, spill_private_key=show_secrets, spill_preshared_keys=show_secrets)
|
180
|
+
|
181
|
+
config['wireguard'] = {
|
182
|
+
'peers': {},
|
183
|
+
}
|
184
|
+
|
185
|
+
def _dump_value(value):
|
186
|
+
if isinstance(value, (ipaddress.IPv4Network, ipaddress.IPv6Network, wgnlpy.sockaddr_in.sockaddr_in)):
|
187
|
+
return str(value)
|
188
|
+
elif type(value) is list:
|
189
|
+
result = []
|
190
|
+
for v in value:
|
191
|
+
result.append(_dump_value(v))
|
192
|
+
return result
|
193
|
+
else:
|
194
|
+
return value
|
195
|
+
|
196
|
+
def _dump_values(cfg, key, value):
|
197
|
+
if show_all:
|
198
|
+
if value is None:
|
199
|
+
return
|
200
|
+
else:
|
201
|
+
if not value:
|
202
|
+
return
|
203
|
+
|
204
|
+
if key in SECRET_SETTINGS:
|
205
|
+
if show_secrets:
|
206
|
+
cfg[key] = str(value)
|
207
|
+
else:
|
208
|
+
cfg[key] = f"# VALUE IS HIDDEN - USE --show-secrets TO REVEAL"
|
209
|
+
else:
|
210
|
+
cfg[key] = _dump_value(value)
|
211
|
+
|
212
|
+
for key in ['private_key', 'listen_port', 'fwmark']:
|
213
|
+
value = getattr(state, key)
|
214
|
+
_dump_values(config['wireguard'], key, value)
|
157
215
|
|
158
|
-
|
159
|
-
|
216
|
+
for peer in state.peers:
|
217
|
+
config['wireguard']['peers'][str(peer)] = {}
|
218
|
+
for key in ['preshared_key', 'endpoint', 'persistent_keepalive_interval', 'allowedips']:
|
219
|
+
value = getattr(state.peers[peer], key)
|
220
|
+
_dump_values(config['wireguard']['peers'][str(peer)], key, value)
|
ifstate-1.13.7.dist-info/RECORD
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
ifstate/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
ifstate/ifstate.py,sha256=l6VxiAXWyoqj7T5J495gM5Nhn807f5pHmL8_kh1uJAc,8891
|
3
|
-
ifstate/shell.py,sha256=7_JFpi4icr9MijynDzbb0v5mxhFsng6PCC4m3uQ255A,2177
|
4
|
-
ifstate/vrrp.py,sha256=FJ9b1eJseTtZFfknHU-xV68Qz7cPrRrc5PTcjUVj-fY,5953
|
5
|
-
ifstate-1.13.7.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
6
|
-
libifstate/__init__.py,sha256=dFqgv0fFecMsztHMh_IZnFyv2mOIyoM3KsmR13iCx5w,31132
|
7
|
-
libifstate/exception.py,sha256=5i59BZdl56J_sNJbyU9n6uHuUNJEyDOO4FJ-neDn9Ds,2608
|
8
|
-
libifstate/log.py,sha256=XVoZdwdQoWsjuupFIuG6OP0OrBpXpx7oqyAaUhQ-nJk,4553
|
9
|
-
libifstate/util.py,sha256=WzbGKX78iWUunnZ-v_3OREmxMiYt7vVM_QyCgTcMYow,10802
|
10
|
-
libifstate/address/__init__.py,sha256=zIGM7UWXSvoijHMD06DfS2CDtiHpiJlqDgJG7Dl1IPE,3222
|
11
|
-
libifstate/bpf/__init__.py,sha256=NVzaunTmJU2PbIQg9eWBMKpFgLh3EnD3ujNa7Yt6rNc,7699
|
12
|
-
libifstate/bpf/ctypes.py,sha256=kLZJHZlba09Vc-tbsJAcKpDwdoNO2IjlYVLCopawHmA,4274
|
13
|
-
libifstate/bpf/map.py,sha256=cLHNMvRBDNW2yVCEf3z242_oRdU0HqVbFEYVkKXng0w,10818
|
14
|
-
libifstate/brport/__init__.py,sha256=NzdA8F4hr2se1bXKNnyKZbvOFlCWBq_cdjwsL1H0Y-o,2964
|
15
|
-
libifstate/fdb/__init__.py,sha256=9dpL5n8ct3CaA-z8I6ZEkD3yL6yWJQeq3fpIe9pc2zw,6486
|
16
|
-
libifstate/link/__init__.py,sha256=epVw6jY8exNeJZUmmUas91yJoeupfgIY7rthq7SGIIw,142
|
17
|
-
libifstate/link/base.py,sha256=vGMQDgvLbIX4OF9YOMwttcRAOZeGvsIQqXEpKNdLJH4,34739
|
18
|
-
libifstate/link/dsa.py,sha256=Y3axTtcym6YL1voKblxctx4PoKDZHzpteKQNnEBUrS8,264
|
19
|
-
libifstate/link/physical.py,sha256=cJiq-MCfy-3XQoU-OxzgfPZZtu_pJ8u2ioJgn9VYdGk,560
|
20
|
-
libifstate/link/tun.py,sha256=m55o5cwO3h3DCLofUR-68fM4ggLoTKElp6ZJ2LrJSCc,959
|
21
|
-
libifstate/link/veth.py,sha256=V_jmQCizI5Vv8-pcsfldSfMRTn1knR11wZDZI_yXvks,2249
|
22
|
-
libifstate/neighbour/__init__.py,sha256=FJJpbJvqnxvOEii6QDMYzW5jQDEbiEy71GQOEbqaS48,2463
|
23
|
-
libifstate/netns/__init__.py,sha256=Fip3g2P1Tt_12pLt8abHsMRjSLZVi5THd1RJYcm9zfM,8887
|
24
|
-
libifstate/parser/__init__.py,sha256=byz1W0G7UewVc5FFie-ti3UZjGK3-75wHIaOeq0oySQ,88
|
25
|
-
libifstate/parser/base.py,sha256=VFAo05O3tiKtI381LVUMYfsDTseMKoQGTfkgnEkm3H4,4770
|
26
|
-
libifstate/parser/yaml.py,sha256=MC0kmwqt3P45z61fb_wfUqoj0iZyhFYkdPyr0UqMSZA,1415
|
27
|
-
libifstate/routing/__init__.py,sha256=fxDqDaNRcrb-8Lo6qH3UBifzJGymWwmMBXQSpMgyG0Y,22754
|
28
|
-
libifstate/sysctl/__init__.py,sha256=EF52CdOOkVSUFR2t21A99KlG1-PjsD4qOiceQC4eI24,3074
|
29
|
-
libifstate/tc/__init__.py,sha256=inPdampCOIr_4oKNB3awqMkW0Eh4fpPh9jvSba6sPVg,12092
|
30
|
-
libifstate/wireguard/__init__.py,sha256=HEmGsrtIX8MEjxtMbqgzP-e2BIUicyfmcywnRE93lRQ,6579
|
31
|
-
libifstate/xdp/__init__.py,sha256=X1xhEIGng7R5d5F4KsChykT2g6H-XBRWbWABijoYDQA,7208
|
32
|
-
schema/ifstate.conf.schema.json,sha256=NOPeI8_r1jXvgAAJeBqz92ZACNvxskId3qMykj-sG7M,201292
|
33
|
-
ifstate-1.13.7.dist-info/METADATA,sha256=mmhqlLk_amWU3IHFsUo7FWtaZF3sMLoZ0VZNACZra1M,1598
|
34
|
-
ifstate-1.13.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
35
|
-
ifstate-1.13.7.dist-info/entry_points.txt,sha256=HF6jX7Uu_nF1Ly-J9uEPeiRapOxnM6LuHsb2y6Mt-k4,52
|
36
|
-
ifstate-1.13.7.dist-info/top_level.txt,sha256=A7peI7aKBaM69fsiSPvMbL3rzTKZZr5qDxKC-pHMGdE,19
|
37
|
-
ifstate-1.13.7.dist-info/RECORD,,
|