Subversion Repositories uuid_mac_utils

Compare Revisions

Regard whitespace Rev 1 → Rev 2

/trunk/includes/mac_utils.inc.phps
0,0 → 1,130
<?php
 
/*
* MAC utils for PHP
* Copyright 2017 Daniel Marschall, ViaThinkSoft
* Version 19 August 2017
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
define('IEEE_MAC_REGISTRY', __DIR__ . '/../web-data');
 
function mac_valid($mac) {
$mac = str_replace(array('-', ':'), '', $mac);
$mac = strtoupper($mac);
 
if (strlen($mac) != 12) return false;
 
$mac = preg_replace('@[0-9A-F]@', '', $mac);
 
return ($mac == '');
}
 
function _lookup_ieee_registry($file, $oui_name, $mac) {
$begin = substr($mac, 0, 2).'-'.substr($mac, 2, 2).'-'.substr($mac, 4, 2);
$f = file_get_contents($file);
 
$f = str_replace("\r", '', $f);
 
# We are using a positive-lookahead because entries like the MA-M references have a blank line between organization and address
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);
foreach ($m as $n) {
preg_match('@(\S+)\s+\(base 16\)(.*)$@ism', $n[2], $m);
 
if (preg_match('@(.+)\-(.+)@ism', $m[1], $o)) {
$z = hexdec(substr($mac, 6, 6));
$beg = hexdec($o[1]);
$end = hexdec($o[2]);
if (($z < $beg) || ($z > $end)) continue;
} else {
$beg = 0x000000;
$end = 0xFFFFFF;
}
 
$x = trim(preg_replace('@^\s+@ism', '', $m[2]));
 
# "PRIVATE" entries are only marked at the "(hex)" line, but not at the "(base16)" line
if ($x == '') $x = trim($n[1]);
 
$x = explode("\n", $x);
 
$ra_len = strlen(dechex($end-$beg));
 
$out = '';
$out .= sprintf("%-24s 0x%s\n", "IEEE $oui_name part:", substr($mac, 0, 12-$ra_len));
$out .= sprintf("%-24s 0x%s\n", "NIC specific part:", substr($mac, 12-$ra_len));
$out .= sprintf("%-24s %s\n", "Registrant:", $x[0]);
foreach ($x as $n => $y) {
if ($n == 0) continue;
else if ($n == 1) $out .= sprintf("%-24s %s\n", "Address of registrant:", $y);
else if ($n >= 2) $out .= sprintf("%-24s %s\n", "", $y);
}
 
// TODO: also print the date of last update of the OUI files
 
return $out;
}
 
return false;
}
 
function decode_mac($mac) {
if (!mac_valid($mac)) return false;
 
// Format MAC
$mac = strtoupper($mac);
$mac = preg_replace('@[^0-9A-F]@', '', $mac);
if (strlen($mac) != 12) {
# echo "Invalid MAC address\n";
return false;
}
$mac_ = preg_replace('@^(..)(..)(..)(..)(..)(..)$@', '\\1-\\2-\\3-\\4-\\5-\\6', $mac);
echo sprintf("%-24s %s\n", "MAC address:", $mac_);
 
// Empfaengergruppe
$ig = hexdec($mac[1]) & 1; // Bit #LSB+0 of Byte 1
$ig_ = ($ig == 0) ? '[0] Individual' : '[1] Group';
echo sprintf("%-24s %s\n", "I/G flag:", $ig_);
 
// Vergabestelle
$ul = hexdec($mac[1]) & 2; // Bit #LSB+1 of Byte 1
$ul_ = ($ul == 0) ? '[0] Universally Administered Address (UAA)' : '[1] Locally Administered Address (LAA)';
echo sprintf("%-24s %s\n", "U/L flag:", $ul_);
 
// Query IEEE registries
// TODO: gilt OUI nur bei Individual UAA?
if (
($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY.'/mam.txt', 'OUI-28 (MA-M)', $mac)) ||
($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY.'/oui36.txt', 'OUI-36 (MA-S)', $mac)) ||
# 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]
# 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.
($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY.'/iab.txt', 'IAB', $mac))
) {
return $x;
} else {
return _lookup_ieee_registry(IEEE_MAC_REGISTRY.'/oui.txt', 'OUI-24 (MA-L)', $mac);
}
 
// TODO
// FF-FF-FF-FF-FF-FF = Broadcast-Adresse
 
// TODO
// IP-Multicast
// 01-00-5E-00-00-00 bis 01-00-5E-7F-FF-FF (unterste 23 bit der MAC = unterste 23 Bit der IP) ...
// 224.0.0.1 -> 01-00-5e-00-00-01
// erste 4 Bits durch Class D konvention belegt. 5 bits sind unbekannt
 
// TODO: VRRP
// 00-00-5E-00-01-ID
}