Initial commit
This commit is contained in:
commit
542ebdea34
40 changed files with 4592 additions and 0 deletions
79
checker/service.go
Normal file
79
checker/service.go
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
// This file is part of the happyDomain (R) project.
|
||||
// Copyright (c) 2020-2026 happyDomain
|
||||
// Authors: Pierre-Olivier Mercier, et al.
|
||||
|
||||
package checker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
sdk "git.happydns.org/checker-sdk-go/checker"
|
||||
happydns "git.happydns.org/happyDomain/model"
|
||||
"git.happydns.org/happyDomain/services/abstract"
|
||||
)
|
||||
|
||||
// resolver is the *net.Resolver used to discover additional A/AAAA records
|
||||
// beyond what abstract.Server pins. Overridable in tests.
|
||||
var resolver = net.DefaultResolver
|
||||
|
||||
// resolveServer extracts the *abstract.Server payload from the options.
|
||||
func resolveServer(opts sdk.CheckerOptions) (*abstract.Server, error) {
|
||||
svc, ok := sdk.GetOption[happydns.ServiceMessage](opts, OptionService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no service in options: did the host wire AutoFillService?")
|
||||
}
|
||||
if svc.Type != "abstract.Server" {
|
||||
return nil, fmt.Errorf("service is %q, expected abstract.Server", svc.Type)
|
||||
}
|
||||
var server abstract.Server
|
||||
if err := json.Unmarshal(svc.Service, &server); err != nil {
|
||||
return nil, fmt.Errorf("unmarshal abstract.Server: %w", err)
|
||||
}
|
||||
return &server, nil
|
||||
}
|
||||
|
||||
// addressesFromServer returns the (host, ips) tuple to probe.
|
||||
func addressesFromServer(server *abstract.Server) (host string, ips []string) {
|
||||
if server.A != nil && len(server.A.A) > 0 {
|
||||
host = strings.TrimSuffix(server.A.Hdr.Name, ".")
|
||||
ips = append(ips, server.A.A.String())
|
||||
}
|
||||
if server.AAAA != nil && len(server.AAAA.AAAA) > 0 {
|
||||
if host == "" {
|
||||
host = strings.TrimSuffix(server.AAAA.Hdr.Name, ".")
|
||||
}
|
||||
ips = append(ips, server.AAAA.AAAA.String())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// discoverIPs resolves host through the system resolver and returns every
|
||||
// A/AAAA address it knows about. abstract.Server only carries one pinned A
|
||||
// and one pinned AAAA, so a domain backed by multiple records would only
|
||||
// be partially probed without this.
|
||||
//
|
||||
// Failures are non-fatal: callers fall back to the pinned IPs from
|
||||
// addressesFromServer. Returned IPs are deduped against `seen`.
|
||||
func discoverIPs(ctx context.Context, host string, seen map[string]struct{}) []string {
|
||||
if host == "" {
|
||||
return nil
|
||||
}
|
||||
addrs, err := resolver.LookupIP(ctx, "ip", host)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
var out []string
|
||||
for _, ip := range addrs {
|
||||
s := ip.String()
|
||||
if _, dup := seen[s]; dup {
|
||||
continue
|
||||
}
|
||||
seen[s] = struct{}{}
|
||||
out = append(out, s)
|
||||
}
|
||||
return out
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue