Rev 15 | Rev 17 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 15 | Rev 16 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | <?php |
1 | <?php |
2 | 2 | ||
3 | /* |
3 | /* |
4 | * MAC utils for PHP |
4 | * MAC (EUI-48 and EUI-64) utils for PHP |
5 | * Copyright 2017 - 2023 Daniel Marschall, ViaThinkSoft |
5 | * Copyright 2017 - 2023 Daniel Marschall, ViaThinkSoft |
6 | * Version 2023-04-29 |
6 | * Version 2023-04-29 |
7 | * |
7 | * |
8 | * Licensed under the Apache License, Version 2.0 (the "License"); |
8 | * Licensed under the Apache License, Version 2.0 (the "License"); |
9 | * you may not use this file except in compliance with the License. |
9 | * you may not use this file except in compliance with the License. |
Line 23... | Line 23... | ||
23 | /** |
23 | /** |
24 | * @param string $mac |
24 | * @param string $mac |
25 | * @return bool |
25 | * @return bool |
26 | */ |
26 | */ |
27 | function mac_valid(string $mac): bool { |
27 | function mac_valid(string $mac): bool { |
- | 28 | $tmp = ipv6linklocal_to_eui64($mac); |
|
- | 29 | if ($tmp !== false) $mac = $tmp; |
|
- | 30 | ||
28 | $mac = str_replace(array('-', ':'), '', $mac); |
31 | $mac = str_replace(array('-', ':'), '', $mac); |
29 | $mac = strtoupper($mac); |
32 | $mac = strtoupper($mac); |
30 | 33 | ||
31 | if (strlen($mac) != 12) return false; |
34 | if ((strlen($mac) != 12) && (strlen($mac) != 16)) return false; |
32 | 35 | ||
33 | $mac = preg_replace('@[0-9A-F]@', '', $mac); |
36 | $mac = preg_replace('@[0-9A-F]@', '', $mac); |
34 | 37 | ||
35 | return ($mac == ''); |
38 | return ($mac === ''); |
- | 39 | } |
|
- | 40 | ||
- | 41 | /** |
|
- | 42 | * @param string $mac |
|
- | 43 | * @param string $delimiter |
|
- | 44 | * @return string|false |
|
- | 45 | */ |
|
- | 46 | function mac_canonize(string $mac, string $delimiter="-") { |
|
- | 47 | if (!mac_valid($mac)) return false; |
|
- | 48 | ||
- | 49 | $tmp = ipv6linklocal_to_eui64($mac); |
|
- | 50 | if ($tmp !== false) $mac = $tmp; |
|
- | 51 | ||
- | 52 | $mac = strtoupper($mac); |
|
- | 53 | $mac = preg_replace('@[^0-9A-F]@', '', $mac); |
|
- | 54 | if ((strlen($mac) != 12) && (strlen($mac) != 16)) return false; |
|
- | 55 | $mac = preg_replace('@^(..)(..)(..)(..)(..)(..)(..)(..)$@', '\\1'.$delimiter.'\\2'.$delimiter.'\\3'.$delimiter.'\\4'.$delimiter.'\\5'.$delimiter.'\\6'.$delimiter.'\\7'.$delimiter.'\\8', $mac); |
|
- | 56 | return preg_replace('@^(..)(..)(..)(..)(..)(..)$@', '\\1'.$delimiter.'\\2'.$delimiter.'\\3'.$delimiter.'\\4'.$delimiter.'\\5'.$delimiter.'\\6', $mac); |
|
36 | } |
57 | } |
37 | 58 | ||
38 | /** |
59 | /** |
39 | * @param string $file |
60 | * @param string $file |
40 | * @param string $oui_name |
61 | * @param string $oui_name |
41 | * @param string $mac |
62 | * @param string $mac |
42 | * @return false|string |
63 | * @return false|string |
43 | */ |
64 | */ |
44 | function _lookup_ieee_registry(string $file, string $oui_name, string $mac) { |
65 | function _lookup_ieee_registry(string $file, string $oui_name, string $mac) { |
- | 66 | $mac = mac_canonize($mac, ''); |
|
- | 67 | if ($mac === false) return false; |
|
45 | $begin = substr($mac, 0, 2).'-'.substr($mac, 2, 2).'-'.substr($mac, 4, 2); |
68 | $begin = substr($mac, 0, 2).'-'.substr($mac, 2, 2).'-'.substr($mac, 4, 2); |
46 | $f = file_get_contents($file); |
69 | $f = file_get_contents($file); |
47 | 70 | ||
48 | $f = str_replace("\r", '', $f); |
71 | $f = str_replace("\r", '', $f); |
49 | 72 | ||
Line 87... | Line 110... | ||
87 | 110 | ||
88 | return false; |
111 | return false; |
89 | } |
112 | } |
90 | 113 | ||
91 | /** |
114 | /** |
- | 115 | * @param string $eui64 |
|
- | 116 | * @return false|string If EUI-64 can be converted into EUI-48 (if it has FFFE in the middle), returns EUI-48, otherwise returns EUI-64. On invalid input, return false. |
|
- | 117 | */ |
|
- | 118 | function eui64_to_eui48(string $eui64) { |
|
- | 119 | if (!mac_valid($eui64)) return false; |
|
- | 120 | $eui64 = mac_canonize($eui64, ''); |
|
- | 121 | if (eui_bits($eui64) == 48) return mac_canonize($eui64); |
|
- | 122 | ||
- | 123 | if (substr($eui64, 6, 4) == 'FFFE') { |
|
- | 124 | return mac_canonize(substr($eui64, 0, 6).substr($eui64, 10, 6)); |
|
- | 125 | } else { |
|
- | 126 | return mac_canonize($eui64); |
|
- | 127 | } |
|
- | 128 | } |
|
- | 129 | ||
- | 130 | /** |
|
- | 131 | * @param string $eui48 |
|
- | 132 | * @return false|string |
|
- | 133 | */ |
|
- | 134 | function eui48_to_eui64(string $eui48) { |
|
- | 135 | if (!mac_valid($eui48)) return false; |
|
- | 136 | $eui48 = mac_canonize($eui48, ''); |
|
- | 137 | if (eui_bits($eui48) == 64) return mac_canonize($eui48); |
|
- | 138 | ||
- | 139 | $eui64 = substr($eui48, 0, 6).'FFFE'.substr($eui48, 6, 6); |
|
- | 140 | return mac_canonize($eui64); |
|
- | 141 | } |
|
- | 142 | ||
- | 143 | /** |
|
- | 144 | * @param string $ipv6 |
|
- | 145 | * @return false|string |
|
- | 146 | */ |
|
- | 147 | function ipv6linklocal_to_eui64(string $ipv6) { |
|
- | 148 | // https://stackoverflow.com/questions/12095835/quick-way-of-expanding-ipv6-addresses-with-php (modified) |
|
- | 149 | $tmp = inet_pton($ipv6); |
|
- | 150 | if ($tmp === false) return false; |
|
- | 151 | $hex = unpack("H*hex", $tmp); |
|
- | 152 | $ipv6 = substr(preg_replace("/([A-f0-9]{4})/", "$1:", $hex['hex']), 0, -1); |
|
- | 153 | ||
- | 154 | // Remove "fe80::" to convert IPv6 Link Local address back to EUI-64 |
|
- | 155 | // see https://support.lenovo.com/de/de/solutions/ht509925-how-to-convert-a-mac-address-into-an-ipv6-link-local-address-eui-64 |
|
- | 156 | $cnt = 0; |
|
- | 157 | $mac = preg_replace('@^fe80:0000:0000:0000:@i', '', $ipv6, -1, $cnt); |
|
- | 158 | if ($cnt == 0) return false; |
|
- | 159 | ||
- | 160 | // Set LAA to UAA again |
|
- | 161 | $mac[1] = dechex(hexdec($mac[1]) & 253); |
|
- | 162 | ||
- | 163 | return eui64_to_eui48($mac); |
|
- | 164 | } |
|
- | 165 | ||
- | 166 | /** |
|
- | 167 | * @param string $mac |
|
- | 168 | * @return false|int |
|
- | 169 | */ |
|
- | 170 | function eui_bits(string $mac) { |
|
- | 171 | if (!mac_valid($mac)) return false; |
|
- | 172 | $mac = mac_canonize($mac, ''); |
|
- | 173 | return (int)(strlen($mac)*4); |
|
- | 174 | } |
|
- | 175 | ||
- | 176 | /** |
|
- | 177 | * @param string $mac |
|
- | 178 | * @return false|string |
|
- | 179 | */ |
|
- | 180 | function eui_to_ipv6linklocal(string $mac) { |
|
- | 181 | if (!mac_valid($mac)) return false; |
|
- | 182 | if (eui_bits($mac) == 48) { |
|
- | 183 | $mac = eui48_to_eui64($mac); |
|
- | 184 | } |
|
- | 185 | $mac = mac_canonize($mac, ''); |
|
- | 186 | ||
- | 187 | $mac[1] = dechex(hexdec($mac[1]) | 2); |
|
- | 188 | ||
- | 189 | $mac = str_pad($mac, 16, '0', STR_PAD_LEFT); |
|
- | 190 | return strtolower('fe80::'.substr($mac,0, 4).':'.substr($mac,4, 4).':'.substr($mac,8, 4).':'.substr($mac,12, 4)); |
|
- | 191 | } |
|
- | 192 | ||
- | 193 | /** |
|
92 | * @param string $mac |
194 | * @param string $mac |
93 | * @return void |
195 | * @return void |
94 | * @throws Exception |
196 | * @throws Exception |
95 | */ |
197 | */ |
96 | function decode_mac(string $mac) { |
198 | function decode_mac(string $mac) { |
97 | // Amazing website about MAC addresses: https://mac-address.alldatafeeds.com/faq#how-to-recognise-mac-address-application |
199 | // Amazing website about MAC addresses: https://mac-address.alldatafeeds.com/faq#how-to-recognise-mac-address-application |
98 | 200 | ||
- | 201 | echo sprintf("%-32s %s\n", "Input:", $mac); |
|
- | 202 | ||
- | 203 | $type = ''; |
|
- | 204 | $tmp = ipv6linklocal_to_eui64($mac); |
|
- | 205 | if ($tmp !== false) { |
|
- | 206 | $mac = $tmp; |
|
- | 207 | $type = 'IPv6-Link-Local'; |
|
- | 208 | } |
|
99 | if (!mac_valid($mac)) throw new Exception("Invalid MAC address"); |
209 | if (!mac_valid($mac)) throw new Exception("Invalid MAC address"); |
- | 210 | if ($tmp === false) { |
|
- | 211 | // Size |
|
- | 212 | $type = eui_bits($mac)==48 ? 'EUI-48 (6 Byte)' : 'EUI-64 (8 Byte)'; |
|
- | 213 | } |
|
- | 214 | echo sprintf("%-32s %s\n", "Type:", $type); |
|
- | 215 | ||
- | 216 | echo "\n"; |
|
100 | 217 | ||
101 | // Format MAC |
218 | // Format MAC |
102 | $mac = strtoupper($mac); |
219 | $mac = mac_canonize($mac, ''); |
103 | $mac = preg_replace('@[^0-9A-F]@', '', $mac); |
- | |
104 | if (strlen($mac) != 12) { |
- | |
105 | throw new Exception("Invalid MAC address"); |
- | |
106 | } |
- | |
107 | $mac_ = preg_replace('@^(..)(..)(..)(..)(..)(..)$@', '\\1-\\2-\\3-\\4-\\5-\\6', $mac); |
- | |
108 | echo sprintf("%-32s %s\n", "MAC address:", $mac_); |
- | |
109 | 220 | ||
110 | // Empfaengergruppe |
221 | // Show various representations |
111 | $ig = hexdec($mac[1]) & 1; // Bit #LSB+0 of Byte 1 |
222 | $eui48 = eui64_to_eui48($mac); |
- | 223 | echo sprintf("%-32s %s\n", "EUI-48:", (eui_bits($eui48) != 48) ? 'Not available' : $eui48); |
|
- | 224 | $eui64 = eui48_to_eui64($mac); |
|
112 | $ig_ = ($ig == 0) ? '[0] Individual (Unicast)' : '[1] Group (Multicast)'; |
225 | echo sprintf("%-32s %s\n", "EUI-64:", (eui_bits($eui64) != 64) ? 'Not available' : $eui64); |
- | 226 | $ipv6 = eui_to_ipv6linklocal($mac); |
|
113 | echo sprintf("%-32s %s\n", "Transmission type (I/G flag):", $ig_); |
227 | echo sprintf("%-32s %s\n", "IPv6 link local address:", $ipv6); |
114 | 228 | ||
115 | // Vergabestelle |
229 | // Vergabestelle |
116 | $ul = hexdec($mac[1]) & 2; // Bit #LSB+1 of Byte 1 |
230 | $ul = hexdec($mac[1]) & 2; // Bit #LSB+1 of Byte 1 |
117 | $ul_ = ($ul == 0) ? '[0] Universally Administered Address (UAA)' : '[1] Locally Administered Address (LAA)'; |
231 | $ul_ = ($ul == 0) ? '[0] Universally Administered Address (UAA)' : '[1] Locally Administered Address (LAA)'; |
118 | echo sprintf("%-32s %s\n", "Administration type (U/L flag):", $ul_); |
232 | echo sprintf("%-32s %s\n", "Administration type (U/L flag):", $ul_); |
119 | 233 | ||
- | 234 | // Empfaengergruppe |
|
- | 235 | $ig = hexdec($mac[1]) & 1; // Bit #LSB+0 of Byte 1 |
|
- | 236 | $ig_ = ($ig == 0) ? '[0] Individual (Unicast)' : '[1] Group (Multicast)'; |
|
- | 237 | echo sprintf("%-32s %s\n", "Transmission type (I/G flag):", $ig_); |
|
- | 238 | ||
120 | // Query IEEE registries |
239 | // Query IEEE registries |
121 | // TODO: gilt OUI nur bei Individual UAA? |
240 | // TODO: gilt OUI nur bei Individual UAA? |
122 | if (count(glob(IEEE_MAC_REGISTRY.'/*.txt')) > 0) { |
241 | if (count(glob(IEEE_MAC_REGISTRY.'/*.txt')) > 0) { |
123 | if ( |
242 | if ( |
124 | ($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY . '/mam.txt', 'OUI-28 (MA-M)', $mac)) || |
- | |
125 | ($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY . '/oui36.txt', 'OUI-36 (MA-S)', $mac)) || |
- | |
126 | # The IEEE Registration Authority distinguishes between IABs and OUI-36 values. Both are 36-bit values which may be used to generate EUI-48 values, but IABs may not be used to generate EUI-64 values.[6] |
243 | # The IEEE Registration Authority distinguishes between IABs and OUI-36 values. Both are 36-bit values which may be used to generate EUI-48 values, but IABs may not be used to generate EUI-64 values.[6] |
127 | # Note: The Individual Address Block (IAB) is an inactive registry activity, which has been replaced by the MA-S registry product as of January 1, 2014. |
244 | # Note: The Individual Address Block (IAB) is an inactive registry activity, which has been replaced by the MA-S registry product as of January 1, 2014. |
128 | ($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY . '/iab.txt', 'IAB', $mac)) |
245 | ($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY . '/iab.txt', 'IAB', $mac)) || |
- | 246 | ($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY . '/oui36.txt', 'OUI-36 (MA-S)', $mac)) || |
|
- | 247 | ($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY . '/mam.txt', 'OUI-28 (MA-M)', $mac)) || |
|
- | 248 | ($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY . '/oui.txt', 'OUI-24 (MA-L)', $mac)) |
|
129 | ) { |
249 | ) { |
130 | echo $x; |
250 | echo $x; |
131 | } else { |
- | |
132 | echo _lookup_ieee_registry(IEEE_MAC_REGISTRY . '/oui.txt', 'OUI-24 (MA-L)', $mac); |
- | |
133 | } |
251 | } |
134 | } |
252 | } |
135 | 253 | ||
136 | $vm = ''; |
254 | $vm = ''; |
137 | // === FAQ "Detection rules which don't have their dedicated page yet" === |
255 | // === FAQ "Detection rules which don't have their dedicated page yet" === |
Line 264... | Line 382... | ||
264 | // https://www.iana.org/go/rfc1112 |
382 | // https://www.iana.org/go/rfc1112 |
265 | // http://www.cavebear.com/archive/cavebear/Ethernet/Ethernet.txt |
383 | // http://www.cavebear.com/archive/cavebear/Ethernet/Ethernet.txt |
266 | if (mac_between($mac, '01:00:5E:00:00:00', '01:00:5E:7F:FF:FF')) $app = 'IPv4 Multicast (EtherType is 0x0800)'; |
384 | if (mac_between($mac, '01:00:5E:00:00:00', '01:00:5E:7F:FF:FF')) $app = 'IPv4 Multicast (EtherType is 0x0800)'; |
267 | if (mac_between($mac, '33:33:00:00:00:00', '33:33:FF:FF:FF:FF')) $app = 'IPv6 Multicast. IPv6 neighbor discovery (EtherType is 0x86DD)'; // TODO: Dabei werden die untersten 32 Bit der IPv6-Multicast-Adresse in die MAC-Adresse eingebettet. |
385 | if (mac_between($mac, '33:33:00:00:00:00', '33:33:FF:FF:FF:FF')) $app = 'IPv6 Multicast. IPv6 neighbor discovery (EtherType is 0x86DD)'; // TODO: Dabei werden die untersten 32 Bit der IPv6-Multicast-Adresse in die MAC-Adresse eingebettet. |
268 | if (mac_between($mac, '00:00:5E:00:52:13', '00:00:5E:00:52:13')) $app = 'Proxy Mobile IPv6'; |
386 | if (mac_between($mac, '00:00:5E:00:52:13', '00:00:5E:00:52:13')) $app = 'Proxy Mobile IPv6'; |
269 | //if (mac_between($mac, '00:00:5E:FE:C0:00:02:00', '00:00:5E:FE:C0:00:02:FF')) $app = 'IPv4 derived documentation'; |
387 | if (mac_between($mac, '00:00:5E:FE:C0:00:02:00', '00:00:5E:FE:C0:00:02:FF')) $app = 'IPv4 derived documentation'; |
270 | //if (mac_between($mac, '00:00:5E:FE:C6:33:64:00', '00:00:5E:FE:C6:33:64:FF')) $app = 'IPv4 derived documentation'; |
388 | if (mac_between($mac, '00:00:5E:FE:C6:33:64:00', '00:00:5E:FE:C6:33:64:FF')) $app = 'IPv4 derived documentation'; |
271 | //if (mac_between($mac, '00:00:5E:FE:CB:00:71:00', '00:00:5E:FE:CB:00:71:FF')) $app = 'IPv4 derived documentation'; |
389 | if (mac_between($mac, '00:00:5E:FE:CB:00:71:00', '00:00:5E:FE:CB:00:71:FF')) $app = 'IPv4 derived documentation'; |
272 | //if (mac_equals($mac, '00:00:5E:FE:EA:C0:00:02')) $app = 'IPv4 multicast derived documentation'; |
390 | if (mac_equals($mac, '00:00:5E:FE:EA:C0:00:02')) $app = 'IPv4 multicast derived documentation'; |
273 | //if (mac_equals($mac, '00:00:5E:FE:EA:C6:33:64')) $app = 'IPv4 multicast derived documentation'; |
391 | if (mac_equals($mac, '00:00:5E:FE:EA:C6:33:64')) $app = 'IPv4 multicast derived documentation'; |
274 | //if (mac_equals($mac, '00:00:5E:FE:EA:CB:00:71')) $app = 'IPv4 multicast derived documentation'; |
392 | if (mac_equals($mac, '00:00:5E:FE:EA:CB:00:71')) $app = 'IPv4 multicast derived documentation'; |
275 | //if (mac_between($mac, '01:00:5E:FE:C0:00:02:00', '01:00:5E:FE:C0:00:02:FF')) $app = 'IPv4 derived documentation'; |
393 | if (mac_between($mac, '01:00:5E:FE:C0:00:02:00', '01:00:5E:FE:C0:00:02:FF')) $app = 'IPv4 derived documentation'; |
276 | //if (mac_between($mac, '01:00:5E:FE:C6:33:64:00', '01:00:5E:FE:C6:33:64:FF')) $app = 'IPv4 derived documentation'; |
394 | if (mac_between($mac, '01:00:5E:FE:C6:33:64:00', '01:00:5E:FE:C6:33:64:FF')) $app = 'IPv4 derived documentation'; |
277 | //if (mac_between($mac, '01:00:5E:FE:CB:00:71:00', '01:00:5E:FE:CB:00:71:FF')) $app = 'IPv4 derived documentation'; |
395 | if (mac_between($mac, '01:00:5E:FE:CB:00:71:00', '01:00:5E:FE:CB:00:71:FF')) $app = 'IPv4 derived documentation'; |
278 | //if (mac_equals($mac, '01:00:5E:FE:EA:C0:00:02')) $app = 'IPv4 multicast derived documentation'; |
396 | if (mac_equals($mac, '01:00:5E:FE:EA:C0:00:02')) $app = 'IPv4 multicast derived documentation'; |
279 | //if (mac_equals($mac, '01:00:5E:FE:EA:C6:33:64')) $app = 'IPv4 multicast derived documentation'; |
397 | if (mac_equals($mac, '01:00:5E:FE:EA:C6:33:64')) $app = 'IPv4 multicast derived documentation'; |
280 | //if (mac_equals($mac, '01:00:5E:FE:EA:CB:00:71')) $app = 'IPv4 multicast derived documentation'; |
398 | if (mac_equals($mac, '01:00:5E:FE:EA:CB:00:71')) $app = 'IPv4 multicast derived documentation'; |
281 | if (mac_between($mac, '01:80:C2:00:00:20', '01:80:C2:00:00:2F')) $app = 'Reserved for use by Multiple Registration Protocol (MRP) applications'; |
399 | if (mac_between($mac, '01:80:C2:00:00:20', '01:80:C2:00:00:2F')) $app = 'Reserved for use by Multiple Registration Protocol (MRP) applications'; |
282 | //if (mac_between($mac, '02:00:5E:FE:00:00:00:00', '02:00:5E:FE:FF:FF:FF:FF')) $app = 'IPv4 Addr Holders'; |
400 | if (mac_between($mac, '02:00:5E:FE:00:00:00:00', '02:00:5E:FE:FF:FF:FF:FF')) $app = 'IPv4 Addr Holders'; |
283 | if (mac_equals($mac, '03:00:00:20:00:00')) $app = 'IP multicast address'; |
401 | if (mac_equals($mac, '03:00:00:20:00:00')) $app = 'IP multicast address'; |
284 | if (mac_equals($mac, 'C0:00:00:04:00:00')) $app = 'IP multicast address'; |
402 | if (mac_equals($mac, 'C0:00:00:04:00:00')) $app = 'IP multicast address'; |
285 | //if (mac_between($mac, '03:00:5E:FE:00:00:00:00', '03:00:5E:FE:FF:FF:FF:FF')) $app = 'IPv4 Addr Holders'; |
403 | if (mac_between($mac, '03:00:5E:FE:00:00:00:00', '03:00:5E:FE:FF:FF:FF:FF')) $app = 'IPv4 Addr Holders'; |
286 | 404 | ||
287 | // === FAQ "How to recognise a MPLS multicast frame by MAC address?" === |
405 | // === FAQ "How to recognise a MPLS multicast frame by MAC address?" === |
288 | // http://www.iana.org/go/rfc5332 |
406 | // http://www.iana.org/go/rfc5332 |
289 | // http://www.iana.org/go/rfc7213 |
407 | // http://www.iana.org/go/rfc7213 |
290 | if (mac_between($mac, '01:00:5E:80:00:00', '01:00:5E:8F:FF:FF')) $app = 'MPLS multicast (EtherType is 0x8847 or 0x8848)'; |
408 | if (mac_between($mac, '01:00:5E:80:00:00', '01:00:5E:8F:FF:FF')) $app = 'MPLS multicast (EtherType is 0x8847 or 0x8848)'; |
Line 447... | Line 565... | ||
447 | if (mac_between($mac, '00:00:5E:00:52:01', '00:00:5E:00:52:01')) $app = 'PacketPWEthB'; |
565 | if (mac_between($mac, '00:00:5E:00:52:01', '00:00:5E:00:52:01')) $app = 'PacketPWEthB'; |
448 | if (mac_between($mac, '00:00:5E:00:52:02', '00:00:5E:00:52:12')) $app = 'Unassigned (small allocations)'; |
566 | if (mac_between($mac, '00:00:5E:00:52:02', '00:00:5E:00:52:12')) $app = 'Unassigned (small allocations)'; |
449 | if (mac_between($mac, '00:00:5E:00:53:00', '00:00:5E:00:53:FF')) $app = 'Assigned for use in documentation'; |
567 | if (mac_between($mac, '00:00:5E:00:53:00', '00:00:5E:00:53:FF')) $app = 'Assigned for use in documentation'; |
450 | if (mac_between($mac, '00:00:5E:00:54:00', '00:00:5E:90:00:FF')) $app = 'Unassigned'; |
568 | if (mac_between($mac, '00:00:5E:00:54:00', '00:00:5E:90:00:FF')) $app = 'Unassigned'; |
451 | if (mac_between($mac, '00:00:5E:90:01:01', '00:00:5E:90:01:FF')) $app = 'Unassigned (small allocations requiring both unicast and multicast)'; |
569 | if (mac_between($mac, '00:00:5E:90:01:01', '00:00:5E:90:01:FF')) $app = 'Unassigned (small allocations requiring both unicast and multicast)'; |
452 | //if (mac_between($mac, '00:00:5E:EF:10:00:00:00', '00:00:5E:EF:10:00:00:FF')) $app = 'General documentation'; |
570 | if (mac_between($mac, '00:00:5E:EF:10:00:00:00', '00:00:5E:EF:10:00:00:FF')) $app = 'General documentation'; |
453 | //if (mac_between($mac, '00:00:5E:FF:FE:00:53:00', '00:00:5E:FF:FE:00:53:FF')) $app = 'EUI-48 derived documentation'; |
571 | if (mac_between($mac, '00:00:5E:FF:FE:00:53:00', '00:00:5E:FF:FE:00:53:FF')) $app = 'EUI-48 derived documentation'; |
454 | if (mac_between($mac, '01:00:5E:00:00:00', '01:00:5E:7F:FF:FF')) $app = 'DoD Internet Multicast (EtherType is 0x0800)'; // TODO: IPv4-Multicast (Dabei werden dann die unteren 23 Bit der IP-Multicast-Adresse direkt auf die untersten 23 Bit der MAC-Adresse abgebildet. Der IP-Multicast-Adresse 224.0.0.1 ist somit die Multicast-MAC-Adresse 01-00-5e-00-00-01 fest zugeordnet.) |
572 | if (mac_between($mac, '01:00:5E:00:00:00', '01:00:5E:7F:FF:FF')) $app = 'DoD Internet Multicast (EtherType is 0x0800)'; // TODO: IPv4-Multicast (Dabei werden dann die unteren 23 Bit der IP-Multicast-Adresse direkt auf die untersten 23 Bit der MAC-Adresse abgebildet. Der IP-Multicast-Adresse 224.0.0.1 ist somit die Multicast-MAC-Adresse 01-00-5e-00-00-01 fest zugeordnet.) |
455 | if (mac_between($mac, '01:00:5E:80:00:00', '01:00:5E:FF:FF:FF')) $app = 'DoD Internet'; |
573 | if (mac_between($mac, '01:00:5E:80:00:00', '01:00:5E:FF:FF:FF')) $app = 'DoD Internet'; |
456 | if (mac_equals($mac, '01:00:5E:90:00:02')) $app = 'AllL1MI-ISs'; |
574 | if (mac_equals($mac, '01:00:5E:90:00:02')) $app = 'AllL1MI-ISs'; |
457 | if (mac_equals($mac, '01:00:5E:90:00:03')) $app = 'AllL2MI-ISs'; |
575 | if (mac_equals($mac, '01:00:5E:90:00:03')) $app = 'AllL2MI-ISs'; |
458 | if (mac_between($mac, '01:00:5E:90:00:04', '01:00:5E:90:00:FF')) $app = 'Unassigned (small allocations)'; |
576 | if (mac_between($mac, '01:00:5E:90:00:04', '01:00:5E:90:00:FF')) $app = 'Unassigned (small allocations)'; |
459 | if (mac_between($mac, '01:00:5E:90:01:01', '01:00:5E:90:01:FF')) $app = 'Unassigned (small allocations requiring both unicast and multicast)'; |
577 | if (mac_between($mac, '01:00:5E:90:01:01', '01:00:5E:90:01:FF')) $app = 'Unassigned (small allocations requiring both unicast and multicast)'; |
460 | if (mac_between($mac, '01:00:5E:90:02:00', '01:00:5E:90:0F:FF')) $app = 'Unassigned'; |
578 | if (mac_between($mac, '01:00:5E:90:02:00', '01:00:5E:90:0F:FF')) $app = 'Unassigned'; |
461 | if (mac_between($mac, '01:00:5E:90:02:00', '00:00:5E:FF:FF:FF')) $app = 'Unassigned'; |
579 | if (mac_between($mac, '01:00:5E:90:02:00', '00:00:5E:FF:FF:FF')) $app = 'Unassigned'; |
462 | if (mac_between($mac, '01:00:5E:90:10:00', '01:00:5E:90:10:FF')) $app = 'Documentation'; |
580 | if (mac_between($mac, '01:00:5E:90:10:00', '01:00:5E:90:10:FF')) $app = 'Documentation'; |
463 | if (mac_between($mac, '01:00:5E:90:11:00', '01:00:5E:FF:FF:FF')) $app = 'Unassigned'; |
581 | if (mac_between($mac, '01:00:5E:90:11:00', '01:00:5E:FF:FF:FF')) $app = 'Unassigned'; |
464 | //if (mac_between($mac, '01:00:5E:EF:10:00:00:00', '01:00:5E:EF:10:00:00:FF')) $app = 'General documentation'; |
582 | if (mac_between($mac, '01:00:5E:EF:10:00:00:00', '01:00:5E:EF:10:00:00:FF')) $app = 'General documentation'; |
465 | //if (mac_between($mac, '02:00:5E:00:00:00:00:00', '02:00:5E:0F:FF:FF:FF:FF')) $app = 'Reserved'; |
583 | if (mac_between($mac, '02:00:5E:00:00:00:00:00', '02:00:5E:0F:FF:FF:FF:FF')) $app = 'Reserved'; |
466 | //if (mac_between($mac, '02:00:5E:10:00:00:00:00', '02:00:5E:10:00:00:00:FF')) $app = 'Documentation'; |
584 | if (mac_between($mac, '02:00:5E:10:00:00:00:00', '02:00:5E:10:00:00:00:FF')) $app = 'Documentation'; |
467 | //if (mac_between($mac, '02:00:5E:10:00:00:01:00', '02:00:5E:EF:FF:FF:FF:FF')) $app = 'Unassigned'; |
585 | if (mac_between($mac, '02:00:5E:10:00:00:01:00', '02:00:5E:EF:FF:FF:FF:FF')) $app = 'Unassigned'; |
468 | //if (mac_between($mac, '02:00:5E:F0:00:00:00:00', '02:00:5E:FD:FF:FF:FF:FF')) $app = 'Reserved'; |
586 | if (mac_between($mac, '02:00:5E:F0:00:00:00:00', '02:00:5E:FD:FF:FF:FF:FF')) $app = 'Reserved'; |
469 | //if (mac_between($mac, '02:00:5E:FE:00:00:00:00', '02:00:5E:FE:FF:FF:FF:FF')) $app = 'IPv4 Addr Holders'; |
587 | if (mac_between($mac, '02:00:5E:FE:00:00:00:00', '02:00:5E:FE:FF:FF:FF:FF')) $app = 'IPv4 Addr Holders'; |
470 | //if (mac_between($mac, '02:00:5E:FF:00:00:00:00', '02:00:5E:FF:FD:FF:FF:FF')) $app = 'Reserved'; |
588 | if (mac_between($mac, '02:00:5E:FF:00:00:00:00', '02:00:5E:FF:FD:FF:FF:FF')) $app = 'Reserved'; |
471 | //if (mac_between($mac, '02:00:5E:FF:FE:00:00:00', '02:00:5E:FF:FE:FF:FF:FF')) $app = 'IANA EUI-48 Holders'; |
589 | if (mac_between($mac, '02:00:5E:FF:FE:00:00:00', '02:00:5E:FF:FE:FF:FF:FF')) $app = 'IANA EUI-48 Holders'; |
472 | //if (mac_between($mac, '02:00:5E:FF:FF:00:00:00', '02:00:5E:FF:FF:FF:FF:FF')) $app = 'Reserved'; |
590 | if (mac_between($mac, '02:00:5E:FF:FF:00:00:00', '02:00:5E:FF:FF:FF:FF:FF')) $app = 'Reserved'; |
473 | //if (mac_between($mac, '03:00:5E:00:00:00:00:00', '03:00:5E:0F:FF:FF:FF:FF')) $app = 'Reserved'; |
591 | if (mac_between($mac, '03:00:5E:00:00:00:00:00', '03:00:5E:0F:FF:FF:FF:FF')) $app = 'Reserved'; |
474 | //if (mac_between($mac, '03:00:5E:10:00:00:00:00', '03:00:5E:10:00:00:00:FF')) $app = 'Documentation'; |
592 | if (mac_between($mac, '03:00:5E:10:00:00:00:00', '03:00:5E:10:00:00:00:FF')) $app = 'Documentation'; |
475 | //if (mac_between($mac, '03:00:5E:10:00:00:01:00', '03:00:5E:EF:FF:FF:FF:FF')) $app = 'Unassigned'; |
593 | if (mac_between($mac, '03:00:5E:10:00:00:01:00', '03:00:5E:EF:FF:FF:FF:FF')) $app = 'Unassigned'; |
476 | //if (mac_between($mac, '03:00:5E:F0:00:00:00:00', '03:00:5E:FD:FF:FF:FF:FF')) $app = 'Reserved'; |
594 | if (mac_between($mac, '03:00:5E:F0:00:00:00:00', '03:00:5E:FD:FF:FF:FF:FF')) $app = 'Reserved'; |
477 | //if (mac_between($mac, '03:00:5E:FF:00:00:00:00', '03:00:5E:FF:FD:FF:FF:FF')) $app = 'Reserved'; |
595 | if (mac_between($mac, '03:00:5E:FF:00:00:00:00', '03:00:5E:FF:FD:FF:FF:FF')) $app = 'Reserved'; |
478 | //if (mac_between($mac, '03:00:5E:FF:FE:00:00:00', '03:00:5E:FF:FE:FF:FF:FF')) $app = 'IANA EUI-48 Holders'; |
596 | if (mac_between($mac, '03:00:5E:FF:FE:00:00:00', '03:00:5E:FF:FE:FF:FF:FF')) $app = 'IANA EUI-48 Holders'; |
479 | //if (mac_between($mac, '03:00:5E:FF:FF:00:00:00', '03:00:5E:FF:FF:FF:FF:FF')) $app = 'Reserved'; |
597 | if (mac_between($mac, '03:00:5E:FF:FF:00:00:00', '03:00:5E:FF:FF:FF:FF:FF')) $app = 'Reserved'; |
480 | 598 | ||
481 | // === FAQ "How to recognise a Cisco's MAC address application?" === |
599 | // === FAQ "How to recognise a Cisco's MAC address application?" === |
482 | // https://www.cisco.com/c/en/us/support/docs/switches/catalyst-4500-series-switches/13414-103.html |
600 | // https://www.cisco.com/c/en/us/support/docs/switches/catalyst-4500-series-switches/13414-103.html |
483 | // https://tools.ietf.org/html/rfc1060 |
601 | // https://tools.ietf.org/html/rfc1060 |
484 | // https://en.wikipedia.org/wiki/Multicast_address#cite_note-15 |
602 | // https://en.wikipedia.org/wiki/Multicast_address#cite_note-15 |
Line 526... | Line 644... | ||
526 | if (mac_equals($mac, 'AB:00:00:03:00:00')) $app = 'DECNET Phase IV end node, EtherType is 0x6003'; |
644 | if (mac_equals($mac, 'AB:00:00:03:00:00')) $app = 'DECNET Phase IV end node, EtherType is 0x6003'; |
527 | if (mac_equals($mac, 'AB:00:00:04:00:00')) $app = 'DECNET Phase IV Router, EtherType is 0x6003'; |
645 | if (mac_equals($mac, 'AB:00:00:04:00:00')) $app = 'DECNET Phase IV Router, EtherType is 0x6003'; |
528 | if (mac_between($mac, 'AB:00:00:05:00:00', 'AB:00:03:FF:FF:FF')) $app = 'Reserved DEC'; |
646 | if (mac_between($mac, 'AB:00:00:05:00:00', 'AB:00:03:FF:FF:FF')) $app = 'Reserved DEC'; |
529 | if (mac_equals($mac, 'AB:00:03:00:00:00')) $app = 'DEC Local Area Transport (LAT) - old, EtherType is 0x6004'; |
647 | if (mac_equals($mac, 'AB:00:03:00:00:00')) $app = 'DEC Local Area Transport (LAT) - old, EtherType is 0x6004'; |
530 | if (mac_between($mac, 'AB:00:04:00:00:00', 'AB:00:04:00:FF:FF')) $app = 'Reserved DEC customer private use'; |
648 | if (mac_between($mac, 'AB:00:04:00:00:00', 'AB:00:04:00:FF:FF')) $app = 'Reserved DEC customer private use'; |
531 | if (mac_between($mac, 'AB:00:04:01:00:00', 'AB:00:04:01:FF:FF')) $app = 'DEC Local Area VAX Cluster groups System Communication Architecture (SCA) EtherType is 0x6007'; |
649 | if (mac_between($mac, 'AB:00:04:01:00:00', 'AB:00:04:01:FF:FF')) $app = 'DEC Local Area VAX Cluster groups System Communication Architecture (SCA), EtherType is 0x6007'; |
532 | 650 | ||
533 | if ($app) { |
651 | if ($app) { |
534 | echo sprintf("%-32s %s\n", "Special use:", $app); |
652 | echo sprintf("%-32s %s\n", "Special use:", $app); |
535 | } |
653 | } |
536 | 654 | ||
Line 538... | Line 656... | ||
538 | 656 | ||
539 | /** |
657 | /** |
540 | * @param string $mac1 |
658 | * @param string $mac1 |
541 | * @param string $mac2 |
659 | * @param string $mac2 |
542 | * @return bool |
660 | * @return bool |
543 | * @throws Exception |
- | |
544 | */ |
661 | */ |
545 | function mac_equals(string $mac1, string $mac2): bool { |
662 | function mac_equals(string $mac1, string $mac2): bool { |
- | 663 | $mac1test = eui64_to_eui48($mac1); |
|
- | 664 | if ($mac1test === false) return false; |
|
- | 665 | $mac2test = eui64_to_eui48($mac2); |
|
- | 666 | if ($mac2test === false) return false; |
|
- | 667 | ||
- | 668 | if (eui_bits($mac1test) != eui_bits($mac2test)) { |
|
- | 669 | $mac1test = eui48_to_eui64($mac1); |
|
- | 670 | $mac2test = eui48_to_eui64($mac2); |
|
- | 671 | } |
|
- | 672 | ||
546 | return mac_between($mac1, $mac2, $mac2); |
673 | return mac_canonize($mac1test) == mac_canonize($mac2test); |
547 | } |
674 | } |
548 | 675 | ||
549 | /** |
676 | /** |
550 | * @param string $mac |
677 | * @param string $mac |
551 | * @param string $low |
678 | * @param string $low |
552 | * @param string $high |
679 | * @param string $high |
553 | * @return bool |
680 | * @return bool |
554 | * @throws Exception |
- | |
555 | */ |
681 | */ |
556 | function mac_between(string $mac, string $low, string $high): bool { |
682 | function mac_between(string $mac, string $low, string $high): bool { |
- | 683 | $mactest = eui64_to_eui48($mac); |
|
557 | if (empty($high)) $high = $low; |
684 | if ($mactest === false) return false; |
- | 685 | $lowtest = eui64_to_eui48($low); |
|
- | 686 | if ($lowtest === false) return false; |
|
- | 687 | $hightest = eui64_to_eui48($high); |
|
- | 688 | if ($hightest === false) return false; |
|
558 | 689 | ||
559 | if (!mac_valid($mac)) throw new Exception("Invalid MAC: $mac"); |
690 | if ((eui_bits($mactest) != eui_bits($lowtest)) || (eui_bits($lowtest) != eui_bits($hightest))) { |
- | 691 | $mactest = eui48_to_eui64($mac); |
|
560 | if (!mac_valid($low)) throw new Exception("Invalid MAC: $low"); |
692 | $lowtest = eui48_to_eui64($low); |
561 | if (!mac_valid($high)) throw new Exception("Invalid MAC: $high"); |
693 | $hightest = eui48_to_eui64($high); |
- | 694 | } |
|
562 | 695 | ||
563 | $mac = strtoupper(preg_replace('@[^0-9A-F]@', '', $mac)); |
696 | $mactest = strtoupper(preg_replace('@[^0-9A-F]@', '', $mactest)); |
564 | $low = strtoupper(preg_replace('@[^0-9A-F]@', '', $low)); |
697 | $lowtest = strtoupper(preg_replace('@[^0-9A-F]@', '', $lowtest)); |
565 | $high = strtoupper(preg_replace('@[^0-9A-F]@', '', $high)); |
698 | $hightest = strtoupper(preg_replace('@[^0-9A-F]@', '', $hightest)); |
566 | 699 | ||
567 | $mac = gmp_init($mac, 16); |
700 | $mactest = gmp_init($mactest, 16); |
568 | $low = gmp_init($low, 16); |
701 | $lowtest = gmp_init($lowtest, 16); |
569 | $high = gmp_init($high, 16); |
702 | $hightest = gmp_init($hightest, 16); |
570 | 703 | ||
571 | return (gmp_cmp($mac, $low) >= 0) && (gmp_cmp($mac, $high) <= 0); |
704 | return (gmp_cmp($mactest, $lowtest) >= 0) && (gmp_cmp($mactest, $hightest) <= 0); |
572 | } |
705 | } |
573 | 706 |