(isHeadless)
| 7160 | if (d.advisories && d.advisories.length) { |
| 7161 | html += '<ul class="text-xs text-cyan-400/80 mt-2 list-disc pl-5">' + |
| 7162 | d.advisories.map(a => '<li>' + escapeHtml(a) + '</li>').join('') + '</ul>'; |
| 7163 | } |
| 7164 | out.innerHTML = html; |
| 7165 | } catch (e) { |
| 7166 | out.innerHTML = '<p class="text-sm text-red-400">Failed: ' + escapeHtml(e.message) + '</p>'; |
| 7167 | } finally { |
| 7168 | _ndBusy(btn, false); |
| 7169 | } |
| 7170 | } |
| 7171 | async function ipv6TrustBaseline() { |
| 7172 | try { |
| 7173 | await postAPI('/api/net/ipv6-baseline', { action: 'reset' }); |
| 7174 | addConsoleMessage('IPv6 baseline reset — re-learning current RA router(s) / DHCPv6 server(s)', 'info'); |
| 7175 | await runIpv6Watch(); |
| 7176 | } catch (e) { |
| 7177 | addConsoleMessage('Failed to reset IPv6 baseline: ' + e.message, 'error'); |
| 7178 | } |
| 7179 | } |
| 7180 | |
| 7181 | // ---- NDP Watch (passive IPv6 neighbor-discovery spoofing) ------------------ |
| 7182 | const _NDP_VERDICT_STYLE = { |
| 7183 | clean: ['bg-green-950/40 border-green-900 text-green-400', '✓ No NDP spoofing — neighbour bindings consistent'], |
| 7184 | 'dad-dos': ['bg-amber-950/50 border-amber-800 text-amber-300', '⚠ dos-new-ip6 — a MAC is defending every DAD claim (SLAAC DoS)'], |
| 7185 | storm: ['bg-red-950/60 border-red-800 text-red-300', '🛑 Neighbor Advertisement flood (NDP DoS)'], |
| 7186 | spoofed: ['bg-red-950/60 border-red-800 text-red-300', '🛑 NDP spoofing — forged Neighbor Advertisement / router poisoning (IPv6 MITM)'], |
| 7187 | unknown: ['bg-slate-800 border-slate-700 text-slate-400', '— Could not determine'], |
| 7188 | }; |
| 7189 | function _ndpFillIfaces() { |
| 7190 | const sel = document.getElementById('ndp-iface'); |
| 7191 | if (!sel || sel.dataset.filled === '1') return Promise.resolve(); |
| 7192 | return fetchAPI('/api/net/interfaces').then(x => { |
| 7193 | (x.interfaces || []).forEach(i => { |
| 7194 | const o = document.createElement('option'); |
| 7195 | o.value = i.name; |
| 7196 | const tag = i.type === 'wifi' ? ' (WiFi)' : i.type === 'ethernet' ? ' (LAN)' : (i.type ? ' (' + i.type + ')' : ''); |
| 7197 | o.textContent = i.name + tag; |
| 7198 | sel.appendChild(o); |
| 7199 | }); |
no test coverage detected