Subversion Repositories uuid_mac_utils

Compare Revisions

Regard whitespace Rev 24 → Rev 25

/trunk/TODO
File deleted
/trunk/includes/mac_utils.inc.php
3,7 → 3,7
/*
* MAC (EUI-48 and EUI-64) utils for PHP
* Copyright 2017 - 2023 Daniel Marschall, ViaThinkSoft
* Version 2023-05-06
* Version 2023-07-11
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
76,11 → 76,11
 
/**
* @param string $file
* @param string $oui_name
* @param string $registry_name
* @param string $mac
* @return false|string
*/
function _lookup_ieee_registry(string $file, string $oui_name, string $mac) {
function _lookup_ieee_registry(string $file, string $registry_name, string $mac) {
$mac = mac_canonize($mac, '');
if ($mac === false) return false;
$begin = substr($mac, 0, 2).'-'.substr($mac, 2, 2).'-'.substr($mac, 4, 2);
110,11 → 110,17
 
$x = explode("\n", $x);
 
$ra_len = strlen(dechex($end-$beg));
// The 12 is hardcoded and is valid for MAC-48 and MAC-64!
// Reason: The length of the prefix is calculated from MAC-48. MAC-64 just extends the vendor-specific part
// end-beg (= range) OUI24 0xFFFFFF len=6 12-6 = 6 nibbles prefix
// OUI28 0xFFFFF len=5 12-5 = 7 nibbles prefix
// OUI36 0xFFF len=3 12-3 = 9 nibbles prefix
$prefix_len = 12-strlen(dechex($end-$beg));
 
$out = sprintf("%-32s 0x%s\n", "IEEE $oui_name:", substr($mac, 0, 12-$ra_len));
$out .= sprintf("%-32s 0x%s\n", "Vendor-specific part:", substr($mac, 12-$ra_len));
$out = sprintf("%-32s 0x%s\n", "IEEE $registry_name:", substr($mac, 0, $prefix_len));
$out .= sprintf("%-32s 0x%s\n", "Vendor-specific part:", substr($mac, $prefix_len));
$out .= sprintf("%-32s %s\n", "Registrant:", $x[0]);
 
foreach ($x as $n => $y) {
if ($n == 0) continue;
else if ($n == 1) $out .= sprintf("%-32s %s\n", "Address of registrant:", $y);
263,7 → 269,7
// Format MAC for machine readability
$mac = mac_canonize($mac, '');
 
/**
/*
*
* ZYXM
* 0 0000 EUI (OUI)
365,9 → 371,7
}
 
if ((hexdec($mac[1])&1) == 1) {
// Question: https://networkengineering.stackexchange.com/questions/83121/can-eli-aai-sai-addresses-be-multicast
// Are there "Multicast ELI", "Multicast AAI", "Multicast SAI"?
// Some documents of IEEE suggest this, but I am not 100% sure!
// see also https://networkengineering.stackexchange.com/questions/83121/can-eli-aai-sai-addresses-be-multicast
 
/* https://standards.ieee.org/wp-content/uploads/import/documents/tutorials/eui.pdf writes:
* - The assignee of an OUI or OUI-36 is exclusively authorized to assign group
379,7 → 383,7
* extended identifier is an ELI.
*/
 
// TODO: If "Multicast EUI" is not an EUI, how should we name it instead?!
// TODO: If "Multicast EUI" is not an EUI (as tutorials/eui.pdf states), how should we name it instead?!
$type = "Multicast $type";
}
 
406,13 → 410,19
 
echo "\n";
 
$is_eli_unicast = (hexdec($mac[1]) & 0xF) == 0xA; // ELI = 1010 (unicast)
$is_eli = (hexdec($mac[1]) & 0xE) == 0xA; // ELI = 101x (unicast and multicast)
 
$is_eui_unicast = (hexdec($mac[1]) & 0x3) == 0x0; // EUI = xx00 (unicast)
$is_eui = (hexdec($mac[1]) & 0x2) == 0x0; // EUI = xx0x (unicast and multicast)
 
// Show various representations
if ($mac[1] == 'A') {
if ($is_eli) {
// Note: There does not seem to exist an algorithm for encapsulating/converting ELI-48 <=> ELI-64
echo sprintf("%-32s %s\n", "ELI-".eui_bits($mac).":", mac_canonize($mac));
$mac48 = eui64_to_eui48($mac);
echo sprintf("%-32s %s\n", "MAC-48 (Local):", (eui_bits($mac48) != 48) ? 'Not available' : $mac48);
} else if (($mac[1] == '0') || ($mac[1] == '4') || ($mac[1] == '8') || ($mac[1] == 'C')) {
} else if ($is_eui) {
$eui48 = eui64_to_eui48($mac);
echo sprintf("%-32s %s\n", "EUI-48 or MAC-48:", (eui_bits($eui48) != 48) ? 'Not available' : $eui48);
if (eui_bits($mac) == 48) {
443,17 → 453,25
// Query IEEE registries
if (count(glob(IEEE_MAC_REGISTRY.DIRECTORY_SEPARATOR.'*.txt')) > 0) {
$alt_mac = $mac;
$alt_mac[1] = dechex(hexdec($alt_mac[1])^1); // switch Unicat<=>Multicast in order to find the vendor
$alt_mac[1] = dechex(hexdec($alt_mac[1])^1); // switch Unicast<=>Multicast in order to find the vendor
 
if ($mac[1] == 'A') {
if (is_dir(IEEE_MAC_REGISTRY)) {
if ($is_eli) {
// Query the CID registry
if (
($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY . DIRECTORY_SEPARATOR . 'cid.txt', 'CID', $mac)) ||
($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY . DIRECTORY_SEPARATOR . 'cid.txt', 'CID', $alt_mac))
) {
echo "\n";
echo $x;
} else {
$registry_name = 'CID';
echo "\n";
echo sprintf("%-32s 0x%s\n", "IEEE $registry_name:", substr($mac, 0, 6));
echo sprintf("%-32s 0x%s\n", "Vendor-specific part:", substr($mac, 6));
echo sprintf("%-32s %s\n", "Registrant:", "$registry_name not found in database");
}
} else {
} else if ($is_eui) {
// Query the OUI registries
if (
# 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]
467,10 → 485,30
($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY . DIRECTORY_SEPARATOR . 'mam.txt', '28 bit identifier (MA-M)', $alt_mac)) ||
($x = _lookup_ieee_registry(IEEE_MAC_REGISTRY . DIRECTORY_SEPARATOR . 'oui.txt', 'OUI (MA-L)', $alt_mac))
) {
echo "\n";
echo $x;
} else {
$registry_name = 'OUI (MA-L)?';
echo "\n";
echo sprintf("%-32s 0x%s\n", "IEEE $registry_name:", substr($mac, 0, 6));
echo sprintf("%-32s 0x%s\n", "Vendor-specific part:", substr($mac, 6));
echo sprintf("%-32s %s\n", "Registrant:", "$registry_name not found in database");
 
$registry_name = '28 bit identifier (MA-M)?';
echo "\n";
echo sprintf("%-32s 0x%s\n", "IEEE $registry_name:", substr($mac, 0, 7));
echo sprintf("%-32s 0x%s\n", "Vendor-specific part:", substr($mac, 7));
echo sprintf("%-32s %s\n", "Registrant:", "$registry_name not found in database");
 
$registry_name = 'OUI-36 (MA-S)?';
echo "\n";
echo sprintf("%-32s 0x%s\n", "IEEE $registry_name:", substr($mac, 0, 9));
echo sprintf("%-32s 0x%s\n", "Vendor-specific part:", substr($mac, 9));
echo sprintf("%-32s %s\n", "Registrant:", "$registry_name not found in database");
}
}
}
}
 
$vm = '';
// === FAQ "Detection rules which don't have their dedicated page yet" ===
/trunk/includes/uuid_utils.inc.php
67,7 → 67,7
 
switch ($variant) {
case 0:
echo sprintf("%-24s %s\n", "Variant:", "[0xx] NCS (reserved for backward compatibility)");
echo sprintf("%-32s %s\n", "Variant:", "[0xx] NCS (reserved for backward compatibility)");
 
/*
* Internal structure of variant #0 UUIDs
112,10 → 112,10
$ts = gmp_strval($ts);
$ms = gmp_strval($ms);
$ts = gmdate('Y-m-d H:i:s', intval($ts))."'".str_pad($ms, 7, '0', STR_PAD_LEFT).' GMT';
echo sprintf("%-24s %s\n", "Timestamp:", "[0x$timestamp] $ts");
echo sprintf("%-32s %s\n", "Timestamp:", "[0x$timestamp] $ts");
 
$reserved = substr($uuid, 12, 4);
echo sprintf("%-24s %s\n", "Reserved:", "0x$reserved");
echo sprintf("%-32s %s\n", "Reserved:", "0x$reserved");
 
# Family 13 (dds) looks like node is 00 | nnnnnn 000000.
# Family 2 is presumably (ip).
129,20 → 129,20
} else {
$family_ = "Unknown ($family_dec)"; # There are probably no more families
}
echo sprintf("%-24s %s\n", "Family:", "[0x$family_hex = $family_dec] $family_");
echo sprintf("%-32s %s\n", "Family:", "[0x$family_hex = $family_dec] $family_");
 
$nodeid = substr($uuid, 18, 14);
echo sprintf("%-24s %s\n", "Node ID:", "0x$nodeid");
echo sprintf("%-32s %s\n", "Node ID:", "0x$nodeid");
# TODO: interprete node id (the family specifies it)
 
break;
case 1:
echo sprintf("%-24s %s\n", "Variant:", "[10x] RFC 4122 (Leach-Mealling-Salz)");
echo sprintf("%-32s %s\n", "Variant:", "[10x] RFC 4122 (Leach-Mealling-Salz)");
 
$version = hexdec(substr($uuid, 12, 1));
switch ($version) {
case 1:
echo sprintf("%-24s %s\n", "Version:", "[1] Time-based with unique random host identifier");
echo sprintf("%-32s %s\n", "Version:", "[1] Time-based with unique random host identifier");
 
# Timestamp: Count of 100ns intervals since 15 Oct 1582 00:00:00
# 1/0,0000001 = 10000000
154,33 → 154,33
$ts = gmp_strval($ts);
$ms = gmp_strval($ms);
$ts = gmdate('Y-m-d H:i:s', intval($ts))."'".str_pad($ms, 7, '0', STR_PAD_LEFT).' GMT';
echo sprintf("%-24s %s\n", "Timestamp:", "[0x$timestamp] $ts");
echo sprintf("%-32s %s\n", "Timestamp:", "[0x$timestamp] $ts");
 
$x = hexdec(substr($uuid, 16, 4));
$dec = $x & 0x3FFF; // The highest 2 bits are used by "variant" (10x)
$hex = substr($uuid, 16, 4);
echo sprintf("%-24s %s\n", "Clock ID:", "[0x$hex] $dec");
echo sprintf("%-32s %s\n", "Clock ID:", "[0x$hex] $dec");
 
$x = substr($uuid, 20, 12);
$nodeid = '';
for ($i=0; $i<6; $i++) {
$nodeid .= substr($x, $i*2, 2);
if ($i != 5) $nodeid .= ':';
if ($i != 5) $nodeid .= '-';
}
echo sprintf("%-24s %s\n", "Node ID:", "$nodeid");
echo sprintf("%-32s %s\n", "Node ID:", "$nodeid");
 
if (function_exists('decode_mac')) {
echo "\nIn case that this Node ID is a MAC address, here is the interpretation of that MAC address:\n";
echo "\nIn case that this Node ID is a MAC address, here is the interpretation of that MAC address:\n\n";
decode_mac($nodeid);
}
 
break;
case 2:
echo sprintf("%-24s %s\n", "Version:", "[2] DCE Security version");
echo sprintf("%-32s %s\n", "Version:", "[2] DCE Security version");
 
# The time_low field (which represents an integer in the range [0, 232-1]) is interpreted as a local-ID; that is, an identifier (within the domain specified by clock_seq_low) meaningful to the local host. In the particular case of a POSIX host, when combined with a POSIX UID or POSIX GID domain in the clock_seq_low field (above), the time_low field represents a POSIX UID or POSIX GID, respectively.
$x = substr($uuid, 0, 8);
echo sprintf("%-24s %s\n", "Local ID:", "0x$x");
echo sprintf("%-32s %s\n", "Local ID:", "0x$x");
 
# The clock_seq_low field (which represents an integer in the range [0, 28-1]) is interpreted as a local domain (as represented by sec_rgy_domain_t; see sec_rgy_domain_t ); that is, an identifier domain meaningful to the local host. (Note that the data type sec_rgy_domain_t can potentially hold values outside the range [0, 28-1]; however, the only values currently registered are in the range [0, 2], so this type mismatch is not significant.) In the particular case of a POSIX host, the value sec_rgy_domain_person is to be interpreted as the "POSIX UID domain", and the value sec_rgy_domain_group is to be interpreted as the "POSIX GID domain".
$x = substr($uuid, 18, 2);
187,7 → 187,7
if ($x == '00') $domain_info = 'POSIX: User-ID / Non-POSIX: site-defined';
else if ($x == '01') $domain_info = 'POSIX: Group-ID / Non-POSIX: site-defined';
else $domain_info = 'site-defined';
echo sprintf("%-24s %s\n", "Local Domain:", "0x$x ($domain_info)");
echo sprintf("%-32s %s\n", "Local Domain:", "0x$x ($domain_info)");
 
# Timestamp: Count of 100ns intervals since 15 Oct 1582 00:00:00
# 1/0,0000001 = 10000000
210,7 → 210,7
$ts_max = gmdate('Y-m-d H:i:s', intval($ts))."'".str_pad($ms, 7, '0', STR_PAD_LEFT).' GMT';
 
$timestamp = substr($uuid, 13, 3).substr($uuid, 8, 4).'xxxxxxxx';
echo sprintf("%-24s %s\n", "Timestamp:", "[0x$timestamp] $ts_min - $ts_max");
echo sprintf("%-32s %s\n", "Timestamp:", "[0x$timestamp] $ts_min - $ts_max");
 
$x = hexdec(substr($uuid, 16, 2).'00');
$dec_min = $x & 0x3FFF; // The highest 2 bits are used by "variant" (10x)
217,58 → 217,63
$x = hexdec(substr($uuid, 16, 2).'FF');
$dec_max = $x & 0x3FFF; // The highest 2 bits are used by "variant" (10x)
$hex = substr($uuid, 16, 2).'xx';
echo sprintf("%-24s %s\n", "Clock ID:", "[0x$hex] $dec_min - $dec_max");
echo sprintf("%-32s %s\n", "Clock ID:", "[0x$hex] $dec_min - $dec_max");
 
$x = substr($uuid, 20, 12);
$nodeid = '';
for ($i=0; $i<6; $i++) {
$nodeid .= substr($x, $i*2, 2);
if ($i != 5) $nodeid .= ':';
if ($i != 5) $nodeid .= '-';
}
echo sprintf("%-24s %s\n", "Node ID:", "$nodeid");
echo sprintf("%-32s %s\n", "Node ID:", "$nodeid");
 
if (function_exists('decode_mac')) {
echo "\nIn case that this Node ID is a MAC address, here is the interpretation of that MAC address:\n";
echo "\nIn case that this Node ID is a MAC address, here is the interpretation of that MAC address:\n\n";
decode_mac($nodeid);
}
 
break;
case 3:
echo sprintf("%-24s %s\n", "Version:", "[3] Name-based (MD5 hash)");
echo sprintf("%-32s %s\n", "Version:", "[3] Name-based (MD5 hash)");
 
$hash = str_replace('-', '', strtolower($uuid));
$hash[12] = '?'; // was overwritten by version
$hash[16] = '?'; // was partially overwritten by variant
 
echo sprintf("%-24s %s\n", "MD5(Namespace+Subject):", "$hash");
echo sprintf("%-32s %s\n", "MD5(Namespace+Subject):", "$hash");
 
break;
case 4:
echo sprintf("%-24s %s\n", "Version:", "[4] Random");
echo sprintf("%-32s %s\n", "Version:", "[4] Random");
 
$rand = '';
$rand_line1 = '';
$rand_line2 = '';
for ($i=0; $i<16; $i++) {
$bin = base_convert(substr($uuid, $i*2, 2), 16, 2);
$bin = str_pad($bin, 8, "0", STR_PAD_LEFT);
 
if ($i == 6) {
$bin[0] = 'x';
$bin[1] = 'x';
// was overwritten by version
$bin[0] = '?';
$bin[1] = '?';
$bin[2] = '?';
$bin[3] = '?';
} else if ($i == 8) {
$bin[0] = 'x';
$bin[1] = 'x';
$bin[2] = 'x';
$bin[3] = 'x';
// was partially overwritten by variant
$bin[0] = '?';
$bin[1] = '?';
}
 
$rand .= "$bin ";
if ($i<8) $rand_line1 .= "$bin ";
if ($i>=8) $rand_line2 .= "$bin ";
}
 
echo sprintf("%-24s %s\n", "Random bits:", trim($rand));
echo sprintf("%-32s %s\n", "Random bits:", trim($rand_line1));
echo sprintf("%-32s %s\n", "", trim($rand_line2));
 
break;
case 5:
echo sprintf("%-24s %s\n", "Version:", "[5] Name-based (SHA-1 hash)");
echo sprintf("%-32s %s\n", "Version:", "[5] Name-based (SHA-1 hash)");
 
$hash = str_replace('-', '', strtolower($uuid));
$hash[12] = '?'; // was overwritten by version
275,21 → 280,21
$hash[16] = '?'; // was partially overwritten by variant
$hash .= '????????'; // was cut off
 
echo sprintf("%-24s %s\n", "SHA1(Namespace+Subject):", "$hash");
echo sprintf("%-32s %s\n", "SHA1(Namespace+Subject):", "$hash");
 
 
break;
default:
echo sprintf("%-24s %s\n", "Version:", "[$version] Unknown");
echo sprintf("%-32s %s\n", "Version:", "[$version] Unknown");
break;
}
 
break;
case 2:
echo sprintf("%-24s %s\n", "Variant:", "[110] Reserved for Microsoft Corporation");
echo sprintf("%-32s %s\n", "Variant:", "[110] Reserved for Microsoft Corporation");
break;
case 3:
echo sprintf("%-24s %s\n", "Variant:", "[111] Reserved for future use");
echo sprintf("%-32s %s\n", "Variant:", "[111] Reserved for future use");
break;
}
}
425,7 → 430,7
*/
$mac = get_mac_address();
if ($mac) {
$node = str_replace(':','',$mac);
$node = str_replace('-','',str_replace(':','',$mac));
for ($i = 0; $i < 6; $i++) {
$uuid['node'][$i] = hexdec(substr($node, $i*2, 2));
}
468,7 → 473,7
$out = implode("\n",$out);
$m = array();
if (preg_match("/([0-9a-f]{2}\\-[0-9a-f]{2}\\-[0-9a-f]{2}\\-[0-9a-f]{2}\\-[0-9a-f]{2}\\-[0-9a-f]{2})/ismU", $out, $m)) {
$detected_mac = str_replace('-', ':', strtolower($m[1]));
$detected_mac = strtolower($m[1]);
return $detected_mac;
}
}
/trunk/index.php
9,7 → 9,7
 
<body>
 
<h1>UUID &amp;amp; MAC Utils by Daniel Marschall</h1>
<h1>UUID &amp; MAC Utils by Daniel Marschall</h1>
 
<!-- <p><a href="https://svn.viathinksoft.com/cgi-bin/viewvc.cgi/uuid_mac_utils/">View the source code</a></p> -->
<p><a href="https://github.com/danielmarschall/uuid_mac_utils/">View the source code</a></p>
/trunk/interprete_mac.php
30,6 → 30,8
 
?></pre>
 
<br>
 
</body>
 
</html>
/trunk/interprete_uuid.php
77,21 → 77,24
echo 'This is not a valid UUID.';
} else {
$oid = uuid_to_oid($uuid);
echo sprintf("%-24s %s\n", "Your input:", $uuid);
echo sprintf("%-32s %s\n", "Your input:", $uuid);
echo "\n";
echo sprintf("%-24s %s\n", "URI:", 'uuid:'.strtolower(oid_to_uuid(uuid_to_oid($uuid))));
echo sprintf("%-24s %s\n", "Microsoft GUID syntax:", '{'.strtoupper(oid_to_uuid(uuid_to_oid($uuid))).'}');
echo sprintf("%-24s %s\n", "C++ struct syntax:", uuid_c_syntax($uuid));
echo sprintf("%-32s %s\n", "URN:", 'urn:uuid:'.strtolower(oid_to_uuid(uuid_to_oid($uuid))));
echo sprintf("%-32s %s\n", "URI:", 'uuid:'.strtolower(oid_to_uuid(uuid_to_oid($uuid))));
echo sprintf("%-32s %s\n", "Microsoft GUID syntax:", '{'.strtoupper(oid_to_uuid(uuid_to_oid($uuid))).'}');
echo sprintf("%-32s %s\n", "C++ struct syntax:", uuid_c_syntax($uuid));
echo "\n";
echo sprintf("%-24s %s\n", "As OID:", $oid);
echo sprintf("%-24s %s\n", "DER encoding of OID:", OidDerConverter::hexarrayToStr(OidDerConverter::oidToDER($oid)));
echo sprintf("%-32s %s\n", "As OID:", $oid);
echo sprintf("%-32s %s\n", "DER encoding of OID:", OidDerConverter::hexarrayToStr(OidDerConverter::oidToDER($oid)));
echo "\n";
echo "Interpration of the UUID:\n";
echo "Interpration of the UUID:\n\n";
uuid_info($uuid);
}
 
?></pre>
 
<br>
 
</body>
 
</html>