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
- Setting the hostname (Redhat)
- Cardbus or PCMCIA?
- Cardbus/PCMCIA on Redhat
- Cardbus/PCMCIA on Debian
- PCMCIA: an Older Approach
- Some Possible Problems
- Wireless Networks
- PPP+Local Net
- 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,
- Edit /etc/network and set your hostname (and domainname,
if desired) there.
- 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:
- 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.
- 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).
- 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.
- 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:
- If the card did not get the expected address, run dmesg and also
check /var/log/messages for hints on what might have gone wrong.
- I'm seeing some flakiness on Redhat 8.0 in configuring the card
(sometimes it freezes for a while after I insert the card, and once it
unfreezes I see messages in dmesg such as: cs: socket c17d2800 voltage interrogation
timed out. This may be a hardware problem.
Re-inserting usually cures it; cardctl
eject; cardctl insert probably also would work.
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:
- Start the PPP connection on the gateway.
- Start local networking on both machines (order not important).
- Verify that the machines can talk to each other locally, and that
the gateway machine can still see the outside world through PPP).
- Use iptables to turn on connection sharing, using this
lesson from linuxchix which explains it much better than I would.
- 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