3G, PINs, prompts and pppd

A recent post by Quintin, and specifically a few comments regarding 3G made me think The primary advice to users looking to use 3G under Linux is to switch off the PIN on the SIM. Well, I’ve posted before on how to make 3G work … but Quintin’s post challenged me to take it to the next level…

What is the next level

Well, whatever it is, I’m not where I want to be. What I’ll describe here is how to reliably fire things up with udev, to automatically make udev start pppd (and stop it again), and finally, to bug the user logged in on X11 (first display, aka, :0) to get a PIN, and to then proceed with dialing up. As an aside, the 10.11.12.13 bug once more pops up, and a reliablie workaround (yes, workaround cause it’s really not a fix) is presented.

Assumptions

That you’re using a new enough kernel to not need the huaweiAktBbo program. Iirc this is around 2.6.22 and upwards. If your modem at any point comes up with anything other than exactly two ttyUSB tty devices, upgrade your kernel. I’ve had enough trouble with the huaweiAktBbo setup that I’ve given up.

udev

Previously I was rather inconsistent with udev, and fired only on a usb device with the specific vendor and product id. This probably missed a good number of devices, so instead, I’ve now moved to matching on the driver (option1 … a sub-driver of the option module for single-port devices), and the tty subsystem (this manages to ignore all the clutter surrounding the fake cd-rom device). This still leaves me with two events, one for ttyUSB0, and one for ttyUSB1, which is more than acceptable.

Right, so firstly, we need a small helper program, which I’ve stupidly called udev-rules, and which is stored in /usr/local/sbin/ (and must be executable by root), the content is rather simplistic, but it does contain some trickery. In particular, you should note that I customize the linkname to represent the device node name, specifically, if I’m dialing on ttyUSB0 then I set linkname to 3g-ttyUSB0 – this is so that I can reliably detect which pppd process to kill when the device gets removed. The script looks at the environment variable $ACTION (exported by udevd) to determine whether the device is being added or removed, and at $DEVNAME for the name of the device node. Additionally, on the start case a parameter with the endpoint number is passed (this value is always “00” for the endpoints we want to use for dialing, even with multiple modems attached).

pppd creates a pid file in /var/run with the name of pppd-${linkname}.pid, which is what we’re abusing on shutdown to kill the correct pppd processes.

The udev rules file itself is called 99-huawei.rules and should be stored in /etc/udev/rules.d/ (usually). This just contains two rules that calls the above script at the appropriate times (when /dev/ttyUSB? becomes available, or goes away).

And that, ladies and gentlemen, is as difficult as the udev side of things becomes.

3g peer file

Well, this has never changed much. It’s still the same old “3g” peers file (store in /etc/ppp/peers) as per my TLUG howto, with one exception, the connect option now points to a uls_3g_connect program, which has been written specifically because the chat program (which is what I suspect causes problems for most distro’s in that it cannot do conditionals).

You need to store this little script in /usr/local/sbin/ (or edit the peers file), and must be executable by root (best is to change the ownership to root by executing “chown root:root /usr/local/sbin/uls_3g_connect.pl” and then “chmod a+x /usr/local/sbin/uls_3g_connect.pl”.

This little program is where the magic happens. If you really care, and can read perl, enjoy. This little piece of code is actually quite simple, but it does what I consider to be quite funky stuff. Firstly, and simply because I’ve never done this in perl, it actually works with \r\n, and correctly strips the lines coming in (chomp refused to do this for me), it expects the commands sent to be echoed back (and abuses alarm for a timeout hack), it actually checks the modem for it’s PIN status (AT+CPIN?), after which it only sends the PIN if it’s required, and the pin is obtained from a sub routine, which makes use of who and awk to obtain the username of the logged in user (check for the :0 display – ie, X11 user on the first display), and then abuses su and Xdialog to pop up a prompt on the desktop asking for the pin (this prompt is run as the user, which is how I get by .Xauthority issues, as well as hopefully sucessfully restricting the user from causing havoc … I seriously doubt it’s 100 % solid, but a check to ensure the returned pin is 4/5 digits should be good enough if somebody cares.

dns bug

If you do a careful comparison of the options I send to the modem now, and those that I’ve sent before you’ll note that I issue an additional AT line. This was snarfed from minicom after I noticed that the bug did not show itself on first dial after I first interacted with the modem using minicom. A few redials does still show it sometimes, but no longer on every single boot. The acceptwins option also doesn’t seem to make that huge impact. So instead I now do this:

if [[ “${DNS1}” == “10.11.12.13” ]]; then
echo “Detected E220 firmware bug, requesting pppd to renogotiate the link as a workaround.”
kill -HUP $PPPD_PID && exit -1
fi

Which causes pppd to renogotiate the link if/when the problem is detected. This is found inside a if [ $USEPEERDNS ] section, and my whole ip-up script is wrapped in a ( … ) | logger -t ip-up. Just in case you’re wondering. It’s probably good enough to put the following in /etc/ppp/ip-up.local:

[[ “${USEPEERDNS}” ]] && [[ “${DNS1}” == “10.11.12.13” ]] && kill -HUP $PPPD_PID && exit -1

Your mileage may vary.

conclusions

The above is all that is required to make work what I’ve heard a lot of people complain about. Probably not the cleanest solution, probably won’t integrate into the gnome network manager directly, and it’s definitely not bug free (I finished writing it about 3 ago). There are a few things I’d still like to do:

  • Obtain some kind of unique identification off the SIM before entering the SIM allowing the prompt to indicate which SIM is being used. I’ve got some documentation lying around indicating how to ID the modem but this isn’t actually good enough (but will have to do if the SIM cannot be identified without first unlocking it).
  • Check a config file for a PIN to use based on the above identification, marking it invalid if the PIN auth fails.

Anyway, the point being that for general desktop use the above will probably suffice, at least, until the next time I grow annoyed and feel like improving it.

3 Responses to “3G, PINs, prompts and pppd”

  1. majikins says:

    Thank you! this worked for me.

    For the non-guru guys out there ensure that you place uls-3g-connect.pl in /usr/local/sbin and then give it root and executable access like so:
    chown root.root uls-3g-connect.pl
    and then
    chmod +x uls-3g-connect.pl

    there maybe a better way of doing the above, but its how I did it.

    jkroon – u rock!

    • Jaco Kroon says:

      Oh yes. No, that’s the “correct” way. The ownership doesn’t really matter but it is important that it be executable by root. On my system it’s a symlink to it’s location in my subversion repository. I’m updating the post itself to make this more clear.

  2. […] spit too much gunk at you. From here on it’s pretty simple. I use my chat perl script from my 3G, PINs, prompts and pppd entry, along with this file in /etc/ppp/peers/: /dev/rfcomm0 linkname 3g-rfcomm0 defaultmetric 5000 […]