fix(netmap): résolution DNS via Livebox pour les noms d'appareils
nmap forcé sur 192.168.1.1 avec -R --dns-servers pour récupérer les hostnames DHCP enregistrés par la Livebox (.home). Ajout du champ netbios (script nbstat) et affichage du meilleur nom détecté (NetBIOS > hostname DNS) avec badge de source. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
f421636ab8
commit
8d9eaf98c2
+15
-4
@@ -423,6 +423,7 @@ def _netmap_save(data: dict):
|
|||||||
def _netmap_parse(output: str) -> list[dict]:
|
def _netmap_parse(output: str) -> list[dict]:
|
||||||
hosts = []
|
hosts = []
|
||||||
current: dict = {}
|
current: dict = {}
|
||||||
|
in_script = False
|
||||||
for line in output.splitlines():
|
for line in output.splitlines():
|
||||||
m_host = re.search(r"Nmap scan report for (.+)", line)
|
m_host = re.search(r"Nmap scan report for (.+)", line)
|
||||||
if m_host:
|
if m_host:
|
||||||
@@ -431,25 +432,35 @@ def _netmap_parse(output: str) -> list[dict]:
|
|||||||
raw = m_host.group(1)
|
raw = m_host.group(1)
|
||||||
ip_m = re.search(r"\((\d+\.\d+\.\d+\.\d+)\)", raw)
|
ip_m = re.search(r"\((\d+\.\d+\.\d+\.\d+)\)", raw)
|
||||||
if ip_m:
|
if ip_m:
|
||||||
current = {"ip": ip_m.group(1), "hostname": raw.split("(")[0].strip(), "mac": "", "vendor": ""}
|
current = {"ip": ip_m.group(1), "hostname": raw.split("(")[0].strip(), "mac": "", "vendor": "", "netbios": ""}
|
||||||
else:
|
else:
|
||||||
current = {"ip": raw.strip(), "hostname": "", "mac": "", "vendor": ""}
|
current = {"ip": raw.strip(), "hostname": "", "mac": "", "vendor": "", "netbios": ""}
|
||||||
|
in_script = False
|
||||||
continue
|
continue
|
||||||
m_mac = re.search(r"MAC Address: ([0-9A-F:]+)\s*(?:\((.+)\))?", line, re.I)
|
m_mac = re.search(r"MAC Address: ([0-9A-F:]+)\s*(?:\((.+)\))?", line, re.I)
|
||||||
if m_mac:
|
if m_mac:
|
||||||
current["mac"] = m_mac.group(1)
|
current["mac"] = m_mac.group(1)
|
||||||
current["vendor"] = m_mac.group(2) or ""
|
current["vendor"] = m_mac.group(2) or ""
|
||||||
|
continue
|
||||||
|
# Résultat du script nbstat
|
||||||
|
m_nb = re.search(r"NetBIOS name: ([^,]+)", line, re.I)
|
||||||
|
if m_nb:
|
||||||
|
nb = m_nb.group(1).strip()
|
||||||
|
if nb and nb.lower() not in ("<unknown>", ""):
|
||||||
|
current["netbios"] = nb
|
||||||
if current.get("ip"):
|
if current.get("ip"):
|
||||||
hosts.append(current)
|
hosts.append(current)
|
||||||
return hosts
|
return hosts
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/api/netmap/scan")
|
@app.get("/api/netmap/scan")
|
||||||
def api_netmap_scan():
|
def api_netmap_scan():
|
||||||
try:
|
try:
|
||||||
r = subprocess.run(
|
r = subprocess.run(
|
||||||
["nmap", "-sn", "-T4", "--host-timeout", "2s", NETMAP_RANGE],
|
["nmap", "-sn", "-T4", "-R", "--dns-servers", "192.168.1.1",
|
||||||
capture_output=True, text=True, timeout=120
|
"--host-timeout", "3s", "--script", "nbstat", NETMAP_RANGE],
|
||||||
|
capture_output=True, text=True, timeout=180
|
||||||
)
|
)
|
||||||
hosts = _netmap_parse(r.stdout)
|
hosts = _netmap_parse(r.stdout)
|
||||||
return {"hosts": hosts, "names": _netmap_load()}
|
return {"hosts": hosts, "names": _netmap_load()}
|
||||||
|
|||||||
+11
-4
@@ -537,21 +537,28 @@ function netmapRender(hosts) {
|
|||||||
if (!hosts.length) { el.innerHTML = '<span style="color:var(--muted)">Aucun appareil détecté.</span>'; return; }
|
if (!hosts.length) { el.innerHTML = '<span style="color:var(--muted)">Aucun appareil détecté.</span>'; return; }
|
||||||
const rows = hosts.map(h => {
|
const rows = hosts.map(h => {
|
||||||
const k = h.ip.replace(/\./g, '_');
|
const k = h.ip.replace(/\./g, '_');
|
||||||
const name = _netmapNames[h.ip] || '';
|
// Meilleur nom détecté : NetBIOS > hostname DNS > fabricant
|
||||||
|
const detected = h.netbios || h.hostname || '';
|
||||||
|
const savedName = _netmapNames[h.ip] || '';
|
||||||
|
// Pré-remplir le champ avec le nom détecté si pas encore de nom sauvegardé
|
||||||
|
const inputVal = savedName || detected;
|
||||||
|
const detectedBadge = detected
|
||||||
|
? `<span style="font-size:10px;color:var(--muted);margin-left:4px" title="${h.netbios ? 'NetBIOS' : 'DNS'}">${h.netbios ? '🔵' : '🔤'} ${detected}</span>`
|
||||||
|
: '';
|
||||||
return `<tr>
|
return `<tr>
|
||||||
<td><code style="color:var(--accent)">${h.ip}</code></td>
|
<td><code style="color:var(--accent)">${h.ip}</code></td>
|
||||||
<td><code style="color:var(--muted);font-size:12px">${h.mac || '—'}</code></td>
|
<td><code style="color:var(--muted);font-size:12px">${h.mac || '—'}</code></td>
|
||||||
<td style="color:var(--muted);font-size:12px">${h.vendor || '—'}</td>
|
<td style="color:var(--muted);font-size:12px">${h.vendor || '—'}</td>
|
||||||
<td style="color:var(--muted);font-size:12px">${h.hostname || '—'}</td>
|
<td style="font-size:12px">${detectedBadge || '<span style="color:var(--muted)">—</span>'}</td>
|
||||||
<td>
|
<td>
|
||||||
<input class="netmap-name-input" id="nm_${k}" value="${h.ip in _netmapNames ? _netmapNames[h.ip].replace(/"/g,'"') : ''}" placeholder="Nom perso…">
|
<input class="netmap-name-input" id="nm_${k}" value="${inputVal.replace(/"/g,'"').replace(/</g,'<')}" placeholder="Nom perso…">
|
||||||
<button class="netmap-save-btn" onclick="netmapSaveName('${h.ip}')">Sauver</button>
|
<button class="netmap-save-btn" onclick="netmapSaveName('${h.ip}')">Sauver</button>
|
||||||
<span class="netmap-flash" id="nmf_${k}"></span>
|
<span class="netmap-flash" id="nmf_${k}"></span>
|
||||||
</td>
|
</td>
|
||||||
</tr>`;
|
</tr>`;
|
||||||
}).join('');
|
}).join('');
|
||||||
el.innerHTML = `<table>
|
el.innerHTML = `<table>
|
||||||
<thead><tr><th>IP</th><th>MAC</th><th>Fabricant</th><th>Hostname</th><th>Nom perso</th></tr></thead>
|
<thead><tr><th>IP</th><th>MAC</th><th>Fabricant</th><th>Nom détecté</th><th>Nom perso</th></tr></thead>
|
||||||
<tbody>${rows}</tbody>
|
<tbody>${rows}</tbody>
|
||||||
</table>`;
|
</table>`;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user