unifi: list networks and set the DNS their DHCP hands out
Which DNS server the home network's DHCP hands out could be changed only in the controller's own interface or by hand against its API (novox/hq issue 198).
This commit is contained in:
@@ -23,6 +23,19 @@ export interface UnifiPortForward {
|
||||
site_id?: string;
|
||||
}
|
||||
|
||||
export interface UnifiNetwork {
|
||||
_id: string;
|
||||
name: string;
|
||||
purpose: string;
|
||||
ip_subnet?: string;
|
||||
dhcpd_enabled?: boolean;
|
||||
dhcpd_dns_enabled?: boolean;
|
||||
dhcpd_dns_1?: string;
|
||||
dhcpd_dns_2?: string;
|
||||
dhcpd_dns_3?: string;
|
||||
dhcpd_dns_4?: string;
|
||||
}
|
||||
|
||||
export interface UnifiDevice {
|
||||
_id: string;
|
||||
name: string;
|
||||
@@ -232,6 +245,17 @@ export class UnifiApiClient {
|
||||
await this.request<unknown>("DELETE", `/api/s/${this.site}/rest/portforward/${id}`);
|
||||
}
|
||||
|
||||
// --- Networks ---
|
||||
|
||||
async listNetworks(): Promise<UnifiNetwork[]> {
|
||||
return this.request<UnifiNetwork>("GET", `/api/s/${this.site}/rest/networkconf`);
|
||||
}
|
||||
|
||||
async updateNetwork(id: string, fields: Partial<UnifiNetwork>): Promise<UnifiNetwork> {
|
||||
const result = await this.request<UnifiNetwork>("PUT", `/api/s/${this.site}/rest/networkconf/${id}`, fields);
|
||||
return result[0];
|
||||
}
|
||||
|
||||
// --- Devices ---
|
||||
|
||||
async listDevices(): Promise<UnifiDevice[]> {
|
||||
|
||||
@@ -1,10 +1,23 @@
|
||||
// unifi's tools — its own code (novox/hq ADR 0039), importing unifi's own client. They return
|
||||
// structured data; the mesh serves them through the sdk's tool harness. unifi is tools-only (no
|
||||
// events entrypoint): the controller does not push lifecycle events the mesh consumes, so this
|
||||
// module reads its resources — port forwards, devices, clients — and exposes them, and stops there.
|
||||
// module reads its resources — port forwards, networks, devices, clients — and exposes them, and stops there.
|
||||
|
||||
import { registerModuleTools, type ToolDefinition } from "@novox/mesh-sdk/tools";
|
||||
import { UnifiApiClient, type UnifiPortForward } from "../client.js";
|
||||
import { UnifiApiClient, type UnifiNetwork, type UnifiPortForward } from "../client.js";
|
||||
|
||||
function summarizeNetwork(n: UnifiNetwork): Record<string, unknown> {
|
||||
const dns = [n.dhcpd_dns_1, n.dhcpd_dns_2, n.dhcpd_dns_3, n.dhcpd_dns_4].filter((s): s is string => !!s);
|
||||
return {
|
||||
id: n._id,
|
||||
name: n.name,
|
||||
purpose: n.purpose,
|
||||
subnet: n.ip_subnet ?? null,
|
||||
dhcp: n.dhcpd_enabled ?? null,
|
||||
// What DHCP hands out as DNS: the listed servers when set, otherwise the gateway itself.
|
||||
dhcp_dns: n.dhcpd_dns_enabled ? dns : "the gateway",
|
||||
};
|
||||
}
|
||||
|
||||
function summarizePortForward(r: UnifiPortForward): Record<string, unknown> {
|
||||
return {
|
||||
@@ -88,6 +101,40 @@ export function getUnifiTools(unifi: UnifiApiClient): ToolDefinition[] {
|
||||
return { deleted: true, id: String(args.id) };
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "unifi_list_networks",
|
||||
description: "List the networks the UniFi controller manages, with the DNS servers each one's DHCP hands out.",
|
||||
input: {},
|
||||
run: async () => {
|
||||
const nets = await unifi.listNetworks();
|
||||
return { count: nets.length, networks: nets.map(summarizeNetwork) };
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "unifi_set_network_dns",
|
||||
description:
|
||||
"Set the DNS servers a network's DHCP hands out to its devices (see unifi_list_networks for ids). " +
|
||||
"Up to four addresses, comma-separated; \"gateway\" hands out the gateway itself. Devices pick it up when they renew.",
|
||||
input: {
|
||||
id: { type: "string", description: "the network id" },
|
||||
dns: { type: "string", description: "comma-separated DNS server addresses, or \"gateway\"" },
|
||||
},
|
||||
run: async (args) => {
|
||||
const asked = String(args.dns ?? "").trim();
|
||||
if (!asked) return { updated: false, reason: "say dns: addresses, or \"gateway\"" };
|
||||
const servers = asked === "gateway" ? [] : asked.split(",").map((s) => s.trim()).filter(Boolean);
|
||||
if (servers.length > 4) return { updated: false, reason: "DHCP hands out at most four DNS servers" };
|
||||
const fields: Partial<UnifiNetwork> = {
|
||||
dhcpd_dns_enabled: servers.length > 0,
|
||||
dhcpd_dns_1: servers[0] ?? "",
|
||||
dhcpd_dns_2: servers[1] ?? "",
|
||||
dhcpd_dns_3: servers[2] ?? "",
|
||||
dhcpd_dns_4: servers[3] ?? "",
|
||||
};
|
||||
const net = await unifi.updateNetwork(String(args.id), fields);
|
||||
return { updated: summarizeNetwork(net) };
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "unifi_list_devices",
|
||||
description: "List the network devices (APs, switches, gateways) the UniFi controller manages.",
|
||||
|
||||
Reference in New Issue
Block a user