Tuesday, October 11, 2011

Compiling kernel modules (tun.ko) for Android

If you want to use OpenVPN on your Android device, the first obstacle you have to face is trying to get the right network tunnel module for your phone's kernel. I always have a hard time to get the pre-compile version that matches the kernel I use. (Note: If you don't want to deal with this issue, you can always pick a kernel that comes with the tunnel module.) However, I always like to use the stock kernel which doesn't come with network tunnel module. So, after googling for awhile, I found out that compiling your own kernel module actually is not that difficult. First, I found this tutorial online http://sshrootat.blogspot.com/2011/06/compiling-tunko-for-android-openvpn.html by Sean Crosby. This is a very good tutorial; however, I encountered few issues when I tried to follow instruction. So, I want to share my steps here which are very close to Sean's tutorial but with extra details. Note: these steps are targeted for Tegra device like Motorola Xoom and assume you have basic Linux knowledge and a Linux machine around to compile the source.

  1. First thing you need is to find which kernel version you have on your device. 
    • "uname -a" will do the trick. Note: If you need a program like "Terminal Emulator" to run command on your Android device. The output of uname should look something like this "Linux localhost 2.6.36.3-g111d827...." The number "2.6.36.3" is the kernel version number you're looking for. And the "g111d827" is the build number which you will need later when you compile the module because the build number has to be identical between kernel and the module.
  2. Once you know the version you need, than you have to download the right source code. By the time I wrote this post, http://android.git.kernel.org was hacked and was offline for more than a month. So,  I found another alternative repository https://www.codeaurora.org/gitweb/quic/la/?p=kernel/tegra.git;a=heads. The web page listed all source branches in this repository. In this case, I would pick the branch "aosp/android-tegra-2.6.36". 
    • To clone the source, create a new directory "android-kernel" and than run this command "git clone git://codeaurora.org/kernel/tegra.git -b aosp/android-tegra-2.6.36". I will take awhile to download the source, you can let it run and continue to next step.
  3. Download the ARM crosscompiler from https://sourcery.mentor.com/sgpp/lite/arm/portal/release1293
    • create a directory "compiler" and extract the binary with this command "tar -jvxf arm-2010q1-202-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2" 
    • Since I'm not a Unix programmer and don't know much about cross compiler, if this compiler doesn't work with your Linux version (I'm using Ubuntu 10.4), than you may have to do some research finding the right one.
  4. Add the compiler bin to your path.
    • "export PATH=$PATH:~/android-kernel/compiler/arm-2010q1/bin"
  5. Once the source is downloaded, you should have "tegra" directory inside "android-kernel". Now, it's time to get your existing kernel configuration from your device. The file is located under "/proc" and called "config.gz". Download it to your linux machine and unzip it using "gunzip config.gz". Now, copy "config" file to "tegra" directory and rename it to ".config". You also need to make some changes to .config file.
    • update CONFIG_CROSS_COMPILE to match your cross compiler. In this case, "arm-none-linux-gnueabi-" is the value.
    • update CONFIG_LOCAL_VERSION to match your build number. In this case, it is "-g111d827".
    • if your .config file has CONFIG_LOCALVERSION_AUTO set to Y like mine, change it to #CONFIG_LOCALVERSION_AUTO is not set
    • last but the most important one is to make sure CONFIG_TUN is un-commented and set to m
  6. Modify the setlocationversion script so it won't display "+" symbol.
    • go to tegra directory
    • vi scripts/setlocalversion
    • locate the following line
      • if $short; then
      •      echo "+"
    • change echo "+" to echo ""
  7. Set the environment properties for the compiler
    • export ARCH=arm
  8. Compile the modules
    • go to "tegra" directory
    • run "make modules"
  9. If the compile succeed, you should find a tun.ko file under drivers/net.
    • run "strings tun.ko" to make the version is matching your kernel version.
  10. Now, copy the module file back to your Android device and enjoy OpenVPN.