<?xml version="1.0" encoding="utf-8"?> 
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <generator uri="https://gohugo.io/" version="0.78.2">Hugo</generator><title type="html"><![CDATA[dhcpcd on Roy's Blog]]></title>
    
        <subtitle type="html"><![CDATA[Mainly about tech stuff I have a hand in]]></subtitle>
    
    
    
            <link href="https://roy.marples.name/blog/tags/dhcpcd/" rel="alternate" type="text/html" title="HTML" />
            <link href="https://roy.marples.name/blog/tags/dhcpcd/atom.xml" rel="self" type="application/atom+xml" title="Atom" />
            <link href="https://roy.marples.name/blog/tags/dhcpcd/feed.json" rel="alternate" type="application/json" title="Json" />
    <updated>2021-03-12T11:08:32+00:00</updated>
    
    <id>https://roy.marples.name/blog/tags/dhcpcd/</id>
        
        <entry>
            <title type="html"><![CDATA[Capsicum vs Pledge Final Thoughts]]></title>
            <link href="https://roy.marples.name/blog/posts/capsicum_vs_pledge_final_thoughts/?utm_source=atom_feed" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://roy.marples.name/blog/posts/capsicum_vs_pledge_final_thoughts/</id>
            
            <published>2020-06-15T17:15:00+00:00</published>
            <updated>2020-06-15T17:15:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>Following on from <a href="../capsicum_vs_pledge_part2">Capsicum vs Pledge Part 2</a>
I thought I would post my final thougts on the topic as the development
on these sandbox technologies draws to a close in <a href="/projects/dhcpcd">dhcpcd</a>.</p>
<p>But first, let us discuss &hellip;</p>
<h2 id="the-posix-resource-limited-sandbox">The POSIX Resource Limited sandbox</h2>
<p>POSIX documents
<a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html">setrlimit(2)</a>.
Disabling the ability to open new files, sockets, etc, or create new processes
is actually pretty powerful.</p>
<p>Thanks to the privsep dhcpcd now has to support both Capsicum and Pledge, this
turned out to be pretty easy to implement.
The <em>only</em> issue with this is the
<a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html">poll(2)</a>
interface which dhcpcd makes great use of.
Implementations found on Linux, OpenBSD and Solaris return <code>EINVAL</code> when the
<code>nfds</code> argument is greater than <code>RLIMIT_NOFILE</code> where-as the other OS&rsquo;s dhcpcd
supports don&rsquo;t.
This means that on Linux, OpenBSD and Solaris an attacker could close
an exiting file descriptor and try to open a new one.
On OpenBSD this is not that much of a big deal because pledge should stop
that from happening.
On Linux and Solaris, they can&rsquo;t open a file thanks to the chrooted empty
directory but they can create a new one.
But thanks to <code>RLIMIT_FSIZE</code> they can&rsquo;t actually write to it.
At most they could create a network socket and send arbitary data over it.
For Linux, we could look into using seccomp to stop this.</p>
<p>For implementations such as NetBSD and FreeBSD, setting <code>RLIMIT_NOFILE</code> to zero
with poll(2) still working means they cannot create any few file descriptor.
This means that if an attacker breaches a resource limited process it
<strong>can only work with the resources it has</strong> because it cannot fork another
process, nor open any files, sockets, etc.
It&rsquo;s also running as an unpriviledged user locked in an empty directory,
so there is nothing to see or do there.
All the resources it currently has are:</p>
<ul>
<li>PF_INET, PF_LINK, etc sockets that can only query for data</li>
<li>network proxy process (receives only, does not send)</li>
<li>BPF processes (send and receive, the read and write filters are also locked)</li>
<li>privileged actioneer (filters ioctls, validates paths and outbound traffic)</li>
</ul>
<p>So the only way to do anything outside of what dhcpcd normally does is to use
a facility that does not need to create a file or socket, or fork a process.
The only remaining avenue of attack is to break the privileged actioneer
process- that cannot be protected by any sandboxing as it needs to do a lot
of stuff. Both OpenBSD&rsquo;s and FreeBSD&rsquo;s dhclient have such a privileged
process as well.</p>
<p>The priviledged actioneer process itself doesn&rsquo;t do a great deal.
For example to add a route on BSD you create a RTM_ADD message.
The master process will do this and instead of writing to the PF_ROUTE socket
itself it will pass the message to the privilged actioneer process which
in turn writes to it&rsquo;s PF_ROUTE socket.
Every ioctl, path accessed or network bound packet is validated by the
privileged actioneer. Even though it&rsquo;s generic, it&rsquo;s also locked down.</p>
<h2 id="so-what-extra-to-capsicum-and-pledge-bring-to-the-table">So what extra to Capsicum and Pledge bring to the table?</h2>
<p>Both bring system call filtering.
For example,
<a href="https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+3+NetBSD-current">sysctl(2)</a>
does not need to create a new resource.
Information available to the ordinal user such as
<a href="https://en.wikipedia.org/wiki/Uname">uname</a> may not be
desirable to leak to these sandboxed processes.
But then the question to ask is what can they do with it?</p>
<p>Pledge overcomes the <code>RLIMIT_NOFILE</code> limitation for poll(2) on OpenBSD.</p>
<p>Capsicum goes a bit futher by limiting rights of each resource you
have in terms of what you can do with them.</p>
<p>What they both bring to the table though is making sandboxing easier.
Here, Pledge is the outright winner. As I pointed out in my initial blog
post, Pledge is really easy.
But make it too easy and it&rsquo;s not as secure as it could be.
Capsicum is harder and the resource limited sandbox is harder still.</p>
<p>The take-away point from this is while Capsicum and Pledge are nice,
they don&rsquo;t beat a good design.</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://roy.marples.name/blog/tags/tech" term="tech" label="tech" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/code" term="code" label="code" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/dhcpcd" term="dhcpcd" label="dhcpcd" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/sandbox" term="sandbox" label="sandbox" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Capsicum vs Pledge in a Network Management Tool ... Part 2]]></title>
            <link href="https://roy.marples.name/blog/posts/capsicum_vs_pledge_part2/?utm_source=atom_feed" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://roy.marples.name/blog/posts/capsicum_vs_pledge_part2/</id>
            
            <published>2020-05-14T14:00:00+00:00</published>
            <updated>2020-05-14T14:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>A few days ago I posted about <a href="../capsicum_vs_pledge">Capsicum vs Pledge</a>
in dhcpcd. Well, I finished the Capsicum integration yesterday so I thought
I would take some time to revisit my findings.</p>
<h2 id="capsicum-is-hard-to-develop-for">Capsicum is hard to develop for</h2>
<p>It&rsquo;s either on or off.
You can limit each FD with capabilites mode off, but I&rsquo;m not sure what that gains
as it&rsquo;s mainly there to allow the FD to be used in the restricted world so
we can treat it as either on or off really.</p>
<p>Pledge is granular, you can turn areas on or off.
For example, you can allow full file access while restricting various ioctls.
Ideally, the only thing you want to pledge is stdio, which is kinda needed
for the Privilege Separation IPC to work.
However, we end up pledging dns inet and route as well.</p>
<p>So why is Capsicum harder? Well, the short answer is that it&rsquo;s not.
The long answer is that it&rsquo;s perceived to be harder because you have to
do all the work up front to get your code working whereas Pledge allows you
do it it piece meal.</p>
<h2 id="pledge-is-as-secure-as-capsicum">Pledge is as secure as Capsicum</h2>
<p>As I said in my prior post, I&rsquo;m not a security expert, but here&rsquo;s my findings:</p>
<p>You can make Pledge as secure as Capsicum, <strong>but you don&rsquo;t have to</strong>.</p>
<p>As a user on OpenBSD I can see lots of processes marked with <code>p</code> to indicate
they have pledged something.
<del>What that something is though is a black box.</del>
You can use <code>ps-o pledge-p $pid</code> to show the promises a process has pledged.
The more promises you see the more that process is allowed to do.
Short list good, long list bad.</p>
<p>As a user on FreeBSD I can see lots of processes marked with &lsquo;C&rsquo; to indicate
they are in Capsicum Capabilites Mode. Because this is just on or off, I
know exactly what this process can and cannot do.</p>
<p>Armed with this knowledge I would trust a Capsicum enabled application more
than a Pledge enabled application. But to fully trust either you still need
to audit the code.</p>
<h2 id="they-both-have-limitations">They both have limitations</h2>
<p>With a Pledged process you cannot change a BPF filter with the bpf pledge.
This is unfortunate, a possible solution could be to spawn a process AND filter
for every address you want to monitor for DaD or ARP pinging.
That <em>could</em> be a lot of resources wasted as BPF is neither infinite nor cheap.</p>
<p>With a Capsicum Capability Mode enabled process you cannot call sendto(2)
that is not connected.
Unlike the above, there is no easy solution.
I can&rsquo;t spawn off another process because unlike normal communication,
because I <strong>need</strong> to bind to the <code>bootpc</code> and <code>dhcpv6-client</code> ports
so I can dictate which source port is used to send the message.
The binding would then fail because the network proxy process
is already using the port.
A possible solution is to call RTM_GET to work out which host I send to
on the local network, craft the packet by hand and send it out using a BPF
socket.</p>
<p>I strongly feel that both should be fixed upstream:</p>
<ul>
<li>the bpf Pledge should allow changing the BPF filter.</li>
<li>Capsicum should allow sendto unconnected if bound to a priviledged port or another capability created to grant to the socket.</li>
</ul>
<p>As it stands, dhcpcd does not Pledge for BPF processes and does not run
the generic network proxy process in Capsicum Capabilites mode.
However, both processes are using the unprivileged user and chrooted to an
empty directory. Neither do any processing of data coming in, they just
ferry it back to the master process via IPC which runs under the same
restrictions but is also sandboxed with Pledge or Capsicum so I&rsquo;m
confident that it&rsquo;s good enough.</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://roy.marples.name/blog/tags/tech" term="tech" label="tech" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/code" term="code" label="code" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/dhcpcd" term="dhcpcd" label="dhcpcd" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/sandbox" term="sandbox" label="sandbox" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Capsicum vs Pledge in a Network Management Tool]]></title>
            <link href="https://roy.marples.name/blog/posts/capsicum_vs_pledge/?utm_source=atom_feed" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://roy.marples.name/blog/posts/capsicum_vs_pledge/</id>
            
            <published>2020-05-12T11:46:00+00:00</published>
            <updated>2020-05-12T11:46:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>So one of the big goals of <a href="/projects/dhcpcd">dhcpcd</a> was to implement
<a href="https://en.wikipedia.org/wiki/Privilege_separation">Privilege Separation</a>.
This was achieved in <a href="/blog/dhcpcd-9-0-0-released.html">dhcpcd-9</a> which was
important because it was a required step of work to
<a href="https://lists.freebsd.org/pipermail/freebsd-net/2019-October/054535.html">merge dhcpcd into FreeBSD base system</a>. Once done, we can then look at what is
required to enable <a href="https://wiki.freebsd.org/Capsicum">Capsicum</a> support,
which is the last required step before dhcpcd can even be considered for
importing into FreeBSD base system.</p>
<p>The good news is that <em>basic</em> Capsicum support has been enabled in
<a href="https://roy.marples.name/cgit/dhcpcd.git/commit/?id=727b7e9bf8b2fe810913c76c5fd36767869944bb">this commit</a> by ensuring all the file descriptors of the
network facing processes are limited in their capability.
The bad news is that <a href="https://www.freebsd.org/cgi/man.cgi?capsicum(4)">capability mode</a> is only enabled for the BPF processes- the end goal is that
the master process is at least placed in capability mode.</p>
<p>So what&rsquo;s the problem? Well, the first problem is that Capsicum is really
hard to use, a lot of this is not helped by the documentation.
It took a long time to work out how it works and how to use it.
The second problem is that capability mode is really hard core- it stops
a lot of stuff working dead in it&rsquo;s tracks by killing access not capability
limited in the global namespace.</p>
<p>From dhcpcds perspective the big issue is that
<del>gethostname(3) and</del> getifaddrs(3) won&rsquo;t work.
This is the biggest show stopper, hard to IPC.</p>
<p><em>EDIT: gethostname(3) does work in Capsicum capabilities mode.</em></p>
<p>Let&rsquo;s just take a moment to talk about getifaddrs(3)- it&rsquo;s a really
powerful interface to work out what interfaces are available to work with.
In some OS it&rsquo;s the only mechanism to get the hardware address assigned
to an interface. Also, it&rsquo;s possible for the route(4) (or netlink(7))
socket to overflow so it&rsquo;s required to re-learn the system state which means
it cannot be cached.
Not that FreeBSD supports reporting route(4) overflow, but that&rsquo;s another story.</p>
<p>Due to the getifaddrs(3) show stopper, I decided to look into
<a href="https://man.openbsd.org/pledge.2">OpenBSDs pledge(2)</a>. While the documentation
is still very technical, it&rsquo;s easier to read and understand compared to
Capsicum. It&rsquo;s also really <em>really</em> <strong>really</strong> easy to implement in comparison
as you only pledge features rather than each file descriptor.
Because of this, it&rsquo;s also very granular.
<a href="https://roy.marples.name/cgit/dhcpcd.git/commit/?id=2f9d9eae5fb8fb1922b0e096e157987ac0df110e">The initial commit to enable pledge</a> is mainly allowing the
current ioctl IPC framework to pass data back again.</p>
<p>But can we do better? Can we operate with the same Pledges that OpenBSDs
dhclient(8) uses? The answer is of course <strong>YES</strong>!
By caching some initial data that does not change such as utsname and
machine uuid AND moving all file IO to privsep,
<a href="https://roy.marples.name/cgit/dhcpcd.git/commit/?id=2f9d9eae5fb8fb1922b0e096e157987ac0df110e">this commit</a>
allows almost perfect Pledge support.
We could go better if privsep gains support for the <code>SIOCGIFGROUP</code> ioctl as
this would allow the <code>inet</code> pledge to be dropped.
It&rsquo;s not quite perfect because
<a href="http://openbsd-archive.7691.n7.nabble.com/pledge-bpf-32bit-arch-unbreak-td299901.html">a Pledged process cannot change a BPF filter</a>.
We would need to space a BPF process per address which is then limited by the
number of BPF instances you are allowed. I&rsquo;m not sure this a good thing, and
ironically BPF processes are the one thing we have in Capsicums capability mode.
This is also a massive improvement over the initial dhcpcd-9 release because
it means we no longer need any files in the chroot directory and <code>/var/empty</code>
can be used again.
This alone should make current and new FreeBSD users of dhcpcd quite happy.
It will also go some way to enabling capabilities mode for the master
dhcpcd process in the future.</p>
<p>Now, I can&rsquo;t say which technology is more secure- that&rsquo;s really not my field
of expertise.
I can&rsquo;t even say if either are really needed or actually make security worse
because Privilege Separation
<a href="https://en.wikipedia.org/wiki/Inter-process_communication">IPC</a>
adds more code, complexity and as such could make it more prone
to bugs some of which could be a security attack vector in itself.</p>
<p>But what I can say is that Pledge is much easier to develop for
because it&rsquo;s really granular unlike Capsicum which is either on or off or
per fd limited.</p>
<p>I&rsquo;ll continue working on Capsicum support in dhcpcd just to see if I can
enable Capabilites Mode in the master process.
When that&rsquo;s finished I will do a more in-depth comparison of these two
technologies.</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://roy.marples.name/blog/tags/tech" term="tech" label="tech" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/code" term="code" label="code" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/dhcpcd" term="dhcpcd" label="dhcpcd" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/sandbox" term="sandbox" label="sandbox" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Being thanked gives me the warm fuzzies]]></title>
            <link href="https://roy.marples.name/blog/posts/2020-05-02_dhcpcd_thanks/?utm_source=atom_feed" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://roy.marples.name/blog/posts/2020-05-02_dhcpcd_thanks/</id>
            
            <published>2020-05-02T01:05:00+00:00</published>
            <updated>2020-05-02T01:05:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>So I just got this email and I thought I would share it verbatim:</p>
<blockquote>
<p>I just wanted to thank you for such a great piece of software (dhcpcd)&hellip;</p>
<p>I often forget the people that make all this cool stuff that make linux.
bsd and all the other unixes work&hellip;
so rather sending a bug report, I&rsquo;d just though i&rsquo;d send you a hello!
and thanks for giving my machines ip addresses!!!!!</p>
<p>I was diagnosing a race condition between gnome network manager,
wireless, wpa_supplicant and dhcpcd&hellip;</p>
<p>but that for further research&hellip;
(your software is doing exactly what is should do). :-).</p>
<p>Regards,</p>
<p>Lee</p>
</blockquote>
<p><em>THIS</em> is one of the main reasons I enjoy this hobby of mine &hellip;.
random thoughts of happiness that come in from total strangers that appreciate
that I made something for free that in turn made them happy :)</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://roy.marples.name/blog/tags/life" term="life" label="life" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/dhcpcd" term="dhcpcd" label="dhcpcd" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Anonymity Profiles for DHCP Clients aka RFC 7844]]></title>
            <link href="https://roy.marples.name/blog/posts/anonymity_profiles_for_dhcp_clients/?utm_source=atom_feed" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://roy.marples.name/blog/posts/anonymity_profiles_for_dhcp_clients/</id>
            
            <published>2020-01-15T17:39:00+00:00</published>
            <updated>2020-01-15T17:39:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>DHCP clients by default send a fair chunk of data which can identify you to the local DHCP server.
In return they provide you with a stable IP address and configuration parameters.</p>
<p>At a bare minimum, the hardware address of the interface is sent- this is <strong>required</strong> to work.</p>
<p>So, how to solve this dilema of wanting total anonymity?
The answer is to randomise the hardware address. This will happen when the carrier is down OR dhcpcd starts with the interface down.
Then, dhcpcd will use this random hardware address to set a DUID LL which will be used inplace of any saved DUID and set the IAID to all zeros.
This combo is used by DHCP and DHCPv6 to identify a lease.
As this is randomised each time the carrier comes up you get a different IP address!</p>
<p>Try not to use this on an unstable link as it could drain the DHCP server of addresses :(</p>
<p>But we can&rsquo;t stop there!
dhcpcd also sends some identifying options as well! For example, this is sent in the vendor class identifier:<br>
<code>dhcpcd-8.99.0:NetBSD-9.99.17:amd64:x86_64</code></p>
<p>It does not identify you or the device in anyway, but it does say what software is being used on which hardware.
This <em>could</em> be used by DHCP servers to hand out a specific image to download and boot from TFTP for network boot clients.</p>
<p>Now, there are a gazzillion and one DHCP options out there- we don&rsquo;t know what you&rsquo;ve configured.
So dhcpcd will mask <strong>all</strong> of them when anonymous mode is activated, unless they are essential for enabling dhcpcd to work correctly on the network.
But wait! What if you really want to leak something? Like say your on a corporate network that uses DHCP security and still want to remain anonymous?
Well you can! Any request or option <strong>after</strong> the anonymous option in <code>dhcpcd.conf</code> is turned on.
So the placing of the anonymous directive is important, unlike other dhcpcd options. So far this is the only implementation of <a href="https://tools.ietf.org/html/rfc7844">RFC 7844</a> which does this :)</p>
<p>This is <em>NOT</em> enabled by default because most people want stable addresses <em>AND</em> a flappy link could drain addresses as disussed earlier.</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://roy.marples.name/blog/tags/dhcpcd" term="dhcpcd" label="dhcpcd" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[structure padding in C]]></title>
            <link href="https://roy.marples.name/blog/posts/structure_padding_in_c/?utm_source=atom_feed" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://roy.marples.name/blog/posts/structure_padding_in_c/</id>
            
            <published>2020-01-09T01:06:00+00:00</published>
            <updated>2020-01-09T01:06:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>Whilst developing <a href="https://en.wikipedia.org/wiki/Privilege_separation">Privilege Separation</a> in <a href="/projects/dhcpcd">dhcpcd</a>, I had to come up with an <a href="https://en.wikipedia.org/wiki/Inter-process_communication">IPC</a> design for it.
Of course, that involves creating <a href="https://en.wikipedia.org/wiki/Struct_(C_programming_language)">structures</a>.</p>
<p>So far, my structures in dhcpcd are long lived- or rather the scope is design to live outside of where it was created.
As such they are created on the <a href="https://en.wikipedia.org/wiki/Heap_(data_structure)">heap</a> and are at the <a href="https://cpp4arduino.com/2018/11/06/what-is-heap-fragmentation.html">mercy of malloc</a>.
Generally I use <a href="https://pubs.opengroup.org/onlinepubs/009695399/functions/calloc.html">calloc</a> so that the whole area is inited to zero as <a href="https://en.wikipedia.org/wiki/Uninitialized_variable">uninitialised memory is bad</a>.</p>
<p>So I decided to start out and see if I can just create the structures I need on the stack.
Turns out I could! Yay!
Now, how to you initialise a structure on the stack to all zeros?
First let us consider this structure:</p>
<div class="highlight"><pre style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#069;font-weight:bold">struct</span> ps_addr {
	sa_family_t psa_family;
	<span style="color:#069;font-weight:bold">union</span> {
		<span style="color:#069;font-weight:bold">struct</span> in_addr psau_in_addr;
		<span style="color:#069;font-weight:bold">struct</span> in6_addr psau_in6_addr;
	} psa_u;
<span style="color:#099">#define	psa_in_addr		psa_u.psau_in_addr
</span><span style="color:#099">#define	psa_in6_addr	psa_u.psau_in6_addr
</span><span style="color:#099"></span>};
</code></pre></div><p>The first way is memset:</p>
<div class="highlight"><pre style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#069;font-weight:bold">struct</span> ps_addr psa;

memset(<span style="color:#555">&amp;</span>psa, <span style="color:#f60">0</span>, <span style="color:#069;font-weight:bold">sizeof</span>(psa));
psa.psa_family <span style="color:#555">=</span> AF_INET;
</code></pre></div><p>But what if you could avoid memset?
Luckily the <a href="https://www.dribin.org/dave/blog/archives/2010/05/15/c99_syntax/">C standard allows setting any member and will zero all other members</a>.
So we can do this:</p>
<div class="highlight"><pre style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#069;font-weight:bold">struct</span> ps_addr psa <span style="color:#555">=</span> { .psa_family <span style="color:#555">=</span> AF_INET };
</code></pre></div><p>Wow!!! So simple. This reduces binary size a fair bit.
But <strong>then</strong> I turned on the <a href="https://github.com/google/sanitizers/wiki/MemorySanitizer">Memory Sanitiser</a> and boom, it crashed hard.
Why?</p>
<p>The answer is simple- padding.
<a href="http://www.catb.org/esr/structure-packing/">Eric S Raymond gives a very good writeup</a> about the problem.
Basically, the standard will initialise any unintialised members to zero- but padding added for alignent isn&rsquo;t a member!
So we need to ensure that our structure requires zero padding.</p>
<p>Here is the new struct:</p>
<div class="highlight"><pre style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#069;font-weight:bold">struct</span> ps_addr {
	sa_family_t psa_family;
	uint8_t psa_pad[<span style="color:#f60">4</span><span style="color:#555">-</span> <span style="color:#069;font-weight:bold">sizeof</span>(sa_family_t)];
	<span style="color:#069;font-weight:bold">union</span> {
		<span style="color:#069;font-weight:bold">struct</span> in_addr psau_in_addr;
		<span style="color:#069;font-weight:bold">struct</span> in6_addr psau_in6_addr;
	} psa_u;
<span style="color:#099">#define	psa_in_addr		psa_u.psau_in_addr
</span><span style="color:#099">#define	psa_in6_addr	psa_u.psau_in6_addr
</span><span style="color:#099"></span>};
</code></pre></div><p>And it allows the former structure initialisation to work and memory sanitisers are happy- so happy days :)
Now, if anyone can tell me what I can use instead of the magic number 4 in the above I&rsquo;d be even happier!</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://roy.marples.name/blog/tags/dhcpcd" term="dhcpcd" label="dhcpcd" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/code" term="code" label="code" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[open_memstream]]></title>
            <link href="https://roy.marples.name/blog/posts/open_memstream/?utm_source=atom_feed" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://roy.marples.name/blog/posts/open_memstream/</id>
            
            <published>2019-07-20T13:52:00+00:00</published>
            <updated>2019-07-20T13:52:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p><a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/open_memstream.html">open_memstream</a> is one of the more important functions added to POSIX libc of late. It&rsquo;s so important because it makes the generation of strings really easy- you no longer need to care about allocating the right amount of memory as the library will do it for you.
Now, there&rsquo;s many functions that already help with this, such as <a href="https://netbsd.gw.com/cgi-bin/man-cgi?asprintf">asprintf</a> but that&rsquo;s not standard and if you want to create many strings in one area you still need to care about the size of the area. You want to create an area if you have many strings, because it&rsquo;s more efficient for malloc and if you keep the area around and re-use it then it avoids <a href="https://stackoverflow.com/questions/3770457/what-is-memory-fragmentation">memory fragmentation</a>.</p>
<p>Now, to be clear, <em>you have been able to do this since forever</em> using <a href="https://pubs.opengroup.org/onlinepubs/009695399/functions/fopen.html">fopen</a>, writing to the file and then allocating your area based on the final file size. Still, it requires some memory management still but more importantly <em>it writes to a file</em>. Writing to a file is slow and reduces the life span of the disk you&rsquo;re writing to. It&rsquo;s only been fairly recently that <a href="https://en.wikipedia.org/wiki/Tmpfs">tmpfs</a> was a thing, but even today not all OS&rsquo;s have /tmp mounted as tmpfs. Requiring this isn&rsquo;t exactly ideal for a generic program to do- the setup and install should be easy.
Because of all these reasons, most programs worked the string length needed and either allocated an area or string and then finally write the string. However, while saving the disk, it&rsquo;s also a lot more error prone because you need to work out the length of everything and that&rsquo;s not always trivial, especially for things like a DHCP client which is always building strings based on the information given by the DHCP server.</p>
<p>Here&rsquo;s an example of <code>open_memstream</code> in action:</p>
<div class="highlight"><pre style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#09f;font-style:italic">/*
</span><span style="color:#09f;font-style:italic"> * Example program which manages an area of environment strings
</span><span style="color:#09f;font-style:italic"> * to send to child programs.
</span><span style="color:#09f;font-style:italic"> */</span>

<span style="color:#099">#include</span> <span style="color:#099">&lt;stdio.h&gt;</span><span style="color:#099">
</span><span style="color:#099">#include</span> <span style="color:#099">&lt;stdlib.h&gt;</span><span style="color:#099">
</span><span style="color:#099">#include</span> <span style="color:#099">&lt;unistd.h&gt;</span><span style="color:#099">
</span><span style="color:#099"></span>
<span style="color:#069;font-weight:bold">static</span> <span style="color:#069;font-weight:bold">const</span> <span style="color:#078;font-weight:bold">char</span> <span style="color:#555">*</span>foo <span style="color:#555">=</span> <span style="color:#c30">&#34;foo&#34;</span>;
<span style="color:#069;font-weight:bold">static</span> <span style="color:#069;font-weight:bold">const</span> <span style="color:#078;font-weight:bold">char</span> <span style="color:#555">*</span>bar <span style="color:#555">=</span> <span style="color:#c30">&#34;bar&#34;</span>;

<span style="color:#078;font-weight:bold">int</span> <span style="color:#c0f">main</span>(<span style="color:#078;font-weight:bold">void</span>)
{
        <span style="color:#078;font-weight:bold">char</span> <span style="color:#555">*</span>argv[] <span style="color:#555">=</span> { <span style="color:#c30">&#34;/usr/bin/env&#34;</span>, <span style="color:#366">NULL</span> };
        <span style="color:#078;font-weight:bold">char</span> <span style="color:#555">*</span>buf, <span style="color:#555">*</span>ep, <span style="color:#555">*</span>p, <span style="color:#555">**</span>env, <span style="color:#555">**</span>envp;
        size_t buflen, nenv, i;
        FILE <span style="color:#555">*</span>fp <span style="color:#555">=</span> open_memstream(<span style="color:#555">&amp;</span>buf, <span style="color:#555">&amp;</span>buflen);

        fprintf(fp, <span style="color:#c30">&#34;FOO=%s&#34;</span>, foo);
        fputc(<span style="color:#c30">&#39;\0&#39;</span>, fp);
        fprintf(fp, <span style="color:#c30">&#34;BAR=%s&#34;</span>, bar);
        fputc(<span style="color:#c30">&#39;\0&#39;</span>, fp);

        <span style="color:#09f;font-style:italic">/* We could keep fp around as our area and just rewind it. */</span>
        fclose(fp);

        <span style="color:#09f;font-style:italic">/* execve relies on a trailing NULL */</span>
        nenv <span style="color:#555">=</span> <span style="color:#f60">1</span>;
        <span style="color:#069;font-weight:bold">for</span> (p <span style="color:#555">=</span> buf, ep <span style="color:#555">=</span> p <span style="color:#555">+</span> buflen; p <span style="color:#555">&lt;</span> ep; p<span style="color:#555">++</span>) {
                <span style="color:#069;font-weight:bold">if</span> (<span style="color:#555">*</span>p <span style="color:#555">==</span> <span style="color:#c30">&#39;\0&#39;</span>)
                        nenv<span style="color:#555">++</span>;
        }

        <span style="color:#09f;font-style:italic">/* reallocarray(3) should be standard really */</span>
        envp <span style="color:#555">=</span> env <span style="color:#555">=</span> malloc(nenv <span style="color:#555">*</span> <span style="color:#069;font-weight:bold">sizeof</span>(<span style="color:#078;font-weight:bold">char</span> <span style="color:#555">*</span>));
        <span style="color:#555">*</span>envp<span style="color:#555">++</span> <span style="color:#555">=</span> buf;
        <span style="color:#069;font-weight:bold">for</span> (p <span style="color:#555">=</span> buf, ep<span style="color:#555">--</span>; p <span style="color:#555">&lt;</span> ep; p<span style="color:#555">++</span>) {
                <span style="color:#069;font-weight:bold">if</span> (<span style="color:#555">*</span>p <span style="color:#555">==</span> <span style="color:#c30">&#39;\0&#39;</span>)
                        <span style="color:#555">*</span>envp<span style="color:#555">++</span> <span style="color:#555">=</span> p <span style="color:#555">+</span> <span style="color:#f60">1</span>;
        }
        <span style="color:#555">*</span>envp <span style="color:#555">=</span> <span style="color:#366">NULL</span>;

        execve(argv[<span style="color:#f60">0</span>], argv, env);
}
</code></pre></div><p>As you can see, we only manage the environment array handed to to <code>execve</code>.
<code>open_memstream</code> is managing our string area and <code>fprintf</code> is working out the
length each string needs to be for us.
This vastly reduces the complexity and increases the security and reliabilty
of creating large environment strings, which most DHCP clients do.
We could also write a helper function to write the string AND the trailing
NULL terminator for the string to be more efficient.
You&rsquo;ll get to see this in dhcpcd-8 which should be released later this year.</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://roy.marples.name/blog/tags/tech" term="tech" label="tech" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/code" term="code" label="code" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/dhcpcd" term="dhcpcd" label="dhcpcd" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Red-Black Tree]]></title>
            <link href="https://roy.marples.name/blog/posts/red_black_tree/?utm_source=atom_feed" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://roy.marples.name/blog/posts/red_black_tree/</id>
            
            <published>2019-07-04T13:43:00+00:00</published>
            <updated>2019-07-04T13:43:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>Pretty much every piece of software I&rsquo;ve seen uses a list of objects. When you need to easily grow and shrink this list easily you then need something like a <a href="https://en.wikipedia.org/wiki/Linked_list">Linked List</a>.
dhcpcd has used very popular and widely available BSD based <a href="https://netbsd.gw.com/cgi-bin/man-cgi?queue+3+NetBSD-current">queue(3), specifically a tailq</a>. The main advantages of this type of list are:</p>
<ul>
<li>Very low extra memory needed for it&rsquo;s implementation</li>
<li>Fast at insertion and removal operation- both are O(1)</li>
</ul>
<p>However, it&rsquo;s just a list. And like any list, to find something we need to pick a starting point and then search in a single direction and match each item until we find it.
This is described as O(N) and it&rsquo;s performance roughly corrolates to the Number of objects in the list. If you need to insert at an arbitary point <em>(for example to order the list)</em> you need to search it, so this is O(N) also.</p>
<p>But is this slow?</p>
<p>Typically for dhcpcd, the answer is no because on a desktop, tablet, phone or SOHO router you only have a handful of objects in all the lists.
However, <a href="https://roy.marples.name/archives/dhcpcd-discuss/0002332.html">someone ran dhcpcd on a switch with millions of routes</a> and dhcpcd was taking minutes of CPU time for routing table modifications. So in this corner case &hellip; yes! dhcpcd is slow!
A suggestion to improve matters was given in that report- use a <a href="https://en.wikipedia.org/wiki/Red%E2%80%93black_tree">Red-Black Tree</a> instead of a Linked List. A RB tree guarantees O(log N) performance for searching. A patch was even submitted based on OpenBSD&rsquo;s tree implementation!
This reduced the dhcpcd runtime from minutes to seconds in his situation.</p>
<p>Now you can&rsquo;t just swap in a RB Tree for a Linked List. Each object within an RB Tree has to have a unique key. Also, you need to have comparison function to define an order to the objects within the tree.
Only then can you start to implement it. To find an object within the tree, you just need to know it&rsquo;s key and off you go.
I settled on using NetBSD&rsquo;s <a href="https://netbsd.gw.com/cgi-bin/man-cgi?rbtree+3+NetBSD-current">rbtree(3)</a> implementation instead of the initial suggestion to use the generic BSD <a href="https://netbsd.gw.com/cgi-bin/man-cgi?tree+3+NetBSD-current">tree(3)</a>.
This mainly to reduce the binary size of dhcpcd because it&rsquo;s in libc on NetBSD and on other systems it will creates a smaller binary due to the complexity of the tree(3) macros.
Testing also showed it was slightly faster and also easier to actually develop with.</p>
<p>So should you replace all LinkedLists with RB Trees? No! That would be silly :)
After all, sometimes you don&rsquo;t actually need to search or order a list- a lot of the time, lists are used for push/pop operations and thus gain nothing from RB Tree.</p>
<p>You&rsquo;ll get to see this in dhcpcd-8 which should be released later this year.</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://roy.marples.name/blog/tags/tech" term="tech" label="tech" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/dhcpcd" term="dhcpcd" label="dhcpcd" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/code" term="code" label="code" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Right after all these years]]></title>
            <link href="https://roy.marples.name/blog/posts/right_after_all_these_years/?utm_source=atom_feed" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://roy.marples.name/blog/posts/right_after_all_these_years/</id>
            
            <published>2014-01-15T10:51:00+00:00</published>
            <updated>2014-01-15T10:51:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>So one of the main features of <a href="/projects/dhcpcd">dhcpcd</a> was the ability to add and remove addresses <em>and</em> subnets in accordance with interface preference and state.
This worked very well in Linux, both for IPv4 and IPv6.</p>
<p>When I discovered <a href="http://roy.marples.name/blog/archives/77-FreeBSD.html">FreeBSD</a> and then <a href="http://roy.marples.name/blog/archives/128-Finding-NetBSD.html">NetBSD</a> making dhcpcd work with the same features provided troublesome. For the IPv4 case, we needed to patch the kernel so that <a href="http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/netinet/in.c.diff?r1=1.129&amp;r2=1.130&amp;only_with_tag=MAIN&amp;f=h">IFA_ROUTE</a> <a href="http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/netinet/in.c.diff?r1=1.141&amp;r2=1.142&amp;only_with_tag=MAIN&amp;f=h">remained sane</a>.
For the IPv6 case it was a lot more complicated as parts of the IPv6 stack <strong>rely</strong> on the kernel processing Router Advertisements instead of a 3rd party tool. Working this out was a lot more time consuming and complicated, <a href="http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/netinet6/nd6_nbr.c.diff?r1=1.98&amp;r2=1.99&amp;only_with_tag=MAIN&amp;f=h">but we got there</a> <a href="http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/netinet6/nd6.c.diff?r1=1.146&amp;r2=1.147&amp;only_with_tag=MAIN&amp;f=h">with minimal fuss</a>!</p>
<p>So as of now, dhcpcd can fully replace the NetBSD and Linux in kernel Router Advertisement handling code.</p>
<p>But why was I right after all these years? Because quite a few knowledgeable NetBSD folk assured me that the kernel was fine and it was likely dhcpcd at fault. As it turned out, it really was the kernels fault.</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://roy.marples.name/blog/tags/netbsd" term="netbsd" label="NetBSD" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/dhcpcd" term="dhcpcd" label="dhcpcd" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/tech" term="tech" label="tech" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[dhcpcd gains DHCPv6 INFORM support and other things]]></title>
            <link href="https://roy.marples.name/blog/posts/dhcpcd_gains_dhcpv6_inform_support_and_other_things/?utm_source=atom_feed" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://roy.marples.name/blog/posts/dhcpcd_gains_dhcpv6_inform_support_and_other_things/</id>
            
            <published>2012-10-13T11:16:00+00:00</published>
            <updated>2012-10-13T11:16:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>It&rsquo;s been an eventful two years of not blogging. Mainly as I got heavily involved in playing <a href="http://eu.battle.net/wow/en/character/aszune/Twisteddeath/advanced">World of Warcrat</a>, <a href="http://www.swtor.com/">Star Wars: The Old Republic</a> and now <a href="https://www.guildwars2.com/en/">Guild Wars 2</a> and this is a technical blog not a gaming one.</p>
<p>Anyhoo, since GW2 is a lot more casual than the others the idea is that I have more time for working on open source stuff, like say dhcpcd. Well, I finally found some time over the past few months and put <a href="http://roy.marples.name/cgi-bin/gitweb.cgi?p=dhcpcd.git;a=commit;h=57cd5affbff05d41497b8295986e46360f6464db">DHCPv6 INFORM support into dhcpcd</a>. This is only triggered when dhcpcd recieves an IPv6 RA with the O flag set. Luckily, I put <a href="http://roy.marples.name/cgi-bin/gitweb.cgi?p=dhcpcd.git;a=commit;h=17f851e8344b1eb60954dd439b97917ec19734fa">IPv6 RS support</a> into dhcpcd a few months ago but didn&rsquo;t feel the urge to blog about it. Well, I do now!</p>
<p>Before the end of the year, I aim to have DHCPv6 IA support triggered via IPv6 RA with the M flag set as well. Do I have any other goals? Well, all my other projects are pretty much complete. One of the reasons why I starting gaming so much is that I&rsquo;m pretty happy with the current state of affairs and anything else is just a bonus. That being said, there are a lot more DHCPv6 things to do besides IA support such as better separation between IPv4 and IPv6, moving to TAILQ lists intsead of our hand rolled and other misc stuff such as improving dhcpcd-dbus and dhcpcd-gtk.</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://roy.marples.name/blog/tags/dhcpcd" term="dhcpcd" label="dhcpcd" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/gaming" term="gaming" label="gaming" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[On the importance of MTU]]></title>
            <link href="https://roy.marples.name/blog/posts/on_the_importance_of_mtu/?utm_source=atom_feed" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://roy.marples.name/blog/posts/on_the_importance_of_mtu/</id>
            
            <published>2009-07-04T17:58:00+00:00</published>
            <updated>2009-07-04T17:58:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>So, I&rsquo;m now finally natviely IPv6 enabled :)</p>
<p>This led to an <a href="http://mail-index.netbsd.org/tech-net/2009/07/01/msg001460.html">interesting debtate about my internet connection</a>. In a nutshell my <a href="http://www.draytek.co.uk/products/vigor120.html">Drayetk Vigor 100 is broken</a>, but apparently by design. The problem is this- for IPv4 goes through my NAT whose public IP has an MTU of 1492 so Path MTU Discovery works fine. However IPv6 does not need NAT and the PPPoE interface does not have a public IPv6 and nor do the internal clients use it even it there was one. So the path MTU is 1500, which is too big for the PPPoE to handle.</p>
<p>The correct solution is to obviously terminate the IPv6 on a PPPoA connection, but only the <a href="http://www.cisco.com/en/US/products/ps6202/">Cisco 877 router</a> does this and that&rsquo;s outside of my price range, even on eBay.
One solution is to clamp the MSS on the router to 1430 so that all clients work. But this is a hack.
The best solution with my hardware is to force the MTU to 1492 for all nodes inside my network, so they share the same MTU as the PPPoE so that Path MTU Discovery works.</p>
<p>You can see this working for yourself on IPv6 now, as this site is IPv6 enabled and sits behind the PPPoE link. You&rsquo;ll need to query IPv4 servers for the address though as I don&rsquo;t yet have a glue record for IPv6, but as I&rsquo;m changing registrar that should change in a few weeks :)</p>
<p>Because of this, I&rsquo;ve made the dhcpcd default to request and use the MTU value if offered by the DHCP server. You&rsquo;ll be seeing this in dhcpcd-5.0.5 (now out). dhcpcd-5.0.6 will feature restoring the MTU correctly between leases.</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://roy.marples.name/blog/tags/dhcpcd" term="dhcpcd" label="dhcpcd" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/site" term="site" label="site" />
                             
                                <category scheme="https://roy.marples.name/blog/tags/tech" term="tech" label="tech" />
                            
                        
                    
                
            
        </entry>
    
</feed>
