Hack 17 Bluetooth to GPRS in Linux

figs/expert.giffigs/hack17.gif

Use your Bluetooth phone as a modem when Wi-Fi isn't available.

No doubt the novelty of being able to scan for nearby Bluetooth devices from your Linux machine will wear off all too soon, and you'll be wanting to actually do things with your shiny new Bluetooth connection. Being able to use your cell phone as a modem from all those places you can't pull in a Wi-Fi signal would be pretty cool, wouldn't it?

Bluetooth supports a number of "profiles," which define the way that Bluetooth devices can communicate with each other. In this case, we want to make use of the Dial-up Networking (DUN) profile, which relies on a protocol called RFCOMM to emulate a serial link between two devices. You can use RFCOMM to connect your Linux box to your phone, and then run pppd over the link to get access to the Internet. This works using GPRS, or even an ordinary Internet dial-up.

Assuming you've got Bluetooth working [Hack #16], you should be able to bring your phone within range of your computer and scan for it using hcitool. We'll presume that you've done this, and that hcitool reports a BD address for your phone of 00:11:22:33:44:55.

You can also use sdptool to verify that there's a device in range that supports the DUN profile:

$ sdptool search DUN Inquiring ... Searching for DUN on 00:11:22:33:44:55 ... Service Name: Dial-up Networking Service RecHandle: 0x10001 Service Class ID List:   "Dialup Networking" (0x1103)   "Generic Networking" (0x1201) Protocol Descriptor List:   "L2CAP" (0x0100)   "RFCOMM" (0x0003)     Channel: 1

Note this channel number, because you'll need it later. As you can see, hcitool and sdptool offer a lot of other useful Bluetooth diagnostic functions, which you can read more about on their respective manpages.

Before you can actually connect to the phone, however, you may need to set up what's referred to as device pairing between your Linux box and your phone, so that your phone knows to allow your computer access to its services, and possibly vice versa. Your computer's PIN can be found in /etc/bluetooth/pin, and you will want to alter this to a unique value that only you know.

Most phones have a Bluetooth PIN that you can configure within the phone itself. BlueZ comes with a little Python utility called bluepin that pops up a GTk+ dialog to ask for your phone's PIN as needed; this utility apparently doesn't work out of the box requires in some Linux distributions. More to the point, who wants to be asked for your phone's PIN every time you use the thing, anyway? The following Perl script can be saved to /etc/bluetooth/pindb, and you can use it store PINs for multiple Bluetooth devices:

#!/usr/bin/perl while ( ) {     print "PIN:$1\n" if /^$ARGV[1]\s+(\w+)/o; } __DATA_  _ # Your Bluetooth PINs can go here, in BD address / PIN pairs,  # one to a line, separated by whitespace. # # ## etc. 00:11:22:33:44:55       11111

Make sure that /etc/bluetooth/pindb is owned by root and chmod 0700 you don't want ordinary users being able to look up your Bluetooth device PINs. The options section of your /etc/bluetooth/hcid.conf should accordingly look something like this:

options {         autoinit yes;         security auto;         pairing multi;         pin_helper /etc/bluetooth/pindb; }

This ensures that HCI devices are configured at boot, that pairing is allowed, and that hcid will ask pindb for your PINs on a per-device basis. Be sure to restart hcid by running /etc/rc.d/init.d/bluetooth restart if you made any changes to your /etc/bluetooth/hcid.conf.

Now that your computer is set up for pairing, you'll have to set up your phone similarly, for which you'll need to refer to your user's manual. This set-up process often requires that the phone can scan for your computer's Bluetooth adapter, so be sure that your computer is within range with a working Bluetooth adapter. The interface will probably come up as "BlueZ (0)", or something similar, unless you changed the "name" option in your hcid.conf. You probably want to set up the pairing on the phone as "trusted," or the moral equivalent, so that the phone doesn't ask you to verify the connection each time you try to dial out from your Linux box.

Now that I've shown that there's a device in range that offers dial-up networking, and set up pairing with it, the next step is to bind an RFCOMM interface to that device. First, make sure that there are RFCOMM entries in your /dev directory, using ls -l /dev/rfcomm*. If ls reports "No such file or directory", you can trivially create 64 RFCOMM device entries by switching to the superuser and doing the following:

# for n in `seq 0 63`; do mknod -m660 /dev/rfcomm$n c 216 $n; done # chown root:uucp /dev/rfcomm* 

If you're running Debian, you probably want to chown your RFCOMM devices to group dialout, instead of uucp.

Now, as the superuser, bind /dev/rfcomm0 to your phone on the channel reported for DUN by sdptool earlier, using the rfcomm utility from bluez-utils:

# rfcomm bind /dev/rfcomm0 00:11:22:33:44:55:66 1 

You'll know that the device was bound successfully if, like any good Unix utility, rfcomm just returns silently. You can demonstrate that it did actually work, however, by running rfcomm without any arguments:

# rfcomm rfcomm0: 00:11:22:33:44:55 channel 1 clean

Now you can pretty much just treat this serial device as if it were an ordinary modem. Just to prove it, try running minicom as root, and switch the serial device to /dev/rfcomm0. When the terminal loads, type AT and press Enter. If the phone responds OK, then congratulations are in order you're talking to your cell phone over a Bluetooth connection.

Before going any further, you may want to add the following to your /etc/bluetooth/rfcomm.conf , so that the RFCOMM device is configured by default when Bluetooth loads:

rfcomm0 {         # Automatically bind the device at startup         bind yes;         device 00:11:22:33:44:55;         channel 1;         comment "My Phone"; }

If you're running bluez-utils 2.3 or earlier on a non-Debian-based distro, you may need to add rfcomm bind all to the start( ) section of your /etc/rc.d/init.d/bluetooth for this to work right.

From here, it's just a short hop to getting your computer on the Net. Put the following into /etc/ppp/peers/gprs:

/dev/rfcomm0 connect '/usr/sbin/chat -v -f /etc/ppp/peers/gprs.chat' noauth defaultroute usepeerdns lcp-echo-interval 65535 debug

Then save the following as /etc/ppp/peers/gprs.chat:

TIMEOUT         15 ECHO            ON HANGUP          ON ''              AT OK              ATZ OK              ATD*99#

Alternately, if you prefer using wvdial, try adding the following to your /etc/wvdial.conf:

[Dialer gprs] Modem       = /dev/rfcomm0 Phone       = *99# Username    = foo Password    = bar

Note that while European providers give you a username and password, in the U.S. you still need to supply dummy values to satisfy wvdial. Consult your network provider's web site for details about what values you may need to use. Your GPRS is actually already authenticated by your very presence on the cellular network, so you don't have to re-auth just to use PPP. The "phone number" listed is the standard GPRS dial-up number, which may work for you right off the bat if your phone is configured properly. Most GSM phones support multiple GPRS access points, however so, if the default for your phone doesn't work for you, try going into minicom and typing AT+CGDCONT? followed by a carriage return. Your phone should respond with a list of available Packet Data Protocol (PDP) contexts. Pick the one that seems the most appropriate, and then set your GPRS phone number in /etc/wvdial.conf to *99***n#, replacing n with the number of the PDP profile you want to use. Failing that, try contacting your service provider for advice!

You can test this setup as root by running either pppd call gprs or wvdial gprs, depending on your setup, and watching /var/log/messages in another window. The only hitch with this setup is that it doesn't set up your nameservers in /etc/resolv.conf by default. The way around this on Red Hat is to store the following in /etc/sysconfig/network-scripts/ifcfg-ppp0 (or ppp1, ppp2, etc. as you prefer):

# comment out CHATSCRIPT and uncomment WVDIALSECT if you're using wvdial DEVICE=ppp0 MODEMPORT=/dev/rfcomm0 CHATSCRIPT=/etc/ppp/peers/gprs.chat # WVDIALSECT=gprs

This way you can just use ifup ppp0 and ifdown ppp0 to bring the link up and down. To get the identical result on Debian, use the pppd configuration just shown, and add the following to your /etc/network/interfaces:

iface ppp0 inet ppp     provider gprs

If you're not using a Red Hat- or Debian-like distribution, you can always just add the following additional lines to your /etc/ppp/peers/gprs to make DNS work right, and use pppd call gprs and killall pppd to bring the link up and down:

welcome 'cp -b /etc/ppp/resolv.conf /etc/resolv.conf' disconnect 'mv /etc/resolv.conf~ /etc/resolv.conf'

That's just about all you need to know to get online from anywhere you can get GSM service. Just don't expect blistering speeds from it: as of this writing, GPRS ranges in speed from under 5k/s to just over 20k/s, depending on your service not exactly high speed by modern standards, but amazing where you would otherwise have nothing at all.

As a little bonus, here's a short iptables script to let you share that GPRS with anyone in Wi-Fi range, which could be stored as or called from /etc/ppp/ip-up.local:

# Enable IP forwarding and rp_filter (to kill IP spoof attempts). echo "1" > /proc/sys/net/ipv4/ip_forward echo "1" > /proc/sys/net/ipv4/conf/all/rp_filter # Load relevant kernel modules, if necessary. for i in ip_tables ipt_MASQUERADE iptable_nat     ip_conntrack ip_conntrack_ftp ip_conntrack_irc \     ip_nat_irc ip_nat_ftp; do      modprobe $i 2>/dev/null; done # Masquerade anything that's not from a PPP interface # (e.g. ethernet, Wi-Fi, etc.) iptables -t nat -A POSTROUTING -o ppp+ -j MASQUERADE

But what, you ask, about regular dial-up connections? How about faxes? Well, it turns out that you're in luck: simply replace the GPRS access number with any regular phone number of your choice and (on most phones) you get a 9,600 baud data connection to that line. Configuring efax or mgetty-sendfax to use Bluetooth to fax from a GSM phone in this manner is therefore left as an exercise for the reader.

Schuyler Erle



Wireless Hacks. 100 Industrial-Strength Tips and Techniques
Wireless Hacks. 100 Industrial-Strength Tips and Techniques
ISBN: N/A
EAN: N/A
Year: 2003
Pages: 158

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net