It’s 2011 and it is hard to believe I’m not only referring to these notes but I’m actually adding quite a bit of information. But calamity has struck and thanks to my aversion to paper billing and AT&T’s aversion to modernity, I didn’t pay the phone bill needed to keep my DSL line operational. Far from being a simple interruption of internet service, this became a serious pain in the ass. After eight days with no internet, I finally am back on line thanks to a dial up modem. If you ever have your main internet shut off inadvertently, it does not come back over night. It can take weeks! This is why dial up modems are not completely dead. As long as you still have your phone line, they’re good to have on hand in case you lose your DSL provider. When I wrote this original document in 1998, I never could have dreamed that I’d need it in 2011. I’m hoping it becomes obsolete, but I’ve done that before.

Winmodems = BAD

Seems like almost all internal modems (probably laptop ones too) made after the Golden Age Of Network Telephony are Winmodems meaning that they use your CPU to do most of their thinking. Proper modems have their own controller and don’t depend on the OS and its driver for help. Rumor has it that Linux has some drivers for this, but since the whole concept of modems is horribly obsolete, it’s not exactly simple to figure out how to deploy that technology. Far better is to buy an external modem which supports the AT command set over a serial or USB connection.

setserial

You plug in a modem and now you want to get the computer to admit it’s there. If it’s an internal modem, look at the output of lscpi. Unfortunately, I found my internal modem identified on the PCI bus but that was as far as I got since it turned out to be one of the aforementioned Winmodems.

The setserial command is useful for configuring serial ports. Hopefully Linux did this automagically and what you really need to do with setserial is to verify that the serial port you think the modem lives on is accessible.

$ sudo setserial -g /dev/ttyS*
/dev/ttyS0, UART: 16550A, Port: 0x03f8, IRQ: 4
/dev/ttyS1, UART: unknown, Port: 0x02f8, IRQ: 3
/dev/ttyS2, UART: unknown, Port: 0x03e8, IRQ: 4
/dev/ttyS3, UART: unknown, Port: 0x02e8, IRQ: 3

This shows that out of the four normal serial ports (the ones with device files set up be default on my distro) only one UART is found. This means that the OS only knows about one serial interface (the UART is the serial interface chip). This is good and looks normal. Plug your external modem into that serial port. You can now tell your modem using programs to direct their attention to /dev/ttyS0.

If you’re having trouble, look at the kernel and make sure you have serial port devices compiled.

Minicom

The program minicom is very handy for all matters involving serial communications and especially ones involving modems. If it’s not setup, run minicom -s and then tell it which serial device you are using and if you know the speed and stopbits and parity, etc, add them too though it looks like the default is going to work out pretty well for most users. When running the program, you can press ctrl-a and then z to escape to the interactive menu.

With minicom running, you can now try to contact your modem. If you’re modem is not unusably exotic, it should understand the Hayes AT command set made popular before most humans were born. This works by typing AT and some command. There are only two that I remember and need to worry about. The first is just AT followed by nothing but an enter. The modem should respond with OK. If it does, you have reached an important milestone. You are now pretty sure that your modem will be functional as far as your computer is concerned.

Next check to see if it’s operational as far as the phone company is concerned. Try ATDT5551212 but substitute your cell phone number in there. The modem should dial your cell phone. If your cell phone rings, you should be good to go with the next phase.

After everything is working, you’ll also want to try to fire up the modem without the speaker making so much obnoxious nostalgic racket. That should be "M0". Here’s the compete initialization string that wvdial (see below) proposed and its meaning:

ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
  • AT - Get the ball rolling, let the modem know it’s being addressed.

  • Q0 - Turn off quiet mode. This is verbose mode, not noisy.

  • V1 - Messages in English.

  • E1 - Echo on so you can see what you type. E0 is off.

  • S0=0 - Put a 0 in register 0 which is number of rings before auto answer.

  • &C - V.250 compliant mystery directive.

  • &D - V.250 compliant mystery directive.

  • +F - V.250 Fax class

  • M0 - speaker off (M1 speaker on at connect, M2 speaker always driving you crazy).

Escape Characters

Note
This was from my original 1998 notes. I think that generally modems use serial signals to escape things now.

This is a good thing to initialize the modem with. This prevents the use of escape characters. Escape characters are not too handy when using ppp and if some asswipe embeds the escape sequence in a web tag or something-- ouch, modem shutdown. Setting the ESC character register to some value greater than 127 effectively cancels the functionality of the escape function.

+++ATS2=200

pppd

You must make sure that pppd is installed. Of course this is hard to install if you don’t have a network. I installed it from source with not much trouble and put it in /usr/local/sbin with a sym link to /usr/sbin/pppd.

Also note that pppd is a userspace program that interacts with the kernel’s ppp facilities. Point there is that you need to have ppp compiled into the kernel, not necessarily something you’d normally have to have.

wvdial

With pppd in place, you probably should use wvdial to manage things. It’s not strictly necessary, but since this is an obsolete technology, the automagical charm of wvdial is actually pretty comprehensive and not likely to change.

To get the ball rolling have wvdial try to configure itself like this:

$ sudo wvdialconf /etc/wvdial.conf

Then edit that file and add your ISP’s local access phone number, your username (mine required chris@copper.net), and your password. Uncomment that stuff too.

I actually ran wvdialconf one more time after making those changes and that was ok. Now if you’re lucky, you should just be able to run:

$ sudo wvdial

and everything should work! The way to test this is to make sure there are no errors when wvdial runs and then try ifconfig and look for an entry for a ppp0 device. If it’s here and working it should have given you an IP address.

DNS

At this point I was able to log in to my remote hosts using their IP numbers, but any kind of hostname reference was not working. Back in the old days of modems men were men and DHCP clients didn’t pamper you by changing your name server records. This means you have to edit your own /etc/resolv.conf file and add the nameservers the ISP tells you about. You can call them if you don’t know (but not on the phone that the modem’s using!). My wvdial output actually contained the name server’s IP addresses so you might look for them there. The /etc/resolv.conf file will look like:

nameserver 67.211.172.29
nameserver 67.211.172.30

Configure As A Router

If you use modules in your kernel, you can load them at the beginning of this script. I compiled all the iptables stuff in the main kernel so I didn’t have to mess with that. This script is taken from a sample you can find here.

#!/bin/bash
# This assumes that wvdial is running and ppp is now active.
# This should set up DNS servers, IP forwarding, and the iptables
# masquerading rules.
# See: http://tldp.org/HOWTO/IP-Masquerade-HOWTO/firewall-examples.html

IPTABLES=/sbin/iptables

if grep ^nameserver /etc/resolv.conf > /dev/null
then
    echo Looks like resolv.conf is ok:
    cat /etc/resolv.conf
else
    echo Looks like we need to set up resolv.conf.
    cat > /etc/resolv.conf <<TheEnd
nameserver 67.211.172.29
nameserver 67.211.172.30
TheEnd
    echo Hope this looks ok
    cat /etc/resolv.conf
fi

EXTIF="ppp0"
INTIF="eth0"
echo "   External Interface:  $EXTIF"
echo "   Internal Interface:  $INTIF"

echo "   Enabling forwarding.."
echo "1" > /proc/sys/net/ipv4/ip_forward

echo "   Enabling DynamicAddr.."
echo "1" > /proc/sys/net/ipv4/ip_dynaddr

echo "   Clearing any existing rules and setting default policy.."
$IPTABLES -P INPUT ACCEPT
$IPTABLES -F INPUT
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES -F OUTPUT
$IPTABLES -P FORWARD DROP
$IPTABLES -F FORWARD
$IPTABLES -t nat -F

echo "   FWD: Allow all connections OUT and only existing and related ones IN"
$IPTABLES -A FORWARD -i $EXTIF -o $INTIF -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A FORWARD -i $INTIF -o $EXTIF -j ACCEPT
$IPTABLES -A FORWARD -j LOG

echo "   Enabling SNAT (MASQUERADE) functionality on $EXTIF"
$IPTABLES -t nat -A POSTROUTING -o $EXTIF -j MASQUERADE