core

package module
v0.0.0-...-279a53c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 29, 2026 License: BSD-2-Clause Imports: 27 Imported by: 0

Documentation

Overview

* Copyright (c) 2024 Johan Stenstam, johani@johani.org

* Copyright (c) 2024 Johan Stenstam, johan.stenstam@internetstiftelsen.se

* Copyright (c) 2024 Johan Stenstam, johan.stenstam@internetstiftelsen.se

Index

Constants

View Source
const (
	TypeNOTIFY       = 65280 // OBE, replaced by DSYNC (RFC 9859)
	TypeMSIGNER      = 65281 // OBE, replaced by HSYNC
	TypeHSYNC        = 65282 // Legacy provider enrollment
	TypeHSYNC2       = 65283 // Legacy provider enrollment (string flags)
	TypeTSYNC        = 65284 // Transfer sync
	TypeHSYNC3       = 65285 // Per-provider enrollment
	TypeHSYNCPARAM   = 65286 // Zone-wide multi-provider policy
	TypeCHUNK        = 65288 // Unified Chunk/Manifest
	TypeJSONMANIFEST = 65289 // Older version of CHUNK
	TypeJSONCHUNK    = 65289 // Older version of CHUNK
)

All experimental types use the private use range (65280-65534).

View Source
const (
	FormatJSON = 1 // JSON format (original format)
	FormatJWT  = 2 // JWT format (signed manifest with flattened claims)

)

Format constants for CHUNK RR type

View Source
const (
	SchemeNotify  = 1
	SchemeUpdate  = 2
	SchemeScanner = 3
	SchemeAPI     = 4
	// Private schemes:
	SchemeMSUpdate = 129
	SchemeReport   = 130
)
View Source
const (
	HsyncStateON     uint8 = 1
	HsyncStateOFF    uint8 = 0
	HsyncNSmgmtOWNER uint8 = 1
	HsyncNSmgmtAGENT uint8 = 2
	HsyncSignYES     uint8 = 1
	HsyncSignNO      uint8 = 0
)
View Source
const (
	// Single bit flags
	FlagNSmgmt uint16 = 1 << 0 // bit 0: 0=OWNER, 1=AGENT
	FlagSign   uint16 = 1 << 1 // bit 1: 0=NOSIGN, 1=SIGN
	FlagAudit  uint16 = 1 << 2 // bit 2: 0=NO, 1=YES

	// Multi-bit fields
	ParentSyncMask  uint16 = 0x7 << 3 // bits 3-5: 3 bits for parentsync
	ParentSyncShift uint   = 3        // shift amount for parentsync field
)

Define bit positions and masks in the Flags field

View Source
const (
	ParentSyncOwner uint16 = iota
	ParentSyncNotify
	ParentSyncUpdate
	ParentSyncAPI
)

ParentSync values (using iota for sequential values)

View Source
const (
	Hsync2StateON  uint8 = 1
	Hsync2StateOFF uint8 = 0
)

Keep these constants for State

View Source
const (
	HsyncParentSyncOwner uint8 = 0 // zone owner handles parent sync
	HsyncParentSyncAgent uint8 = 1 // providers coordinate via leader election
)

ParentSync constants: who handles parent synchronisation. The mechanism (NOTIFY, UPDATE, etc.) is announced by the parent via DSYNC.

View Source
const (
	MsignerMethodDNS = 1
	MsignerMethodAPI = 2
	MsignerStateON   = 1
	MsignerStateOFF  = 0
)
View Source
const TypeDELEG = 65287
View Source
const TypeDSYNC = 0x0042 // 66 is the official IANA code
View Source
const TypeJWK = 0xFF2C // 65324 in decimal (private use range 65280-65534)

TypeJWK is the DNS type code for JWK records. Using private use range for testing. IANA allocation should be requested for production.

Variables

View Source
var AgentMsgToString = map[AgentMsg]string{
	AgentMsgHello:        "HELLO",
	AgentMsgBeat:         "BEAT",
	AgentMsgNotify:       "SYNC",
	AgentMsgUpdate:       "UPDATE",
	AgentMsgRfi:          "RFI",
	AgentMsgStatus:       "STATUS",
	AgentMsgPing:         "PING",
	AgentMsgKeystate:     "KEYSTATE",
	AgentMsgEdits:        "EDITS",
	AgentMsgConfig:       "CONFIG",
	AgentMsgAudit:        "AUDIT",
	AgentMsgStatusUpdate: "STATUS-UPDATE",
}
View Source
var FormatToString = map[uint8]string{
	FormatJSON: "JSON",
	FormatJWT:  "JWT",
}

FormatToString maps format constants to their string representations

View Source
var Hsync2StateToString = map[uint8]string{
	Hsync2StateON:  "ON",
	Hsync2StateOFF: "OFF",
}

Keep the State mappings

View Source
var HsyncNSmgmtToString = map[uint8]string{
	HsyncNSmgmtOWNER: "OWNER",
	HsyncNSmgmtAGENT: "AGENT",
}
View Source
var HsyncParentSyncToString = map[uint8]string{
	HsyncParentSyncOwner: "owner",
	HsyncParentSyncAgent: "agent",
}
View Source
var HsyncSignToString = map[uint8]string{
	HsyncSignYES: "SIGN",
	HsyncSignNO:  "NOSIGN",
}
View Source
var HsyncStateToString = map[uint8]string{
	HsyncStateON:  "ON",
	HsyncStateOFF: "OFF",
}
View Source
var (
	// ManifestJSONFormat controls whether manifest chunks are displayed as JSON or base64
	// true = JSON (default), false = base64
	ManifestJSONFormat = true
)
View Source
var MsignerMethodToString = map[MsignerMethod]string{
	MsignerMethodDNS: "DNS",
	MsignerMethodAPI: "API",
}
View Source
var SchemeToString = map[DsyncScheme]string{
	SchemeNotify:  "NOTIFY",
	SchemeUpdate:  "UPDATE",
	SchemeScanner: "SCANNER",
	SchemeAPI:     "API",

	SchemeMSUpdate: "MSUPDATE",
	SchemeReport:   "REPORT",
}
View Source
var StateToString = map[uint8]string{
	MsignerStateON:  "ON",
	MsignerStateOFF: "OFF",
}
View Source
var StringToFormat = map[string]uint8{
	"JSON": FormatJSON,
	"JWT":  FormatJWT,
}

StringToFormat maps string representations to format constants (reverse of FormatToString) NOTE: This map must be kept in sync with FormatToString - when adding a new format to FormatToString, also add the corresponding entry here.

View Source
var StringToHsync2State = map[string]uint8{
	"ON":  Hsync2StateON,
	"OFF": Hsync2StateOFF,
}
View Source
var StringToHsyncNSmgmt = map[string]uint8{
	"OWNER": HsyncNSmgmtOWNER,
	"AGENT": HsyncNSmgmtAGENT,
}
View Source
var StringToHsyncParentSync = map[string]uint8{
	"owner": HsyncParentSyncOwner,
	"agent": HsyncParentSyncAgent,
}
View Source
var StringToHsyncSign = map[string]uint8{
	"SIGN":   HsyncSignYES,
	"NOSIGN": HsyncSignNO,
}
View Source
var StringToHsyncState = map[string]uint8{
	"ON":  HsyncStateON,
	"OFF": HsyncStateOFF,
}
View Source
var StringToMsignerMethod = map[string]MsignerMethod{
	"DNS": MsignerMethodDNS,
	"API": MsignerMethodAPI,
}
View Source
var StringToScheme = map[string]DsyncScheme{
	"NOTIFY":   SchemeNotify,
	"UPDATE":   SchemeUpdate,
	"SCANNER":  SchemeScanner,
	"API":      SchemeAPI,
	"MSUPDATE": SchemeMSUpdate,
	"REPORT":   SchemeReport,
	"REPORTER": SchemeReport,
	"1":        SchemeNotify,
	"2":        SchemeUpdate,
	"3":        SchemeScanner,
	"4":        SchemeAPI,

	"129": SchemeMSUpdate,
	"130": SchemeReport,
}
View Source
var StringToState = map[string]uint8{
	"ON":  MsignerStateON,
	"OFF": MsignerStateOFF,
}
View Source
var TransportToString = map[Transport]string{
	TransportDo53: "do53",
	TransportDoT:  "dot",
	TransportDoH:  "doh",
	TransportDoQ:  "doq",
}

Functions

func BuildNotifyQNAME

func BuildNotifyQNAME(distributionID, zone string) string

BuildNotifyQNAME constructs a NOTIFY QNAME from a distribution ID and zone.

The distribution ID is prepended as a label to the zone, following the pattern: <distributionID>.<zone>

This pattern is used by:

  • KDC: distributionID = distribution ID (e.g., "a1b2.kdc.example.com.")
  • Agents: distributionID = sync operation ID (e.g., "sync123.agent.example.com.")

The zone is ensured to be a fully-qualified domain name (FQDN) with trailing dot.

Parameters:

  • distributionID: The unique identifier for this operation (distribution, sync, etc.)
  • zone: The base zone name (will be made FQDN if not already)

Returns:

  • The constructed NOTIFY QNAME as FQDN

Example:

BuildNotifyQNAME("a1b2", "kdc.example.com") -> "a1b2.kdc.example.com."

func CalculateCHUNKHMAC

func CalculateCHUNKHMAC(chunk *CHUNK, hmacKey []byte) error

CalculateCHUNKHMAC calculates HMAC-SHA256 for a CHUNK manifest record.

The HMAC is calculated over: Format (1 byte) + JSON data This provides integrity protection for the manifest. Only manifest chunks (Sequence=0) can have HMAC protection.

The HMAC key is typically derived from the recipient's long-term public key, ensuring that only the intended recipient can verify the manifest integrity.

Parameters:

  • chunk: The CHUNK manifest to calculate HMAC for (must have Sequence=0)
  • hmacKey: The 32-byte HMAC key (SHA-256)

Returns:

  • Error if the chunk is not a manifest, key is wrong size, or calculation fails
  • On success, sets chunk.HMAC and chunk.HMACLen

func DecodeJWKToPublicKey

func DecodeJWKToPublicKey(jwkData string) (crypto.PublicKey, string, error)

DecodeJWKToPublicKey parses base64url-encoded JWK JSON to Go crypto.PublicKey. Returns: (public-key, key-algorithm, error)

The returned algorithm string is one of: "ES256" (P-256), "X25519"

func EncodePublicKeyToJWK

func EncodePublicKeyToJWK(key crypto.PublicKey, use string) (string, string, error)

EncodePublicKeyToJWK converts a Go crypto.PublicKey to base64url-encoded JWK JSON. Returns: (base64url-jwk, key-algorithm, error)

Supported key types:

  • *ecdsa.PublicKey (P-256 curve)
  • ed25519.PublicKey (for X25519, converted from Ed25519)

The returned algorithm string is one of: "ES256" (P-256), "X25519"

The use parameter specifies the intended use: "" (omit), "sig" (signing), "enc" (encryption)

func ExtractDistributionIDFromQNAME

func ExtractDistributionIDFromQNAME(qname, zone string) (string, error)

ExtractDistributionIDFromQNAME extracts a distribution ID from a NOTIFY QNAME.

Given a QNAME like "a1b2.kdc.example.com." and a zone "kdc.example.com.", this function returns "a1b2".

The function validates that the QNAME ends with the zone and returns an error if it doesn't.

Parameters:

  • qname: The NOTIFY QNAME to extract from (FQDN)
  • zone: The base zone name (will be made FQDN if not already)

Returns:

  • The distribution ID (without trailing dots), or an error if:
  • QNAME doesn't end with zone
  • QNAME equals zone (no distribution ID present)
  • Zone is empty

Example:

ExtractDistributionIDFromQNAME("a1b2.kdc.example.com.", "kdc.example.com.") -> "a1b2", nil

func GetJWKKeyType

func GetJWKKeyType(jwkData string) (string, string, error)

GetJWKKeyType returns the key type and curve from base64url-encoded JWK data without fully decoding the key. Useful for inspection. Returns: (kty, crv, error)

func IsDuplicate

func IsDuplicate(r1, r2 dns.RR) bool

IsDuplicate checks if two RRs are duplicates, excluding TTL. Wraps dns.IsDuplicate but fixes PrivateRR comparison: miekg/dns PrivateRR.isDuplicate always returns false, so we compare by wire format instead.

func IsEncryptedTransport

func IsEncryptedTransport(t Transport) bool

IsEncryptedTransport returns true if the transport is encrypted (doq, dot, doh), false for do53

func IsJSONManifest

func IsJSONManifest(chunk *CHUNK) bool

IsJSONManifest checks if a CHUNK manifest uses JSON format.

func IsJWTManifest

func IsJWTManifest(chunk *CHUNK) bool

IsJWTManifest checks if a CHUNK manifest uses JWT format. This can be used for format auto-detection before choosing the appropriate extraction method.

func NewCHUNK

func NewCHUNK() dns.PrivateRdata

func NewDELEG

func NewDELEG() dns.PrivateRdata

func NewDSYNC

func NewDSYNC() dns.PrivateRdata

func NewHSYNC

func NewHSYNC() dns.PrivateRdata

func NewHSYNC2

func NewHSYNC2() dns.PrivateRdata

func NewHSYNC3

func NewHSYNC3() dns.PrivateRdata

func NewHSYNCPARAM

func NewHSYNCPARAM() dns.PrivateRdata

func NewJSONCHUNK

func NewJSONCHUNK() dns.PrivateRdata

func NewJSONMANIFEST

func NewJSONMANIFEST() dns.PrivateRdata

func NewJWK

func NewJWK() dns.PrivateRdata

NewJWK creates a new JWK PrivateRdata

func NewMSIGNER

func NewMSIGNER() dns.PrivateRdata

func NewNOTIFY

func NewNOTIFY() dns.PrivateRdata

func NewTSYNC

func NewTSYNC() dns.PrivateRdata

func ParseTransportString

func ParseTransportString(s string) (map[string]uint8, error)

ParseTransportString parses a transport string like "doq:30,dot:20" into a map. - Keys are lower-cased and trimmed - Values must be integers in [0,100] - Duplicate keys are rejected

func RRsetDiffer

func RRsetDiffer(zone string, newrrs, oldrrs []dns.RR, rrtype uint16, lg *log.Logger, verbose, debug bool) (bool, []dns.RR, []dns.RR)

RRsetDiffer compares old and new DNS resource record slices for a given RR type in a zone, ignoring RRSIG records. It returns: a boolean that is true if the RRsets differ, a slice of records present in newrrs but not in oldrrs (adds), and a slice of records present in oldrrs but not in newrrs (removes). RRsetDiffer compares old and new DNS resource records of a specific type in a zone and reports whether the RRsets differ, returning slices of records that were added and removed. It ignores RRSIG records and determines equality using dns.IsDuplicate. When verbose or debug are true, comparison details are written to the provided logger.

func RegisterCHUNKRR

func RegisterCHUNKRR() error

func RegisterDelegRR

func RegisterDelegRR() error

johani

func RegisterDsyncRR

func RegisterDsyncRR() error

func RegisterHsync2RR

func RegisterHsync2RR() error

func RegisterHsync3RR

func RegisterHsync3RR() error

func RegisterHsyncRR

func RegisterHsyncRR() error

func RegisterHsyncparamRR

func RegisterHsyncparamRR() error

func RegisterJSONCHUNKRR

func RegisterJSONCHUNKRR() error

func RegisterJSONMANIFESTRR

func RegisterJSONMANIFESTRR() error

func RegisterJWKRR

func RegisterJWKRR()

RegisterJWKRR registers the JWK type with miekg/dns

func RegisterMsignerRR

func RegisterMsignerRR() error

func RegisterNotifyRR

func RegisterNotifyRR() error

func RegisterTsyncRR

func RegisterTsyncRR() error

func ValidateJWK

func ValidateJWK(jwkData string) error

ValidateJWK checks if base64url-encoded JWK data is well-formed. This does basic validation without converting to crypto.PublicKey.

func VerifyCHUNKHMAC

func VerifyCHUNKHMAC(chunk *CHUNK, hmacKey []byte) (bool, error)

VerifyCHUNKHMAC verifies the HMAC-SHA256 for a CHUNK manifest record.

This function recalculates the HMAC using the provided key and compares it with the HMAC stored in the chunk using constant-time comparison to prevent timing attacks.

Parameters:

  • chunk: The CHUNK manifest to verify (must have Sequence=0)
  • hmacKey: The 32-byte HMAC key (SHA-256)

Returns:

  • true if HMAC verification succeeds
  • false with error if:
  • Chunk is not a manifest (Sequence != 0)
  • HMAC key is wrong size
  • HMAC is not set in the chunk
  • HMAC verification fails (false, nil)

Types

type AgentAuditPost

type AgentAuditPost struct {
	MessageType  AgentMsg    // AgentMsgAudit
	MyIdentity   string      // Sender identity
	YourIdentity string      // Recipient identity
	Zone         string      // Zone (FQDN)
	AuditData    interface{} // Zone data repo snapshot (placeholder)
	Message      string      // Optional status message
	Time         time.Time   // Timestamp
}

AgentAuditPost represents an AUDIT response message carrying audit data back to the requesting agent as a separate transaction (two-phase pattern). Sent by the receiving agent in response to an RFI AUDIT request.

type AgentBeatPost

type AgentBeatPost struct {
	MessageType    AgentMsg
	MyIdentity     string          // Sender's identity
	YourIdentity   string          // Recipient's identity
	MyBeatInterval uint32          // Intended beat interval in seconds
	Zones          []string        // Zones shared with the remote agent
	Time           time.Time       // Message timestamp
	Gossip         json.RawMessage `json:"Gossip,omitempty"` // Gossip data (opaque at core level)
}

AgentBeatPost represents a heartbeat message. Used by both API and DNS transports.

type AgentBeatResponse

type AgentBeatResponse struct {
	Status       string // ok | error
	MyIdentity   string // Responder's identity
	YourIdentity string // Original sender
	Time         time.Time
	Client       string
	Msg          string
	Error        bool
	ErrorMsg     string
}

AgentBeatResponse represents the response to a heartbeat.

type AgentConfigPost

type AgentConfigPost struct {
	MessageType  AgentMsg          // AgentMsgConfig
	MyIdentity   string            // Sender identity
	YourIdentity string            // Recipient identity
	Zone         string            // Zone (FQDN)
	Subtype      string            // Config subtype: "upstream", "downstream", "sig0key"
	ConfigData   map[string]string // Key-value config data
	Message      string            // Optional status message
	Time         time.Time         // Timestamp
}

AgentConfigPost represents a CONFIG response message carrying config data back to the requesting agent as a separate transaction (two-phase pattern). Sent by the receiving agent in response to an RFI CONFIG request.

type AgentEditsPost

type AgentEditsPost struct {
	MessageType  AgentMsg                       // AgentMsgEdits
	MyIdentity   string                         // Combiner identity
	YourIdentity string                         // Requesting agent identity
	Zone         string                         // Zone (FQDN)
	AgentRecords map[string]map[string][]string // All agents' contributions (agentID → owner → []RR strings)
	Message      string                         // Optional status message
	Time         time.Time                      // Timestamp
}

AgentEditsPost represents an EDITS message carrying an agent's current contributions from the combiner back to the requesting agent. Modeled on AgentKeystatePost. The combiner sends this in response to an RFI EDITS request.

type AgentHelloPost

type AgentHelloPost struct {
	MessageType  AgentMsg
	Name         string    `json:"name,omitempty"` // DEPRECATED: Unused field
	MyIdentity   string    // Agent identity (FQDN)
	YourIdentity string    // Recipient identity (FQDN)
	Addresses    []string  `json:"addresses,omitempty"` // DEPRECATED: Use DNS discovery (SVCB records) instead
	Port         uint16    `json:"port,omitempty"`      // DEPRECATED: Use DNS discovery (URI scheme) instead
	TLSA         dns.TLSA  `json:"tlsa,omitempty"`      // DEPRECATED: Use DNS discovery (TLSA query) instead
	Zone         string    // Zone that triggered this hello (only one zone per hello)
	Time         time.Time // Message timestamp
}

AgentHelloPost represents a hello handshake message. Used by both API and DNS transports.

type AgentHelloResponse

type AgentHelloResponse struct {
	Status       string // ok | error
	MyIdentity   string // Responder's identity
	YourIdentity string // Original sender
	Time         time.Time
	Msg          string
	Error        bool
	ErrorMsg     string
}

AgentHelloResponse represents the response to a hello message.

type AgentKeystatePost

type AgentKeystatePost struct {
	MessageType  AgentMsg            // AgentMsgKeystate
	MyIdentity   string              // Sender's identity
	YourIdentity string              // Recipient's identity
	Zone         string              // Zone this key belongs to (FQDN)
	KeyTag       uint16              // DNSKEY key tag (unused for inventory)
	Algorithm    uint8               // DNSKEY algorithm number (unused for inventory)
	Signal       string              // "propagated", "rejected", "removed", "published", "retired", "inventory"
	Message      string              // Optional detail (e.g. rejection reason)
	KeyInventory []KeyInventoryEntry // Complete key inventory (only when Signal == "inventory")
	Time         time.Time           // Message timestamp
}

AgentKeystatePost represents a KEYSTATE message for key lifecycle signaling. Used for agent↔signer communication about DNSKEY propagation status. When Signal == "inventory", KeyInventory carries the complete key set for the zone.

type AgentKeystateResponse

type AgentKeystateResponse struct {
	Status       string // ok | error
	MyIdentity   string // Responder's identity
	YourIdentity string // Original sender
	Zone         string // Echoed zone
	KeyTag       uint16 // Echoed key tag
	Signal       string // Echoed signal
	Time         time.Time
	Msg          string
	Error        bool
	ErrorMsg     string
}

AgentKeystateResponse represents the response to a KEYSTATE message.

type AgentMsg

type AgentMsg string

AgentMsg identifies the type of agent message. String type for human-readable JSON and easy extensibility.

const (
	AgentMsgHello        AgentMsg = "hello"
	AgentMsgBeat         AgentMsg = "beat"
	AgentMsgNotify       AgentMsg = "sync"   // sync: agent→agent zone data synchronization
	AgentMsgUpdate       AgentMsg = "update" // update: agent→combiner zone data contribution
	AgentMsgRfi          AgentMsg = "rfi"
	AgentMsgStatus       AgentMsg = "status"
	AgentMsgPing         AgentMsg = "ping"
	AgentMsgKeystate     AgentMsg = "keystate"
	AgentMsgEdits        AgentMsg = "edits"
	AgentMsgConfig       AgentMsg = "config"
	AgentMsgAudit        AgentMsg = "audit"
	AgentMsgStatusUpdate AgentMsg = "status-update"
)

type AgentMsgPost

type AgentMsgPost struct {
	MessageType  AgentMsg            // "sync", "update", "rfi", "status"
	OriginatorID string              // Original author of the update
	YourIdentity string              // Recipient's identity
	Addresses    []string            `json:"addresses,omitempty"` // DEPRECATED: Use DNS discovery (SVCB records) instead
	Port         uint16              `json:"port,omitempty"`      // DEPRECATED: Use DNS discovery (URI scheme) instead
	TLSA         dns.TLSA            `json:"tlsa,omitempty"`      // DEPRECATED: Use DNS discovery (TLSA query) instead
	Zone         string              // Zone this message refers to (only one zone per message)
	Records      map[string][]string `json:"records,omitempty"`    // Resource records grouped by owner name (legacy: Class-overloaded)
	Operations   []RROperation       `json:"operations,omitempty"` // Explicit operations (takes precedence over Records)
	Time         time.Time           // Message timestamp
	RfiType      string              // Type of RFI request if MessageType is RFI
	RfiSubtype   string              `json:"rfi_subtype,omitempty"` // Subtype within an RFI type (e.g. "upstream", "sig0key" for CONFIG)
	Nonce        string              `json:"nonce,omitempty"`       // Unique nonce for replay protection and confirmation correlation
	ZoneClass    string              `json:"zone_class,omitempty"`  // "mp" (default) or "provider"
	Publish      *PublishInstruction `json:"publish,omitempty"`     // KEY/CDS publication instruction for combiner
}

AgentMsgPost represents a generic agent message (sync, update, rfi, status). Used by both API and DNS transports.

type AgentMsgResponse

type AgentMsgResponse struct {
	Status      string // ok | error
	Time        time.Time
	AgentId     string
	Msg         string
	Zone        string
	RfiResponse map[string]*RfiData
	Error       bool
	ErrorMsg    string
}

AgentMsgResponse represents the response to an AgentMsgPost.

type AgentPingPost

type AgentPingPost struct {
	MessageType  AgentMsg  // AgentMsgPing
	MyIdentity   string    // Sender's identity
	YourIdentity string    // Recipient's identity
	Nonce        string    // For round-trip verification
	Time         time.Time // Message timestamp
}

AgentPingPost represents a ping message for connectivity testing. Used by both API and DNS transports.

type AgentPingResponse

type AgentPingResponse struct {
	Status       string // ok | error
	MyIdentity   string // Responder's identity
	YourIdentity string // Original sender
	Nonce        string // Echo from request
	Time         time.Time
	Msg          string
	Error        bool
	ErrorMsg     string
}

AgentPingResponse represents the response to a ping message.

type CHUNK

type CHUNK struct {
	Format     uint8  // Format identifier (used for manifest, unused for data chunks)
	HMACLen    uint16 // HMAC length (0 for data chunks, >0 for manifest)
	HMAC       []byte // HMAC-SHA256 checksum (only present if HMACLen > 0)
	Sequence   uint16 // Chunk sequence number (unused when Total=0)
	Total      uint16 // Total chunks or 0 for manifest (0 = manifest, >0 = data chunk)
	DataLength uint16 // Length of data
	Data       []byte // Format-specific data (JSON manifest or chunk payload)
}

func CreateCHUNKManifest

func CreateCHUNKManifest(manifestData *ManifestData, format uint8) (*CHUNK, error)

CreateCHUNKManifest creates a CHUNK manifest record from manifest data.

Manifest chunks are identified by Sequence=0. The Total field contains the number of data chunks. The Data field stores raw JSON bytes (not base64-encoded).

Parameters:

  • manifestData: The manifest structure containing chunk count, metadata, and optional payload
  • format: The serialization format (typically FormatJSON=1)

Returns:

  • A CHUNK record with Sequence=0, or an error if JSON marshaling fails

func (*CHUNK) Copy

func (rd *CHUNK) Copy(dest dns.PrivateRdata) error

func (*CHUNK) Len

func (rd *CHUNK) Len() int

func (*CHUNK) Pack

func (rd *CHUNK) Pack(buf []byte) (int, error)

func (*CHUNK) Parse

func (rd *CHUNK) Parse(txt []string) error

func (CHUNK) String

func (rd CHUNK) String() string

func (*CHUNK) Unpack

func (rd *CHUNK) Unpack(buf []byte) (int, error)

type ConcurrentMap

type ConcurrentMap[K comparable, V any] struct {
	// contains filtered or unexported fields
}

A "thread" safe map of type string:Anything. To avoid lock bottlenecks this map is dived to several (shardCount) map shards.

func NewCmap

func NewCmap[V any]() *ConcurrentMap[string, V]

Creates a new concurrent map.

func NewStringer

func NewStringer[K Stringer, V any]() ConcurrentMap[K, V]

Creates a new concurrent map.

func NewWithCustomShardingFunction

func NewWithCustomShardingFunction[K comparable, V any](sharding func(key K) uint32) ConcurrentMap[K, V]

Creates a new concurrent map.

func (*ConcurrentMap[K, V]) Clear

func (m *ConcurrentMap[K, V]) Clear()

Clear removes all items from map.

func (*ConcurrentMap[K, V]) Count

func (m *ConcurrentMap[K, V]) Count() int

Count returns the number of elements within the map.

func (*ConcurrentMap[K, V]) Get

func (m *ConcurrentMap[K, V]) Get(key K) (V, bool)

Get retrieves an element from map under given key.

func (*ConcurrentMap[K, V]) GetShard

func (m *ConcurrentMap[K, V]) GetShard(key K) *ConcurrentMapShared[K, V]

GetShard returns shard under given key

func (*ConcurrentMap[K, V]) Has

func (m *ConcurrentMap[K, V]) Has(key K) bool

Looks up an item under specified key

func (*ConcurrentMap[K, V]) IsEmpty

func (m *ConcurrentMap[K, V]) IsEmpty() bool

IsEmpty checks if map is empty.

func (*ConcurrentMap[K, V]) Items

func (m *ConcurrentMap[K, V]) Items() map[K]V

Items returns all items as map[string]V

func (*ConcurrentMap[K, V]) Iter deprecated

func (m *ConcurrentMap[K, V]) Iter() <-chan Tuple[K, V]

Iter returns an iterator which could be used in a for range loop.

Deprecated: using IterBuffered() will get a better performence

func (*ConcurrentMap[K, V]) IterBuffered

func (m *ConcurrentMap[K, V]) IterBuffered() <-chan Tuple[K, V]

IterBuffered returns a buffered iterator which could be used in a for range loop.

func (*ConcurrentMap[K, V]) IterCb

func (m *ConcurrentMap[K, V]) IterCb(fn IterCb[K, V])

Callback based iterator, cheapest way to read all elements in a map.

func (*ConcurrentMap[K, V]) Keys

func (m *ConcurrentMap[K, V]) Keys() []K

Keys returns all keys as []string

func (*ConcurrentMap[K, V]) MSet

func (m *ConcurrentMap[K, V]) MSet(data map[K]V)

func (*ConcurrentMap[K, V]) MarshalJSON

func (m *ConcurrentMap[K, V]) MarshalJSON() ([]byte, error)

Reviles ConcurrentMap "private" variables to json marshal.

func (*ConcurrentMap[K, V]) NumShards

func (m *ConcurrentMap[K, V]) NumShards() int

func (*ConcurrentMap[K, V]) Pop

func (m *ConcurrentMap[K, V]) Pop(key K) (v V, exists bool)

Pop removes an element from the map and returns it

func (*ConcurrentMap[K, V]) Remove

func (m *ConcurrentMap[K, V]) Remove(key K)

Remove removes an element from the map.

func (*ConcurrentMap[K, V]) RemoveCb

func (m *ConcurrentMap[K, V]) RemoveCb(key K, cb RemoveCb[K, V]) bool

RemoveCb locks the shard containing the key, retrieves its current value and calls the callback with those params If callback returns true and element exists, it will remove it from the map Returns the value returned by the callback (even if element was not present in the map)

func (*ConcurrentMap[K, V]) Set

func (m *ConcurrentMap[K, V]) Set(key K, value V)

Sets the given value under the specified key.

func (*ConcurrentMap[K, V]) SetIfAbsent

func (m *ConcurrentMap[K, V]) SetIfAbsent(key K, value V) bool

Sets the given value under the specified key if no value was associated with it.

func (*ConcurrentMap[K, V]) UnmarshalJSON

func (m *ConcurrentMap[K, V]) UnmarshalJSON(b []byte) (err error)

Reverse process of Marshal.

func (*ConcurrentMap[K, V]) Upsert

func (m *ConcurrentMap[K, V]) Upsert(key K, value V, cb UpsertCb[V]) (res V)

Insert or Update - updates existing element or inserts a new one using UpsertCb

type ConcurrentMapShared

type ConcurrentMapShared[K comparable, V any] struct {
	sync.RWMutex // Read Write mutex, guards access to internal map.
	// contains filtered or unexported fields
}

A "thread" safe string to anything map.

type ConfirmationAccumulator

type ConfirmationAccumulator struct {
	// contains filtered or unexported fields
}

ConfirmationAccumulator accumulates confirmation entries and tracks timing.

This is a generic accumulator used by KDC, KRS, and agents to collect success/failure status for operations before sending confirmation messages.

Usage pattern:

  1. Create accumulator: acc := NewConfirmationAccumulator()
  2. Add entries as operations complete: acc.AddEntry(entry)
  3. Get results: successes := acc.GetSuccesses(), failures := acc.GetFailures()
  4. Mark complete: acc.MarkComplete()

func NewConfirmationAccumulator

func NewConfirmationAccumulator() *ConfirmationAccumulator

NewConfirmationAccumulator creates a new confirmation accumulator.

func (*ConfirmationAccumulator) AddEntry

func (ca *ConfirmationAccumulator) AddEntry(entry ConfirmationEntry)

AddEntry adds a confirmation entry to the accumulator.

If an entry with the same ID already exists, it will be replaced. This allows updating the status of an operation.

func (*ConfirmationAccumulator) Clear

func (ca *ConfirmationAccumulator) Clear()

Clear removes all entries from the accumulator (useful for reuse).

func (*ConfirmationAccumulator) GetAllEntries

func (ca *ConfirmationAccumulator) GetAllEntries() []ConfirmationEntry

GetAllEntries returns all entries regardless of status.

func (*ConfirmationAccumulator) GetCompletedTime

func (ca *ConfirmationAccumulator) GetCompletedTime() (time.Time, error)

GetCompletedTime returns the completion time, or error if not yet complete.

func (*ConfirmationAccumulator) GetDuration

func (ca *ConfirmationAccumulator) GetDuration() (time.Duration, error)

GetDuration returns the duration from start to completion, or error if not yet complete.

func (*ConfirmationAccumulator) GetEntry

GetEntry retrieves a specific entry by ID, or nil if not found.

func (*ConfirmationAccumulator) GetFailures

func (ca *ConfirmationAccumulator) GetFailures() []ConfirmationEntry

GetFailures returns all entries with status "failed".

func (*ConfirmationAccumulator) GetStartTime

func (ca *ConfirmationAccumulator) GetStartTime() time.Time

GetStartTime returns the time when the accumulator was created.

func (*ConfirmationAccumulator) GetStats

func (ca *ConfirmationAccumulator) GetStats() (total int, successes int, failures int)

GetStats returns summary statistics about the accumulator.

func (*ConfirmationAccumulator) GetSuccesses

func (ca *ConfirmationAccumulator) GetSuccesses() []ConfirmationEntry

GetSuccesses returns all entries with status "success".

func (*ConfirmationAccumulator) HasEntry

func (ca *ConfirmationAccumulator) HasEntry(id string) bool

HasEntry returns true if an entry with the given ID exists.

func (*ConfirmationAccumulator) IsComplete

func (ca *ConfirmationAccumulator) IsComplete() bool

IsComplete returns true if the accumulator has been marked complete.

func (*ConfirmationAccumulator) MarkComplete

func (ca *ConfirmationAccumulator) MarkComplete()

MarkComplete marks the accumulator as complete and sets the completion time.

type ConfirmationEntry

type ConfirmationEntry interface {
	// GetId returns the unique identifier for this confirmation entry
	// (e.g., key ID, component ID, sync operation ID)
	GetId() string

	// GetStatus returns "success" or "failed"
	GetStatus() string

	// GetDetails returns additional details or error message
	// Returns empty string for successful operations
	GetDetails() string
}

ConfirmationEntry is a generic interface for confirmation entries.

This interface is implemented by specific types like:

  • KeyStatusEntry (KDC/KRS key installation confirmation)
  • ComponentStatusEntry (KDC/KRS component installation confirmation)
  • SyncStatusEntry (Agent-to-agent sync confirmation)

Each implementation provides its own fields and logic, but all must provide an ID, status, and details for generic accumulation.

type DELEG

type DELEG struct {
	// Hdr      dns.RR_Header
	Priority uint16          // If zero, Value must be empty or discarded by the user of this library
	Target   string          `dns:"domain-name"`
	Value    []DELEGKeyValue `dns:"pairs"`
}

func (*DELEG) Copy

func (rr *DELEG) Copy(dest dns.PrivateRdata) error

func (*DELEG) Len

func (rr *DELEG) Len() int

johani

func (*DELEG) Pack

func (rr *DELEG) Pack(buf []byte) (int, error)

johani

func (*DELEG) Parse

func (rr *DELEG) Parse(s []string) error

func (*DELEG) String

func (rr *DELEG) String() string

func (*DELEG) Unpack

func (rr *DELEG) Unpack(buf []byte) (int, error)

type DELEGAlpn

type DELEGAlpn struct {
	Alpn []string
}

SVCBAlpn pair is used to list supported connection protocols. The user of this library must ensure that at least one protocol is listed when alpn is present. Protocol IDs can be found at: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids Basic use pattern for creating an alpn option:

h := new(dns.HTTPS)
h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
e := new(dns.SVCBAlpn)
e.Alpn = []string{"h2", "http/1.1"}
h.Value = append(h.Value, e)

func (*DELEGAlpn) Key

func (*DELEGAlpn) Key() DELEGKey

func (*DELEGAlpn) String

func (s *DELEGAlpn) String() string

type DELEGIPv4Hint

type DELEGIPv4Hint struct {
	Hint []net.IP
}

SVCBIPv4Hint pair suggests an IPv4 address which may be used to open connections if A and AAAA record responses for SVCB's Target domain haven't been received. In that case, optionally, A and AAAA requests can be made, after which the connection to the hinted IP address may be terminated and a new connection may be opened. Basic use pattern for creating an ipv4hint option:

	h := new(dns.HTTPS)
	h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
	e := new(dns.SVCBIPv4Hint)
	e.Hint = []net.IP{net.IPv4(1,1,1,1).To4()}

 Or

	e.Hint = []net.IP{net.ParseIP("1.1.1.1").To4()}
	h.Value = append(h.Value, e)

func (*DELEGIPv4Hint) Key

func (*DELEGIPv4Hint) Key() DELEGKey

func (*DELEGIPv4Hint) String

func (s *DELEGIPv4Hint) String() string

type DELEGIPv6Hint

type DELEGIPv6Hint struct {
	Hint []net.IP
}

SVCBIPv6Hint pair suggests an IPv6 address which may be used to open connections if A and AAAA record responses for SVCB's Target domain haven't been received. In that case, optionally, A and AAAA requests can be made, after which the connection to the hinted IP address may be terminated and a new connection may be opened. Basic use pattern for creating an ipv6hint option:

h := new(dns.HTTPS)
h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
e := new(dns.SVCBIPv6Hint)
e.Hint = []net.IP{net.ParseIP("2001:db8::1")}
h.Value = append(h.Value, e)

func (*DELEGIPv6Hint) Key

func (*DELEGIPv6Hint) Key() DELEGKey

func (*DELEGIPv6Hint) String

func (s *DELEGIPv6Hint) String() string

type DELEGKey

type DELEGKey uint16

SVCBKey is the type of the keys used in the SVCB RR.

const (
	DELEG_MANDATORY DELEGKey = iota
	DELEG_ALPN
	DELEG_NO_DEFAULT_ALPN
	DELEG_PORT
	DELEG_IPV4HINT
	DELEG_ECHCONFIG
	DELEG_IPV6HINT
	DELEG_DOHPATH // rfc9461 Section 5
	DELEG_OHTTP   // rfc9540 Section 8

)

Keys defined in rfc9460

func (DELEGKey) String

func (key DELEGKey) String() string

type DELEGKeyValue

type DELEGKeyValue interface {
	Key() DELEGKey // Key returns the numerical key code.

	String() string // String returns the string representation of the value.
	// contains filtered or unexported methods
}

DELEGKeyValue defines a key=value pair for the DELEG RR type. A DELEG RR can have multiple DELEGKeyValues appended to it.

type DELEGLocal

type DELEGLocal struct {
	KeyCode DELEGKey // Never 65535 or any assigned keys.
	Data    []byte   // All byte sequences are allowed.
}

SVCBLocal pair is intended for experimental/private use. The key is recommended to be in the range [SVCB_PRIVATE_LOWER, SVCB_PRIVATE_UPPER]. Basic use pattern for creating a keyNNNNN option:

h := new(dns.HTTPS)
h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
e := new(dns.SVCBLocal)
e.KeyCode = 65400
e.Data = []byte("abc")
h.Value = append(h.Value, e)

func (*DELEGLocal) Key

func (s *DELEGLocal) Key() DELEGKey

func (*DELEGLocal) String

func (s *DELEGLocal) String() string

type DELEGMandatory

type DELEGMandatory struct {
	Code []DELEGKey
}

SVCBMandatory pair adds to required keys that must be interpreted for the RR to be functional. If ignored, the whole RRSet must be ignored. "port" and "no-default-alpn" are mandatory by default if present, so they shouldn't be included here.

It is incumbent upon the user of this library to reject the RRSet if or avoid constructing such an RRSet that: - "mandatory" is included as one of the keys of mandatory - no key is listed multiple times in mandatory - all keys listed in mandatory are present - escape sequences are not used in mandatory - mandatory, when present, lists at least one key

Basic use pattern for creating a mandatory option:

s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
e := new(dns.SVCBMandatory)
e.Code = []uint16{dns.SVCB_ALPN}
s.Value = append(s.Value, e)
t := new(dns.SVCBAlpn)
t.Alpn = []string{"xmpp-client"}
s.Value = append(s.Value, t)

func (*DELEGMandatory) Key

func (*DELEGMandatory) Key() DELEGKey

func (*DELEGMandatory) String

func (s *DELEGMandatory) String() string

type DELEGNoDefaultAlpn

type DELEGNoDefaultAlpn struct{}

SVCBNoDefaultAlpn pair signifies no support for default connection protocols. Should be used in conjunction with alpn. Basic use pattern for creating a no-default-alpn option:

s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
t := new(dns.SVCBAlpn)
t.Alpn = []string{"xmpp-client"}
s.Value = append(s.Value, t)
e := new(dns.SVCBNoDefaultAlpn)
s.Value = append(s.Value, e)

func (*DELEGNoDefaultAlpn) Key

func (*DELEGNoDefaultAlpn) String

func (*DELEGNoDefaultAlpn) String() string

type DELEGPort

type DELEGPort struct {
	Port uint16
}

SVCBPort pair defines the port for connection. Basic use pattern for creating a port option:

s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
e := new(dns.SVCBPort)
e.Port = 80
s.Value = append(s.Value, e)

func (*DELEGPort) Key

func (*DELEGPort) Key() DELEGKey

func (*DELEGPort) String

func (s *DELEGPort) String() string

type DNSClient

type DNSClient struct {
	Port            string
	Transport       Transport
	TLSConfig       *tls.Config
	HTTPClient      *http.Client
	QUICConfig      *quic.Config
	Timeout         time.Duration
	DNSClientUDP    *dns.Client
	DNSClientTCP    *dns.Client
	DNSClientTLS    *dns.Client
	DisableFallback bool
	ForceTCP        bool
}

DNSClient represents a DNS client that supports multiple transport protocols

func NewDNSClient

func NewDNSClient(transport Transport, port string, tlsConfig *tls.Config, opts ...DNSClientOption) *DNSClient

NewDNSClient creates a new DNS client with the specified transport XXX: Once we can do cert validation we should add a WithVerifyCertificates() option.

func (*DNSClient) Exchange

func (c *DNSClient) Exchange(msg *dns.Msg, server string, debug bool) (*dns.Msg, time.Duration, error)

Exchange sends a DNS message and returns the response

type DNSClientOption

type DNSClientOption func(*DNSClient)

func WithDisableFallback

func WithDisableFallback() DNSClientOption

func WithForceTCP

func WithForceTCP() DNSClientOption

type DSYNC

type DSYNC struct {
	Type   uint16
	Scheme DsyncScheme
	Port   uint16
	Target string
}

func (*DSYNC) Copy

func (rd *DSYNC) Copy(dest dns.PrivateRdata) error

func (*DSYNC) Len

func (rd *DSYNC) Len() int

func (*DSYNC) Pack

func (rd *DSYNC) Pack(buf []byte) (int, error)

func (*DSYNC) Parse

func (rd *DSYNC) Parse(txt []string) error

func (DSYNC) String

func (rd DSYNC) String() string

func (*DSYNC) Unpack

func (rd *DSYNC) Unpack(buf []byte) (int, error)

type DsyncScheme

type DsyncScheme uint8

type HSYNC

type HSYNC struct {
	State    uint8 // 0=OFF, 1=ON
	NSmgmt   uint8 // 1=OWNER, 2=AGENT
	Sign     uint8 // 1=SIGN, 2=NOSIGN
	Identity string
	Upstream string
}

func (*HSYNC) Copy

func (rd *HSYNC) Copy(dest dns.PrivateRdata) error

func (*HSYNC) Len

func (rd *HSYNC) Len() int

func (*HSYNC) Pack

func (rd *HSYNC) Pack(buf []byte) (int, error)

func (*HSYNC) Parse

func (rd *HSYNC) Parse(txt []string) error

func (HSYNC) String

func (rd HSYNC) String() string

func (*HSYNC) Unpack

func (rd *HSYNC) Unpack(buf []byte) (int, error)

type HSYNC2

type HSYNC2 struct {
	State    uint8  // 0=OFF, 1=ON
	Flags    uint16 // Will hold both NSmgmt and Sign bits
	Identity string
	Upstream string
}

func (*HSYNC2) Copy

func (rd *HSYNC2) Copy(dest dns.PrivateRdata) error

func (*HSYNC2) DoAudit

func (rd *HSYNC2) DoAudit() bool

func (*HSYNC2) DoSign

func (rd *HSYNC2) DoSign() bool

func (*HSYNC2) GetParentSync

func (rd *HSYNC2) GetParentSync() uint16

func (*HSYNC2) IsAgent

func (rd *HSYNC2) IsAgent() bool

func (*HSYNC2) Len

func (rd *HSYNC2) Len() int

func (*HSYNC2) Pack

func (rd *HSYNC2) Pack(buf []byte) (int, error)

func (*HSYNC2) Parse

func (rd *HSYNC2) Parse(txt []string) error

func (*HSYNC2) SetAudit

func (rd *HSYNC2) SetAudit(enabled bool)

Add helper functions for the new flags

func (*HSYNC2) SetNSmgmt

func (rd *HSYNC2) SetNSmgmt(isAgent bool)

Helper functions for flag handling

func (*HSYNC2) SetParentSync

func (rd *HSYNC2) SetParentSync(value uint16) error

func (*HSYNC2) SetSign

func (rd *HSYNC2) SetSign(doSign bool)

func (HSYNC2) String

func (rd HSYNC2) String() string

func (*HSYNC2) Unpack

func (rd *HSYNC2) Unpack(buf []byte) (int, error)

type HSYNC3

type HSYNC3 struct {
	State    uint8  // 0=OFF, 1=ON
	Label    string // unqualified provider tag, e.g. "netnod" — NOT an FQDN
	Identity string // FQDN for agent discovery, e.g. "agent.netnod.se."
	Upstream string // label of upstream provider, or "." — NOT an FQDN
}

func (*HSYNC3) Copy

func (rd *HSYNC3) Copy(dest dns.PrivateRdata) error

func (*HSYNC3) Len

func (rd *HSYNC3) Len() int

func (*HSYNC3) Pack

func (rd *HSYNC3) Pack(buf []byte) (int, error)

func (*HSYNC3) Parse

func (rd *HSYNC3) Parse(txt []string) error

func (HSYNC3) String

func (rd HSYNC3) String() string

func (*HSYNC3) Unpack

func (rd *HSYNC3) Unpack(buf []byte) (int, error)

type HSYNCPARAM

type HSYNCPARAM struct {
	Value []HSYNCPARAMKeyValue
}

HSYNCPARAM is a single RR per zone carrying zone-wide multi-provider policy as key=value pairs.

func (*HSYNCPARAM) Copy

func (rr *HSYNCPARAM) Copy(dest dns.PrivateRdata) error

func (*HSYNCPARAM) GetAuditors

func (h *HSYNCPARAM) GetAuditors() []string

GetAuditors returns the auditors list, defaulting to empty.

func (*HSYNCPARAM) GetNSmgmt

func (h *HSYNCPARAM) GetNSmgmt() uint8

GetNSmgmt returns the nsmgmt value from the HSYNCPARAM record, defaulting to HsyncNSmgmtOWNER.

func (*HSYNCPARAM) GetParentSync

func (h *HSYNCPARAM) GetParentSync() uint8

GetParentSync returns the parentsync value, defaulting to HsyncParentSyncOwner.

func (*HSYNCPARAM) GetServers

func (h *HSYNCPARAM) GetServers() []string

GetServers returns the servers list, defaulting to empty.

func (*HSYNCPARAM) GetSigners

func (h *HSYNCPARAM) GetSigners() []string

GetSigners returns the signers list, defaulting to empty.

func (*HSYNCPARAM) GetSuffix

func (h *HSYNCPARAM) GetSuffix() string

GetSuffix returns the suffix label, or "" if not set.

func (*HSYNCPARAM) HasPubcds

func (h *HSYNCPARAM) HasPubcds() bool

HasPubcds returns true if the pubcds flag is present.

func (*HSYNCPARAM) HasPubkey

func (h *HSYNCPARAM) HasPubkey() bool

HasPubkey returns true if the pubkey flag is present.

func (*HSYNCPARAM) IsAuditorLabel

func (h *HSYNCPARAM) IsAuditorLabel(label string) bool

IsAuditorLabel checks if the given label is listed in the auditors.

func (*HSYNCPARAM) IsServerLabel

func (h *HSYNCPARAM) IsServerLabel(label string) bool

IsServerLabel checks if the given label is listed in the servers.

func (*HSYNCPARAM) IsSignerLabel

func (h *HSYNCPARAM) IsSignerLabel(label string) bool

IsSignerLabel checks if the given label is listed in the signers.

func (*HSYNCPARAM) Len

func (rr *HSYNCPARAM) Len() int

func (*HSYNCPARAM) Pack

func (rr *HSYNCPARAM) Pack(buf []byte) (int, error)

func (*HSYNCPARAM) Parse

func (rr *HSYNCPARAM) Parse(s []string) error

func (*HSYNCPARAM) String

func (rr *HSYNCPARAM) String() string

func (*HSYNCPARAM) Unpack

func (rr *HSYNCPARAM) Unpack(buf []byte) (int, error)

type HSYNCPARAMAuditors

type HSYNCPARAMAuditors struct {
	Auditors []string
}

func (*HSYNCPARAMAuditors) Key

func (*HSYNCPARAMAuditors) String

func (s *HSYNCPARAMAuditors) String() string

type HSYNCPARAMFlag

type HSYNCPARAMFlag struct {
	// contains filtered or unexported fields
}

func (*HSYNCPARAMFlag) Key

func (s *HSYNCPARAMFlag) Key() HSYNCPARAMKey

func (*HSYNCPARAMFlag) String

func (s *HSYNCPARAMFlag) String() string

type HSYNCPARAMKey

type HSYNCPARAMKey uint16

HSYNCPARAMKey is the type of keys used in the HSYNCPARAM RR.

const (
	HSYNCPARAM_NSMGMT     HSYNCPARAMKey = 0
	HSYNCPARAM_PARENTSYNC HSYNCPARAMKey = 1
	HSYNCPARAM_SERVERS    HSYNCPARAMKey = 2
	HSYNCPARAM_SIGNERS    HSYNCPARAMKey = 3
	HSYNCPARAM_PUBKEY     HSYNCPARAMKey = 4
	HSYNCPARAM_PUBCDS     HSYNCPARAMKey = 5
	HSYNCPARAM_SUFFIX     HSYNCPARAMKey = 6
	HSYNCPARAM_AUDITORS   HSYNCPARAMKey = 7
)

func (HSYNCPARAMKey) String

func (key HSYNCPARAMKey) String() string

type HSYNCPARAMKeyValue

type HSYNCPARAMKeyValue interface {
	Key() HSYNCPARAMKey

	String() string
	// contains filtered or unexported methods
}

HSYNCPARAMKeyValue defines a key=value pair for the HSYNCPARAM RR type.

type HSYNCPARAMLocal

type HSYNCPARAMLocal struct {
	KeyCode HSYNCPARAMKey
	Data    []byte
}

func (*HSYNCPARAMLocal) Key

func (s *HSYNCPARAMLocal) Key() HSYNCPARAMKey

func (*HSYNCPARAMLocal) String

func (s *HSYNCPARAMLocal) String() string

type HSYNCPARAMNSmgmt

type HSYNCPARAMNSmgmt struct {
	Value uint8
}

func (*HSYNCPARAMNSmgmt) Key

func (*HSYNCPARAMNSmgmt) String

func (s *HSYNCPARAMNSmgmt) String() string

type HSYNCPARAMParentSync

type HSYNCPARAMParentSync struct {
	Value uint8
}

func (*HSYNCPARAMParentSync) Key

func (*HSYNCPARAMParentSync) String

func (s *HSYNCPARAMParentSync) String() string

type HSYNCPARAMServers

type HSYNCPARAMServers struct {
	Servers []string
}

func (*HSYNCPARAMServers) Key

func (*HSYNCPARAMServers) String

func (s *HSYNCPARAMServers) String() string

type HSYNCPARAMSigners

type HSYNCPARAMSigners struct {
	Signers []string
}

func (*HSYNCPARAMSigners) Key

func (*HSYNCPARAMSigners) String

func (s *HSYNCPARAMSigners) String() string

type HSYNCPARAMSuffix

type HSYNCPARAMSuffix struct {
	Label string
}

func (*HSYNCPARAMSuffix) Key

func (*HSYNCPARAMSuffix) String

func (s *HSYNCPARAMSuffix) String() string

type IterCb

type IterCb[K comparable, V any] func(key K, v V)

Iterator callback called for every key,value found in maps. RLock is held for all calls for a given shard therefore callback sees a consistent view of a shard, but not across the shards

type JSONCHUNK

type JSONCHUNK struct {
	Sequence uint16 `json:"sequence"` // Chunk sequence number (0-based)
	Total    uint16 `json:"total"`    // Total number of chunks
	Data     []byte `json:"data"`     // Base64-encoded JSON data (raw bytes, not base64 string)
}

JSONCHUNK - Chunked JSON Data Transport Transports large JSON-structured data (zone lists or encrypted blobs) in chunks Format: Base64-encoded JSON data with sequence/total metadata

func (*JSONCHUNK) Copy

func (rd *JSONCHUNK) Copy(dest dns.PrivateRdata) error

func (*JSONCHUNK) Len

func (rd *JSONCHUNK) Len() int

func (*JSONCHUNK) Pack

func (rd *JSONCHUNK) Pack(buf []byte) (int, error)

func (*JSONCHUNK) Parse

func (rd *JSONCHUNK) Parse(txt []string) error

func (JSONCHUNK) String

func (rd JSONCHUNK) String() string

func (*JSONCHUNK) Unpack

func (rd *JSONCHUNK) Unpack(buf []byte) (int, error)

type JSONMANIFEST

type JSONMANIFEST struct {
	ChunkCount uint16                 `json:"chunk_count"`          // Number of JSONCHUNK records (0 if payload is inline)
	ChunkSize  uint16                 `json:"chunk_size,omitempty"` // Maximum size of each chunk in bytes (optional)
	Checksum   string                 `json:"checksum,omitempty"`   // SHA-256 checksum (optional)
	Metadata   map[string]interface{} `json:"metadata,omitempty"`   // Additional metadata (must include "content")
	Payload    []byte                 `json:"payload,omitempty"`    // Inline payload (base64-encoded in JSON, optional)
}

JSONMANIFEST - JSON Distribution Manifest Small metadata about a distribution event for a specific node Format: JSON structure with chunk_count, checksum, metadata Size limit: <500 bytes (never chunked) The Metadata map should contain a "content" field indicating the type:

  • "zonelist": List of zone names (JSON array of strings)
  • "encrypted_keys": HPKE-encrypted key material
  • "clear_text": Clear text payload (base64 encoded)
  • "encrypted_text": HPKE-encrypted text payload (base64 encoded)

When payload fits inline (typically < 1000 bytes), it can be included directly in the Payload field, eliminating the need for separate JSONCHUNK queries. In this case, ChunkCount should be 0 (or Payload is used instead of chunks).

func (*JSONMANIFEST) Copy

func (rd *JSONMANIFEST) Copy(dest dns.PrivateRdata) error

func (*JSONMANIFEST) Len

func (rd *JSONMANIFEST) Len() int

func (*JSONMANIFEST) Pack

func (rd *JSONMANIFEST) Pack(buf []byte) (int, error)

func (*JSONMANIFEST) Parse

func (rd *JSONMANIFEST) Parse(txt []string) error

func (JSONMANIFEST) String

func (rd JSONMANIFEST) String() string

func (*JSONMANIFEST) Unpack

func (rd *JSONMANIFEST) Unpack(buf []byte) (int, error)

type JWK

type JWK struct {
	JWKData string // base64url-encoded JWK JSON
}

Zone file syntax:

owner TTL CLASS JWK "base64url-encoded-jwk-json"

Example:

_jwk.example.com. 3600 IN JWK "eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2IiwieCI6Ii4uLiIsInkiOiIuLi4ifQ"

JWK represents the RDATA for a JWK DNS record. The RDATA contains a base64url-encoded JSON Web Key per RFC 7517.

func (*JWK) Copy

func (rd *JWK) Copy(dest dns.PrivateRdata) error

Copy returns a copy of the JWK RDATA

func (*JWK) Len

func (rd *JWK) Len() int

Len returns the wire format length

func (*JWK) Pack

func (rd *JWK) Pack(buf []byte) (int, error)

Pack packs the JWK RDATA into wire format

func (*JWK) Parse

func (rd *JWK) Parse(txt []string) error

Parse parses the JWK RDATA from zone file format Expected format: "base64url-encoded-jwk-json"

func (*JWK) String

func (rd *JWK) String() string

String returns the string representation for zone files

func (*JWK) Unpack

func (rd *JWK) Unpack(buf []byte) (int, error)

Unpack unpacks the JWK RDATA from wire format

type JWKKey

type JWKKey struct {
	Kty string `json:"kty"`           // Key Type (e.g., "EC", "OKP")
	Crv string `json:"crv,omitempty"` // Curve (e.g., "P-256", "X25519")
	X   string `json:"x,omitempty"`   // X coordinate (base64url)
	Y   string `json:"y,omitempty"`   // Y coordinate (base64url, EC only)
	Alg string `json:"alg,omitempty"` // Algorithm (optional)
	Use string `json:"use,omitempty"` // Public Key Use (optional)
}

JWK represents a JSON Web Key structure per RFC 7517

type KeyInventoryEntry

type KeyInventoryEntry struct {
	KeyTag    uint16 `json:"key_tag"`
	Algorithm uint8  `json:"algorithm"`
	Flags     uint16 `json:"flags"`
	State     string `json:"state"` // "created","published","standby","active","retired","foreign"
	KeyRR     string `json:"keyrr"` // Full DNSKEY RR string (public key data)
}

KeyInventoryEntry describes a single DNSKEY in a KEYSTATE inventory message.

type MSIGNER

type MSIGNER struct {
	State  uint8         // 0=OFF, 1=ON
	Method MsignerMethod // 1=DNS, 2=API
	//	Port   uint16
	Target string
}

func (*MSIGNER) Copy

func (rd *MSIGNER) Copy(dest dns.PrivateRdata) error

func (*MSIGNER) Len

func (rd *MSIGNER) Len() int

func (*MSIGNER) Pack

func (rd *MSIGNER) Pack(buf []byte) (int, error)

func (*MSIGNER) Parse

func (rd *MSIGNER) Parse(txt []string) error

func (MSIGNER) String

func (rd MSIGNER) String() string

func (*MSIGNER) Unpack

func (rd *MSIGNER) Unpack(buf []byte) (int, error)

type ManifestData

type ManifestData struct {
	ChunkCount uint16                 `json:"chunk_count"`          // Number of data chunks (0 = inline payload)
	ChunkSize  uint16                 `json:"chunk_size,omitempty"` // Expected chunk size in bytes
	Metadata   map[string]interface{} `json:"metadata,omitempty"`   // Application-specific metadata
	Payload    []byte                 `json:"payload,omitempty"`    // Optional inline payload (for small data)
}

ManifestData represents the JSON structure stored in a CHUNK manifest's Data field. This is a generic structure used by KDC (key distributions), agents (sync operations), and any other component that uses CHUNK-based data distribution.

func ExtractManifestData

func ExtractManifestData(chunk *CHUNK) (*ManifestData, error)

ExtractManifestData extracts ManifestData from a CHUNK manifest record.

This function parses the JSON data from a manifest chunk (Sequence=0) and returns the structured ManifestData. Only FormatJSON is supported by this function. For FormatJWT manifests, use distrib.ExtractJWTManifestData instead.

Parameters:

  • chunk: The CHUNK record to extract from (must have Sequence=0)

Returns:

  • The parsed ManifestData structure, or an error if:
  • Chunk is not a manifest (Sequence != 0)
  • Format is not FormatJSON (use distrib.ExtractJWTManifestData for FormatJWT)
  • JSON parsing fails

type MsignerMethod

type MsignerMethod uint8

type NOTIFY

type NOTIFY struct {
	Type   uint16
	Scheme uint8
	Port   uint16
	Target string
}

func (*NOTIFY) Copy

func (rd *NOTIFY) Copy(dest dns.PrivateRdata) error

func (*NOTIFY) Len

func (rd *NOTIFY) Len() int

func (*NOTIFY) Pack

func (rd *NOTIFY) Pack(buf []byte) (int, error)

func (*NOTIFY) Parse

func (rd *NOTIFY) Parse(txt []string) error

func (NOTIFY) String

func (rd NOTIFY) String() string

func (*NOTIFY) Unpack

func (rd *NOTIFY) Unpack(buf []byte) (int, error)

type PublishInstruction

type PublishInstruction struct {
	KEYRRs    []string `json:"key_rrs,omitempty"` // KEY RRs in text format (supports rollover)
	CDSRRs    []string `json:"cds_rrs,omitempty"` // CDS RRs in text format (future use)
	Locations []string `json:"locations"`         // ["at-apex"], ["at-ns"], both, or [] (retract)
}

PublishInstruction tells the combiner to publish (or retract) KEY/CDS records at the zone apex and/or at _signal names derived from the agent's NS contributions.

type RROperation

type RROperation struct {
	Operation string   `json:"operation"`         // "add", "delete", "replace"
	RRtype    string   `json:"rrtype"`            // DNS RR type name (e.g. "DNSKEY", "NS", "A")
	Records   []string `json:"records,omitempty"` // RR strings in ClassINET text format
}

RROperation describes an explicit operation on DNS records. When Operations is populated on a message, Records is ignored by the receiver. Operations use explicit semantics instead of overloading the DNS Class field.

type RRset

type RRset struct {
	Name   string
	Class  uint16
	RRtype uint16
	RRs    []dns.RR
	RRSIGs []dns.RR

	// UnclampedTTL is the operator-configured TTL captured the first
	// time SignRRset clamps this RRset under K-step rollover clamping
	// (§5.2 of the automated KSK rollover design). Sentinel 0 means
	// "never clamped." Reset only on whole-RRset replacement (inbound
	// zone transfer / zone reload), which naturally zeroes the field.
	UnclampedTTL uint32 `json:"-"`
}

func (*RRset) Add

func (rrset *RRset) Add(rr dns.RR)

Add adds a RR to the RRset if it is not already present.

func (*RRset) Clone

func (rrset *RRset) Clone() *RRset

func (*RRset) Delete

func (rrset *RRset) Delete(rr dns.RR)

Delete deletes a RR from the RRset if it is present.

func (*RRset) RRSIGsDiffer

func (rrset *RRset) RRSIGsDiffer(newrrset *RRset) bool

RRSIGsDiffer compares two slices of RRSIGs and returns true if they differ. Two RRSIG slices are considered equal if they contain the same RRSIGs (using dns.IsDuplicate for comparison), regardless of order. Returns true if the RRSIGs differ, false if they are the same.

func (*RRset) RRsetDiffer

func (rrset *RRset) RRsetDiffer(newrrset *RRset, lg *log.Logger, verbose, debug bool) (bool, []dns.RR, []dns.RR)

func (*RRset) RemoveRR

func (rrset *RRset) RemoveRR(rr dns.RR, verbose, debug bool)

func (*RRset) String

func (rrset *RRset) String(maxlen int) (out string)

type RRsetString

type RRsetString struct {
	Name   string   `json:"name"`
	RRtype uint16   `json:"rrtype"`
	RRs    []string `json:"rrs"`
	RRSIGs []string `json:"rrsigs,omitempty"`
}

String-based versions of RRset for JSON marshaling

type RemoveCb

type RemoveCb[K any, V any] func(key K, v V, exists bool) bool

RemoveCb is a callback executed in a map.RemoveCb() call, while Lock is held If returns true, the element will be removed from the map

type RfiData

type RfiData struct {
	Status      string // ok | error
	Time        time.Time
	Msg         string
	Error       bool
	ErrorMsg    string
	ZoneXfrSrcs []string
	ZoneXfrAuth []string
	ZoneXfrDsts []string
	AuditData   interface{}       `json:"audit_data,omitempty"`  // zone data repo snapshot for RFI AUDIT
	ConfigData  map[string]string `json:"config_data,omitempty"` // key-value config data for RFI CONFIG
}

RfiData contains response data for RFI (Request For Information) messages.

type StatusUpdatePost

type StatusUpdatePost struct {
	MessageType  AgentMsg
	MyIdentity   string
	YourIdentity string
	Zone         string
	SubType      string
	NSRecords    []string `json:",omitempty"`
	DSRecords    []string `json:",omitempty"`
	Result       string   `json:",omitempty"`
	Msg          string   `json:",omitempty"`
	Time         time.Time
}

StatusUpdatePost represents a generic status update message with subtypes. Used for combiner→agent notifications (e.g. delegation data changed) and agent→agent notifications (e.g. parent sync completed). Subtypes: "ns-changed", "ksk-changed", "parentsync-done".

type Stringer

type Stringer interface {
	fmt.Stringer
	comparable
}

type TSYNC

type TSYNC struct {
	Type       uint16
	Alias      string
	Transports string
	V4addr     string
	V6addr     string
}

Zone file syntax:

owner TTL CLASS TSYNC alias "transport=..." "v4=..." "v6=..."

Example:

_tsync.example.com. 3600 IN TSYNC ns1.example.com. "transport=doq=30,dot=20" "v4=192.0.2.1,198.51.100.1" "v6=2001:db8::1"

Fields:

alias      - FQDN (mandatory)
transport  - quoted key=value: comma-separated transport=priority pairs (optional)
v4         - quoted key=value: comma-separated IPv4 addresses (optional)
v6         - quoted key=value: comma-separated IPv6 addresses (optional)

func (*TSYNC) Copy

func (rd *TSYNC) Copy(dest dns.PrivateRdata) error

func (*TSYNC) Len

func (rd *TSYNC) Len() int

func (*TSYNC) Pack

func (rd *TSYNC) Pack(buf []byte) (int, error)

func (*TSYNC) Parse

func (rd *TSYNC) Parse(txt []string) error

func (TSYNC) String

func (rd TSYNC) String() string

func (*TSYNC) Unpack

func (rd *TSYNC) Unpack(buf []byte) (int, error)

type Transport

type Transport uint8

Transport represents the DNS transport protocol

const (
	TransportDo53 Transport = iota + 1
	TransportDoT
	TransportDoH
	TransportDoQ
)

func StringToTransport

func StringToTransport(s string) (Transport, error)

StringToTransport converts a string transport name to Transport type

type Tuple

type Tuple[K comparable, V any] struct {
	Key K
	Val V
}

Used by the Iter & IterBuffered functions to wrap two variables together over a channel,

type UpsertCb

type UpsertCb[V any] func(exist bool, valueInMap V, newValue V) V

Callback to return new element to be inserted into the map It is called while lock is held, therefore it MUST NOT try to access other keys in same map, as it can lead to deadlock since Go sync.RWLock is not reentrant

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL