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.
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
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
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
If you’re having trouble, look at the kernel and make sure you have serial port devices compiled.
minicom is very handy for all matters involving serial
communications and especially ones involving modems. If it’s not
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
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
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
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).
|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.
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
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.
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 email@example.com), 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.
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
/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 220.127.116.11 nameserver 18.104.22.168
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 22.214.171.124 nameserver 126.96.36.199 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