This post describes one way to quickly set up a two-computer network such that both machines on the network can access the outside internet. The use case in mind here is you’re at a cafe with a friend, the wifi there sucks, you have your mobile broadband connection and you want to share it with your friend.

Note that there are many ways to get to the desired end result here. This solution has your local laptop doing NAT and forwarding packets at the IP layer.

Supplies:

  • your debian/ubuntu laptop
  • a “mobile broadband” connection with some provider, like Verizon or T-Mobile
  • an ethernet cord

Step 0: Get your mobile broadband connection working, possibly with T-Mobile.

Step 1: Set up your machine to run a dhcp server for your local wired network

  • sudo apt-get install isc-dhcp-server
  • Edit /etc/dhcp/dhcpd.conf. Here are the relevant parts of mine. (Yes, the ‘authoritative’ directive is commented out, I’m not sure how essential this is or not – but I’m trying avoid the dhcp server from taking over my local machine’s default route.)
    default-lease-time 600;
    max-lease-time 7200;
    #authoritative;
    log-facility syslog;
    subnet 172.16.16.0 netmask 255.255.255.0 {
      range 172.16.16.10 172.16.16.250;
      option domain-name-servers 208.67.222.222; # opendns
      option routers 172.16.16.1;
    }
    
  • Edit /etc/defaults/isc-dhcp-server:
    mike@110psi:$ cat /etc/default/isc-dhcp-server | tail -n 1
    INTERFACES="eth4"
    
  • sudo ifconfig eth4 172.16.16.1 netmask 255.255.255.0
  • sudo /etc/init.d/isc-dhcpd-server restart

At this point you should physically connect your friend’s laptop to yours using an ethernet cable. To watch the connection happen: tail -f /var/log/syslog. You should be able to go between the two computers and ping each other. If you can’t, then you want to debug this until you can… the rest of this recipe won’t have any effect if your local wired net is broken.

Step 2: Fix up your routing table

Between pppd, your local dhcp server, and you issuing manual ifconfig commands, it’s easy for your local routing table to get in a bad state. Here’s what you want it to look like:

mike@110psi:~$ netstat -nr
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
10.0.0.1        0.0.0.0         255.255.255.255 UH        0 0          0 ppp0
172.16.16.0     0.0.0.0         255.255.255.0   U         0 0          0 eth4
0.0.0.0         0.0.0.0         0.0.0.0         U         0 0          0 ppp0

If you need to remove/add/edit routes, the tool you want to use is ‘route’. For example:

sudo route del default
sudo route add default gw 10.0.0.1

Step 3: Set up your computer to do some NAT

I scripted this out. Here’s the script:

#!/bin/sh
# nat and firewall
# for now, just nat.

ipt=/sbin/iptables
EXTIF=ppp0
INTIF=eth4

case "$1" in
	start)
		echo "Starting firewall:"

		echo -ne "\tClearing existing rules..."
		$ipt -F INPUT
		$ipt -F OUTPUT
		$ipt -F FORWARD
		$ipt -t nat -F
		echo " done."

		echo -ne "\tInput / Output rules..."
		$ipt -P INPUT ACCEPT
		$ipt -P OUTPUT ACCEPT
		echo " done."

		echo -ne "\tForwarding rules, and /proc/sys/net/ipv4/ip_forward..."
		echo "1" > /proc/sys/net/ipv4/ip_forward
		#$ipt -A FORWARD -i $EXTIF -o $INTIF -m state --state ESTABLISHED,RELATED -j ACCEPT
		$ipt -A FORWARD -i $EXTIF -o $INTIF -j ACCEPT
		$ipt -A FORWARD -i $INTIF -o $EXTIF -j ACCEPT
		echo " done."

		echo -ne "\tEnabling MASQUERADE on $EXTIF..."
		$ipt -t nat -A POSTROUTING -o $EXTIF -j MASQUERADE
		echo " done."

		echo "Firewall.sh is up."
	;;
	stop)
		echo -n "Stopping firewall...";
		$ipt -F INPUT
		$ipt -F OUTPUT
		$ipt -F FORWARD
		$ipt -P INPUT ACCEPT
		$ipt -P FORWARD ACCEPT
		$ipt -P OUTPUT ACCEPT
		$ipt -t nat -F
		echo "0" > /proc/sys/net/ipv4/ip_forward
		echo " done.";
		echo "Firewall.sh is down."
	;;
	*)
		N=/etc/init.d/firewall.sh
        	echo "Usage: $N {start|stop}" >&2
		exit 1
	;;
esac

Start your NAT up with “sudo ./nat-script-name.sh start”.

Step 4: debug it because it doesn’t work.

Break the problem into pieces:

  • debug the connection between the two computers (/var/log/syslog, ifconfig, isc-dhcp-server and ping are your friends here)
  • debug your local routing table (using netstat and route commands)
  • debug your connection to your mobile broadband provider (pppd, wvdial, minicom, ping, etc)

If you find some variant of this recipe works better for your local machine, please post it in the comments so we can all share. Good luck.

It is possible – I’m writing this post via T-Mobile and my new webConnect Rocket.

Step 0: see if your webConnect Rocket is actually the same as mine.

mike@110psi:~$ lsusb
Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 002: ID 19d2:1201 ONDA Communication S.p.A.
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

If you don’t have the “19d2:1201 ONDA Communication S.p.A.” line, then likely you have a different version of the webConnect Rocket than I do and this guide may or may not apply.

Step 1: usb_modeswitch. This is necessary because the webConnect, like many usb dongles these days, actually has its windows (and mac?) drivers loaded directly on it. When the dongle is first inserted into a windows machine, it appears as a hard drive with its driver on it. Windows installs the driver, then magically changes the device into a modem. We need to use usb_modeswitch to do that magic change ourselves.

sudo apt-get install usb-modeswitch

As of this writing, you need to manually add the file /etc/usb_modeswitch.d/19d2:1201 with text:

# t-mobile ZTE MF691  Rocket 2

DefaultVendor=  0x19d2
DefaultProduct= 0x1201

TargetVendor=   0x19d2
TargetProduct=  0x1203

MessageContent="5553424392020000000000000000061B000000020000000000000000000000"

For more details, see this forum post and this one. Hopefully this file will be included directly in the usb-modeswitch-data package soon, but for the meantime it looks like the maintainer is currently traveling.

Now, we need to configure udev to run usb_modeswitch automatically when it sees the webConnect hard drive. Add the following lines to the file /lib/udev/rules.d/40-usb_modeswitch.rules:

# t-mobile ZTE MF691  Rocket 2
ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="1201", RUN+="usb_modeswitch '%b/%k'"

(Before you add those lines check that they haven’t already been added by upstream since this writing. No need to have them in there twice.)

At this point I’d recommend a) restarting your machine and the b) inserting your webConnect Rocket. To test everything’s good so far, you should be able to use minicom to connect to both /dev/ttyACM0 and /dev/ttyACM1 and issue some basic AT commands.

Step 2: I haven’t been able to get network-manager to work correctly with the webConnect rocket. I get a lot of “modem-manager: Got failure code 100: Unknown error” in the logs. If you’ve got the time, the relevant source is here.

However, we can use wvdial and pppd to connect. If you haven’t already:

sudo apt-get install wvdial pppd

You can run ‘wvdailconf’ as root to generate a basic /etc/wvdial.conf. Then you want to edit it to look like mine:

[Dialer Defaults]
Init1 = ATZ
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Modem Type = USB Modem
ISDN = 0
New PPPD = yes
Phone = *99***1#
Modem = /dev/ttyACM0
Username = user
Password = pass
Baud = 460800
Stupid Mode = 1

I suspect there may be other options that should be in here that would be helpful. But in any case, this is a working base case. If you find any additional helpful options, please let me know in the comments.

Step 3: Connect to T-Mobile! To connect, run

sudo wvdial

Wvdial will manage the connection process to T-Mobile, spawning an instance of pppd to maintain the connection. Once the connection is established, you can hit cntrl-c to kill the instance of wvdial while still leaving pppd alive and your connection to T-Mobile active.

To disconnect:

sudo pkill pppd

does the trick.

It’ll be nice once modem-manager (and hence network-manager) has functioning support for this device. I’ll update this post once it does. In the meantime… good luck!

Debian-based distributions have a really useful series of directories to run cron scripts from. Any executable you place in /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly or /etc/cron.monthly will get run with that frequency. I like these for two reasons: 1) it’s file-based, which I find a lot easier to manage and keep track of than each user’s crontabs and 2) this eliminates one possible source of bugs in my work – namely, the scheduling of my cron tasks.

However, there is a downside to /etc/cron.daily and friends. All scripts in there run as root. It’s generally bad practice to run anything as root that doesn’t have to run as root… and this is especially true if your script has scary lines like “rm -rf $SOME_VAR” in it. You’re asking for trouble.

Unfortunately, AFAIK there is no way to drop privilege within a script. However, this can be done by spanning a whole new child process. So, let’s add a short preamble to all the scripts we place in /etc/cron.daily and friends:

#!/bin/sh

USER='some-low-privilege-user'
if [ `whoami` != "$USER" ]; then
  sudo -u $USER "$0"
  exit
fi

... rest of the script ...

Now we have some extra assurance our cron job isn’t going to go haywire and screw the whole machine!

gsynaptics gives you a nice little GUI in gnome to control the options on your synaptics touchpad, like the one my T61p came with. It’s easy to set up on a default debian install, you just need to add a few stanazas to your xorg.conf

Here’s the edits I needed from a default install xorg.conf:

  1. Make a backup of your current xorg.conf
  2. Remove the “Generic Mouse” section. You don’t need it anymore.
  3. Add a section for your touchpad like so:
    Section "InputDevice"
      Identifier  "Synaptics Touchpad"
      Driver      "synaptics"
      Option      "SendCoreEvents"  "true"
      Option      "Protocol"        "auto-dev"
      Option      "Device"          "/dev/psaux"
      Option      "SHMConfig"       "true"
    EndSection
    
  4. And add a line in your “ServerLayout” section referencing your new synaptics section. I didn’t have a ServerLayout section so I had to add one, mine looks like this:
    Section "ServerLayout"
      Identifier  "Default Layout"
      Screen      "Default Screen"
      InputDevice "Generic Keyboard"
      InputDevice "Synaptics Touchpad"
    EndSection
    

Now save everything you’re doing and then restart X11 by hitting cntrl-alt-backspace. If X won’t start back up, you can hit cntrl-alt-f1 and log in at a command prompt, restore your xorg.conf from the backup you made earlier, then run /etc/init.d/gdm restart.

In the event that things just aren’t working, your friend is /var/log/Xorg.0.log. That log file contains the results of your x-server’s parsing of your xorg.conf.

Splashy is a linux-boot graphical boot screen thinger. It aims to make your booting process into x11 more full of rounded corners and less of 1970’s terminal text streaking by.

Want to get rid of it? Well, make sure to purge it when you remove it, or your system will fail partway through the init scripts on the next boot. You won’t have x11 or networking or dbus. You will have a screen full of errors and a login prompt. So make sure you do:

sudo apt-get --purge remove splashy

However, if you already did just a apt-get remove splashy just like you’d do for any other package, and now your system suddenly won’t boot past 1980, what should you do? Kill the offending file.

sudo rm -ffffffffffffffff /etc/lsb-base-logging.sh

And reboot. Your system should come back up with networking and all. At this point you probably want to re-install splashy then re-remove it using the –purge option to get rid of all its last traces.

Here are the steps I took to get Eclipse working with Java on my Debian Lenny more-or-less default install laptop.  I know zero (soon to be non-zero) Java, and I’ve never used Eclipse before.

sudo apt-get install eclipse
sudo apt-get install sun-java6-doc

You will then need to download a zipped file from sun’s servers to your /tmp dir, and then re-run the configuration scripts for that package.  AFAIK, that package just installs the help files in the appropriate places.  It doesn’t do the download for you because Sun makes you check a bunch of boxes off about licenses etc. before letting you download.

Increase your productivity about a billion percent for 15 Euro: viPlugin. It works as expected, so far recommended.  The only thing is I didn’t receive my license via email till about 4 hours after I bought it.  So get it set up now.  I, for one, do appreciate the reasonable pricing for viPlugin as apposed to some other vi IDE plugins.  Reasonable pricing makes the difference between me searching for a crack or just paying for the license… but that’s worthy of a whole rant (er, post) of it’s own.

And I think that’s it.  I’m now on my way to becoming yet another Java monk- er, programmer.

Update:

Hum, why is it never that easy?  So the GNU version of the Java complier doesn’t like you using the Scanner class. I have no idea why and right now, with this project 22 hours overdue, I don’t really care (so why am I writing this up now?).  Anyway:

sudo apt-get install sun-java6-jdk
sudo update-java-alternatives -s java-6-sun
sudo update-alternatives --config java

And you want to select /usr/lib/jvm/java-6-sun/jre/bin/java

sudo update-alternatives --config javac

And you want to select /usr/lib/jvm/java-6-sun/bin/javac

In Eclipse, “Windows” > “Preferences” > “Java” > “Installed JREs”.  You want to ‘Add’ the JRE /usr/lib/jvm/java-6-sun-1.6.0.07  Then you want to make that the default by checking the box and clicking OK.

And now, Eclipse will find that Scanner class for you.

Update #2:

You probably want to use Sun’s javadoc:

sudo update-alternatives --config javadoc

and select /usr/lib/jvm/java-6-sun/bin/javadoc

Update #3:

If you want to use the JUnit4 package, you need to add it to the build path of your project.

sudo apt-get install junit4

In Eclipse, “Windows” > “Preferences” > “Java” > “Installed JREs”.  Select “Edit” on the JRE you’re using – for me, this is java-6-sun-1.6.0.07.  Then “Add External JARs…” and add /usr/lib/eclipse/plugins/org.junit4_4.1.0.1/junit-4.1.jar.  I don’t know why this doesn’t all just happen automagically… I see some hints around that there’s a licensing issue.

My new T61p has the standard built-in Intel 4965AGN wireless card for 802.11b/g/n goodness. The kernel has had driver support for this hardware since 2.6.24. But, after doing a default Debian Lenny install, the wireless just ain’t working… what gives?

Well, this comes up in /var/log/syslog and others:

iwl4965: iwlwifi-4965-1.ucode firmware file req failed: Reason -2
iwl4965: Could not read microcode: -2

As is explained here, the iwlwifi drivers require a binary firmware (aka microcode) image to function. The drivers themselves are free, both as in beer and as in freedom. However, the microcode images, in order to enforce end-user FCC compliance, are free as in beer but not freedom. Thus a default Debian install, which bends over backwards to be free as in beer and free as in freedom, does not include the microcode images.

Two options:

  1. Install the firmware image yourself. Find the image you need here (as of August 2008 the version you want was 1.21), download it, extract it, and copy it to /lib/firmware/iwlwifi-4965-1.ucode.
  2. Or, add the non-free repositories to your /etc/apt/sources.list, and do an
    apt-get install firmware-iwlwifi

Or, pretend you didn’t really want wireless if you can’t have it free as in freedom… and put it on your to-do list to reverse-engineer that binary firmware image. Buena suerte! ;p

I can’t remember if a reboot was necessary after installing the microcode image. But that should be it in terms of edits and installs… everything wifi, all the way out to the gnome GUI, should now just automagically work.

This is the first in what will be a short series of posts of what I’ve had to do to get Debian (Lenny – currently the ‘testing’ distro) working fully and smoothly on my new T61p.

The key options in my T61p package:

39T4822 	VBB WWAN
42V9332 	SBB WAN:VERIZONSIERRACDMA2000
42V8603 	SBB INT.WWAN ANTENNA 15.4"
42V8659 	SBB CL.PLATE T61P WL WWAN
42W7002 	SBB FCC-ID/LABEL FOR WWAN
42V8675 	SBB VERIZON OPTION

That all translates to a slickly built-in Verizon card and antenna:

$ sudo lsusb -v | grep Sierra
Bus 006 Device 002: ID 1199:0220 Sierra Wireless, Inc.
  idVendor           0x1199 Sierra Wireless, Inc.
  iManufacturer           1 Sierra Wireless, Incorporated
  iProduct                2 Sierra Wireless MC5725 Modem

Here is the only officially unofficial official public documentation I could find for that card on Linux.

Before setting this up with Debian, I’d recommend getting it working with Windows if you haven’t reformatted over it yet. The card and connection pretty much ‘just works’ on Lenovo’s preinstalled Windows. This will mostly eliminate Verizon as the source of the problem if things don’t go right with Debian.

A default Debian install provides a number of tools you can use to configure and automate your connection. I like gnome-ppp (essentially a GUI frontend on wvdial) best. I’ve also set it up with gnome’s network-admin applet (System->Administration->Network), but it doesn’t provide good user feedback on the connection process or status. And by ‘good’, I mean ‘any’. Perhaps future versions will have better integration of dial-out connections, now that they’re coming back into style with EVDO and 3G networks. In any case, I will provide instructions for both these two tools here. (Note this is an either/or. There is no reason to bother setting this up with both tools, other than to test out the GUI’s.)

First, GUI configuration. Here’s your key points:

  • Username: YOURPHONENUMBER@vzw3g.com
  • Password: vzw
  • Phone number to dial: #777

For gnome-ppp, you want to:

  • Use the ‘Detect’ mechanism. It worked perfect for me. Try it.
  • Under Options, enable ’stupid mode’ to speed up the connection process substantially. You’re also calling Verizon stupid, in a extremely passive aggressive manner… ummm, feels so good…. stupid stupid stupid.

For network-admin:

  • Set the Modem port to /dev/ttyUSB0.
  • Check the ‘Set modem as default route to Internet’ option or your machine will just drop your outbound packets on the floor.
  • No remote authentication. In the file /etc/ppp/peers/ppp0, add a line ‘noauth’ to disable your authentication of the verizon servers. This means that if someone successfully hijacks Verizon’s ‘#777′ number, you will have no way of knowing, and they will have complete control over your traffic. (gnome-ppp does this ‘noauth’ for you automatically, for better or for worse.)
  • Do not set the modem volume. In the file /etc/chatscripts/ppp0, comment out the line that has a command like ‘AT&FH0XX’ where XX are wildcards depending on your GUI settings. Issuing this command causes the modem error out, reporting ‘NO CARRIER’ on the ensuing ATDT (dial) command.

And that’s it! For debugging, your friends are tail, /var/log/syslog, /var/log/messages, gnome-ppp’s GUI log display, cat, echo, /dev/ttyUSB0, minicom and or course, good old google.

Just plug it in. It just works. I can’t believe it. Somebody wake me up… or wait, don’t. My debian box is ‘just working’!

Still, I’m watching songbird’s development closely and eagerly….

Pintos is a minimal operating system for x86 hardware used primarily for instructional purposes (eg.). QEMU is an open-source hardware emulator typically used for operating system development. Debian is a linux operating system, regular style.

Step #1 – Debian: Drop windows and install debian (or go dual-boot).

Step #2 – QEMU:

sudo apt-get install qemu

To test everything is working as it should at this point, you can download a small linux kernel image here (Sec: disk images). Then:

bzip2 -d linux-0.2.img.bz2
qemu linux-0.2.img

You are now running a minimal linux system on emulated x86 hardware, which is in turn running on a full-featured linux system (debian) on real (probably also x86) hardware. Press ctrl-alt to get out of the minimal linux system if you get stuck with it stealing all your keystrokes.

Step #3 – Pintos:

  • 3.A – Download pintos.
  • 3.B – Fix pintos to default to QEMU (rather than bochs) by applying the following diff:
    Index: threads/Make.vars
    =======================================
    @@ -4,4 +4,5 @@
    -SIMULATOR = --bochs
    +#SIMULATOR = --bochs
    +SIMULATOR = --qemu
    
    Index: utils/pintos
    =======================================
    @@ -85,7 +85,7 @@
    -    $sim = "bochs" if !defined $sim;
    +    $sim = "qemu" if !defined $sim;
    @@ -107,8 +107,8 @@
    -  --bochs                  (default) Use Bochs as simulator
    -  --qemu                   Use QEMU as simulator
    +  --qemu                   (default) Use QEMU as simulator
    +  --bochs                  Use Bochs as simulator
    
  • 3.C – Compile pintos:
    cd threads/
    make
    
  • 3.D – Run a test app with pintos:
    cd threads/build/
    ../../utils/pintos run alarm-multiple
    
  • 3.E – You may wish to throw pintos in your default path (some of the scripts provided require it’s there). There are many ways to do this, this is my favorite:
    sudo ln -s `pwd`/utils/pintos /usr/local/bin/

And that’s it! In step 3.D you finished up by running a little test app that created 5 threads that slept for varying predefined periods of time with some messaging to the console, thus testing pintos’ scheduling/threading abilities. You’re now ready to augment and enhance pintos… coffee anyone?