Showing posts with label networking. Show all posts
Showing posts with label networking. Show all posts

Wednesday, 19 October 2011

Wicd cannot connect to ad-hoc networks

In my Nokia (5800 Xpress music) phone I have a network sharing application called Joikuspot. Its purpose is to use your phone as a wireless access point offering your mobile data plan via wi-fi to other devices (such as my laptop with Arch Linux). The provided wlan network is in ad-hoc mode though and my Wicd client cannot connect to it. dmesg says: "Unable to find TIM Element in beacon". After some research I found this bug, some says that it is solved in the newest version of wicd but for me upgrading to 1.7.0 did not solve the issue.

Fortunately the ad-hoc network works fine with manual configuration. To bring down the wlan0 interface and restart it in ad-hoc mode without passphrase (as my phone app does not support protected networking) and obtaining an IP address with dhclient (dhcpcd might work as well) simply use this command:

ifconfig wlan0 down && iwconfig wlan0 mode Ad-Hoc && iwconfig wlan0 essid <ESSID_of_your_wlan> key off && ifconfig wlan0 up && dhclient wlan0

As a workaround for wicd I created a preconnect script (more about wicd scripting: here) that runs this command and does not let wicd to destroy my ad-hoc connection (because it wants to do it) until another connection is set manually in the wicd client. I used a loop that does not let the script end while a lock file exists. Choosing another connection in wicd deletes the lock file, the ad-hoc script ends and gives back the control to wicd.

The script lies under /etc/wicd/scripts/preconnect/ad-hoc.sh

#!/bin/bash

script="$(basename "$0")"
script_name="${script/.sh/}"

echo $1 $2 $3 $4 $5 >> "/var/log/wicd/${script_name}.log"

echo "Running ${script}" >"/var/log/wicd/${script_name}.log"
exec 2>>"/var/log/wicd/${script_name}.log"
exec 1>&2

connection_type="$1"
echo "Connection type: ${connection_type}"

if [ "${connection_type}" == "wired" ]; then
        profile="$3"
        echo "Profile: ${profile}"
elif [ "${connection_type}" == "wireless" ]; then
        essid="$2"
        bssid="$3"
        echo "ESSID: ${essid}"
        echo "BSSID: ${bssid}"
else
        echo "Unknown connection type: ${connection_type}" >&2
        exit
fi

rm /var/lock/wicd_adhoc.lock

case $2 in
*JoikuSpot*)
  # When I connect to my phone my ESSID contains JoikuSpot
     touch /var/lock/wicd_adhoc.lock
     ifconfig wlan0 down && iwconfig wlan0 mode Ad-Hoc && iwconfig wlan0 essid $2 key off && ifconfig wlan0 up && dhclient wlan0

     while [ -f /var/lock/wicd_adhoc.lock ]
     do
     sleep 2;
     done

esac


Waiting for the real bugfix in the newer releases of wicd!

Wednesday, 21 September 2011

Powerful networking with Wicd

Wicd is a very clever network manager. It is independent of any desktop environments meaning that it is compatible with any window managers. It has a daemon running in the background and a client with a ststus icon in the systray and a cool GUI to manipulate your network connections. Wicd handles both wired and wireless connections. You can set it up to automatically connect to the wired network when you plug in your ethernet cable and in other circumstances connect to your preferred wifi access points.

Installation is easy, just follow the Wicd Arch Wiki. I put the wicd daemon in my /etc/rc.conf (after dbus) and disabled the original networking daemon:
DAEMONS=(...dbus ... !network ... wicd ...)
I edited my .xinitrc to run the client when X starts:

...
wicd-client &
...
exec ck-launch-session wmfs

(See my actual rc.conf and .xinitrc files on the right panel of this blog.)

Above the basic networking services Wicd gives you scripting possibilities to execute programs on different networking events and different networking environments. This feature is very useful for laptops that are brought from one network to another (home / office / net café, etc.) and the behavior of the machine can be altered according to the network it is connected to. Just some ideas:
- You can automatically mount nfs and/or samba shares when you connect to your office network.
- You can start or stop daemons according to your network connection (i.e. if you use network printers you can set up your cupsd service to start only at places where you use printers).
- You can switch off your wi-fi antenna after disconnecting from a wireless network to gain battery life when your laptop is running on battery power.

Mainly I use my laptop in my office and at home. In the office I have both wired and wireless networks (at my desk I usually plug in the network cable but when I am at a meeting in another room I use wi-fi). I need the same settings for both cases. At home I use wireless internet, I do not have a printer nor do I use nfs file shares. I want to access samba shares anywhere.

You can find the preconnect, postconnect, predisconnect, postdisconnect directories under /etc/wicd/scripts/. Bash scripts placed in these directories are executed each time the appropriate network event (the nemes of the directories are self-explanatories) occurs. I use two of them but their usage depends only on your creativity.

I created a share_mount.sh script that runs after wicd connects to a network and a share_umount.sh that runs before disconnecting. If the network is wired or the wireless ESSID belongs to my office's wifi router then I start the rpcbind and nfs-common daemons to use nfs, the cupsd daemon for printing and I mount my office nfs shares (defined previously in fstab with noauto option). In all networks I start samba and smbnetfs to automatically mount samba shares after network connection. Logs go to the /etc/wicd/<script_name>.log file. I used wicd's sample scripts to build up my own ones:

Postconnect script ( /etc/wicd/scripts/postconnect/share_mount.sh ):

#!/bin/bash

script="$(basename "$0")"
script_name="${script/.sh/}"

echo "Running ${script}" >"/var/log/wicd/${script_name}.log"
exec 2>>"/var/log/wicd/${script_name}.log"
exec 1>&2

connection_type="$1"
echo "Connection type: ${connection_type}"

if [ "${connection_type}" == "wired" ]; then
profile="$3"
echo "Profile: ${profile}"
elif [ "${connection_type}" == "wireless" ]; then
essid="$2"
bssid="$3"
echo "ESSID: ${essid}"
echo "BSSID: ${bssid}"
else
echo "Unknown connection type: ${connection_type}" >&2
exit
fi

case $2 in "wired" | "myoffice_essid")
# I am at office:
rc.d start rpcbind nfs-common cupsd;
mount -a -t nfs;;
esac
# I am anywhere:
rc.d start samba smbnetfs


Predisconnect script ( /etc/wicd/scripts/predisconnect/share_umount.sh ):

Before disconnecting a network this script handles the file unmounting and daemon stopping process in the opposite way I used in my connect script.

#!/bin/bash

script="$(basename "$0")"
script_name="${script/.sh/}"

echo "Running ${script}" >"/var/log/wicd/${script_name}.log"
exec 2>>"/var/log/wicd/${script_name}.log"
exec 1>&2

echo umounting nfs and smb filesystems
#umount /media/Erba_nfs
umount -a -t nfs
rc.d stop cupsd smbnetfs samba nfs-common rpcbind


Wicd's actual (1.7.0) version is not able to handle ad-hoc networking. Scripts can help you again, see the workaround here.

Wednesday, 14 September 2011

Networking mystery with Realtek r8169

eth0 stopped working. Maybe due to the 3.0 kernel upgrade?
dhcpcd showed "Link is not ready" and "no carrier" and I could not get an IP.
I tried dhclient instead of dhcpcd, no results, although dhclient seems to be a nicer solution in general (more informative log output and faster connection in my opinion).

My ethernet driver according to lspci -v is:

09:00.0 Ethernet controller:
Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet controller (rev 03)

Subsystem: Lenovo Device 21c5
Flags: bus master, fast devsel, latency 0, IRQ 42
I/O ports at 2000 [size=256] Memory at f0804000 (64-bit, prefetchable) [size=4K] Memory at f0800000 (64-bit, prefetchable) [size=16K] [virtual] Expansion ROM at f0820000 [disabled] [size=128K] Capabilities: [40] Power Management version 3 Capabilities: [50] MSI: Enable+ Count=1/1 Maskable- 64bit+ Capabilities: [70] Express Endpoint, MSI 01 Capabilities: [ac] MSI-X: Enable- Count=4 Masked- Capabilities: [cc] Vital Product Data Capabilities: [100] Advanced Error Reporting Capabilities: [140] Virtual Channel Capabilities: [160] Device Serial Number 4e-00-00-00-68-4c-e0-00
Kernel driver in use: r8169
Kernel modules: r8169

Google says that the r8169 driver is buggy, if any problem occurs installing a newer driver can help. Ok. How?

* If you have the same issue, please go to the end of this post for a possible solution, you might not need to do all these steps I made.

AUR's r8169 package did not work for me, the download link had an authentication problem, the driver could not be downloaded.

OK. Let's find another source, realtek's homepage:

http://www.realtek.com.tw/downloads/downloadsView.aspx?Langid=1&PNid=5&PFid=5&Level=5&Conn=4&DownTypeID=3&GetDown=false#RTL8111B/RTL8168B/RTL8111/RTL8168%3Cbr%3ERTL8111C/RTL8111CP/RTL8111D%28L%29%3Cbr%3ERTL8168C/RTL8111DP/RTL8111E%3Cbr%3ERTL8168E/RTL8111F

Actually this package should install the r8168 driver and remove the native r8169 one.
After clicking on several dead links on Realtek's page one moment I could finally download the "LINUX driver for kernel 2.6.x and 2.4.x (Support x86 and x64)" (8.025.00 ) driver package.
I unpacked the tarball and went on the way that the README said but again I faced a problem: the r8168 module could not be loaded (modprobe r8168 said: "FATAL: Module r8168 not found."). At the same time r8169 could not be loaded either (the installation moved it to somewhere else), so now i had no ethernet driver at all. Sad thing, now what?

Googling again I found the solution after a day of madness:
Download the above mentioned Realtek driver package, untar it, step into the install directory, run the autorun.sh according to the README. After do this as root (still in the installation directory):

depmod -a
insmod ./src/r8168.ko
cp ./src/r8168.ko /lib/modules/$(uname -r)/kernel/drivers/net/
modprobe r8168

Now the last two lines of lspci -v have to say something like this:
Kernel driver in use: r8168
Kernel modules: r8168

(instead of r8169).

Now edit your /etc/rc.conf and put r8168 into the MODULES section. If r8169 was there then delete it or restrict it with (... r8168 !r8169 ...)

Huh, that was a hard day!

* And now I see that AUR has a r8168 package. Probably installing this could have solved my problem in one step but it is too late, I have done it in a different - apparently much more difficult - way. Please try this AUR package first if you have a similar problem. You still might need to change your daemons array in your rc.conf to use the newly installed driver instead of the old one.