<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel>
  <title>Paterissa</title>
  <link>https://paterissa.net</link>
  <description>Blog feed</description>
  <item>
    <title>my boy…</title>
    <link>https://paterissa.net/post?id=3</link>
    <guid>https://paterissa.net/post?id=3</guid>
    <description><![CDATA[<h1 id="my-boy">my boy&hellip;</h1>
<p>So, firstly, the new pokémon game isn&rsquo;t great. Not a fan. (Guys, really? Not modeling the sides of buildings is one thing. Not using normal and depth maps in a game released later than the 7th console generation is crazy).</p>
<p>But also,</p>
]]></description>
    <pubDate>Thu, 11 Dec 2025 00:57:31 +0000</pubDate>
    <content:encoded><![CDATA[<h1 id="my-boy">my boy&hellip;</h1>
<p>So, firstly, the new pokémon game isn&rsquo;t great. Not a fan. (Guys, really? Not modeling the sides of buildings is one thing. Not using normal and depth maps in a game released later than the 7th console generation is crazy).</p>
<p>But also, the new megas. They made Garchomp worse once. Surely they won&rsquo;t do it agai—</p>
<p><img src="https://i.postimg.cc/vm4LdM10/mega.png" alt="I&rsquo;d have two nickels"></p>
]]></content:encoded>
  </item>
  <item>
    <title>DNS 1: Research and Encoding</title>
    <link>https://paterissa.net/post?id=2</link>
    <guid>https://paterissa.net/post?id=2</guid>
    <description><![CDATA[<h1 id="dns-1-research-and-encoding">DNS 1: Research and Encoding</h1>
<p>On a personal level, I&rsquo;ve been interested in DNS resolution and how it actually works for a while. Whenever it&rsquo;s been described to me, it sounds simple, and yet, consulting with tutorials consistently led to such resu</p>
]]></description>
    <pubDate>Wed, 26 Nov 2025 23:06:02 +0000</pubDate>
    <content:encoded><![CDATA[<h1 id="dns-1-research-and-encoding">DNS 1: Research and Encoding</h1>
<p>On a personal level, I&rsquo;ve been interested in DNS resolution and how it actually works for a while. Whenever it&rsquo;s been described to me, it sounds simple, and yet, consulting with tutorials consistently led to such results as: &ldquo;we&rsquo;ll use a library for parsing DNS packets&rdquo;, &ldquo;let&rsquo;s implement a subset&rdquo;, and such. Of course, there were some truly excellent guides out there, but I decided that if I really wanted to do it, I should do it properly and hit the books (or, more accurately, the Request for Comments). Thus, as I develop it, I&rsquo;m going to go step by step and document what I find.</p>
<p>How complicated could it really be—</p>
<p><img src="https://i.postimg.cc/vmNMn6CM/ohmy.png" alt="oh my"></p>
<h2 id="how-dns-resolution-works">How DNS Resolution Works</h2>
<p><em><a href="https://datatracker.ietf.org/doc/html/rfc1035">RFC 1035</a></em></p>
<p>So, good news for me. The number of updates was misleading, thankfully. I was fully committed either way, but a cursory glance through them told me most didn&rsquo;t matter <em>or</em> were implementation details I didn&rsquo;t care about yet. So let&rsquo;s actually get somewhere first, and then we&rsquo;ll care about those.</p>
<p>Underlyingly, DNS is pretty simple. There are &ldquo;zones&rdquo;, which approximately correlate to subtrees in an internet-wide sort of file hierarchy (practically speaking, the little chunks separated by dots). In order to know what is inside a &ldquo;zone&rdquo;, you have to do a send a query to an authoritative source—the nameserver responsible for that zone<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>. It&rsquo;ll give you a response, and based on what you get, you either are referred to the authoritative for a lower subtree or you have ana answer to your query (if there is one). All resolvers start out with knowledge of at least one authoritative to refer to (the spec seems to assume this is a root nameserver as managed by IANA, but obviously this isn&rsquo;t usually strictly true).</p>
<p>Instead of directly querying from top to bottom down the tree hierarchy, a client can (and pretty much always does) query a <em>recursive</em> nameserver. These follow down the tree, and then cache results for durations specified in the responses to be able to respond to future queries without doing the whole process again.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
<p>Interestingly, though the spec distinguishes between resolvers and recursive nameservers, resolvers running as a daemon on the host system can act similarly to a recursive nameserver, caching included—this is referred to in one place as a &ldquo;DNS stub&rdquo;. For an example, see <a href="https://wiki.archlinux.org/title/Systemd-resolved">systemd-resolved</a>. All things considered, I would like to try to build something along these lines I can run locally, but also something I could deploy to my personal server, so I&rsquo;m opting to build a library and then a resolver application dependent on it.</p>
<p>Regardless, for a normal, nothing-cached-whatsoever request, you&rsquo;d query one of the root nameservers<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>, which would then give you an NS (nameserver) response to send you to the TLD nameserver (e.g., .com, .net), and that would send you to an authoritative, and <em>eventually</em> something will hand you an A or a CNAME or whatever. Or nothing at all. What are those? Well.</p>
<h2 id="huh-theres-a-lot-of-response-types">Huh, There&rsquo;s a Lot of Response Types</h2>
<p>All communication in DNS is done in terms of messages. This is a very simple structure consisting of a header and four optional data fields. The format is helpfully and intuitively defined in terms of octets, helpfully avoiding any semantics about the edgiest of edge cases about what the smallest addressable unit is on some systems that may or may not exist. It then consists of a header, zero or <del>more</del> one questions<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>, zero or more answers, zero or more authorities, and zero or more additionals. Of these, answers, authorities, and additionals all share a format known as a &ldquo;resource record&rdquo; or RR.</p>
<p>The header structure is fairly straightforward:</p>
<table>
<thead>
<tr>
<th style="text-align:center">Section</th>
<th style="text-align:center">Size</th>
<th style="text-align:left">Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">ID</td>
<td style="text-align:center">2 octets</td>
<td style="text-align:left">Identifier to match up responses to queries</td>
</tr>
<tr>
<td style="text-align:center">QR</td>
<td style="text-align:center">1 bit</td>
<td style="text-align:left">Set if message is response, else query</td>
</tr>
<tr>
<td style="text-align:center">OPCODE</td>
<td style="text-align:center">4 bits</td>
<td style="text-align:left">Specifies the kind of query</td>
</tr>
<tr>
<td style="text-align:center">AA</td>
<td style="text-align:center">1 bit</td>
<td style="text-align:left">Set if response is from authoritative</td>
</tr>
<tr>
<td style="text-align:center">TC</td>
<td style="text-align:center">1 bit</td>
<td style="text-align:left">Set if message was truncated (i.e., INCOMPLETE, not compressed)<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup></td>
</tr>
<tr>
<td style="text-align:center">RD</td>
<td style="text-align:center">1 bit</td>
<td style="text-align:left">Optional for implementation, if set in query it requests recursive behavior</td>
</tr>
<tr>
<td style="text-align:center">RA</td>
<td style="text-align:center">1 bit</td>
<td style="text-align:left">Set in response if nameserver supports recursive resolution</td>
</tr>
<tr>
<td style="text-align:center">Z</td>
<td style="text-align:center">3 bits</td>
<td style="text-align:left">Reserved, should be zeroed</td>
</tr>
<tr>
<td style="text-align:center">RCODE</td>
<td style="text-align:center">4 bits</td>
<td style="text-align:left">Response codes</td>
</tr>
<tr>
<td style="text-align:center">QDCOUNT</td>
<td style="text-align:center">2 octets</td>
<td style="text-align:left">Number of entries in question section</td>
</tr>
<tr>
<td style="text-align:center">ANCOUNT</td>
<td style="text-align:center">2 octets</td>
<td style="text-align:left">Number of entries in answer section</td>
</tr>
<tr>
<td style="text-align:center">NSCOUNT</td>
<td style="text-align:center">2 octets</td>
<td style="text-align:left">Number of entries in authority section</td>
</tr>
<tr>
<td style="text-align:center">ARCOUNT</td>
<td style="text-align:center">2 octets</td>
<td style="text-align:left">Number of entries in additional section</td>
</tr>
</tbody>
</table>
<p>And so, for that matter, is a question field, except for two details:</p>
<table>
<thead>
<tr>
<th style="text-align:center">Section</th>
<th style="text-align:center">Size</th>
<th style="text-align:left">Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">QNAME</td>
<td style="text-align:center">Variable, up to 255 octets</td>
<td style="text-align:left">The domain to be resolved</td>
</tr>
<tr>
<td style="text-align:center">QTYPE</td>
<td style="text-align:center">2 octets</td>
<td style="text-align:left">Specifies the qtype of query</td>
</tr>
<tr>
<td style="text-align:center">QCLASS</td>
<td style="text-align:center">2 octets</td>
<td style="text-align:left">Specifies the qclass of query</td>
</tr>
</tbody>
</table>
<p>Those details being types and classes, which are shared between questions and response records (though questions have a slightly larger set for both). The class describes the network the request should be regarding (e.g., in essentially every modern situation, class 1 = IN = the Internet; though it looks like <a href="https://jpmens.net/2012/06/28/hesiod-a-lightweight-directory-service-on-dns/">Hesiod</a> might still matter in some niche situations), and the type describes the type of record being sought (ranging from very recognizable ones like A records, CNAME records, and MX (mail) records to much more niche ones I&rsquo;ve personally never heard of like PTR &ldquo;domain name pointer&rdquo;, WKS &ldquo;well known service description&rdquo;, and SOA &ldquo;start of zone of authority&rdquo;. I don&rsquo;t know what most of them mean, but I&rsquo;ll definitely research them as I move forwards and put it in a future post.</p>
<p>Regardless, the full list in C macro form works out to:</p>
<pre><code>#define DNSL_DEFINE_COMMON_TYPE_VALUES(name) \
    DNSL_##name##_A = 1, \
    DNSL_##name##_NS = 2, \
    DNSL_##name##_OBSOLETE_MD = 3, \
    DNSL_##name##_OBSOLETE_MF = 4, \
    DNSL_##name##_CNAME = 5, \
    DNSL_##name##_SOA = 6, \
    DNSL_##name##_EXPERIMENTAL_MB = 7, \
    DNSL_##name##_EXPERIMENTAL_MG = 8, \
    DNSL_##name##_EXPERIMENTAL_MR = 9, \
    DNSL_##name##_EXPERIMENTAL_NULL = 10, \
    DNSL_##name##_WKS = 11, \
    DNSL_##name##_PTR = 12, \
    DNSL_##name##_HINFO = 13, \
    DNSL_##name##_MINFO = 14, \
    DNSL_##name##_MX = 15, \
    DNSL_##name##_TXT = 16

#define DNSL_DEFINE_COMMON_CLASS_VALUES(name) \
    DNSL_##name##_IN = 1, \
    DNSL_##name##_OBSOLETE_CS = 2, \
    DNSL_##name##_CH = 3, \
    DNSL_##name##_HS = 4
...
enum dnsl_question_type {
    DNSL_DEFINE_COMMON_TYPE_VALUES(QUESTION_TYPE),
    DNSL_QUESTION_TYPE_AXFR = 252,
    DNSL_QUESTION_TYPE_MAILB = 253,
    DNSL_QUESTION_TYPE_OBSOLETE_MAILA = 254,
    DNSL_QUESTION_TYPE_ALL = 255
};

enum dnsl_question_class {
    DNSL_DEFINE_COMMON_CLASS_VALUES(QUESTION_CLASS),
    DNSL_QUESTION_CLASS_ALL = 255
};
...
enum dnsl_rrecord_type {
    DNSL_DEFINE_COMMON_TYPE_VALUES(RRECORD_TYPE)
};

enum dnsl_rrecord_class {
    DNSL_DEFINE_COMMON_CLASS_VALUES(RRECORD_CLASS)
};
</code></pre>
<p>With that, all we have left to look into structure wise is resource records. They&rsquo;re not too dissimilar from questions, but much more complicated in practice:</p>
<table>
<thead>
<tr>
<th style="text-align:center">Section</th>
<th style="text-align:center">Size</th>
<th style="text-align:left">Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">NAME</td>
<td style="text-align:center">Variable, up to 255 octets</td>
<td style="text-align:left">The domain name to which the record pertains</td>
</tr>
<tr>
<td style="text-align:center">TYPE</td>
<td style="text-align:center">2 octets</td>
<td style="text-align:left">Specifies the type of the response</td>
</tr>
<tr>
<td style="text-align:center">CLASS</td>
<td style="text-align:center">2 octets</td>
<td style="text-align:left">Specifies the class of the response</td>
</tr>
<tr>
<td style="text-align:center">TTL</td>
<td style="text-align:center">4 octets</td>
<td style="text-align:left">Time interval in seconds before cached response must be expired</td>
</tr>
<tr>
<td style="text-align:center">RDLENGTH</td>
<td style="text-align:center">2 octets</td>
<td style="text-align:left">Length of the RDATA field</td>
</tr>
<tr>
<td style="text-align:center">RDATA</td>
<td style="text-align:center">Variable</td>
<td style="text-align:left">Describes the resource depending on TYPE and CLASS</td>
</tr>
</tbody>
</table>
<p>So&hellip; what is the RDATA format?</p>
<p>That depends. And varies quite a bit. So we&rsquo;ll get to that in a future post when I finish implementing responses. For the meantime, it&rsquo;s essentially the result of the query. For instance, an A query returns a 4 octet IP address, while CNAME returns a variable-length domain name.</p>
<h2 id="odds-and-ends">Odds and Ends</h2>
<p>With that, there&rsquo;s two more minor details to cover in the spec before getting to implementation and such.</p>
<h3 id="domain-name-format">Domain Name Format</h3>
<p>Domains run through a quick processing step before being inserted into queries. For each &ldquo;label&rdquo; in the original domain name—i.e., each portion separated by the dots—it should be prefixed with its length, and null terminated. For instance, <a href="https://www.paterissa.net">www.paterissa.net</a> would become 0x03www0x09paterissa0x03net0x00. Don&rsquo;t think this can always be treated as a C string, though, since technically \0x00 can legally occur inside a label itself<sup id="fnref:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup>. I&rsquo;m not entirely certain how that interacts with internationalization/IDN names yet. I&rsquo;ll come back to that at the tail end of a future post. Finally—and this is important for the next section—labels are strictly restricted to a maximum size of 63 octets. This is because the two high bits are reserved.</p>
<h3 id="message-compression">Message Compression</h3>
<p>To reduce message size, DNS uses a compression scheme to eliminate the repetition of domain names across multiple values in a single response. The spec is a bit difficult to parse on this: it says</p>
<blockquote>
<p>The compression scheme allows a domain name in a message to be<br>
represented as either:</p>
<ul>
<li>a sequence of labels ending in a zero octet</li>
<li>a pointer</li>
<li>a sequence of labels ending with a pointer</li>
</ul>
</blockquote>
<p>So&hellip; what does that actually mean? It&rsquo;s pretty simple, just described in an unnecessarily difficult fashion. Let&rsquo;s say you have example.com, sub1.example.com, sub2.example.com, and sub1.sub2.example.com, in that order. That means:</p>
<p>example.com &gt; example + com + 0x00<br>
sub1.example.com &gt; sub1 + pointer(example.com) <em>or</em> sub1 + example + com + 0x00<br>
sub2.example.com &gt; sub2 + pointer(example.com) <em>or</em> sub2 + example + com + 0x00<br>
sub1.sub2.example.com &gt; sub1 + pointer(sub2.example.com) <em>or</em> sub1 + sub2 + pointer(example.com) <em>or</em> sub1 + sub2 + example + com + 0x00</p>
<p>So it&rsquo;s not really that complicated. The pointer format is a two octet sequence that is 0b11+ offset, where offset measures from the start of the header.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>&ldquo;each zone is the complete database for a particular &lsquo;pruned&rsquo; subtree of the domain space&rdquo;&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>&ldquo;In either case, resolvers are replaced with stub resolvers which act as front ends to resolvers located in a recursive server in one or more name servers known to perform that service&rdquo;&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p><a href="https://www.iana.org/domains/root/servers">The list is available here</a>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>So. Facts to keep you up at night. There is absolutely nothing forcing this to be 0 or 1. Indeed, there&rsquo;s an <a href="https://datatracker.ietf.org/doc/html/rfc9619">entirely separate RFC</a> noting that, hey, technically this can be as many as 65,535, but it&rsquo;s fiiiine and it&rsquo;s USUALLY one and indeed &ldquo;several parameters specified for DNS response messages such as AA and RCODE have no defined meaning when the message contains multiple queries as there is no way to signal which question those parameters relate to&rdquo; so really an implementation should &ldquo;A DNS message with OPCODE = 0 and QDCOUNT &gt; 1 MUST be treated as an incorrectly formatted message&rdquo;. Cool? Cool.&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p>It&rsquo;s not abundantly clear in the spec, but <a href="https://datatracker.ietf.org/doc/html/rfc2181#section-9">RFC 2181</a> specifies: &ldquo;Where TC is set, the partial RRSet that would not completely fit may be left in the response. When a DNS client receives a reply with TC set, it should ignore that response, and query again, using a mechanism, such as a TCP connection, that will permit larger replies.&rdquo;&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:6">
<p>Sigh. Yes, this also means that to be compliant you can&rsquo;t simply stop at 0x00.&#160;<a href="#fnref:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>]]></content:encoded>
  </item>
  <item>
    <title>New Blog Website!</title>
    <link>https://paterissa.net/post?id=1</link>
    <guid>https://paterissa.net/post?id=1</guid>
    <description><![CDATA[<h1 id="new-blog-website">New Blog Website!</h1>
<p>Hi! Chances are you don&rsquo;t know me, but if you do, it&rsquo;s me, thehinterlander (the artist formally and occasionally also known as pitl). I&rsquo;ve had some blogging ventures before, but I&rsquo;ve never really managed to keep it going long-te</p>
]]></description>
    <pubDate>Tue, 25 Nov 2025 20:10:09 +0000</pubDate>
    <content:encoded><![CDATA[<h1 id="new-blog-website">New Blog Website!</h1>
<p>Hi! Chances are you don&rsquo;t know me, but if you do, it&rsquo;s me, thehinterlander (the artist formally and occasionally also known as pitl). I&rsquo;ve had some blogging ventures before, but I&rsquo;ve never really managed to keep it going long-term, partly because I don&rsquo;t love the modern social media ecosystem overly much. Tumblr was alright for a while, but the feed got on my nerves.</p>
<p>However, over the past few weeks, I&rsquo;ve been working hard on putting together a personal blog! Built by myself, on my own hardware, managed by myself! So here we are.</p>
<p>If somehow you stumble across this (admittedly improbable) you can expect to see the following over however long I run this place:</p>
<ul>
<li>Tech musings, programming notes, maybe a couple tutos for things I&rsquo;m working on</li>
<li>Reviews of games, music, and other media</li>
<li>Announcements for any projects</li>
<li><del>Many many half-finished projects</del></li>
<li>Potentially a little social or political commentary of the more docile variety</li>
</ul>
<p>And so on and so forth.</p>
]]></content:encoded>
  </item>
</channel></rss>