Skip to content

Commit 69cb96e

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 69cb96e

File tree

1 file changed

+50
-9
lines changed

1 file changed

+50
-9
lines changed

scripts/js/network.js

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -179,16 +179,57 @@ $(() => {
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+
// Multicast overrides all SLAP meaning
194+
if (isMulticast) {
195+
// Case 2.1 - Multicast
196+
cell.html(utils.escapeHtml(data.hwaddr) + "<br>Multicast Address");
197+
} else if (isLocal) {
198+
// Case 2.2 - Local SLAP
199+
let slapLabel = null;
200+
// SLAP quadrant resolution (RFC 9542)
201+
const ts = Math.floor(firstOctet / 4) % 4; // bits 2–3 become bits 0–1
202+
switch (ts) {
203+
case 0x0:
204+
slapLabel = "Administratively Assigned (AAI)";
205+
break;
206+
case 0x1:
207+
slapLabel = "Extended Local (ELI)";
208+
break;
209+
case 0x2:
210+
slapLabel = "Reserved";
211+
break;
212+
case 0x3:
213+
slapLabel = "Standard Assigned (SAI)";
214+
break;
215+
default:
216+
// satisfy ESLint
217+
slapLabel = "Unclassified";
218+
break;
219+
}
220+
221+
cell.html(utils.escapeHtml(data.hwaddr) + "<br>Locally Administered");
222+
cell.css("font-style", "italic").attr("title", slapLabel);
223+
} else if (data.macVendor && data.macVendor.length > 0) {
224+
// Case 2.3 - Global address space (U/L = 0)
225+
cell.html(utils.escapeHtml(data.hwaddr) + "<br>" + utils.escapeHtml(data.macVendor));
226+
} else {
227+
// Case 2.4 - Lookup failed
228+
cell.html(utils.escapeHtml(data.hwaddr) + "<br>Global: Unknown");
229+
}
230+
} else {
231+
// Case 3 — Not IP-mock, not MAC-like
232+
cell.css("color", "red").html(utils.escapeHtml(data.hwaddr) + "<br>Unknown Format");
192233
}
193234

194235
// Add delete button

0 commit comments

Comments
 (0)