Skip to content

Commit fe3ea1a

Browse files
committed
network: correct MAC classification to match RFC 9542 (SLAP)
RFC 9542 replaces RFC 7042 and defines the Structured Local Address Plan (SLAP), subdividing the locally administered address space into four distinct quadrants: - Administratively Assigned (x2), - Reserved (x6), - Extended Local (xA), - and Standard Assigned (xE). Modern systems — including iOS, Android, virtualization platforms, containers, and privacy-preserving network stacks — use these ranges extensively. This patch updates the classification logic to implement RFC 9542 semantics: - Decode SLAP quadrants for local addresses (x2/x6/xA/xE) - Distinguish global vendor MACs from global addresses with unknown vendors - Correctly identify multicast addresses (bit 0 set) and avoid mislabeling them as local - Preserve support for mock ip- addresses and malformed/unknown formats This improves accuracy for randomized mobile MACs, manufacturer local address blocks, protocol-assigned local addresses, and security-focused deployments where correct interpretation of the first-octet bit fields matters. Signed-off-by: Robin Getz <rgetz503@gmail.com>
1 parent 62c55dc commit fe3ea1a

File tree

1 file changed

+52
-9
lines changed

1 file changed

+52
-9
lines changed

scripts/js/network.js

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -179,16 +179,59 @@ $(() => {
179179
$("td:eq(0)", row).html(ips.join("<br>"));
180180

181181
// MAC + Vendor field if available
182-
if (data.macVendor && data.macVendor.length > 0) {
183-
$("td:eq(1)", row).html(
184-
utils.escapeHtml(data.hwaddr) + "<br>" + utils.escapeHtml(data.macVendor)
185-
);
186-
}
187-
188-
// Make mock MAC addresses italics and add title
182+
const cell = $("td:eq(1)", row);
189183
if (data.hwaddr.startsWith("ip-")) {
190-
$("td:eq(1)", row).css("font-style", "italic");
191-
$("td:eq(1)", row).attr("title", "Mock MAC address");
184+
// Case 1 - Make mock MAC addresses italics and add title
185+
cell.css("font-style", "italic").attr("title", "Mock MAC address");
186+
} else if (data.hwaddr.includes(":")) {
187+
// Case 2 — MAC-like address
188+
const parts = data.hwaddr.split(":");
189+
const firstOctet = Number.parseInt(parts[0], 16);
190+
// Arithmetic-only flag detection
191+
const isMulticast = firstOctet % 2 === 1; // bit 0
192+
const isLocal = Math.floor(firstOctet / 2) % 2 === 1; // bit 1
193+
const lowNibble = firstOctet % 16; // 2nd hex digit
194+
// Multicast overrides all SLAP meaning
195+
if (isMulticast) {
196+
// Case 2.1 - Multicast
197+
cell.html(utils.escapeHtml(data.hwaddr) + "<br>Multicast Address");
198+
} else {
199+
// SLAP quadrant resolution (RFC 9542)
200+
let slapLabel = null;
201+
if (isLocal) {
202+
// Case 2.2 - Local SLAP
203+
switch (lowNibble) {
204+
case 0x2:
205+
slapLabel = "Local: Administrative";
206+
break;
207+
case 0x6:
208+
slapLabel = "Local: Reserved";
209+
break;
210+
case 0xa:
211+
slapLabel = "Local: Extended";
212+
break;
213+
case 0xe:
214+
slapLabel = "Local: Standard";
215+
break;
216+
default:
217+
slapLabel = "Local: Unclassified";
218+
break;
219+
}
220+
cell.html(utils.escapeHtml(data.hwaddr) + "<br>" + slapLabel);
221+
} else {
222+
// Case 2.3 - Global address space (U/L = 0)
223+
if (data.macVendor && data.macVendor.length > 0) {
224+
// Case 2.3.1 - Lookup worked
225+
cell.html(utils.escapeHtml(data.hwaddr) + "<br>" + utils.escapeHtml(data.macVendor));
226+
} else {
227+
// Case 2.3.2 - Lookup failed
228+
cell.html(utils.escapeHtml(data.hwaddr) + "<br>Global: Unknown");
229+
}
230+
}
231+
}
232+
} else {
233+
// Case 3 — Not IP-mock, not MAC-like
234+
cell.css("color", "red").html(utils.escapeHtml(data.hwaddr) + "<br>Unknown Format");
192235
}
193236

194237
// Add delete button

0 commit comments

Comments
 (0)