Sunday 1 June 2014

Berlin Clock


The programming exercise below was shown to me by the writer of From Fragile to Agile.
Click here to see my answer  on GitHub.

"Create a representation of the Berlin Clock for a given time (hh::mm:ss).
The Berlin Uhr (Clock) is a rather strange way to show the time. On the top of the clock there is a yellow lamp that blinks on/off every two seconds. The time is calculated by adding rectangular lamps.
The top two rows of lamps are red. These indicate the hours of a day. In the top row there are 4 red lamps. Every lamp represents 5 hours. In the lower row of red lamps every lamp represents 1 hour. So if two lamps of the first row and three of the second row are switched on that indicates 5+5+3=13h or 1 pm.

The two rows of lamps at the bottom count the minutes. The first of these rows has 11 lamps, the second 4. In the first row every lamp represents 5 minutes. In this first row the 3rd, 6th and 9th lamp are red and indicate the first quarter, half and last quarter of an hour. The other lamps are yellow. In the last row with 4 lamps every lamp represents 1 minute.
The lamps are switched on from left to right.

Test Cases (Y = Yellow, R = Red, O = Off)
Input Result 00:00:00 Y OOOO OOOO OOOOOOOOOOO OOOO
13:17:01 O RROO RRRO YYROOOOOOOO YYOO
23:59:59 O RRRR RRRO YYRYYRYYRYY YYYY
24:00:00 Y RRRR RRRR OOOOOOOOOOO OOOO"


Saturday 2 November 2013

Ubuntu Wireless Hotspot using Edimax EW-7811Un

I have had my phone, a Nexus 4, for quite a while now and I absolutely love it. The only problem I have with it is its incompatibility with my home wireless router, which is a D-Link DSL-2780 decorated with the TalkTalk branding.

My Nexus 4 connects to the router just fine, but all network related activities are slow as hell. Web sites take long to resolve, connection drops frequently, network shares are unreachable and it is just not usable. This is not the case when connected to the wireless network at my workplace.

My first thought was to replace my old router, but I couldn't really justify spending money on replacing my router just because my phone had issues with it. Besides, I got a data plan for Internet access, so the only real problem was not being able to access my network shares.

After reading a few forums and blogs, I thought I would give a shot at creating a wireless hotspot using an Edimax EW-7811Un Wifi dongle I had lying around. The steps below show how I paired the Edimax dongle with my HP ProLiant micro server running Ubuntu Server 12.04 to create a wireless access point.

Hostapd 

 

The first thing I installed on my Ubuntu server was hostapd. The hostapd daemon manages the Wifi link, including authentication of connections and it supports WPA2. The Edimax EW-7811Un contains the RTL8192cu chipset, this unfortunately does not work with the hostapd package in the Ubuntu repository.

The chipset and driver of the device can be found by entering the command below, after plugging in the Edimax.

lshw -c network

lshw is a utility used to probe detailed information about the machine and connected devices. The -c flag is used to indicate the class of the hardware we wish to probe.

Luckily, Realtek provides Linux drivers and their own version of hostapd which can be downloaded from here, however only the Linux kernels 2.6.18~3.9 are supported. I copied the downloaded zip file over to the server using scp.

scp RTL8188C_8192C_USB_linux_v4.0.2_9000.20130911.zip sam@192.168.1.90:/home/sam

Unzipped the file using unzip.

unzip RTL8188C_8192C_USB_linux_v4.0.2_9000.20130911.zip

Installed the driver for the Edimax EW-7811Un using the supplied install script. Use chmod +x to make the script executable first.

 cd RTL8188C_8192C_USB_linux_v4.0.2_9000.20130911/  
 sudo chmod +x install.sh  
 sudo bash install.sh  

In order to tell the system to ignore the old driver and use the newly installed one, I had to do two things.

First, blacklist the old driver module by editing the /etc/modprobe.d/blacklist.conf file. The following was appended to the end of that file.

 blacklist rtl8192cu

Secondly, edit the /etc/modules file and tell the kernel to load the newly install driver module. This was done by appending the following line to the file.

 8192cu

Now to compile and install Realtek's hostapd.

 cd RTL8188C_8192C_USB_linux_v4.0.2_9000.20130911/wpa_supplicant_hostapd  
 tar -xzf wpa_supplicant_hostapd-0.8_rtw_r7475.20130812.tar.gz  
 cd wpa_supplicant_hostapd-0.8_rtw_r7475.20130812/hostapd  
 sudo make  
 sudo make install  

I created a hostapd configuration file, hostapd.conf, within /etc/hostapd/ (you may need to make the directory).

 sudo mkdir /etc/hostapd  
 cd /etc/hostapd  
 sudo nano hostapd.conf  

The following segment shows the contents of the hostapd.conf file. You can enter your own ssid and wpa_passphrase. The value for wpa determines which security protocol to use. The value 0 = none, 1 = wpa, 3 = wpa2 and 3 = both.

interface=wlan0
driver=rtl871xdrv
ssid=SAMEERAN
channel=6
wmm_enabled=0
wpa=2
wpa_passphrase=MYPASSWORD
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
auth_algs=1
macaddr_acl=0

That's all there is to setting up the hostapd. By default, the hostapd daemon looks for the configuration file /etc/hostapd/hostapd.conf. We can check that by running the following command and checking the value of DAEMON_CONF.

 cat /etc/init.d/hostapd

If we were to start the hostapd daemon now, we would see the wireless network. However, if we try to connect to it, our device would not be able to obtain an ip address.

isc-dhcp-server

 

To allow our client devices to retrieve an ip address, I had to install a DHCP service on the Ubuntu server. The most commonly used package is isc-dhcp-server, an alternative is dnsmasq which also incorporates a DNS service.

 sudo apt-get install isc-dhcp-server

The /etc/default/isc-dhcp-server file had to be edited in order to specify the interface on which the DHCP server would listen on.

 sudo nano /etc/default/isc-dhcp-server

I gave the INTERFACES the value 'wlan0'.

 INTERFACES="wlan0"

The /etc/dhcp/dhcpd.conf file also needed to be edited in order to specify ip address lease times, ip address range and DNS servers.

 sudo nano /etc/dhcp/dhcpd.conf

I changed the value of the lease times to the following.

 default-lease-time 18000;  
 max-lease-time 36000;  

I appended the below to specify the ip address range 10.10.0.2 - 10.10.0.10, DNS server (ip of my home router 192.168.1.1) and router ip (ip of the wlan0 interface 10.10.0.1, I will show you how I set that up later on).

 subnet 10.10.0.0 netmask 255.255.255.0 {  
     range 10.10.0.2 10.10.0.10;  
     option domain-name-servers 192.168.1.1;         
     option routers 10.10.0.1;  
 }  

I appended the following to the /etc/network/interfaces to give the wlan0 interface a static ip address (isc-dhcp-server will complain if not static). You might want to comment out any line that mention wlan0 to stop any conflicts.

 auto wlan0  
 iface wlan0 inet static  
 address 10.10.0.1  
 netmask 255.255.255.0  

Restart the networking service in order to pick up the changes.

 sudo service networking restart

If we were to start up isc-dhcp-server and hostapd, any clients connecting to our hotspot would now get an ip address and would be able to access networked computers. To allow the clients to access the internet, ip forwarding needs to be setup.

First we edit /etc/sysctl.conf and add the line show below (this line may already be in the config file and just needs uncommenting). This enables ip forwarding in the kernel.

 net.ipv4.ip_forward = 1  

Run the below command to allow the kernel to pick up the changes.

 sudo sysctl -p /etc/sysctl.conf  

Sysctl is a tool to configure the kernel parameters. The -p flag allows you to load settings from a configuration file.

Lastly, I set up NAT with the help of iptables. The command below appends a new POSTROUTING rule to the nat table (table with nat rules).  The rule is as follows, any packets arriving from the source network 10.10.0.0/16 (our hotspot) should be sent to the output interface eth0 (ethernet). The '-j MASQUERADE" means we want to change the sender ip in the packet to the ip address of the eth0 interface. (Here is an awesome article that explains how NAT works and how the command below works).

 sudo iptables -t nat -A POSTROUTING -s 10.10.0.0/16 -o eth0 -j MASQUERADE  


Since the iptables rule is lost after reboot, the rule needs to be saved and reloaded. I have made the rule to be loaded after the networking service is started.

The command below saves the current iptables rules to the /etc/iptables.conf file.

 sudo -s  
 sudo iptables-save > /etc/iptables.up.rules 
 exit  


Next, add the following line at under the wlan0 configuration section in the /etc/network/interfaces file.

 post-up iptables-restore < /etc/iptables.up.rules

The last thing to do is to give the machine a reboot. I had a problem with the hostapd service not starting up automatically. I had to manually start it up using the following command.

 sudo service hostapd start

I will update this page once I had a chance to figure out why the service does not start up after a reboot.

After I started up the hostapd service, I was able to see and connect to the wireless hotspot from my Nexus 4. I'm happy to say that the Nexus 4 works beautifully with the hotspot created using the Edimax EW-7811Un Wifi dongle.