From: Pieter Lexis Date: Thu, 9 Mar 2017 16:52:55 +0000 (+0100) Subject: Add a dot-file describing the syncres (WIP) X-Git-Tag: rec-4.1.0-alpha1~174^2~21 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0c65560b0b31b0807247cae58c32a63a1a7af58f;p=pdns Add a dot-file describing the syncres (WIP) --- diff --git a/pdns/recursordist/contrib/syncres.dot b/pdns/recursordist/contrib/syncres.dot new file mode 100644 index 000000000..d496017c2 --- /dev/null +++ b/pdns/recursordist/contrib/syncres.dot @@ -0,0 +1,263 @@ +digraph { + graph [fontname = "monospace"]; + node [fontname = "monospace"]; + edge [fontname = "monospace"]; + + subgraph cluster_beginResolve { + label="SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector&ret)\nreturns the RCODE\nret is filled with all relevant records"; + + beginResolve_doResolve [label="SyncRes::doResolve()", color=red]; + + "Is this an AXFR request?"; + "Is this an AXFR request?" -> beginResolve_return_minus_1 [label=yes]; + "Is this an AXFR request?" -> "Is qname+qclass+qtype 'special'?" [label=no]; + "Is qname+qclass+qtype 'special'?" -> "Handle special names (version.bind, localhost)" [label=yes]; + "Handle special names (version.bind, localhost)" -> beginResolve_return_0; + + "Is qname+qclass+qtype 'special'?" -> "Is the qlass IN?" [label=no]; + "Is the qlass IN?" -> beginResolve_return_minus_1 [label=no]; + "Is the qlass IN?" -> beginResolve_doResolve [label=yes]; + beginResolve_doResolve -> beginResolve_return_doResolve; + beginResolve_return_doResolve [label="return result from doResolve", color=green]; + beginResolve_return_0 [label="return 0", color=green]; + beginResolve_return_minus_1 [label="return -1", color=green]; + } + + subgraph cluster_doResolve { + label="SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector&ret, unsigned int depth, set& beenthere)"; + + doResolve_doOOBResolve [label="SyncRes::doOOBResolve()", color=red]; + doResolve_doCNAMECacheCheck [label="SyncRes::doCNAMECacheCheck()", color=red]; + doResolve_asyncResolveWrapper [label="SyncRes::asyncResolveWrapper()", color=red]; + doResolve_doCacheCheck [label="SyncRes::doCacheCheck()", color=red]; + doResolve_getBestNSNamesFromCache [label="SyncRes::getBestNSNamesFromCache()", color=red]; + doResolve_doResolveAt [label="SyncRes::doResolveAt()", color=red]; + + doResolve_return_res [label="return res", color=green]; + doResolve_return_servfail [label="return SERVFAIL", color=green]; + + "SERVFAIL if too deep" -> "Check if called from getRootNS()"; + "Check if called from getRootNS()" -> "Check if RD-bit was not set (d_cacheonly)" [label=yes]; + "Check if called from getRootNS()" -> doResolve_getBestNSNamesFromCache [label=no]; + "Check if RD-bit was not set (d_cacheonly)" -> doResolve_doCNAMECacheCheck [label=no]; + "Check if RD-bit was not set (d_cacheonly)" -> "Check if there is a forward or auth-zone" [label=yes]; + "Check if there is a forward or auth-zone" -> doResolve_doCNAMECacheCheck [label=no]; + "Check if there is a forward or auth-zone" -> "Check if we are auth" [label=yes]; + "Check if we are auth" -> doResolve_asyncResolveWrapper [label="no, so forward"]; + "Check if we are auth" -> doResolve_doOOBResolve [label=yes]; + doResolve_doOOBResolve -> "return res from doOOBResolve()"; + "return res from doOOBResolve()" [color=green]; + doResolve_asyncResolveWrapper -> "return result from asyncResolveWrapper()"; + "return result from asyncResolveWrapper()" [color=green]; + doResolve_doCNAMECacheCheck -> "Did doCNAMECacheCheck() return a true-ish value?"; + "Did doCNAMECacheCheck() return a true-ish value?" -> doResolve_return_res [label=yes]; + "Did doCNAMECacheCheck() return a true-ish value?" -> doResolve_doCacheCheck [label=no]; + doResolve_doCacheCheck -> "did doCacheCheck() return a true-ish value?"; + "did doCacheCheck() return a true-ish value?" -> doResolve_return_res [label=yes]; + "did doCacheCheck() return a true-ish value?" -> doResolve_getBestNSNamesFromCache [label=no]; + + doResolve_getBestNSNamesFromCache -> doResolve_doResolveAt; + doResolve_doResolveAt -> doResolve_return_res [label="res == -2"]; + doResolve_doResolveAt -> doResolve_return_servfail [label="res < 0 &&\nres != -2"]; + doResolve_doResolveAt -> doResolve_return_res [label="res >= 0"]; + } + + subgraph cluster_doOOBResolve { + label="SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vector&ret, unsigned int depth, int& res)\nReturns true if data came from local auth-store.\nvector ret is filled with answers"; + + doOOBResolve_getBestAuthZone [label="SyncRes::getBestAuthZone()", color=red]; + doOOBResolve_return_false [label="return false", color=green]; + doOOBResolve_return_true [label="return true", color=green]; + + doOOBResolve_getBestAuthZone -> doOOBResolve_return_false [label="returned iterator to end of authstorage"]; + doOOBResolve_getBestAuthZone -> "Add auth-records matching qname+qtype || CNAME || NS to ret" [label="returned iterator in the authstorage"]; + "Add auth-records matching qname+qtype || CNAME || NS to ret" -> doOOBResolve_return_true [label="records were added to ret"] + "Add auth-records matching qname+qtype || CNAME || NS to ret" -> "Did we have any data for the qname?" [label="no records were added to ret"]; + + "Did we have any data for the qname?" -> "Add SOA to AUTHORITY in ret" [label="yes (empty NOERROR)"]; + "Add SOA to AUTHORITY in ret" -> "Set res to NOERROR" -> doOOBResolve_return_true; + + "Did we have any data for the qname?" -> "Is there a wildcard match?" [label=no]; + "Is there a wildcard match?" -> "Add auth-records from wildcard to ret" [label=yes]; + "Add auth-records from wildcard to ret" -> "Set res to NOERROR"; + + "Is there a wildcard match?" -> "Add NS-records from auth-zone" [label=no]; + + "Add NS-records from auth-zone" -> "Set res to NOERROR" [label="NS record were added"]; + "Add NS-records from auth-zone" -> "Try to add SOA" [label="No NS record were added"]; + + "Try to add SOA" -> "Set res to NXDOMAIN" -> doOOBResolve_return_true; + } + + subgraph cluster_asyncResolveWrapper { + label="SyncRes::asyncResolveWrapper()"; + } + + subgraph cluster_doResolveAt { + label="SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype, vector&ret, unsigned int depth, set&beenthere)\nreturns -1 in case of no results, -2 when a FilterEngine Policy was hit, rcode otherwise"; + + doResolveAt_nameServersBlockedByRPZ [label="SyncRes::nameserversBlockedByRPZ()", color=red]; + doResolveAt_doOOBResolve_for_NS [label="SyncRes::doOOBResolve()", color=red]; + doResolveAt_retrieveAddressesForNS [label="SyncRes::retrieveAddressesForNS()", color=red]; + doResolveAt_nameserverIPBlockedByRPZ [label="SyncRes::nameserverIPBlockedByRPZ()", color=red]; + doResolveAt_Lua_preoutquery [label="Lua preoutquery", color=red]; + doResolveAt_asyncresolveWrapper [label="SyncRes::asyncresolveWrapper()", color=red]; + doResolveAt_processRecords [label="SyncRes::processRecords()", color=red]; + doResolveAt_doResolve [label="SyncRes::doResolve()", color=red]; + + doResolveAt_return_minus_2 [label="return -2", color=green]; + doResolveAt_return_minus_1 [label="return -1", color=green]; + doResolveAt_return_0 [label="return 0", color=green]; + doResolveAt_return_rcode [label="return rcode", color=green]; + doResolveAt_return_servfail [label="return SERVFAIL", color=green]; + doResolveAt_return_nxdomain [label="return NXDOMAIN", color=green]; + + doResolveAt_mainloop_continue [label="continue"]; + doResolveAt_mainloop_continue -> "Get nameserver from nameservers"; + + doResolveAt_nsiploop_continue [label="continue"]; + doResolveAt_nsiploop_continue -> "Get IP from IPs"; + + doResolveAt_nameServersBlockedByRPZ -> doResolveAt_return_minus_2 [label="RPZ NSDNAME hit"]; + doResolveAt_nameServersBlockedByRPZ -> "Get nameserver from nameservers" [lhead=cluster_doResolveAt_mainloop, label="RPZ NSDNAME not hit"]; + + doResolveAt_ImmediateServFailException [label="throw ImmediateServFailException", color=green]; + + "Get nameserver from nameservers" -> doResolveAt_mainloop_continue [label="qname == nsname"]; + "Get nameserver from nameservers" -> doResolveAt_return_minus_1 [label="All nameservers tried"]; + "Get nameserver from nameservers" -> "Is the nameserver out of band?"; + "Is the nameserver out of band?" -> doResolveAt_doOOBResolve_for_NS [label=yes]; + doResolveAt_doOOBResolve_for_NS -> "updateCacheFromRecords()"; + "Is the nameserver out of band?" -> doResolveAt_retrieveAddressesForNS [label=no]; + doResolveAt_retrieveAddressesForNS -> doResolveAt_mainloop_continue [label="No IPs returned"]; + doResolveAt_retrieveAddressesForNS -> doResolveAt_nameserverIPBlockedByRPZ [label="IPs returned"]; + doResolveAt_nameserverIPBlockedByRPZ -> doResolveAt_return_minus_2 [label="RPZ NSIP hit"]; + doResolveAt_nameserverIPBlockedByRPZ -> "Get IP from IPs" [label="RPZ NSIP not hit"]; + + "Get IP from IPs" -> doResolveAt_nsiploop_continue [label="IP is throttled"]; + "Get IP from IPs" -> doResolveAt_ImmediateServFailException [label="Too many queries sent while resolving"]; + "Get IP from IPs" -> doResolveAt_ImmediateServFailException [label="Resolving took too long"]; + "Get IP from IPs" -> doResolveAt_mainloop_continue [label="No IP address worked"]; + "Get IP from IPs" -> doResolveAt_Lua_preoutquery; + + doResolveAt_Lua_preoutquery -> "Check resolveret" [label="true"]; + doResolveAt_Lua_preoutquery -> doResolveAt_getEDNSSubnetMask [label="false"]; + doResolveAt_getEDNSSubnetMask -> doResolveAt_asyncresolveWrapper; + doResolveAt_asyncresolveWrapper -> "Check resolveret"; + "Check resolveret" -> doResolveAt_ImmediateServFailException [label="resolveret == -3\n(kill query)"]; + "Check resolveret" -> "resolveret == 1"; + "resolveret == 1" -> doResolveAt_nsiploop_continue [label="nameserver returned\nSERVFAIL || REFUSED"]; + "resolveret == 1" -> "updateCacheFromRecords()"; + "updateCacheFromRecords()" -> doResolveAt_return_rcode [label="rcode != NOERROR"]; // line 1473 + "updateCacheFromRecords()" -> doResolveAt_processRecords; // line 1484 + doResolveAt_processRecords -> doResolveAt_return_0 [label="done == true"]; + doResolveAt_processRecords -> "Have newtarget?"; + + "Have newtarget?" -> "qname == newtarget || depth > 10?" [label=yes]; + "qname == newtarget || depth > 10?" -> doResolveAt_return_servfail [label=yes]; + "qname == newtarget || depth > 10?" -> doResolveAt_doResolve [label=no]; + doResolveAt_doResolve -> doResolveAt_return_rcode; + + "Have newtarget?" -> "Have NXDOMAIN from upstream?" [label=no]; + "Have NXDOMAIN from upstream?" -> "Add NSECs if needed" [label=yes]; + "Add NSECs if needed" -> doResolveAt_return_nxdomain; + + "Have NXDOMAIN from upstream?" -> "Have empty NOERROR?" [label=no]; + "Have empty NOERROR?" -> "Add NSEC records if needed" [label=yes]; + "Add NSEC records if needed" -> doResolveAt_return_0; + + "Have empty NOERROR?" -> "Have realreferral?" [label=no]; + "Have realreferral?" -> "Was a server in nsset blocker by RPZNSDNAME?" [label=yes]; + "Was a server in nsset blocker by RPZNSDNAME?" -> doResolveAt_return_minus_2 [label=yes]; + "Was a server in nsset blocker by RPZNSDNAME?" -> "Get nameserver from nameservers" [label=no]; + + "Have realreferral?" -> "Was this an OOB nameserver?" [label=no]; + "Was this an OOB nameserver?" -> "Get nameserver from nameservers" [label="no, nameserver was lame"]; + "Was this an OOB nameserver?" -> "Get nameserver from nameservers" [label=yes]; + } + + subgraph cluster_processRecords { + label="SyncRes::processRecords(const std::string& prefix, const DNSName& qname, const QType& qtype, const DNSName& auth, LWResult& lwr, const bool sendRDQuery, vector& ret, set& nsset, DNSName& newtarget, DNSName& newauth, bool& realreferral, bool& negindic, bool& sawDS)\nreturns true is this level of recursion is done"; + +// { rank=same; "Get record from lwr.d_records" processRecords_return_done} + +// { rank=same; "Is this a proper CNAME referral?" "Is this a DNSSEC record in the ANSWER section?" "Is this the actual answer?" "Is this an NS record in the AUTHORITY?" "Is this a DS in the AUTHORITY?" "Is this a proper NXDOMAIN?" "Are we not done && is this a NOERROR && is this a SOA in the AUTHORITY?"} + + "Get record from lwr.d_records"; + "Get record from lwr.d_records" -> "Is this a proper NXDOMAIN?"; // line 1177 + "Get record from lwr.d_records" -> processRecords_return_done [label="All records checked"]; + "Get record from lwr.d_records" -> "Get record from lwr.d_records" [label="type != OPT &&\nclass != IN"]; + + "Is this a proper NXDOMAIN?" -> "is newtarget empty?" [label=yes]; // note, we have a CNAME chasing bug here issue #679 + "is newtarget empty?" -> processRecords_wasVariable [label=no]; + "is newtarget empty?" -> "Add this SOA to ret" [label=yes]; + processRecords_wasVariable [label="SyncRes::wasVariable", color=red] + "Add this SOA to ret" -> processRecords_wasVariable; + processRecords_wasVariable -> "Set negindic to true" [label="was indeed variable"]; + processRecords_wasVariable -> "Add to negative cache" [label="was not variable"]; + "Add to negative cache" -> "If s_rootNXTrust && auth.isRoot()"; + "If s_rootNXTrust && auth.isRoot()" -> "Set negindic to true" [label=no]; + "If s_rootNXTrust && auth.isRoot()" -> "Add tld label to negative cache" [label=yes]; + "Add tld label to negative cache" -> "Set negindic to true"; + "Set negindic to true" -> "Get record from lwr.d_records"; + + "Is this a proper NXDOMAIN?" -> "Is this a proper CNAME referral?" [label=no]; + "Is this a proper CNAME referral?" -> "Add CNAME record to ret" [label=yes]; + "Add CNAME record to ret" -> "Set newtarget to this CNAME" -> "Get record from lwr.d_records"; + + "Is this a proper CNAME referral?" -> "Is this a DNSSEC record in the ANSWER section?" [label=no]; + "Is this a DNSSEC record in the ANSWER section?" -> "Is the record.qtype not RRSIG and is the record's qname the qname we want?"[label=yes]; + "Is the record.qtype not RRSIG and is the record's qname the qname we want?" -> "Add this record to ret" [label=yes]; + "Add this record to ret" -> "Get record from lwr.d_records"; + "Is the record.qtype not RRSIG and is the record's qname the qname we want?" -> "Get record from lwr.d_records" [label=no]; + + "Is this a DNSSEC record in the ANSWER section?" -> "Is this the actual answer?" [label=no]; + "Is this the actual answer?" -> "Set done=true" [label=yes]; + "Set done=true" -> "Add answer record to ret" -> "Get record from lwr.d_records"; + + "Is this the actual answer?" -> "Is this an NS record in the AUTHORITY?" [label=no]; + "Is this an NS record in the AUTHORITY?" -> "Is record.d_name more specific than the our current auth?" [label=yes]; + "Is record.d_name more specific than the our current auth?" -> "set newauth to record.d_name" [label=yes]; + "set newauth to record.d_name" -> "set realreferral=true" -> "add NS record to ret"; + "Is record.d_name more specific than the our current auth?" -> "add NS record to ret" [label=no]; + "add NS record to ret" -> "Get record from lwr.d_records"; + + "Is this an NS record in the AUTHORITY?" -> "Is this a DS in the AUTHORITY?" [label=no]; + "Is this a DS in the AUTHORITY?" -> "set sawDS=true" [label=yes]; + "set sawDS=true" -> "Get record from lwr.d_records"; + + "Is this a DS in the AUTHORITY?" -> "Are we not done && is this a NOERROR && is this a SOA in the AUTHORITY?" [label=no]; + "Are we not done && is this a NOERROR && is this a SOA in the AUTHORITY?" -> "is newtarget empty?" [label=yes]; + "is newtarget empty?" -> "Harvest DNSSEC data and add to negative cache" [label=yes]; + "is newtarget empty?" -> "Get record from lwr.d_records"; + "Harvest DNSSEC data and add to negative cache" -> "Set negindic to true" -> "Get record from lwr.d_records"; + + "Are we not done && is this a NOERROR && is this a SOA in the AUTHORITY?" -> "Get record from lwr.d_records" [label=no]; + + processRecords_return_done [label="return done", color=green]; + } + + subgraph cluster_doCNAMECacheCheck { + label="SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector& ret, unsigned int depth, int &res)\nreturns true if this function handled the query"; + + doCNAMECacheCheck_return_true [label="return true", color=green]; + doCNAMECacheCheck_return_false [label="return false", color=green]; + + doCNAMECacheCheck_servfail [label="Set res to SERVFAIL"]; + doCNAMECacheCheck_servfail -> doCNAMECacheCheck_return_true; + + doCNAMECacheCheck_doResolve [label="SyncRes::doResolve", color=red]; + + "Too deep recursion or CNAMEs?" -> doCNAMECacheCheck_servfail [label=yes]; + "Too deep recursion or CNAMEs?" -> "Get cache entries for qname|CNAME" [label=no]; + "Get cache entries for qname|CNAME" -> "get a record from the cache entries" -> "Is the TTL not expired?"; + "Is the TTL not expired?" -> "get a record from the cache entries" [label=yes]; + "Is the TTL not expired?" -> "Add record and RRSIGS to ret" [label=no]; + "Add record and RRSIGS to ret" -> "is qtype CNAME?"; + "is qtype CNAME?" -> doCNAMECacheCheck_doResolve [label=no]; + doCNAMECacheCheck_doResolve -> "Set res to the result of doResolve" -> doCNAMECacheCheck_return_true; + "is qtype CNAME?" -> "Set res=0" [label=yes]; + "Set res=0" -> doCNAMECacheCheck_return_true; + "Get cache entries for qname|CNAME" -> doCNAMECacheCheck_return_false [label="No cache entries"]; + } +}