forked from git-commit/wol-server-flask
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ieeemac.py
155 lines (125 loc) · 3.8 KB
/
ieeemac.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# ieeemac.py
# Copyright (C) 2007, 2008 Justin Azoff [email protected]
# 2014, Maximilian Berger
#
# This module is released under the MIT License:
# http://www.opensource.org/licenses/mit-license.php
"""Parses, finds, and converts MAC addresses between the following formats:
bare: 001122334455
windows: 00-11-22-33-44-55
unix?: 00:11:22:33:44:55
cisco: 0011.2233.4455
>>> from ieeemac import Mac, ismac
>>> ismac("00:11:22:33:44:55")
True
>>> ismac("00:11:22:33:44:5f")
True
>>> ismac("00:11:22:33:44:5g")
False
>>> m=Mac("00:11:22:33:44:5f")
>>> m.to_cisco
'0011.2233.445f'
>>> m.to_windows
'00-11-22-33-44-5f'
>>> m=Mac("00:01:02:03:04:05")
>>> m.to_windows
'00-01-02-03-04-05'
"""
import sys
import re
SEGMENT = "[0-9a-fA-F]{2}"
SIX = ((SEGMENT,)*6)
REGEXES_S = {
'unix': '(%s):(%s):(%s):(%s):(%s):(%s)' % SIX,
'windows': '(%s)-(%s)-(%s)-(%s)-(%s)-(%s)' % SIX,
'cisco': '(%s)(%s)\.(%s)(%s)\.(%s)(%s)' % SIX,
'bare': '(%s)(%s)(%s)(%s)(%s)(%s)' % SIX,
}
ALL_REGEX_S = '|'.join("(?P<%s>%s)" % (name, x) for (name, x) in REGEXES_S.items())
ALL_REGEX_S = "(%s)" % ALL_REGEX_S
ALL_REGEX = re.compile(ALL_REGEX_S)
ALL_REGEX_EXACT = re.compile(ALL_REGEX_S + "$")
FORMATS = {
'unix': '%s:%s:%s:%s:%s:%s',
'windows': '%s-%s-%s-%s-%s-%s',
'cisco': '%s%s.%s%s.%s%s',
'bare': '%s%s%s%s%s%s',
}
GROUP_OFFSETS = {}
for idx, group in enumerate(REGEXES_S.keys()):
GROUP_OFFSETS[group] = 2 + idx*7
REGEXES = {}
for t, r in REGEXES_S.items():
REGEXES[t] = re.compile(r + '$')
class Mac:
def __init__(self, mac):
if not mac:
raise ValueError("Invalid mac address: None")
mac = mac.lower()
ret = ALL_REGEX_EXACT.match(mac)
if not ret:
raise ValueError("Invalid mac address: %s" % mac)
for re_type, m in ret.groupdict().items():
if m:
self.format = re_type
go = GROUP_OFFSETS[re_type]
self.groups = ret.groups()[go:go+6]
#don't fix the groups here, most times I just want to init
#the object to see if the mac is valid
self.groups_need_fixing = True
return
def _formats(self):
return FORMATS.keys()
formats = property(_formats)
def to_format(self, format):
if self.groups_need_fixing:
self.groups = tuple(["%02x" % int(x, 16) for x in self.groups])
self.groups_need_fixing = False
return FORMATS[format] % self.groups
def __getattr__(self, attr):
if attr.startswith("to_"):
format = attr[3:]
return self.to_format(format)
else:
raise AttributeError
def __str__(self):
return self.to_format(self.format)
def __repr__(self):
return "Mac(%s)" % self
def __eq__(self, other):
if isinstance(other, str):
return self.to_bare == Mac(other).to_bare
else:
return self.to_bare == other.to_bare
mac = Mac
def is_mac(mac):
if not mac:
return False
mac = mac.lower()
ret = ALL_REGEX_EXACT.match(mac)
if not ret:
return False
return True
def is_mac_legacy(s):
try:
Mac(s)
return True
except ValueError:
return False
def find_macs(text):
"""return any MAC addresses found in the text"""
stuff = []
for x in ALL_REGEX.finditer(text):
x = x.group()
m = Mac(x)
stuff.append(m)
return stuff
def main():
if len(sys.argv) == 1:
print("Usage: %s mac_address" % sys.argv[0])
sys.exit(1)
m = Mac(sys.argv[1])
print("Input mac address in %s format" % m.format)
for f in m.formats:
print("%-10s %s" % (f, m.to_format(f)))
__all__ = ["Mac", "mac", "ismac", "find_macs", "main"]