Skip to content

Commit ff2f786

Browse files
authored
Merge pull request #6 from tonyseek/feature/tap-support
Add TAP mode support by parsing MAC addresses
2 parents adeeb33 + 0073da7 commit ff2f786

File tree

6 files changed

+35
-10
lines changed

6 files changed

+35
-10
lines changed

CHANGES.rst

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
0.2.0 (WIP)
22
-----------
33

4+
- Feature GH-1: Add support to TAP mode of OpenVPN servers by parsing virtual
5+
addresses as MAC and IP both.
46
- Fix GH-2: **BREAK-COMPATIBILITY** Use real or virtual addresses as the key
57
of client_list and routing_table, instead of using common name.
68

openvpn_status/models.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
from __future__ import absolute_import
22

33
from collections import OrderedDict
4-
from ipaddress import ip_address
54

65
from .descriptors import LabelProperty, name_descriptors
7-
from .utils import parse_time, parse_peer, parse_filesize
6+
from .utils import parse_time, parse_peer, parse_vaddr, parse_filesize
87

98

109
@name_descriptors
@@ -33,7 +32,7 @@ class Client(object):
3332
class Routing(object):
3433
"""The OpenVPN routing model."""
3534

36-
virtual_address = LabelProperty(u'Virtual Address', input_type=ip_address)
35+
virtual_address = LabelProperty(u'Virtual Address', input_type=parse_vaddr)
3736
common_name = LabelProperty(u'Common Name')
3837
real_address = LabelProperty(u'Real Address', input_type=parse_peer)
3938
last_ref = LabelProperty(u'Last Ref', input_type=parse_time)

openvpn_status/utils.py

+10
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
from __future__ import absolute_import
22

3+
import re
34
import datetime
45
import collections
56
import ipaddress
67

78
from six import python_2_unicode_compatible as unicode_compatible
89
from humanize.filesize import naturalsize
10+
from netaddr import EUI, mac_unix
911

1012

1113
DATETIME_FORMAT_OPENVPN = u'%a %b %d %H:%M:%S %Y'
14+
RE_VIRTUAL_ADDR_MAC = re.compile(
15+
u'^{0}:{0}:{0}:{0}:{0}:{0}$'.format(u'[a-f0-9]{2}'), re.I)
1216

1317

1418
def parse_time(time):
@@ -25,6 +29,12 @@ def parse_peer(peer):
2529
return PeerAddress(ipaddress.ip_address(host), int(port))
2630

2731

32+
def parse_vaddr(virtual_addr):
33+
if RE_VIRTUAL_ADDR_MAC.search(virtual_addr):
34+
return EUI(virtual_addr, dialect=mac_unix)
35+
return ipaddress.ip_address(virtual_addr)
36+
37+
2838
def parse_filesize(size):
2939
if isinstance(size, FileSize):
3040
return size

setup.py

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
install_requires=[
4141
'six>=1.9.0',
4242
'humanize',
43+
'netaddr',
4344
],
4445
extras_require={
4546
':python_version == "2.7"': [

tests/data/openvpn-status.txt

+2
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ [email protected],10.10.10.10:49502,334948,1973012,Thu Jun 18 04:23:03 2015
55
[email protected],10.10.10.10:49503,334948,1973012,Thu Jun 18 04:23:03 2015
66
[email protected],10.10.10.10:64169,1817262,28981224,Thu Jun 18 04:08:39 2015
77
[email protected],10.10.10.10:63414,111183,1202203,Thu Jun 18 07:57:25 2015
8+
[email protected],10.0.0.100:55712,0,0,Thu Oct 19 20:14:19 2017
89
ROUTING TABLE
910
Virtual Address,Common Name,Real Address,Last Ref
1011
192.168.255.118,[email protected],10.10.10.10:63414,Thu Jun 18 08:12:09 2015
1112
192.168.255.134,[email protected],10.10.10.10:49502,Thu Jun 18 08:12:09 2015
1213
192.168.255.135,[email protected],10.10.10.10:49503,Thu Jun 18 08:12:09 2015
1314
192.168.255.126,[email protected],10.10.10.10:64169,Thu Jun 18 08:11:55 2015
15+
22:1d:63:bf:62:38,[email protected],10.0.0.100:55712,Thu Oct 19 20:14:19 2017
1416
GLOBAL STATS
1517
Max bcast/mcast queue length,0
1618
END

tests/test_parser.py

+18-7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
from __future__ import absolute_import
22

33
import datetime
4+
import ipaddress
45

56
from pytest import fixture, raises
67
from six import text_type
8+
from netaddr import EUI
79

810
from openvpn_status.parser import LogParser, ParsingError
911

@@ -22,8 +24,9 @@ def test_parser(openvpn_status):
2224
parser = LogParser.fromstring(openvpn_status.read())
2325
status = parser.parse()
2426

25-
assert len(status.client_list) == 4
26-
assert len(status.routing_table) == 4
27+
assert len(status.client_list) == 5
28+
assert len(status.routing_table) == 5
29+
2730
assert status.global_stats.max_bcast_mcast_queue_len == 0
2831
assert status.updated_at == datetime.datetime(2015, 6, 18, 8, 12, 15)
2932

@@ -36,11 +39,19 @@ def test_parser(openvpn_status):
3639
assert client.bytes_received == 334948
3740
assert client.bytes_sent == 1973012
3841

39-
routing = status.routing_table[u'192.168.255.134']
40-
assert text_type(routing.virtual_address) == u'192.168.255.134'
41-
assert routing.common_name == u'[email protected]'
42-
assert text_type(routing.real_address) == u'10.10.10.10:49502'
43-
assert routing.last_ref == datetime.datetime(2015, 6, 18, 8, 12, 9)
42+
tun_routing = status.routing_table[u'192.168.255.134']
43+
assert isinstance(tun_routing.virtual_address, ipaddress.IPv4Address)
44+
assert text_type(tun_routing.virtual_address) == u'192.168.255.134'
45+
assert tun_routing.common_name == u'[email protected]'
46+
assert text_type(tun_routing.real_address) == u'10.10.10.10:49502'
47+
assert tun_routing.last_ref == datetime.datetime(2015, 6, 18, 8, 12, 9)
48+
49+
tap_routing = status.routing_table[u'22:1d:63:bf:62:38']
50+
assert isinstance(tap_routing.virtual_address, EUI)
51+
assert text_type(tap_routing.virtual_address) == u'22:1d:63:bf:62:38'
52+
assert tap_routing.common_name == u'[email protected]'
53+
assert text_type(tap_routing.real_address) == u'10.0.0.100:55712'
54+
assert tap_routing.last_ref == datetime.datetime(2017, 10, 19, 20, 14, 19)
4455

4556

4657
def test_parser_with_syntax_errors(broken_status):

0 commit comments

Comments
 (0)