Uncategorized

Compiling profanity for raspbian

Install dependencies:

1
sudo apt-get install libncurses5-dev libncursesw5-dev libxml2-dev

Compile and install libstrophe:

1
2
3
4
5
6
7
8
9
mkdir ~/.local
mkdir ~/src
cd ~/src
git clone https://github.com/strophe/libstrophe
cd libstrophe
./bootstrap.sh
./configure --with-libxml2 --prefix=$HOME/.local/
make
make install

Compile and install profanity:

1
2
3
4
5
6
cd ~/src
git clone https://github.com/boothj5/profanity.git
cd profanity
LDFLAGS=-L$HOME/.local/lib CPPFLAGS=-I$HOME/.local/include ./configure --prefix=$HOME/.local
make
make install

Run it:

1
LD_LIBRARY_PATH=$HOME/.local/lib $HOME/.local/bin/profanity

Automating FTP with a Non-Interactive FTP Client

Sometimes FTP has to be used to transfer files instead of one of the more secure alternatives, like SCP. Since the FTP client ftp only supports interactive mode, it can be hard to automate when being called from a script.

The script below is used — almost — the same way as a the scp command is. Its first arguments are files to be copied, and the final argument is the FTP address to send them to, similar to the URI used with scp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/bin/bash
if [ $# -lt 2 ]; then
echo Usage: $(basename $0) SOURCE... USERNAME:PASSWORD@HOST:DEST_DIR
exit 1
fi
from=${@: 1:$(($#-1))}
dest=${@: -1:1}
read user password host path <<< $(echo $dest | sed -n 's/^\([^:]*\)\(:\(.*\)\)\?@\([^:]*\)\(:\(.*\)\)\?$/\1 \3 \4 \6/p')
[ "$path" == "" ] && path=.
[ "$user" == "" ] && user=anonymous && password=none
put_commands=""
for f in $from; do
[ ! -f $f ] && echo File does not exist: $f && exit 1
put_commands=$put_commands$'\nput '$f' '$(basename $f)
done
ftp -inv <<EOF
open $host
user $user $password
binary
cd $path
$put_commands
bye
<<EOF

JavaScript: List Directory Contents With Apache Indexes

This can be useful if you are writing something that is entirely client-side and has to list the contents of directories on the web server. The only limitations are that:

  • the web server has to be running Apache with directory indexes enabled;
  • the directory to list has an index (e.g. there is no ‘index.html’ file in it); and
  • the directory to list has to be on the same domain as the script (browser security policies don’t allow cross site requests).
    Here is the code. It uses JQuery to make a AJAX request to the Apache directory index, and then parses it for links to the directory’s contents.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/*
 * Returns a list of the files in 'path' to the callback:
 * cb(error, ['file1', 'file2', ...])
 */
function apacheIndexList(path, cb) {
  $.ajax({
    url: path,
    success: function(data) {
      /* Sanity check: is this an Apache directory index?
       */
      data = $('<html>').html(data);
      if($('title', data)[0].innerHTML.substr(0, 8) !==
        "Index of")
        return cb("Bad Apache directory index: " + path);
      /* Get all the hrefs after the "Parent Directory"
       * link: these are the contents of the directory.
       */
      var passedParentLink = false;
      var files = $('a', data).filter(function(i, a) {
        if(passedParentLink)
          return true;
        if(a.innerHTML.trim() === "Parent Directory")
           passedParentLink = true;
        return false;
      });
      var tidied = $(files).map(function(i, a) {
        if(a.href.substr(-1) === '/')
            return a.href.split('/').slice(-2,-1) + '/';
        return a.href.split('/').pop();
      });
      cb(null, tidied);
    },
    error: function(jqXHR, error, errorThrown) {
      cb(error);
    }
  });
}

This can be tested on the console. First define a function ls:

1
2
3
4
5
6
function ls(d) {
apacheIndexList(d, function(e, l) {
if(e) throw e;
else console.log(l);
});
}

Then try listing the contents of some directories:

1
2
3
4
5
6
7
> ls('images/')
&lt; undefined
["img1.jpg", "img2.jpg", "img3.jpg", "thumbs/"]
> ls('images/thumbs/')
&lt; undefined
["img1.jpg", "img2.jpg", "img3.jpg"]

Flash Colors on Terminal Window in C

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <string.h>
int main()
{
        int i;
        struct winsize w;
        char *spaces;
        /* Get terminal window size: */
        ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
        /* Allocate enough spaces to fill the whole
* whole window (rows * cols):*/
        spaces = (char *)malloc(w.ws_row * w.ws_col);
        memset(spaces, ' ', w.ws_row * w.ws_col);
        /* Change background color, then print
* rows * cols of white spaces: */
        for(i = 0; 1; i++) {
                printf("\e[7;%dm\n", 31 + i%6);
                write(1, spaces, w.ws_row * w.ws_col);
                usleep(1000 * 1000);
        }
        return 0;
}

Native Baresip VoIP Client for Kindle 3

Download and configure alsa-lib to compile its static library (libasound.a):

1
2
3
4
5
wget ftp://ftp.alsa-project.org/pub/lib/alsa-lib-1.0.25.tar.bz2
tar xf alsa-lib-1.0.25.tar.bz2
cd alsa-lib-1.0.25/
mkdir ../alsa-static-build
CC=arm-linux-gnueabi-gcc ./configure --disable-shared --enable-static --target=arm-linux --host=i686-linux --prefix=/usr

Compile the library, and install it to the directory just created above (make sure to specify absolute path, in this case “/src/alsa-static-build”):

1
2
3
make
make install DESTDIR=/src/alsa-static-build
cd ..

Download and compile the re and rem libraries:

1
2
3
4
5
6
7
8
9
10
11
wget http://www.creytiv.com/pub/re-0.4.0.tar.gz
wget http://www.creytiv.com/pub/rem-0.4.0.tar.gz
tar xf re-0.4.0.tar.gz
mv re-0.4.0 re
cd re
CC=arm-linux-gnueabi-gcc LD=arm-linux-gnueabi-ld make
cd ..
tar xf rem-0.4.0.tar.gz
mv rem-0.4.0 rem
CC=arm-linux-gnueabi-gcc LD=arm-linux-gnueabi-ld make
cd ..

Download and compile baresip with the STATIC option:

1
2
3
4
wget http://www.creytiv.com/pub/baresip-0.4.0.tar.gz
tar xf baresip-0.4.0.tar.gz
cd baresip-0.4.0
CC=arm-linux-gnueabi-gcc LD=arm-linux-gnueabi-ld SYSROOT=/usr/arm-linux-gnueabi STATIC=yes make

The make above may fail in the linking because it can’t find the static alsa library — if so, it doesn’t matter. Now statically link the baresip binary to all the modules and libasound:

1
arm-linux-gnueabi-gcc -static-libgcc -Wl,-Bstatic -fPIC -rdynamic build-arm/src/aucodec.o build-arm/src/audio.o build-arm/src/aufile.o build-arm/src/aufilt.o build-arm/src/auloop.o build-arm/src/auplay.o build-arm/src/ausrc.o build-arm/src/calc.o build-arm/src/call.o build-arm/src/conf.o build-arm/src/contact.o build-arm/src/mctrl.o build-arm/src/menc.o build-arm/src/mnat.o build-arm/src/net.o build-arm/src/os.o build-arm/src/play.o build-arm/src/realtime.o build-arm/src/rtpkeep.o build-arm/src/stream.o build-arm/src/sipreq.o build-arm/src/ua.o build-arm/src/ui.o build-arm/src/uuid.o build-arm/src/vidcodec.o build-arm/src/vidisp.o build-arm/src/vidsrc.o build-arm/src/video.o build-arm/src/vidloop.o build-arm/src/static.o build-arm/src/main.o build-arm/modules/stun/stun.o build-arm/modules/turn/turn.o build-arm/modules/ice/ice.o build-arm/modules/natbd/natbd.o build-arm/modules/alsa/alsa.o build-arm/modules/alsa/alsa_src.o build-arm/modules/alsa/alsa_play.o build-arm/modules/cons/cons.o build-arm/modules/evdev/evdev.o build-arm/modules/evdev/print.o build-arm/modules/g711/g711.o build-arm/modules/l16/l16.o build-arm/modules/oss/oss.o build-arm/modules/stdio/stdio.o build-arm/modules/v4l/v4l.o -I../alsa-static-build/usr/include/ -L../alsa-static-build/usr/lib -L../re -lre -L../rem -lrem -lm -lasound -o baresip -Wl,-Bdynamic -ldl -lrt -lm -lresolv -lpthread -Wl,-Bstatic

This should create the binary “baresip”:

1
2
ls
Makefile baresip build-arm docs include mk modules share src

Compile PJSIP (and pjsua VoIP client) for Kindle 3

Prerequisites:

  • a jailbroken Kindle 3
  • access to a shell on the Kindle (by running a terminal, or connecting via SSH)
  • a Debian chroot on the Kindle
    Cross compilation tools will also be needed. This is how to do it under Debian Squeeze:

Add the emdedian repository[1]:

1
2
vi /etc/apt/sources.list
apt-get install emdebian-archive-keyring

Install ARM cross compilation tools:

1
2
3
4
apt-get update
apt-get install build-essential
apt-get install linux-libc-dev-armel-cross libc6-armel-cross libc6-dev-armel-cross binutils-arm-linux-gnueabi  gcc-4.3-arm-linux-gnueabi g++-4.3-arm-linux-gnueabi gdb-arm-linux-gnueabi uboot-mkimage

Compile the sources:

Prepare the build directory that will contain the ARM binaries:

1
2
cd src/
mkdir build

Download, configure and compile the alsa library[2]:

1
2
3
4
5
6
7
wget ftp://ftp.alsa-project.org/pub/lib/alsa-lib-1.0.25.tar.bz2
tar xzf alsa-lib-1.0.25.tar.bz2
cd alsa-lib-1.0.25
CC=arm-linux-gnueabi-gcc ./configure --target=arm-linux --host=i686-linux --prefix=/
make
make install DESTDIR=/usr/arm-linux-gnueabi/
make install DESTDIR=$(pwd)/../build

Download and configure pjsip:

1
2
3
4
5
cd ..
wget http://www.pjsip.org/release/1.12/pjproject-1.12.tar.bz2
tar xf pjproject-1.12.tar.bz2
cd pjproject-1.12
CC=arm-linux-gnueabi-gcc ./configure --target=arm-linux --host=i686-linux --prefix=/usr

Make sure that alsa was found:

1
grep alsa config.log

You should see something like:

1
2
3
...
ac_cv_header_alsa_version_h=yes
ac_pa_use_alsa='1'

Compile pjsip:

1
2
3
4
5
make dep
make
make install DESTDIR=$(pwd)/../build
cp pjsip-apps/bin/pjs* ../build/usr/bin/
rename 's/-arm-.*//' ../build/usr/bin/pjs*

To save precious space, you can delete the include directories that shouldn’t be needed on the device:

1
2
rm -r build/include
rm -r build/usr/include

Copy the contents of the build directory into the root directory of the chroot running on the Kindle.

Create a configuration pjsua file with options that optimize for running on a slow device[3]:

1
2
3
4
5
6
7
8
cat > pjsua-kindle.conf << EOF
--capture-dev 1
--add-codec pcma
--snd-auto-close -1
--clock-rate 8000
--quality 2
--ec-tail 0
EOF

pjsua should now be able to make VoIP calls:

1
pjsua --config-file pjsua-kindle.conf

References:

[1] http://wiki.micromint.com/index.php/Debian_ARM_Cross-compile
[2] http://omappedia.org/wiki/ALSA_Setup#ALSA_library
[3] https://trac.pjsip.org/repos/wiki/audio-check-cpu

Linux: Listen to the Network -- Literally

Pipe all the raw data received on the interface eth0 to aplay:

1
tcpdump -i eth0 -w - | aplay

Listen to the network in stereo:

1
tcpdump -i eth0 -w - | aplay -c 2

Use a filter expression to only listen to specific data:

1
tcpdump -i eth0 -w -  tcp port 80 | aplay

Create Time-lapse Video From Images

Using mencoder, this will concatenate all .jpg image files in the current directory to create a time-lapse video at 30 frames per second:

1
mencoder "mf://*.jpg" -mf fps=30 -ovc lavc -lavcopts vhq:vbitrate=1500 -lameopts preset=medium -o timelapse.avi

Personal Dynamic DNS Server

Assumptions:

  • You wish to use a dynamic DNS updater client such as ddclient to remotely update the DNS record of a host.
  • You already have a Bind DNS server installed.
  • You have a NS DNS record that points to your Bind DNS server (for example, at ns.example.com).
  • You have a web server running PHP.
    First, add a new zone for dynamic addresses to your Bind configuration. This is done by creating a new zone file, “/etc/bind/zones/master/dyn.example.com.db” (create the directory if it doesn’t already exist). Add some appropriate TTLs. For example:
1
2
3
4
5
6
7
8
9
10
11
$ORIGIN dyn.example.com.
$TTL 10 ; 10 seconds
dyn.example.com. IN SOA ns.example.com. hostmaster.example.com. (
18 ; serial
10800 ; refresh (3 hours)
3600 ; retry (1 hour)
604800 ; expire (1 week)
10 ; minimum (10 seconds)
)
$TTL 3600 ; 1 hour
NS ns.example.com.

Save the zone file and then add these lines to /etc/bind/named.conf.local:

1
2
3
4
5
zone "dyn.example.com" {
type master;
file "/etc/bind/zones/master/dyn.example.com.db"
allow-update { 127.0.0.1; };
};

replacing the path to point to the location of the zone file you just created. If the web server that listens to update requests from clients (that we will set up below) is not on the same machine as Bind, it has to be added to “allow-update” above instead of “127.0.0.1”.

Now download this script and put it the appropriate directory so that it is accessible on your web server at “/nic/update” (for example, “dns.example.com/nic/update”): update.php

You will need to use Apache’s MultiViews or mod_rewrite to ensure that the script is accessible at “/nic/update” and not just “/nic/update.php”.

Update the config section to contain the correct zone information along with the authentication credentials that the dynamic DNS updater client script will use. ddclient is such a client.

Prevent DoS attacks on an ET server

This iptables rules script protects against attacks where clients send many “getstatus” or “getinfo” requests, slowing down the server.

1
2
3
4
5
6
iptables -N et_dos
iptables -A INPUT -p udp --dport 27960 -m u32 --u32 "0>>22&0x3C@ 12=0x67657473 && 0>>22&0x3C@ 16=0x74617475" -j et_dos #filter for getstatu
iptables -A INPUT -p udp --dport 27960 -m u32 --u32 "0>>22&0x3C@ 12=0x67657469 && 0>>22&0x3C@ 16&0xFFFFFF00=0x6e666f00" -j et_dos #filter for getinfo
iptables -A et_dos -m limit --limit 10/minute --limit-burst 5 -j RETURN
iptables -A et_dos -m limit --limit 10/minute --limit-burst 5 -j LOG --log-prefix "IPTABLES DENIED (ET DoS): " --log-level 4
iptables -A et_dos -j DROP