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.
I'm going to have to break this question apart and answer the parts separately. First the title question.
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
.
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.
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.
It's for NIS(YP), which you probably don't want.
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;
}
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With