Subversion Repositories uuid_mac_utils

Rev

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