iPhone Tethering Woes

Another technical post this time, I am going to describe issues I’ve been having tethering my iPhone 4 to my MacBook Pro. I did eventually get a work around but it’s still not exactly great. Still, I had to piece a lot of this together by myself so this might be of interest.

Having enabled tethering on my iPhone 4, I thought I was ready to rock and roll with Internet access on the go – especially since the East Coast trains between London and Leeds now limit the amount of free time you get on them. Unfortunately, It wasn’t actually working. Both through the USB cable and via Bluetooth, Snow Leopard seemed unable to grab an IP address from the iPhone and I was ending up with something like the following:

The network service in question would always cycle from “No IP Address” to “Self-Assigned IP” and then stay that way. Basically, it was as if it was waiting for a DHCP address from the phone, but never actually getting one.

Initially, I thought that the phone (and TetherMe) might be to blame and that it simply wasn’t going to work. Other reports I had found suggested removing PdaNet, which I didn’t have installed and I couldn’t find much else in the way of ideas. Oddly enough, I fired up my Boot Camp Windows 7 installation and it worked first time, without any complaints at all (once I’d installed iTunes, that is).  So back into OS X I went to try and figure out what the deal was.

Apple actually put out a free iPhone Configuration Tool that allows you to see debug messages being output. I fired this up and proceeded to see the following messages being generated when I was trying to tether in OS X.

Thu Oct 21 00:32:32 iPhone bootpd[2029] <Notice>: DHCP DISCOVER [en1]: 1,90:27:e4:48:XX:XX
Thu Oct 21 00:32:32 iPhone bootpd[2029] <Notice>: OFFER sent MBP pktsize 300

So obviously, the iPhone was receiving the DHCP requests and actually trying to respond to them. Either the response was mal-formed, or the Mac simply wasn’t dealing with the response correctly.

It turns out that you can monitor the DHCP traffic using tcpdump from the command line. Here’s an example of a DHCP request and response that I captured:

MBP:~ $>sudo tcpdump -vvv -c 2 -i en4  -n port 67
tcpdump: listening on en4, link-type EN10MB (Ethernet), capture size 65535 bytes
00:35:20.256776 IP (tos 0x0, ttl 255, id 56463, offset 0, flags [none], proto UDP (17), length 328) > [udp sum ok] BOOTP/DHCP, Request from 90:27:e4:48:XX:XX, length 300, xid 0x7a1edf11, secs 42, Flags [none] (0x0000)
Client-Ethernet-Address 90:27:e4:48:XX:XX
Vendor-rfc1048 Extensions
Magic Cookie 0x63825363
DHCP-Message Option 53, length 1: Discover
Parameter-Request Option 55, length 10:
Subnet-Mask, Default-Gateway, Domain-Name-Server, Domain-Name
Option 119, LDAP, Option 252, Netbios-Name-Server
Netbios-Node, Netbios-Scope
MSZ Option 57, length 2: 1500
Client-ID Option 61, length 7: ether 90:27:e4:48:XX:XX
Lease-Time Option 51, length 4: 7776000
END Option 255, length 0
PAD Option 0, length 0, occurs 25

00:35:20.258306 IP (tos 0x0, ttl 255, id 12107, offset 0, flags [none], proto UDP (17), length 328) > [udp sum ok] BOOTP/DHCP, Reply, length 300, xid 0x7a1edf11, Flags [none] (0x0000)
Client-Ethernet-Address 90:27:e4:48:XX:XX
sname "iPhone"
Vendor-rfc1048 Extensions
Magic Cookie 0x63825363
DHCP-Message Option 53, length 1: Offer
Server-ID Option 54, length 4:
Lease-Time Option 51, length 4: 3564
Subnet-Mask Option 1, length 4:
Default-Gateway Option 3, length 4:
Domain-Name-Server Option 6, length 8:,
END Option 255, length 0
PAD Option 0, length 0, occurs 22

The response from the DCHP server running on the iPhone (bootpd) seems to be providing enough information for the Mac to set things up – IP allocation, subnet mask, gateway and DNS – so I’m not really sure what was going wrong. Also, the fact that it worked fine under Windows seemed to confirm my conclusions. The question now was; what can I do about it?

After a bunch of hacking around, I came up with a script that would force a DHCP renewal of the network service I was interested in, capture the conversation and then extract the data needed in order to force the manual settings on the network device.  It looks something like this:



#Get interface name (like en3 or en4)
IF=`networksetup -listnetworkserviceorder | grep "$INTERFACE" | grep -o "Device:.*" | sed -e 's/)//g' | awk '{print $2}'`

#Make sure we are in DHCP mode and force renewal
sudo networksetup -setdhcp "$INTERFACE"
sudo ipconfig set $IF DHCP

#Grab the DHCP packets:
FULLINFO=`sudo tcpdump -vvv -c 3 -i $IF -n port 67 2>/dev/null`

IP=`echo $FULLINFO | grep -o "Your-IP .*" | awk '{print $2}'`
SERVER=`echo $FULLINFO | grep -o "Default-Gateway .*" | awk '{print $6}'`
MASK=`echo $FULLINFO | grep -o "Subnet-Mask .*" | awk '{print $6}'`


sudo networksetup -setmanual "$INTERFACE" $IP $MASK $SERVER
sudo networksetup -setdnsservers "$INTERFACE" $DNS

The INTERFACE variable can be changed to “Blutooth PAN” if required and I have forced the DNS to point to the Google DNS servers. The rest simply forces the DHCP call and answer to happen, captures 3 packets of it and then extracts the information of use. The final two lines of the script apply the network settings. I had to find out about the networksetup command in OS X, which is basically a scriptable version of most of the controls in the Networking preference pane. I also used tcpdump for the first time in the course of this little adventure. Apart from that, it’s a pretty standard shell script with good old awk and sed – probably being used incorrectly/inefficiently, but it works!

One thing to note is that this script leaves the network interface in a manually configured setting. Chances are that the next time you try and connect to tether, these settings will still work and you won’t need to run the script again. For the iPhone USB device, this isn’t something that you can go back in and change through the preference pane. Running the following will revert things back to how they should be.

sudo networksetup -setdhcp "iPhone USB"

I put the script somewhere in my path so that although I do have an additional step to force this to work in Snow Leopard, it’s as simple as opening a terminal and running a single command. In retrospect, it was a lot of hassle but kind of fun and satisfying to have got it to work.

This was a bit of a pain, but worth it in the end… hopefully it might be of some help to others!

One comment

  • Jeff
    06/03/2012 - 7:23 PM | Permalink

    I found this very helpful. I was not aware you could setmanual on the iPhone USB interface. Thank you for taking the time to post.


  • Leave a Reply

    Your email address will not be published. Required fields are marked *