Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieving DHCP-allocated domain suffix in Linux C

I'm trying to retrieve the local domain suffix of my host programmatically in ANSI C (Linux). Eg: my machine is ironside.0ffnet.net, I'd like to retrieve "0ffnet.net".

I've seen a number of posts addressing this by using getnameinfo() and getaddrinfo(), however it appears that these functions pull their information from the /etc/hosts file for any interface addresses local to the machine.

If my machine is allocated an address (and corresponding domain suffix) via DHCP, the /etc/hosts file does not get updated, instead this information is stored in /etc/resolv.conf e.g.:

dfex@ironside:~/hush$cat /etc/resolv.conf 
domain 0ffnet.net
search 0ffnet.net
nameserver 139.130.4.4

as a result, both getnameinfo() and getaddrinfo() simply return the hostname of the machine, without the suffix, using the /etc/hosts info, which looks like:

dfex@ironside:~/hush$ cat /etc/hosts
::1             ironside localhost6.localdomain6 localhost6
127.0.1.1       ironside
127.0.0.1       localhost
::1             localhost ip6-localhost ip6-loopback

Does anybody know of a function that will pull this information without resorting to system() calls? I've been combing through Beej's guide without much success.

like image 848
Benjamin Dale Avatar asked Sep 01 '12 11:09

Benjamin Dale


3 Answers

I'm going to have to break this question apart and answer the parts separately. First the title question.

DHCP domain

The only way to really know what the DHCP client has received from the DHCP server is to read the files that the client has left in /var/lib/dhcp. The search domain suggested by DHCP might not be used at all, if something else has taken control of resolv.conf.

"the local domain suffix of my host"

A host may belong to several domains, or none, making this a hard concept to define. resolv.conf specifies domains that will be searched for hostnames that you are resolving; there's no fundamental guarantee that the search will be successful when applied to your own hostname.

Whatever! The resolver search list is what I really want. How do I get it?

Call res_init and then look at _res.dnsrch and/or _res.defdname. Or parse resolv.conf yourself; it's a pretty simple and stable format.

Then what is getdomainname() for?

It's for NIS(YP), which you probably don't want.

like image 162
Alan Curry Avatar answered Oct 16 '22 07:10

Alan Curry


You could try to use:

int getdomainname(char *name, size_t len);

Try to run this program:

#include <unistd.h>
#include <stdio.h>

int main()
{
 char buf[255];
 getdomainname(buf, 255);
 printf("Domain: %s\n", buf);
 return 0; 
}

EDIT:

Nope, after many tries I suspect you'll have to use a syscall and an ugly C parser (using AWK inside the popen would have made this code a little bit shorter).

This code seems to work for me:

#include <stdio.h>
#include <string.h>

int main()
{
 char buf[255];
 const char reqhostname[255] = "ENTER_YOUR_HOSTNAME_HERE";

 FILE *fd;
 char readbuf[255];
 char *pch;
 int token_counter = 0;

 memset(buf, 0, 255);
 strcat(buf, "host ");
 strcat(buf, reqhostname);
 fd = popen(buf, "r");
 fgets(readbuf, 255, fd);
 printf("Host returned: %s\n", readbuf);
 pclose(fd);

 pch = strtok(readbuf, " ");
 while (pch != NULL)
   {
        strcpy(buf, pch);
        break;
   }

 memset(buf2, 0, 255);
 pch = strtok(buf, ".");
 while (pch != NULL)
   {
        pch = strtok(NULL, ".");
        if (pch == NULL)
           {
                memset(buf, 0, 255);
                strncpy(buf, buf2, strlen(buf2) - 1);
                break;
           }
        token_counter++;
        strcat(buf2, pch);
        strcat(buf2, ".");
   }

 printf("Domain: %s\n", buf);

 return 0;
}
like image 31
Avio Avatar answered Oct 16 '22 05:10

Avio


Thanks @alan-curry that definitely pointed me in the right direction. For anyone else struggling with this, res_init is definitely the way to go. Here's a quick way to get the local domain suffix:

#include <stdio.h>
#include <resolv.h>

int main (int argc, char *argv[]) {

res_init();

printf ("Default domain: %s\n", _res.defdname);
return 0;
}
like image 29
Benjamin Dale Avatar answered Oct 16 '22 06:10

Benjamin Dale