#!/usr/bin/env python3 # Writes docs/options.md from the option catalog in internal/dhcp4/catalog.go # (the options by name, and the reserved codes). Run from the repository # root after changing the catalog: # # python3 scripts/optionsdoc.py import re src = open("internal/dhcp4/catalog.go").read() rows = re.findall(r'\{Code: (\d+), Name: "([^"]+)", Type: (\w+), Help: "((?:[^"\\]|\\.)*)"', src) types = {"TypeIP": "ip", "TypeIPs": "ips", "TypeString": "string", "TypeU8": "uint8", "TypeU16": "uint16", "TypeU32": "uint32", "TypeI32": "int32", "TypeBool": "bool", "TypeDomains": "domains", "TypeRoutes": "routes", "TypeHex": "hex"} reserved = re.findall(r'^\t(\d+): +"([^"]+)",', src, re.M) out = """# DHCP options Options are set by name, or by number with a type. Set them in the settings (every subnet), on a subnet, or on a reservation; the most specific wins ([subnets.md](subnets.md#options)). ```sh steward settings set --option domain-name-servers=10.0.10.2,10.0.10.3 steward subnet update office --option routers=10.0.10.1 --unset-option ntp-servers steward reservation update nas --option 224:string=hello # an option Steward doesn't know ``` `steward option list` prints the list below; the web UI offers it in each options editor. (This page is written by scripts/optionsdoc.py from the catalog in internal/dhcp4/catalog.go.) ## Options by name | Code | Name | Type | What | |---:|---|---|---| """ for code, name, typ, help_ in rows: help_ = help_.replace('\\"', '"').replace("|", "\\|") out += f"| {code} | `{name}` | {types[typ]} | {help_} |\n" out += """ The names are Kea's, so a Kea configuration's options carry over. ## Value types | Type | How to write it | Example | |---|---|---| | ip | an IPv4 address | `10.0.10.255` | | ips | IPv4 addresses, separated by commas or spaces, in order of preference | `10.0.10.2, 10.0.10.3` | | string | text, as it is | `lan` | | uint8, uint16, uint32 | a whole number | `1500` | | int32 | a whole number, maybe negative | `-3600` | | bool | `true` or `false` (`yes`/`no`, `on`/`off`, `1`/`0` work too) | `false` | | domains | domain names, separated by commas or spaces; sent in DNS wire format (RFC 3397) | `lan, home.arpa` | | routes | `DESTINATION/LENGTH via ROUTER`, separated by commas (Kea's `DEST - ROUTER` works too); RFC 3442 | `10.20.0.0/16 via 10.0.10.1, 0.0.0.0/0 via 10.0.10.1` | | hex | bytes in hex, with or without colons | `01:02:0a` | Values are checked when they are set, and stored in a canonical form: `10.0.10.2,10.0.10.3` becomes `10.0.10.2, 10.0.10.3`. Clients that use `classless-static-route` ignore `routers`, so give the default route in it as well (`0.0.0.0/0 via ROUTER`). ## Options by number An option the list doesn't have is set by its number and type, `CODE:TYPE=VALUE`; without a type the value is hex: ```sh steward subnet update office --option 224:string=hello --option 225=01:02 ``` In the API, give `{"option": "224", "type": "string", "value": "hello"}`. ## Options Steward sets itself These can't be set; Steward fills them in (`option_reserved` if you try): | Code | Why | |---:|---| """ for code, why in reserved: out += f"| {code} | {why} |\n" open("docs/options.md", "w").write(out) print("wrote docs/options.md")