diff --git a/RFC-8482 b/RFC-8482 new file mode 100644 index 0000000..57f0f06 --- /dev/null +++ b/RFC-8482 @@ -0,0 +1,450 @@ +Internet Engineering Task Force (IETF) J. Abley +Request for Comments: 8482 Afilias +Updates: 1034, 1035 O. Gudmundsson +Category: Standards Track M. Majkowski +ISSN: 2070-1721 Cloudflare Inc. + E. Hunt + ISC + January 2019 + + + Providing Minimal-Sized Responses to DNS Queries That Have QTYPE=ANY + +Abstract + + The Domain Name System (DNS) specifies a query type (QTYPE) "ANY". + The operator of an authoritative DNS server might choose not to + respond to such queries for reasons of local policy, motivated by + security, performance, or other reasons. + + The DNS specification does not include specific guidance for the + behavior of DNS servers or clients in this situation. This document + aims to provide such guidance. + + This document updates RFCs 1034 and 1035. + +Status of This Memo + + This is an Internet Standards Track document. + + This document is a product of the Internet Engineering Task Force + (IETF). It represents the consensus of the IETF community. It has + received public review and has been approved for publication by the + Internet Engineering Steering Group (IESG). Further information on + Internet Standards is available in Section 2 of RFC 7841. + + Information about the current status of this document, any errata, + and how to provide feedback on it may be obtained at + https://www.rfc-editor.org/info/rfc8482. + + +Copyright Notice + + Copyright (c) 2019 IETF Trust and the persons identified as the + document authors. All rights reserved. + + This document is subject to BCP 78 and the IETF Trust's Legal + Provisions Relating to IETF Documents + (https://trustee.ietf.org/license-info) in effect on the date of + publication of this document. Please review these documents + carefully, as they describe your rights and restrictions with respect + to this document. Code Components extracted from this document must + include Simplified BSD License text as described in Section 4.e of + the Trust Legal Provisions and are provided without warranty as + described in the Simplified BSD License. + +Table of Contents + + 1. Introduction ....................................................3 + 1.1. Terminology ................................................3 + 2. Motivations for Use of ANY Queries ..............................3 + 3. General Approach ................................................4 + 4. Behavior of DNS Responders ......................................5 + 4.1. Answer with a Subset of Available RRsets ...................5 + 4.2. Answer with a Synthesized HINFO RRset ......................5 + 4.3. Answer with Best Guess as to Intention .....................6 + 4.4. Transport Considerations ...................................6 + 5. Behavior of DNS Initiators ......................................7 + 6. HINFO Considerations ............................................7 + 7. Updates to RFCs 1034 and 1035 ...................................7 + 8. Implementation Experience .......................................8 + 9. Security Considerations .........................................8 + 10. IANA Considerations ............................................9 + 11. References .....................................................9 + 11.1. Normative References ......................................9 + 11.2. Informative References ....................................9 + Acknowledgements ..................................................10 + Authors' Addresses ................................................10 + + +1. Introduction + + The Domain Name System (DNS) specifies a query type (QTYPE) "ANY". + The operator of an authoritative DNS server might choose not to + respond to such queries for reasons of local policy, motivated by + security, performance, or other reasons. + + The DNS specification [RFC1034] [RFC1035] does not include specific + guidance for the behavior of DNS servers or clients in this + situation. This document aims to provide such guidance. + +1.1. Terminology + + This document uses terminology specific to the Domain Name System + (DNS), descriptions of which can be found in [RFC8499]. + + [RFC1035] defined type 255 to be "*". However, DNS implementations + commonly use the keyword "ANY" to refer to that type code; this + document follows that common usage. + + In this document, "ANY query" refers to a DNS meta-query with + QTYPE=ANY. An "ANY response" is a response to such a query. + + In this document, "conventional ANY response" means an ANY response + that is constructed in accordance with the algorithm documented in + Section 4.3.2 of [RFC1034] and specifically without implementing any + of the mechanisms described in this document. + + In an exchange of DNS messages between two hosts, this document + refers to the host sending a DNS request as the "initiator" and the + host sending a DNS response as the "responder". + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and + "OPTIONAL" in this document are to be interpreted as described in + BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all + capitals, as shown here. + +2. Motivations for Use of ANY Queries + + ANY queries are legitimately used for debugging and checking the + state of a DNS server for a particular name. + + ANY queries are sometimes used as an attempt to reduce the number of + queries needed to get information, e.g., to obtain MX, A, and AAAA + resource record sets (RRsets) for a mail domain in a single query. + However, there is no documented guidance available for this use case, + and some implementations have been observed not to function as their + + developers expected. If implementers assume that an ANY query will + ultimately be received by an authoritative server and will fetch all + existing RRsets, they should include a fallback mechanism to use when + that does not happen. + + ANY queries are frequently used to exploit the amplification + potential of DNS servers and resolvers using spoofed source addresses + and UDP transport (see [RFC5358]). Having the ability to return + small responses to such queries makes DNS servers less attractive + amplifiers. + + ANY queries are sometimes used to help mine authoritative-only DNS + servers for zone data, since they are expected to return all RRsets + for a particular query name. If DNS operators prefer to reduce the + potential for information leaks, they might choose not to send large + ANY responses. + + Some authoritative-only DNS server implementations require additional + processing in order to send a conventional ANY response; avoiding + that processing expense might be desirable. + +3. General Approach + + This proposal provides a mechanism for an authoritative DNS server to + signal that conventional ANY queries are not supported for a + particular QNAME. It does so in a way that is both compatible with + and triggers desirable behavior by unmodified clients (e.g., DNS + resolvers). + + Alternative proposals for dealing with ANY queries have been + discussed. One approach proposes using a new RCODE to signal that an + authoritative server did not answer ANY queries in the standard way. + This approach was found to have an undesirable effect on both + resolvers and authoritative-only servers; resolvers receiving an + unknown RCODE would resend the same query to all available + authoritative servers rather than suppress future ANY queries for the + same QNAME. + + The proposal described in this document avoids that outcome by + returning a non-empty RRset in the ANY response, which provides + resolvers with something to cache and effectively suppresses repeat + queries to the same or different authoritative DNS servers. + + +4. Behavior of DNS Responders + + Below are the three different modes of behavior by DNS responders + when processing queries with QNAMEs that exist, QCLASS=IN, and + QTYPE=ANY. Operators and implementers are free to choose whichever + mechanism best suits their environment. + + 1. A DNS responder can choose to select one or a larger subset of + the available RRsets at the QNAME. + + 2. A DNS responder can return a synthesized HINFO resource record. + See Section 6 for discussion of the use of HINFO. + + 3. A resolver can try to give out the most likely records the + requester wants. This is not always possible, and the result + might well be a large response. + + Except as described below in this section, the DNS responder MUST + follow the standard algorithms when constructing a response. + +4.1. Answer with a Subset of Available RRsets + + A DNS responder that receives an ANY query MAY decline to provide a + conventional ANY response or MAY instead send a response with a + single RRset (or a larger subset of available RRsets) in the answer + section. + + The RRsets returned in the answer section of the response MAY consist + of a single RRset owned by the name specified in the QNAME. Where + multiple RRsets exist, the responder SHOULD choose a small subset of + those available to reduce the amplification potential of the + response. + + If the zone is signed, appropriate RRSIG records MUST be included in + the answer. + + Note that this mechanism does not provide any signaling to indicate + to a client that an incomplete subset of the available RRsets has + been returned. + +4.2. Answer with a Synthesized HINFO RRset + + If there is no CNAME present at the owner name matching the QNAME, + the resource record returned in the response MAY instead be + synthesized. In this case, a single HINFO resource record SHOULD be + returned. The CPU field of the HINFO RDATA SHOULD be set to + "RFC8482". The OS field of the HINFO RDATA SHOULD be set to the null + string to minimize the size of the response. + + The TTL encoded for the synthesized HINFO resource record SHOULD be + chosen by the operator of the DNS responder to be large enough to + suppress frequent subsequent ANY queries from the same initiator with + the same QNAME, understanding that a TTL that is too long might make + policy changes relating to ANY queries difficult to change in the + future. The specific value used SHOULD be configurable by the + operator of the nameserver according to local policy, based on the + familiar considerations involved in choosing a TTL value for any + resource record in any zone. + + If the DNS query includes DO=1 and the QNAME corresponds to a zone + that is known by the responder to be signed, a valid RRSIG for the + RRsets in the answer (or authority if answer is empty) section MUST + be returned. In the case of DO=0, the RRSIG SHOULD be omitted. + + A system that receives an HINFO response SHOULD NOT infer that the + response was generated according to this specification and apply any + special processing of the response because, in general, it is not + possible to tell with certainty whether the HINFO RRset received was + synthesized. In particular, systems SHOULD NOT rely upon the HINFO + RDATA described in this section to distinguish between synthesized + and non-synthesized HINFO RRsets. + +4.3. Answer with Best Guess as to Intention + + In some cases, it is possible to guess what the initiator wants in + the answer (but not always). Some implementations have implemented + the spirit of this document by returning all RRsets of RRTYPE CNAME, + MX, A, and AAAA that are present at the owner name while suppressing + others. This heuristic seems to work well in practice; it satisfies + the needs of some applications whilst suppressing other RRsets such + as TXT and DNSKEY that can often contribute to large responses. + Whilst some applications may be satisfied by this behavior, the + resulting responses in the general case are larger than in the + approaches described in Sections 4.1 and 4.2. + + As before, if the zone is signed and the DO bit is set on the + corresponding query, an RRSIG RRset MUST be included in the response. + +4.4. Transport Considerations + + A DNS responder MAY behave differently when processing ANY queries + received over different transports, e.g., by providing a conventional + ANY response over TCP whilst using one of the other mechanisms + specified in this document in the case where a query was received + using UDP. + + Implementers MAY provide configuration options to allow operators to + specify different behavior over different transports. + +5. Behavior of DNS Initiators + + A DNS initiator that sends a query with QTYPE=ANY and receives a + response containing an HINFO resource record or a single RRset, as + described in Section 4, MAY cache the response in the normal way. + Such cached resource records SHOULD be retained in the cache + following normal caching semantics, as with any other response + received from a DNS responder. + + A DNS initiator MAY suppress queries with QTYPE=ANY in the event that + the local cache contains a matching HINFO resource record with the + CPU field of the HINFO RDATA, as described in Section 4. A DNS + initiator MAY instead respond to such queries with the contents of + the local cache in the usual way. + +6. HINFO Considerations + + It is possible that the synthesized HINFO RRset in an ANY response, + once cached by the initiator, might suppress subsequent queries from + the same initiator with QTYPE=HINFO. Thus, the use of HINFO in this + proposal would effectively mask the HINFO RRset present in the zone. + + Operators of authoritative servers who serve zones that rely upon + conventional use of the HINFO RRTYPE SHOULD sensibly choose the + "single RRset" method described in this document or select another + type. + + The HINFO RRTYPE is believed to be rarely used in the DNS at the time + of writing, based on observations made in passive DNS and at + recursive and authoritative DNS servers. + +7. Updates to RFCs 1034 and 1035 + + This document extends the specification for processing ANY queries + described in Section 4.3.2 of [RFC1034]. + + It is important to note that returning a subset of available RRsets + when processing an ANY query is legitimate and consistent with + [RFC1035]; it can be argued that ANY does not always mean ALL, as + used in Section 3.2.3 of [RFC1035]. The main difference here is that + the TC bit SHOULD NOT be set in the response, thus indicating that + this is not a complete answer. + + This document describes optional behavior for both DNS initiators and + responders; implementation of the guidance provided by this document + is OPTIONAL. + + RRSIG queries (i.e., queries with QTYPE=RRSIG) are similar to ANY + queries in the sense that they have the potential to generate large + responses as well as extra work for the responders that process them, + e.g., in the case where signatures are generated on the fly. RRSIG + RRsets are not usually obtained using such explicit queries but are + rather included in the responses for other RRsets that the RRSIGs + cover. This document does not specify appropriate behavior for RRSIG + queries; however, future such advice might well benefit from + consistency with and experience with the approaches for ANY queries + described here. + +8. Implementation Experience + + In October 2015, the Cloudflare authoritative nameserver + implementation implemented the HINFO response. A few minor problems + were reported and have since been resolved. + + An implementation of the subset-mode response to ANY queries was + implemented in NSD 4.1 in 2016. + + An implementation of a single RRset response to an ANY query was made + for BIND9 by Tony Finch, and that functionality was subsequently made + available in production releases starting in BIND 9.11. + +9. Security Considerations + + Queries with QTYPE=ANY are frequently observed as part of reflection + attacks, since a relatively small query can be used to elicit a large + response. This is a desirable characteristic if the goal is to + maximize the amplification potential of a DNS server as part of a + volumetric attack. The ability of a DNS operator to suppress such + responses on a particular server makes that server a less useful + amplifier. + + The optional behavior described in this document to reduce the size + of responses to queries with QTYPE=ANY is compatible with the use of + DNSSEC by both initiator and responder. + + +10. IANA Considerations + + IANA has updated the following entry in the "Resource Record (RR) + TYPEs" registry [RR_TYPES]: + + +------+-------+-------------------------------+--------------------+ + | TYPE | Value | Meaning | Reference | + +------+-------+-------------------------------+--------------------+ + | * | 255 | A request for some or all | [RFC1035][RFC6895] | + | | | records the server has | [RFC8482] | + | | | available | | + +------+-------+-------------------------------+--------------------+ + +11. References + +11.1. Normative References + + [RFC1034] Mockapetris, P., "Domain names - concepts and facilities", + STD 13, RFC 1034, DOI 10.17487/RFC1034, November 1987, + . + + [RFC1035] Mockapetris, P., "Domain names - implementation and + specification", STD 13, RFC 1035, DOI 10.17487/RFC1035, + November 1987, . + + [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, + DOI 10.17487/RFC2119, March 1997, + . + + [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC + 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, + May 2017, . + +11.2. Informative References + + [RFC5358] Damas, J. and F. Neves, "Preventing Use of Recursive + Nameservers in Reflector Attacks", BCP 140, RFC 5358, + DOI 10.17487/RFC5358, October 2008, + . + + [RFC6895] Eastlake 3rd, D., "Domain Name System (DNS) IANA + Considerations", BCP 42, RFC 6895, DOI 10.17487/RFC6895, + April 2013, . + + [RFC8499] Hoffman, P., Sullivan, A., and K. Fujiwara, "DNS + Terminology", BCP 219, RFC 8499, DOI 10.17487/RFC8499, + January 2019, . + + [RR_TYPES] IANA, "Domain Name System (DNS) Parameters", + . + +Acknowledgements + + David Lawrence provided valuable observations and concrete + suggestions. Jeremy Laidman helped make the document better. Tony + Finch realized that this document was valuable and implemented it + while under attack. Richard Gibson identified areas where more + detail and accuracy were useful. A large number of other people also + provided comments and suggestions; we thank them all for the + feedback. + +Authors' Addresses + + Joe Abley + Afilias + 300-184 York Street + London, ON N6A 1B5 + Canada + + Phone: +1 519 670 9327 + Email: jabley@afilias.info + + + Olafur Gudmundsson + Cloudflare Inc. + + Email: olafur+ietf@cloudflare.com + + + Marek Majkowski + Cloudflare Inc. + + Email: marek@cloudflare.com + + + Evan Hunt + ISC + 950 Charter St + Redwood City, CA 94063 + United States of America + + Email: each@isc.org diff --git a/bash.go b/bash.go index 5e63e5f..5c49a39 100644 --- a/bash.go +++ b/bash.go @@ -54,7 +54,7 @@ func test() error { func mainBash() { if err := test(); err != nil { - log.Println(logError, "exit in mainBash()") + debug(LogError, "exit in mainBash()") exit(err) } } diff --git a/fsnotify.go b/fsnotify.go index 8e00527..23809e6 100644 --- a/fsnotify.go +++ b/fsnotify.go @@ -14,7 +14,7 @@ func watchSysClassNet() { // Create new watcher. watcher, err := fsnotify.NewWatcher() if err != nil { - log.Println(logError, "watchSysClassNet() failed:", err) + debug(LogError, "watchSysClassNet() failed:", err) return } defer watcher.Close() @@ -43,7 +43,7 @@ func watchSysClassNet() { // Add a path. err = watcher.Add("/tmp") if err != nil { - log.Println(logError, "watchSysClassNet() watcher.Add() failed:", err) + debug(LogError, "watchSysClassNet() watcher.Add() failed:", err) return } diff --git a/hostname.go b/hostname.go index 62803c1..06e2ce7 100644 --- a/hostname.go +++ b/hostname.go @@ -6,8 +6,12 @@ package main import ( - "log" "git.wit.org/wit/shell" + + // dnssec IPv6 socket library + "git.wit.org/jcarr/dnssecsocket" + + "git.wit.org/jcarr/control-panel-dns/cloudflare" ) // will try to get this hosts FQDN @@ -16,15 +20,13 @@ import "github.com/Showmax/go-fqdn" // this is the king of dns libraries import "github.com/miekg/dns" -// dnssec IPv6 socket library -import "git.wit.org/jcarr/dnssecsocket" func getHostname() { var err error var s string = "gui.Label == nil" s, err = fqdn.FqdnHostname() if (err != nil) { - log.Println("FQDN hostname error =", err) + debug(LogError, "FQDN hostname error =", err) return } if (me.fqdn != nil) { @@ -34,7 +36,47 @@ func getHostname() { me.changed = true } } - log.Println("FQDN =", s) + debug(LogNet, "FQDN =", s) + + dn := run("domainname") + if (me.domainname.S != dn) { + debug(LogChange, "domainname has changed from", me.domainname.S, "to", dn) + me.domainname.SetText(dn) + me.changed = true + } + + hshort := run("hostname -s") + if (me.hostshort.S != hshort) { + debug(LogChange, "hostname -s has changed from", me.hostshort.S, "to", hshort) + me.hostshort.SetText(hshort) + me.changed = true + } + + var test string + test = hshort + "." + dn + if (me.hostname != test) { + debug(LogInfo, "me.hostname", me.hostname, "does not equal", test) + if (me.hostnameStatus.S != "BROKEN") { + debug(LogChange, "me.hostname", me.hostname, "does not equal", test) + me.changed = true + me.hostnameStatus.SetText("BROKEN") + } + } else { + if (me.hostnameStatus.S != "VALID") { + debug(LogChange, "me.hostname", me.hostname, "is valid") + me.hostnameStatus.SetText("VALID") + me.changed = true + } + // enable the cloudflare button if the provider is cloudflare + if (me.cloudflareB == nil) { + debug(LogChange, "me.cloudflare == nil; me.DnsAPI.S =", me.DnsAPI.S) + if (me.DnsAPI.S == "cloudflare") { + me.cloudflareB = me.mainStatus.NewButton("cloudflare wit.com", func () { + cloudflare.CreateRR(myGui, "wit.com", "3777302ac4a78cd7fa4f6d3f72086d06") + }) + } + } + } } // returns true if the hostname is good @@ -43,31 +85,36 @@ func getHostname() { // and domainname and hostname func goodHostname(h string) bool { hostname := shell.Chomp(shell.Cat("/etc/hostname")) - log.Println("hostname =", hostname) + debug(true, "hostname =", hostname) hs := run("hostname -s") dn := run("domainname") - log.Println("hostname short =", hs, "domainname =", dn) + debug(true, "hostname short =", hs, "domainname =", dn) tmp := hs + "." + dn if (hostname == tmp) { - log.Println("hostname seems to be good", hostname) + debug(true, "hostname seems to be good", hostname) return true } return false } -func dnsAAAA(s string) []string { +func digAAAA(s string) []string { var aaaa []string // lookup the IP address from DNS rrset := dnssecsocket.Dnstrace(s, "AAAA") - log.Println(args.VerboseDNS, SPEW, rrset) + // debug(true, args.VerboseDNS, SPEW, rrset) for i, rr := range rrset { - log.Println(args.VerboseDNS, "r.Answer =", i, rr) ipaddr := dns.Field(rr, 1) + // how the hell do you detect a RRSIG AAAA record here? + if (ipaddr == "28") { + continue + } + debug(LogNow, "r.Answer =", i, "rr =", rr, "ipaddr =", ipaddr) aaaa = append(aaaa, ipaddr) + me.ipv6s[ipaddr] = rr } - log.Println(args.VerboseDNS, "aaaa =", aaaa) + debug(true, args.VerboseDNS, "aaaa =", aaaa) return aaaa } diff --git a/log.go b/log.go index b0994c0..252f4da 100644 --- a/log.go +++ b/log.go @@ -2,15 +2,22 @@ package main import ( "log" + "reflect" witlog "git.wit.org/wit/gui/log" ) +var LogPrefix = "ipv6cp" // ipv6 control panel debugging line + // various debugging flags -var logNow bool = true // useful for active development -var logError bool = true -var logWarn bool = false -var logInfo bool = false -var logVerbose bool = false +var DEBUGON bool = true +var LogNow bool = true // useful for active development +var LogError bool = true // probably always leave this one +var LogChange bool = true // turn on /proc debugging output + +var LogInfo bool = false // general info +var LogNet bool = false // general network debugging +var LogProc bool = false // turn on /proc debugging output +var LogExec bool = false // turn on os.Exec() debugging var SPEW witlog.Spewt @@ -28,6 +35,25 @@ func sleep(a ...any) { } func exit(a ...any) { - log.Println(logError, "got to log() exit") + debug(LogError, "got to log() exit") witlog.Exit(a...) } + +func debug(a ...any) { + if (! DEBUGON) { + return + } + + if (a == nil) { + return + } + var tbool bool + if (reflect.TypeOf(a[0]) == reflect.TypeOf(tbool)) { + if (a[0] == false) { + return + } + a[0] = LogPrefix // ipv6 control panel debugging line + } + + log.Println(a...) +} diff --git a/lookupAAAA.go b/lookupAAAA.go deleted file mode 100644 index 8ae3f02..0000000 --- a/lookupAAAA.go +++ /dev/null @@ -1,32 +0,0 @@ -package main - -/* -import "log" -import "github.com/miekg/dns" - -import "git.wit.org/jcarr/dnssecsocket" - -import "github.com/davecgh/go-spew/spew" -// import "github.com/Showmax/go-fqdn" - -func lookupAAAA(hostname string) string { - // lookup the IP address from DNS - dnsRR := dnssecsocket.Dnstrace(hostname, "AAAA") - spew.Dump(dnsRR) - if (dnsRR == nil) { - return "BROKEN" - } - ipaddr := dns.Field(dnsRR, 1) - log.Println("ipaddr", ipaddr) - return ipaddr -} -*/ - -/* -func main() { - hostname := "check.lab.wit.org" - // 2604:bbc0:2:248:5054:f0ff:fe00:156 - - lookupAAAA(hostname) -} -*/ diff --git a/net.go b/net.go index e6d3d07..487486e 100644 --- a/net.go +++ b/net.go @@ -2,13 +2,11 @@ package main import ( - "log" + // "log" "net" "strings" ) -var DEBUGNET bool = false - // this doesn't work /* func watchNetworkInterfaces() { @@ -18,21 +16,21 @@ func watchNetworkInterfaces() { // Set up a notification channel notification := make(chan net.Interface) - log.Println(DEBUGNET, "watchNet()") + debug(LogNet, "watchNet()") // Start goroutine to watch for changes go func() { - log.Println(DEBUGNET, "watchNet() func") + debug(LogNet, "watchNet() func") for { - log.Println(DEBUGNET, "forever loop start") + debug(LogNet, "forever loop start") // Check for changes in each interface for _, i := range interfaces { - log.Println(DEBUGNET, "something on i =", i) + debug(LogNet, "something on i =", i) if status := i.Flags & net.FlagUp; status != 0 { notification <- i - log.Println(DEBUGNET, "something on i =", i) + debug(LogNet, "something on i =", i) } } - log.Println(DEBUGNET, "forever loop end") + debug(LogNet, "forever loop end") } }() } @@ -44,20 +42,20 @@ func IsIPv6(address string) bool { func (t *IPtype) IsReal() bool { if (t.ip.IsPrivate() || t.ip.IsLoopback() || t.ip.IsLinkLocalUnicast()) { - log.Println(DEBUGNET, "\t\tIP is Real = false") + debug(LogNet, "\t\tIP is Real = false") return false } else { - log.Println(DEBUGNET, "\t\tIP is Real = true") + debug(LogNet, "\t\tIP is Real = true") return true } } func IsReal(ip *net.IP) bool { if (ip.IsPrivate() || ip.IsLoopback() || ip.IsLinkLocalUnicast()) { - log.Println(DEBUGNET, "\t\tIP is Real = false") + debug(LogNet, "\t\tIP is Real = false") return false } else { - log.Println(DEBUGNET, "\t\tIP is Real = true") + debug(LogNet, "\t\tIP is Real = true") return true } } @@ -74,7 +72,7 @@ func renameInterface(i *net.Interface) { func checkInterface(i net.Interface) { val, ok := me.ifmap[i.Index] if ! ok { - log.Println(i.Name, "is a new network interface. The linux kernel index =", i.Index) + debug(i.Name, "is a new network interface. The linux kernel index =", i.Index) me.ifmap[i.Index] = new(IFtype) me.ifmap[i.Index].gone = false me.ifmap[i.Index].iface = &i @@ -86,9 +84,9 @@ func checkInterface(i net.Interface) { return } me.ifmap[i.Index].gone = false - log.Println(args.VerboseNet, "me.ifmap[i] does exist. Need to compare everything.", i.Index, i.Name, val.iface.Index, val.iface.Name) + debug(LogNet, "me.ifmap[i] does exist. Need to compare everything.", i.Index, i.Name, val.iface.Index, val.iface.Name) if (val.iface.Name != i.Name) { - log.Println(val.iface.Name, "has changed to it's name to", i.Name) + debug(val.iface.Name, "has changed to it's name to", i.Name) me.ifmap[i.Index].iface = &i me.changed = true if (me.Interfaces != nil) { @@ -112,6 +110,19 @@ func realAAAA() []string { return aaaa } +func realA() []string { + var a []string + + for s, t := range me.ipmap { + if (t.IsReal()) { + if (t.ipv4) { + a = append(a, s) + } + } + } + return a +} + func checkDNS() (map[string]*IPtype, map[string]*IPtype) { var ipv4s map[string]*IPtype var ipv6s map[string]*IPtype @@ -126,14 +137,14 @@ func checkDNS() (map[string]*IPtype, map[string]*IPtype) { ipt = "IPv6" } if (t.IsReal()) { - log.Println("\tIP is Real ", ipt, i.Index, i.Name, s) + debug("\tIP is Real ", ipt, i.Index, i.Name, s) if (t.ipv6) { ipv6s[s] = t } else { ipv4s[s] = t } } else { - log.Println("\tIP is not Real", ipt, i.Index, i.Name, s) + debug("\tIP is not Real", ipt, i.Index, i.Name, s) } } return ipv6s, ipv4s @@ -141,14 +152,14 @@ func checkDNS() (map[string]*IPtype, map[string]*IPtype) { // Will figure out if an IP address is new func checkIP(ip *net.IPNet, i net.Interface) bool { - log.Println(args.VerboseNet, "\t\taddr.(type) = *net.IPNet") - log.Println(args.VerboseNet, "\t\taddr.(type) =", ip) + debug(LogNet, "\t\taddr.(type) = *net.IPNet") + debug(LogNet, "\t\taddr.(type) =", ip) var realip string realip = ip.IP.String() val, ok := me.ipmap[realip] if ok { - log.Println(args.VerboseNet, val.ipnet.IP.String(), "is already a defined IP address") + debug(LogNet, val.ipnet.IP.String(), "is already a defined IP address") me.ipmap[realip].gone = false return false } @@ -175,82 +186,101 @@ func checkIP(ip *net.IPNet, i net.Interface) bool { } } if (IsReal(&ip.IP)) { - log.Println("\tIP is Real ", t, i.Index, i.Name, realip) + debug("\tIP is Real ", t, i.Index, i.Name, realip) } else { - log.Println("\tIP is not Real", t, i.Index, i.Name, realip) + debug("\tIP is not Real", t, i.Index, i.Name, realip) } - log.Println(args.VerboseNet, "\t\tIP is IsPrivate() =", ip.IP.IsPrivate()) - log.Println(args.VerboseNet, "\t\tIP is IsLoopback() =", ip.IP.IsLoopback()) - log.Println(args.VerboseNet, "\t\tIP is IsLinkLocalUnicast() =", ip.IP.IsLinkLocalUnicast()) - // log.Println("HERE HERE", "realip =", realip, "me.ip[realip]=", me.ipmap[realip]) + debug(LogNet, "\t\tIP is IsPrivate() =", ip.IP.IsPrivate()) + debug(LogNet, "\t\tIP is IsLoopback() =", ip.IP.IsLoopback()) + debug(LogNet, "\t\tIP is IsLinkLocalUnicast() =", ip.IP.IsLinkLocalUnicast()) + // debug("HERE HERE", "realip =", realip, "me.ip[realip]=", me.ipmap[realip]) return true } func scanInterfaces() { - me.changed = false + debug(LogNet, "scanInterfaces() START") ifaces, _ := net.Interfaces() // me.ifnew = ifaces - log.Println(DEBUGNET, SPEW, ifaces) + debug(LogNet, SPEW, ifaces) for _, i := range ifaces { addrs, _ := i.Addrs() - // log.Println("range ifaces = ", i) + // debug("range ifaces = ", i) checkInterface(i) - log.Println(args.VerboseNet, "*net.Interface.Name = ", i.Name, i.Index) - log.Println(args.VerboseNet, SPEW, i) - log.Println(DEBUGNET, SPEW, addrs) + debug(LogNet, "*net.Interface.Name = ", i.Name, i.Index) + debug(LogNet, SPEW, i) + debug(LogNet, SPEW, addrs) for _, addr := range addrs { - log.Println(DEBUGNET, "\taddr =", addr) - log.Println(DEBUGNET, SPEW, addrs) + debug(LogNet, "\taddr =", addr) + debug(LogNet, SPEW, addrs) ips, _ := net.LookupIP(addr.String()) - log.Println(DEBUGNET, "\tLookupIP(addr) =", ips) + debug(LogNet, "\tLookupIP(addr) =", ips) switch v := addr.(type) { case *net.IPNet: - checkIP(v, i) - // log.Println("\t\tIP is () =", ip.()) + if checkIP(v, i) { + debug(true, "scanInterfaces() IP is new () i =", v.IP.String()) + } default: - log.Println(DEBUGNET, "\t\taddr.(type) = NO IDEA WHAT TO DO HERE v =", v) + debug(LogNet, "\t\taddr.(type) = NO IDEA WHAT TO DO HERE v =", v) } } } - deleteChanges() + if deleteChanges() { + me.changed = true + debug(LogNow, "deleteChanges() detected network changes") + } + updateRealAAAA() + debug(LogNet, "scanInterfaces() END") +} + +// displays the IP address found on your network interfaces +func updateRealAAAA() { var all4 string var all6 string for s, t := range me.ipmap { if (t.ipv4) { all4 += s + "\n" - log.Println("IPv4 =", s) + debug(LogNet, "IPv4 =", s) } else if (t.ipv6) { all6 += s + "\n" - log.Println("IPv6 =", s) + debug(LogNet, "IPv6 =", s) } else { - log.Println("???? =", s) + debug(LogNet, "???? =", s) } } - all4 = strings.TrimSpace(all4) - all6 = strings.TrimSpace(all6) - me.IPv4.SetText(all4) - me.IPv6.SetText(all6) + all4 = sortLines(all4) + all6 = sortLines(all6) + if (me.IPv4.S != all4) { + debug(LogNow, "IPv4 addresses have changed", all4) + me.IPv4.SetText(all4) + } + if (me.IPv6.S != all6) { + debug(LogNow, "IPv6 addresses have changed", all6) + me.IPv6.SetText(all6) + } } // delete network interfaces and ip addresses from the gui -func deleteChanges() { +func deleteChanges() bool { + var changed bool = false for i, t := range me.ifmap { if (t.gone) { - log.Println("DELETE int =", i, "name =", t.name, t.iface) + debug(LogChange, "DELETE int =", i, "name =", t.name, t.iface) delete(me.ifmap, i) - me.changed = true + changed = true } t.gone = true } for s, t := range me.ipmap { if (t.gone) { - log.Println("DELETE name =", s, "IPv4 =", t.ipv4) - log.Println("DELETE name =", s, "IPv6 =", t.ipv6) - log.Println("DELETE name =", s, "iface =", t.iface) - log.Println("DELETE name =", s, "ip =", t.ip) + debug(LogChange, "DELETE name =", s, "IPv4 =", t.ipv4) + debug(LogChange, "DELETE name =", s, "IPv6 =", t.ipv6) + debug(LogChange, "DELETE name =", s, "iface =", t.iface) + debug(LogChange, "DELETE name =", s, "ip =", t.ip) delete(me.ipmap, s) - me.changed = true + changed = true } t.gone = true } + + return changed } diff --git a/nsupdate.go b/nsupdate.go index 84f607d..db33018 100644 --- a/nsupdate.go +++ b/nsupdate.go @@ -6,7 +6,6 @@ package main import ( - "log" "os" ) @@ -17,17 +16,17 @@ import ( func nsupdate() { var tsigSecret string - log.Println(true, "nsupdate() START") + debug(true, "nsupdate() START") cmd := "go-nsupdate --tsig-algorithm=hmac-sha512" tsigSecret = os.Getenv("TIG_SECRET") cmd += " --tig-secret=\"" + tsigSecret + "\"" cmd += " -i wlo1 " + me.hostname - log.Println(true, "nsupdate() RUN:", cmd) + debug(true, "nsupdate() RUN:", cmd) for s, t := range me.ipmap { if (t.IsReal()) { if (t.ipv6) { - log.Println(true, "nsupdate() found real AAAA =", s, "on iface", t.iface.Name) + debug(true, "nsupdate() found real AAAA =", s, "on iface", t.iface.Name) } } } diff --git a/proc.go b/proc.go new file mode 100644 index 0000000..bf78c16 --- /dev/null +++ b/proc.go @@ -0,0 +1,99 @@ +package main + +import ( + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" +) + +func getProcessNameByPort(port int) string { + // Convert port to hex string + portHex := strconv.FormatInt(int64(port), 16) + + // Function to search /proc/net/tcp or /proc/net/udp + searchProcNet := func(file string) string { + data, err := ioutil.ReadFile(file) + if err != nil { + return "" + } + // debug(LogProc, "searchProcNet() data:", string(data)) + + lines := strings.Split(string(data), "\n") + for _, line := range lines { + fields := strings.Fields(line) + debug(LogProc, "searchProcNet() portHex:", portHex) + if (len(fields) > 9) { + debug(LogProc, "searchProcNet() fields[9]", fields[9]) + } + debug(LogProc, "searchProcNet() lines:", line) + if len(fields) > 1 { + parts := strings.Split(fields[1], ":") + if len(parts) > 1 { + // Convert the hexadecimal string to an integer + value, _ := strconv.ParseInt(parts[1], 16, 64) + debug(LogProc, "searchProcNet() value, port =", value, port, "parts[1] =", parts[1]) + if (port == int(value)) { + debug(LogProc, "searchProcNet() THIS IS THE LINE:", fields) + return fields[9] + } + } + } + } + + return "" + } + + // Search TCP and then UDP + inode := searchProcNet("/proc/net/tcp") + if inode == "" { + inode = searchProcNet("/proc/net/udp") + } + debug(LogProc, "searchProcNet() inode =", inode) + + // Search for process with the inode + procs, _ := ioutil.ReadDir("/proc") + for _, proc := range procs { + if !proc.IsDir() { + continue + } + + fdPath := filepath.Join("/proc", proc.Name(), "fd") + fds, err := ioutil.ReadDir(fdPath) + if err != nil { + continue // Process might have exited; skip it + } + + for _, fd := range fds { + fdLink, _ := os.Readlink(filepath.Join(fdPath, fd.Name())) + var s string + s = "socket:["+inode+"]" + if strings.Contains(fdLink, "socket:[") { + debug(LogProc, "searchProcNet() fdLink has socket:", fdLink) + debug(LogProc, "searchProcNet() proc.Name() =", proc.Name(), "s =", s) + } + if strings.Contains(fdLink, "socket:[35452]") { + debug(LogProc, "searchProcNet() found proc.Name() =", proc.Name(), fdLink) + return proc.Name() + } + if strings.Contains(fdLink, "socket:[35450]") { + debug(LogProc, "searchProcNet() found proc.Name() =", proc.Name(), fdLink) + return proc.Name() + } + if strings.Contains(fdLink, "socket:[35440]") { + debug(LogProc, "searchProcNet() found proc.Name() =", proc.Name(), fdLink) + return proc.Name() + } + if strings.Contains(fdLink, "socket:[21303]") { + debug(LogProc, "searchProcNet() found proc.Name() =", proc.Name(), fdLink) + // return proc.Name() + } + if strings.Contains(fdLink, "socket:["+inode+"]") { + return proc.Name() + } + } + } + + return "" +} diff --git a/protobuf/Makefile b/protobuf/Makefile new file mode 100644 index 0000000..35a9d9c --- /dev/null +++ b/protobuf/Makefile @@ -0,0 +1,22 @@ +all: + protoc --version + make dnsmessage.pb.go + +clean: + rm -f *.pb.go + +dnsmessage.pb.go: dnsmessage.proto + protoc --go_out=. dnsmessage.proto + +compile: + protoc --go_out=. *.proto + +deps: + apt install golang-goprotobuf-dev + apt install protobuf-compiler + +push: + git pull + git add --all + git commit -a -s + git push diff --git a/protobuf/dnsmessage.pb.go b/protobuf/dnsmessage.pb.go new file mode 100644 index 0000000..50fab47 --- /dev/null +++ b/protobuf/dnsmessage.pb.go @@ -0,0 +1,749 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: dnsmessage.proto + +package dnsmessage + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type PBDNSMessage_Type int32 + +const ( + PBDNSMessage_DNSQueryType PBDNSMessage_Type = 1 + PBDNSMessage_DNSResponseType PBDNSMessage_Type = 2 + PBDNSMessage_DNSOutgoingQueryType PBDNSMessage_Type = 3 + PBDNSMessage_DNSIncomingResponseType PBDNSMessage_Type = 4 +) + +var PBDNSMessage_Type_name = map[int32]string{ + 1: "DNSQueryType", + 2: "DNSResponseType", + 3: "DNSOutgoingQueryType", + 4: "DNSIncomingResponseType", +} + +var PBDNSMessage_Type_value = map[string]int32{ + "DNSQueryType": 1, + "DNSResponseType": 2, + "DNSOutgoingQueryType": 3, + "DNSIncomingResponseType": 4, +} + +func (x PBDNSMessage_Type) Enum() *PBDNSMessage_Type { + p := new(PBDNSMessage_Type) + *p = x + return p +} + +func (x PBDNSMessage_Type) String() string { + return proto.EnumName(PBDNSMessage_Type_name, int32(x)) +} + +func (x *PBDNSMessage_Type) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(PBDNSMessage_Type_value, data, "PBDNSMessage_Type") + if err != nil { + return err + } + *x = PBDNSMessage_Type(value) + return nil +} + +func (PBDNSMessage_Type) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_c3136ceafbfed9e7, []int{0, 0} +} + +type PBDNSMessage_SocketFamily int32 + +const ( + PBDNSMessage_INET PBDNSMessage_SocketFamily = 1 + PBDNSMessage_INET6 PBDNSMessage_SocketFamily = 2 +) + +var PBDNSMessage_SocketFamily_name = map[int32]string{ + 1: "INET", + 2: "INET6", +} + +var PBDNSMessage_SocketFamily_value = map[string]int32{ + "INET": 1, + "INET6": 2, +} + +func (x PBDNSMessage_SocketFamily) Enum() *PBDNSMessage_SocketFamily { + p := new(PBDNSMessage_SocketFamily) + *p = x + return p +} + +func (x PBDNSMessage_SocketFamily) String() string { + return proto.EnumName(PBDNSMessage_SocketFamily_name, int32(x)) +} + +func (x *PBDNSMessage_SocketFamily) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(PBDNSMessage_SocketFamily_value, data, "PBDNSMessage_SocketFamily") + if err != nil { + return err + } + *x = PBDNSMessage_SocketFamily(value) + return nil +} + +func (PBDNSMessage_SocketFamily) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_c3136ceafbfed9e7, []int{0, 1} +} + +type PBDNSMessage_SocketProtocol int32 + +const ( + PBDNSMessage_UDP PBDNSMessage_SocketProtocol = 1 + PBDNSMessage_TCP PBDNSMessage_SocketProtocol = 2 +) + +var PBDNSMessage_SocketProtocol_name = map[int32]string{ + 1: "UDP", + 2: "TCP", +} + +var PBDNSMessage_SocketProtocol_value = map[string]int32{ + "UDP": 1, + "TCP": 2, +} + +func (x PBDNSMessage_SocketProtocol) Enum() *PBDNSMessage_SocketProtocol { + p := new(PBDNSMessage_SocketProtocol) + *p = x + return p +} + +func (x PBDNSMessage_SocketProtocol) String() string { + return proto.EnumName(PBDNSMessage_SocketProtocol_name, int32(x)) +} + +func (x *PBDNSMessage_SocketProtocol) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(PBDNSMessage_SocketProtocol_value, data, "PBDNSMessage_SocketProtocol") + if err != nil { + return err + } + *x = PBDNSMessage_SocketProtocol(value) + return nil +} + +func (PBDNSMessage_SocketProtocol) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_c3136ceafbfed9e7, []int{0, 2} +} + +type PBDNSMessage_PolicyType int32 + +const ( + PBDNSMessage_UNKNOWN PBDNSMessage_PolicyType = 1 + PBDNSMessage_QNAME PBDNSMessage_PolicyType = 2 + PBDNSMessage_CLIENTIP PBDNSMessage_PolicyType = 3 + PBDNSMessage_RESPONSEIP PBDNSMessage_PolicyType = 4 + PBDNSMessage_NSDNAME PBDNSMessage_PolicyType = 5 + PBDNSMessage_NSIP PBDNSMessage_PolicyType = 6 +) + +var PBDNSMessage_PolicyType_name = map[int32]string{ + 1: "UNKNOWN", + 2: "QNAME", + 3: "CLIENTIP", + 4: "RESPONSEIP", + 5: "NSDNAME", + 6: "NSIP", +} + +var PBDNSMessage_PolicyType_value = map[string]int32{ + "UNKNOWN": 1, + "QNAME": 2, + "CLIENTIP": 3, + "RESPONSEIP": 4, + "NSDNAME": 5, + "NSIP": 6, +} + +func (x PBDNSMessage_PolicyType) Enum() *PBDNSMessage_PolicyType { + p := new(PBDNSMessage_PolicyType) + *p = x + return p +} + +func (x PBDNSMessage_PolicyType) String() string { + return proto.EnumName(PBDNSMessage_PolicyType_name, int32(x)) +} + +func (x *PBDNSMessage_PolicyType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(PBDNSMessage_PolicyType_value, data, "PBDNSMessage_PolicyType") + if err != nil { + return err + } + *x = PBDNSMessage_PolicyType(value) + return nil +} + +func (PBDNSMessage_PolicyType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_c3136ceafbfed9e7, []int{0, 3} +} + +type PBDNSMessage struct { + Type *PBDNSMessage_Type `protobuf:"varint,1,req,name=type,enum=PBDNSMessage_Type" json:"type,omitempty"` + MessageId []byte `protobuf:"bytes,2,opt,name=messageId" json:"messageId,omitempty"` + ServerIdentity []byte `protobuf:"bytes,3,opt,name=serverIdentity" json:"serverIdentity,omitempty"` + SocketFamily *PBDNSMessage_SocketFamily `protobuf:"varint,4,opt,name=socketFamily,enum=PBDNSMessage_SocketFamily" json:"socketFamily,omitempty"` + SocketProtocol *PBDNSMessage_SocketProtocol `protobuf:"varint,5,opt,name=socketProtocol,enum=PBDNSMessage_SocketProtocol" json:"socketProtocol,omitempty"` + From []byte `protobuf:"bytes,6,opt,name=from" json:"from,omitempty"` + To []byte `protobuf:"bytes,7,opt,name=to" json:"to,omitempty"` + InBytes *uint64 `protobuf:"varint,8,opt,name=inBytes" json:"inBytes,omitempty"` + TimeSec *uint32 `protobuf:"varint,9,opt,name=timeSec" json:"timeSec,omitempty"` + TimeUsec *uint32 `protobuf:"varint,10,opt,name=timeUsec" json:"timeUsec,omitempty"` + Id *uint32 `protobuf:"varint,11,opt,name=id" json:"id,omitempty"` + Question *PBDNSMessage_DNSQuestion `protobuf:"bytes,12,opt,name=question" json:"question,omitempty"` + Response *PBDNSMessage_DNSResponse `protobuf:"bytes,13,opt,name=response" json:"response,omitempty"` + OriginalRequestorSubnet []byte `protobuf:"bytes,14,opt,name=originalRequestorSubnet" json:"originalRequestorSubnet,omitempty"` + RequestorId *string `protobuf:"bytes,15,opt,name=requestorId" json:"requestorId,omitempty"` + InitialRequestId []byte `protobuf:"bytes,16,opt,name=initialRequestId" json:"initialRequestId,omitempty"` + DeviceId []byte `protobuf:"bytes,17,opt,name=deviceId" json:"deviceId,omitempty"` + NewlyObservedDomain *bool `protobuf:"varint,18,opt,name=newlyObservedDomain" json:"newlyObservedDomain,omitempty"` + DeviceName *string `protobuf:"bytes,19,opt,name=deviceName" json:"deviceName,omitempty"` + FromPort *uint32 `protobuf:"varint,20,opt,name=fromPort" json:"fromPort,omitempty"` + ToPort *uint32 `protobuf:"varint,21,opt,name=toPort" json:"toPort,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PBDNSMessage) Reset() { *m = PBDNSMessage{} } +func (m *PBDNSMessage) String() string { return proto.CompactTextString(m) } +func (*PBDNSMessage) ProtoMessage() {} +func (*PBDNSMessage) Descriptor() ([]byte, []int) { + return fileDescriptor_c3136ceafbfed9e7, []int{0} +} + +func (m *PBDNSMessage) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PBDNSMessage.Unmarshal(m, b) +} +func (m *PBDNSMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PBDNSMessage.Marshal(b, m, deterministic) +} +func (m *PBDNSMessage) XXX_Merge(src proto.Message) { + xxx_messageInfo_PBDNSMessage.Merge(m, src) +} +func (m *PBDNSMessage) XXX_Size() int { + return xxx_messageInfo_PBDNSMessage.Size(m) +} +func (m *PBDNSMessage) XXX_DiscardUnknown() { + xxx_messageInfo_PBDNSMessage.DiscardUnknown(m) +} + +var xxx_messageInfo_PBDNSMessage proto.InternalMessageInfo + +func (m *PBDNSMessage) GetType() PBDNSMessage_Type { + if m != nil && m.Type != nil { + return *m.Type + } + return PBDNSMessage_DNSQueryType +} + +func (m *PBDNSMessage) GetMessageId() []byte { + if m != nil { + return m.MessageId + } + return nil +} + +func (m *PBDNSMessage) GetServerIdentity() []byte { + if m != nil { + return m.ServerIdentity + } + return nil +} + +func (m *PBDNSMessage) GetSocketFamily() PBDNSMessage_SocketFamily { + if m != nil && m.SocketFamily != nil { + return *m.SocketFamily + } + return PBDNSMessage_INET +} + +func (m *PBDNSMessage) GetSocketProtocol() PBDNSMessage_SocketProtocol { + if m != nil && m.SocketProtocol != nil { + return *m.SocketProtocol + } + return PBDNSMessage_UDP +} + +func (m *PBDNSMessage) GetFrom() []byte { + if m != nil { + return m.From + } + return nil +} + +func (m *PBDNSMessage) GetTo() []byte { + if m != nil { + return m.To + } + return nil +} + +func (m *PBDNSMessage) GetInBytes() uint64 { + if m != nil && m.InBytes != nil { + return *m.InBytes + } + return 0 +} + +func (m *PBDNSMessage) GetTimeSec() uint32 { + if m != nil && m.TimeSec != nil { + return *m.TimeSec + } + return 0 +} + +func (m *PBDNSMessage) GetTimeUsec() uint32 { + if m != nil && m.TimeUsec != nil { + return *m.TimeUsec + } + return 0 +} + +func (m *PBDNSMessage) GetId() uint32 { + if m != nil && m.Id != nil { + return *m.Id + } + return 0 +} + +func (m *PBDNSMessage) GetQuestion() *PBDNSMessage_DNSQuestion { + if m != nil { + return m.Question + } + return nil +} + +func (m *PBDNSMessage) GetResponse() *PBDNSMessage_DNSResponse { + if m != nil { + return m.Response + } + return nil +} + +func (m *PBDNSMessage) GetOriginalRequestorSubnet() []byte { + if m != nil { + return m.OriginalRequestorSubnet + } + return nil +} + +func (m *PBDNSMessage) GetRequestorId() string { + if m != nil && m.RequestorId != nil { + return *m.RequestorId + } + return "" +} + +func (m *PBDNSMessage) GetInitialRequestId() []byte { + if m != nil { + return m.InitialRequestId + } + return nil +} + +func (m *PBDNSMessage) GetDeviceId() []byte { + if m != nil { + return m.DeviceId + } + return nil +} + +func (m *PBDNSMessage) GetNewlyObservedDomain() bool { + if m != nil && m.NewlyObservedDomain != nil { + return *m.NewlyObservedDomain + } + return false +} + +func (m *PBDNSMessage) GetDeviceName() string { + if m != nil && m.DeviceName != nil { + return *m.DeviceName + } + return "" +} + +func (m *PBDNSMessage) GetFromPort() uint32 { + if m != nil && m.FromPort != nil { + return *m.FromPort + } + return 0 +} + +func (m *PBDNSMessage) GetToPort() uint32 { + if m != nil && m.ToPort != nil { + return *m.ToPort + } + return 0 +} + +type PBDNSMessage_DNSQuestion struct { + QName *string `protobuf:"bytes,1,opt,name=qName" json:"qName,omitempty"` + QType *uint32 `protobuf:"varint,2,opt,name=qType" json:"qType,omitempty"` + QClass *uint32 `protobuf:"varint,3,opt,name=qClass" json:"qClass,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PBDNSMessage_DNSQuestion) Reset() { *m = PBDNSMessage_DNSQuestion{} } +func (m *PBDNSMessage_DNSQuestion) String() string { return proto.CompactTextString(m) } +func (*PBDNSMessage_DNSQuestion) ProtoMessage() {} +func (*PBDNSMessage_DNSQuestion) Descriptor() ([]byte, []int) { + return fileDescriptor_c3136ceafbfed9e7, []int{0, 0} +} + +func (m *PBDNSMessage_DNSQuestion) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PBDNSMessage_DNSQuestion.Unmarshal(m, b) +} +func (m *PBDNSMessage_DNSQuestion) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PBDNSMessage_DNSQuestion.Marshal(b, m, deterministic) +} +func (m *PBDNSMessage_DNSQuestion) XXX_Merge(src proto.Message) { + xxx_messageInfo_PBDNSMessage_DNSQuestion.Merge(m, src) +} +func (m *PBDNSMessage_DNSQuestion) XXX_Size() int { + return xxx_messageInfo_PBDNSMessage_DNSQuestion.Size(m) +} +func (m *PBDNSMessage_DNSQuestion) XXX_DiscardUnknown() { + xxx_messageInfo_PBDNSMessage_DNSQuestion.DiscardUnknown(m) +} + +var xxx_messageInfo_PBDNSMessage_DNSQuestion proto.InternalMessageInfo + +func (m *PBDNSMessage_DNSQuestion) GetQName() string { + if m != nil && m.QName != nil { + return *m.QName + } + return "" +} + +func (m *PBDNSMessage_DNSQuestion) GetQType() uint32 { + if m != nil && m.QType != nil { + return *m.QType + } + return 0 +} + +func (m *PBDNSMessage_DNSQuestion) GetQClass() uint32 { + if m != nil && m.QClass != nil { + return *m.QClass + } + return 0 +} + +type PBDNSMessage_DNSResponse struct { + Rcode *uint32 `protobuf:"varint,1,opt,name=rcode" json:"rcode,omitempty"` + Rrs []*PBDNSMessage_DNSResponse_DNSRR `protobuf:"bytes,2,rep,name=rrs" json:"rrs,omitempty"` + AppliedPolicy *string `protobuf:"bytes,3,opt,name=appliedPolicy" json:"appliedPolicy,omitempty"` + Tags []string `protobuf:"bytes,4,rep,name=tags" json:"tags,omitempty"` + QueryTimeSec *uint32 `protobuf:"varint,5,opt,name=queryTimeSec" json:"queryTimeSec,omitempty"` + QueryTimeUsec *uint32 `protobuf:"varint,6,opt,name=queryTimeUsec" json:"queryTimeUsec,omitempty"` + AppliedPolicyType *PBDNSMessage_PolicyType `protobuf:"varint,7,opt,name=appliedPolicyType,enum=PBDNSMessage_PolicyType" json:"appliedPolicyType,omitempty"` + AppliedPolicyTrigger *string `protobuf:"bytes,8,opt,name=appliedPolicyTrigger" json:"appliedPolicyTrigger,omitempty"` + AppliedPolicyHit *string `protobuf:"bytes,9,opt,name=appliedPolicyHit" json:"appliedPolicyHit,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PBDNSMessage_DNSResponse) Reset() { *m = PBDNSMessage_DNSResponse{} } +func (m *PBDNSMessage_DNSResponse) String() string { return proto.CompactTextString(m) } +func (*PBDNSMessage_DNSResponse) ProtoMessage() {} +func (*PBDNSMessage_DNSResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c3136ceafbfed9e7, []int{0, 1} +} + +func (m *PBDNSMessage_DNSResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PBDNSMessage_DNSResponse.Unmarshal(m, b) +} +func (m *PBDNSMessage_DNSResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PBDNSMessage_DNSResponse.Marshal(b, m, deterministic) +} +func (m *PBDNSMessage_DNSResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_PBDNSMessage_DNSResponse.Merge(m, src) +} +func (m *PBDNSMessage_DNSResponse) XXX_Size() int { + return xxx_messageInfo_PBDNSMessage_DNSResponse.Size(m) +} +func (m *PBDNSMessage_DNSResponse) XXX_DiscardUnknown() { + xxx_messageInfo_PBDNSMessage_DNSResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_PBDNSMessage_DNSResponse proto.InternalMessageInfo + +func (m *PBDNSMessage_DNSResponse) GetRcode() uint32 { + if m != nil && m.Rcode != nil { + return *m.Rcode + } + return 0 +} + +func (m *PBDNSMessage_DNSResponse) GetRrs() []*PBDNSMessage_DNSResponse_DNSRR { + if m != nil { + return m.Rrs + } + return nil +} + +func (m *PBDNSMessage_DNSResponse) GetAppliedPolicy() string { + if m != nil && m.AppliedPolicy != nil { + return *m.AppliedPolicy + } + return "" +} + +func (m *PBDNSMessage_DNSResponse) GetTags() []string { + if m != nil { + return m.Tags + } + return nil +} + +func (m *PBDNSMessage_DNSResponse) GetQueryTimeSec() uint32 { + if m != nil && m.QueryTimeSec != nil { + return *m.QueryTimeSec + } + return 0 +} + +func (m *PBDNSMessage_DNSResponse) GetQueryTimeUsec() uint32 { + if m != nil && m.QueryTimeUsec != nil { + return *m.QueryTimeUsec + } + return 0 +} + +func (m *PBDNSMessage_DNSResponse) GetAppliedPolicyType() PBDNSMessage_PolicyType { + if m != nil && m.AppliedPolicyType != nil { + return *m.AppliedPolicyType + } + return PBDNSMessage_UNKNOWN +} + +func (m *PBDNSMessage_DNSResponse) GetAppliedPolicyTrigger() string { + if m != nil && m.AppliedPolicyTrigger != nil { + return *m.AppliedPolicyTrigger + } + return "" +} + +func (m *PBDNSMessage_DNSResponse) GetAppliedPolicyHit() string { + if m != nil && m.AppliedPolicyHit != nil { + return *m.AppliedPolicyHit + } + return "" +} + +// See exportTypes in https://docs.powerdns.com/recursor/lua-config/protobuf.html#protobufServer +// for the list of supported resource record types. +type PBDNSMessage_DNSResponse_DNSRR struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Type *uint32 `protobuf:"varint,2,opt,name=type" json:"type,omitempty"` + Class *uint32 `protobuf:"varint,3,opt,name=class" json:"class,omitempty"` + Ttl *uint32 `protobuf:"varint,4,opt,name=ttl" json:"ttl,omitempty"` + Rdata []byte `protobuf:"bytes,5,opt,name=rdata" json:"rdata,omitempty"` + Udr *bool `protobuf:"varint,6,opt,name=udr" json:"udr,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PBDNSMessage_DNSResponse_DNSRR) Reset() { *m = PBDNSMessage_DNSResponse_DNSRR{} } +func (m *PBDNSMessage_DNSResponse_DNSRR) String() string { return proto.CompactTextString(m) } +func (*PBDNSMessage_DNSResponse_DNSRR) ProtoMessage() {} +func (*PBDNSMessage_DNSResponse_DNSRR) Descriptor() ([]byte, []int) { + return fileDescriptor_c3136ceafbfed9e7, []int{0, 1, 0} +} + +func (m *PBDNSMessage_DNSResponse_DNSRR) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PBDNSMessage_DNSResponse_DNSRR.Unmarshal(m, b) +} +func (m *PBDNSMessage_DNSResponse_DNSRR) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PBDNSMessage_DNSResponse_DNSRR.Marshal(b, m, deterministic) +} +func (m *PBDNSMessage_DNSResponse_DNSRR) XXX_Merge(src proto.Message) { + xxx_messageInfo_PBDNSMessage_DNSResponse_DNSRR.Merge(m, src) +} +func (m *PBDNSMessage_DNSResponse_DNSRR) XXX_Size() int { + return xxx_messageInfo_PBDNSMessage_DNSResponse_DNSRR.Size(m) +} +func (m *PBDNSMessage_DNSResponse_DNSRR) XXX_DiscardUnknown() { + xxx_messageInfo_PBDNSMessage_DNSResponse_DNSRR.DiscardUnknown(m) +} + +var xxx_messageInfo_PBDNSMessage_DNSResponse_DNSRR proto.InternalMessageInfo + +func (m *PBDNSMessage_DNSResponse_DNSRR) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *PBDNSMessage_DNSResponse_DNSRR) GetType() uint32 { + if m != nil && m.Type != nil { + return *m.Type + } + return 0 +} + +func (m *PBDNSMessage_DNSResponse_DNSRR) GetClass() uint32 { + if m != nil && m.Class != nil { + return *m.Class + } + return 0 +} + +func (m *PBDNSMessage_DNSResponse_DNSRR) GetTtl() uint32 { + if m != nil && m.Ttl != nil { + return *m.Ttl + } + return 0 +} + +func (m *PBDNSMessage_DNSResponse_DNSRR) GetRdata() []byte { + if m != nil { + return m.Rdata + } + return nil +} + +func (m *PBDNSMessage_DNSResponse_DNSRR) GetUdr() bool { + if m != nil && m.Udr != nil { + return *m.Udr + } + return false +} + +type PBDNSMessageList struct { + Msg []*PBDNSMessage `protobuf:"bytes,1,rep,name=msg" json:"msg,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PBDNSMessageList) Reset() { *m = PBDNSMessageList{} } +func (m *PBDNSMessageList) String() string { return proto.CompactTextString(m) } +func (*PBDNSMessageList) ProtoMessage() {} +func (*PBDNSMessageList) Descriptor() ([]byte, []int) { + return fileDescriptor_c3136ceafbfed9e7, []int{1} +} + +func (m *PBDNSMessageList) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PBDNSMessageList.Unmarshal(m, b) +} +func (m *PBDNSMessageList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PBDNSMessageList.Marshal(b, m, deterministic) +} +func (m *PBDNSMessageList) XXX_Merge(src proto.Message) { + xxx_messageInfo_PBDNSMessageList.Merge(m, src) +} +func (m *PBDNSMessageList) XXX_Size() int { + return xxx_messageInfo_PBDNSMessageList.Size(m) +} +func (m *PBDNSMessageList) XXX_DiscardUnknown() { + xxx_messageInfo_PBDNSMessageList.DiscardUnknown(m) +} + +var xxx_messageInfo_PBDNSMessageList proto.InternalMessageInfo + +func (m *PBDNSMessageList) GetMsg() []*PBDNSMessage { + if m != nil { + return m.Msg + } + return nil +} + +func init() { + proto.RegisterEnum("PBDNSMessage_Type", PBDNSMessage_Type_name, PBDNSMessage_Type_value) + proto.RegisterEnum("PBDNSMessage_SocketFamily", PBDNSMessage_SocketFamily_name, PBDNSMessage_SocketFamily_value) + proto.RegisterEnum("PBDNSMessage_SocketProtocol", PBDNSMessage_SocketProtocol_name, PBDNSMessage_SocketProtocol_value) + proto.RegisterEnum("PBDNSMessage_PolicyType", PBDNSMessage_PolicyType_name, PBDNSMessage_PolicyType_value) + proto.RegisterType((*PBDNSMessage)(nil), "PBDNSMessage") + proto.RegisterType((*PBDNSMessage_DNSQuestion)(nil), "PBDNSMessage.DNSQuestion") + proto.RegisterType((*PBDNSMessage_DNSResponse)(nil), "PBDNSMessage.DNSResponse") + proto.RegisterType((*PBDNSMessage_DNSResponse_DNSRR)(nil), "PBDNSMessage.DNSResponse.DNSRR") + proto.RegisterType((*PBDNSMessageList)(nil), "PBDNSMessageList") +} + +func init() { + proto.RegisterFile("dnsmessage.proto", fileDescriptor_c3136ceafbfed9e7) +} + +var fileDescriptor_c3136ceafbfed9e7 = []byte{ + // 836 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x54, 0xdd, 0x8f, 0xdb, 0xc4, + 0x17, 0x95, 0x3f, 0xb2, 0x49, 0x6e, 0xec, 0xd4, 0x9d, 0xcd, 0xef, 0xd7, 0x21, 0x54, 0xd4, 0x0a, + 0xa8, 0xb2, 0x78, 0x58, 0x41, 0x10, 0x88, 0x27, 0x24, 0xba, 0x49, 0x85, 0x45, 0xeb, 0xf5, 0x8e, + 0xb3, 0x42, 0x3c, 0xba, 0xf6, 0x60, 0x8d, 0x48, 0x3c, 0x59, 0x7b, 0x52, 0x94, 0x27, 0x84, 0xf8, + 0xc7, 0xd1, 0x5c, 0xe7, 0xc3, 0xee, 0xee, 0xbe, 0xdd, 0x73, 0xee, 0xb9, 0xc7, 0x9e, 0x7b, 0xef, + 0x0c, 0x78, 0x79, 0x59, 0x6f, 0x78, 0x5d, 0xa7, 0x05, 0xbf, 0xda, 0x56, 0x52, 0xc9, 0xd9, 0x3f, + 0x2e, 0x38, 0xf1, 0x9b, 0x45, 0x94, 0xbc, 0x6f, 0x68, 0xf2, 0x1a, 0x6c, 0xb5, 0xdf, 0x72, 0x6a, + 0xf8, 0x66, 0x30, 0x9e, 0x93, 0xab, 0x76, 0xf2, 0x6a, 0xb5, 0xdf, 0x72, 0x86, 0x79, 0xf2, 0x12, + 0x86, 0x07, 0xa7, 0x30, 0xa7, 0xa6, 0x6f, 0x04, 0x0e, 0x3b, 0x13, 0xe4, 0x35, 0x8c, 0x6b, 0x5e, + 0x7d, 0xe4, 0x55, 0x98, 0xf3, 0x52, 0x09, 0xb5, 0xa7, 0x16, 0x4a, 0x3e, 0x61, 0xc9, 0x4f, 0xe0, + 0xd4, 0x32, 0xfb, 0x93, 0xab, 0xb7, 0xe9, 0x46, 0xac, 0xf7, 0xd4, 0xf6, 0x8d, 0x60, 0x3c, 0x9f, + 0x76, 0xbf, 0x9a, 0xb4, 0x14, 0xac, 0xa3, 0x27, 0x0b, 0x18, 0x37, 0x38, 0xd6, 0xa7, 0xc9, 0xe4, + 0x9a, 0xf6, 0xd0, 0xe1, 0xe5, 0x63, 0x0e, 0x47, 0x0d, 0xfb, 0xa4, 0x86, 0x10, 0xb0, 0xff, 0xa8, + 0xe4, 0x86, 0x5e, 0xe0, 0x3f, 0x62, 0x4c, 0xc6, 0x60, 0x2a, 0x49, 0xfb, 0xc8, 0x98, 0x4a, 0x12, + 0x0a, 0x7d, 0x51, 0xbe, 0xd9, 0x2b, 0x5e, 0xd3, 0x81, 0x6f, 0x04, 0x36, 0x3b, 0x42, 0x9d, 0x51, + 0x62, 0xc3, 0x13, 0x9e, 0xd1, 0xa1, 0x6f, 0x04, 0x2e, 0x3b, 0x42, 0x32, 0x85, 0x81, 0x0e, 0xef, + 0x6a, 0x9e, 0x51, 0xc0, 0xd4, 0x09, 0x6b, 0x7f, 0x91, 0xd3, 0x11, 0xb2, 0xa6, 0xc8, 0xc9, 0xf7, + 0x30, 0xb8, 0xdf, 0xf1, 0x5a, 0x09, 0x59, 0x52, 0xc7, 0x37, 0x82, 0xd1, 0xfc, 0xb3, 0xee, 0x19, + 0x16, 0x51, 0x72, 0x7b, 0x10, 0xb0, 0x93, 0x54, 0x97, 0x55, 0xbc, 0xde, 0xca, 0xb2, 0xe6, 0xd4, + 0x7d, 0xa2, 0x8c, 0x1d, 0x04, 0xec, 0x24, 0x25, 0x3f, 0xc2, 0x0b, 0x59, 0x89, 0x42, 0x94, 0xe9, + 0x9a, 0x71, 0x34, 0x93, 0x55, 0xb2, 0xfb, 0x50, 0x72, 0x45, 0xc7, 0x78, 0xe4, 0xa7, 0xd2, 0xc4, + 0x87, 0x51, 0x75, 0xa4, 0xc2, 0x9c, 0x3e, 0xf3, 0x8d, 0x60, 0xc8, 0xda, 0x14, 0xf9, 0x1a, 0x3c, + 0x51, 0x0a, 0x25, 0x4e, 0xb5, 0x61, 0x4e, 0x3d, 0x34, 0x7d, 0xc0, 0xeb, 0x0e, 0xe5, 0xfc, 0xa3, + 0xc8, 0xf4, 0x12, 0x3d, 0x47, 0xcd, 0x09, 0x93, 0x6f, 0xe0, 0xb2, 0xe4, 0x7f, 0xad, 0xf7, 0x37, + 0x1f, 0x70, 0x69, 0xf2, 0x85, 0xdc, 0xa4, 0xa2, 0xa4, 0xc4, 0x37, 0x82, 0x01, 0x7b, 0x2c, 0x45, + 0xbe, 0x00, 0x68, 0xaa, 0xa3, 0x74, 0xc3, 0xe9, 0x25, 0xfe, 0x5a, 0x8b, 0xd1, 0x5f, 0xd3, 0xb3, + 0x8d, 0x65, 0xa5, 0xe8, 0xa4, 0x99, 0xc7, 0x11, 0x93, 0xff, 0xc3, 0x85, 0x92, 0x98, 0xf9, 0x1f, + 0x66, 0x0e, 0x68, 0x7a, 0x0b, 0xa3, 0x56, 0xe7, 0xc9, 0x04, 0x7a, 0xf7, 0xe8, 0x6e, 0xa0, 0x7b, + 0x03, 0x90, 0xd5, 0x77, 0x03, 0x2f, 0x82, 0xcb, 0x1a, 0xa0, 0x2d, 0xef, 0xaf, 0xd7, 0x69, 0x5d, + 0xe3, 0xf2, 0xbb, 0xec, 0x80, 0xa6, 0xff, 0xda, 0xe8, 0x79, 0x1c, 0x8b, 0xae, 0xae, 0x32, 0x99, + 0x37, 0x9e, 0x2e, 0x6b, 0x00, 0xf9, 0x16, 0xac, 0xaa, 0xaa, 0xa9, 0xe9, 0x5b, 0xc1, 0x68, 0xfe, + 0xea, 0xc9, 0xa1, 0x62, 0xcc, 0x98, 0xd6, 0x92, 0xaf, 0xc0, 0x4d, 0xb7, 0xdb, 0xb5, 0xe0, 0x79, + 0x2c, 0xd7, 0x22, 0x6b, 0x2e, 0xdd, 0x90, 0x75, 0x49, 0xbd, 0xed, 0x2a, 0x2d, 0x6a, 0x6a, 0xfb, + 0x56, 0x30, 0x64, 0x18, 0x93, 0x19, 0x38, 0xf7, 0x3b, 0x5e, 0xed, 0x57, 0x87, 0x45, 0xee, 0xe1, + 0x9f, 0x74, 0x38, 0xed, 0x7e, 0xc2, 0xb8, 0xd2, 0x17, 0x28, 0xea, 0x92, 0xe4, 0x2d, 0x3c, 0xef, + 0x7c, 0x0e, 0xdb, 0xd2, 0xc7, 0x4b, 0x49, 0xbb, 0x87, 0x38, 0xe7, 0xd9, 0xc3, 0x12, 0x32, 0x87, + 0x49, 0x97, 0xac, 0x44, 0x51, 0xf0, 0x0a, 0x2f, 0xdf, 0x90, 0x3d, 0x9a, 0xd3, 0x9b, 0xd7, 0xe1, + 0x7f, 0x11, 0x0a, 0xaf, 0xe4, 0x90, 0x3d, 0xe0, 0xa7, 0x7f, 0x43, 0x0f, 0x3b, 0xa7, 0xdb, 0x51, + 0x9e, 0x07, 0x8a, 0x31, 0xb6, 0xe8, 0x3c, 0xce, 0xe6, 0xc1, 0x9b, 0x40, 0x2f, 0x6b, 0x0d, 0xb3, + 0x01, 0xc4, 0x03, 0x4b, 0xa9, 0x35, 0xbe, 0x5b, 0x2e, 0xd3, 0x21, 0x4e, 0x33, 0x4f, 0x55, 0x8a, + 0x3d, 0x74, 0x58, 0x03, 0xb4, 0x6e, 0x97, 0x57, 0xd8, 0xb2, 0x01, 0xd3, 0xe1, 0x2c, 0x07, 0x1b, + 0x0f, 0xea, 0x81, 0xd3, 0x2c, 0x58, 0x85, 0x07, 0xf7, 0x0c, 0x72, 0x09, 0xcf, 0x5a, 0x03, 0x46, + 0xd2, 0x24, 0x14, 0x26, 0x8b, 0x28, 0xb9, 0xd9, 0xa9, 0x42, 0x8a, 0xb2, 0x38, 0xcb, 0x2d, 0xf2, + 0x39, 0xbc, 0x58, 0x44, 0x49, 0x58, 0x66, 0x72, 0x23, 0xca, 0xa2, 0x53, 0x66, 0xcf, 0xbe, 0x04, + 0xa7, 0xfd, 0x7c, 0x92, 0x01, 0xd8, 0x61, 0xb4, 0x5c, 0x79, 0x06, 0x19, 0x42, 0x4f, 0x47, 0x3f, + 0x78, 0xe6, 0x6c, 0x06, 0xe3, 0xee, 0x0b, 0x49, 0xfa, 0x60, 0xdd, 0x2d, 0x62, 0xcf, 0xd0, 0xc1, + 0xea, 0x3a, 0xf6, 0xcc, 0xd9, 0xef, 0x00, 0xad, 0xe9, 0x8c, 0xa0, 0x7f, 0x17, 0xfd, 0x1a, 0xdd, + 0xfc, 0x16, 0x35, 0x4e, 0xb7, 0xd1, 0xcf, 0xef, 0x97, 0x9e, 0x49, 0x1c, 0x18, 0x5c, 0xbf, 0x0b, + 0x97, 0xd1, 0x2a, 0x8c, 0x3d, 0x8b, 0x8c, 0x01, 0xd8, 0x32, 0x89, 0x6f, 0xa2, 0x64, 0x19, 0xc6, + 0x9e, 0xad, 0xab, 0xa2, 0x64, 0x81, 0xd2, 0x9e, 0xfe, 0x93, 0x28, 0x09, 0x63, 0xef, 0x62, 0xf6, + 0x1d, 0x78, 0xed, 0xc5, 0x78, 0x27, 0x6a, 0x45, 0x5e, 0x81, 0xb5, 0xa9, 0x0b, 0x6a, 0xe0, 0xf6, + 0xbb, 0x9d, 0xc5, 0x61, 0x3a, 0xf3, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3d, 0x56, 0xce, 0x98, + 0xcb, 0x06, 0x00, 0x00, +} diff --git a/protobuf/dnsmessage.proto b/protobuf/dnsmessage.proto new file mode 100644 index 0000000..c75e67e --- /dev/null +++ b/protobuf/dnsmessage.proto @@ -0,0 +1,105 @@ +/* + * This file describes the message format used by the protobuf logging feature in PowerDNS and dnsdist. + * + * MIT License + * + * Copyright (c) 2016-now PowerDNS.COM B.V. and its contributors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +syntax = "proto2"; + +message PBDNSMessage { + enum Type { + DNSQueryType = 1; // Query received by the service + DNSResponseType = 2; // Response returned by the service + DNSOutgoingQueryType = 3; // Query sent out by the service to a remote server + DNSIncomingResponseType = 4; // Response returned by the remote server + } + enum SocketFamily { + INET = 1; // IPv4 (RFC 791) + INET6 = 2; // IPv6 (RFC 2460) + } + enum SocketProtocol { + UDP = 1; // User Datagram Protocol (RFC 768) + TCP = 2; // Transmission Control Protocol (RFC 793) + } + enum PolicyType { + UNKNOWN = 1; // No RPZ policy applied, or unknown type + QNAME = 2; // Policy matched on the QName + CLIENTIP = 3; // Policy matched on the client IP + RESPONSEIP = 4; // Policy matched on one of the IPs contained in the answer + NSDNAME = 5; // Policy matched on the name of one nameserver involved + NSIP = 6; // Policy matched on the IP of one nameserver involved + } + required Type type = 1; // Type of event + optional bytes messageId = 2; // UUID, shared by the query and the response + optional bytes serverIdentity = 3; // ID of the server emitting the protobuf message + optional SocketFamily socketFamily = 4; + optional SocketProtocol socketProtocol = 5; + optional bytes from = 6; // DNS requestor (client) as 4 (IPv4) or 16 (IPv6) raw bytes in network byte order + optional bytes to = 7; // DNS responder (server) as 4 (IPv4) or 16 (IPv6) raw bytes in network byte order + optional uint64 inBytes = 8; // Size of the query or response on the wire + optional uint32 timeSec = 9; // Time of message reception (seconds since epoch) + optional uint32 timeUsec = 10; // Time of message reception (additional micro-seconds) + optional uint32 id = 11; // ID of the query/response as found in the DNS header + + message DNSQuestion { + optional string qName = 1; // Fully qualified DNS name (with trailing dot) + optional uint32 qType = 2; // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4 + optional uint32 qClass = 3; // Typically 1 (IN), see https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2 + } + optional DNSQuestion question = 12; // DNS query received from client + + message DNSResponse { + // See exportTypes in https://docs.powerdns.com/recursor/lua-config/protobuf.html#protobufServer + // for the list of supported resource record types. + message DNSRR { + optional string name = 1; // Fully qualified DNS name (with trailing dot) + optional uint32 type = 2; // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4 + optional uint32 class = 3; // Typically 1 (IN), see https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2 + optional uint32 ttl = 4; // TTL in seconds + optional bytes rdata = 5; // raw address bytes in network byte order for A & AAAA; text representation for others, with fully qualified (trailing dot) domain names + optional bool udr = 6; // True if this is the first time this RR has been seen for this question + } + optional uint32 rcode = 1; // DNS Response code, or 65536 for a network error including a timeout + repeated DNSRR rrs = 2; // DNS resource records in response + optional string appliedPolicy = 3; // Filtering policy (RPZ or Lua) applied + repeated string tags = 4; // Additional tags applied + optional uint32 queryTimeSec = 5; // Time of the corresponding query reception (seconds since epoch) + optional uint32 queryTimeUsec = 6; // Time of the corresponding query reception (additional micro-seconds) + optional PolicyType appliedPolicyType = 7; // Type of the filtering policy (RPZ or Lua) applied + optional string appliedPolicyTrigger = 8; // The RPZ trigger + optional string appliedPolicyHit = 9; // The value (qname or IP) that caused the hit + } + + optional DNSResponse response = 13; + optional bytes originalRequestorSubnet = 14; // EDNS Client Subnet value (4 or 16 raw bytes in network byte order) + optional string requestorId = 15; // Username of the requestor + optional bytes initialRequestId = 16; // UUID of the incoming query that initiated this outgoing query or incoming response + optional bytes deviceId = 17; // Device ID of the requestor (could be mac address IP address or e.g. IMEI, format implementation dependent) + optional bool newlyObservedDomain = 18; // True if the domain has not been seen before + optional string deviceName = 19; // Device name of the requestor + optional uint32 fromPort = 20; // Source port of the DNS query (client) + optional uint32 toPort = 21; // Destination port of the DNS query (server) +} + +message PBDNSMessageList { + repeated PBDNSMessage msg = 1; +} diff --git a/protobuf/dnstap.proto b/protobuf/dnstap.proto new file mode 100644 index 0000000..3504d99 --- /dev/null +++ b/protobuf/dnstap.proto @@ -0,0 +1,262 @@ +// dnstap: flexible, structured event replication format for DNS software +// +// This file contains the protobuf schemas for the "dnstap" structured event +// replication format for DNS software. + +// Written in 2013-2014 by Farsight Security, Inc. +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this file to the public +// domain worldwide. This file is distributed without any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication along +// with this file. If not, see: +// +// . + +package dnstap; + +// "Dnstap": this is the top-level dnstap type, which is a "union" type that +// contains other kinds of dnstap payloads, although currently only one type +// of dnstap payload is defined. +// See: https://developers.google.com/protocol-buffers/docs/techniques#union +message Dnstap { + // DNS server identity. + // If enabled, this is the identity string of the DNS server which generated + // this message. Typically this would be the same string as returned by an + // "NSID" (RFC 5001) query. + optional bytes identity = 1; + + // DNS server version. + // If enabled, this is the version string of the DNS server which generated + // this message. Typically this would be the same string as returned by a + // "version.bind" query. + optional bytes version = 2; + + // Extra data for this payload. + // This field can be used for adding an arbitrary byte-string annotation to + // the payload. No encoding or interpretation is applied or enforced. + optional bytes extra = 3; + + // Identifies which field below is filled in. + enum Type { + MESSAGE = 1; + } + required Type type = 15; + + // One of the following will be filled in. + optional Message message = 14; +} + +// SocketFamily: the network protocol family of a socket. This specifies how +// to interpret "network address" fields. +enum SocketFamily { + INET = 1; // IPv4 (RFC 791) + INET6 = 2; // IPv6 (RFC 2460) +} + +// SocketProtocol: the transport protocol of a socket. This specifies how to +// interpret "transport port" fields. +enum SocketProtocol { + UDP = 1; // User Datagram Protocol (RFC 768) + TCP = 2; // Transmission Control Protocol (RFC 793) +} + +// Message: a wire-format (RFC 1035 section 4) DNS message and associated +// metadata. Applications generating "Message" payloads should follow +// certain requirements based on the MessageType, see below. +message Message { + + // There are eight types of "Message" defined that correspond to the + // four arrows in the following diagram, slightly modified from RFC 1035 + // section 2: + + // +---------+ +----------+ +--------+ + // | | query | | query | | + // | Stub |-SQ--------CQ->| Recursive|-RQ----AQ->| Auth. | + // | Resolver| | Server | | Name | + // | |<-SR--------CR-| |<-RR----AR-| Server | + // +---------+ response | | response | | + // +----------+ +--------+ + + // Each arrow has two Type values each, one for each "end" of each arrow, + // because these are considered to be distinct events. Each end of each + // arrow on the diagram above has been marked with a two-letter Type + // mnemonic. Clockwise from upper left, these mnemonic values are: + // + // SQ: STUB_QUERY + // CQ: CLIENT_QUERY + // RQ: RESOLVER_QUERY + // AQ: AUTH_QUERY + // AR: AUTH_RESPONSE + // RR: RESOLVER_RESPONSE + // CR: CLIENT_RESPONSE + // SR: STUB_RESPONSE + + // Two additional types of "Message" have been defined for the + // "forwarding" case where an upstream DNS server is responsible for + // further recursion. These are not shown on the diagram above, but have + // the following mnemonic values: + + // FQ: FORWARDER_QUERY + // FR: FORWARDER_RESPONSE + + // The "Message" Type values are defined below. + + enum Type { + // AUTH_QUERY is a DNS query message received from a resolver by an + // authoritative name server, from the perspective of the authorative + // name server. + AUTH_QUERY = 1; + + // AUTH_RESPONSE is a DNS response message sent from an authoritative + // name server to a resolver, from the perspective of the authoritative + // name server. + AUTH_RESPONSE = 2; + + // RESOLVER_QUERY is a DNS query message sent from a resolver to an + // authoritative name server, from the perspective of the resolver. + // Resolvers typically clear the RD (recursion desired) bit when + // sending queries. + RESOLVER_QUERY = 3; + + // RESOLVER_RESPONSE is a DNS response message received from an + // authoritative name server by a resolver, from the perspective of + // the resolver. + RESOLVER_RESPONSE = 4; + + // CLIENT_QUERY is a DNS query message sent from a client to a DNS + // server which is expected to perform further recursion, from the + // perspective of the DNS server. The client may be a stub resolver or + // forwarder or some other type of software which typically sets the RD + // (recursion desired) bit when querying the DNS server. The DNS server + // may be a simple forwarding proxy or it may be a full recursive + // resolver. + CLIENT_QUERY = 5; + + // CLIENT_RESPONSE is a DNS response message sent from a DNS server to + // a client, from the perspective of the DNS server. The DNS server + // typically sets the RA (recursion available) bit when responding. + CLIENT_RESPONSE = 6; + + // FORWARDER_QUERY is a DNS query message sent from a downstream DNS + // server to an upstream DNS server which is expected to perform + // further recursion, from the perspective of the downstream DNS + // server. + FORWARDER_QUERY = 7; + + // FORWARDER_RESPONSE is a DNS response message sent from an upstream + // DNS server performing recursion to a downstream DNS server, from the + // perspective of the downstream DNS server. + FORWARDER_RESPONSE = 8; + + // STUB_QUERY is a DNS query message sent from a stub resolver to a DNS + // server, from the perspective of the stub resolver. + STUB_QUERY = 9; + + // STUB_RESPONSE is a DNS response message sent from a DNS server to a + // stub resolver, from the perspective of the stub resolver. + STUB_RESPONSE = 10; + } + + // One of the Type values described above. + required Type type = 1; + + // One of the SocketFamily values described above. + optional SocketFamily socket_family = 2; + + // One of the SocketProtocol values described above. + optional SocketProtocol socket_protocol = 3; + + // The network address of the message initiator. + // For SocketFamily INET, this field is 4 octets (IPv4 address). + // For SocketFamily INET6, this field is 16 octets (IPv6 address). + optional bytes query_address = 4; + + // The network address of the message responder. + // For SocketFamily INET, this field is 4 octets (IPv4 address). + // For SocketFamily INET6, this field is 16 octets (IPv6 address). + optional bytes response_address = 5; + + // The transport port of the message initiator. + // This is a 16-bit UDP or TCP port number, depending on SocketProtocol. + optional uint32 query_port = 6; + + // The transport port of the message responder. + // This is a 16-bit UDP or TCP port number, depending on SocketProtocol. + optional uint32 response_port = 7; + + // The time at which the DNS query message was sent or received, depending + // on whether this is an AUTH_QUERY, RESOLVER_QUERY, or CLIENT_QUERY. + // This is the number of seconds since the UNIX epoch. + optional uint64 query_time_sec = 8; + + // The time at which the DNS query message was sent or received. + // This is the seconds fraction, expressed as a count of nanoseconds. + optional fixed32 query_time_nsec = 9; + + // The initiator's original wire-format DNS query message, verbatim. + optional bytes query_message = 10; + + // The "zone" or "bailiwick" pertaining to the DNS query message. + // This is a wire-format DNS domain name. + optional bytes query_zone = 11; + + // The time at which the DNS response message was sent or received, + // depending on whether this is an AUTH_RESPONSE, RESOLVER_RESPONSE, or + // CLIENT_RESPONSE. + // This is the number of seconds since the UNIX epoch. + optional uint64 response_time_sec = 12; + + // The time at which the DNS response message was sent or received. + // This is the seconds fraction, expressed as a count of nanoseconds. + optional fixed32 response_time_nsec = 13; + + // The responder's original wire-format DNS response message, verbatim. + optional bytes response_message = 14; +} + +// All fields except for 'type' in the Message schema are optional. +// It is recommended that at least the following fields be filled in for +// particular types of Messages. + +// AUTH_QUERY: +// socket_family, socket_protocol +// query_address, query_port +// query_message +// query_time_sec, query_time_nsec + +// AUTH_RESPONSE: +// socket_family, socket_protocol +// query_address, query_port +// query_time_sec, query_time_nsec +// response_message +// response_time_sec, response_time_nsec + +// RESOLVER_QUERY: +// socket_family, socket_protocol +// query_name, query_type, query_class +// query_message +// query_time_sec, query_time_nsec +// query_zone +// response_address, response_port + +// RESOLVER_RESPONSE: +// socket_family, socket_protocol +// query_name, query_type, query_class +// query_time_sec, query_time_nsec +// query_zone +// response_address, response_port +// response_message +// response_time_sec, response_time_nsec + +// CLIENT_QUERY: +// socket_family, socket_protocol +// query_message +// query_time_sec, query_time_nsec + +// CLIENT_RESPONSE: +// socket_family, socket_protocol +// query_time_sec, query_time_nsec +// response_message +// response_time_sec, response_time_nsec diff --git a/rtnetlink.go b/rtnetlink.go index 46898b5..d4449c0 100644 --- a/rtnetlink.go +++ b/rtnetlink.go @@ -10,7 +10,7 @@ func Example_listLink() { // Dial a connection to the rtnetlink socket conn, err := rtnetlink.Dial(nil) if err != nil { - log.Println(logError, "Example_listLink() failed", err) + debug(LogError, "Example_listLink() failed", err) return } defer conn.Close() diff --git a/run.go b/run.go deleted file mode 100644 index 510007e..0000000 --- a/run.go +++ /dev/null @@ -1,37 +0,0 @@ -package main - -import ( - "bytes" - "fmt" - "strings" - "os/exec" - - "git.wit.org/wit/shell" -) - -func run(s string) string { - cmdArgs := strings.Fields(s) - // Define the command you want to run - // cmd := exec.Command(cmdArgs) - cmd := exec.Command(cmdArgs[0], cmdArgs[1:len(cmdArgs)]...) - - // Create a buffer to capture the output - var out bytes.Buffer - - // Set the output of the command to the buffer - cmd.Stdout = &out - - // Run the command - err := cmd.Run() - if err != nil { - fmt.Println("Error running command:", err) - return "" - } - - tmp := shell.Chomp(out.String()) - // Output the results - fmt.Println("Command Output:", tmp) - - return tmp -} - diff --git a/unix.go b/unix.go index c9b5cc0..e9776ae 100644 --- a/unix.go +++ b/unix.go @@ -9,6 +9,11 @@ import ( "os" "os/exec" "net" + "bytes" + "fmt" + "strings" + + "git.wit.org/wit/shell" ) func CheckSuperuser() bool { @@ -23,7 +28,7 @@ func Escalate() { cmd.Stderr = os.Stderr err := cmd.Run() if err != nil { - log.Println(logError, "exit in Escalate()") + debug(LogError, "exit in Escalate()") exit(err) } } @@ -45,7 +50,7 @@ func DumpPublicDNSZone(zone string) { func dumpIPs(host string) { ips, err := net.LookupIP(host) if err != nil { - log.Println(logError, "dumpIPs() failed:", err) + debug(LogError, "dumpIPs() failed:", err) } for _, ip := range ips { log.Println(host, ip) @@ -64,3 +69,29 @@ func ddclient() { */ func ddupdate() { } + +func run(s string) string { + cmdArgs := strings.Fields(s) + // Define the command you want to run + // cmd := exec.Command(cmdArgs) + cmd := exec.Command(cmdArgs[0], cmdArgs[1:len(cmdArgs)]...) + + // Create a buffer to capture the output + var out bytes.Buffer + + // Set the output of the command to the buffer + cmd.Stdout = &out + + // Run the command + err := cmd.Run() + if err != nil { + fmt.Println("Error running command:", err) + return "" + } + + tmp := shell.Chomp(out.String()) + // Output the results + debug(LogExec, "Command Output:", tmp) + + return tmp +}