Say Goodnight Software

iOS & More

BonjourVertise – Bonjour Across Subnets

| 0 comments

For my day job I work at a fairly large corporation. The networking structure is extremely complex, such that all wireless devices are on a different subnet than wired ethernet devices. Further, there seems to be multiple subnets for wireless devices, even ones that are right next to each other. Plus, the IS department is extremely security oriented. All I wanted to be able to do was sync my to-do manager (Things) on my iPad, iPhone and Mac Pro. Things uses Bonjour to do its syncing. This proved so difficult, that I eventually gave up and used a different to-do manager for a long time. Longing to get back to Things. Today I was able to return to Things! Click to find out how, and download a application that will do it for you!

Recently I worked on an iPad project where I needed to connect to a server on my Mac Pro. Again, I ran into this same Bonjour cross-subnet issue. I spent some time investigating the issue. Apparently Bonjour does do cross subnet advertising, but only if you configure your DNS server correctly. However, I asked this question on Stackoverflow.com and got a very interesting response. A program doesn’t have to provide the service it advertises!

This got me thinking of how I could forward the bonjour advertising for my mobile devices by writing a small application on my MacPro that would insert the bonjour data into the MacPro subnet, but refer to a service (by IP address) provided by my mobile devices.

I started by using a fantastic program for exploring Bonjour services called Bonjour Browser. This is useful for watching when services popup and go away, and what they look like. However, in this case, I really needed to look at the services running on my mobile devices, not on my MacPro, because for Things syncing the desktop client connects to the mobile devices when the mobile device advertises itself. So, I needed to find out the information that the mobile device was advertising, and forward that to the MacPro subnet. Luckily, there is a BonjourBrowser for the iPhone as well!

What pieces of information do we need? We will need:

- the mobile device IP address
- the bonjour service identifier that Things uses
- the port that Things is running on

The IP address is easy. On your iPhone go to ‘Settings’, ‘WiFi’, and click the blue arrow next to the network you are connected to.

The bonjour service identifier is a bit harder, but as I said, there is Bonjour Browser for the iPhone. The problem is that even on iOS4, when Things gets pushed to the background, it no longer advertises in bonjour. However, for some reason bonjour browser still sees the identifier! It can’t get the ip or port for us, but the identifier should be: _cciphonethings._tcp. Note that if you want to advertise a different service, the identifier will be something else, chosen by the developer of that service.

Lastly, we need the port. This is a tough one. When using bonjour properly, ports are left up to the system to dynamically allocate. This is awesome for developers cause we never have to hard code them. However, we need to figure out what port Things is using, and it could be different every time. Further, once Things gets pushed to the background on iOS4, it is no longer advertising, and when brought back to the foreground, it will have a different port. The best way I found is to go old school, and scan it out!

First, I started with an application called nmap. nmap will do all kinds of scanning, but we are interested in the port scanning to a specific ip address. A command like this will scan all the ports on your iPhone/iPad, and output the open ports.

sudo nmap -PN -p0-65535

However, that can take a while. Usually ‘Things’ ports are either 65000-65535 or 49000-50000. However, I have no basis for this. If you can’t scan out the port in those ranges, broaden it a bit. I found scanning every port takes about 10 minutes, so if you get stuck you can always scan them all.

You should see results like this:


Starting Nmap 5.21 ( http://nmap.org ) at 2010-09-27 20:15 EDT
Nmap scan report for 10.0.1.198
Host is up (0.0064s latency).
Not shown: 1000 closed ports
PORT STATE SERVICE
49231/tcp open unknown
MAC Address: blah:blah:blah:blah (Unknown)

Nmap done: 1 IP address (1 host up) scanned in 12.30 seconds

That tells us the port we want is 49231!

Now that we have the port, you just need to write a bit of code that advertises the service in our local subnet. For this code I am directly uses the dns_sd.h that provides the most basic Bonjour advertising. It looks like this:

- (IBAction) advertiseClicked:(id) sender {
	
	DNSServiceRef register_svc;
    DNSServiceErrorType err;
	NSString* hostname = [self getHostnameWithIP:[[ipAddress stringValue] UTF8String]];
	err = DNSServiceRegister(&register_svc,
                             0 ,
                             0 ,
                             [hostname UTF8String],
                             [[bonjourType stringValue] UTF8String],
                             NULL,
                             [hostname UTF8String],
                             htons([portNumber intValue]),
                             0,
                             NULL,
                             NULL,
                             NULL);
	
	if (err != kDNSServiceErr_NoError) {
        NSLog(@"error in DNSServiceRegister");
    }
}

You simply plug in the bits of information we gathered, and viola! You are now advertising! To make it even, easier I wrote a little application that handles most of this for you, including the scanning of the port. I put everything up on GitHub, so you can grab it with the links below!

Source Code
Binary

Leave a Reply

Required fields are marked *.