Friday, 13 March 2009

ifup: network-functions: line 52: eth0: No such file or directory

The (external) power supply on my Linux box broke the other day. Tranquil PC sent me a new one, so I booted the machine up for the first time in ages. I noticed an error message as it was trying to bring up the eth0 interface (which is nicknamed "moors" on my machine):

ifup: network-functions: line 52: eth0: No such file or directory

This appeared twice every time I booted the machine.


I looked in /etc/sysconfig/network-script/network-functions, and line 52 was the (rather unhelpful):

. $CONFIG

I went through a prolonged debugging session, putting trace code in ifup and network-functions, and I found the problem was caused by line 155 of ifup:

is_available ${REALDEVICE}

REALDEVICE at this point is "eth0". is_available starts like this:

LC_ALL= LANG= ip -o link | grep -q $1
[ "$?" = "1" ] || return 0

alias=`modprobe -c | awk "/^(alias|install)[[:space:]]+$1[[:space:]]/ { print \\$3 }"`
if [ -z "$alias" -o "$alias" = "off" -o "$alias" = "/bin/true" ]; then
return 2
fi
modprobe $1 > /dev/null 2>&1 || return 1
# if it is a mainframe ccwgroup device, configure it before
# trying to rename it:
need_config ${1}

I haven't figured out what all the tests at the top do, but (for eth0 only, and only when rebooting) control comes through to the call to need_config. need_config looks like this:

CONFIG="ifcfg-${1}"
[ -f "${CONFIG}" ] && return
CONFIG="${1}"
[ -f "${CONFIG}" ] && return
local addr=`get_hwaddr ${1}`
if [ -n "$addr" ]; then
local nconfig=`get_config_by_hwaddr ${addr}`
if [ -n "$nconfig" ] ; then
CONFIG=$nconfig
[ -f "${CONFIG}" ] && return
fi
fi

So CONFIG gets changed from "ifcfg-moors" (which is what it was to start with) to "eth0" - and there is no such file (nor an ifcfg-eth0) in /etc/sysconfig/network-scripts.


I have "fixed" the problem by adding a line to the top of need_config:

[ -f "${CONFIG}" ] && return

but this is the ravings on someone who doesn't really know what is going on!


Helpful suggestions welcome.

Thursday, 5 March 2009

Adding a second Internet connection - part 2

Now I have routing working properly on my new router, I took the opportunity to move it onto eth0 (my firewalled, "dirty" interface).


First, I set up a new aliased ethernet port on the Linux box, using the Gnome System Settings/Network tool. I gave this IP address 192.168.0.1 (no default gateway).


Then I connected to the new router, and changed its IP address to 192.168.0.250. I physically moved it onto the eth0 network. Finally I telnetted to it and set up its own routes, as follows:

D-Link> ip route addrom index 1
D-Link> ip route addrom name gbit
D-Link> ip route addrom set 192.168.3.0/24 192.168.0.1 1
D-Link> ip route addrom save
ip route addrom: save ok
D-Link> ip route addrom index 2
D-Link> ip route addrom name mbit
D-Link> ip route addrom set 192.168.1.0/24 192.168.0.1 1
D-Link> ip route addrom save
ip route addrom: save ok
D-Link> ip route addrom index 3
D-Link> ip route addrom name dirty
D-Link> ip route addrom set 192.168.2.0/24 192.168.0.1 1
D-Link> ip route addrom save
ip route addrom: save ok

This set up the following static routes:

Dest FF Len Device Gateway Metric stat Timer Use RN
192.168.0.0 00 24 enet0 192.168.0.250 1 041b 0 1150
192.168.1.0 00 24 enet0 192.168.0.1 1 001b 0 0
192.168.2.0 00 24 enet0 192.168.0.1 1 001b 0 0
192.168.3.0 00 24 enet0 192.168.0.1 1 001b 0 445

Then I altered the routes on the Linux box as follows:

ip route add 192.168.2.0/24 dev eth0 src 192.168.2.1 table ISP1
ip route add default via 192.168.2.5 table ISP1

ip route add 192.168.0.0/24 dev eth0 src 192.168.0.1 table ISP2
ip route add default via 192.168.0.250 table ISP2

ip route add 192.168.2.0/24 dev eth0 src 192.168.2.1
ip route add default via 192.168.2.5

ip rule add from 192.168.2.1 table ISP1
ip rule add from 192.168.0.1 table ISP2

I also set up static routes for some IP addresses I wanted to reach via one or other ISP (e.g. their DNS servers).


That all works - I can connect in from outside via either of the two routers (I have set up identical NAT mappings on both). I can easily switch to the secondary router like this:

ip route del default
ip route add default via 192.168.0.250

I am now considering load balancing between the two routers. I think the commands to do this would be:

ip route del default
ip route add default scope global nexthop via 192.168.2.5 dev eth0 weight 6 nexthop via 192.168.0.250 dev eth0 weight 1

Thursday, 19 February 2009

Adding a second Internet connection

I have just installed a second ADSL connection, intending it to be a backup in case the first one goes down. This comes with a DSL-2640R NAT router (including firewall).


My existing network is somewhat complicated - at its heart is a CentOS 4 Linux box from Tranquil PC, with three network cards, which routes between the three networks.


  • My existing ADSL router is on eth0 (192.168.2.1) at 192.168.2.5.
  • I have a 100 Mbit network on eth1 (192.168.1.1)
  • I have a Gbit network on eth2 (192.168.3.1)

Although I want untimately to set up load sharing and automatic failover, to start with I just wanted everything to work, viz:

  • All machines on the network to have access to the Internet, and all other machines (including both ADSL routers).
  • To be able to connect to the Linux box from outside, via either Internet connection.

The first thing I did was to assign the new DSL-2640R router IP address 192.168.1.250, turn off DHCP (so it didn't conflict with the existing DHCP server) and add it to the network on eth1. I originally tried to put it on the same network as the existing router, but I don't understand how it would be possible to distinguish outside traffic coming in via the two routers unless they were on separate interfaces. It may be worth trying a virtual interface here.

Allowing the router to see the other networks


Now I could see the DSL-2640R from the Linux box, but not from either of the other networks (as the DSL-2640R did not have a setting for default gateway on its LAN side, so it couldn't find a route back to the other networks).


I first tried setting up NAT on the Linux box for the eth0 interface, by editing /etc/sysconfig/iptables as follows:

*nat
:PREROUTING ACCEPT [39:3410]
:POSTROUTING ACCEPT [33:2787]
:OUTPUT ACCEPT [10:677]
-A POSTROUTING -d 192.168.1.250 -o eth0 -j MASQUERADE
COMMIT

That enabled me to see the web interface of the DSL-2640R from anywhere on my network, but did not allow incoming traffic from the router to see the rest of my network.


I discovered that the router has a telnet interface, which shows the following help (once you have logged in and typed "help"):

Valid commands are:
sys exit ether wan
ip bridge dot1q pktqos
show set lan

Although I couldn't find any documentation for this interface, it looked remarkably familiar to the one on my ZyXel Prestige 660HW, for which I did have documentation.


I therefore set up two static routes in rom (so they survive a reboot), as follows:

D-Link> ip route addrom index 1
D-Link> ip route addrom name gbit
D-Link> ip route addrom set 192.168.3.0/24 192.168.1.1 1
D-Link> ip route addrom save
ip route addrom: save ok
D-Link> ip route addrom index 2
D-Link> ip route addrom name dirty
D-Link> ip route addrom set 192.168.2.0/24 192.168.1.1 1
D-Link> ip route addrom save
ip route addrom: save ok

That worked fine, so I reverted iptables to its original state.

Enabling incoming traffic


The next step was to enable incoming traffic from the DSL-2640R. I first opened up the necessary ports in the DSL-2640R's NAT setup, redirecting them all to the Linux box on 192.168.1.1. That allowed the incoming traffic, but the Linux box couldn't reply, because its default route back was via the original ADSL router at 192.168.2.5. Having read an article at http://lartc.org/howto/lartc.rpdb.multiple-links.html, I amended the routing tables on the Linux box. I first added two new tables to /etc/iproute2/rt_tables

200 ISP1
201 ISP2

Then added routes to these tables:

ip route add 192.168.2.0/24 dev eth0 src 192.168.2.1 table ISP1
ip route add default via 192.168.2.5 table ISP1

ip route add 192.168.1.0/24 dev eth0 src 192.168.1.1 table ISP2
ip route add default via 192.168.1.250 table ISP2

ip route add 192.168.2.0/24 dev eth0 src 192.168.2.1
ip route add default via 192.168.2.5

ip rule add from 192.168.2.1 table ISP1
ip rule add from 192.168.1.1 table ISP2


I don't fully understand how all this works (and I would be grateful if anyone explains it to me), but it does seem to.

Switching between the two Internet connections


The next step is to allow switching the default gateway between the two routers (in case the primary one goes down). This is done using a couple of scripts:

# Switch to new Internet connection
ip route del default
ip route add default via 192.168.1.250


#Switch to original Internet connection
ip route del default
ip route add default via 192.168.2.5


That works too - I may set this up to switch automatically, or to load balance, but I think I've done enough for now.

Tuesday, 15 July 2008

Debugging PHP using Eclipse and DBG

I've recently got back in to writing PHP code, and decided I would like to use an IDE with integrated debugger, like I am used to with C, C++, C#, Java and other languages.


Having reviewed the available IDEs that support PHP, I chose Eclipse - mostly because it supports a variety of languages, and I wanted to see if it was as good as people said.


I installed Eclipse from www.eclipse.org onto a Windows XP machine. Then I installed PHPeclipse from www.phpeclipse.net.


I then installed the DBG PHP debugger from dd.cron.ru/dbg/onto my Linux server.


I had some difficulty getting debugging to work. Firstly, I had to update PHPeclipse from the nightly build (this is done in Help, Software Updates), and make sure only DBG support was included (only one debugger is allowed to be installed at a time). Secondly, I found remote debugging did not work at all - all attempts to debug gave the message "failed to establish connection to client host on localhost:10001".


It turns out that DBG requires HTTP_SERVER_VARS to be set in order to find out the IP address of the machine running Eclipse, but CentOS 5 disables this variable by default. The solution was to add
register_long_arrays On
to php.ini to re-enable the variable.


It is a little too early to give my impressions of Eclipse - I haven't really found my way about it properly yet. But debugging PHP now (mostly) works, and that in itself is really useful.

Tuesday, 29 April 2008

Running Xen Virtual Machines full screen

I'm playing with running Windows in a Xen VM, with Centos 5 as the host O/S. One of the things I want to do is for the VM to appear exactly as it would if it was the native O/S - to do that, it has to take up the whole screen. The Xen virtual machine console does have a Full Screen option on its View menu, but it definitely does not do what it says on the tin!


I have solved this problem - what I do is to start an X Window server on another virtual screen as display 1, with its only client vncviewer running in full screen mode.


The command line I used was
startx /usr/bin/vncviewer -FullScreen -MenuKey F12 localhost:1 -- :1
. This starts an X session on display :1 (the one you see if you press Ctrl-Alt-F8), running vncviewer full screen with the VNC menu key set to F12, connecting to VM 1. You can then switch back to your host O/S display with Ctrl-Alt-F7


By the way, I have discovered a very useful Xen VM option (which should, IMHO, be the default for Windows VMs) - usbdevice = 'tablet'. This makes Windows think it has a USB graphics tablet, so the mouse cursor tracks the mouse cursor in the VNC viewer exactly. Without this you end up in the horrible situation of having Windows thinking the mouse cursor is in a different place to where you are pointing, and actually refusing to let you point at part of the screen.

CentOS 5 dual display

I've just taken delivery of a nice Tranquil PC T2e with a 2GHz Intel Core 2 Duo T7200, 4GB of RAM, a 500 GB disk and a twin head graphics card.


I hope to set it up as a virtual PC platform, running my main development system (Windows XP Pro) in a virtual machine, test systems and various flavours of Linux in more virtuam machines.


I initially installed CentOS 5 with the Xen kernel to host the VMs.


However, I was struggling to get dual head working with the ATI Radeon HD 3450 graphics card in the machine - as soon as I used the GUI to tell X Windows to use dual head, X stopped working. Hacking xorg.conf to use the ati drivers that come with CentOS caused an error message that it can't find an ATI Mach 64 card. The proprietary drivers from ATI fail to load with undefined symbols.


I solved this problem by getting an older ATI Radeon X600 card - the standard radeon drivers that come with CentOS understood this card, and it was then simple to get it working.

Tuesday, 8 April 2008

Setting up the Tortoise SVN client

I use the Subversion revision control system for all my development projects. It keeps a complete history of every change to every source file in each development project. As well as enabling me to determine exactly what source was used to build a particular version of a product, it also lets me find out what changes I made which introduced a problem or feature. Its branching and merging facilities make it possible for multiple developers to work on the same project without interfering with each other. But, as a friend on the CIX conferencing system once said, "a revision control system is vital for any projects with more than zero developers".


I also use Tortoise SVN as my Windows client for SVN. Here is how I set it up.


First download and install the latest Tortoise SVN. This will add itself into Windows Explorer, providing additional right-click options on files and folders. Now right-click on any folder, choose TortoiseSVN from the menu, and Settings from the sub-menu. You can change which of the many SVN options appear on the initial right-click menu, and which on the TortoiseSVN sub-menu in the "Look and Feel" section.


By default, Tortoise will check every folder on all your hard drives to see if they are SVN folders, and keep cached information about them. This can slow Windows Explorer a little if you have lots of folders. I keep all my SVN checked out sources in one of about 5 folders (one for each of my major customers, and one for my own development). You can tell Tortoise only to check these folders in the "Icon Overlays" section - untick all the "Drive Types" boxes, then add the paths to the "Include paths" box. Finish each path with "\*" (e.g. "C:\Development\*") to also include sub-folders.


If you use Tortoise to connect to report SVN repositories, you will usually use an "svn+ssh:user@domain/project/trunk" style of URL to tell Tortoise where to find the repository. If the repository's SSH server is on an unusual port (see Hacking SSH for details), you will need to configure ssh to use the port. To do this set up putty saved sessions for each of your SVN servers, using the appropriate user name, host name and port. Then use the saved session instead of a full username@domain - e.g. "svn+ssh:@savedsession/project/trunk".


I like to see the SVN revision number and status against all SVN files in Windows Explorer. To do this, display the folder in detail view, right click on the column headings at the top, choose "More...", and scroll down that list to the ones beginning SVN. Tick the ones you want (I like Status and Revision) and they will be included. You can then click on the Status column to sort your directory display with the modified files at the top.