netdiag-app/src/lib/tools/netzwerk/ipconflict.ts
Eduard Wisch 9ee9c954b2 Neues Werkzeug: IP-Konflikt-Prüfung
- arpConflictScan (Plugin): pingt das Subnetz über mehrere Runden und liest
  je Runde die ARP-Tabelle; mehrere MACs pro IP = Konflikt. Kein Root nötig
- Erkennt den Fall, dass /proc/net/arp nicht lesbar ist (Android-Limit) und
  meldet das ehrlich, statt fälschlich Entwarnung zu geben
- ipconflict.ts: neues Protokoll-Tool, in der Tool-Registry eingetragen —
  listet betroffene IPs samt der konkurrierenden MAC-Adressen

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 23:00:32 +02:00

90 lines
2.8 KiB
TypeScript

/**
* Tool: IP-Konflikt-Prüfung — findet IP-Adressen, die von zwei Geräten
* gleichzeitig benutzt werden und so das Netz durcheinanderbringen.
*
* Verfahren ohne Root: Das Subnetz wird über mehrere Runden angepingt und
* jeweils die ARP-Tabelle ausgelesen. Tauchen für eine IP mehrere MAC-Adressen
* auf, nutzen mehrere Geräte dieselbe Adresse — ein Konflikt.
*/
import { scanner } from '../../scanner';
import type { MeasureStatus, Tool } from '../types';
export const ipConflictTool: Tool = {
id: 'ipconflict',
category: 'netzwerk',
name: 'IP-Konflikt',
icon: 'alert-triangle',
description: 'Findet IP-Adressen, die zwei Geräte gleichzeitig benutzen.',
scope: 'protocol',
params: [
{
key: 'subnet',
label: 'Netzbereich (CIDR) — leer = aktiver Adapter',
type: 'text',
placeholder: 'leer lassen → automatisch über WLAN/LAN',
},
{
key: 'rounds',
label: 'Prüfrunden (mehr = zuverlässiger, dauert länger)',
type: 'number',
default: 4,
},
],
async run(ctx) {
// Netzbereich: Dialog → Protokoll → aktiver Adapter
let subnet =
String(ctx.params.subnet ?? '').trim() || String(ctx.protocol.subnet ?? '').trim();
if (!subnet) {
try {
subnet = String((await scanner.getLocalSubnet()).subnet ?? '').trim();
} catch {
/* unten abgefangen */
}
}
if (!subnet) {
return {
label: 'Kein Netzbereich — WLAN/LAN nicht aktiv?',
result: { error: 'Netzbereich konnte nicht ermittelt werden' },
measureStatus: 2,
};
}
const rounds = Number(ctx.params.rounds) || 4;
const res = await scanner.arpConflictScan({ subnet, rounds });
// ARP-Tabelle nicht lesbar → ehrliche Rückmeldung statt falscher Entwarnung
if (!res.arpAvailable) {
return {
label: 'ARP-Tabelle nicht lesbar — Konfliktprüfung nicht möglich',
result: {
subnet,
hinweis:
'Android gibt /proc/net/arp auf diesem Gerät nicht frei. Eine ' +
'zuverlässige IP-Konflikt-Erkennung ist ohne Root hier leider nicht möglich.',
},
measureStatus: 1,
};
}
const n = res.conflicts.length;
const status: MeasureStatus = n > 0 ? 2 : 0;
return {
label:
n > 0
? `${n} IP-Konflikt${n > 1 ? 'e' : ''} gefunden!`
: `Kein Konflikt — ${res.checked} Adressen geprüft`,
result: {
subnet,
geprueft: res.checked,
runden: res.rounds,
konflikte: res.conflicts.map((c) => `${c.ip}${c.macs.join(' / ')}`),
hinweis:
n > 0
? 'Mehrere MAC-Adressen pro IP — diese Geräte stören sich gegenseitig.'
: 'Jede gefundene IP wird von genau einem Gerät benutzt.',
},
measureStatus: status,
};
},
};