Monday, August 10, 2009

Using PAN/NAP instead of rfcomm/ppd

I finally got a new mobile phone - one that not only supports rfcomm ("serial port" via bluetooth) but also the "PAN Network Access Point" profile - which allows a computer to connect to the internet easily, without many extra layers like PPP etc.

It's actually quite easy to use. (Note: I'm doing all that on recent openSUSE Factory, but I am pretty sure that it would work just as good on plain 11.1)

It is very handy to have the bluez-test package installed, many of the tools I am using are in that package.
First, we need to create a connection to the phone, exchange PIN numbers etc. I use bluetooth-applet from the gnome-bluetooth package (or the one from bluez-gnome) for that, it's just the best maintained tool for the task, even if you are a KDE guy like I am, I'd highly recommend it.

Now we need to find out the phones Bluetooth-Address (bdaddr):

seife@stoetzler:~> test-discovery
[ 00:24:EF:xx:xx:xx ]
Name = seife C510
Paired = 1
LegacyPairing = 1
Alias = seife C510
Address = 00:24:EF:xx:xx:xx
RSSI = -54
Class = 0x5a0204
Icon = phone

The hex number after "Address" is the bdaddr of your device.

Now we can create a network device:
seife@stoetzler:~> test-network 00:24:EF:xx:xx:xx nap
Connected /org/bluez/16833/hci0/dev_00_24_EF_XX_XX_XX to 00:24:EF:xx:xx:xx
Press CTRL-C to disconnect


Now you should have a bnep0 network interface and can (as root) either run dhcpcd directly on it, or create a config file "ifcfg-bnep0" in /etc/sysconfig/network like this:
BOOTPROTO='dhcp'
NAME='pand network device'
STARTMODE='auto'
USERCONTROL='no'

and then call "ifup-dhcp bnep0".

Two things to consider:
First, if your system is using NetworkManager, you don't get DNS addresses into resolv.conv. See this post for details. I now have
NETCONFIG_DNS_POLICY="STATIC_FALLBACK ppp0 bnep0 NetworkManager"

in my /etc/sysconfig/network/config

Second, test-network will terminate the connection after 1000 seconds (it is only a test tool), but it is easy to fix, just copy it to ~/bin/my-test-network (or whatever name you like) and apply the following trivial diff:
--- /usr/bin/test-network
+++ ~/bin/my-test-network
@@ -35,9 +35,10 @@
print "Press CTRL-C to disconnect"

try:
- time.sleep(1000)
- print "Terminating connection"
+ while 1:
+ time.sleep(1000)
except:
pass

+print "Terminating connection"
network.Disconnect()


I'm not a python wizard, so I'm pretty sure you can do better, but it works well for me.

5 comments:

  1. Harald Müller-Ney30 October, 2009 14:02

    Thank you, NICE. Interesting to read, even though my phone does not support it.
    "Old method" using rfcomm via some scripts still work, but I would prefer the PAN approach.

    I have to check my wifes new phone.

    ReplyDelete
  2. Hi, sadfully this approach doesn't seem to work with 11.1.
    bluez-test there misses test-network and even installing an uptodate bluez package doesn't work but brings a connection refused error.

    ReplyDelete
  3. Harald Müller-Ney04 November, 2009 14:09

    In case anyone is interested in the "old method" and likes to improve my initial script ;) (still with many debug output):
    -----------------------------------------------------------------------
    #!/bin/bash
    # config section
    # configure your BLUEZ ID
    BLUEZID="00:XX:XX:XX:XX:XX"
    # after suspend/resume cycle bluetooth might be off
    echo enable > /proc/acpi/ibm/bluetooth
    # short sleep to make sure bluethooth is ready
    sleep 1
    # Channel for dial up network via bluetooth might change
    # (experienced with Nokia E71 after turning bluetooth off/on)
    # re-set channel each time

    # release all rfcoom devices
    rfcomm release all
    # get current active dialup network channel
    RFCHANNEL=`sdptool browse $BLUEZID | \
    grep -A4 "Dialup Networking" | \
    awk '$1 == "Channel:" {print $2}'`
    # print out channel for debugging reasons
    echo Channel is: $RFCHANNEL
    # bind rfcomm0 to channel and device (bind all not always successful)
    rfcomm bind rfcomm0 $BLUEZID $RFCHANNEL
    # DEBUGGING check if rfcomm0 has been setup correctly
    rfcomm
    # Finally dial in
    wvdial umts
    -----------------------------------------------------------------------

    ReplyDelete
  4. Juergen Weigert07 March, 2010 18:39

    Harald, your script looks familiar to me. Over the years I've been contributing many bits and pieces to my script. It is at
    https://api.opensuse.org/public/source/home:jnweiger/jw-settings/bluetooth-internet.sh

    Seife, this is what test-network does to me on my 11.2 box:
    test-network 00:xx:xx:xx:xx:xx nap
    Traceback (most recent call last):
    File "/usr/bin/test-network", line 31, in
    iface = network.Connect(service)
    File "/usr/lib/python2.6/site-packages/dbus/proxies.py", line 68, in __call__
    return self._proxy_method(*args, **keywords)
    File "/usr/lib/python2.6/site-packages/dbus/proxies.py", line 140, in __call__
    **keywords)
    File "/usr/lib/python2.6/site-packages/dbus/connection.py", line 622, in call_blocking
    message, timeout)
    dbus.exceptions.DBusException: org.freedesktop.DBus.Error.UnknownMethod: Method "Connect" with signature "s" on interface "org.bluez.Network" doesn't exist

    ReplyDelete
  5. [...] wrote last year about how to use bluetooth networking to connect to the internet via a mobile phone. Since then, I had heard rumours that NetworkManager was now able to do this as well, but I [...]

    ReplyDelete