//go:build standalone package checker import ( "errors" "net" "net/http" "strings" "github.com/miekg/dns" sdk "git.happydns.org/checker-sdk-go/checker" ) // RenderForm exposes a minimal form accepting either an IP address or a // reverse-arpa owner, plus an optional expected hostname (for FCrDNS). func (p *ptrProvider) RenderForm() []sdk.CheckerOptionField { return []sdk.CheckerOptionField{ { Id: "ip", Type: "string", Label: "IP address or reverse name", Placeholder: "2001:db8::1 or 4.3.2.1.in-addr.arpa", Required: true, Description: "IPv4, IPv6 or fully-qualified reverse name. The checker derives one from the other automatically.", }, { Id: "expected", Type: "string", Label: "Expected hostname", Placeholder: "mail.example.com", Description: "Optional. When set, the checker compares it to the PTR served by the reverse zone.", }, } } // ParseForm turns the submitted input into a minimal CheckerOptions set // suitable for the Collect pipeline. We encode the inputs as a synthetic // svcs.PTR service so Collect's existing unmarshaller picks it up. func (p *ptrProvider) ParseForm(r *http.Request) (sdk.CheckerOptions, error) { raw := strings.TrimSpace(r.FormValue("ip")) if raw == "" { return nil, errors.New("IP address or reverse name is required") } var owner string if ip := net.ParseIP(raw); ip != nil { rev, err := dns.ReverseAddr(ip.String()) if err != nil { return nil, err } owner = rev } else { owner = dns.Fqdn(raw) } expected := strings.TrimSpace(r.FormValue("expected")) if expected == "" { // Build a service payload with no declared target: the checker will // still do existence + FCrDNS. return sdk.CheckerOptions{ "domain_name": strings.TrimSuffix(owner, "."), "subdomain": "@", }, nil } return sdk.CheckerOptions{ "domain_name": strings.TrimSuffix(owner, "."), "subdomain": "@", "expected_target": expected, }, nil }