Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

netdb: getaddrinfo()/getnameinfo()

39 views
Skip to first unread message

Davlet Panech

unread,
Aug 23, 2002, 6:46:07 PM8/23/02
to
Hi,

I have been using gethostby/name/addr() for resolving IP address
resolution; however my man page says that these functions are
deprecated in favour of getaddrinfo()/getnameinfo(). I'm having
trouble understanding how they work though. What is the right way
to retrieve the list of aliases (that alternative human-readable names)
of a host using getaddrinfo()/getnameinfo()? It seems impossible from
what I see in the manuals.

Another question: if I wanted to retrieve the list of all local
interfaces, how would I do that? I have always used gethostname()
followed by gethostbyname(), is that the right thing to do?

[My experience with UNIX is quite limited, please be easy on me!]

Thanks,
D.P.

Dan Mercer

unread,
Aug 24, 2002, 1:37:28 PM8/24/02
to
In article <3D66BB2F...@tellabs.com>,

What UNIX?

--
Dan Mercer
dame...@mmm.com

If responding by email, include the phrase 'from usenet'
in the subject line to avoid spam filtering.

Opinions expressed herein are my own and may not represent those of my employer.

Davlet Panech

unread,
Aug 27, 2002, 5:03:55 PM8/27/02
to
Dan Mercer wrote:
>
> In article <3D66BB2F...@tellabs.com>,
> Davlet Panech <Davlet...@Tellabs.com> writes:
> > Hi,
> >
> > I have been using gethostby/name/addr() for resolving IP address
> > resolution; however my man page says that these functions are
> > deprecated in favour of getaddrinfo()/getnameinfo(). I'm having
> > trouble understanding how they work though. What is the right way
> > to retrieve the list of aliases (that alternative human-readable names)
> > of a host using getaddrinfo()/getnameinfo()? It seems impossible from
> > what I see in the manuals.
> >
> > Another question: if I wanted to retrieve the list of all local
> > interfaces, how would I do that? I have always used gethostname()
> > followed by gethostbyname(), is that the right thing to do?
> >
> > [My experience with UNIX is quite limited, please be easy on me!]
> >
> > Thanks,
> > D.P.
>
> What UNIX?

The ones that support getaddrinfo(), obviously. For example Sun Solaris.
What difference does it make anyway? My question is about getaddrinfo()
and friends whose behavior I assume is standardized (I was using the
Open Group standard but couldn't make out the details which is why I
post here).

As far as question #2 -- finding out all local interfaces -- I would be
interested in a standard way if one exists. Or a confirmation that
it does not exist + OS-specific ways for a few popular UNIXes (Solaris,
Linux, FreeBSD), but that maybe off-topic here (?).

Once again I'm a newbie so please forgive my ignorance.

Thank you,
D.P.

Floyd Davidson

unread,
Aug 27, 2002, 6:17:56 PM8/27/02
to
Davlet Panech <Davlet...@Tellabs.com> wrote:
>
>The ones that support getaddrinfo(), obviously. For example Sun Solaris.
>What difference does it make anyway? My question is about getaddrinfo()
>and friends whose behavior I assume is standardized (I was using the
>Open Group standard but couldn't make out the details which is why I
>post here).
>
>As far as question #2 -- finding out all local interfaces -- I would be
>interested in a standard way if one exists. Or a confirmation that
>it does not exist + OS-specific ways for a few popular UNIXes (Solaris,
>Linux, FreeBSD), but that maybe off-topic here (?).
>
>Once again I'm a newbie so please forgive my ignorance.
>
>Thank you,
>D.P.

As far as I can tell (I am a long ways from being an expert
though), you are correct about aliases and getaddrinfo().

Finding all network interfaces is fairly portable, though there
are some systems where getting the hardware address is different
than on others. Here is a demo program that has been posted to
the net many times, which demonstrates locating all network
interfaces and how to obtain information about any given
interface. This was specifically developed on Linux and you
will very likely need to fiddle with which headers are included
to port it to other platforms, or even other Linux
distributions.

/*
* display info about network interfaces
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <net/if_arp.h>

#define inaddrr(x) (*(struct in_addr *) &ifr->x[sizeof sa.sin_port])
#define IFRSIZE ((int)(size * sizeof (struct ifreq)))

int main(void)
{
unsigned char *u;
int sockfd, size = 1;
struct ifreq *ifr;
struct ifconf ifc;
struct sockaddr_in sa;

if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
fprintf(stderr, "Cannot open socket.\n");
exit(EXIT_FAILURE);
}

ifc.ifc_len = IFRSIZE;
ifc.ifc_req = NULL;

do {
++size;
/* realloc buffer size until no overflow occurs */
if (NULL == (ifc.ifc_req = realloc(ifc.ifc_req, IFRSIZE))) {
fprintf(stderr, "Out of memory.\n");
exit(EXIT_FAILURE);
}
ifc.ifc_len = IFRSIZE;
if (ioctl(sockfd, SIOCGIFCONF, &ifc)) {
perror("ioctl SIOCFIFCONF");
exit(EXIT_FAILURE);
}
} while (IFRSIZE <= ifc.ifc_len);

ifr = ifc.ifc_req;
for (;(char *) ifr < (char *) ifc.ifc_req + ifc.ifc_len; ++ifr) {

if (ifr->ifr_addr.sa_data == (ifr+1)->ifr_addr.sa_data) {
continue; /* duplicate, skip it */
}

if (ioctl(sockfd, SIOCGIFFLAGS, ifr)) {
continue; /* failed to get flags, skip it */
}

printf("Interface: %s\n", ifr->ifr_name);
printf("IP Address: %s\n", inet_ntoa(inaddrr(ifr_addr.sa_data)));

/*
This won't work on HP-UX 10.20 as there's no SIOCGIFHWADDR ioctl. You'll
need to use DLPI or the NETSTAT ioctl on /dev/lan0, etc (and you'll need
to be root to use the NETSTAT ioctl. Also this is deprecated and doesn't
work on 11.00).

On Digital Unix you can use the SIOCRPHYSADDR ioctl according to an old
utility I have. Also on SGI I think you need to use a raw socket, e.g. s
= socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP)

Dave

From: David Peter <dave....@eu.citrix.com>
*/

if (0 == ioctl(sockfd, SIOCGIFHWADDR, ifr)) {

/* Select which hardware types to process.
*
* See list in system include file included from
* /usr/include/net/if_arp.h (For example, on
* Linux see file /usr/include/linux/if_arp.h to
* get the list.)
*/
switch (ifr->ifr_hwaddr.sa_family) {
default:
printf("\n");
continue;
case ARPHRD_NETROM: case ARPHRD_ETHER: case ARPHRD_PPP:
case ARPHRD_EETHER: case ARPHRD_IEEE802: break;
}

u = (unsigned char *) &ifr->ifr_addr.sa_data;

if (u[0] + u[1] + u[2] + u[3] + u[4] + u[5]) {
printf("HW Address: %2.2x.%2.2x.%2.2x.%2.2x.%2.2x.%2.2x\n",
u[0], u[1], u[2], u[3], u[4], u[5]);
}
}

if (0 == ioctl(sockfd, SIOCGIFNETMASK, ifr) &&
strcmp("255.255.255.255", inet_ntoa(inaddrr(ifr_addr.sa_data)))) {
printf("Netmask: %s\n", inet_ntoa(inaddrr(ifr_addr.sa_data)));
}

if (ifr->ifr_flags & IFF_BROADCAST) {
if (0 == ioctl(sockfd, SIOCGIFBRDADDR, ifr) &&
strcmp("0.0.0.0", inet_ntoa(inaddrr(ifr_addr.sa_data)))) {
printf("Broadcast: %s\n", inet_ntoa(inaddrr(ifr_addr.sa_data)));
}
}

if (0 == ioctl(sockfd, SIOCGIFMTU, ifr)) {
printf("MTU: %u\n", ifr->ifr_mtu);
}

if (0 == ioctl(sockfd, SIOCGIFMETRIC, ifr)) {
printf("Metric: %u\n", ifr->ifr_metric);
}
printf("\n");
}

close(sockfd);
return EXIT_SUCCESS;
}


--
Floyd L. Davidson <http://www.ptialaska.net/~floyd>
Ukpeagvik (Barrow, Alaska) fl...@barrow.com

Bjorn Reese

unread,
Aug 28, 2002, 6:45:54 AM8/28/02
to
Davlet Panech wrote:

> I have been using gethostby/name/addr() for resolving IP address
> resolution; however my man page says that these functions are
> deprecated in favour of getaddrinfo()/getnameinfo(). I'm having
> trouble understanding how they work though. What is the right way
> to retrieve the list of aliases (that alternative human-readable names)
> of a host using getaddrinfo()/getnameinfo()? It seems impossible from
> what I see in the manuals.

gethostbyname() returns a hostent structure which contains the
aliases in a NULL terminated array called h_addr_list.

getaddrinfo() returns an addrinfo structure which contains the
same aliases, but in a linked-list. So you just traverse the
list using ai_next, and retrieve each alias contained in ai_addr.

If you want to convert these aliases into a human-readable format
you must use inet_ntop() (or inet_ntoa()).

0 new messages