Subversion Repositories oidplus

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
226 daniel-mar 1
<?php
2
 
3
/*
4
 * MAC utils for PHP
5
 * Copyright 2017 Daniel Marschall, ViaThinkSoft
6
 * Version 19 August 2017
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
 
21
define('IEEE_MAC_REGISTRY', __DIR__ . '/web-data');
22
 
23
function mac_valid($mac) {
24
        $mac = str_replace(array('-', ':'), '', $mac);
25
        $mac = strtoupper($mac);
26
 
27
        if (strlen($mac) != 12) return false;
28
 
29
        $mac = preg_replace('@[0-9A-F]@', '', $mac);
30
 
31
        return ($mac == '');
32
}
33
 
34
function _lookup_ieee_registry($file, $oui_name, $mac) {
35
        $begin = substr($mac, 0, 2).'-'.substr($mac, 2, 2).'-'.substr($mac, 4, 2);
36
        $f = file_get_contents($file);
37
 
38
        $f = str_replace("\r", '', $f);
39
 
40
        # We are using a positive-lookahead because entries like the MA-M references have a blank line between organization and address
41
        preg_match_all('@^\s*'.preg_quote($begin, '@').'\s+\(hex\)\s+(\S+)\s+(.*)\n\n\s*(?=[0-9A-F])@ismU', "$f\n\nA", $m, PREG_SET_ORDER);
42
        foreach ($m as $n) {
43
                preg_match('@(\S+)\s+\(base 16\)(.*)$@ism', $n[2], $m);
44
 
45
                if (preg_match('@(.+)\-(.+)@ism', $m[1], $o)) {
46
                        $z = hexdec(substr($mac, 6, 6));
47
                        $beg = hexdec($o[1]);
48
                        $end = hexdec($o[2]);
49
                        if (($z < $beg) || ($z > $end)) continue;
50
                } else {
51
                        $beg = 0x000000;
52
                        $end = 0xFFFFFF;
53
                }
54
 
55
                $x = trim(preg_replace('@^\s+@ism', '', $m[2]));
56
 
57
                # "PRIVATE" entries are only marked at the "(hex)" line, but not at the "(base16)" line
58
                if ($x == '') $x = trim($n[1]);
59
 
60
                $x = explode("\n", $x);
61
 
62
                $ra_len = strlen(dechex($end-$beg));
63
 
64
                $out = '';
65
                $out .= sprintf("%-24s 0x%s\n", "IEEE $oui_name part:", substr($mac, 0, 12-$ra_len));
66
                $out .= sprintf("%-24s 0x%s\n", "NIC specific part:", substr($mac, 12-$ra_len));
67
                $out .= sprintf("%-24s %s\n", "Registrant:", $x[0]);
68
                foreach ($x as $n => $y) {
69
                        if ($n == 0) continue;
70
                        else if ($n == 1) $out .= sprintf("%-24s %s\n", "Address of registrant:", $y);
71
                        else if ($n >= 2) $out .= sprintf("%-24s %s\n", "", $y);
72
                }
73
 
74
                // TODO: also print the date of last update of the OUI files
75
 
76
                return $out;
77
        }
78
 
79
        return false;
80
}
81
 
82
function decode_mac($mac) {
83
        if (!mac_valid($mac)) return false;
84
 
85
        // Format MAC
86
        $mac = strtoupper($mac);
87
        $mac = preg_replace('@[^0-9A-F]@', '', $mac);
88
        if (strlen($mac) != 12) {
89
                # echo "Invalid MAC address\n";
90
                return false;
91
        }
92
        $mac_ = preg_replace('@^(..)(..)(..)(..)(..)(..)$@', '\\1-\\2-\\3-\\4-\\5-\\6', $mac);
93
        echo sprintf("%-24s %s\n", "MAC address:", $mac_);
94
 
95
        // Empfaengergruppe
96
        $ig = hexdec($mac[1]) & 1; // Bit #LSB+0 of Byte 1
97
        $ig_ = ($ig == 0) ? '[0] Individual' : '[1] Group';
98
        echo sprintf("%-24s %s\n", "I/G flag:", $ig_);
99
 
100
        // Vergabestelle
101
        $ul = hexdec($mac[1]) & 2; // Bit #LSB+1 of Byte 1
102
        $ul_ = ($ul == 0) ? '[0] Universally Administered Address (UAA)' : '[1] Locally Administered Address (LAA)';
103
        echo sprintf("%-24s %s\n", "U/L flag:", $ul_);
104
 
105
        // Query IEEE registries
106
        // TODO: gilt OUI nur bei Individual UAA?
107
        if (
108
                ($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY.'/mam.txt', 'OUI-28 (MA-M)', $mac)) ||
109
                ($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY.'/oui36.txt', 'OUI-36 (MA-S)', $mac)) ||
110
                # 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]
111
                # 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.
112
                ($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY.'/iab.txt', 'IAB', $mac))
113
           ) {
114
                return $x;
115
        } else {
116
                return _lookup_ieee_registry(IEEE_MAC_REGISTRY.'/oui.txt', 'OUI-24 (MA-L)', $mac);
117
        }
118
 
119
        // TODO
120
        // FF-FF-FF-FF-FF-FF = Broadcast-Adresse
121
 
122
        // TODO
123
        // IP-Multicast
124
        // 01-00-5E-00-00-00 bis 01-00-5E-7F-FF-FF (unterste 23 bit der MAC = unterste 23 Bit der IP) ...
125
        //      224.0.0.1 -> 01-00-5e-00-00-01
126
        //      erste 4 Bits durch Class D konvention belegt. 5 bits sind unbekannt
127
 
128
        // TODO: VRRP
129
        // 00-00-5E-00-01-ID
130
}