Setting up an Ubuntu Router

I wanted to experiment with sniffing data on the network. Of course, my own network. This was not a creepy sniffing of my neighbours’ network. I was keen in converting my Ubuntu VM into a router VM. Then I can redirect all traffic from ‘client’ VM via the ‘router’ VM on which the sniffer is running. So, my requirements are simple, I need a VM with dual network adapter, one of which will be for the WAN side and other will be on the LAN side (exactly like a home router). What is required to convert a VM into router is a different topic and it will not be covered in this blog post.

Configure the Dual Network Adapter

The most important part of this is to understand that only one of the adapter is visible to your DHCP server and other is not. Why is this important? Because, only one of the adapter will get an IP from the DHCP and other will have to manually set. This DHCP-enabled adapter will be the WAN side adapter and the manual IP adapter will be the LAN side adapter. So, how do you configure dual interfaces on Ubuntu?

In Ubuntu, the networking system is configured via the ‘/etc/network/interfaces‘ file. Originally, there would have been only one interface as shown below:

$> ifconfig 
 eth0 Link encap:Ethernet HWaddr 08:00:27:d9:7a:ca 
 inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.0
 inet6 addr: fe80::a00:27ff:fed9:7aca/64 Scope:Link
 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
 RX packets:600 errors:0 dropped:0 overruns:0 frame:0
 TX packets:852 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:1000 
 RX bytes:273084 (273.0 KB) TX bytes:141395 (141.3 KB)

lo Link encap:Local Loopback 
 inet addr:127.0.0.1 Mask:255.0.0.0
 inet6 addr: ::1/128 Scope:Host
 UP LOOPBACK RUNNING MTU:16436 Metric:1
 RX packets:479 errors:0 dropped:0 overruns:0 frame:0
 TX packets:479 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:0 
 RX bytes:147404 (147.4 KB) TX bytes:147404 (147.4 KB)

Now, let us configure the networking system to understand the 2nd interface, which we shall name as ‘eth1.’

So edit ‘/etc/network/interfaces‘ as show below:

# The loopback network interface
 auto lo
 iface lo inet loopback

# The primary network interface
 auto eth0
 iface eth0 inet dhcp

 auto eth1
 iface eth1 inet static
 address 192.168.50.1
 network 192.168.50.0
 netmask 255.255.255.0
 broadcast 192.168.50.255

What this means is that:

  • eth0 is DHCP-enabled and gets the IP from the DHCP server.
  • eth1 has static IP of 192.168.50.1

Restart the network (via ‘sudo /etc/init.d/networking restart’):

network-restart
Restart of network

Now, both the interfaces are up as shown below:

$> ifconfig 
 eth0 Link encap:Ethernet HWaddr 08:00:27:d9:7a:ca 
 inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.0
 inet6 addr: fe80::a00:27ff:fed9:7aca/64 Scope:Link
 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
 RX packets:600 errors:0 dropped:0 overruns:0 frame:0
 TX packets:852 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:1000 
 RX bytes:273084 (273.0 KB) TX bytes:141395 (141.3 KB)

eth1 Link encap:Ethernet HWaddr 08:00:27:85:3a:24 
 inet addr:192.168.50.1 Bcast:192.168.50.255 Mask:255.255.255.0
 inet6 addr: fe80::a00:27ff:fe85:3a24/64 Scope:Link
 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
 RX packets:3043 errors:0 dropped:0 overruns:0 frame:0
 TX packets:34454004 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:1000 
 RX bytes:372333 (372.3 KB) TX bytes:3193181649 (3.1 GB)

lo Link encap:Local Loopback 
 inet addr:127.0.0.1 Mask:255.0.0.0
 inet6 addr: ::1/128 Scope:Host
 UP LOOPBACK RUNNING MTU:16436 Metric:1
 RX packets:479 errors:0 dropped:0 overruns:0 frame:0
 TX packets:479 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:0 
 RX bytes:147404 (147.4 KB) TX bytes:147404 (147.4 KB)

Now we have 2 interfaces:

  1. ‘eth0’ (DHCP-enabled) pointing to the WAN side
  2. ‘eth1’ (static IP) pointing to the LAN side

Configure NAT routing

Use the following script, which I had borrowed from somewhere (forgot!) and slightly modified to my taste (available on github):

#!/bin/sh


#
#--------------------------------- constants
fn_check_dependencies() {
	local __cmd=${1}
	local __path=$(which ${__cmd})

	if [ $? -ne 0 ]; then
		echo "****************** !! \${__cmd}\' IS NOT AVAILABLE !! ******************"
		echo
		exit 1
	fi

	echo ${__path}
}

#
#--------------------------------- constants
AWK=$(fn_check_dependencies awk)
ECHO=$(fn_check_dependencies echo)
DEPMOD=$(fn_check_dependencies depmod)
GREP=$(fn_check_dependencies grep)
IP=$(fn_check_dependencies ip)
IPTABLES=$(fn_check_dependencies iptables)
MODPROBE=$(fn_check_dependencies modprobe)
NETSTAT=$(fn_check_dependencies netstat)

#
#--------------------------------- functions
fn_get_wan_iface() {
	${ECHO} $(${IP} route show | ${GREP} default | ${AWK} '{print $5}')
}

fn_get_lan_iface() {
	local _wan_ip=$(fn_get_wan_iface)
	${ECHO} $(${NETSTAT} -i | ${GREP} -ve lo -ve Iface -ve Kernel -ve ${_wan_ip} | ${AWK} '{print $1}')
}

fn_load_mod() {
	local __mod_name=${1}
	${ECHO} " |->; ${__mod_name}"
	${MODPROBE} ${__mod_name}
	if [ $? -ne 0 ]; then
		${ECHO} "****************** !! FAILED TO LOAD ${__mod_name} !! ******************"
		${ECHO}
		exit 1
	fi
}

fn_load_modules() {
	${ECHO} " - Loading kernel modules: "
	${DEPMOD} -a
	fn_load_mod ip_tables
	fn_load_mod nf_conntrack
	fn_load_mod nf_conntrack_ftp
	fn_load_mod nf_conntrack_irc
	fn_load_mod iptable_nat
	fn_load_mod nf_nat_ftp
	${ECHO}
}

fn_enable_ipv4_forwarding() {
	${ECHO} " - Enabling forwarding.."
	${ECHO} "1" > /proc/sys/net/ipv4/ip_forward
}

fn_enable_ipv4_dynamic_addr() {
	${ECHO} " - Enabling DynamicAddr.."
	${ECHO} "1" > /proc/sys/net/ipv4/ip_dynaddr
}

fn_clear_previous_fw_rules() {
	${ECHO} " - Clearing existing firewall rules"
	${IPTABLES} -t nat -D POSTROUTING -o "$WANIF" -j MASQUERADE
	${IPTABLES} -t filter -D FORWARD -i "$WANIF" -o "$LANIF" -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT 
	${IPTABLES} -t filter -D FORWARD -i "$LANIF" -o "$WANIF" -j ACCEPT
	${IPTABLES} -t filter -D FORWARD -j LOG
}

fn_create_fw_rules() {
	${ECHO} " - Enabling firewall rules"
	${IPTABLES} -t nat -A POSTROUTING -o "$WANIF" -j MASQUERADE
	${IPTABLES} -t filter -A FORWARD -i "$WANIF" -o "$LANIF" -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT 
	${IPTABLES} -t filter -A FORWARD -i "$LANIF" -o "$WANIF" -j ACCEPT
	${IPTABLES} -t filter -A FORWARD -j LOG
}

#
#--------------------------------- Main
${ECHO}
${ECHO} "======================= Enabling NAT ======================="
${ECHO}

WANIF=$(fn_get_wan_iface)
LANIF=$(fn_get_lan_iface)

${ECHO} "WAN Interface: $WANIF"
${ECHO} "LAN Interface: $LANIF"
${ECHO}

if [ -z ${WANIF} ]; then
	${ECHO} "****************** !! WAN interface not found !! ******************"
	${ECHO}
	exit 1
fi

if [ -z ${LANIF} ]; then
	${ECHO} "****************** !! LAN interface not found !! ******************"
	${ECHO}
	exit 1
fi

if [ ${WAN} = ${LANIF} ]; then
	${ECHO} "****************** !! Only one interface found !! ******************"
	${ECHO}
	exit 1
fi

${ECHO} "Setting up network:"
fn_load_modules
fn_enable_ipv4_forwarding
fn_enable_ipv4_dynamic_addr
fn_clear_previous_fw_rules
fn_create_fw_rules
${ECHO}
${ECHO} "======================= Done ======================="
${ECHO}

The above script does the following:

  1. Ensures the required kernel modules are loaded.
  2. Enable IP forwarding
  3. Enable masquerading on the WAN side interface
  4. All connections via LAN interface should be transferred to WAN interface
  5. Finally, all ‘established’ or ‘related’ connections via WAN should be transferred to LAN.

Done. Now when a device connects to this Ubuntu box via ‘eth1’ it connect to the internet. In other words, this ubuntu box serves as a router for other connected devices.

How to: Create a local SVN on Ubuntu

Often times I get into a situation where I mess up with my development (of personal projects). Though I use github for personal projects yet sometimes it is convenient to have a local SVN for all silly works (like .vimrc, .bashrc, etc…). After a lot of procrastination, I decided to set a local svn repo for all my silly “not-to-be-published” work.

Points to note
  • First, understand that I am working on my personal box & so I got complete permission to violate 😉 the value of a sudoer account.
  • Second, I am kinda cli person. Except for the joys of multi-window vim sessions I don’t want an overhead of apache et al. So I did not invest time in configuring my apache for my svn.
  • Third, I am gonna access my SVN as a “file:///” & not as “http://” or “svn:///”

And, so here we go…

Install Subversion Package

Don’t expect an explanation here 😉

$> sudo apt-get install subversion subversion-tools

Repository directory

Create a directory to hold all your repositories. Since I own my box, to avoid confusion I created the repo directory as a peer to my user account. Another reason is this will ensure that my guest accounts (i.e., family et al) don’t get access to my SVN (by the virtue of they not being a sudoer).

$> sudo mkdir /home/svn

Create repo

Create a new, empty repository at the path provided. Suppose, I want a repository for all my silly test works (like a super silly shell script to dump the current ip), I shall call it ‘test.’ Then:

$> sudo svnadmin create /home/svn/test
$> ls -l /home/svn/
total 4
drwxr-xr-x 6 root root 4096 2014-09-18 18:32 test

This has created an empty repository under /home/svn/test.

Import data

Importing data implies that some data is available somewhere already. In my case, yes I do have my silly scripts to import and hence I change directory into where I have stored the scripts and import them as below:

$> cd ~/sillyscripts
$> sudo svn import . file:///home/svn/test/trunk -m "Initial import"

Now the entire sub-tree under sillyscripts have been imported into test.

Checkout

Final point to remember is that the original location from where the data was imported (i.e., ~/sillyscripts) is _NOT_ under svn. We need to freshly checkout the repo.

$> cd ~/svnprojects/
$> svn co file:///home/svn/test
$> cd ~/svnprojects/test
$> svn info
Path: .
URL: file:///home/svn/test
Repository Root: file:///home/svn/test
Repository UUID: 4158fc24-64e9-4705-b124-8f2b88018be7
Revision: 1
Node Kind: directory
Schedule: normal
Last Changed Author: root
Last Changed Rev: 1
Last Changed Date: 2014-09-18 19:00:02 +0300 (Thu, 18 Sep 2014)

Voila! Now play with your data & have fun 🙂

Courtesy:

HowTo: Show/Display available network interfaces

The biggest problem I found was not identifying all the network interfaces available but the ones that are up. For instance, the 2 quickest way to identify all the available network interfaces are:

ip link
$> ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 5c:26:0a:7b:7b:f6 brd ff:ff:ff:ff:ff:ff
3: wlan0: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN mode DEFAULT group default qlen 1000
    link/ether a0:88:b4:ca:8b:4c brd ff:ff:ff:ff:ff:ff

Obviously, there are 2 interfaces (sans the default, lo): eth0 & wlan0. Btw, can you tell which of these 2 are up & which is NOT?!!!! Trust me I couldn’t. At least not in the first look! Then figured a pattern in the presence of ‘DOWN’ or ‘UP’ keywords!! Yet, this was not sufficient for me as I was wanting to identify the network interfaces that are UP using a generic script. ‘grep’-ing for ‘UP’ & ‘DOWN’ would not work out here.

ifconfig
$> ifconfig -a
eth0      Link encap:Ethernet  HWaddr 5c:26:0a:7b:7b:f6
          inet addr:10.212.140.25  Bcast:10.212.140.255  Mask:255.255.255.0
          inet6 addr: fe80::5e26:aff:fe7b:7bf6/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:919885 errors:0 dropped:0 overruns:0 frame:0
          TX packets:418690 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1098622617 (1.0 GB)  TX bytes:48860614 (48.8 MB)
          Interrupt:20 Memory:e2e00000-e2e20000

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:92466 errors:0 dropped:0 overruns:0 frame:0
          TX packets:92466 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:12115565 (12.1 MB)  TX bytes:12115565 (12.1 MB)

wlan0     Link encap:Ethernet  HWaddr a0:88:b4:ca:8b:4c
          BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:506150 errors:0 dropped:0 overruns:0 frame:0
          TX packets:344206 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:557950489 (557.9 MB)  TX bytes:40095705 (40.0 MB)

Another obvious problem! Can you see that it is not easy to figure out which of the interfaces are down!! Of course, the presense of UP (or the lack of it) is not sufficient to write a simple bash script!!

So, after a bit of research & some soul-searching as well, I figure out a simpler way:

netstat -i

$> netstat -i
Kernel Interface table
Iface   MTU Met   RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0       1500 0    921323      0      0 0        419605      0      0      0 BMRU
lo        65536 0     93141      0      0 0         93141      0      0      0 LRU

Ah! There you can see only eth0 is displayed! Voila! I found my unicorn here! 🙂 So, now my script would be a simple:

$> netstat -i | grep -vi 'kernel' | grep -vi 'iface' | grep -v 'lo' | awk '{print $1}'
eth0

Isn’t this awesome?! 🙂

One can even use ‘ifconfig -s‘ instead of ‘netstat -i‘ and the output be the same! 🙂

FYI: I am using Ubuntu 14.04 LTS 64-bit.

Ubuntu: Disable start of a service on boot

A simple problem I was facing in Ubuntu was finding an equivalent of “chkconfig” available on the Redhat flavors. Well, for the unaware people:

chkconfig‘ is popularly used for adding or removing any services during boot. In other words, it updates and queries runlevel information for system services.

So, my search was for a similar tool on Ubuntu. And, this is what I found at the end of the search: update-rc.d. This is very simple to use & equally intuitive as well. For instance,

$> sudo update-rc.d -f mongodb remove
Removing any system startup links for /etc/init.d/mongodb ...

The above usage helped me remove ‘mongodb’ from automatically starting on boot. Voila! 🙂

Reference

Simple Character Device Driver

It has been nearly 5 years since I did any work on device drivers. Also since then I have been off C or its sibling languages (on Python now-a-days), I thought first lemme get comfortable with linux kernel (& C, of course) before I can even dream of getting back to my core. In that line, I wrote a very simple character device driver which upon read returns a character buffer with every bit turned to one.

In other words, the idea is simple, our (virtual) device is almost like an inverse of (or a not of, if you prefer) of /dev/zero. Reading from this device would result in every bit turning one. For instance, if we read 1 Byte of data from /dev/ones & store it in file ‘out’:

$> dd if=/dev/ones of=out bs=1 count=1
1+0 records in
1+0 records out
1 byte (1 B) copied, 0.000142743 s, 7.0 kB/s

Then dump the content of ‘out’ file in hex mode, we should get:

$> od -t x1 out
0000000 ff
0000001

Download the entire code.

What & Why a character device driver?

Lemme answer the why? Because it is the easiest! 🙂 No complication and a virtual character device can be as limited in its capabilities as you can think of. So, now what is a character device? It is where:

  • Read/write arbitrary bytes at a time
  • Generally seek is _not_ supported. (Generally!)
  • Very importantly, works on streams of bytes (or data, if you like). In other words, it does _NOT_ support buffered I/O. So every R/W is directly sent to (or from) the device.

Examples of character devices are printers, mice, keyboards & likewise.
Examples of pseudo(or virtual) character devices in Linux are /dev/null, /dev/zero, /dev/random & similar devices.

Basics

I am revisiting so lemme just wanna throw some light to the forgotten corners of my knowledge. Writing a device driver (at least, in Linux) is like writing any C – program. The only difference is that the Linux kernel kinda provides a framework and set of libraries that the driver code should adhere to. Very similar to, say, .NET framework or MFC. Linux kernel subsystem expects the driver to:

  1. define the entry & exit points.
  2. implement a set of operations (typically, file operations)
  3. register with the subsystem.
  4. create the device file

Entry & Exit points

These are like constructor & destructor available in many OOP languages like C++ or Java. Unlike C++, these entry points are mandatory. These are called when a kernel module is loaded. (Note: I said kernel module & not a driver!)

A device driver is a kernel module which talks (or at least, can talk to) a hardware device.
A kernel module is just any pluggable piece of code that can be inserted into the Linux subsystem (or framework, if that helps you).

But for this blog let us not worry about the nitty-gritty and the words kernel module and driver are interchangeably used.
So, a simple kernel module, which does nothing, is as follow:

#include <linux/module.h>

static int __init
one_init(void)
{
    return 0;
}

static void __exit
one_exit(void)
{
    return;
}

module_init(one_init);
module_exit(one_exit);

Suppose you name this as ones.c. You can compile the above using a Makefile as defined below:

TARGET_MODULE := ones
BUILDSYSTEM_DIR := '/lib/modules/${shell uname -r}/build'
PWD := $(shell pwd)

obj-m := $(TARGET_MODULE).o

default: test
    ${MAKE} -C ${BUILDSYSTEM_DIR} SUBDIRS=${PWD} modules

clean:
    ${MAKE} -C ${BUILDSYSTEM_DIR} SUBDIRS=${PWD} clean

Don’t worry about the details of the Makefile. Just know & note that the kernel module is compile with Kernel header files (at least). So you gotta download the kernel header files in accordance to your OS flavor. Once you compile, you should get a few additional file of which ‘ones.ko’ is of importance to us & this is the kernel module (or Kernel Object as the extension suggests). The module related Linux commands are:

#insert the kernel module into the kernel subsystem
$> insmod ones.ko

# list to verify
$> lsmod | grep ones
ones 19598 0

# details on the module
$> modinfo ./ones.ko
filename: ./ones.ko
author: Rp <rp@meetrp.com>
description: This device driver turns on every bit to '1'
license: GPL
srcversion: C5FDECEF298D041105E333F
depends:
vermagic: 2.6.32-358.18.1.el6.x86_64 SMP mod_unload modversions

# remove the module from kernel subsystem
$> rmmod ones

Implement of file operations

Let us add more meat to the simple module. Let us develop this simple kernel module into a character device driver. Now, what are our requirements: “Read should result in every bit turned to one. ” This means the use should be able to open, read and close our virtual device. As mentioned above, Linux kernel subsystem provides a framework to define & implement these operations. The are defined under ‘struct file_operations,’ which holds pointers to functions defined by the driver to perform various operations on the device. In other words, Linux kernel subsystem uses the file_operation structure to access driver’s functions. So, continuing with our driver, the structure is populated thus:

static struct file_operations fops = {
    .owner = THIS_MODULE, // pointer to the module struct
    .open = one_open,     // address of one_open
    .release = one_close, // address of one_close
    .read = one_read,     // address of one_read
};

Don’t worry about the “.owner,” part of it. You can safely ignore it as well. Now these function declarations (or prototypes) are available within linux/fs.h. Also the prototypes for the functions of interest are:

int (*open) (struct inode *, struct file *);
ssize_t (*read) (struct file *, char *, size_t, loff_t *);
int (*release) (struct inode *, struct file *);

So now add these to our driver code:

#include <linux/fs.h>

// called when 'open' system call is invoked
static int
one_open(struct inode *in, struct file *fp)
{
    open_count++;
    debug("Count of open dev files #%d", open_count);

    return 0;
}

// called when 'close' is invoked
static int
one_close(struct inode *in, struct file *fp)
{
    if (! open_count) {
        error("Device close attempted while count is #%d", open_count);
        return -EFAULT;
    }

    debug("Device closed. count is #%d", open_count);
    open_count--;
    return 0;
}

Since we are working on virtual device I just maintain the count of open requests and matching those with the number of close. This is _not_ required but then my zodiac sign is Virgo! 😉 Let us define the read functionality, which is where our core logic resides. Note the declaration of ‘read’ function pointer:

ssize_t (*read) (struct file *, char *, size_t, loff_t *);
  • The first parameter is a pointer to file structure, which can be ignored in our case as we are _not_ creating (during open) or destroying (during close) any of the file pointers.
  • The second parameter is the buffer that is allocated in the user space for the read data.
  • The third is the number of bytes to be read and finally,
  • the fourth is the offset within the file, which, again, is not required in our case.
  • Also note that the function should return the number of bytes successfully read.

So, what we are interested in is how to copy number of bytes from kernel space to user space pointed by . Simple, yeah?! 🙂

Now the question is how to copy from Kernel space to user space. Without going into details, we have a special set of functions to do such transfers and the one of interest to us is ‘copy_to_user‘ function, which:

  1. as name suggests, copies data from a buffer in kernel to a buffer in user space.
  2. checks the pointer validity
  3. checks the sufficiency of the size of the buffer allocated in user space.

The self-explanatory prototype looks like this:

long copy_to_user( void __user *to, const void * from, unsigned long n );

Now, the final piece of the puzzle. The ‘ones’. I used a global buffer array (one_arr) of size of a page (PAGE_SIZE) which has every of its bit of every Byte turned on, i.e., 0xFF. So, our read function is nothing more than just copy data from this global buffer array to the user space, one page at a time. Thus our code is:

// called when the 'read' system call is done on the device file
static ssize_t
one_read(struct file *fp, char *buf, size_t buf_size, loff_t *off)
{
    size_t count = 0;

    if (! buf_size) {
        debug("buf_size is ZERO!!");
        return 0;
    }

    debug("requested size #%ld", buf_size);
    while (buf_size) {
        size_t chunk = buf_size;

        if (chunk > PAGE_SIZE)
            chunk = PAGE_SIZE;

        debug("about to copy #%ld size of data", chunk);
        debug("data: 0x%x", (unsigned char)one_arr[0]);
        if (copy_to_user(buf, one_arr, chunk))
            return -EFAULT;

        buf += chunk;
        count += chunk;
        buf_size -= chunk;
    }

    debug("return #%ld", count);
    return count;
}

Register of character device with the subsystem

Finally, we are now ready to register this module as a character device driver. The registration happens in the constructor (i.e., init function). The registration API has the following prototype:

int register_chrdev (unsigned int major, const char *name, const struct file_operations *fops);

I am not gonna talk about the major number, the first parameter, in this blog. The second parameter is the name we would like to give to our device driver. The final parameter is the pointer to the file_operations structure defined earlier. We can add the following into the init function:

major = register_chrdev(0, "one", &amp;fops);
if (major &lt; 0) {
    error("Device registration failed - %d!!", major);
    return -EFAULT;
}

Thus ends our coding for the character device driver.
The rest of the entire code can be downloaded from here.

Create the device file

When you load our driver we should be able to see these entries in the log (in CentOS/RHEL, it is /var/log/messages):

Sep 13 20:22:50 rp kernel: [ ONE : one_init : 038 ] [DBG] registering the character device
Sep 13 20:22:50 rp kernel: [ ONE : one_init : 040 ] [DBG] return value: 247
Sep 13 20:22:50 rp kernel: [ ONE : one_init : 046 ] [INF] Device registration successful. Major #247
Sep 13 20:22:50 rp kernel: [ ONE : one_init : 047 ] [DBG] about to prepare the array

Note the major number printed. Using this, we can create a device node on the CLI as shown below.

$> mknod /dev/ones c 247 1
$> chmod a+w+r /dev/ones

Remember to be run as a root or in sudo mode.

Tada! The first simple driver ready! 🙂

You can download the entire code including a test program from here.

References

The blog & articles I referenced while rebuilding my knowledge. Thought these might be useful to you guys as well:

 

Wine – Run windows app on Linux

Wine is a free & open source software application designed to run windows-based application on other operating systems. In English, using wine one can run any windows software (games including) in Linux!

Trivia: WINE is an acronym for WINdows Emulator or Wine Is Not an Emulator.

Wine for Ubuntu and Ubuntu derivatives

Wine is not a part of default repository that comes with the Ubuntu bundle. So as a first measure, we need to add the Wine repository to Ubuntu software sources.

Adding the WineHQ PPA Repository

Open “System Settings” by clicking on the top-right corner of the ubuntu desktop.

ubuntu-system-settings
Open software settings in ubuntu

 

Open “Software updates” as shown below:

Ubuntu Software Updates
Ubuntu Software Updates

 

In the “Software & Updates” window, select ‘Other Software‘ and then click on ‘Add…‘ to get this:

Ubuntu add a new repo
Ubuntu add a new repo

Then, copy and paste the following: ppa:ubuntu-wine/ppa.

Installing Wine

Open “Ubuntu Software Center“:

ubuntu-software-center
Ubuntu Software Center

 

Type ‘wine‘ in the right-top corner textbox of the software center window, which is actually a search textbox. Click ‘Enter.’  You should get a list of all softwares related to wine. The one of interest to us is the top-most one titled ‘Microsofts Windows Compatibility Layer.‘ Select it and click ‘Install.’

Once installed you should be able to see a view like below where ‘Install’ button is replaced with ‘Remove.’

ubuntu-install-wine
Install Wine

Voila! Installation done! 🙂

What next?

Configure Wine

This would be the first step I would suggest to do.

ubuntu-configure-wine
Configure Wine

 

The major step is to configure wine to the windows version you are interested in. For instance, I am interested in “Windows 7” so change the ‘Windows version’ to ‘WIndows 7’.

ubuntu-wine-configuration
Wine Configuration

This ensures that Wine will emulate Windows 7 behavior, if it would make any difference to the software you are going to install.

How to install?

Unfortunately, there is only one way to do it. Command line! First step, download the software you want to install. Next step is to install the package using wine as show below:

$> wine [full path of .exe file]

Done! 🙂

Install Wine using apt-get

Same as before we have to add Wine HQ repository to the software sources and install wine.

$> sudo add-apt-repository ppa:ubuntu-wine/ppa
$> sudo apt-get update
$> sudo apt-get install wine

Done! 🙂

Related Links