Add PF_LOCAL support in getaddrinfo(3) and getnameinfo(3):
- In a PF_LOCAL address, "hostname" must begins with '/' and "servname" is always NULL. All of ai_flags are ignored. - PF_UNSPEC matches PF_LOCAL. EAI_SERVICE is not returned to make AF-independent programming easier; "servname" is always ignored in PF_LOCAL. In practice, PF_INET* and PF_LOCAL are mutually-exclusive because a hostname which begins with '/' is invalid in PF_INET*. No domain name resolution is performed for a PF_LOCAL address. Differential Revision: https://reviews.freebsd.org/D3634
This commit is contained in:
parent
9217785474
commit
a3fcca6713
@ -18,7 +18,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd February 14, 2013
|
.Dd September 20, 2015
|
||||||
.Dt GETADDRINFO 3
|
.Dt GETADDRINFO 3
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -40,7 +40,6 @@
|
|||||||
The
|
The
|
||||||
.Fn getaddrinfo
|
.Fn getaddrinfo
|
||||||
function is used to get a list of
|
function is used to get a list of
|
||||||
.Tn IP
|
|
||||||
addresses and port numbers for host
|
addresses and port numbers for host
|
||||||
.Fa hostname
|
.Fa hostname
|
||||||
and service
|
and service
|
||||||
@ -59,7 +58,9 @@ arguments are either pointers to NUL-terminated strings or the null pointer.
|
|||||||
An acceptable value for
|
An acceptable value for
|
||||||
.Fa hostname
|
.Fa hostname
|
||||||
is either a valid host name or a numeric host address string consisting
|
is either a valid host name or a numeric host address string consisting
|
||||||
of a dotted decimal IPv4 address or an IPv6 address.
|
of a dotted decimal IPv4 address,
|
||||||
|
an IPv6 address,
|
||||||
|
or a UNIX-domain address.
|
||||||
The
|
The
|
||||||
.Fa servname
|
.Fa servname
|
||||||
is either a decimal port number or a service name listed in
|
is either a decimal port number or a service name listed in
|
||||||
@ -105,6 +106,7 @@ operating system.
|
|||||||
Denotes the type of socket that is wanted:
|
Denotes the type of socket that is wanted:
|
||||||
.Dv SOCK_STREAM ,
|
.Dv SOCK_STREAM ,
|
||||||
.Dv SOCK_DGRAM ,
|
.Dv SOCK_DGRAM ,
|
||||||
|
.Dv SOCK_SEQPACKET ,
|
||||||
or
|
or
|
||||||
.Dv SOCK_RAW .
|
.Dv SOCK_RAW .
|
||||||
When
|
When
|
||||||
@ -112,9 +114,11 @@ When
|
|||||||
is zero the caller will accept any socket type.
|
is zero the caller will accept any socket type.
|
||||||
.It Fa ai_protocol
|
.It Fa ai_protocol
|
||||||
Indicates which transport protocol is desired,
|
Indicates which transport protocol is desired,
|
||||||
.Dv IPPROTO_UDP
|
.Dv IPPROTO_UDP ,
|
||||||
|
.Dv IPPROTO_TCP ,
|
||||||
|
.Dv IPPROTO_SCTP ,
|
||||||
or
|
or
|
||||||
.Dv IPPROTO_TCP .
|
.Dv IPPROTO_UDPLITE .
|
||||||
If
|
If
|
||||||
.Fa ai_protocol
|
.Fa ai_protocol
|
||||||
is zero the caller will accept any protocol.
|
is zero the caller will accept any protocol.
|
||||||
@ -131,6 +135,9 @@ or be the bitwise-inclusive OR of one or more of the values
|
|||||||
.Dv AI_NUMERICSERV
|
.Dv AI_NUMERICSERV
|
||||||
and
|
and
|
||||||
.Dv AI_PASSIVE .
|
.Dv AI_PASSIVE .
|
||||||
|
For a UNIX-domain address,
|
||||||
|
.Fa ai_flags
|
||||||
|
is ignored.
|
||||||
.Bl -tag -width "AI_CANONNAMEXX"
|
.Bl -tag -width "AI_CANONNAMEXX"
|
||||||
.It Dv AI_ADDRCONFIG
|
.It Dv AI_ADDRCONFIG
|
||||||
If the
|
If the
|
||||||
@ -419,6 +426,9 @@ freeaddrinfo(res0);
|
|||||||
.Xr getnameinfo 3 ,
|
.Xr getnameinfo 3 ,
|
||||||
.Xr getservbyname 3 ,
|
.Xr getservbyname 3 ,
|
||||||
.Xr resolver 3 ,
|
.Xr resolver 3 ,
|
||||||
|
.Xr inet 4 ,
|
||||||
|
.Xr inet6 4 ,
|
||||||
|
.Xr unix 4 ,
|
||||||
.Xr hosts 5 ,
|
.Xr hosts 5 ,
|
||||||
.Xr resolv.conf 5 ,
|
.Xr resolv.conf 5 ,
|
||||||
.Xr services 5 ,
|
.Xr services 5 ,
|
||||||
|
@ -137,13 +137,20 @@ static const struct afd {
|
|||||||
offsetof(struct sockaddr_in6, sin6_addr),
|
offsetof(struct sockaddr_in6, sin6_addr),
|
||||||
in6_addrany, in6_loopback, 1},
|
in6_addrany, in6_loopback, 1},
|
||||||
#define N_INET 1
|
#define N_INET 1
|
||||||
|
#define N_LOCAL 2
|
||||||
#else
|
#else
|
||||||
#define N_INET 0
|
#define N_INET 0
|
||||||
|
#define N_LOCAL 1
|
||||||
#endif
|
#endif
|
||||||
{PF_INET, sizeof(struct in_addr),
|
{PF_INET, sizeof(struct in_addr),
|
||||||
sizeof(struct sockaddr_in),
|
sizeof(struct sockaddr_in),
|
||||||
offsetof(struct sockaddr_in, sin_addr),
|
offsetof(struct sockaddr_in, sin_addr),
|
||||||
in_addrany, in_loopback, 0},
|
in_addrany, in_loopback, 0},
|
||||||
|
#define sizeofmember(type, member) (sizeof(((type *)0)->member))
|
||||||
|
{PF_LOCAL, sizeofmember(struct sockaddr_un, sun_path),
|
||||||
|
sizeof(struct sockaddr_un),
|
||||||
|
offsetof(struct sockaddr_un, sun_path),
|
||||||
|
NULL, NULL, 0},
|
||||||
{0, 0, 0, 0, NULL, NULL, 0},
|
{0, 0, 0, 0, NULL, NULL, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -152,29 +159,47 @@ struct explore {
|
|||||||
int e_socktype;
|
int e_socktype;
|
||||||
int e_protocol;
|
int e_protocol;
|
||||||
int e_wild;
|
int e_wild;
|
||||||
#define WILD_AF(ex) ((ex)->e_wild & 0x01)
|
#define AF_ANY 0x01
|
||||||
#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
|
#define SOCKTYPE_ANY 0x02
|
||||||
#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
|
#define PROTOCOL_ANY 0x04
|
||||||
|
#define WILD_AF(ex) ((ex)->e_wild & AF_ANY)
|
||||||
|
#define WILD_SOCKTYPE(ex) ((ex)->e_wild & SOCKTYPE_ANY)
|
||||||
|
#define WILD_PROTOCOL(ex) ((ex)->e_wild & PROTOCOL_ANY)
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct explore explore[] = {
|
static const struct explore explore[] = {
|
||||||
#if 0
|
{ PF_LOCAL, SOCK_DGRAM, ANY,
|
||||||
{ PF_LOCAL, ANY, ANY, 0x01 },
|
AF_ANY | PROTOCOL_ANY },
|
||||||
#endif
|
{ PF_LOCAL, SOCK_STREAM, ANY,
|
||||||
|
AF_ANY | PROTOCOL_ANY },
|
||||||
|
{ PF_LOCAL, SOCK_SEQPACKET, ANY,
|
||||||
|
AF_ANY | PROTOCOL_ANY },
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
{ PF_INET6, SOCK_DGRAM, IPPROTO_UDP, 0x07 },
|
{ PF_INET6, SOCK_DGRAM, IPPROTO_UDP,
|
||||||
{ PF_INET6, SOCK_STREAM, IPPROTO_TCP, 0x07 },
|
AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY },
|
||||||
{ PF_INET6, SOCK_STREAM, IPPROTO_SCTP, 0x03 },
|
{ PF_INET6, SOCK_STREAM, IPPROTO_TCP,
|
||||||
{ PF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, 0x07 },
|
AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY },
|
||||||
{ PF_INET6, SOCK_DGRAM, IPPROTO_UDPLITE, 0x03 },
|
{ PF_INET6, SOCK_STREAM, IPPROTO_SCTP,
|
||||||
{ PF_INET6, SOCK_RAW, ANY, 0x05 },
|
AF_ANY | SOCKTYPE_ANY },
|
||||||
|
{ PF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP,
|
||||||
|
AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY },
|
||||||
|
{ PF_INET6, SOCK_DGRAM, IPPROTO_UDPLITE,
|
||||||
|
AF_ANY | SOCKTYPE_ANY },
|
||||||
|
{ PF_INET6, SOCK_RAW, ANY,
|
||||||
|
AF_ANY | PROTOCOL_ANY },
|
||||||
#endif
|
#endif
|
||||||
{ PF_INET, SOCK_DGRAM, IPPROTO_UDP, 0x07 },
|
{ PF_INET, SOCK_DGRAM, IPPROTO_UDP,
|
||||||
{ PF_INET, SOCK_STREAM, IPPROTO_TCP, 0x07 },
|
AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY },
|
||||||
{ PF_INET, SOCK_STREAM, IPPROTO_SCTP, 0x03 },
|
{ PF_INET, SOCK_STREAM, IPPROTO_TCP,
|
||||||
{ PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP, 0x07 },
|
AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY },
|
||||||
{ PF_INET, SOCK_DGRAM, IPPROTO_UDPLITE, 0x03 },
|
{ PF_INET, SOCK_STREAM, IPPROTO_SCTP,
|
||||||
{ PF_INET, SOCK_RAW, ANY, 0x05 },
|
AF_ANY | SOCKTYPE_ANY },
|
||||||
|
{ PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP,
|
||||||
|
AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY },
|
||||||
|
{ PF_INET, SOCK_DGRAM, IPPROTO_UDPLITE,
|
||||||
|
AF_ANY | SOCKTYPE_ANY },
|
||||||
|
{ PF_INET, SOCK_RAW, ANY,
|
||||||
|
AF_ANY | PROTOCOL_ANY },
|
||||||
{ -1, 0, 0, 0 },
|
{ -1, 0, 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -408,6 +433,7 @@ getaddrinfo(const char *hostname, const char *servname,
|
|||||||
ERR(EAI_BADFLAGS);
|
ERR(EAI_BADFLAGS);
|
||||||
switch (hints->ai_family) {
|
switch (hints->ai_family) {
|
||||||
case PF_UNSPEC:
|
case PF_UNSPEC:
|
||||||
|
case PF_LOCAL:
|
||||||
case PF_INET:
|
case PF_INET:
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
case PF_INET6:
|
case PF_INET6:
|
||||||
@ -1130,6 +1156,9 @@ explore_null(const struct addrinfo *pai, const char *servname,
|
|||||||
*res = NULL;
|
*res = NULL;
|
||||||
ai = NULL;
|
ai = NULL;
|
||||||
|
|
||||||
|
if (pai->ai_family == PF_LOCAL)
|
||||||
|
return (0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* filter out AFs that are not supported by the kernel
|
* filter out AFs that are not supported by the kernel
|
||||||
* XXX errno?
|
* XXX errno?
|
||||||
@ -1172,8 +1201,11 @@ explore_numeric(const struct addrinfo *pai, const char *hostname,
|
|||||||
const struct afd *afd;
|
const struct afd *afd;
|
||||||
struct addrinfo *ai;
|
struct addrinfo *ai;
|
||||||
int error;
|
int error;
|
||||||
char pton[PTON_MAX];
|
char pton[PTON_MAX], path[PATH_MAX], *p;
|
||||||
|
|
||||||
|
#ifdef CTASSERT
|
||||||
|
CTASSERT(sizeofmember(struct sockaddr_un, sun_path) <= PATH_MAX);
|
||||||
|
#endif
|
||||||
*res = NULL;
|
*res = NULL;
|
||||||
ai = NULL;
|
ai = NULL;
|
||||||
|
|
||||||
@ -1182,6 +1214,15 @@ explore_numeric(const struct addrinfo *pai, const char *hostname,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch (afd->a_af) {
|
switch (afd->a_af) {
|
||||||
|
case AF_LOCAL:
|
||||||
|
if (hostname[0] != '/')
|
||||||
|
ERR(EAI_NONAME);
|
||||||
|
if (strlen(hostname) > afd->a_addrlen)
|
||||||
|
ERR(EAI_MEMORY);
|
||||||
|
/* NUL-termination does not need to be guaranteed. */
|
||||||
|
strncpy(path, hostname, afd->a_addrlen);
|
||||||
|
p = &path[0];
|
||||||
|
break;
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
/*
|
/*
|
||||||
* RFC3493 requires getaddrinfo() to accept AF_INET formats
|
* RFC3493 requires getaddrinfo() to accept AF_INET formats
|
||||||
@ -1192,15 +1233,17 @@ explore_numeric(const struct addrinfo *pai, const char *hostname,
|
|||||||
*/
|
*/
|
||||||
if (inet_aton(hostname, (struct in_addr *)pton) != 1)
|
if (inet_aton(hostname, (struct in_addr *)pton) != 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
p = pton;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (inet_pton(afd->a_af, hostname, pton) != 1)
|
if (inet_pton(afd->a_af, hostname, pton) != 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
p = pton;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pai->ai_family == afd->a_af) {
|
if (pai->ai_family == afd->a_af) {
|
||||||
GET_AI(ai, afd, pton);
|
GET_AI(ai, afd, p);
|
||||||
GET_PORT(ai, servname);
|
GET_PORT(ai, servname);
|
||||||
if ((pai->ai_flags & AI_CANONNAME)) {
|
if ((pai->ai_flags & AI_CANONNAME)) {
|
||||||
/*
|
/*
|
||||||
@ -1320,6 +1363,12 @@ get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
|
|||||||
memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
|
memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
|
||||||
ai->ai_addr->sa_len = afd->a_socklen;
|
ai->ai_addr->sa_len = afd->a_socklen;
|
||||||
ai->ai_addrlen = afd->a_socklen;
|
ai->ai_addrlen = afd->a_socklen;
|
||||||
|
if (ai->ai_family == PF_LOCAL) {
|
||||||
|
size_t n = strnlen(addr, afd->a_addrlen);
|
||||||
|
|
||||||
|
ai->ai_addrlen -= afd->a_addrlen - n;
|
||||||
|
ai->ai_addr->sa_len -= afd->a_addrlen - n;
|
||||||
|
}
|
||||||
ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
|
ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
|
||||||
p = (char *)(void *)(ai->ai_addr);
|
p = (char *)(void *)(ai->ai_addr);
|
||||||
memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
|
memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
|
||||||
@ -1378,6 +1427,9 @@ get_port(struct addrinfo *ai, const char *servname, int matchonly)
|
|||||||
if (servname == NULL)
|
if (servname == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
switch (ai->ai_family) {
|
switch (ai->ai_family) {
|
||||||
|
case AF_LOCAL:
|
||||||
|
/* AF_LOCAL ignores servname silently. */
|
||||||
|
return (0);
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
#ifdef AF_INET6
|
#ifdef AF_INET6
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd February 14, 2013
|
.Dd September 20, 2015
|
||||||
.Dt GETNAMEINFO 3
|
.Dt GETNAMEINFO 3
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -47,7 +47,7 @@ functions and is the converse of the
|
|||||||
.Xr getaddrinfo 3
|
.Xr getaddrinfo 3
|
||||||
function.
|
function.
|
||||||
.Pp
|
.Pp
|
||||||
If a link-layer address is passed to
|
If a link-layer address or UNIX-domain address is passed to
|
||||||
.Fn getnameinfo ,
|
.Fn getnameinfo ,
|
||||||
its ASCII representation will be stored in
|
its ASCII representation will be stored in
|
||||||
.Fa host .
|
.Fa host .
|
||||||
@ -56,7 +56,8 @@ The string pointed to by
|
|||||||
will be set to the empty string if non-NULL;
|
will be set to the empty string if non-NULL;
|
||||||
.Fa flags
|
.Fa flags
|
||||||
will always be ignored.
|
will always be ignored.
|
||||||
This is intended as a replacement for the legacy
|
For a link-layer address,
|
||||||
|
this can be used as a replacement of the legacy
|
||||||
.Xr link_ntoa 3
|
.Xr link_ntoa 3
|
||||||
function.
|
function.
|
||||||
.Pp
|
.Pp
|
||||||
@ -66,10 +67,17 @@ structure
|
|||||||
.Fa sa
|
.Fa sa
|
||||||
should point to either a
|
should point to either a
|
||||||
.Li sockaddr_in ,
|
.Li sockaddr_in ,
|
||||||
.Li sockaddr_in6
|
.Li sockaddr_in6 ,
|
||||||
|
.Li sockaddr_dl ,
|
||||||
or
|
or
|
||||||
.Li sockaddr_dl
|
.Li sockaddr_un
|
||||||
structure (for IPv4, IPv6 or link-layer respectively) that is
|
structure
|
||||||
|
.Po for IPv4 ,
|
||||||
|
IPv6,
|
||||||
|
link-layer,
|
||||||
|
or UNIX-domain respectively
|
||||||
|
.Pc
|
||||||
|
that is
|
||||||
.Fa salen
|
.Fa salen
|
||||||
bytes long.
|
bytes long.
|
||||||
.Pp
|
.Pp
|
||||||
@ -182,6 +190,9 @@ printf("host=%s\en", hbuf);
|
|||||||
.Xr inet_ntop 3 ,
|
.Xr inet_ntop 3 ,
|
||||||
.Xr link_ntoa 3 ,
|
.Xr link_ntoa 3 ,
|
||||||
.Xr resolver 3 ,
|
.Xr resolver 3 ,
|
||||||
|
.Xr inet 4 ,
|
||||||
|
.Xr inet6 4 ,
|
||||||
|
.Xr unix 4 ,
|
||||||
.Xr hosts 5 ,
|
.Xr hosts 5 ,
|
||||||
.Xr resolv.conf 5 ,
|
.Xr resolv.conf 5 ,
|
||||||
.Xr services 5 ,
|
.Xr services 5 ,
|
||||||
|
@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <net/if_dl.h>
|
#include <net/if_dl.h>
|
||||||
#include <net/if_types.h>
|
#include <net/if_types.h>
|
||||||
@ -62,67 +63,102 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
static int getnameinfo_inet(const struct sockaddr *, socklen_t, char *,
|
static const struct afd *find_afd(int);
|
||||||
|
static int getnameinfo_inet(const struct afd *,
|
||||||
|
const struct sockaddr *, socklen_t, char *,
|
||||||
size_t, char *, size_t, int);
|
size_t, char *, size_t, int);
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
static int ip6_parsenumeric(const struct sockaddr *, const char *, char *,
|
static int ip6_parsenumeric(const struct sockaddr *, const char *, char *,
|
||||||
size_t, int);
|
size_t, int);
|
||||||
static int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int);
|
static int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int);
|
||||||
#endif
|
#endif
|
||||||
static int getnameinfo_link(const struct sockaddr *, socklen_t, char *,
|
static int getnameinfo_link(const struct afd *,
|
||||||
|
const struct sockaddr *, socklen_t, char *,
|
||||||
|
size_t, char *, size_t, int);
|
||||||
|
static int hexname(const u_int8_t *, size_t, char *, size_t);
|
||||||
|
static int getnameinfo_un(const struct afd *,
|
||||||
|
const struct sockaddr *, socklen_t, char *,
|
||||||
size_t, char *, size_t, int);
|
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)
|
|
||||||
{
|
|
||||||
if (sa == NULL)
|
|
||||||
return (EAI_FAIL);
|
|
||||||
|
|
||||||
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 {
|
static const struct afd {
|
||||||
int a_af;
|
int a_af;
|
||||||
size_t a_addrlen;
|
size_t a_addrlen;
|
||||||
socklen_t a_socklen;
|
socklen_t a_socklen;
|
||||||
int a_off;
|
int a_off;
|
||||||
|
int (*a_func)(const struct afd *,
|
||||||
|
const struct sockaddr *, socklen_t, char *,
|
||||||
|
size_t, char *, size_t, int);
|
||||||
} afdl [] = {
|
} afdl [] = {
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
{PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
|
{PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
|
||||||
offsetof(struct sockaddr_in6, sin6_addr)},
|
offsetof(struct sockaddr_in6, sin6_addr),
|
||||||
|
getnameinfo_inet},
|
||||||
#endif
|
#endif
|
||||||
{PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
|
{PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
|
||||||
offsetof(struct sockaddr_in, sin_addr)},
|
offsetof(struct sockaddr_in, sin_addr),
|
||||||
|
getnameinfo_inet},
|
||||||
|
#define sizeofmember(type, member) (sizeof(((type *)0)->member))
|
||||||
|
{PF_LOCAL, sizeofmember(struct sockaddr_un, sun_path),
|
||||||
|
sizeof(struct sockaddr_un),
|
||||||
|
offsetof(struct sockaddr_un, sun_path),
|
||||||
|
getnameinfo_un},
|
||||||
|
{PF_LINK, sizeofmember(struct sockaddr_dl, sdl_data),
|
||||||
|
sizeof(struct sockaddr_dl),
|
||||||
|
offsetof(struct sockaddr_dl, sdl_data),
|
||||||
|
getnameinfo_link},
|
||||||
{0, 0, 0},
|
{0, 0, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sockinet {
|
int
|
||||||
u_char si_len;
|
getnameinfo(const struct sockaddr *sa, socklen_t salen,
|
||||||
u_char si_family;
|
|
||||||
u_short si_port;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
getnameinfo_inet(const struct sockaddr *sa, socklen_t salen,
|
|
||||||
char *host, size_t hostlen, char *serv, size_t servlen,
|
char *host, size_t hostlen, char *serv, size_t servlen,
|
||||||
int flags)
|
int flags)
|
||||||
{
|
{
|
||||||
const struct afd *afd;
|
const struct afd *afd;
|
||||||
|
|
||||||
|
if (sa == NULL)
|
||||||
|
return (EAI_FAIL);
|
||||||
|
|
||||||
|
afd = find_afd(sa->sa_family);
|
||||||
|
if (afd == NULL)
|
||||||
|
return (EAI_FAMILY);
|
||||||
|
if (sa->sa_family == PF_LOCAL) {
|
||||||
|
/*
|
||||||
|
* PF_LOCAL uses variable sa->sa_len depending on the
|
||||||
|
* content length of sun_path. Require 1 byte in
|
||||||
|
* sun_path at least.
|
||||||
|
*/
|
||||||
|
if (salen > afd->a_socklen ||
|
||||||
|
salen <= afd->a_socklen -
|
||||||
|
sizeofmember(struct sockaddr_un, sun_path))
|
||||||
|
return (EAI_FAIL);
|
||||||
|
} else if (salen != afd->a_socklen)
|
||||||
|
return (EAI_FAIL);
|
||||||
|
|
||||||
|
return ((*afd->a_func)(afd, sa, salen, host, hostlen,
|
||||||
|
serv, servlen, flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct afd *
|
||||||
|
find_afd(int af)
|
||||||
|
{
|
||||||
|
const struct afd *afd;
|
||||||
|
|
||||||
|
if (af == PF_UNSPEC)
|
||||||
|
return (NULL);
|
||||||
|
for (afd = &afdl[0]; afd->a_af > 0; afd++) {
|
||||||
|
if (afd->a_af == af)
|
||||||
|
return (afd);
|
||||||
|
}
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
getnameinfo_inet(const struct afd *afd,
|
||||||
|
const struct sockaddr *sa, socklen_t salen,
|
||||||
|
char *host, size_t hostlen, char *serv, size_t servlen,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
struct servent *sp;
|
struct servent *sp;
|
||||||
struct hostent *hp;
|
struct hostent *hp;
|
||||||
u_short port;
|
u_short port;
|
||||||
@ -132,18 +168,8 @@ getnameinfo_inet(const struct sockaddr *sa, socklen_t salen,
|
|||||||
char numserv[512];
|
char numserv[512];
|
||||||
char numaddr[512];
|
char numaddr[512];
|
||||||
|
|
||||||
for (afd = &afdl[0]; afd->a_af > 0; afd++) {
|
|
||||||
if (afd->a_af == sa->sa_family)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (afd->a_af == 0)
|
|
||||||
return (EAI_FAMILY);
|
|
||||||
|
|
||||||
if (salen != afd->a_socklen)
|
|
||||||
return EAI_FAIL;
|
|
||||||
|
|
||||||
/* network byte order */
|
/* network byte order */
|
||||||
port = ((const struct sockinet *)sa)->si_port;
|
port = ((const struct sockaddr_in *)sa)->sin_port;
|
||||||
addr = (const char *)sa + afd->a_off;
|
addr = (const char *)sa + afd->a_off;
|
||||||
|
|
||||||
if (serv == NULL || servlen == 0) {
|
if (serv == NULL || servlen == 0) {
|
||||||
@ -377,7 +403,8 @@ ip6_sa2str(const struct sockaddr_in6 *sa6, char *buf, size_t bufsiz, int flags)
|
|||||||
*/
|
*/
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
static int
|
static int
|
||||||
getnameinfo_link(const struct sockaddr *sa, socklen_t salen,
|
getnameinfo_link(const struct afd *afd,
|
||||||
|
const struct sockaddr *sa, socklen_t salen,
|
||||||
char *host, size_t hostlen, char *serv, size_t servlen, int flags)
|
char *host, size_t hostlen, char *serv, size_t servlen, int flags)
|
||||||
{
|
{
|
||||||
const struct sockaddr_dl *sdl =
|
const struct sockaddr_dl *sdl =
|
||||||
@ -465,3 +492,30 @@ hexname(const u_int8_t *cp, size_t len, char *host, size_t hostlen)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getnameinfo_un():
|
||||||
|
* Format a UNIX IPC domain address (pathname).
|
||||||
|
*/
|
||||||
|
/* ARGSUSED */
|
||||||
|
static int
|
||||||
|
getnameinfo_un(const struct afd *afd,
|
||||||
|
const struct sockaddr *sa, socklen_t salen,
|
||||||
|
char *host, size_t hostlen, char *serv, size_t servlen, int flags)
|
||||||
|
{
|
||||||
|
size_t pathlen;
|
||||||
|
|
||||||
|
if (serv != NULL && servlen > 0)
|
||||||
|
*serv = '\0';
|
||||||
|
if (host != NULL && hostlen > 0) {
|
||||||
|
pathlen = sa->sa_len - afd->a_off;
|
||||||
|
|
||||||
|
if (pathlen + 1 > hostlen) {
|
||||||
|
*host = '\0';
|
||||||
|
return (EAI_MEMORY);
|
||||||
|
}
|
||||||
|
strlcpy(host, (const char *)sa + afd->a_off, pathlen + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user