iPhone DNS Servers

November 17th, 2009

I have been bashing my head against the fact that on the iPhone you seemingly cannot access /etc/resolv.conf, or use functions from the Mac such as SCDynamicStore stuff. I have seen many people asking this question, a few related to the same package I was trying to use – ares.

Eventually I managed to find a fix which uses the libresolv to find the DNS servers. This seems to work just fine and I have shown the patch to ares_init.c below for reference.

#if TARGET_OS_IPHONE
#include <resolv.h>
#endif

...

#if TARGET_OS_IPHONE
// XXX: On the iPhone we need to get the DNS servers using resolv.h magic
if ((_res.options & RES_INIT) == 0) res_init();
channel->nservers = _res.nscount;
channel->servers = malloc(channel->nservers * sizeof(struct server_state));
memset(channel->servers, '\0', channel->nservers * sizeof(struct server_state));

int i;
for (i = 0; i < channel->nservers; i++)
{
    memcpy(&channel->servers[i].addr, &_res.nsaddr_list[i].sin_addr, sizeof(struct in_addr));
}
#endif

[As per most of my posts these days, this is just a brain dump. I'll try to pad it out as soon as possible]

7 Responses to “iPhone DNS Servers”

  1. [...] there are people out there better informed and/or more tenacious than trolls; so here is a solution using resolv.h that some bright spark who stumbled across our begging on the dev forums came up with, which you [...]

  2. luke says:

    Nice work.Kudos

  3. Anim says:

    as i understand we need to add ares lib to the iphone project.
    should i compile ares and then add it or just add the source files?
    any good reference of how to use it inside the objective-c?

  4. @Anim – It’s up to you really. Probably easiest to compile ares and add it as a static library to link against, mainly because then you’re using the configure script from the ares project properly.

  5. Steve says:

    Thanks, this was very helpful!

    Couple of comments:
    1. With c-ares v1.7.4 the ares_addr field has a union for ipv4 and ipv6. So the inside of the loop now needs to be something like

    channel->servers[i].addr.family = AF_INET;
    memcpy(&channel->servers[i].addr.addr.addr4, &_res.nsaddr_list[i].sin_addr, sizeof(struct in_addr));

    2. This doesn’t support nameservers which themselves are only accessible via IPv6 addresses. But the _res field doesn’t seem to support that either (as of iOS 4.2), so I don’t see what can be done about it for now.

  6. @Steve – Thanks for those comments. I’ll take a look when I get a chance. I’ve not been using ares with ipv6 nameservers so haven’t had to worry about it before.

  7. ocean says:

    After upgraded to ios sdk 4.3, this does not work any more:(

Leave a Reply