<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Smörgåsbord &#187; Tech</title>
	<atom:link href="http://smorgasbord.gavagai.nl/topics/tech/feed/" rel="self" type="application/rss+xml" />
	<link>http://smorgasbord.gavagai.nl</link>
	<description>Ambachtelijk bereide beschouwingen.</description>
	<lastBuildDate>Thu, 02 Sep 2010 08:17:45 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Thar she blows!</title>
		<link>http://smorgasbord.gavagai.nl/2010/09/thar-she-blows/</link>
		<comments>http://smorgasbord.gavagai.nl/2010/09/thar-she-blows/#comments</comments>
		<pubDate>Wed, 01 Sep 2010 21:38:37 +0000</pubDate>
		<dc:creator>Wicher</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[en_GB]]></category>
		<category><![CDATA[kaboom]]></category>
		<category><![CDATA[sheevaplug]]></category>

		<guid isPermaLink="false">http://smorgasbord.gavagai.nl/?p=1098</guid>
		<description><![CDATA[
Last night my Sheevaplug&#8217;s power supply unit blew up. Slept clean through it but I think the fumes were responsible for the unorthodox dreaming I did that night. Incidentally, the dream was about electronics. I dreamt I was part of some development project, bringing electronics to the Indian countryside and I had just invented this [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://smorgasbord.gavagai.nl/2010/09/thar-she-blows/img_1418/" rel="attachment wp-att-1099"><img src="http://smorgasbord.gavagai.nl/wp-content/uploads/2010/09/IMG_1418-300x224.jpg" alt="Blown Sheevaplug PSU" title="Blown Sheevaplug PSU" width="300" height="224" class="aligncenter size-medium wp-image-1099" /></a></p>
<p>Last night my <a href="http://en.wikipedia.org/wiki/SheevaPlug">Sheevaplug</a>&#8217;s power supply unit blew up. Slept clean through it but I think the fumes were responsible for the unorthodox dreaming I did that night. Incidentally, the dream was about electronics. I dreamt I was part of some development project, bringing electronics to the Indian countryside and I had just invented this incredibly tiny airplane which could be made from readily available components such as tins and shrubs. It could fly a route autonomously (!) and had a cargo net which could be used for transporting lumber, cattle, children &#8211; anything a farmer family would need transported. The size of a large model airplane, one was supposed to hold on to its landing gear (with one&#8217;s legs taking over landing gear functions &#8211; better bring some bandages) and enjoy the flight. So I was flying around the hot Indian plains, soldering iron tucked under my belt, spreading the tale of this quantum leap in mobility in the land of Vishnu and Sheeva.</p>
<p>Back to my Sheevaplug. It was no more. A capacitator in the power supply unit (that converts 230VAC  to 5VDC) had made a complete mess of itself. And the rest of the PSU. It looks like burnt Marshmallows but smells worse.<br />
Also, the button cell that keeps the system clock running when power is lost, had swollen to unhealthy dimensions and had barfed its contents over part of the mainboard:</p>
<p><a href="http://smorgasbord.gavagai.nl/2010/09/thar-she-blows/img_1420/" rel="attachment wp-att-1106"><img src="http://smorgasbord.gavagai.nl/wp-content/uploads/2010/09/IMG_1420-300x168.jpg" alt="Swollen AG10 button cell" title="Swollen AG10 button cell" width="300" height="168" class="aligncenter size-medium wp-image-1106" /></a></p>
<p>Well, at least <a href="http://plugcomputer.org/plugforum/index.php?topic=1734.0">I&#8217;m</a> <a href="http://www.ronketti.org.uk/toasty.jpg">not</a> <a href="http://chemicaloliver.net/electronics/sheevaplug-why-globalscale-suck/">alone</a> in getting the marshmallow treatment. It appears to be a heat issue on the first version of the development kit. </p>
<p>Amazingly, the PSU still supplied about 2V, enough to make the blue LED blink to signal me that my marshmallows were ready.</p>
<p>I keep this box with old AC/DC adapters around. I&#8217;ve adapted my Sheevaplug to contain a socket to plug in a jack from an external 5VDC 2A supply, replaced the CMOS battery, and after some initial problems with the unit losing track of time after being powered down, all is working fine again. But better not take this Sheevaplug to the scorching heat of the land of Sheeva.</p>
]]></content:encoded>
			<wfw:commentRss>http://smorgasbord.gavagai.nl/2010/09/thar-she-blows/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>OpenSSH chrooting, matching, tunneling</title>
		<link>http://smorgasbord.gavagai.nl/2010/05/openssh-chrooting-matching-tunneling/</link>
		<comments>http://smorgasbord.gavagai.nl/2010/05/openssh-chrooting-matching-tunneling/#comments</comments>
		<pubDate>Sat, 08 May 2010 16:42:27 +0000</pubDate>
		<dc:creator>Wicher</dc:creator>
				<category><![CDATA[Howto]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[chroot]]></category>
		<category><![CDATA[en_GB]]></category>
		<category><![CDATA[openssh]]></category>
		<category><![CDATA[sftp]]></category>
		<category><![CDATA[tunnel]]></category>

		<guid isPermaLink="false">http://smorgasbord.gavagai.nl/?p=1043</guid>
		<description><![CDATA[Intro &#8211; running a cluster

So I had assembled this computing cluster thing based on execnet for a CS project. The slave nodes were dozens of student lab computers. Those are running firewalls blocking all ingress traffic, not just from the big bad internet but also from the lab networks — which contain only trusted machines [...]]]></description>
			<content:encoded><![CDATA[<h2>Intro &#8211; running a cluster</h2>
<p>
So I had assembled this computing cluster thing based on <a href="http://codespeak.net/execnet/">execnet</a> for a CS project. The slave nodes were dozens of student lab computers. Those are running firewalls blocking all ingress traffic, not just from the big bad internet but also from the lab networks — which contain only trusted machines and are <em>already</em> protected by a firewall restricting flow to and from larger networks!<br />
Thing is, I need access to the SSH daemons running on those nodes. And I do not (and should not) have root on those machines&#8230;<br />
Solving this problem on <a href="http://en.wikipedia.org/wiki/Layer_8">OSI Layer-8</a> proved to be an inefficient approach. The best way to fight bureaucracy is to not take it seriously. A bureaucracy (almost by definition) is not creative and cannot keep up with workarounds. To admit existence of creative, necessary workarounds to achieve legitimate ends is to admit defeat and that is why workarounds usually get ignored. It&#8217;s ignore and counter-ignore which is a bit sad since there is (or should be) a common goal: education, in this case. But I digress. The solution proved to be to ignore layer 8 and solve the problem on OSI layer 4. That certainly saved a lot of keystrokes!<br />
To punch through the firewall, I have each slave node initiate a reverse tunnel (<code>ssh -R</code>) to a central node, using pubkey authentication. This way the otherwise unreachable SSH daemons on the slave nodes are proxied on the master node and are reachable via a socket on the master nodes&#8217; loopback interface. The slave nodes specify the reverse tunnel endpoint port based on their IP. They connect automatically, and with some clever but too-kludgy-to-show scripting I can dynamically update my running clusterfied program with newly joining slave nodes to export compute jobs to.<br />
Obviously, the slave nodes need to login to the central node via SSH and do so using a single account on the central node. But I don&#8217;t fully trust the slave nodes. I want them to be able to initiate reverse tunnels, and not do much else. Here&#8217;s how I approached this problem, with the server running OpenSSH 5.3p1.
</p>
<h2>Chroot</h2>
<p>
Chrooting comes to mind. With a chroot, you can limit the filesystem locations the user can access to some remote uninteresting branch of the tree.<br />
From <code>man 5 sshd_config</code>:</p>
<pre>
ChrootDirectory
Specifies a path to chroot(2) to after authentication.  This path, and
all its components, must be root-owned directories that are not writable
by any other user or group.  After  the  chroot,  sshd(8) changes the
working directory to the user's home directory.

The path may contain the following tokens that are expanded at runtime
once the connecting user has been authenticated: %% is replaced by a
literal '%', %h is replaced by the home directory of the user being
authenticated, and %u is replaced by the username of that user.
</pre>
<p> I set up a group for that and use the following &#8216;Match&#8217; stanza in the central node&#8217;s <code>sshd_config</code>:</p>
<pre>
Match Group chrootage
        ChrootDirectory %h
</pre>
<p><code>%h</code> is the matched user&#8217;s homedir.<br />
I set up a user named &#8216;chroot&#8217; with a not-so-regular home directory. More on that home directory later on. This user needs a <em>valid shell</em>, even if it will never run that shell (I do not want them to run one). Without a valid shell the user will not be able to log in.
</p>
<h2>ForceCommand</h2>
<p>
From <code>man 5 sshd_config</code>:</p>
<pre>
ForceCommand
Forces the execution of the command specified by ForceCommand, ignoring
any command supplied by the client and ~/.ssh/rc if present. The command
is invoked by using the user's login shell with the -c option. This
applies to shell, command, or subsystem execution.  It is most useful
inside a Match block.
The command originally supplied by the client is available in the
SSH_ORIGINAL_COMMAND environment variable. Specifying a command of
``internal-sftp'' will force the use of an in-process sftp server that
requires no support files when used with ChrootDirectory.
</pre>
<p>Well that ought to suit my purposes. Ideally, this command would be a rather boring and useless one that just sits there waiting for input. I could copy <code>cat</code> and the libs it links to over to the chroot directory. I might as well make it the login shell for the chroot user. But the user would then still be able to use sftp. And if I would want to disable sftp, I would have to do so server-wide! Me and the other users use sftp extensively, so I&#8217;d then need to run a second SSH daemon with no sftp subsystems especially for this purpose. Hmmm.<br />
Another approach is to limit the user to the internal sftp subsystem. Added benefit is that I do not need to maintain any binaries and libs in the chroot. With this, the user logging in with SSH is presented by a boring interpreter in which he cannot launch any programs — it&#8217;s the sftp subsystem. Portforwarding, which is needed for the reverse tunnel, will work. SFTP will work, obviously. Let&#8217;s do it.<br />
<code>sshd_config</code>:</p>
<pre>
Subsystem       sftp    internal-sftp

Match Group chrootage
        ChrootDirectory %h
        ForceCommand internal-sftp
</pre>
</p>
<h2>Make SFTP boring ­— chrooted home directory contents</h2>
<p>
So what do we need inside the chroot directory? No binaries or device nodes, that is one of the advantages of using the <code>internal-sftp</code> subsystem.<br />
We do need an <code>authorized_keys</code> file readable by the chrooted user since this user won&#8217;t be able to log in using pubkey auth otherwise. We can&#8217;t use <code>AuthorizedKeysFile</code> inside a <code>Match</code> stanza, so the <code>authorized_keys</code> will have to reside in the default location — the <code>.ssh</code> subdirectory of the user&#8217;s homedir. I will use <code>authorized_keys</code> to limit the set of hosts this user can login from to the domain of the slave nodes, so obviously the user should not be able to add keys or lift limitations — <code>authorized_keys</code> will need to be read-only. This is what I ended up with.</p>
<pre>
#ls -Rla /path/to/chrooted_homedir
/path/to/chrooted_homedir/:
total 16
drwxr-xr-x 3 root root       178 May  8 16:36 .
drwxrwxrwt 9 root sys       4887 May  8 16:36 ..
dr-xr-x--- 2 root chrootage  189 May  8 16:22 .ssh

/path/to/chrooted_homedir/.ssh:
total 12
dr-xr-x--- 2 root chrootage  189 May  8 16:22 .
drwxr-xr-x 3 root root       178 May  8 16:36 ..
-rw-r----- 1 root chrootage 1221 May  8 14:25 authorized_keys
</pre>
<p>This is all the user can view over sftp. It is minimal and extremely boring. Note that there is no place the user can write to. Even if he would have some way of launching programs (he hasn&#8217;t, due to <code>ForceCommand</code>) there is no place to upload them to and launch them from in the first place.<br />
On to authorized_keys:</p>
<pre>
no-pty,from="*.science.uu.nl" ssh-rsa AAAAB3and-the-rest-of-the-pubkey
</pre>
<p><code>no-pty</code> serves to prevent the allocation of a terminal. I don&#8217;t think it offers any security beyond the measures already in place, but I like to think this saves resources.
</p>
<h2>Tunneling risks</h2>
<p>
I need TCP forwarding to get the reverse tunnels to work. That means that using the account, users can set up arbitrary TCP tunnels, using the master node as a proxy&#8230; Less nice. But wait &#8211; can&#8217;t I use <code>PermitOpen</code> inside <code>Match</code> to limit the creation of arbitrary tunnels? Yes. But the reverse tunnel is subjected to the same restrictions. Therefore, I would need a PermitOpen for every slave node and I&#8217;d need to know the source port of the incoming client connection in advance. There&#8217;s no wildcarding in PermitOpen, so this is infeasable.
</p>
<h2>&#8216;Match&#8217; directive precedence</h2>
<p>
The order appears to be significant. That&#8217;s also what the manpage seems to hint at where it says</p>
<pre>
Match:
Introduces a conditional block.  If all of the criteria on the Match
line are satisfied, the keywords on the following lines override those
set in the global section of the config file, until either another Match
line or the end of the file.
</pre>
<p>It&#8217;s not as clear as could be what happens to keywords in the next Match directive. What if the next Match directive matches? Nothing! The next Match directives don&#8217;t matter! In my tests, incoming connections appeared to be only matched once. The match blocks have no relation to eachother, only to the main config.<br />
That implies that you need to put the <em>most specific</em> match directives — the ones with the most patterns ­— on top, and that each Match block needs to hold any and all keywords you want to specify beyond the main config. It&#8217;s not CSS ;-)</p>
]]></content:encoded>
			<wfw:commentRss>http://smorgasbord.gavagai.nl/2010/05/openssh-chrooting-matching-tunneling/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Social social networking with Facemix</title>
		<link>http://smorgasbord.gavagai.nl/2010/04/social-social-networking-with-facemix/</link>
		<comments>http://smorgasbord.gavagai.nl/2010/04/social-social-networking-with-facemix/#comments</comments>
		<pubDate>Fri, 16 Apr 2010 16:50:52 +0000</pubDate>
		<dc:creator>Wicher</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[WWW]]></category>
		<category><![CDATA[aprilfools]]></category>
		<category><![CDATA[en_GB]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[squid]]></category>
		<category><![CDATA[upsidedownternet]]></category>
		<category><![CDATA[url_rewrite_program]]></category>

		<guid isPermaLink="false">http://smorgasbord.gavagai.nl/?p=1007</guid>
		<description><![CDATA[It&#8217;s not too late for posts about April Fool&#8217;s Day pranks I hope?
In the tradition of the Upsidedownternet this April 1st I had some fun with Facebook addicts.
You may not be aware of the fact that any picture on facebook is publicly accessible. Yes, it is. There&#8217;s no authentication &#038; authorisation whatsoever. Handling those in [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s not too late for posts about April Fool&#8217;s Day pranks I hope?<br />
In the tradition of <a href="http://www.ex-parrot.com/pete/upside-down-ternet.html">the Upsidedownternet</a> this April 1st I had some fun with Facebook addicts.</p>
<p>You may not be aware of the fact that any picture on facebook is publicly accessible. Yes, it is. There&#8217;s no authentication &#038; authorisation whatsoever. Handling those in a scalable way would ramp up costs. Your privacy is not worth those costs. Contrary to the impression you are trying to deliver through your profile, you are not important. Happy shareholders are important!</p>
<p>Due to this fact I just need to know the URLs of your pictures. From the URL I can determine whether it&#8217;s a profile picture, profile picture thumbnail, photo, photo thumbnail, etc.</p>
<p>Wouldn&#8217;t it be fun to mix the pictures of the facebook page you are currently viewing with those from facebook pages others are viewing? So when you&#8217;re browsing your friend&#8217;s albums, you not only see his pictures but pictures from other peoples&#8217; albums too, and vice versa?<br />
The pictures may be requested by the guy across the bar, or by the girl one floor down in the library, or by anyone on the same network as you are — all of you are browsing together with the people in your physical vicinity, sharing whatever pictures you encounter! It&#8217;s beyond Facebook. It&#8217;s crowdbrowsing. It&#8217;s Megafacebook.<br />
While you may not know these newly inserted friends, you might get to. Maybe you bump into one another at the toilets, or at the counter.<br />
<i>&#8220;Why is everyone staring at me like that?&#8221;</i> you naively wonder. (They&#8217;ve seen those pictures).<br />
<i>&#8220;Does she know that I know about those pictures of her and her friends? But wait&#8230; what might she know about me?&#8221;</i>, your paranoid mind ponders.<br />
It&#8217;s all about what you think of others and what others think of you. Total absorption. Now that&#8217;s what I call social networking. All hail Facebook <b><i>Social!</i></b></p>
<p><a href="http://smorgasbord.gavagai.nl/wp-content/uploads/2010/04/FacebookSocial3.png"><img src="http://smorgasbord.gavagai.nl/wp-content/uploads/2010/04/FacebookSocial3.png" alt="Facebook Social" title="Facebook Social" width="90" height="20" class="aligncenter size-full wp-image-1009" /></a></p>
<p>Give the wifi crowd at your local coffeeshop the pleasure of learning a little bit more about eachothers lives and friends.</p>
<h3>Get to work</h3>
<p>You need:</p>
<ul>
<li>one network vulnerable to ARP poison routing (that&#8217;s most of them) or one network which you already control anyway. Make everyone route their traffic through your machine.
</li>
<li>one installment of the Nginx web server, configured with <code>--with-http_random_index_module</code>. I use the 0.8.3x series.
</li>
<li>one installment of the Squid http proxy server. I use the 3.1 series.
</li>
<li>Perl and LWP::Simple.
</li>
</ul>
<h4>Set up Nginx</h4>
<p>Create some directories to hold the images:<br />
<code><br />
mkdir /var/www/facemix/{albums,photos,photosthumb,smoelen,smoelenthumb}<br />
</code><br />
Tell Nginx to respond to requests for those directories by randomly serving one of the files in them:<br />
<code><br />
        location ~ ^/facemix/([^/]+)(/?.*)$ {<br />
                alias /var/www/facemix/$1/$2;<br />
                random_index on;<br />
                expires -1;<br />
                }<br />
</code><br />
You need the &#8216;expires -1&#8242; to avoid caching. If proxies or user agents were to cache the results, they wouldn&#8217;t be very random anymore now would they.</p>
<p>Stick some files in there and test your installation.</p>
<h4>Set up Squid</h4>
<p>Set up squid in interception mode. If you&#8217;re not NATting the routed traffic, set it to run on port 80. If Nginx is already listening on that socket, make Nginx listen on some other port, or localhost only, while running squid on port 80 but only on the external interface.</p>
<h4>Set up networking</h4>
<p>This is for iptables.</p>
<ul>
<li>You&#8217;re NATting the pwned hosts. Run something along the lines of<br />
<code>iptables -t nat -A PREROUTING -i $INTERFACE -p tcp --dport 80 -j REDIRECT --to-port 8080</code><br />
to redirect all traffic incoming on $INTERFACE and destined for port 80 to port 8080, which is where you need squid to listen on.</li>
<li>You&#8217;re doing 2-way ARP poisoning (cheers!). Run something along the lines of<br />
<code>iptables -t nat -A PREROUTING -p tcp -m tcp --dport 80 -j DNAT --to-destination $YOURIP</code><br />
Squid needs to run on port 80 on interface with IP $YOURIP.
</li>
</ul>
<p>Check Squid&#8217;s logs to verify that requests are intercepted successfully.</p>
<h4>Run the redirection script</h4>
<p>I don&#8217;t touch Perl very often, and cobbling together this script made me remember why that is. It&#8217;s very usable as a means of frightening little kids.<br />
In a nutshell, what my redirector script does is</p>
<ol>
<li>determine whether the URL fed to it by Squid is a facebook picture url;
</li>
<li>if so, and if we don&#8217;t have that picture yet, fork off to download it;
</li>
<li>point Squid to a random picture of the same type (served by Nginx).
</li>
</ol>
<p>I like the forking. I dislike the iffed regexes which could probably be condensed into one but then it wouldn&#8217;t be &#8216;cobbling together&#8217; anymore. </p>
<p>Adjust the variables for your setup and tell Squid about the script (eg <code>url_rewrite_program /usr/local/lib/facemix-squidredir.pl</code>).</p>
<p>The Facebook logo will change to reflect the fact that the users are now browsing facebook in <b><i>Social!</i></b> mode.</p>
<p>One further note: This is privacy-invasive. I brush away my moral doubts by stating that anyone who signed away their privacy rights when joining facebook AND AT THE SAME TIME entertains any expectations with respect to privacy,<br />
« inhale »<br />
&#8230; is utterly mental and has completely lost any and all sense of proportionality. If you care about privacy, why use a service which lets you view <b>any</b> picture of <b>any</b> user <i>regardless</i> of who you are? Who are you kidding?</p>
<p>If you&#8217;re still reading, here&#8217;s the script:</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/usr/bin/perl -w</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">use</span> LWP<span style="color: #339933;">::</span><span style="color: #006600;">Simple</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #0000ff;">$WEBROOT</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">'http://localhost/facemix/'</span><span style="color: #339933;">;</span>
<span style="color: #0000ff;">$WEBDIR</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">'/var/www/facemix/'</span><span style="color: #339933;">;</span>
<span style="color: #0000ff;">$CHANCE</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">5</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">#One in X requests gets mixed</span>
<span style="color: #0000ff;">$SIG</span><span style="color: #009900;">&#123;</span>CHLD<span style="color: #009900;">&#125;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">'IGNORE'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #0000ff;">$|</span><span style="color: #339933;">=</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">&lt;&gt;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">local</span> <span style="color: #0000ff;">@reqfrags</span> <span style="color: #339933;">=</span> <span style="color: #000066;">split</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/ /</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$_</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">local</span> <span style="color: #0000ff;">$url</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">@reqfrags</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span>    <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$url</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/(^http:\/\/.*.fbcdn.net\/rsrc.php\/z7VU4\/hash\/66ad7upf.png$)/</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;http://smormedia.gavagai.nl/2010/04/FacebookSocial2.png<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">elsif</span>    <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$url</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/(^http:\/\/photos-.*.fbcdn.net\/.*\/.*_n.jpg$)/</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$url</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/(^http:\/\/photos-.*.fbcdn.net\/.*\/n.*.jpg$)/</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #0000ff;">&amp;mixurl</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">'photos/'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">elsif</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$url</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/(^http:\/\/photos-.*.fbcdn.net\/.*\/.*_s.jpg$)/</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$url</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/(^http:\/\/photos-.*.fbcdn.net\/.*\/s.*.jpg$)/</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #0000ff;">&amp;mixurl</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">'photosthumb/'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">elsif</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$url</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/(^http:\/\/profile.*.fbcdn.net\/.*\/.*_n.jpg$)/</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$url</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/(^http:\/\/profile.*.fbcdn.net\/.*\/n.*.jpg$)/</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #0000ff;">&amp;mixurl</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">'smoelen/'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">elsif</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$url</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/(^http:\/\/profile.*.fbcdn.net\/.*\/.*_q.jpg$)/</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$url</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/(^http:\/\/profile.*.fbcdn.net\/.*\/q.*.jpg$)/</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #0000ff;">&amp;mixurl</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">'smoelenthumb/'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">elsif</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$url</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/(^http:\/\/photos-.*.fbcdn.net\/.*\/.*_a.jpg$)/</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$url</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/(^http:\/\/photos-.*.fbcdn.net\/.*\/a.*.jpg$)/</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #0000ff;">&amp;mixurl</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">'albums/'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">else</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$url</span><span style="color: #339933;">.</span><span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">sub</span> mixurl <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">#args: subdir, url</span>
    <span style="color: #000066;">local</span> <span style="color: #0000ff;">$vork</span> <span style="color: #339933;">=</span> <span style="color: #000066;">fork</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$vork</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #0000ff;">&amp;getit</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">int</span><span style="color: #009900;">&#40;</span><span style="color: #000066;">rand</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$CHANCE</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000066;">print</span> <span style="color: #0000ff;">$WEBROOT</span><span style="color: #339933;">.</span><span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000066;">print</span> <span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">sub</span> getit <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">#args: subdir, url</span>
    <span style="color: #000066;">local</span> <span style="color: #0000ff;">$storedir</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$WEBDIR</span><span style="color: #339933;">.</span><span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">local</span> <span style="color: #0000ff;">@urlfrags</span> <span style="color: #339933;">=</span> <span style="color: #000066;">split</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/\//</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">local</span> <span style="color: #0000ff;">$fname</span> <span style="color: #339933;">=</span> <span style="color: #000066;">pop</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">@urlfrags</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000066;">stat</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$storedir</span><span style="color: #339933;">.</span><span style="color: #0000ff;">$fname</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      getstore<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">$storedir</span><span style="color: #339933;">.</span><span style="color: #ff0000;">'._tmp-'</span><span style="color: #339933;">.</span><span style="color: #0000ff;">$fname</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000066;">rename</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$storedir</span><span style="color: #339933;">.</span><span style="color: #ff0000;">'._tmp-'</span><span style="color: #339933;">.</span><span style="color: #0000ff;">$fname</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$storedir</span><span style="color: #339933;">.</span><span style="color: #0000ff;">$fname</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000066;">exit</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://smorgasbord.gavagai.nl/2010/04/social-social-networking-with-facemix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>*Online* merging of COW volumes with dm-snapshot</title>
		<link>http://smorgasbord.gavagai.nl/2010/03/online-merging-of-cow-volumes-with-dm-snapshot/</link>
		<comments>http://smorgasbord.gavagai.nl/2010/03/online-merging-of-cow-volumes-with-dm-snapshot/#comments</comments>
		<pubDate>Sat, 20 Mar 2010 18:11:20 +0000</pubDate>
		<dc:creator>Wicher</dc:creator>
				<category><![CDATA[Howto]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[device mapper]]></category>
		<category><![CDATA[DM]]></category>
		<category><![CDATA[en_GB]]></category>
		<category><![CDATA[LVM]]></category>
		<category><![CDATA[snapshot-merge]]></category>

		<guid isPermaLink="false">http://smorgasbord.gavagai.nl/?p=981</guid>
		<description><![CDATA[Your mum told you not to touch block devices containing mounted filesystems. But today we&#8217;ll be doing exactly that. Specifically, we&#8217;re going to use the Linux Device Mapper (DM) snapshot and snapshot-merge target. To do what? To do this:

Make all reads come from one device, A
Make all writes go to another block device, B
Merge the [...]]]></description>
			<content:encoded><![CDATA[<p>Your mum told you not to touch block devices containing mounted filesystems. But today we&#8217;ll be doing exactly that. Specifically, we&#8217;re going to use the Linux Device Mapper (DM) snapshot and snapshot-merge target. To do what? To do this:</p>
<ol>
<li>Make all reads come from one device, A</li>
<li>Make all writes go to another block device, B</li>
<li>Merge the writes stored in B into A</li>
<li>Without unmounting the filesystem on A!</li>
</ol>
<p>Why? Well, as pointed out in the comments on <a href="http://lwn.net/Articles/363575/">this LWN article</a> you could use this as a way to roll back an unfortunate upgrade without taking your system offline. But if the upgrade _is_ fortunate, you might want to merge the changes back in without having to take your filesystem offline.</p>
<p>Or you could use it to speed up writes — perform those against a RAM-based block device, and merge those writes back in when sysload is low. Or use it like I&#8217;m planning on doing: to avoid the small but frequent writes (growing logfiles, mainly) to the CF card in my <a href="http://www.pcengines.ch/alix2d13.htm">Alix2</a> which I&#8217;ve built my router with.</p>
<p>#1+#2 are old hat — but if you&#8217;ve never made a writable snapshot with DM (not LVM) I strongly suggest you read the <a href="http://linuxgazette.net/114/kapil.html">&#8220;Right To Your Own Devices&#8221;</a> LinuxGazette article. It&#8217;s what got me started.</p>
<p>#3 is fairly recent hat, for &#8216;kernel 2.6.33&#8242; values of &#8220;recent&#8221;. </p>
<p>#4 is shiny new hat and is what this post will be about.</p>
<h3>Prerequisites</h3>
<p>You must be running the Linux kernel, 2.6.33+, and have device mapper support (CONFIG_DM_SNAPSHOT) loaded and ready to go. You also need a recent <a href="http://sources.redhat.com/lvm2/">LVM2 userland</a>, I used version 2.02.60.<br />
Usually one goes about snapshotting with the use of LVM, the Logical Volume Manager. LVM is just an easy high-level way of employing DM functionality for common use cases. Ours is not one of those, hence we&#8217;ll be using raw dmsetup-foo. That&#8217;s why I strongly recommend you read the LinuxGazette article mentioned before. We&#8217;ll not be revisiting DM basics.</p>
<h3>Get Dirty</h3>
<ul>
<li>
Create your base block device of about 500MB.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;"><span style="color: #000000; font-weight: bold;">if</span></span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>zero <span style="color: #007800;">of</span>=hard <span style="color: #007800;">bs</span>=1M <span style="color: #007800;">count</span>=<span style="color: #000000;">500</span>
losetup <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>loop0 hard</pre></div></div>

<p>Neat, now you have a block device which is actually a file on your file system (which is on a block device). You could mkfs and mount it, but we&#8217;re not going to, not yet. We&#8217;re going to add yet another layer of indirection: the device mapper.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #000000;">0</span> $<span style="color: #7a0874; font-weight: bold;">&#40;</span>blockdev <span style="color: #660033;">--getsize</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>loop0<span style="color: #7a0874; font-weight: bold;">&#41;</span> linear <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>loop0 <span style="color: #000000;">0</span> <span style="color: #000000; font-weight: bold;">|</span> dmsetup create hard_a</pre></div></div>

<p>You now have a <code>/dev/mapper/hard_a</code> which is a linear (not mirror, not stripe, not crypt, not anything else but plain boring linear) mapping of blocks to its underlying block device, which was <code>/dev/loop0</code>, which is backed by the file with name <code>hard</code>.
</li>
<li>
Create a device which the writes will end up on. How large should it be? You decide. If you write more data than this volume can hold, it will be dropped and all your writes will be lost. That&#8217;s what you get for bad planning! Of course, you could err on the safe side and make it huge. But I don&#8217;t think it&#8217;s of any use to make it larger than the device whose writes you want it to receive (please correct me if I&#8217;m wrong). And by making it huge, you&#8217;re wasting space. Why not have it take up exactly the amount of space it needs? Dynamically growing, so to say? With a loop device backed by a sparse file, you can! A <a href="http://en.wikipedia.org/wiki/Sparse_file">sparse file</a> is a file whose empty bytes are represented by metadata. That means they don&#8217;t actually have to be there until needed, which is on write.<br />
Let&#8217;s make a 200MB sparsely backed device to hold the writes diverted from our other device:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;"><span style="color: #000000; font-weight: bold;">if</span></span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>zero <span style="color: #007800;">of</span>=soft_a <span style="color: #007800;">bs</span>=<span style="color: #000000;">1</span> <span style="color: #007800;">count</span>=<span style="color: #000000;">0</span> <span style="color: #007800;">seek</span>=200M
losetup <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>loop1 soft_a</pre></div></div>

</li>
<li>
Now we make yet another device: <code>top</code>. This is the device we&#8217;ll be making a filesystem on. But all writes will go into the file called <code>soft</code>. That&#8217;s called a writable snapshot and you can assemble it like this:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #000000;">0</span> $<span style="color: #7a0874; font-weight: bold;">&#40;</span>blockdev <span style="color: #660033;">--getsize</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>hard_a<span style="color: #7a0874; font-weight: bold;">&#41;</span> snapshot <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>hard_a <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>loop1 p <span style="color: #000000;">8</span> <span style="color: #000000; font-weight: bold;">|</span> dmsetup create top</pre></div></div>

<p>You now have a <code>/dev/mapper/top</code> block device. Go ahead, mkfs it<a name="voednoodpunt1" href="#voednood1">[*]</a>, mount it and stick some files on it. Interestingly, you can see how many blocks (in units of bytes) you have dirtied by looking at the physical size of the &#8217;soft_a&#8217; file:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">du</span> <span style="color: #660033;">-B1</span> soft_a</pre></div></div>

</li>
<li>
Now for the magic part. Freeze the block device!</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">dmsetup <span style="color: #7a0874; font-weight: bold;">suspend</span> top</pre></div></div>

<p>All reads and writes to /dev/mapper/top will now block. Processes that were accessing the device will be in suspended animation. Really? Depends. You will observe that you can still do an <code>ls</code> on the filesystem if you&#8217;ve run one before and haven&#8217;t changed any data in the meantime. That&#8217;s because of the kernel&#8217;s caches, in this case, the dentry (directory-entry) cache. You can drop those caches (but you don&#8217;t have to) by running <code>echo 3 > /proc/sys/vm/drop_caches</code>, and after that, you will observe that an <code>ls</code> incantantion will appear to hang. Leave it like that for the moment.
</li>
<li>
Now we want to merge the dirty blocks back into <code>hard_a</code>. But if we fiddle with the constituents of <code>/dev/mapper/top</code> through DM, it will be dropped! We can&#8217;t merge dirty blocks right back into <code>/dev/mapper/hard_a</code> as DM doesn&#8217;t trust us prodding the fundaments. So we fool it by creating a second loop device <em>backed by the same file</em> as the loop device backing <code>/dev/mapper/hard_a</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">losetup <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>loop2 hard
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #000000;">0</span> $<span style="color: #7a0874; font-weight: bold;">&#40;</span>blockdev <span style="color: #660033;">--getsize</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>loop2<span style="color: #7a0874; font-weight: bold;">&#41;</span> linear <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>loop2 <span style="color: #000000;">0</span> <span style="color: #000000; font-weight: bold;">|</span> dmsetup create hard_b</pre></div></div>

<p>If you look at the output of <code>dmsetup table</code> you will notice that DM thinks hard_a and hard_b are different devices. And rightly so, because they are, but they happen to point to the same data: the file called <code>hard</code>.
</li>
<li>
Now we can merge the device that holds the dirty blocks for <code>hard_a</code> (that would be <code>/dev/loop1</code>) into <code>hard_b</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #000000;">0</span> $<span style="color: #7a0874; font-weight: bold;">&#40;</span>blockdev <span style="color: #660033;">--getsize</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>hard_b<span style="color: #7a0874; font-weight: bold;">&#41;</span> snapshot-merge <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>hard_b <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>loop1 p <span style="color: #000000;">8</span> <span style="color: #000000; font-weight: bold;">|</span> dmsetup create mergeomatic <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> dmsetup status mergeomatic</pre></div></div>

<p>You don&#8217;t have to do anything with the mergeomatic device. Just wait for it to finish merging. How do you know when it&#8217;s finished? I couldn&#8217;t figure it out so <a href="http://www.redhat.com/archives/dm-devel/2010-January/msg00101.html">I asked the dm-devel list</a>. Turns out you can use <code>dmsetup status mergeomatic</code>, its output format is <code>&lt;sectors_allocated&gt;/&lt;total_sectors&gt; &lt;metadata_sectors&gt;</code> and when the amount of sectors_allocated equals the metadata_sectors it&#8217;s finished. I looked at <code>dmsetup status</code> in my experiments but I had never seen anything but the same numbers, possibly because I/O to small loopback devices on a machine with loads of RAM will be blazing fast — writes to the backing file are cached in RAM, I guess.<br />
Done? Remove the snapshot-merge target:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">dmsetup remove mergeomatic</pre></div></div>

<li>
All that&#8217;s left is to create a new device, based on <code>/dev/mapper/hard_b</code> or its backing file. If you&#8217;re tired of COWing around you could do:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">dmsetup remove hard_b
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #000000;">0</span> $<span style="color: #7a0874; font-weight: bold;">&#40;</span>blockdev <span style="color: #660033;">--getsize</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>loop2<span style="color: #7a0874; font-weight: bold;">&#41;</span> linear <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>loop2 <span style="color: #000000;">0</span> <span style="color: #000000; font-weight: bold;">|</span> dmsetup load top</pre></div></div>

<p>And if you want to continue this trick you&#8217;d just make a fresh sparsely backed loop device and make a snapshot target out of it:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;"><span style="color: #000000; font-weight: bold;">if</span></span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>zero <span style="color: #007800;">of</span>=soft_b <span style="color: #007800;">bs</span>=<span style="color: #000000;">1</span> <span style="color: #007800;">count</span>=<span style="color: #000000;">0</span> <span style="color: #007800;">seek</span>=200M
losetup <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>loop3 soft_b
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #000000;">0</span> $<span style="color: #7a0874; font-weight: bold;">&#40;</span>blockdev <span style="color: #660033;">--getsize</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>hard_b<span style="color: #7a0874; font-weight: bold;">&#41;</span> snapshot <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>hard_b <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>loop3 p <span style="color: #000000;">8</span> <span style="color: #000000; font-weight: bold;">|</span> dmsetup load top</pre></div></div>

</li>
<li>
And now for the grand finale:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">dmsetup resume top</pre></div></div>

<p>All blocked processes will spring to life. <code>ls</code> will return a directory listing as if nothing has happened. Mission accomplished.<br />
With <code>dmsetup load</code> we swapped block devices in-flight. The mounted filesystem on <code>/dev/mapper/top</code> didn&#8217;t notice — all blocks still look the same. But both DM and we know that the blocks are somewhere else physically now. Little did DM know that <code>/dev/mapper/hard_b</code> is backed by the same physical blocks as <code>/dev/mapper/hard_a</code>.<br />
We&#8217;d better do some cleaning up then:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">dmsetup remove hard_a
losetup <span style="color: #660033;">-d</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>loop<span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #000000;">0</span>,<span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#125;</span>
<span style="color: #c20cb9; font-weight: bold;">rm</span> soft_a</pre></div></div>

</li>
</ul>
<p>This hasn&#8217;t left the toying-around phase yet. But I&#8217;m thinking about writing some wrapper scripts and doing some more testing. Maybe I should call it the &#8220;WhatwasIthinking Volume Manager&#8221; as it&#8217;s rather tricky stuff. Especially with all the write buffering on multiple levels. I messed it up more than once during testing ;-)</p>
<p><a name="voednood1" href="#voednoodpunt1">[*]</a> Not just any FS will do. Don&#8217;t use journaled filesystems. They assume their journal will be written to disk in-order. That assumption does not hold with file-backed loop devices, because on those there is yet another filesystem (and buffer layer) below it, deciding what data gets committed first.</p>
]]></content:encoded>
			<wfw:commentRss>http://smorgasbord.gavagai.nl/2010/03/online-merging-of-cow-volumes-with-dm-snapshot/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SheevaPlug hardware crypto</title>
		<link>http://smorgasbord.gavagai.nl/2010/02/sheevaplug-hardware-crypto/</link>
		<comments>http://smorgasbord.gavagai.nl/2010/02/sheevaplug-hardware-crypto/#comments</comments>
		<pubDate>Thu, 04 Feb 2010 23:25:16 +0000</pubDate>
		<dc:creator>Wicher</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[benchmark]]></category>
		<category><![CDATA[en_GB]]></category>
		<category><![CDATA[sheevaplug]]></category>

		<guid isPermaLink="false">http://smorgasbord.gavagai.nl/?p=872</guid>
		<description><![CDATA[Some quick numbers for those looking for performance figures on the CESA crypto accelerator. Like I was, since my SheevaPlug has one. From the kernel config:

CRYPTO_DEV_MV_CESA
This driver allows you to utilize the Cryptographic Engines and Security Accelerator (CESA) which can be found on the Marvell Orion and Kirkwood SoCs, such as QNAP&#8217;s TS-209.
Currently the driver [...]]]></description>
			<content:encoded><![CDATA[<p>Some quick numbers for those looking for performance figures on the CESA crypto accelerator. Like I was, since my <a href="http://en.wikipedia.org/wiki/SheevaPlug">SheevaPlug</a> has one. From the kernel config:</p>
<blockquote><p>
CRYPTO_DEV_MV_CESA<br />
This driver allows you to utilize the Cryptographic Engines and Security Accelerator (CESA) which can be found on the Marvell Orion and Kirkwood SoCs, such as QNAP&#8217;s TS-209.<br />
Currently the driver supports AES in ECB and CBC mode without DMA.
</p></blockquote>
<p>Whether the accelerator will be used depends on whether an application uses the in-kernel crypto algorithms. OpenSSL does not unless it is explicitly enabled to use a certain accelerator, such as is the case with the Via Padlock engine. So this particular engine won&#8217;t let your SSH run faster. But it will speed up device mapper crypto if you use an AES cipher.</p>
<p>Right, let&#8217;s get on with it.<br />
<code><br />
#uname -a<br />
Linux sheeva 2.6.32-gentoo-r3 #3 Thu Feb 4 23:02:42 CET 2010 armv5tel Feroceon 88FR131 rev 1 (v5l) Marvell SheevaPlug Reference Board GNU/Linux<br />
</code></p>
<p>Quick &#038; oh-so-dirty way of getting a RAM-backed block device (that is, if you don&#8217;t have swap enabled):<br />
<code><br />
#mount -t tmpfs tmpfs /mnt/tmp/<br />
#dd if=/dev/zero of=/mnt/tmp/blob bs=1M count=224<br />
#losetup /dev/loop0 /mnt/tmp/blob<br />
#cryptsetup -c aes -h sha1 -d /dev/urandom create test /dev/loop0<br />
</code><br />
First we test without CESA.<br />
<code><br />
#dd if=/dev/zero of=/dev/mapper/test bs=1M count=224<br />
234881024 bytes (235 MB) copied, 41.858 s, 5.6 MB/s<br />
</code><br />
Only 5.6 MB/s and the <code>[kcryptd]</code> kernel process is having your CPU for lunch.<br />
Enter CESA:<br />
<code><br />
#dmsetup remove test<br />
#modprobe mv_cesa<br />
#cryptsetup -c aes -h sha1 -d /dev/urandom create test /dev/loop0<br />
#dd if=/dev/zero of=/dev/mapper/test bs=1M count=224<br />
234881024 bytes (235 MB) copied, 18.0525 s, 13.0 MB/s<br />
</code><br />
13.0 MB/s and there&#8217;s a new kernel process, <code>[mv_crypto]</code>. It&#8217;s eating about three times as much CPU as <code>[kcryptd]</code>. That means it&#8217;s offloading, which is good. The results are consistent over time so let&#8217;s say there&#8217;s a 2.5-fold performance gain.<br />
The loop device setup causes some overhead. Out in the wild you&#8217;ll get about 19 MB/s writing to USB HDD. Cheers!</p>
]]></content:encoded>
			<wfw:commentRss>http://smorgasbord.gavagai.nl/2010/02/sheevaplug-hardware-crypto/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Network security 101: &#8216;Stealth mode&#8217; + ARP cache inoculation</title>
		<link>http://smorgasbord.gavagai.nl/2010/01/network-security-101-stealth-mode-arp-cache-inoculation/</link>
		<comments>http://smorgasbord.gavagai.nl/2010/01/network-security-101-stealth-mode-arp-cache-inoculation/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 19:28:48 +0000</pubDate>
		<dc:creator>Wicher</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Howto]]></category>
		<category><![CDATA[arp spoofing]]></category>
		<category><![CDATA[en_GB]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[wifi]]></category>

		<guid isPermaLink="false">http://smorgasbord.gavagai.nl/?p=820</guid>
		<description><![CDATA[There are times you need to connect to &#8216;dirty&#8217; networks such as public WiFi hotspots. Hopefully you&#8217;re ensuring that sensitive information is encapsulated in transport layer security enabled protocols such as SSL, because anyone on the same link (in the case of WiFi, that&#8217;s the air surrounding you. A vacuum will do, too, but that&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>There are times you need to connect to &#8216;dirty&#8217; networks such as public WiFi hotspots. Hopefully you&#8217;re ensuring that sensitive information is encapsulated in transport layer security enabled protocols such as SSL, because anyone on the same link (in the case of WiFi, that&#8217;s the air surrounding you. A vacuum will do, too, but that&#8217;s less common) can listen in on the traffic you&#8217;re sending. With SSL encapsulation such as HTTP over SSL (https://), your traffic can still be read — but for those who do it&#8217;s an extremely boring read because they don&#8217;t know the session key, only you and the other endpoint do. Hopefully.</p>
<p>One particularly nasty thing that can happen to you is when your machine is subverted into using the attacker&#8217;s machine as the router.  That is known as <a href="http://en.wikipedia.org/wiki/Arp_poisoning">ARP poison routing</a>. The attacker can proceed to not only read the traffic coming from your machine (which, on a shared medium, could be done anyway), or read the traffic going into your machine (again: on a shared medium, that could be done anyway), but the attacker can now also <em><strong>modify</strong></em> the traffic between you and the rest of the non-local network, e.g., the internet, in both directions. And that&#8217;s when he can really go to town with your traffic. Injecting a <a href="http://code.google.com/p/middler/">javascript keylogger</a> into all the webpages you visit. &#8216;<a href="http://hamster.erratasec.com/help/index.html">Sidejacking</a>&#8216; your sessions, so he does not even need to know your passwords, just your session cookies — which you happen to transmit with every page request.</p>
<p>All possible unless you use transport layer security, which is tamper-proof once properly set up. <em><strong>Once properly set up</strong></em>. But setting up can have problems of itself — there are ways of preventing you ever going from HTTP to HTTPS. If you know a thing or two about HTTP and SSL you&#8217;ll be <a href="http://securitytube.net/Defeating-SSL-using-SSLStrip-%28Marlinspike-Blackhat%29-video.aspx">delighted</a> to learn about</a> Moxie&#8217;s <a href="http://www.thoughtcrime.org/software/sslstrip/">very evil but very clever ways</a> of doing so.</p>
<p>Anyway, some level of security can be achieved if you tell your machine to ignore any messages sent to you from the other machines on the local network. That includes messages that will make your machine believe that the router has suddenly changed its physical address — which is quite unlikely to happen, but those messages are exactly the type of message an impersonator would send you. Of course we&#8217;d need to whitelist the routers of the network, otherwise we can&#8217;t get traffic out of it and onto other networks. DNS resolvers will need whitelisting too, unless you&#8217;re running one on your own machine (probably not).<br />
Not openly announcing your presence may also be something you wish for. If you have ever been on a network with a Mac user you have probably seen them popping up in your Zeroconf service browser as &#8220;Firstname Lastname&#8217;s iSomething&#8221;. Let&#8217;s cut down on that kind of promiscuity, too. But you should understand now that you can not actually hide unless you turn off your WiFi. Shared medium, remember?</p>
<p>I prepared a simple script to accomplish the above. I&#8217;ve used <code>ip</code> from the iproute2 package instead of sticking to old-school <code>route</code>, <code>ifconfig</code>, <code>arp</code> &#038; co. And I must say <code>ip neigh flush nud stale</code> has a poetic ring to it, <a href="http://ars.userfriendly.org/cartoons/?id=20100124">wouldn&#8217;t you agree?</a></p>
<p>Take note: this will only protect you from some kind of attacks, and only partially. An attacker has a window of opportunity between your machine getting assigned a DHCP lease and you running this script, for instance. Or maybe the access point <a href="http://www.viddler.com/explore/hak5/videos/56/">is rigged</a>. Actually all protection other than end-to-end encryption combined with mutual authentication is pretty useless on shared networks ;-)</p>
<p>Here&#8217;s the script. Linux-only. If you want to use it, get the latest version from <a href="http://smormedia.gavagai.nl/dist">my public repository</a>.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># arpshield 0.2</span>
<span style="color: #666666; font-style: italic;"># Protects against ARP poisoning and cloaks your machine for all </span>
<span style="color: #666666; font-style: italic;"># local link devices but the router(s) and the DNS server(s).</span>
<span style="color: #666666; font-style: italic;"># Whitelisting DHCP servers also works if you use the dhcpcd program</span>
<span style="color: #666666; font-style: italic;"># to obtain DHCP leases.</span>
<span style="color: #666666; font-style: italic;"># This program is of no help if your setup is already poisoned.</span>
<span style="color: #666666; font-style: italic;"># Have a look at ArpON (http://arpon.sourceforge.net/manpage.html) if</span>
<span style="color: #666666; font-style: italic;"># you need more extensive protection.</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># Needs 'ip', 'awk', 'sed', 'arptables', and 'arping' and expects</span>
<span style="color: #666666; font-style: italic;"># them on $PATH. Needs appropriate privileges (so use sudo).</span>
<span style="color: #666666; font-style: italic;"># Takes a network interface as an argument. The network interface</span>
<span style="color: #666666; font-style: italic;"># should be up and configured. If no argument is given, clear all</span>
<span style="color: #666666; font-style: italic;"># rules. Obviously you should do that before connecting to a new</span>
<span style="color: #666666; font-style: italic;"># network.</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># Copyright 2010 Wicher Minnaard (wicher@gavagai.eu)</span>
<span style="color: #666666; font-style: italic;"># License: Creative Commons Attribution-Share Alike 3.0</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Do you use dhcpcd for aquiring DHCP leases? And is it running?</span>
<span style="color: #007800;">dhcpcdLEASEFILE</span>=<span style="color: #ff0000;">&quot;/var/lib/dhcpcd-<span style="color: #007800;">${1}</span>.info&quot;</span>
<span style="color: #007800;">dhcpcdPIDFILE</span>=<span style="color: #ff0000;">&quot;/var/run/dhcpcd-<span style="color: #007800;">${1}</span>.pid&quot;</span>
<span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #660033;">-f</span> <span style="color: #800000;">${dhcpcdLEASEFILE}</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #660033;">-f</span> <span style="color: #800000;">${dhcpcdPIDFILE}</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #7a0874; font-weight: bold;">source</span> <span style="color: #800000;">${dhcpcdLEASEFILE}</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># In case you lack the luxury of dhcpcd, where is your resolv.conf?</span>
<span style="color: #007800;">RESOLV</span>=<span style="color: #ff0000;">&quot;/etc/resolv.conf&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># No user-servicable parts below this line.</span>
<span style="color: #007800;">DEV</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${1}</span>&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># I know, I know. But if your routing table contains 0.333.456.789 you have bigger problems ;-)</span>
<span style="color: #007800;">IPREGEX</span>=<span style="color: #ff0000;">&quot;\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Register</span>
<span style="color: #007800;">MACreg</span>=<span style="color: #ff0000;">&quot;&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># If not run as root, bail</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$(id -u)</span>&quot;</span> <span style="color: #000000; font-weight: bold;">!</span>= <span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;You need root privileges to modify networking parameters. Exiting.&quot;</span> <span style="color: #000000;">1</span><span style="color: #000000; font-weight: bold;">&gt;&amp;</span><span style="color: #000000;">2</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">2</span>
&nbsp;
getmac<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#123;</span>
<span style="color: #666666; font-style: italic;"># sets MAC register by IP. Sets to nil, if the MAC is not on the local link. </span>
  <span style="color: #007800;">getMAC</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>ip neigh show <span style="color: #800000;">${1}</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">awk</span> <span style="color: #ff0000;">'{print $5}'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
  <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${getMAC}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
    arping <span style="color: #660033;">-c1</span> <span style="color: #660033;">-I</span> <span style="color: #800000;">${DEV}</span> <span style="color: #800000;">${1}</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;&amp;</span><span style="color: #000000;">1</span>
    <span style="color: #007800;">getMAC</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>ip neigh show <span style="color: #800000;">${1}</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">awk</span> <span style="color: #ff0000;">'{print $5}'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
  <span style="color: #000000; font-weight: bold;">fi</span>
  <span style="color: #007800;">MACreg</span>=<span style="color: #800000;">${getMAC}</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
allow<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#123;</span>
  <span style="color: #666666; font-style: italic;"># Whitelists traffic to and from particular IP+MAC pairings and</span>
  <span style="color: #666666; font-style: italic;"># adds them to static ARP.</span>
  <span style="color: #007800;">IP</span>=<span style="color: #800000;">${1}</span>
  <span style="color: #007800;">MAC</span>=<span style="color: #800000;">${2}</span>
  <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${IP}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${MAC}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
    arptables <span style="color: #660033;">-A</span> INPUT  <span style="color: #660033;">-s</span> <span style="color: #800000;">${IP}</span> <span style="color: #660033;">--source-mac</span>      <span style="color: #800000;">${MAC}</span> <span style="color: #660033;">-j</span> ACCEPT
    arptables <span style="color: #660033;">-A</span> OUTPUT <span style="color: #660033;">-d</span> <span style="color: #800000;">${IP}</span> <span style="color: #660033;">--destination-mac</span> <span style="color: #800000;">${MAC}</span> <span style="color: #660033;">-j</span> ACCEPT
    ip neigh replace <span style="color: #800000;">${IP}</span> lladdr <span style="color: #800000;">${MAC}</span> nud permanent dev <span style="color: #800000;">${DEV}</span>
  <span style="color: #000000; font-weight: bold;">fi</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${DEV}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
  <span style="color: #666666; font-style: italic;"># whitelist the routers</span>
  <span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #660033;">-z</span> <span style="color: #800000;">${GATEWAYS}</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #007800;">GATEWAYS</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>ip route show dev <span style="color: #800000;">${DEV}</span><span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;s:.* via \(<span style="color: #007800;">${IPREGEX}</span>\).*:\1:p&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
  <span style="color: #000000; font-weight: bold;">for</span> GWIP <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #800000;">${GATEWAYS}</span>; <span style="color: #000000; font-weight: bold;">do</span>
    <span style="color: #007800;">MACreg</span>=<span style="color: #ff0000;">&quot;&quot;</span>
    getmac <span style="color: #800000;">${GWIP}</span>
    allow <span style="color: #800000;">${GWIP}</span> <span style="color: #800000;">${MACreg}</span>
  <span style="color: #000000; font-weight: bold;">done</span>
  <span style="color: #666666; font-style: italic;"># whitelist the DNS servers</span>
  <span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #660033;">-z</span> <span style="color: #800000;">${DNSSERVERS}</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #007800;">DNSSERVERS</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;s:^nameserver \(<span style="color: #007800;">${IPREGEX}</span>\):\1:p&quot;</span> <span style="color: #800000;">${RESOLV}</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
  <span style="color: #000000; font-weight: bold;">for</span> DNS <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #800000;">${DNSSERVERS}</span>; <span style="color: #000000; font-weight: bold;">do</span>
    <span style="color: #007800;">MACreg</span>=<span style="color: #ff0000;">&quot;&quot;</span>
    getmac <span style="color: #800000;">${DNS}</span>
    allow <span style="color: #800000;">${DNS}</span> <span style="color: #800000;">${MACreg}</span>
  <span style="color: #000000; font-weight: bold;">done</span>
  <span style="color: #666666; font-style: italic;"># if using dhcpcd, we can whitelist the DHCP server too</span>
  <span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #660033;">-n</span> <span style="color: #800000;">${DHCPSID}</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> getmac <span style="color: #800000;">${DHCPSID}</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> allow <span style="color: #800000;">${DHCPSID}</span> <span style="color: #800000;">${MACreg}</span>
  <span style="color: #666666; font-style: italic;"># set default policy to DROP    </span>
  arptables <span style="color: #660033;">-P</span> INPUT DROP
  arptables <span style="color: #660033;">-P</span> OUTPUT DROP
  <span style="color: #666666; font-style: italic;"># clear out non-hardcoded ARP cache entries</span>
  ip neigh flush nud reachable
  ip neigh flush nud stale
<span style="color: #000000; font-weight: bold;">else</span>
  <span style="color: #666666; font-style: italic;"># No argument given, so clean up.</span>
  arptables <span style="color: #660033;">-F</span>
  arptables <span style="color: #660033;">-P</span> INPUT ACCEPT
  arptables <span style="color: #660033;">-P</span> OUTPUT ACCEPT
  ip neigh flush nud permanent
<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://smorgasbord.gavagai.nl/2010/01/network-security-101-stealth-mode-arp-cache-inoculation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SOCAT: access your X server&#8217;s domain socket over TCP</title>
		<link>http://smorgasbord.gavagai.nl/2010/01/socat-access-your-x-servers-domain-socket-over-tcp/</link>
		<comments>http://smorgasbord.gavagai.nl/2010/01/socat-access-your-x-servers-domain-socket-over-tcp/#comments</comments>
		<pubDate>Sun, 10 Jan 2010 18:09:11 +0000</pubDate>
		<dc:creator>Wicher</dc:creator>
				<category><![CDATA[Howto]]></category>
		<category><![CDATA[en_GB]]></category>
		<category><![CDATA[socat]]></category>
		<category><![CDATA[X11]]></category>
		<category><![CDATA[xauth]]></category>
		<category><![CDATA[xhost]]></category>

		<guid isPermaLink="false">http://smorgasbord.gavagai.nl/?p=761</guid>
		<description><![CDATA[Access remote X11 servers that have their TCP socket disabled
This happens to me regularly. Someone brings a machine along and I want to display some app, running on my machine, on their display. Networked X11 to the rescue, you say? No, their X11 server is started with &#8216;-nolisten TCP&#8217; wich is the default on most [...]]]></description>
			<content:encoded><![CDATA[<h3>Access remote X11 servers that have their TCP socket disabled</h3>
<p>This happens to me regularly. Someone brings a machine along and I want to display some app, running on my machine, on their display. Networked X11 to the rescue, you say? No, their X11 server is started with &#8216;-nolisten TCP&#8217; wich is the default on most modern Linux distros. Sadly, the TCP socket can&#8217;t be enabled &#8216;in-flight&#8217; — if you decide you <strong>do</strong> fancy a TCP socket after all, you&#8217;ll have to restart your X server which may be a pain if you&#8217;re in the middle of something (besides, restarting is just plain uncool).<br />
But there is a way to expose the Unix domain socket as a TCP socket, with the help of <a href="http://www.dest-unreach.org/socat/">socat</a>. The following examples all use bash, so if you run a different shell (if you don&#8217;t know, you probably aren&#8217;t) you may need to define environment variables differently.</p>
<h4>Braindead Proof of Concept (BPOC)</h4>
<p>Situation: You want to display an application running on a machine called <code>w00t</code> on another machine, called <code>bling</code>. There&#8217;s an X11 server running on bling, but it&#8217;s not configured to listen on any TCP socket. DNS is properly setup, so if you ping w00t from bling, you get replies from bling&#8217;s IP, and vice versa.</p>
<ol>
<li>On bling, find the domain socket of bling&#8217;s X11 server. Have a look in <code>/tmp/.X11-unix/</code>. The socket&#8217;s name usually reflects its X server display number (which you can determine by running <code>echo $DISPLAY</code> in an xterm).</li>
<li>On bling, run something along the lines of<br />
<code>socat TCP-LISTEN:6066 UNIX-CONNECT:/tmp/.X11-unix/X0</code><br />
This will open up TCP port 6066 on all of bling&#8217;s network interfaces, connecting it to the Unix domain socket of the X server.</li>
<li>In an xterm on bling, run <code>xhost +</code>. You have now opened up your X11 server to the whole wide world, a silly thing to do. Anyone with access to the TCP socket can now read your keystrokes, read your window contents, click your mouse buttons&#8230;</li>
<li>In an xterm on w00t, run <code>DISPLAY="bling:66" xclock</code>. You may have noticed that 66 = 6066 &#8211; 6000 and indeed, by convention the TCP port number for a certain display is its display number + 6000. Anyhow&#8230;. yay, a clock! It&#8217;s displayed on bling, but running on w00t.</li>
</ol>
<h4>Improvements</h4>
<ul>
<li>You may have noticed that in the BPOC, you can use the display on bling only once. <code>socat</code> will allow only one client, and will exit once that client exits. In some situations, you may consider that a feature (it&#8217;s a one-time access grant), but in others you may not. If you want a reusable TCP socket, run something along the lines of<br />
<code>socat TCP-listen:6066,fork,reuseaddr UNIX-CONNECT:/tmp/.X11-unix/X0</code> which forks off a socat process for every TCP connection.
</li>
<li>You may not want to expose a TCP socket on all interfaces. Maybe you only want to expose a socket on the LAN interface, or on the localhost interface (and wrap the packets in an SSH tunnel). Well, you can, using the &#8216;bind&#8217; option:<br />
<code>socat TCP-LISTEN:6066,bind=localhost UNIX-CONNECT:/tmp/.X11-unix/X0</code><br />
Now tunnel it over SSH. On w00t, run <code>ssh -L 6011:localhost:6023 bling</code>. Now localhost:6011 on woot is actually localhost:6023 on bling which is actually /tmp/.X11-unix/X0 on bling. So on w00t you can  start an xclock with its display on bling by running <code>DISPLAY="localhost:11" xclock</code>.
</li>
<li><code>xhost +</code> from the BPOC is braindead indeed. There are a couple things you could have done instead, there are good ways of tightening up your authorization scheme.
<ul>
<li>First off, you don&#8217;t really need to run <code>xhost +</code> if you properly set up X11 cookies, which you should. <a href="http://tldp.org/HOWTO/Remote-X-Apps-6.html#ss6.2">Here are some examples on using the xauth scheme</a>, but take note: <code>xauth generate</code> will probably not work on recent X11 releases since the XSECURITY extension is disabled by default. Just use the same cookies on the client and the server.
</li>
<li>Run <code>xhost +w00t</code>. That&#8217;s host-based authentication, which is stupid, but not as stupid as no authorization at all. Any user on w00t can now connect.
</li>
<li>Suppose that on bling (of course!) you&#8217;d run <code>xhost +SI:localuser:theuser</code> with &#8216;theuser&#8217; being the userID of the unix-user running the socat instance. Now from the point of view of the X server, any client connecting through socat will be coming from &#8216;theuser&#8217; and will therefore be allowed access. Entertaining, but not much different from just running <code>xhost +</code>. It is something to keep in mind though! Many distros by default add the unix-user that started the X server to the authorization list. That user does not need a cookie. If you run socat as that user you will have the effect of running <code>xhost +</code> even if you run <code>xhost -</code>.
</li>
<li>Just run a nested X11 server, such as Xnest or Xephyr. This way you put untrusted users in a sandbox, preventing them from snooping your keyboard and windows. It&#8217;s the X11 equivalent of a chroot.
</li>
</ul>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://smorgasbord.gavagai.nl/2010/01/socat-access-your-x-servers-domain-socket-over-tcp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Paste the X selection buffer with a keyboard shortcut</title>
		<link>http://smorgasbord.gavagai.nl/2009/12/paste-the-x-selection-buffer-with-a-keyboard-shortcut/</link>
		<comments>http://smorgasbord.gavagai.nl/2009/12/paste-the-x-selection-buffer-with-a-keyboard-shortcut/#comments</comments>
		<pubDate>Thu, 10 Dec 2009 19:02:14 +0000</pubDate>
		<dc:creator>Wicher</dc:creator>
				<category><![CDATA[Howto]]></category>
		<category><![CDATA[clipboard]]></category>
		<category><![CDATA[en_GB]]></category>
		<category><![CDATA[X11]]></category>

		<guid isPermaLink="false">http://smorgasbord.gavagai.nl/?p=728</guid>
		<description><![CDATA[Here&#8217;s a trick. Many laptop trackpads lack a middle mouse button. On a regular mouse input device, the middle mouse button is the scroll wheel, and when you press it down it emits a button event. In X11 this button event is used to paste the X selection buffer into the position right beneath the [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a trick. Many laptop trackpads lack a middle mouse button. On a regular mouse input device, the middle mouse button is the scroll wheel, and when you press it down it emits a button event. In X11 this button event is used to paste the X selection buffer into the position right beneath the cursor (<a href="/2009/12/windowsmac-focus-models-and-copy-pasting-doing-it-wrong-both-of-you/">there lies sublime usability in this simple fact</a>).<br />
You can emulate a middle-mouse-button event by pressing the left and right mouse buttons at the same time. Since I lack the manual dexterity to do this on my tiny netbook trackpad I wanted to be able to do middle-mouse-button-paste <b>with my keyboard</b>. Well, that appeared to be easy to accomplish with the X11 Xtest extension for which the <a href="http://hoopajoo.net/projects/xautomation.html">Xautomation</a> collection includes a utility in the form of <code>xte</code>. If you&#8217;d enter <code>xte 'mouseclick 2'</code> in a terminal (within an X11 session, of course), you&#8217;d get the same effect as if you&#8217;d just pressed the middle mouse button. Only thing left is to add a keyboard shortcut to run this command; in my favourite window manager, XFCE, this can be done clickwise via the Settings Manager or simply by running something like <code>xfconf-query -c xfce4-keyboard-shortcuts -p '/commands/custom/&lt;Super&gt;v' -s "xte 'mouseclick 2'"</code>. I can now paste my X selection buffer by pressing the funny &#8216;four-wobbly-squares key&#8217; and &#8216;v&#8217; simultaneously.</p>
]]></content:encoded>
			<wfw:commentRss>http://smorgasbord.gavagai.nl/2009/12/paste-the-x-selection-buffer-with-a-keyboard-shortcut/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Windows/Mac focus models and copy-pasting: Doing it wrong, both of you</title>
		<link>http://smorgasbord.gavagai.nl/2009/12/windowsmac-focus-models-and-copy-pasting-doing-it-wrong-both-of-you/</link>
		<comments>http://smorgasbord.gavagai.nl/2009/12/windowsmac-focus-models-and-copy-pasting-doing-it-wrong-both-of-you/#comments</comments>
		<pubDate>Thu, 10 Dec 2009 18:47:54 +0000</pubDate>
		<dc:creator>Wicher</dc:creator>
				<category><![CDATA[Rants]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[clipboard]]></category>
		<category><![CDATA[en_GB]]></category>
		<category><![CDATA[sloppy focus]]></category>
		<category><![CDATA[usability]]></category>
		<category><![CDATA[X11]]></category>

		<guid isPermaLink="false">http://smorgasbord.gavagai.nl/?p=731</guid>
		<description><![CDATA[Today we talk usability. Specifically, desktop interaction differences between the X11 windowing system and the windowing systems that come with those operating systems you can actually buy in a shop downtown.
Select &#8211; Copy &#8211; Positionyourcursor &#8211; Paste
Say I&#8217;d like to copy some text from some window (which may or may not have the input focus) [...]]]></description>
			<content:encoded><![CDATA[<p>Today we talk usability. Specifically, desktop interaction differences between the X11 windowing system and the windowing systems that come with those operating systems you can actually buy in a shop downtown.</p>
<h3>Select &#8211; Copy &#8211; Positionyourcursor &#8211; Paste</h3>
<p>Say I&#8217;d like to copy some text from some window (which may or may not have the input focus) into some other window (which also may or may not have input focus). This action is commonly called &#8216;copy-paste&#8217;. Copy-paste. That sounds like two steps, doesn&#8217;t it?<br />
Let&#8217;s say both windows are visible on the current desktop. Outside the of the X11 world &#8211; say, on a Windows machine, you&#8217;d have to undertake the following steps:</p>
<ol>
<li>Drag-select the text in the first window.</li>
<li>Press ctrl-c or click edit/copy.</li>
<li>In the second window, click the position you where you want the text to be inserted.</li>
<li>Paste the text with ctrl-v or edit/paste.</li>
</ol>
<p>This is not &#8220;copy-paste&#8221;. This is &#8220;select-copy-positionyourcursor-paste&#8221;. Here&#8217;s how you do it on X11:</p>
<ol>
<li>Drag-select the text in the first window.</li>
<li>Hover over (you don&#8217;t need to click<a name="voednoodpunt1" href="#voednood1">[*]</a>) the position you want the text to be inserted at in the second window and paste by clicking with the middle mouse button.</li>
</ol>
<p>There. Copy-paste. There are two atomic actions involved with that. You can&#8217;t get this down to less than two. You need to specify <b>what</b> you want to copy, and you need to specify <b>where</b> you want to paste it. The X11 engineers understood this. I entertain the thought that they must have valued my time as well, put two and two together, and that this why we have the X selection buffer on X11<a name="voednoodpunt2" href="#voednood2">[**]</a> that makes copy-paste really copy-paste.<br />
(Read the footnote. I will show that not all is smooth in X11-land with respect to clipboards.)</p>
<h3>Window focus</h3>
<p>Whenever I venture out of X11-land there&#8217;s something else I dearly miss. It&#8217;s the ability of an inactive window to receive cursor input events when the cursor is on top of it. It&#8217;s immensely useful. Consider the following scenario.<br />
Let&#8217;s say you&#8217;re browsing the web and you stumble upon a page which you want to discuss with a friend. It&#8217;s a long page, so there&#8217;s going to be some scrolling. You open up an instant messaging window to chat with your friend. You&#8217;re short on screen real estate so the IM window partly occludes the browser window. Meaning the IM window is on top of the browser window.<br />
What you want to do now is to scroll occluded pieces of webpage text into view. But you also want to continue to see what you&#8217;re friend is saying. <b>On Windows, you simply cannot</b>. If you want to scroll the browser window, you&#8217;ll have to activate it, which means it will be raised, which means it will be above your IM window, which means you cannot see what your friend is typing. <b>On X11, you can<a name="voednoodpunt1" href="#voednood1">[*]</a></b>. If your mouse cursor is over the browser window you can use the scroll wheel to scroll text into view, without the browser window being raised. Meaning your IM window is still on top, meaning you can still see what your friend is telling you. In fact, the IM window still has input focus so you can scroll the browser window <b>and</b> continue typing messages to your friend, limited only by your manual dexterity.<br />
<a name="voednoodpunt3" href="#voednood3">[Update: Added video to illustrate Windows behaviour][***]</a></p>
<h3>Extravagance</h3>
<p>If you think these situations are exotic, here&#8217;s and extravagant example for you. Open a file browser (Windows Explorer) window. Expand some folder trees in the left pane until you get a scroll bar in this pane. Navigate to a folder which has a lot of files (C:\Windows will do nicely) so the file pane also receives a scroll bar. You now have two panes, both with a scroll bar, within the same application. Thing is, you can only scroll in one of them at the time! If you want to look around in a &#8220;non-active&#8221; <i>folder pane</i>, you first have to click it. But don&#8217;t just click anywhere! You have to take special care to click it somewhere that doesn&#8217;t change your view in the <i>file pane</i> — better not click (near) one of the folders! Now suppose you&#8217;d like to scroll some files in the file pane into view. Better &#8220;activate&#8221; the file pane first then. Again, take extra special care: don&#8217;t just click anywhere in the file pane because then you may lose any previously made selection. It&#8217;s perverse, it really is. This is all happening inside <u>one single application window</u>. And the folder pane actually <b>does</b> notice when I hover over it (it underlines folders) so why can&#8217;t I scroll the view, then? Perverse. The OS is wasting my time.</p>
<h3>Sloppy focus on Windows</h3>
<p>I remember activating this on Windows 95 and it appears it still works. You can have crude &#8217;sloppy focus&#8217; on Windows. <a href="http://bogomip.net/blog/2008/09/08/sloppy-focus-in-windows/">Just hex-edit your UserPreferencesMask</a> in the Registry</a> (Half of the times that I&#8217;m doing anything remotely interesting on Windows, I find myself entering hex values. Why is that.).<br />
Refreshing as this may be, this will not help you with any of the above scenarios:</p>
<ul>
<li>In the copy-paste scenario, you still can&#8217;t specify insertion position and insert into that position in one single action.</li>
<li>In the IM-while-browsing scenario, your IM window loses input focus when you scroll the web page in the browser window.</li>
<li>Windows Explorer cursor behaviour stays just as perverse as it was with the standard click-to-focus model.</li>
</ul>
<p>But hey, at least Windows users have <b>some</b> choice (provided they understand regedit.exe and hex). On OS-X, <a href="http://jeremy.zawodny.com/blog/archives/000149.html">you don&#8217;t have a choice at all</a> because Apple understands usability better than you do. For instance, Apple knows you head will explode if they&#8217;d give you the option of resizing your application windows by pulling any border or corner. You know very well that you will only want to resize your windows by grabbing the bottom right corner and will thank Apple for protecting you against yourself. (No, you&#8217;re not allowed to rebut until you&#8217;ve read and understand <a href="http://steve-yegge.blogspot.com/2008/04/settling-osx-focus-follows-mouse-debate.html">this mountain of insight and humour</a>.)</p>
<h3>Footnotes</h3>
<p><a name="voednood1" href="#voednoodpunt1">[*]</a> Actually, this is dependent on the focus policy. X11 itself does not specify the focus policy. X11 strives to provide mechanism, not policy. Policy is implemented by the window manager, and there are many window managers available for X11. A couple of them provide a &#8216;click to focus&#8217; policy. Many of them provide &#8217;sloppy focus&#8217; and/or &#8216;focus follows mouse&#8217; policies. <a href="http://people.cs.uchicago.edu/~ahiorean/ahwm/sloppy-focus.html">This page</a> has some concise definitions and elaborates on focus problems encountered the different models.</p>
<p><a name="voednood2" href="#voednoodpunt2">[**]</a> Most window managers also have a &#8216;clipboard&#8217;, running in parallel with the X selection buffer. The clipboard only holds stuff you put there explicitly, whereas the X selection buffer holds whatever text you last selected anywhere in the X11 session. Furthermore, both clipboards usually only accept character data. So if you select and copy some pixels in drawing program A, you can&#8217;t paste them in drawing program B. Program A will have a private clipboard to hold pixel data, and B has one of its own, too. If you stay within the realm of one particular desktop environment with applications specific to this desktop environment, you may actually be able to use the clipboard inter-applicationwise for both text and binary data. But in general, you can&#8217;t. This plurality confuses the hell out of newcomers. </p>
<p><a name="voednood3" href="#voednoodpunt3">[***]</a>A video demonstrating the Windows scroll focus issue:<br />
<img longdesc="http://smormedia.gavagai.nl/2010/03/winfocussnafu.ogv" style="display: block; margin-left: auto; margin-right: auto;" width="400" height="368" src="http://smorgasbord.gavagai.nl/wp-content/plugins/embedtheora/vid_play_thumb.png" onClick="insertVid(this);"/></p>
]]></content:encoded>
			<wfw:commentRss>http://smorgasbord.gavagai.nl/2009/12/windowsmac-focus-models-and-copy-pasting-doing-it-wrong-both-of-you/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
<enclosure url="http://smormedia.gavagai.nl/2010/03/winfocussnafu.ogv" length="1378284" type="video/ogg" />
		</item>
		<item>
		<title>LIRC plugin for Exaile</title>
		<link>http://smorgasbord.gavagai.nl/2009/12/lirc-plugin-for-exaile/</link>
		<comments>http://smorgasbord.gavagai.nl/2009/12/lirc-plugin-for-exaile/#comments</comments>
		<pubDate>Wed, 09 Dec 2009 01:44:58 +0000</pubDate>
		<dc:creator>Wicher</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[en_GB]]></category>
		<category><![CDATA[exaile]]></category>
		<category><![CDATA[lirc]]></category>
		<category><![CDATA[lircaile]]></category>
		<category><![CDATA[remote]]></category>

		<guid isPermaLink="false">http://smorgasbord.gavagai.nl/?p=718</guid>
		<description><![CDATA[Just finished up a 0.1 version of a LIRC (Linux Infrared Control) plugin for the Exaile media player. Now you can use your remote with Exaile efficiently. The plugin is in the public repository and is called Lircaile.
I haven&#8217;t touched Python much as of yet, but I&#8217;m pleased with it: it appears to be a [...]]]></description>
			<content:encoded><![CDATA[<p>Just finished up a 0.1 version of a <a href="http://lirc.org">LIRC</a> (Linux Infrared Control) plugin for the <a href="http://exaile.org/">Exaile media player</a>. Now you can use your remote with Exaile efficiently. The plugin is in <a href="http://smormedia.gavagai.nl/dist/">the public repository</a> and is called Lircaile.<br />
I haven&#8217;t touched Python much as of yet, but I&#8217;m pleased with it: it appears to be a consistent language. Well, here&#8217;s my 0.1 effort. I desperately wanted to have some fun with introspection, but I have the feeling the nested exception logic is a bit&#8230; unusual.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># A LIRC plugin for Exaile. Depends on pylirc from http://sourceforge.net/projects/pylirc/</span>
<span style="color: #808080; font-style: italic;"># Copyright (C) 2009 Wicher Minnaard, http://smorgasbord.gavagai.nl / wicher@gavagai.eu</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># This program is free software: you can redistribute it and/or modify</span>
<span style="color: #808080; font-style: italic;"># it under the terms of the GNU General Public License as published by</span>
<span style="color: #808080; font-style: italic;"># the Free Software Foundation, either version 3 of the License, or</span>
<span style="color: #808080; font-style: italic;"># (at your option) any later version.</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> xl <span style="color: #ff7700;font-weight:bold;">import</span> playlist, player, event
<span style="color: #ff7700;font-weight:bold;">import</span> pylirc, <span style="color: #dc143c;">logging</span>
&nbsp;
LIRCAILE = <span style="color: #008000;">None</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> enable<span style="color: black;">&#40;</span>exaile<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#40;</span>exaile.<span style="color: black;">loading</span><span style="color: black;">&#41;</span>:
        event.<span style="color: black;">add_callback</span><span style="color: black;">&#40;</span>_enable, <span style="color: #483d8b;">'exaile_loaded'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        _enable<span style="color: black;">&#40;</span><span style="color: #008000;">None</span>, exaile, <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> _enable<span style="color: black;">&#40;</span>eventname, exaile, nothing<span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">global</span> LIRCAILE
  LIRCAILE = Lircaile<span style="color: black;">&#40;</span>exaile<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> disable<span style="color: black;">&#40;</span>exaile<span style="color: black;">&#41;</span>:
  pylirc.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Lircaile<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
  <span style="color: #ff7700;font-weight:bold;">def</span> polLirc<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Pops all queued signals off of the LIRC queue and hands them to
    handleCode() for further processing.&quot;&quot;&quot;</span>
    gopoll = <span style="color: #008000;">True</span>
    <span style="color: #ff7700;font-weight:bold;">while</span><span style="color: black;">&#40;</span>gopoll<span style="color: black;">&#41;</span>:
      <span style="color: #dc143c;">code</span> = <span style="color: black;">&#40;</span>pylirc.<span style="color: black;">nextcode</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
      <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#40;</span><span style="color: #dc143c;">code</span><span style="color: black;">&#41;</span>:
        comval = <span style="color: #dc143c;">code</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span>comval<span style="color: black;">&#41;</span> == <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>:
          <span style="color: #008000;">self</span>.<span style="color: black;">handleCode</span><span style="color: black;">&#40;</span>comval<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>          
        <span style="color: #ff7700;font-weight:bold;">else</span>:
          <span style="color: #008000;">self</span>.<span style="color: black;">handleCode</span><span style="color: black;">&#40;</span>comval<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>, comval<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
      <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #808080; font-style: italic;"># We're done, the queue is empty.</span>
        gopoll = <span style="color: #008000;">False</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span>
&nbsp;
&nbsp;
  <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, exaile<span style="color: black;">&#41;</span>:
    <span style="color: #008000;">self</span>.<span style="color: black;">exaile</span> = exaile
    <span style="color: #008000;">self</span>.<span style="color: black;">logger</span> = <span style="color: #dc143c;">logging</span>.<span style="color: black;">getLogger</span><span style="color: black;">&#40;</span>__name__<span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">socket</span> = pylirc.<span style="color: black;">init</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'lircaile'</span><span style="color: black;">&#41;</span>
    event.<span style="color: black;">EventTimer</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0.05</span>, <span style="color: #008000;">self</span>.<span style="color: black;">polLirc</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
  <span style="color: #ff7700;font-weight:bold;">def</span> handleCode<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, command, <span style="color: #66cc66;">*</span>arg<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Takes LIRC signals and uses introspection to try to find appropriate 
    exaile functions to call based on the name of the signal. &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#40;</span>command == <span style="color: #483d8b;">'chvol'</span><span style="color: black;">&#41;</span>:
      <span style="color: #008000;">self</span>.<span style="color: black;">exaile</span>.<span style="color: black;">player</span>.<span style="color: black;">set_volume</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">exaile</span>.<span style="color: black;">player</span>.<span style="color: black;">get_volume</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> + <span style="color: #008000;">float</span><span style="color: black;">&#40;</span>arg<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
      func = <span style="color: #008000;">None</span>
      <span style="color: #808080; font-style: italic;"># Look for a matching playlist function</span>
      <span style="color: #ff7700;font-weight:bold;">try</span>:
        func = <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">exaile</span>.<span style="color: black;">queue</span>, command<span style="color: black;">&#41;</span>
      <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">AttributeError</span>:
        <span style="color: #808080; font-style: italic;"># No? Then look for a matching player function</span>
        <span style="color: #ff7700;font-weight:bold;">try</span>:
          func = <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">exaile</span>.<span style="color: black;">player</span>, command<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">AttributeError</span>:
          <span style="color: #808080; font-style: italic;"># No? Then we're out of options</span>
          <span style="color: #008000;">self</span>.<span style="color: black;">logger</span>.<span style="color: black;">warning</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'No function to handle &quot;'</span>+ command +<span style="color: #483d8b;">'&quot; LIRC event'</span><span style="color: black;">&#41;</span>
      <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">callable</span><span style="color: black;">&#40;</span>func<span style="color: black;">&#41;</span>:
        func<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://smorgasbord.gavagai.nl/2009/12/lirc-plugin-for-exaile/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
