[tux networking]

Howto Set Up Multiple Network Schemes on a Linux Laptop

Redhat Linux comes with nifty GUI programs such as redhat-config-network which make it easy to configure one network.  Debian comes with even better network configuration scripts, though they aren't GUI driven.

Unfortunately, they aren't all that tractable on a laptop where you need to alternate among several different network cards (for instance, a pcmcia ethernet card, a PCMCIA wireless card, and a pcmcia modem) at several different locations (some of which use a fixed IP while others use DHCP).

This HOWTO will discuss easy ways of setting up schemes, to make it very easy to move among different types of networks.  It was tested primarily on Redhat 8.0 and Debian Sarge (Libranet).  Things may be slightly different on other versions, so you may have to adjust file or directory names somewhat.


Debian includes a package called netenv which is intended to solve this problem. I haven't managed to get it to work on my laptop (it prompts me at boot time for a scheme, then proceeds to ignore it) but you may have better luck.

Contents

  1. Setting the hostname (Redhat)
  2. Cardbus or PCMCIA?
  3. Cardbus/PCMCIA on Redhat
  4. Cardbus/PCMCIA on Debian
  5. PCMCIA: an Older Approach
  6. Some Possible Problems
  7. Wireless Networks
  8. PPP+Local Net
  9. To Do

Setting the hostname

Redhat's installer doesn't let you specify a hostname unless you have a network connected at the time you install. On a laptop that needs a PCMCIA network card, chances are you had no network and are now stuck with "localhost". Yuck! No amount of fiddling with the gui network scripts seems to result in a hostname that shows up if you boot your machine without the network card. To set your hostname so that it will persist through reboots,
  1. Edit /etc/network and set your hostname (and domainname, if desired) there.
  2. Edit /etc/hosts and add your desired hostname to the localhost line. (If you omit this step, the hostname command will print an error.)

Network card: Cardbus or PCMCIA?

First: it turns out that there are two different answers depending on whether your network card is PCMCIA (16-bit) or Cardbus (32-bit).  One solution is to use pcmcia-cs' built-in scheme mechanism, but it doesn't work for cardbus, because the /etc/pcmcia scripts aren't called at all for cardbus cards.  It also presumably  isn't useful for laptops with built-in networking, because there aren't any PCMCIA insertion events.  (Perhaps there's a way to force this to happen ... let me know if you find out!)  So I'll start out describing the cardbus mechanism, but later I'll describe the PCMCIA scheme mechanism since it may be useful to someone.

If you're using neither Cardbus nor PCMCIA, but are reading this for use with a laptop with integrated networking, or a desktop machine which gets moved between networks, you can skip the PCMCIA/Cardbus sections.  You may want to check out netplug, or ifplugd, or Netenv, in order to autodetect when you plug in your network cable, and automatically run ifup for you.  Apparently most but not all cards support this now.

Cardbus Cards (should also work with PCMCIA)

First: On Redhat

Cardbus cards are handled by the hotplug mechanism, rather than the PCMCIA mechanism.  Curiously, this is the mechanism that Redhat uses for its networking anyway, so you'd think you'd be all set, right?  Not so -- not if you want to use multiple schemes.

If you've already set up a network interface using the gui tools, you may want to remove it (the simple way), but if not, you need to disable it, using the same ifupXXX mechanism described above.  We'll be using /sbin/ifup, but not from there.  Don't worry about the /etc/pcmcia changes; we won't be needing them. If this is a new install and you haven't set up any networking yet, you can skip this part.

New!  I recently discovered a nifty automatic scheme which works much better (at least on Redhat 8) than my previous manual scheme.  If you've been to this document in the past, check this out!

When Redhat sets up a network interface (assuming it's the only interface on the machine), it looks for a file called /etc/sysconfig/network-scripts/ifcfg-eth0, and uses the values in that script.  So if you can get that file to point to the right place for wherever you are, you're done and Redhat will do the rest of the work for you.

First, you have to make the files with the values you need.  I put the files in /etc/sysconfig/networking/default/ifcfg-schemename, because that's where the ifup command looks; if my ifcfg-home script lives there, then if I ever need to configure networking manually, I can say ifup home.  Note that /etc/sysconfig/networking/default doesn't exist on a standard Redhat system, so I had to create it:
  mkdir /etc/sysconfig/networking/default
Then, if you have an existing configuration, copy it there, naming it according to the scheme you want it to represent, so to make a scheme called "home":
  cp /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/networking/default/ifcfg-home
or if you don't have an existing configuration, just make a new file by that name, which should look something like this.  There's some documentation on this format (but not enough) in /usr/share/doc/initscripts-*/sysconfig.txt.
TYPE=Ethernet
DEVICE=eth0
HWADDR=nn:nn:nn:nn:nn:nn
BOOTPROTO=dhcp
DHCP_HOSTNAME=myhost
 - or -
TYPE=Ethernet
DEVICE=eth0
HWADDR=nn:nn:nn:nn:nn:nn
BOOTPROTO=static
HOSTNAME=myhost
IPADDR=nnn.nn.nn.nn
BROADCAST=nnn.nn.nn.nn
GATEWAY=nnn.nn.nn.nn
PEERDNS=yes
DOMAIN=mydomain.com
DNS1=nnn.nn.nn.nn
DNS2=nnn.nn.nn.nn

Discussion:

HWADDR restricts this profile to work only on one network card.  Remove that line, and it will work on any card (wired or wireless) that you insert.  Yay!
PEERDNS tells Redhat's script to modify /etc/resolv.conf to add your MYDOMAIN and DNS1 and DNS2 servers.  (Unfortunately it ignores any further entries; two servers is the most it can handle.)  Omit all of these if you don't need resolv.conf modified.  However, the script is a little flaky.  If it doesn't work for you, then just make your own resolv.conf files, and swap them in as part of your netscheme script (below).

Switching schemes

Now you need an easy way to switch between schemes.  Here's the little script I wrote to do that.  I named it /usr/local/bin/netscheme and run it as root.
#! /bin/sh
fnam=/etc/sysconfig/network-scripts/ifcfg-eth0

if [ $# -le 0 ]; then
echo -n "Current scheme: "
ls -l $fnam | sed -e 's/.*-//'
exit 0
fi

/bin/rm $fnam
ln -s ../networking/default/ifcfg-$1 $fnam
echo Set scheme to $1
Now I say netscheme home or netscheme dhcp, and the next time I insert the card, hotplug handles everything automagically.  (If it fails to do so, try ifup schemename or ifup eth0.)

The Debian Version

Debian controls network interfaces through the file /etc/network/interfaces. There used to be a way of adding multiple mappings in that file (see below) but that no longer seems to work. Fortunately, there's a simpler and even easier way to switch between multiple schemes.

Create a directory called /etc/network/schemes. Inside it, make files for each scheme you want, with names interfaces-schemename. So I might have interfaces-home and interfaces-work. Each of these files is a complete copy of what you want /etc/network/interfaces to look like in that location. If you need to change your DNS servers, also make a file called resolv.conf-schemename in the same directory.

Then make a simple script, /etc/network/schemes/netscheme, that looks like this:

#! /bin/sh

if [ $# -le 0 ]; then
  echo -n "Current scheme: "
  cat /etc/network/schemes/current
  exit 0
fi

newscheme=$1
echo "Changing scheme to $newscheme"

echo $newscheme >>/etc/network/schemes/current

cp /etc/network/schemes/interfaces-$newscheme /etc/network/interfaces
if [ -f /etc/network/schemes/resolv.conf-$newscheme ]; then
  cp /etc/network/schemes/resolv.conf-$newscheme /etc/resolv.conf
fi

Finally, to make this easy, either make the script setuid root, or make an alias: alias netscheme='sudo /etc/network/schemes/netscheme' (and, if you want, include /etc/network/schemes/netscheme in the list of commands you're allowed to run nopassword in /etc/sudoers).

Now you can type netscheme home or whatever, and be all set to run with the right settings. Easy.

An Older Debian Approach

Debian used to have something called "mappings" that you could put in the interfaces file. But that hasn't worked for me on recent distros. I'm including the old instructions in case they might still be relevant somewhere:

Debian, happily, already has a network scheme setup, which is well described in this mailing list posting

Basically, you edit /etc/network/interfaces, and make entries that look like this:

mapping eth0
script /etc/network/map-scheme.sh
map home eth0-home
map work eth0-work

iface eth0-home inet static
address nn.nn.nn.nn
netmask nn.nn.nn.nn
broadcast nn.nn.nn.nn
gateway nn.nn.nn.nn
up cp /etc/network/resolv.conf.home /etc/resolv.conf

iface eth0-work inet dhcp
hostname myhost
Now you need a little script called /etc/network/map-scheme.sh.  It looks like this (this is cribbed and slightly modified from the mailing list posting I mentioned earlier):
#! /bin/sh
iface="$1"
if [ "$iface" = "" ]; then iface="eth0"; fi
if [ -f /etc/network/scheme ]; then
  scheme=$(cat /etc/network/scheme)
  echo $iface-$scheme
else
  echo $iface
fi
exit 0
But you still need an easy way to switch schemes on Debian, so I wrote a little /usr/local/bin/netscheme script for Debian too (calling it netscheme on both machines means that I don't have to remember two different sets of commands when I switch distros).  Here's my Debian script:
#! /bin/sh
if [ $# -le 0 ]; then
echo -n "Current scheme: "
cat /etc/network/scheme
exit 0
fi
echo "$1" > /etc/network/scheme
Now I can say netscheme home or netscheme dhcp to change the scheme when I change locations, just like on Redhat.

But wait!  Debian needs one more thing.  /etc/network/interfaces can't handle DNS, so you won't be able to resolve any external names.  For DHCP, this isn't a problem (the DHCP script should generate one based on information from the server) but for static schemes you need your own resolv.conf.  To handle this, I make copies of all the resolv.conf files I might need (see man resolv.conf for more info, or, easier, just copy one from any machine on your network) and stick it in /etc/network/resolv.conf.schemename.  Then I add one more line to my static scheme, which looks like this:
  up cp /etc/network/resolv.conf.home /etc/resolv.conf
for the case of the home scheme.

Making Debian hotplug handle cardbus cards

Debian doesn't automatically handle my cardbus ethernet card via hotplug like Redhat does.  So even if the scheme is set, the network doesn't start automatically when I insert the card: I have to run ifup eth0 manually.  With a PCMCIA card, I expect everything would happen automatically.  But I figured out how to make hotplug do this automatically when the card is inserted, on a couple of different Debian installs.

First, try editing /etc/hotplug/net.agent.  Look for the line that says "case $ACTION in", then below that, find where it calls exec /sbin/ifup $INTERFACE$LIFACE.  Remove the $LIFACE from that line, and see if your card is configured now.  $LIFACE is the string "=hotplug", so it was calling ifup eth0=hotplug, and ifup apparently doesn't know how to deal with that.  Perhaps if you added an "eth0=hotplug" line to /etc/network/interfaces in just the right way, it would work, but I haven't come up with a syntax that makes it happy.

If editing net.agent doesn't work, you may have to add a script to call ifup.  This is a bit of a hack, and perhaps there's a better way.  First, you have to know what module your card uses.  For mine, it's 3c59x.  Then do the following:
mkdir /etc/hotplug/pci
Create a file called /etc/hotplug/pci/3c59x (substitute the name of your card's module). In it, put commands similar to this.  ^G means a control-G, the console beep character: this simulates the two beeps you hear upon inserting pcmcia cards, though unfortunately you don't get the high-or-low beep for success or failure.
#! /bin/sh
echo "^G" >/dev/console
/sbin/ifup eth0
echo "^G" >/dev/console
(Substitute eth1 if needed.)  Make it executable:
chmod 755 /etc/hotplug/pci/3c59x
Now the hotplug system should see your card and configure the network appropriately.

What if hotplug doesn't configure the card?

Hotplug debugging tips:  The files in /etc/hotplug are all scripts, so you can add "echo" statements to them to see where it's going and what it's doing.  The catch is that you may not see these echoes, especially if you're in X.  So use lines like this:
echo "Entering pci.agent" >>/etc/hotplug.dbg
scattered throughout the hotplug scripts you want to debug.  The >> makes it append to the file, so you'll be able to read that file as a log of what it did.  Try adding lines like this to pci.agent, net.agent, and also to files in /etc/pcmcia since cardmgr may be stealing the event before hotplug gets it.

PCMCIA Schemes (an older approach)

After much goggling and fiddling, I came up with a setup that works nicely.  The gist is this:

There are two different systems called when a PCMCIA card is inserted: cardmgr (PCMCIA-only) and hotplug (a general system which also covers USB and firewire).  Hotplug is a nice general system; but for networking, cardmgr has the advantage that it has a built-in scheme mechanism which can define multiple zones with different behaviors for each zone.

Redhat's native network setup, located mostly in /etc/sysconfig/networking and /etc/sysconfig/network-scripts, is called from hotplug; so Redhat disables the networking part of cardmgr, though the cardmgr system is still there for use with other types of PCMCIA cards.  If you want schemes to work, you have to re-enable the cardmgr scripts and disable the hotplug ones.  These steps will guide you through this:
  1. Disable hotplug control of networking.  Edit /etc/hotplug/net.agent.  Search down to where it says "RedHat and similar" and find the line that says
    if [ -x /sbin/ifup ]; then
    and change it to say:
    if [ -x /sbin/ifupXXX ]; then
    Now it will skip that clause, because there's no program called /sbin/ifupXXX.
  2. Enable cardmgr control of networking.  You can do this by installing the full pcmcia-cs package, but you already have most of it: really all you need is two files: /etc/pcmcia/network and /etc/pcmcia/network.opts.  If you have a non-Redhat system handy, you can just copy those two files from the other system; or you can copy those files from a pcmcia-cs distribution.  Either way, plunk them down in /etc/pcmcia (you might want to copy the existing /etc/pcmcia/network script somewhere safe first).
  3. Edit /etc/pcmcia/network.opts to customize it for your setup.  This is the file where your schemes should be defined.  The file you copied should have samples of the format.  A DHCP scheme will probably look something like this:
         INFO="Scheme for use at work"
    HOSTNAME="mymachine"
    BOOTP="n"
    DHCP="y"
    DOMAIN="mycompany.com"
    SEARCH="$DOMAIN myotherdomain.org"
    A domain where you're using a static IP address will set DHCP to "y" and add fields for IPADDR, NETMASK, BROADCAST, GATEWAY, DNS_1, DNS_2, and DNS_3.
  4. Now you're ready to test your schemes.  First, set a scheme: cardctl scheme schemename and verify that it set it, by typing cardctl scheme and making sure it returns the right name.  Now insert the pcmcia card, and check with ifconfig -a that it got the expected address.

Some Possible Problems:

Wireless Networks:

If you don't specify HWADDR, then both the Redhat and the Debian script should transparently work with a wi-fi card as well as a lan card.  Hooray!

If you want to do security, though, you'll need some additional work. So far, I've only experimented with WEP (yes, I know it's not secure, but it's probably better than nothing, right?)  Here's how to do WEP, ad-hoc, DHCP and other fun wireless tricks.

Debian

Here's a typical /etc/networks/interfaces setup for a WEP network that has both an essid and a key:

auto eth0
allow-hotplug eth0
iface eth0 inet dhcp
wireless-essid my-essid
wireless-key my-hex-key

The allow-hotplug line is important, otherwise modern udev-based kernels won't notice when you plug in the pcmcia card. (Sometimes they won't anyway, but you have a better chance if that line is there.)

Of course, you can replace the dhcp line with the lines to set a static IP address, while keeping the essid and key lines. Mix 'n' match.

Older Debian

(This method no longer works reliably for me starting with Ubuntu Breezy: the "up", "pre-up", etc. lines are no longer executed at all even though the documentation says they should work.)

After letting the card configure itself with a static address, I can connect if I make the following script and call it /etc/network/do_wep:

#!/bin/sh
iwconfig eth0 key xxxx-xxxx-xx
(or you can also say "key s:passwd").  Then in the Debian interfaces file, in the static ip section right before the up cp resolv.conf line, I add this line:
up sh /etc/network/do_wep
That means that after configuring the static IP address information, the script will check whether it's a wireless card, and if it is, it will set the appropriate WEP key and password.

Theoretically I should be able to put the iwconfig command directly into the interfaces file, but I haven't always had success doing that.  Try it and see.

If you have a network that does something tricky like set a special essid before it will give you your DHCP negotiation, first try putting these line into interfaces (you may not need the first line, depending on which wireless driver you use):
wireless-mode managed
wireless-essid whatever
If that doesn't work, create a script called do_essid with this in it:
iwconfig eth0 essid whatever
then call it this way in interfaces:
  pre-up sh /etc/network/do_essid
Some drivers, such as the hostAP Prism 1/2 driver, require an essid line.  If you don't know your essid, try this:
wireless-essid ANY

Redhat

On Redhat, it's even easier: just add
KEY="xxxx-xxxx-xx"
to the ifcfg-scheme file, perhaps with a MODE=Managed if you want to be explicit about things.

Redhat 8 warning: The Redhat 8 2.4.18 kernel uses obsolete network modules, so if you use a more recent kernel, the module names required by the pcmcia modules are all wrong (for instance, it will try to load the nonexistant wvlan module instead of orinoco).  If it can't find the module, it bails and skips the rest of network setup, and doesn't even register the eth0 device, so you can't proceed with ifup eth0 by hand.  I'm still trying to find a way around this; but I'm not trying very hard, since I use 2.4.21 most of the time anyway.  Curiously, for only one network card, wireless worked just fine for me on the stock kernel, and I'm not sure what the difference is.

Ad-hoc Wireless Networking:

This is so cool!  Just add to your existing setup (Redhat)
ESSID=whatever
MODE=ad-hoc
or make a script (Debian) do_adhoc called as an up post-command that does this:
iwconfig eth0 essid whatever
iwconfig eth0 mode ad-hoc
and you're ready to network with another laptop that's set up similarly, with no need for a WAP or other infrastructure.  Take them anywhere!

PPP + Local Net:

For ages I've wanted a simple way to set up PPP and ethernet at the same time, so that on trips, my husband and I could share a single PPP connection between our two laptops.  We finally have it, and it turns out to be fairly simple!  It doesn't matter whether the second connection is a network card, wireless, or ad-hoc wireless; they're interchangeable and all follow the principles outlined in the rest of this document.

I'm not going to write up a full howto here, but there are a few important keys you need to know:

First, on the gateway machine (the one that is going to run the modem connection), you need a network scheme that uses static IP addresses (we use the 192.168.1 network) and no gateway entry.  No gateway is very important; if you leave in your gateway line, then as soon as you activate the network, it will take over and leave your PPP connection dead.

On the slave machine (the one not running the modem), set the gateway to be the local IP address (on the 192.168.1 net or whatever local network you're using) of the machine with the modem, and that should be all you need to do on that machine.

Finally, on the gateway machine, you need iptables installed and configured.

Once all these are in place, do these steps:
  1. Start the PPP connection on the gateway.
  2. Start local networking on both machines (order not important).
  3. Verify that the machines can talk to each other locally, and that the gateway machine can still see the outside world through PPP).
  4. Use iptables to turn on connection sharing, using this lesson from linuxchix which explains it much better than I would.
  5. If everything is working, then from the slave machine, scp /etc/resolv.conf from the gateway machine; or else set up a DNS server on the gateway machine.

To Do:

(Other network types, plus fun things I'd like to investigate)

Firewire networking: Another cool way of sharing a connection between laptops.  Might be fun to play with some day.

Offline mail: I've been investigating various approaches to offline mail, and I'm nearly ready to write up some of my techniques.

Linux Links
Shallow Sky Home