opnsense_diag_reverse_dns
Resolve any IP address to its hostname via reverse DNS lookup on the OPNsense firewall.
Instructions
Perform a reverse DNS lookup (IP to hostname) from the OPNsense firewall
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| address | Yes | IP address to reverse-lookup |
Implementation Reference
- src/tools/diagnostics.ts:383-389 (handler)Handler case for 'opnsense_diag_reverse_dns' in the switch statement. It parses the address argument, then calls the OPNsense API endpoint /diagnostics/dns/reverse_lookup?address=... and returns the result as JSON.
case "opnsense_diag_reverse_dns": { const parsed = z.object({ address: z.string().min(1) }).parse(args); const result = await client.get( `/diagnostics/dns/reverse_lookup?address=${encodeURIComponent(parsed.address)}`, ); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } - src/tools/diagnostics.ts:106-120 (schema)Tool definition / input schema for 'opnsense_diag_reverse_dns' registered in diagnosticsToolDefinitions. Defines the 'address' parameter as a required string for reverse DNS lookup.
{ name: "opnsense_diag_reverse_dns", description: "Perform a reverse DNS lookup (IP to hostname) from the OPNsense firewall", inputSchema: { type: "object" as const, properties: { address: { type: "string", description: "IP address to reverse-lookup", }, }, required: ["address"], }, }, - src/index.ts:61-61 (registration)Registration of diagnostics tools: maps each tool name from diagnosticsToolDefinitions to handleDiagnosticsTool handler in the toolHandlers map.
for (const def of diagnosticsToolDefinitions) toolHandlers.set(def.name, handleDiagnosticsTool); - src/tools/diagnostics.ts:267-444 (handler)The main handler function handleDiagnosticsTool that dispatches to the switch case for reverse_dns.
export async function handleDiagnosticsTool( name: string, args: Record<string, unknown>, client: OPNsenseClient, ): Promise<{ content: Array<{ type: "text"; text: string }> }> { try { switch (name) { case "opnsense_diag_arp_table": { const filters = ArpFilterSchema.parse(args); const result = await client.get<unknown>("/diagnostics/interface/getArp"); // Apply client-side filtering if any filter params provided if (filters.ip || filters.mac || filters.interface) { const entries = Array.isArray(result) ? result : []; const filtered = entries.filter((entry: Record<string, unknown>) => { if (filters.ip && !String(entry["ip"] ?? "").includes(filters.ip)) return false; if (filters.mac && !String(entry["mac"] ?? "").toLowerCase().includes(filters.mac.toLowerCase())) return false; if (filters.interface && String(entry["intf"] ?? "") !== filters.interface) return false; return true; }); return { content: [{ type: "text", text: JSON.stringify(filtered, null, 2) }] }; } return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } case "opnsense_diag_routes": { const result = await client.get("/diagnostics/interface/getRoutes"); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } case "opnsense_diag_ping": { const parsed = PingSchema.parse(args); // OPNsense 24.7+: job-based ping API (set → start → poll → remove) const setResult = await client.post<{ uuid?: string; result?: string }>( "/diagnostics/ping/set", { ping: { settings: { hostname: parsed.address, count: String(parsed.count) } } }, ); const jobId = setResult.uuid; if (!jobId) { return { content: [{ type: "text", text: JSON.stringify(setResult, null, 2) }] }; } await client.post(`/diagnostics/ping/start/${jobId}`); // Poll until send count reaches requested count (status stays "running" throughout) const maxWait = Math.max(parsed.count * 2000, 10000); const start = Date.now(); let result: Record<string, unknown> | undefined; while (Date.now() - start < maxWait) { await new Promise((r) => setTimeout(r, 1500)); const jobs = await client.get<{ rows?: Array<Record<string, unknown>>; }>("/diagnostics/ping/search_jobs"); const job = (jobs.rows ?? []).find( (j) => j.id === jobId || j.uuid === jobId, ); if (job && Number(job.send ?? 0) >= parsed.count) { result = job; break; } } // Cleanup try { await client.post(`/diagnostics/ping/remove/${jobId}`); } catch { // Best-effort cleanup } if (!result) { return { content: [{ type: "text", text: "Ping timed out waiting for results" }] }; } // Format clean output const output = { host: result.hostname, packets_sent: result.send, packets_received: result.received, packet_loss: result.loss, rtt_min_ms: result.min, rtt_avg_ms: result.avg, rtt_max_ms: result.max, rtt_stddev_ms: result["std-dev"], }; return { content: [{ type: "text", text: JSON.stringify(output, null, 2) }] }; } case "opnsense_diag_traceroute": { const parsed = TracerouteSchema.parse(args); // OPNsense 24.7+: set is synchronous — executes traceroute and returns results const result = await client.post("/diagnostics/traceroute/set", { traceroute: { settings: { hostname: parsed.address, }, }, }); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } case "opnsense_diag_dns_lookup": { const parsed = DnsLookupSchema.parse(args); // OPNsense 24.7+: use reverse_lookup for IP→hostname resolution // Forward lookup (hostname→IP) is not available via API in 24.7 const result = await client.get( `/diagnostics/dns/reverse_lookup?address=${encodeURIComponent(parsed.hostname)}`, ); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } case "opnsense_diag_reverse_dns": { const parsed = z.object({ address: z.string().min(1) }).parse(args); const result = await client.get( `/diagnostics/dns/reverse_lookup?address=${encodeURIComponent(parsed.address)}`, ); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } case "opnsense_diag_fw_states": { const result = await client.post("/diagnostics/firewall/query_states"); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } case "opnsense_diag_fw_logs": { const parsed = FwLogsSchema.parse(args); const result = await client.get( `/diagnostics/firewall/log?limit=${parsed.limit}`, ); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } case "opnsense_diag_system_info": { const result = await client.get("/core/system/status"); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } case "opnsense_diag_log_system": { const parsed = LogQuerySchema.parse(args); const result = await fetchLogWithFallback(client, "system", parsed.limit); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } case "opnsense_diag_log_gateways": { const parsed = LogQuerySchema.parse(args); const result = await fetchLogWithFallback(client, "gateways", parsed.limit); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } case "opnsense_diag_log_routing": { const parsed = LogQuerySchema.parse(args); const result = await fetchLogWithFallback(client, "routing", parsed.limit); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } case "opnsense_diag_log_resolver": { const parsed = LogQuerySchema.parse(args); const result = await fetchLogWithFallback(client, "resolver", parsed.limit); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } default: return { content: [{ type: "text", text: `Unknown diagnostics tool: ${name}` }], }; } } catch (error: unknown) { const message = error instanceof Error ? error.message : "Unknown error"; return { content: [{ type: "text", text: `Error executing ${name}: ${message}` }], }; } }