()
| 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>' + |
| 8045 | '<table class="min-w-full text-xs text-gray-300 whitespace-nowrap"><thead>' + |
| 8046 | '<tr class="text-left text-gray-500"><th class="px-2 py-1">Host</th><th class="px-2 py-1">Mode</th><th class="px-2 py-1">Status</th></tr>' + |
| 8047 | '</thead><tbody>' + |
| 8048 | smb.v1_servers.map(s => { |
| 8049 | const mode = s.mode === 'active' ? '<span class="text-red-300">active</span>' : '<span class="text-amber-300">offered</span>'; |
| 8050 | return `<tr class="border-t border-slate-800"> |
| 8051 | <td class="px-2 py-1 font-mono">${escapeHtml(s.ip)}</td> |
| 8052 | <td class="px-2 py-1">${mode}</td> |
| 8053 | <td class="px-2 py-1">${s.known ? '<span class="text-gray-500">known legacy</span>' : '<span class="text-amber-300">seen</span>'}</td> |
| 8054 | </tr>`; |
| 8055 | }).join('') + |
| 8056 | '</tbody></table>'; |
| 8057 | } |
| 8058 | if ((nr.responders || []).length) { |
| 8059 | html += '<p class="text-xs uppercase text-gray-400 mt-2 mb-1">Name-resolution responders</p>' + |
| 8060 | '<table class="min-w-full text-xs text-gray-300 whitespace-nowrap"><thead>' + |
| 8061 | '<tr class="text-left text-gray-500"><th class="px-2 py-1">Responder</th><th class="px-2 py-1">Proto</th><th class="px-2 py-1">Answered names</th><th class="px-2 py-1">Status</th></tr>' + |
| 8062 | '</thead><tbody>' + |
| 8063 | nr.responders.map(r => { |
| 8064 | const poison = (r.protos || []).some(p => p === 'llmnr' || p === 'nbtns') || r.highvalue.length; |
| 8065 | const badge = poison ? '<span class="text-red-300">poisoner</span>' : (r.known ? '<span class="text-green-400">known mDNS</span>' : '<span class="text-amber-300">mDNS</span>'); |
| 8066 | const names = (r.names || []).join(', ') + (r.highvalue.length ? ' ⚠WPAD' : ''); |
| 8067 | return `<tr class="border-t border-slate-800"> |
| 8068 | <td class="px-2 py-1 font-mono ${poison ? 'text-red-300' : ''}">${escapeHtml(r.ip)}</td> |
| 8069 | <td class="px-2 py-1 text-gray-400">${escapeHtml((r.protos || []).join('/').toUpperCase())}</td> |
| 8070 | <td class="px-2 py-1 font-mono text-gray-400">${escapeHtml(names || '—')}</td> |
| 8071 | <td class="px-2 py-1">${badge}</td> |
| 8072 | </tr>`; |
| 8073 | }).join('') + |
nothing calls this directly
no test coverage detected