diff --git a/pkg/dns/record.go b/pkg/dns/record.go index 2b98905..1b9fc51 100644 --- a/pkg/dns/record.go +++ b/pkg/dns/record.go @@ -6,6 +6,7 @@ import ( "io" "net/netip" "sort" + "strings" "time" "darvaza.org/core" @@ -38,6 +39,53 @@ func SortAddrRecords(s []AddrRecord) []AddrRecord { return s } +// SortRecords sorts a slice of [libdns.Record], by Name, Type and Value +func SortRecords(s []libdns.Record) []libdns.Record { + sort.Slice(s, func(i, j int) bool { + return lessRecord(s[i], s[j]) + }) + return s +} + +func lessRecord(a, b libdns.Record) bool { + aName := strings.ToLower(a.Name) + bName := strings.ToLower(b.Name) + + switch { + case aName < bName: + return true + case aName > bName: + return false + } + + aType := strings.ToUpper(a.Type) + bType := strings.ToUpper(b.Type) + + switch { + case aType < bType: + return true + case aType > bType: + return false + case aType == "A", aType == "AAAA": + // IP Addresses + var aa, ba netip.Addr + + switch { + case aa.UnmarshalText([]byte(a.Value)) != nil: + // bad address on a + return true + case ba.UnmarshalText([]byte(b.Value)) != nil: + // bad address on b + return false + default: + return aa.Less(ba) + } + default: + // text + return a.Value < b.Value + } +} + // SortRegions sorts regions. first by length those 3-character // or shorter, and then by length. It's mostly aimed at // supporting ISO-3166 order diff --git a/pkg/dns/show.go b/pkg/dns/show.go index d133a2c..e6a7fbb 100644 --- a/pkg/dns/show.go +++ b/pkg/dns/show.go @@ -19,6 +19,7 @@ func (mgr *Manager) Show(ctx context.Context, names ...string) error { return core.Wrap(err, "GetRecords") } + SortRecords(recs) return writeRecords(recs, os.Stdout) }