AF_LINK support for getnameinfo().

Obtained from:	NetBSD
This commit is contained in:
bms 2007-03-14 16:44:31 +00:00
parent f3e0084665
commit 5c96749150
2 changed files with 135 additions and 12 deletions

View File

@ -18,7 +18,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd December 20, 2004
.Dd February 28, 2007
.Dt GETNAMEINFO 3
.Os
.Sh NAME
@ -47,15 +47,29 @@ functions and is the converse of the
.Xr getaddrinfo 3
function.
.Pp
If a link-layer address is passed to
.Fn getnameinfo ,
its ASCII representation will be stored in
.Fa host .
The string pointed to by
.Fa serv
will be set to the empty string if non-NULL;
.Fa flags
will always be ignored.
This is intended as a replacement for the legacy
.Xr link_ntoa 3
function.
.Pp
The
.Li sockaddr
structure
.Fa sa
should point to either a
.Li sockaddr_in
or
.Li sockaddr_in ,
.Li sockaddr_in6
structure (for IPv4 or IPv6 respectively) that is
or
.Li sockaddr_dl
structure (for IPv4, IPv6 or link-layer respectively) that is
.Fa salen
bytes long.
.Pp
@ -166,6 +180,7 @@ printf("host=%s\en", hbuf);
.Xr gethostbyaddr 3 ,
.Xr getservbyport 3 ,
.Xr inet_ntop 3 ,
.Xr link_ntoa 3 ,
.Xr resolver 3 ,
.Xr hosts 5 ,
.Xr resolv.conf 5 ,

View File

@ -2,6 +2,7 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* Copyright (c) 2000 Ben Harris.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -49,6 +50,8 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
@ -58,6 +61,38 @@ __FBSDID("$FreeBSD$");
#include <stddef.h>
#include <errno.h>
static int getnameinfo_inet(const struct sockaddr *, socklen_t, char *,
size_t, char *, size_t, int);
#ifdef INET6
static int ip6_parsenumeric(const struct sockaddr *, const char *, char *,
size_t, int);
static int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int);
#endif
static int getnameinfo_link(const struct sockaddr *, socklen_t, char *,
size_t, char *, size_t, int);
static int hexname(const u_int8_t *, size_t, char *, size_t);
int
getnameinfo(const struct sockaddr *sa, socklen_t salen,
char *host, size_t hostlen, char *serv, size_t servlen,
int flags)
{
switch (sa->sa_family) {
case AF_INET:
#ifdef INET6
case AF_INET6:
#endif
return getnameinfo_inet(sa, salen, host, hostlen, serv,
servlen, flags);
case AF_LINK:
return getnameinfo_link(sa, salen, host, hostlen, serv,
servlen, flags);
default:
return EAI_FAMILY;
}
}
static const struct afd {
int a_af;
size_t a_addrlen;
@ -79,14 +114,8 @@ struct sockinet {
u_short si_port;
};
#ifdef INET6
static int ip6_parsenumeric(const struct sockaddr *, const char *, char *,
size_t, int);
static int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int);
#endif
int
getnameinfo(const struct sockaddr *sa, socklen_t salen,
static int
getnameinfo_inet(const struct sockaddr *sa, socklen_t salen,
char *host, size_t hostlen, char *serv, size_t servlen,
int flags)
{
@ -343,3 +372,82 @@ ip6_sa2str(const struct sockaddr_in6 *sa6, char *buf, size_t bufsiz, int flags)
return n;
}
#endif /* INET6 */
/*
* getnameinfo_link():
* Format a link-layer address into a printable format, paying attention to
* the interface type.
*/
/* ARGSUSED */
static int
getnameinfo_link(const struct sockaddr *sa, socklen_t salen,
char *host, size_t hostlen, char *serv, size_t servlen, int flags)
{
const struct sockaddr_dl *sdl =
(const struct sockaddr_dl *)(const void *)sa;
int n;
if (serv != NULL && servlen > 0)
*serv = '\0';
if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && sdl->sdl_slen == 0) {
n = snprintf(host, hostlen, "link#%d", sdl->sdl_index);
if (n > hostlen) {
*host = '\0';
return EAI_MEMORY;
}
return 0;
}
switch (sdl->sdl_type) {
/*
* The following have zero-length addresses.
* IFT_ATM (net/if_atmsubr.c)
* IFT_FAITH (net/if_faith.c)
* IFT_GIF (net/if_gif.c)
* IFT_LOOP (net/if_loop.c)
* IFT_PPP (net/if_ppp.c, net/if_spppsubr.c)
* IFT_SLIP (net/if_sl.c, net/if_strip.c)
* IFT_STF (net/if_stf.c)
* IFT_L2VLAN (net/if_vlan.c)
* IFT_BRIDGE (net/if_bridge.h>
*/
/*
* The following use IPv4 addresses as link-layer addresses:
* IFT_OTHER (net/if_gre.c)
* IFT_OTHER (netinet/ip_ipip.c)
*/
/* default below is believed correct for all these. */
case IFT_ARCNET:
case IFT_ETHER:
case IFT_FDDI:
case IFT_HIPPI:
case IFT_ISO88025:
default:
return hexname((u_int8_t *)LLADDR(sdl), (size_t)sdl->sdl_alen,
host, hostlen);
}
}
static int
hexname(cp, len, host, hostlen)
const u_int8_t *cp;
char *host;
size_t len, hostlen;
{
int i, n;
char *outp = host;
*outp = '\0';
for (i = 0; i < len; i++) {
n = snprintf(outp, hostlen, "%s%02x",
i ? ":" : "", cp[i]);
if (n < 0 || n >= hostlen) {
*host = '\0';
return EAI_MEMORY;
}
outp += n;
hostlen -= n;
}
return 0;
}