April 2009 Archives

I rarely use X11 for system administration. There is one tool, however, which was always invaluable to me: xlax. Sure, there are other solutions but somehow, I got addicted to xlax ever since I was introduced to it by fellow sysadmin.

Until today, that is. I always have source on the disk since it was such a hard thing to find. I run quick xmkmf on it, and... it didn't work! However, since xlax now has a home page which explains everything about XTerm*allowSendEvents I was on right track.

But, now so fast, grasshopper!
dpavlin@llin:/rest/unix/x11/xlax2.4$ make
gcc -m32 -o xlax -g -O2 -fno-strict-aliasing       xlax.o -lXaw -lXmu -lXt -lSM -lICE -lXpm  -lXext -lX11      
xlax.o: In function `SetupInterface':
/rest/unix/x11/xlax2.4/xlax.c:173: undefined reference to `strlcpy'
collect2: ld returned 1 exit status
make: *** [xlax] Error 1
Argh. I started with Digital UNIX (called OSF/1 back then) and part of my brain which deals with minor adjustments hasn't died yet, so I decided to do quick google search for strlcpy which which has handy link to strlcpy implementation in OpenBSD. Licensing terms aside, I decided to give it a try.

After applying following patch:

diff -urw xlax2.4/Imakefile xlax2.4.strlcpy/Imakefile
--- xlax2.4/Imakefile   2008-07-31 22:18:25.000000000 +0200
+++ xlax2.4.strlcpy/Imakefile   2009-04-30 21:32:15.000000000 +0200
@@ -5,8 +5,8 @@
 #            DEFINES = -DDEBUG
             DEPLIBS = XawClientDepLibs
     LOCAL_LIBRARIES = XawClientLibs
-               SRCS = xlax.c
-               OBJS = xlax.o
+               SRCS = xlax.c strlcpy.c
+               OBJS = xlax.o strlcpy.c
 
 ComplexProgramTarget(xlax)

and quick xmkmf && make and I got it compiled.

Another trivial change was to implement automatic ssh to each host in mkxlax by adding -e 'ssh $ARGV[$i]' to system xterm line so I will have remote reminals opened by default.

And now, back to real work :-)

I'm using Subversion for most of my work as all of you well know by now. All this hype about git persuaded me to give it another try. I don't really have anything to gain doing this, since I'm using svk when I need distributed VCS, but somehow I though that git might be right solution to keep all my system configuration so I can debootstrap system checkout configuration and I'm ready to go.

I could use etckeeper to do some of this stuff, but I really didn't want integration with apt. I just wanted single (network connected and backed up) place. I already tried this with git on single machine with local repository, and it worked pretty well.

This time I tried to use git branches to track different machines. I really want a single repository, so I can merge common changes all around. However, today I got this:

root@syslog:/# git push
Counting objects: 16, done.
Compressing objects: 100% (9/9), done.
Writing objects: 100% (10/10), 1.16 KiB, done.
Total 10 (delta 0), reused 0 (delta 0)
To ssh://backup/srv/backup/
   66a2f9b..8f195f5  syslog -> syslog
 ! [rejected]        koha-dev -> koha-dev (non-fast forward)
 ! [rejected]        master -> master (non-fast forward)
error: failed to push some refs to 'ssh://backup/srv/backup/'
I have no idea why would two branches which have nothing to do with current one would disable distributed part of git. If you can't read git output, message above means that I wasn't able to commit my changes to central repository.

This is a huge show stopper for me. Half a day of googling didn't find answer for this particular git question. This makes my whole setup a big useless overhead.

This is all well and fun, but since this is second time that git ate my data I'm falling back to good old friend Subversion. At least, when in breaks, I have error messages which are somewhat useful, Subversion book which explains most operations with it (so I don't have to google for every little bit, like pushing single branch from one repository to another with git).

Don't get me wrong: git is c00l, we all know that, but it's just immature if you don't want to be git developer. If you think that I'm just old-timer which can't join all this new-age DVCS mumble-mumble, read why Google picked Mercurial instead of git as DVCS. Different story, but helpful to see that git isn't only solution to every problem

Now I just need to convert my existing git branches back into subversion. It seems that git-svn dcommit is answer, but how to really push four different git branches back into subversion I still don't know. I will probably just re-add all tracked files to clean Subversion and start all over again.

Last weeked, we had a monthly meeting of LangGang where I saw CouchDB's Futon interface running on top of git (and shell!)

This idea stuck with for a couple of days, but yesterday it just had to get out. So, I'm working on CouchDB HTTP API interface on top of Mojo.

My goal is a bit different, I really want to make Futon work on my Storable dumps on disk from WebPAC so I can get that HTTP interface which is described in architecture documentation at last...

If you want to know what's happening with CouchDB lately, subscribe to CouchDB Podcast which features latest news from CouchDB development.

Have you ever wondered how exactly LDAP groups work? Well, I did last week and here are my findings...

LDAP for Rocket Scientists description of LDAP groups was first one around which I can wrap my mind. However, it has small error so I will reproduce corrected version here:

# LDIF fragment to create group branch under root

dn: ou=groups,dc=example,dc=com
objectclass:organizationalunit
ou: groups
description: generic groups branch

# create the itpeople entry

dn: cn=itpeople,ou=groups,dc=example,dc=com
objectclass: groupofnames
cn: itpeople
description: IT security group
# add the group members all of which are 
# assumed to exist under people
member: cn=road runner,ou=people,dc=example,dc=com
member: cn=micky mouse,ou=people,dc=example,dc=com
Ok, so we need to make two objects in LDAP directory to create single group.
But, where did groupofnames came from?

Warning: rant ahead! I had idea that whole point of very strict schema checking in LDAP is to have single way of defining entities in directory. Did we got there? Let's see data from IBM Technote:

server person group
objectclassnameunique objectclass member attribute nameunique
Lotus Domino LDAP Directory organizationalPerson cn mail groupOfNames member cn description
Netscape Directory Server organizationalPerson cn mail groupOfUniqueNames uniquemember cn description
Microsoft Exchange 5.5 organizationalPerson cn mail groupOfNames member cn description
Microsoft Active Directory organizationalPerson userPrincipalName cn group member cn description

Right... I can clearly see why strict LDAP schema was good idea.

For a long time, I used combination of proxy.pac and DynamicForward in .ssh/config to enable seamless surfing over ssh tunnels. However, this time, I wanted to access university network from home DSL.

I remembered all warnings about tunneling tcp over tcp and why it is bad idea, but I really liked simplicity of reusing ssh. So, I start looking for guides to implement minimal solution like this:

client.lan                      ssh gateway             private network
eth0 192.168.1.20 <--DSL-nat--> eth0 gw.example.com
tun0 10.60.0.81 <-pointopoint-> tun0 10.60.0.80 
                                eth1 10.60.0.10 <-----> 10.60.0.0/24
It's a bit more complicated, because LAN clients have to use NAT to access private network, but that's a single line in configuration. So, let's get started...

client.lan

  1. Generate ssh key for VPN
    root@client:~# ssh-keygen -t rsa -f /root/.ssh/gw-tun0
    Generating public/private rsa key pair.
    Enter passphrase (empty for no passphrase): 
    Enter same passphrase again: 
    Your identification has been saved in /root/.ssh/gw-tun0.
    Your public key has been saved in /root/.ssh/gw-tun0.pub.
    
  2. Transfer it to server
    echo 'tunnel="0",command="/sbin/ifdown tun0;/sbin/ifup tun0"' `cat /root/.ssh/gw-tun0.pub` | \
        ssh dpavlin@gw.example.com 'sudo sh -c "cat >> /root/.ssh/authorized_keys"'
    
    If you didn't have authorized_keys on gw.example.com you will also have to fix group with:
    root@gw:~# chown root:root /root/.ssh/authorized_keys
    
  3. /etc/network/interfaces
    iface tun0 inet static
        pre-up ssh -i /root/.ssh/gw-tun0 -S /var/run/gw-tun0 -M -f -w 0:0 gw.example.com true
        pre-up sleep 5
        address 10.60.0.81
        netmask 255.255.0.0
        pointopoint 10.60.0.80
        up iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o tun0 -j MASQUERADE
        post-down ssh -S /var/run/gw-tun0 -O exit gw.example.com
    
    iptables are used to NAT all hosts on home network, so they can see whole private network and not just IPs on gw.example.com
    I also added following route to my home network gateway so that all traffic for private network will go through VPN:
    # netstat -rn
    Kernel IP routing table
    Destination     Gateway         Genmask
    10.60.0.0       192.168.1.20    255.255.0.0
    

gw.example.com

  1. /etc/ssh/sshd_config
    #PermitRootLogin yes
    PermitTunnel point-to-point
    PermitRootLogin forced-commands-only
    
  2. /etc/network/interfaces
    iface tun0 inet static
        address 10.60.0.80
        netmask 255.255.255.255
        pointopoint 10.60.0.81
        up arp -sD 10.60.0.81 eth1 pub
    
    arp entry is used to make home IP address 10.60.0.81 visible to all hosts in private network. That, together with rinetd on client.lan enabled me to tunnel connections to other hosts on my local network by creating port redirection (again, sigh!). I could have solved that with route on ssh gateway gw.example.com, but this solution leaves configuration of incomming connections on home side of link.
  3. /etc/cron.d/gw.example.com
    # monitor tun0
    */1     * * * * root    fping -q 10.60.0.81 || ( ifdown tun0 ; ifup tun0 ) | logger -t tun0
    

I already blogged about RFID readers but now I really need to replace antique 3M software with something better. So, basically, I started with specification:

User should put RFID tag on reader and get output from Koha
Nice and simple. However, readers are connected to Windows machine. And we need some way for reader to push data about new tag to browser. Hmmm... push? Sound like Comet, doesn't it?

Let's see what we need:

  1. Comet server to display page in web browser and push updates
  2. RFID reader program installable on Windows to communicate with serial port and push messages to Comet server
  3. User with a browser
Again, seems somewhat reasonable. Can perl do it? It seems it can:
  1. Meteor server provides perl comet server which required one additional file to provide integration with Koha.
    I needed comet server to deliver Koha data because of single origin security in browsers which doesn't allow me to make AJAX requests to Koha directly. On the other hand, this gave me excuse to try out HTML::Query to extract part of page which I needed on server.
    I liked this split between Koha and Comet server (even on different boxes and/or network segments), but it came with a price: every page generated in Koha took more than 2 seconds, which was just too slow for nice interactive demo. So, I implemented on-disk caching which is also really nice for debugging. In production version, requests for Koha data might be implemented as forkers (since browser uses AJAX request for it, it makes sense) or I will issue queries directly over Koha's database.
  2. Next step was to add push from my perl RFID reader to Meteor.
    This also turned out to be simple: one socket connection to Meteor, and few revisions later I had more or less following protocol which reader could push to comet server as pipe | encoded string:
    meteor( 'info', "Found reader hardware $hw_ver" );
    meteor( 'info-none-in-range' );
    meteor( 'info-in-range', join(' ',@tags));
    meteor( 'in-range', $tag );
    meteor( 'read', $tag ); 
    meteor( 'removed', $tag ); 
    
  3. I also needed web interface in browser.
    When I need to do something quickly I often turn to jQuery as long time readers of my blog already know. One additional javascript file in Meteor's public_html directory and we have a working interface.
    At first, I created JavaScript object (like hash in perl :-) to keep track of visible tags on screen. But, since each tag is div which has id set to SID of tag, it was easier (and shorter) to just use jQuery to ask DOM if there is element on page. KISS wins again...

So how does it look, you might ask? (You might want to turn volume down, because AudioSwap feature of YouTube should be really considered harmful :-)

This might help solve question is perl dead. Only if it means dead easy. it's 4k of perl code, 4k of JavaScript and 4k of CSS.

I opet... Nemirnog duha, takav kakav valjda jesam, odlučio sam se u ovoj recesiji (sic!) na promjenu posla. Nakon više od godinu dana u CARNet-u, odlučio sam se preći u novu knjižnicu Filozofskog fakulteta u Zagrebu na posao sistemskog knjižničara.

Zašto? Pogledajte video:

Trebam li još što reći? :-)

Proizvodnja: Klub Studenata Filozofskog Fakulteta, ožujak 2009.

About this Archive

This page is an archive of entries from April 2009 listed from newest to oldest.

March 2009 is the previous archive.

May 2009 is the next archive.

Find recent content on the main index or look in the archives to find all content.

Pages

  • pics
OpenID accepted here Learn more about OpenID
Powered by Movable Type 5.04