()
| 8007 | o.value = i.name; |
| 8008 | const tag = i.type === 'wifi' ? ' (WiFi)' : i.type === 'ethernet' ? ' (LAN)' : (i.type ? ' (' + i.type + ')' : ''); |
| 8009 | o.textContent = i.name + tag; |
| 8010 | sel.appendChild(o); |
| 8011 | }); |
| 8012 | sel.dataset.filled = '1'; |
| 8013 | }).catch(() => {}); |
| 8014 | } |
| 8015 | async function runSmbWatch() { |
| 8016 | const out = document.getElementById('smb-results'); |
| 8017 | if (!out) return; |
| 8018 | const btn = (typeof event !== 'undefined' && event && event.target) ? event.target : null; |
| 8019 | const ifaceSel = document.getElementById('smb-iface'); |
| 8020 | const iface = ifaceSel && ifaceSel.value ? ifaceSel.value : ''; |
| 8021 | const secsEl = document.getElementById('smb-secs'); |
| 8022 | const secs = secsEl && secsEl.value ? secsEl.value : '20'; |
| 8023 | _ndBusy(btn, true, 'Listening…'); |
| 8024 | out.classList.remove('hidden'); |
| 8025 | out.innerHTML = '<p class="text-sm text-gray-400">Passively capturing SMB + LLMNR/NBT-NS/mDNS…</p>'; |
| 8026 | try { |
| 8027 | _smbFillIfaces(); |
| 8028 | const qs = '?seconds=' + encodeURIComponent(secs) + (iface ? '&interface=' + encodeURIComponent(iface) : ''); |
| 8029 | const d = await fetchAPI('/api/net/smb-watch' + qs); |
| 8030 | if (!d || d.success === false) { |
| 8031 | const msg = (d && d.error) || 'failed'; |
| 8032 | let extra = ''; |
| 8033 | if (d && d.missing_tool) extra = ' <button onclick="installNetTool(\'tcpdump\', this, runSmbWatch)" class="ml-2 underline text-cyan-400">Install tcpdump</button>'; |
| 8034 | out.innerHTML = '<p class="text-sm text-red-400">Error: ' + escapeHtml(msg) + extra + '</p>'; |
| 8035 | return; |
| 8036 | } |
| 8037 | const [cls, label] = _SMB_VERDICT_STYLE[d.verdict] || _SMB_VERDICT_STYLE.unknown; |
| 8038 | const smb = d.smb || {}, nr = d.nameres || {}, q = nr.queries || {}; |
| 8039 | let html = `<div class="mb-2 px-3 py-2 rounded border ${cls} text-sm">${label}</div>`; |
| 8040 | const _kc = (d.kerberos || {}).counts || {}; |
| 8041 | const _kt = Object.values(_kc).reduce((a, b) => a + (b || 0), 0); |
| 8042 | html += `<p class="text-xs text-gray-500 mb-2">Interface: ${escapeHtml(d.interface || '—')} · ${d.seconds}s · SMBv1 servers: ${(smb.v1_servers || []).length}, SMB2/3 pkts: ${smb.v2_count || 0} · responders: ${(nr.responders || []).length} · queries L${q.llmnr || 0}/N${q.nbtns || 0}/m${q.mdns || 0} · Kerberos msgs: ${_kt}${d.learned ? ' · <span class="text-gray-400">baseline learned now</span>' : ''}</p>`; |
| 8043 | if ((smb.v1_servers || []).length) { |
| 8044 | html += '<p class="text-xs uppercase text-gray-400 mt-2 mb-1">SMBv1 servers</p>' + |
nothing calls this directly
no test coverage detected