ZealOS/docs/Home/Net/Protocols/DNS.CC.html
TomAwezome 1b75d91002 Fix Mount AHCI Port selection.
Add arg to SATARep to specify drive types to show.
Add checks in AHCIPortInit to verify port signatures, add helper method to get signatures from port.
2021-08-02 16:40:05 -04:00

747 lines
62 KiB
HTML
Executable file

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=US-ASCII">
<meta name="generator" content="ZealOS V0.13">
<style type="text/css">
body {background-color:#fef1f0;}
.cF0{color:#000000;background-color:#fef1f0;}
.cF1{color:#0148a4;background-color:#fef1f0;}
.cF2{color:#3b7901;background-color:#fef1f0;}
.cF3{color:#057c7e;background-color:#fef1f0;}
.cF4{color:#bb2020;background-color:#fef1f0;}
.cF5{color:#9e42ae;background-color:#fef1f0;}
.cF6{color:#b57901;background-color:#fef1f0;}
.cF7{color:#b2b6af;background-color:#fef1f0;}
.cF8{color:#555753;background-color:#fef1f0;}
.cF9{color:#678fbb;background-color:#fef1f0;}
.cFA{color:#82bc49;background-color:#fef1f0;}
.cFB{color:#0097a2;background-color:#fef1f0;}
.cFC{color:#e26a6a;background-color:#fef1f0;}
.cFD{color:#c671bc;background-color:#fef1f0;}
.cFE{color:#c7ab00;background-color:#fef1f0;}
.cFF{color:#fef1f0;background-color:#fef1f0;}
</style>
</head>
<body>
<pre style="font-family:monospace;font-size:12pt">
<a name="l1"></a><span class=cF2>// https://www2.cs.duke.edu/courses/fall16/compsci356/DNS/DNS-primer.pdf</span><span class=cF0>
<a name="l2"></a></span><span class=cF2>// https://en.wikipedia.org/wiki/Domain_Name_System</span><span class=cF0>
<a name="l3"></a>
<a name="l4"></a></span><span class=cF2>// DNS Cache is a HashTable, similar to ARP Cache</span><span class=cF0>
<a name="l5"></a>
<a name="l6"></a>#</span><span class=cF1>define</span><span class=cF0> DNS_HASHTABLE_SIZE </span><span class=cFE>2048</span><span class=cF0> </span><span class=cF2>// 1024 might be fine, test it</span><span class=cF0>
<a name="l7"></a>#</span><span class=cF1>define</span><span class=cF0> HTT_DNS </span><span class=cFE>0x00100</span><span class=cF0> </span><span class=cF2>// identical to HTT_DICT_WORD</span><span class=cF0>
<a name="l8"></a>
<a name="l9"></a>#</span><span class=cF1>define</span><span class=cF0> DNS_FLAG_RD </span><span class=cFE>0x0100</span><span class=cF0>
<a name="l10"></a>
<a name="l11"></a>#</span><span class=cF1>define</span><span class=cF0> DNS_OP_QUERY </span><span class=cFE>0</span><span class=cF0>
<a name="l12"></a>
<a name="l13"></a>#</span><span class=cF1>define</span><span class=cF0> DNS_TYPE_A </span><span class=cFE>1</span><span class=cF0>
<a name="l14"></a>
<a name="l15"></a>#</span><span class=cF1>define</span><span class=cF0> DNS_CLASS_IN </span><span class=cFE>1</span><span class=cF0>
<a name="l16"></a>
<a name="l17"></a>#</span><span class=cF1>define</span><span class=cF0> DNS_TIMEOUT </span><span class=cFE>5000</span><span class=cF0>
<a name="l18"></a>
<a name="l19"></a>#</span><span class=cF1>define</span><span class=cF0> DNS_MAX_RETRIES </span><span class=cFE>5</span><span class=cF0>
<a name="l20"></a>
<a name="l21"></a></span><span class=cF1>class</span><span class=cF0> CDNSHash:</span><span class=cF9>CHash</span><span class=cF0>
<a name="l22"></a>{ </span><span class=cF2>// store U8 *hostname as CHash-&gt;str U8 *</span><span class=cF0>
<a name="l23"></a> CAddressInfo info;
<a name="l24"></a> </span><span class=cF2>// Shrine has 'TODO: honor TTL' ...</span><span class=cF0>
<a name="l25"></a> </span><span class=cF2>// Duke: 'TTL: the number of seconds the results can be cached'</span><span class=cF0>
<a name="l26"></a> </span><span class=cF2>// perhaps have a separate task for removing cached results ?</span><span class=cF0>
<a name="l27"></a>};
<a name="l28"></a>
<a name="l29"></a></span><span class=cF1>class</span><span class=cF0> CDNSDomainName
<a name="l30"></a>{
<a name="l31"></a> </span><span class=cF1>U8</span><span class=cF0> **labels;
<a name="l32"></a> </span><span class=cF9>I64</span><span class=cF0> num_labels;
<a name="l33"></a>};
<a name="l34"></a>
<a name="l35"></a></span><span class=cF1>class</span><span class=cF0> CDNSQuestion
<a name="l36"></a>{
<a name="l37"></a> CDNSQuestion *next;
<a name="l38"></a> CDNSDomainName q_name;
<a name="l39"></a> </span><span class=cF9>U16</span><span class=cF0> q_type;
<a name="l40"></a> </span><span class=cF9>U16</span><span class=cF0> q_class;
<a name="l41"></a>};
<a name="l42"></a>
<a name="l43"></a></span><span class=cF1>class</span><span class=cF0> CDNSHeader
<a name="l44"></a>{
<a name="l45"></a> </span><span class=cF9>U16</span><span class=cF0> id;
<a name="l46"></a> </span><span class=cF9>U16</span><span class=cF0> flags;
<a name="l47"></a> </span><span class=cF9>U16</span><span class=cF0> q_count; </span><span class=cF2>// number of entries in question section</span><span class=cF0>
<a name="l48"></a> </span><span class=cF9>U16</span><span class=cF0> a_count; </span><span class=cF2>// number of resource records in answer section</span><span class=cF0>
<a name="l49"></a> </span><span class=cF9>U16</span><span class=cF0> ns_count; </span><span class=cF2>// number of name server resource records in authority records section</span><span class=cF0>
<a name="l50"></a> </span><span class=cF9>U16</span><span class=cF0> ar_count; </span><span class=cF2>// number of resource records in additional records section</span><span class=cF0>
<a name="l51"></a>};
<a name="l52"></a>
<a name="l53"></a></span><span class=cF1>class</span><span class=cF0> CDNSRR
<a name="l54"></a>{ </span><span class=cF2>// RR: Resource Record</span><span class=cF0>
<a name="l55"></a> CDNSRR *next;
<a name="l56"></a> CDNSDomainName name; </span><span class=cF2>// name of the node this record is for</span><span class=cF0>
<a name="l57"></a> </span><span class=cF9>U16</span><span class=cF0> type; </span><span class=cF2>// RR type, e.g. 44=SSHFP, 15=MX, 49=DHCID ...</span><span class=cF0>
<a name="l58"></a> </span><span class=cF9>U16</span><span class=cF0> rr_class; </span><span class=cF2>// class code</span><span class=cF0>
<a name="l59"></a> </span><span class=cF9>U32</span><span class=cF0> ttl; </span><span class=cF2>// count in seconds that RR stays valid (max = 2^31 - 1)</span><span class=cF0>
<a name="l60"></a> </span><span class=cF9>U16</span><span class=cF0> rd_length; </span><span class=cF2>// length of r_data member</span><span class=cF0>
<a name="l61"></a> </span><span class=cF1>U8</span><span class=cF0> *r_data; </span><span class=cF2>// additional RR-specific data</span><span class=cF0>
<a name="l62"></a>};
<a name="l63"></a>
<a name="l64"></a></span><span class=cF1>class</span><span class=cF0> CDNSGlobals
<a name="l65"></a>{
<a name="l66"></a> </span><span class=cF9>U16</span><span class=cF0> addr_family;
<a name="l67"></a> CIPAddressStorage dns_ip;
<a name="l68"></a>
<a name="l69"></a>} dns_globals;
<a name="l70"></a>
<a name="l71"></a></span><span class=cF9>CHashTable</span><span class=cF0> *dns_cache = </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l72"></a>
<a name="l73"></a></span><span class=cF1>U0</span><span class=cF0> DNSCacheInit()
<a name="l74"></a>{
<a name="l75"></a> dns_cache = </span><span class=cF5>HashTableNew</span><span class=cF0>(DNS_HASHTABLE_SIZE);
<a name="l76"></a>
<a name="l77"></a> </span><span class=cF5>MemSet</span><span class=cF0>(&amp;dns_globals.dns_ip, </span><span class=cFE>0</span><span class=cF0>, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CIPAddressStorage</span><span class=cF7>)</span><span class=cF0>);
<a name="l78"></a> dns_globals.addr_family = </span><span class=cFE>0</span><span class=cF0>;
<a name="l79"></a>}
<a name="l80"></a>
<a name="l81"></a>CDNSHash *DNSCacheFind(</span><span class=cF1>U8</span><span class=cF0> *hostname)
<a name="l82"></a>{
<a name="l83"></a> CDNSHash *entry = </span><span class=cF5>HashFind</span><span class=cF0>(hostname, dns_cache, HTT_DNS);
<a name="l84"></a>
<a name="l85"></a> </span><span class=cF1>if</span><span class=cF0> (entry == </span><span class=cF3>NULL</span><span class=cF0>)
<a name="l86"></a> NetWarn(</span><span class=cF6>&quot;DNS CACHE FIND: Could not find a hostname in the DNS Cache.&quot;</span><span class=cF0>);
<a name="l87"></a>
<a name="l88"></a> </span><span class=cF1>return</span><span class=cF0> entry;
<a name="l89"></a>}
<a name="l90"></a>
<a name="l91"></a>CDNSHash *DNSCachePut(</span><span class=cF1>U8</span><span class=cF0> *hostname, CAddressInfo *info)
<a name="l92"></a>{
<a name="l93"></a> NetLog(</span><span class=cF6>&quot;DNS CACHE PUT: Attempting Find DNS Entry in Cache: hostname: %s&quot;</span><span class=cF0>, hostname);
<a name="l94"></a> CDNSHash *entry = DNSCacheFind(hostname);
<a name="l95"></a>
<a name="l96"></a> </span><span class=cF1>if</span><span class=cF0> (!entry)
<a name="l97"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l98"></a> entry = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CDNSHash</span><span class=cF7>)</span><span class=cF0>);
<a name="l99"></a> entry-&gt;str = </span><span class=cF5>StrNew</span><span class=cF0>(hostname);
<a name="l100"></a> entry-&gt;type = HTT_DNS;
<a name="l101"></a>
<a name="l102"></a> AddressInfoCopy(&amp;entry-&gt;info, info);
<a name="l103"></a>
<a name="l104"></a> </span><span class=cF5>HashAdd</span><span class=cF0>(entry, dns_cache);
<a name="l105"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l106"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l107"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l108"></a> NetWarn(</span><span class=cF6>&quot;DNS CACHE PUT: Entry was already found in Cache. Overwriting.&quot;</span><span class=cF0>);
<a name="l109"></a> </span><span class=cF5>Free</span><span class=cF0>(entry-&gt;info.address);
<a name="l110"></a> AddressInfoCopy(&amp;entry-&gt;info, info);
<a name="l111"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l112"></a>
<a name="l113"></a> </span><span class=cF1>return</span><span class=cF0> entry;
<a name="l114"></a>}
<a name="l115"></a>
<a name="l116"></a></span><span class=cF9>I64</span><span class=cF0> DNSQuestionSizeCalculate(CDNSQuestion *q)
<a name="l117"></a>{ </span><span class=cF2>// ??</span><span class=cF0>
<a name="l118"></a> </span><span class=cF9>I64</span><span class=cF0> i, size = </span><span class=cFE>0</span><span class=cF0>;
<a name="l119"></a>
<a name="l120"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i &lt; q-&gt;q_name.num_labels; i++)
<a name="l121"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l122"></a> size += </span><span class=cFE>1</span><span class=cF0> + </span><span class=cF5>StrLen</span><span class=cF0>(q-&gt;q_name.labels[i]);
<a name="l123"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l124"></a>
<a name="l125"></a> </span><span class=cF1>return</span><span class=cF0> size + </span><span class=cFE>1</span><span class=cF0> + </span><span class=cFE>4</span><span class=cF0>;
<a name="l126"></a>}
<a name="l127"></a>
<a name="l128"></a></span><span class=cF1>U0</span><span class=cF0> DNSQuestionSerialize(</span><span class=cF1>U8</span><span class=cF0> *buffer, CDNSQuestion *q)
<a name="l129"></a>{ </span><span class=cF2>// ??</span><span class=cF0>
<a name="l130"></a> </span><span class=cF9>I64</span><span class=cF0> i;
<a name="l131"></a> </span><span class=cF1>U8</span><span class=cF0> *label;
<a name="l132"></a>
<a name="l133"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i &lt; q-&gt;q_name.num_labels; i++)
<a name="l134"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l135"></a> label = q-&gt;q_name.labels[i];
<a name="l136"></a>
<a name="l137"></a> *buffer++ = </span><span class=cF5>StrLen</span><span class=cF0>(label);
<a name="l138"></a>
<a name="l139"></a> </span><span class=cF1>while</span><span class=cF0> (*label)
<a name="l140"></a> *buffer++ = *label++;
<a name="l141"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l142"></a>
<a name="l143"></a> *buffer++ = </span><span class=cFE>0</span><span class=cF0>;
<a name="l144"></a> *buffer++ = q-&gt;q_type &gt;&gt; </span><span class=cFE>8</span><span class=cF0>;
<a name="l145"></a> *buffer++ = q-&gt;q_type &amp; </span><span class=cFE>0xFF</span><span class=cF0>;
<a name="l146"></a> *buffer++ = q-&gt;q_class &gt;&gt; </span><span class=cFE>8</span><span class=cF0>;
<a name="l147"></a> *buffer++ = q-&gt;q_class &amp; </span><span class=cFE>0xFF</span><span class=cF0>;
<a name="l148"></a>}
<a name="l149"></a>
<a name="l150"></a></span><span class=cF9>I64</span><span class=cF0> DNSQuestionSend(</span><span class=cF9>U16</span><span class=cF0> id, </span><span class=cF9>U16</span><span class=cF0> local_port, CDNSQuestion *q)
<a name="l151"></a>{
<a name="l152"></a> CIPV4Address *ipv4_addr;
<a name="l153"></a> </span><span class=cF1>U8</span><span class=cF0> *dns_frame;
<a name="l154"></a> </span><span class=cF9>U16</span><span class=cF0> flags;
<a name="l155"></a> CDNSHeader *header;
<a name="l156"></a> </span><span class=cF9>I64</span><span class=cF0> de_index;
<a name="l157"></a>
<a name="l158"></a> </span><span class=cF1>switch</span><span class=cF0> (dns_globals.addr_family)
<a name="l159"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l160"></a> </span><span class=cF1>case</span><span class=cF0> AF_UNSPEC: </span><span class=cF2>// 0, global dns ip not set</span><span class=cF0>
<a name="l161"></a> NetErr(</span><span class=cF6>&quot;DNS SEND QUESTION: Failed, global dns addr family was AF_UNSPEC.&quot;</span><span class=cF0>);
<a name="l162"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l163"></a>
<a name="l164"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET6:
<a name="l165"></a> NetErr(</span><span class=cF6>&quot;DNS SEND QUESTION: Failed, IPV6 not supported yet in DNS.&quot;</span><span class=cF0>);
<a name="l166"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'DNS'</span><span class=cF0>);
<a name="l167"></a>
<a name="l168"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET:
<a name="l169"></a> ipv4_addr = &amp;dns_globals.dns_ip;
<a name="l170"></a>
<a name="l171"></a> </span><span class=cF1>if</span><span class=cF0> (!*ipv4_addr)
<a name="l172"></a> {
<a name="l173"></a> NetErr(</span><span class=cF6>&quot;DNS SEND QUESTION: Failed, ipv4_addr had no value set.&quot;</span><span class=cF0>);
<a name="l174"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l175"></a> }
<a name="l176"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l177"></a>
<a name="l178"></a> </span><span class=cF2>// UDPPacketAllocate currently only accepts IPV4 ...</span><span class=cF0>
<a name="l179"></a> de_index = UDPPacketAllocate(&amp;dns_frame,
<a name="l180"></a> IPV4AddressGet,
<a name="l181"></a> local_port,
<a name="l182"></a> *ipv4_addr,
<a name="l183"></a> </span><span class=cFE>53</span><span class=cF0>,
<a name="l184"></a> </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CDNSHeader</span><span class=cF7>)</span><span class=cF0> + DNSQuestionSizeCalculate</span><span class=cF7>(</span><span class=cF0>q</span><span class=cF7>)</span><span class=cF0>);
<a name="l185"></a> </span><span class=cF1>if</span><span class=cF0> (de_index &lt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l186"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l187"></a> NetErr(</span><span class=cF6>&quot;DNS SEND QUESTION: Failed, UDPPacketAllocate returned error.&quot;</span><span class=cF0>);
<a name="l188"></a> </span><span class=cF1>return</span><span class=cF0> de_index;
<a name="l189"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l190"></a>
<a name="l191"></a> flags = DNS_OP_QUERY &lt;&lt; </span><span class=cFE>11</span><span class=cF0> | DNS_FLAG_RD;
<a name="l192"></a>
<a name="l193"></a> header = dns_frame;
<a name="l194"></a>
<a name="l195"></a> header-&gt;id = </span><span class=cF5>EndianU16</span><span class=cF0>(id);
<a name="l196"></a> header-&gt;flags = </span><span class=cF5>EndianU16</span><span class=cF0>(flags);
<a name="l197"></a> header-&gt;q_count = </span><span class=cF5>EndianU16</span><span class=cF0>(</span><span class=cFE>1</span><span class=cF0>);
<a name="l198"></a> header-&gt;a_count = </span><span class=cFE>0</span><span class=cF0>;
<a name="l199"></a> header-&gt;ns_count = </span><span class=cFE>0</span><span class=cF0>;
<a name="l200"></a> header-&gt;ar_count = </span><span class=cFE>0</span><span class=cF0>;
<a name="l201"></a>
<a name="l202"></a> DNSQuestionSerialize(dns_frame + </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CDNSHeader</span><span class=cF7>)</span><span class=cF0>, q);
<a name="l203"></a>
<a name="l204"></a> UDPPacketFinish(de_index);
<a name="l205"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
<a name="l206"></a>
<a name="l207"></a>}
<a name="l208"></a>
<a name="l209"></a>
<a name="l210"></a></span><span class=cF9>I64</span><span class=cF0> DNSDomainNameParse(</span><span class=cF1>U8</span><span class=cF0> *packet_data, </span><span class=cF9>I64</span><span class=cF0> packet_length, </span><span class=cF1>U8</span><span class=cF0> **data_inout, </span><span class=cF9>I64</span><span class=cF0> *length_inout, CDNSDomainName *name_out)
<a name="l211"></a>{ </span><span class=cF2>// these methods look not-so-good, ngl.</span><span class=cF0>
<a name="l212"></a> </span><span class=cF1>U8</span><span class=cF0> *data = *data_inout;
<a name="l213"></a> </span><span class=cF1>U8</span><span class=cF0> *name_buf;
<a name="l214"></a> </span><span class=cF9>I64</span><span class=cF0> length = *length_inout;
<a name="l215"></a> </span><span class=cF9>I64</span><span class=cF0> label_len;
<a name="l216"></a> </span><span class=cF1>Bool</span><span class=cF0> jump_taken = </span><span class=cF3>FALSE</span><span class=cF0>;
<a name="l217"></a>
<a name="l218"></a> </span><span class=cF1>if</span><span class=cF0> (length &lt; </span><span class=cFE>1</span><span class=cF0>)
<a name="l219"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l220"></a> NetErr(</span><span class=cF6>&quot;DNS PARSE DOMAIN NAME: Length less than one.&quot;</span><span class=cF0>);
<a name="l221"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l222"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l223"></a>
<a name="l224"></a> name_out-&gt;labels = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cFE>16</span><span class=cF0> * </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF1>U8</span><span class=cF0> *</span><span class=cF7>)</span><span class=cF0>);
<a name="l225"></a> name_out-&gt;num_labels = </span><span class=cFE>0</span><span class=cF0>;
<a name="l226"></a>
<a name="l227"></a> name_buf = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cFE>256</span><span class=cF0>); </span><span class=cF2>// ?..</span><span class=cF0>
<a name="l228"></a> name_out-&gt;labels[</span><span class=cFE>0</span><span class=cF0>] = name_buf;
<a name="l229"></a>
<a name="l230"></a> </span><span class=cF1>while</span><span class=cF0> (length)
<a name="l231"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l232"></a> label_len = *data++;
<a name="l233"></a> length--;
<a name="l234"></a>
<a name="l235"></a> </span><span class=cF1>if</span><span class=cF0> (label_len == </span><span class=cFE>0</span><span class=cF0>)
<a name="l236"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l237"></a> </span><span class=cF1>else</span><span class=cF0> </span><span class=cF1>if</span><span class=cF0> (label_len &gt;= </span><span class=cFE>192</span><span class=cF0>)
<a name="l238"></a> {
<a name="l239"></a> label_len &amp;= </span><span class=cFE>0x3F</span><span class=cF0>; </span><span class=cF2>// ...</span><span class=cF0>
<a name="l240"></a>
<a name="l241"></a> </span><span class=cF1>if</span><span class=cF0> (!jump_taken)
<a name="l242"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l243"></a> *data_inout = data + </span><span class=cFE>1</span><span class=cF0>;
<a name="l244"></a> *length_inout = length - </span><span class=cFE>1</span><span class=cF0>;
<a name="l245"></a> jump_taken = </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l246"></a> NetLog(</span><span class=cF6>&quot;DNS PARSE DOMAIN NAME: Jump taken&quot;</span><span class=cF0>);
<a name="l247"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l248"></a>
<a name="l249"></a> data = packet_data + (label_len &lt;&lt; </span><span class=cFE>8</span><span class=cF0> | *data);
<a name="l250"></a> length = packet_data + packet_length - data;
<a name="l251"></a> }
<a name="l252"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l253"></a> {
<a name="l254"></a> </span><span class=cF1>if</span><span class=cF0> (length &lt; label_len)
<a name="l255"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>; </span><span class=cF2>// ?</span><span class=cF0>
<a name="l256"></a>
<a name="l257"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(name_buf, data, label_len);
<a name="l258"></a> data += label_len;
<a name="l259"></a> length -= label_len;
<a name="l260"></a>
<a name="l261"></a> name_buf[label_len] = </span><span class=cFE>0</span><span class=cF0>;
<a name="l262"></a> name_out-&gt;labels[name_out-&gt;num_labels++] = name_buf;
<a name="l263"></a>
<a name="l264"></a> name_buf += label_len + </span><span class=cFE>1</span><span class=cF0>;
<a name="l265"></a> }
<a name="l266"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l267"></a>
<a name="l268"></a> </span><span class=cF1>if</span><span class=cF0> (!jump_taken)
<a name="l269"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l270"></a> *data_inout = data;
<a name="l271"></a> *length_inout = length;
<a name="l272"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l273"></a>
<a name="l274"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
<a name="l275"></a>}
<a name="l276"></a>
<a name="l277"></a>
<a name="l278"></a></span><span class=cF9>I64</span><span class=cF0> DNSQuestionParse(</span><span class=cF1>U8</span><span class=cF0> *packet_data, </span><span class=cF9>I64</span><span class=cF0> packet_length, </span><span class=cF1>U8</span><span class=cF0> **data_inout, </span><span class=cF9>I64</span><span class=cF0> *length_inout, CDNSQuestion *q_out)
<a name="l279"></a>{
<a name="l280"></a> </span><span class=cF1>U8</span><span class=cF0> *data;
<a name="l281"></a> </span><span class=cF9>I64</span><span class=cF0> length;
<a name="l282"></a> </span><span class=cF9>I64</span><span class=cF0> error = DNSDomainNameParse(packet_data, packet_length, data_inout, length_inout, &amp;q_out-&gt;q_name);
<a name="l283"></a>
<a name="l284"></a> </span><span class=cF1>if</span><span class=cF0> (error &lt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l285"></a> </span><span class=cF1>return</span><span class=cF0> error;
<a name="l286"></a>
<a name="l287"></a> data = *data_inout;
<a name="l288"></a> length = *length_inout;
<a name="l289"></a>
<a name="l290"></a> </span><span class=cF1>if</span><span class=cF0> (length &lt; </span><span class=cFE>4</span><span class=cF0>)
<a name="l291"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l292"></a>
<a name="l293"></a> q_out-&gt;next = </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l294"></a> q_out-&gt;q_type = data[</span><span class=cFE>1</span><span class=cF0>] &lt;&lt; </span><span class=cFE>8</span><span class=cF0> | data[</span><span class=cFE>0</span><span class=cF0>];
<a name="l295"></a> q_out-&gt;q_class = data[</span><span class=cFE>3</span><span class=cF0>] &lt;&lt; </span><span class=cFE>8</span><span class=cF0> | data[</span><span class=cFE>2</span><span class=cF0>];
<a name="l296"></a>
<a name="l297"></a> *data_inout = data + </span><span class=cFE>4</span><span class=cF0>;
<a name="l298"></a> *length_inout = length - </span><span class=cFE>4</span><span class=cF0>;
<a name="l299"></a>
<a name="l300"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
<a name="l301"></a>}
<a name="l302"></a>
<a name="l303"></a></span><span class=cF9>I64</span><span class=cF0> DNSRRParse(</span><span class=cF1>U8</span><span class=cF0> *packet_data, </span><span class=cF9>I64</span><span class=cF0> packet_length, </span><span class=cF1>U8</span><span class=cF0> **data_inout, </span><span class=cF9>I64</span><span class=cF0> *length_inout, CDNSRR *rr_out)
<a name="l304"></a>{
<a name="l305"></a> </span><span class=cF1>U8</span><span class=cF0> *data;
<a name="l306"></a> </span><span class=cF9>I64</span><span class=cF0> length;
<a name="l307"></a> </span><span class=cF9>I64</span><span class=cF0> record_length;
<a name="l308"></a> </span><span class=cF9>I64</span><span class=cF0> error = DNSDomainNameParse(packet_data, packet_length, data_inout, length_inout, &amp;rr_out-&gt;name);
<a name="l309"></a>
<a name="l310"></a> </span><span class=cF1>if</span><span class=cF0> (error &lt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l311"></a> </span><span class=cF1>return</span><span class=cF0> error;
<a name="l312"></a>
<a name="l313"></a> data = *data_inout;
<a name="l314"></a> length = *length_inout;
<a name="l315"></a>
<a name="l316"></a> </span><span class=cF1>if</span><span class=cF0> (length &lt; </span><span class=cFE>10</span><span class=cF0>)
<a name="l317"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l318"></a>
<a name="l319"></a> rr_out-&gt;next = </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l320"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(&amp;rr_out-&gt;type, data, </span><span class=cFE>10</span><span class=cF0>); </span><span class=cF2>// ???</span><span class=cF0>
<a name="l321"></a>
<a name="l322"></a> record_length = </span><span class=cFE>10</span><span class=cF0> + </span><span class=cF5>EndianU16</span><span class=cF0>(rr_out-&gt;rd_length);
<a name="l323"></a>
<a name="l324"></a> </span><span class=cF1>if</span><span class=cF0> (length &lt; record_length)
<a name="l325"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l326"></a>
<a name="l327"></a> rr_out-&gt;r_data = data + </span><span class=cFE>10</span><span class=cF0>; </span><span class=cF2>// ??</span><span class=cF0>
<a name="l328"></a>
<a name="l329"></a> *data_inout = data + record_length;
<a name="l330"></a> *length_inout = length - record_length;
<a name="l331"></a>
<a name="l332"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
<a name="l333"></a>}
<a name="l334"></a>
<a name="l335"></a></span><span class=cF9>I64</span><span class=cF0> DNSResponseParse(</span><span class=cF9>U16</span><span class=cF0> id, </span><span class=cF1>U8</span><span class=cF0> *data, </span><span class=cF9>I64</span><span class=cF0> length, CDNSHeader **header_out, CDNSQuestion **questions_out, CDNSRR **answers_out)
<a name="l336"></a>{
<a name="l337"></a> CDNSHeader *header;
<a name="l338"></a> CDNSQuestion *question;
<a name="l339"></a> CDNSRR *answer;
<a name="l340"></a> </span><span class=cF9>I64</span><span class=cF0> i;
<a name="l341"></a> </span><span class=cF1>U8</span><span class=cF0> *packet_data = data;
<a name="l342"></a> </span><span class=cF9>I64</span><span class=cF0> packet_length = length;
<a name="l343"></a>
<a name="l344"></a> </span><span class=cF1>if</span><span class=cF0> (length &lt; </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CDNSHeader</span><span class=cF7>)</span><span class=cF0>)
<a name="l345"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l346"></a> NetErr(</span><span class=cF6>&quot;DNS PARSE RESPONSE: Length too short.&quot;</span><span class=cF0>);
<a name="l347"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l348"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l349"></a>
<a name="l350"></a> header = data;
<a name="l351"></a> data += </span><span class=cF1>sizeof</span><span class=cF0>(CDNSHeader);
<a name="l352"></a>
<a name="l353"></a> </span><span class=cF1>if</span><span class=cF0> (id != </span><span class=cFE>0</span><span class=cF0> &amp;&amp; </span><span class=cF5>EndianU16</span><span class=cF7>(</span><span class=cF0>header-&gt;id</span><span class=cF7>)</span><span class=cF0> != id)
<a name="l354"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l355"></a> NetErr(</span><span class=cF6>&quot;DNS PARSE RESPONSE: Header ID mismatch.&quot;</span><span class=cF0>);
<a name="l356"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l357"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l358"></a>
<a name="l359"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i &lt; </span><span class=cF5>EndianU16</span><span class=cF7>(</span><span class=cF0>header-&gt;q_count</span><span class=cF7>)</span><span class=cF0>; i++)
<a name="l360"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l361"></a> question = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CDNSQuestion</span><span class=cF7>)</span><span class=cF0>);
<a name="l362"></a> </span><span class=cF1>if</span><span class=cF0> (DNSQuestionParse</span><span class=cF7>(</span><span class=cF0>packet_data, packet_length, &amp;data, &amp;length, question</span><span class=cF7>)</span><span class=cF0> &lt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l363"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l364"></a>
<a name="l365"></a> question-&gt;next = *questions_out;
<a name="l366"></a> *questions_out = question;
<a name="l367"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l368"></a>
<a name="l369"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i &lt; </span><span class=cF5>EndianU16</span><span class=cF7>(</span><span class=cF0>header-&gt;a_count</span><span class=cF7>)</span><span class=cF0>; i++)
<a name="l370"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l371"></a> answer = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CDNSRR</span><span class=cF7>)</span><span class=cF0>);
<a name="l372"></a> </span><span class=cF1>if</span><span class=cF0> (DNSRRParse</span><span class=cF7>(</span><span class=cF0>packet_data, packet_length, &amp;data, &amp;length, answer</span><span class=cF7>)</span><span class=cF0> &lt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l373"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l374"></a>
<a name="l375"></a> answer-&gt;next = *answers_out;
<a name="l376"></a> *answers_out = answer;
<a name="l377"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l378"></a>
<a name="l379"></a> *header_out = header;
<a name="l380"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
<a name="l381"></a>
<a name="l382"></a>}
<a name="l383"></a>
<a name="l384"></a></span><span class=cF1>U0</span><span class=cF0> DNSQuestionBuild(CDNSQuestion *q, </span><span class=cF1>U8</span><span class=cF0> *name)
<a name="l385"></a>{
<a name="l386"></a> </span><span class=cF1>U8</span><span class=cF0> *copy = </span><span class=cF5>StrNew</span><span class=cF0>(name);
<a name="l387"></a> </span><span class=cF1>U8</span><span class=cF0> *dot;
<a name="l388"></a>
<a name="l389"></a> q-&gt;next = </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l390"></a> q-&gt;q_name.labels = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cFE>16</span><span class=cF0> * </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF1>U8</span><span class=cF0> *</span><span class=cF7>)</span><span class=cF0>);
<a name="l391"></a> q-&gt;q_name.labels[</span><span class=cFE>0</span><span class=cF0>] = </span><span class=cFE>0</span><span class=cF0>;
<a name="l392"></a> q-&gt;q_name.num_labels = </span><span class=cFE>0</span><span class=cF0>;
<a name="l393"></a> q-&gt;q_type = DNS_TYPE_A;
<a name="l394"></a> q-&gt;q_class = DNS_CLASS_IN;
<a name="l395"></a>
<a name="l396"></a> </span><span class=cF1>while</span><span class=cF0> (*copy)
<a name="l397"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l398"></a> q-&gt;q_name.labels[q-&gt;q_name.num_labels++] = copy;
<a name="l399"></a> dot = </span><span class=cF5>StrFirstOcc</span><span class=cF0>(copy, </span><span class=cF6>&quot;.&quot;</span><span class=cF0>);
<a name="l400"></a>
<a name="l401"></a> </span><span class=cF1>if</span><span class=cF0> (dot)
<a name="l402"></a> {
<a name="l403"></a> *dot = </span><span class=cFE>0</span><span class=cF0>;
<a name="l404"></a> copy = dot + </span><span class=cFE>1</span><span class=cF0>;
<a name="l405"></a> }
<a name="l406"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l407"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l408"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l409"></a>}
<a name="l410"></a>
<a name="l411"></a></span><span class=cF2>// these Free methods bother me a bit...</span><span class=cF0>
<a name="l412"></a></span><span class=cF1>U0</span><span class=cF0> DNSQuestionFree(CDNSQuestion *q)
<a name="l413"></a>{
<a name="l414"></a> </span><span class=cF5>Free</span><span class=cF0>(q-&gt;q_name.labels[</span><span class=cFE>0</span><span class=cF0>]);
<a name="l415"></a>}
<a name="l416"></a>
<a name="l417"></a></span><span class=cF1>U0</span><span class=cF0> DNSRRFree(CDNSRR *rr)
<a name="l418"></a>{
<a name="l419"></a> </span><span class=cF5>Free</span><span class=cF0>(rr-&gt;name.labels[</span><span class=cFE>0</span><span class=cF0>]);
<a name="l420"></a>}
<a name="l421"></a>
<a name="l422"></a></span><span class=cF1>U0</span><span class=cF0> DNSQuestionChainFree(CDNSQuestion *questions)
<a name="l423"></a>{
<a name="l424"></a> CDNSQuestion *next;
<a name="l425"></a>
<a name="l426"></a> </span><span class=cF1>while</span><span class=cF0> (questions)
<a name="l427"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l428"></a> next = questions-&gt;next;
<a name="l429"></a> DNSQuestionFree(questions);
<a name="l430"></a> </span><span class=cF5>Free</span><span class=cF0>(questions);
<a name="l431"></a> questions = next;
<a name="l432"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l433"></a>}
<a name="l434"></a>
<a name="l435"></a></span><span class=cF1>U0</span><span class=cF0> DNSRRChainFree(CDNSRR *rrs)
<a name="l436"></a>{ </span><span class=cF2>// Shrine sets rrs-&gt;next to a CDNSQuestion when it would be a CDNSRR ... assuming it's wrong and fixing it here..</span><span class=cF0>
<a name="l437"></a> CDNSRR *next;
<a name="l438"></a>
<a name="l439"></a> </span><span class=cF1>while</span><span class=cF0> (rrs)
<a name="l440"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l441"></a> next = rrs-&gt;next;
<a name="l442"></a> DNSRRFree(rrs);
<a name="l443"></a> </span><span class=cF5>Free</span><span class=cF0>(rrs);
<a name="l444"></a> rrs = next;
<a name="l445"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l446"></a>}
<a name="l447"></a>
<a name="l448"></a>
<a name="l449"></a></span><span class=cF9>I64</span><span class=cF0> DNSQueryRun(CUDPSocket *udp_socket, </span><span class=cF1>U8</span><span class=cF0> *name, </span><span class=cF9>U16</span><span class=cF0> port, CAddressInfo **result_out)
<a name="l450"></a>{ </span><span class=cF2>// IPV4-UDP-based, TODO: take good look at this method to ensure no floating pointers after.</span><span class=cF0>
<a name="l451"></a> </span><span class=cF2>// note: UDP Socket created in this method is not closed in this method, gets closed e.g. in DNSAddressInfoGet</span><span class=cF0>
<a name="l452"></a> </span><span class=cF9>I64</span><span class=cF0> retries = </span><span class=cFE>0</span><span class=cF0>;
<a name="l453"></a> </span><span class=cF9>I64</span><span class=cF0> timeout = DNS_TIMEOUT;
<a name="l454"></a> </span><span class=cF9>U16</span><span class=cF0> local_port = </span><span class=cF5>MaxI64</span><span class=cF0>(</span><span class=cFE>1024</span><span class=cF0>, </span><span class=cF5>RandU16</span><span class=cF0>); </span><span class=cF2>// Pick a random port above 1023. (within standard application port range)</span><span class=cF0>
<a name="l455"></a> </span><span class=cF9>U16</span><span class=cF0> id = </span><span class=cF5>RandU16</span><span class=cF0>;
<a name="l456"></a> </span><span class=cF9>I64</span><span class=cF0> error = </span><span class=cFE>0</span><span class=cF0>;
<a name="l457"></a> </span><span class=cF1>U8</span><span class=cF0> buffer[</span><span class=cFE>2048</span><span class=cF0>];
<a name="l458"></a> </span><span class=cF9>I64</span><span class=cF0> count;
<a name="l459"></a> </span><span class=cF1>Bool</span><span class=cF0> have; </span><span class=cF2>// ??</span><span class=cF0>
<a name="l460"></a>
<a name="l461"></a> CDNSQuestion q;
<a name="l462"></a> CDNSHeader *header;
<a name="l463"></a> CDNSQuestion *questions;
<a name="l464"></a> CDNSRR *answers;
<a name="l465"></a> CDNSRR *a;
<a name="l466"></a>
<a name="l467"></a> CSocketAddressIPV4 ipv4_addr;
<a name="l468"></a> CSocketAddressIPV4 ipv4_addr_in; </span><span class=cF2>// ?</span><span class=cF0>
<a name="l469"></a> CSocketAddressIPV4 *ipv4_addr_temp;
<a name="l470"></a> CAddressInfo *res;
<a name="l471"></a>
<a name="l472"></a> </span><span class=cF2>//setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO_MS, &amp;timeout, sizeof(timeout))</span><span class=cF0>
<a name="l473"></a> udp_socket-&gt;receive_timeout_ms = timeout;
<a name="l474"></a>
<a name="l475"></a> ipv4_addr.family = AF_INET;
<a name="l476"></a> ipv4_addr.port = </span><span class=cF5>EndianU16</span><span class=cF0>(local_port);
<a name="l477"></a> ipv4_addr.address.address = INADDR_ANY;
<a name="l478"></a>
<a name="l479"></a> </span><span class=cF2>// UDPSocketBind will be attempted on the udp_socket param, method expects a UDPSocket() result to be made already</span><span class=cF0>
<a name="l480"></a> </span><span class=cF1>if</span><span class=cF0> (UDPSocketBind</span><span class=cF7>(</span><span class=cF0>udp_socket, &amp;ipv4_addr</span><span class=cF7>)</span><span class=cF0>) </span><span class=cF2>// expected return value is 0</span><span class=cF0>
<a name="l481"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l482"></a> NetErr(</span><span class=cF6>&quot;DNS RUN QUERY: Failed to bind UDP socket.&quot;</span><span class=cF0>);
<a name="l483"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l484"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l485"></a>
<a name="l486"></a> DNSQuestionBuild(&amp;q, name);
<a name="l487"></a>
<a name="l488"></a> </span><span class=cF1>while</span><span class=cF0> (</span><span class=cF3>TRUE</span><span class=cF0>) </span><span class=cF2>// Shrine uses while (1) infinite loop, need to be careful not to lock</span><span class=cF0>
<a name="l489"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l490"></a> error = DNSQuestionSend(id, local_port, &amp;q);
<a name="l491"></a> </span><span class=cF1>if</span><span class=cF0> (error &lt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l492"></a> {
<a name="l493"></a> NetErr(</span><span class=cF6>&quot;DNS RUN QUERY: Failed to Send Question.&quot;</span><span class=cF0>);
<a name="l494"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l495"></a> }
<a name="l496"></a>
<a name="l497"></a> count = UDPSocketReceiveFrom(udp_socket, buffer, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>buffer</span><span class=cF7>)</span><span class=cF0>, &amp;ipv4_addr_in);
<a name="l498"></a>
<a name="l499"></a> </span><span class=cF1>if</span><span class=cF0> (count &gt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l500"></a> {
<a name="l501"></a> NetLog(</span><span class=cF6>&quot;DNS RUN QUERY: Trying Parse Response.&quot;</span><span class=cF0>);
<a name="l502"></a>
<a name="l503"></a> header = </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l504"></a> questions = </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l505"></a> answers = </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l506"></a>
<a name="l507"></a> error = DNSResponseParse(id, buffer, count, &amp;header, &amp;questions, &amp;answers);
<a name="l508"></a>
<a name="l509"></a> </span><span class=cF1>if</span><span class=cF0> (error == </span><span class=cFE>0</span><span class=cF0>) </span><span class=cF2>// Shrine has (error &gt;= 0), but DNSResponseParse can only return 0 or 1 ..</span><span class=cF0>
<a name="l510"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l511"></a> have = </span><span class=cF3>FALSE</span><span class=cF0>;
<a name="l512"></a>
<a name="l513"></a> a = answers;
<a name="l514"></a> </span><span class=cF1>while</span><span class=cF0> (a)
<a name="l515"></a> {
<a name="l516"></a> </span><span class=cF2>// Shrine has TODO: if multiple acceptable answers, pick one at random, not just first one.</span><span class=cF0>
<a name="l517"></a> </span><span class=cF2>// perhaps we could use r_count in header for that ?</span><span class=cF0>
<a name="l518"></a>
<a name="l519"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>EndianU16</span><span class=cF7>(</span><span class=cF0>a-&gt;type</span><span class=cF7>)</span><span class=cF0> == DNS_TYPE_A &amp;&amp;
<a name="l520"></a> </span><span class=cF5>EndianU16</span><span class=cF7>(</span><span class=cF0>a-&gt;rr_class</span><span class=cF7>)</span><span class=cF0> == DNS_CLASS_IN &amp;&amp;
<a name="l521"></a> </span><span class=cF5>EndianU16</span><span class=cF7>(</span><span class=cF0>a-&gt;rd_length</span><span class=cF7>)</span><span class=cF0> == </span><span class=cFE>4</span><span class=cF0>)
<a name="l522"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l523"></a> res = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CAddressInfo</span><span class=cF7>)</span><span class=cF0>);
<a name="l524"></a>
<a name="l525"></a> res-&gt;flags = </span><span class=cFE>0</span><span class=cF0>;
<a name="l526"></a> res-&gt;family = AF_INET;
<a name="l527"></a> res-&gt;socket_type = </span><span class=cFE>0</span><span class=cF0>; </span><span class=cF2>// ??</span><span class=cF0>
<a name="l528"></a> res-&gt;protocol = </span><span class=cFE>0</span><span class=cF0>; </span><span class=cF2>// ??</span><span class=cF0>
<a name="l529"></a> res-&gt;address_length = </span><span class=cF1>sizeof</span><span class=cF0>(CSocketAddressIPV4);
<a name="l530"></a> res-&gt;address = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CSocketAddressIPV4</span><span class=cF7>)</span><span class=cF0>);
<a name="l531"></a> res-&gt;canonical_name = </span><span class=cFE>0</span><span class=cF0>;
<a name="l532"></a> res-&gt;next = </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l533"></a>
<a name="l534"></a> ipv4_addr_temp = res-&gt;address;
<a name="l535"></a>
<a name="l536"></a> ipv4_addr_temp-&gt;family = AF_INET;
<a name="l537"></a> ipv4_addr_temp-&gt;port = port;
<a name="l538"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(&amp;ipv4_addr_temp-&gt;address.address, answers-&gt;r_data, </span><span class=cFE>4</span><span class=cF0>);
<a name="l539"></a>
<a name="l540"></a> DNSCachePut(name, res);
<a name="l541"></a> *result_out = res;
<a name="l542"></a> have = </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l543"></a>
<a name="l544"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l545"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l546"></a>
<a name="l547"></a> a = a-&gt;next;
<a name="l548"></a> }
<a name="l549"></a>
<a name="l550"></a> DNSQuestionChainFree(questions);
<a name="l551"></a> DNSRRChainFree(answers);
<a name="l552"></a>
<a name="l553"></a> </span><span class=cF1>if</span><span class=cF0> (have)
<a name="l554"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l555"></a>
<a name="l556"></a> </span><span class=cF2>// Shrine comment: 'at this point, we could try iterative resolution,</span><span class=cF0>
<a name="l557"></a> </span><span class=cF2>// but all end-user DNS servers would have tried that already'</span><span class=cF0>
<a name="l558"></a>
<a name="l559"></a> NetErr(</span><span class=cF6>&quot;DNS RUN QUERY: Failed to find suitable answer in reply.&quot;</span><span class=cF0>);
<a name="l560"></a> error = -</span><span class=cFE>1</span><span class=cF0>;
<a name="l561"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l562"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l563"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l564"></a> NetErr(</span><span class=cF6>&quot;DNS RUN QUERY: Failed a DNS Parse Response.&quot;</span><span class=cF0>);
<a name="l565"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l566"></a> }
<a name="l567"></a>
<a name="l568"></a> </span><span class=cF1>if</span><span class=cF0> (++retries == DNS_MAX_RETRIES)
<a name="l569"></a> {
<a name="l570"></a> NetErr(</span><span class=cF6>&quot;DNS RUN QUERY: Failed, max retries reached.&quot;</span><span class=cF0>);
<a name="l571"></a> error = -</span><span class=cFE>1</span><span class=cF0>;
<a name="l572"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l573"></a> }
<a name="l574"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l575"></a>
<a name="l576"></a> DNSQuestionFree(&amp;q);
<a name="l577"></a> </span><span class=cF1>return</span><span class=cF0> error;
<a name="l578"></a>}
<a name="l579"></a>
<a name="l580"></a></span><span class=cF2>// Shrine has port arg as U8 *service with a no_warn and says it should be parsed as port, allowing that here</span><span class=cF0>
<a name="l581"></a></span><span class=cF2>// Also has CAddressInfo *hints with a no_warn, omitting that for now</span><span class=cF0>
<a name="l582"></a></span><span class=cF9>I64</span><span class=cF0> DNSAddressInfoGet(</span><span class=cF1>U8</span><span class=cF0> *node_name, </span><span class=cF9>U16</span><span class=cF0> port, CAddressInfo **result)
<a name="l583"></a>{
<a name="l584"></a> </span><span class=cF9>I64</span><span class=cF0> error;
<a name="l585"></a> CUDPSocket *udp_socket;
<a name="l586"></a> CDNSHash *cached_entry = DNSCacheFind(node_name);
<a name="l587"></a>
<a name="l588"></a> </span><span class=cF1>if</span><span class=cF0> (cached_entry)
<a name="l589"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l590"></a> *result = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CAddressInfo</span><span class=cF7>)</span><span class=cF0>);
<a name="l591"></a> AddressInfoCopy(*result, &amp;cached_entry-&gt;info);
<a name="l592"></a> </span><span class=cF2>//(*res)-&gt;flags |= AI_CACHED; // TODO: add AI_CACHED define (maybe a better name?) not used anywhere i don't think..</span><span class=cF0>
<a name="l593"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
<a name="l594"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l595"></a>
<a name="l596"></a> udp_socket = UDPSocket(AF_INET);
<a name="l597"></a> error = </span><span class=cFE>0</span><span class=cF0>;
<a name="l598"></a>
<a name="l599"></a> </span><span class=cF1>if</span><span class=cF0> (udp_socket)
<a name="l600"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l601"></a> error = DNSQueryRun(udp_socket, node_name, port, result);
<a name="l602"></a>
<a name="l603"></a> UDPSocketClose(udp_socket);
<a name="l604"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l605"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l606"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l607"></a> NetErr(</span><span class=cF6>&quot;DNS GET ADDRESS INFO: Failed to make UDP Socket.&quot;</span><span class=cF0>);
<a name="l608"></a> error = -</span><span class=cFE>1</span><span class=cF0>;
<a name="l609"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l610"></a>
<a name="l611"></a> </span><span class=cF1>return</span><span class=cF0> error;
<a name="l612"></a>}
<a name="l613"></a>
<a name="l614"></a></span><span class=cF1>U0</span><span class=cF0> DNSResolverIPV4Set(</span><span class=cF9>U32</span><span class=cF0> ip)
<a name="l615"></a>{
<a name="l616"></a> CIPV4Address *address = &amp;dns_globals.dns_ip;
<a name="l617"></a>
<a name="l618"></a> dns_globals.addr_family = AF_INET;
<a name="l619"></a> address-&gt;address = ip;
<a name="l620"></a>}
<a name="l621"></a>
<a name="l622"></a></span><span class=cF1>U0</span><span class=cF0> Host(</span><span class=cF1>U8</span><span class=cF0> *hostname)
<a name="l623"></a>{ </span><span class=cF2>// getaddrinfo() for whole system in Shrine ends up as pointer to DNSAddressInfoGet.. should we do something similar?</span><span class=cF0>
<a name="l624"></a> CAddressInfo *current;
<a name="l625"></a> CAddressInfo *result = </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l626"></a> </span><span class=cF9>I64</span><span class=cF0> error = DNSAddressInfoGet(hostname, </span><span class=cF3>NULL</span><span class=cF0>, &amp;result);
<a name="l627"></a> </span><span class=cF9>I64</span><span class=cF0> i = </span><span class=cFE>0</span><span class=cF0>;
<a name="l628"></a> CSocketAddressIPV4 *ipv4_address;
<a name="l629"></a>
<a name="l630"></a> </span><span class=cF1>if</span><span class=cF0> (error &lt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l631"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l632"></a> NetErr(</span><span class=cF6>&quot;HOST(): Failed at DNS Get Address Info.&quot;</span><span class=cF0>);
<a name="l633"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l634"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l635"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l636"></a> </span><span class=cF6>&quot;Results:\n\n&quot;</span><span class=cF0>;
<a name="l637"></a> current = result;
<a name="l638"></a> </span><span class=cF1>while</span><span class=cF0> (current)
<a name="l639"></a> {
<a name="l640"></a> </span><span class=cF6>&quot;Result %d:\n&quot;</span><span class=cF0>, ++i;
<a name="l641"></a>
<a name="l642"></a> </span><span class=cF6>&quot;</span><span class=cF0> </span><span class=cF6>flags:</span><span class=cF0> </span><span class=cF6>0x%04X \n&quot;</span><span class=cF0>, current-&gt;flags;
<a name="l643"></a> </span><span class=cF6>&quot;</span><span class=cF0> </span><span class=cF6>family:</span><span class=cF0> </span><span class=cF6>%d \n&quot;</span><span class=cF0>, current-&gt;family;
<a name="l644"></a> </span><span class=cF6>&quot;</span><span class=cF0> </span><span class=cF6>socket type:</span><span class=cF0> </span><span class=cF6>%d \n&quot;</span><span class=cF0>, current-&gt;socket_type;
<a name="l645"></a> </span><span class=cF6>&quot;</span><span class=cF0> </span><span class=cF6>protocol:</span><span class=cF0> </span><span class=cF6>%d \n&quot;</span><span class=cF0>, current-&gt;protocol;
<a name="l646"></a> </span><span class=cF6>&quot;</span><span class=cF0> </span><span class=cF6>address length:</span><span class=cF0> </span><span class=cF6>%d \n&quot;</span><span class=cF0>, current-&gt;address_length;
<a name="l647"></a> </span><span class=cF1>switch</span><span class=cF0> (current-&gt;family)
<a name="l648"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l649"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET:
<a name="l650"></a> ipv4_address = current-&gt;address;
<a name="l651"></a> </span><span class=cF6>&quot;</span><span class=cF0> </span><span class=cF6>address:</span><span class=cF0> </span><span class=cF6>%s \n&quot;</span><span class=cF0>, NetworkToPresentation(AF_INET, &amp;ipv4_address-&gt;address);
<a name="l652"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l653"></a>
<a name="l654"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET6:
<a name="l655"></a> </span><span class=cF6>&quot;</span><span class=cF0> </span><span class=cF6>address:</span><span class=cF0> </span><span class=cF6>IPV6 \n&quot;</span><span class=cF0>; </span><span class=cF2>// FIXME</span><span class=cF0>
<a name="l656"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l657"></a>
<a name="l658"></a> </span><span class=cF1>case</span><span class=cF0> AF_UNSPEC:
<a name="l659"></a> </span><span class=cF6>&quot;</span><span class=cF0> </span><span class=cF6>address:</span><span class=cF0> </span><span class=cF6>AF_UNSPEC \n&quot;</span><span class=cF0>;
<a name="l660"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l661"></a>
<a name="l662"></a> </span><span class=cF1>default</span><span class=cF0>:
<a name="l663"></a> </span><span class=cF6>&quot;</span><span class=cF0> </span><span class=cF6>address:</span><span class=cF0> </span><span class=cF6>INVALID \n&quot;</span><span class=cF0>;
<a name="l664"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l665"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l666"></a>
<a name="l667"></a> current = current-&gt;next;
<a name="l668"></a> }
<a name="l669"></a> </span><span class=cF6>&quot;\n&quot;</span><span class=cF0>;
<a name="l670"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l671"></a>
<a name="l672"></a> AddressInfoFree(result);
<a name="l673"></a>}
<a name="l674"></a>
<a name="l675"></a></span><span class=cF1>U0</span><span class=cF0> DNSRep()
<a name="l676"></a>{
<a name="l677"></a> </span><span class=cF9>I64</span><span class=cF0> i;
<a name="l678"></a> CDNSHash *temp_hash;
<a name="l679"></a> CSocketAddressIPV4 *ipv4_address;
<a name="l680"></a>
<a name="l681"></a> </span><span class=cF6>&quot;$LTBLUE$DNS Report:$FG$\n\n&quot;</span><span class=cF0>;
<a name="l682"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i &lt;= dns_cache-&gt;mask; i++)
<a name="l683"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l684"></a> temp_hash = dns_cache-&gt;body[i];
<a name="l685"></a>
<a name="l686"></a> </span><span class=cF1>while</span><span class=cF0> (temp_hash)
<a name="l687"></a> {
<a name="l688"></a> </span><span class=cF6>&quot;DNS Hash @ 0x%X:\n&quot;</span><span class=cF0>, temp_hash;
<a name="l689"></a> </span><span class=cF6>&quot;</span><span class=cF0> </span><span class=cF6>Hostname:</span><span class=cF0> </span><span class=cF6>%s\n&quot;</span><span class=cF0>, temp_hash-&gt;str;
<a name="l690"></a>
<a name="l691"></a> </span><span class=cF1>switch</span><span class=cF0> (temp_hash-&gt;info.family)
<a name="l692"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l693"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET:
<a name="l694"></a> ipv4_address = temp_hash-&gt;info.address;
<a name="l695"></a>
<a name="l696"></a> </span><span class=cF6>&quot;</span><span class=cF0> </span><span class=cF6>IP Address:</span><span class=cF0> </span><span class=cF6>%s\n&quot;</span><span class=cF0>,
<a name="l697"></a> NetworkToPresentation(temp_hash-&gt;info.family,
<a name="l698"></a> &amp;ipv4_address-&gt;address);
<a name="l699"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l700"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET6:
<a name="l701"></a> </span><span class=cF6>&quot;</span><span class=cF0> </span><span class=cF6>IP Address:</span><span class=cF0> </span><span class=cF6>IPV6\n&quot;</span><span class=cF0>; </span><span class=cF2>// FIXME</span><span class=cF0>
<a name="l702"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l703"></a>
<a name="l704"></a> </span><span class=cF1>case</span><span class=cF0> AF_UNSPEC:
<a name="l705"></a> </span><span class=cF6>&quot;</span><span class=cF0> </span><span class=cF6>IP Address:</span><span class=cF0> </span><span class=cF6>AF_UNSPEC&quot;</span><span class=cF0>;
<a name="l706"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l707"></a>
<a name="l708"></a> </span><span class=cF1>default</span><span class=cF0>:
<a name="l709"></a> </span><span class=cF6>&quot;</span><span class=cF0> </span><span class=cF6>IP Address:</span><span class=cF0> </span><span class=cF6>INVALID&quot;</span><span class=cF0>;
<a name="l710"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l711"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l712"></a>
<a name="l713"></a> </span><span class=cF6>&quot;\n&quot;</span><span class=cF0>;
<a name="l714"></a> temp_hash = temp_hash-&gt;next;
<a name="l715"></a> }
<a name="l716"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l717"></a>}
<a name="l718"></a>
<a name="l719"></a>DNSCacheInit;</span></pre></body>
</html>