Add the 'A' and 'P' format specifiers which use getaddrinfo(3) to turn
numbers into names (if possible). Also add the '?' format modifier that elides the "N/A" if that's what you would normally get.
This commit is contained in:
parent
7f2367785b
commit
a9321bb19a
@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: sockaddr_snprintf.3,v 1.3 2004/12/01 00:06:46 peter Exp $
|
||||
.\" $NetBSD: sockaddr_snprintf.3,v 1.4 2005/04/09 02:05:47 atatat Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2004 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
@ -106,6 +106,16 @@ but the interface portion is skipped (see below).
|
||||
For
|
||||
.Dv AF_UNSPEC
|
||||
nothing is printed.
|
||||
.It A
|
||||
The symbolic name of the address is printed.
|
||||
For
|
||||
.Dv AF_INET
|
||||
and
|
||||
.AF_INET6
|
||||
this is the hostname associated with the address.
|
||||
For all other address families, it is the same as the
|
||||
.Dq a
|
||||
format.
|
||||
.It f
|
||||
The numeric value of the family of the address is printed.
|
||||
.It l
|
||||
@ -117,6 +127,16 @@ For
|
||||
and
|
||||
.Dv AF_APPLETALK
|
||||
the numeric value of the port portion of the address is printed.
|
||||
.It P
|
||||
For
|
||||
.Dv AF_INET
|
||||
and
|
||||
.Dv AF_INET6
|
||||
this is the name of the service associated with the port number, if
|
||||
available.
|
||||
For all other address families, it is the same as the
|
||||
.Dq p
|
||||
format.
|
||||
.It I
|
||||
For
|
||||
.Dv AF_LINK
|
||||
@ -134,6 +154,13 @@ addresses, the netrange portion of the address is printed as:
|
||||
For
|
||||
.Dv AF_INET6
|
||||
addresses, the scope portion of the address is printed numerically.
|
||||
.It ?
|
||||
If present between
|
||||
.Dq %
|
||||
and the format character and the selected format does not apply to
|
||||
the given address family, the
|
||||
.Dq N/A
|
||||
string is elided and no output results.
|
||||
.El
|
||||
.Sh RETURN VALUES
|
||||
The
|
||||
@ -172,6 +199,7 @@ is too small to hold the formatted output,
|
||||
.Fn sockaddr_snprintf
|
||||
will still return the buffer, containing a truncated string.
|
||||
.Sh SEE ALSO
|
||||
.Xr getaddrinfo 3 ,
|
||||
.Xr getnameinfo 3 ,
|
||||
.Xr link_ntoa 3 ,
|
||||
.Xr snprintf 3
|
||||
@ -196,9 +224,20 @@ instead of
|
||||
.Pp
|
||||
This function is supposed to be quick, but
|
||||
.Xr getnameinfo 3
|
||||
might use system calls to convert the scope number to an interface name.
|
||||
might use system calls to convert the scope number to an interface
|
||||
name and the
|
||||
.Dq A
|
||||
and
|
||||
.Dq P
|
||||
format characters call
|
||||
.Xr getaddrinfo 3
|
||||
which may block for a noticeable period of time.
|
||||
.Pp
|
||||
Not all formatting characters are supported by all address families and
|
||||
printing
|
||||
.Dq N/A
|
||||
is not very convenient.
|
||||
The
|
||||
.Dq \&?
|
||||
character can suppress this but other formatting (e.g., spacing or
|
||||
punctuation) will remain.
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: sockaddr_snprintf.c,v 1.4 2005/01/13 00:44:25 dyoung Exp $ */
|
||||
/* $NetBSD: sockaddr_snprintf.c,v 1.5 2005/04/09 02:05:47 atatat Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2004 The NetBSD Foundation, Inc.
|
||||
@ -37,7 +37,7 @@
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
__RCSID("$NetBSD: sockaddr_snprintf.c,v 1.4 2005/01/13 00:44:25 dyoung Exp $");
|
||||
__RCSID("$NetBSD: sockaddr_snprintf.c,v 1.5 2005/04/09 02:05:47 atatat Exp $");
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
@ -59,20 +59,26 @@ sockaddr_snprintf(char *buf, size_t len, const char *fmt,
|
||||
const struct sockaddr *sa)
|
||||
{
|
||||
const void *a = NULL;
|
||||
char abuf[1024], nbuf[1024], *addr, *w;
|
||||
char abuf[1024], nbuf[1024], *addr = NULL, *w = NULL;
|
||||
char Abuf[1024], pbuf[32], *name = NULL, *port = NULL;
|
||||
char *ebuf = &buf[len - 1], *sbuf = buf;
|
||||
const char *ptr, *s;
|
||||
in_port_t p = (in_port_t)~0;
|
||||
int p = -1;
|
||||
const struct sockaddr_at *sat = NULL;
|
||||
const struct sockaddr_in *sin4 = NULL;
|
||||
const struct sockaddr_in6 *sin6 = NULL;
|
||||
const struct sockaddr_un *sun = NULL;
|
||||
const struct sockaddr_dl *sdl = NULL;
|
||||
int na = 1;
|
||||
|
||||
#define ADDC(c) if (buf < ebuf) *buf++ = c; else buf++
|
||||
#define ADDN() if (buf < ebuf) *buf = '\0'; else buf[len - 1] = '\0'
|
||||
#define ADDS(p) for (s = p; *s; s++) ADDC(*s)
|
||||
#define ADDNA() ADDS("N/A")
|
||||
#define ADDC(c) do { if (buf < ebuf) *buf++ = c; else buf++; } \
|
||||
while (/*CONSTCOND*/0)
|
||||
#define ADDN() do { if (buf < ebuf) *buf = '\0'; else buf[len - 1] = '\0'; } \
|
||||
while (/*CONSTCOND*/0)
|
||||
#define ADDS(p) do { for (s = p; *s; s++) ADDC(*s); } \
|
||||
while (/*CONSTCOND*/0)
|
||||
#define ADDNA() do { if (na) ADDS("N/A"); } \
|
||||
while (/*CONSTCOND*/0)
|
||||
|
||||
switch (sa->sa_family) {
|
||||
case AF_UNSPEC:
|
||||
@ -82,6 +88,7 @@ sockaddr_snprintf(char *buf, size_t len, const char *fmt,
|
||||
p = ntohs(sat->sat_port);
|
||||
(void)snprintf(addr = abuf, sizeof(abuf), "%u.%u",
|
||||
ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node);
|
||||
(void)snprintf(port = pbuf, sizeof(pbuf), "%d", p);
|
||||
break;
|
||||
case AF_LOCAL:
|
||||
sun = ((const struct sockaddr_un *)(const void *)sa);
|
||||
@ -103,7 +110,6 @@ sockaddr_snprintf(char *buf, size_t len, const char *fmt,
|
||||
if ((w = strchr(addr, ':')) != 0) {
|
||||
*w++ = '\0';
|
||||
addr = w;
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -111,6 +117,9 @@ sockaddr_snprintf(char *buf, size_t len, const char *fmt,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (addr == abuf)
|
||||
name = addr;
|
||||
|
||||
if (a && getnameinfo(sa, (socklen_t)sa->sa_len, addr = abuf,
|
||||
sizeof(abuf), NULL, 0, NI_NUMERICHOST|NI_NUMERICSERV) != 0)
|
||||
return -1;
|
||||
@ -120,20 +129,20 @@ sockaddr_snprintf(char *buf, size_t len, const char *fmt,
|
||||
ADDC(*ptr);
|
||||
continue;
|
||||
}
|
||||
next_char:
|
||||
switch (*++ptr) {
|
||||
case '\0':
|
||||
ADDC('%');
|
||||
goto done;
|
||||
case '?':
|
||||
na = 0;
|
||||
goto next_char;
|
||||
case 'a':
|
||||
ADDS(addr);
|
||||
break;
|
||||
case 'p':
|
||||
if (p != (in_port_t)~0) {
|
||||
(void)snprintf(nbuf, sizeof(nbuf), "%d", p);
|
||||
ADDS(nbuf);
|
||||
} else {
|
||||
ADDNA();
|
||||
}
|
||||
if (p != -1) {
|
||||
(void)snprintf(nbuf, sizeof(nbuf), "%d", p);
|
||||
ADDS(nbuf);
|
||||
} else
|
||||
ADDNA();
|
||||
break;
|
||||
case 'f':
|
||||
(void)snprintf(nbuf, sizeof(nbuf), "%d", sa->sa_family);
|
||||
@ -143,6 +152,28 @@ sockaddr_snprintf(char *buf, size_t len, const char *fmt,
|
||||
(void)snprintf(nbuf, sizeof(nbuf), "%d", sa->sa_len);
|
||||
ADDS(nbuf);
|
||||
break;
|
||||
case 'A':
|
||||
if (name)
|
||||
ADDS(name);
|
||||
else if (!a)
|
||||
ADDNA();
|
||||
else {
|
||||
getnameinfo(sa, (socklen_t)sa->sa_len,
|
||||
name = Abuf, sizeof(nbuf), NULL, 0, 0);
|
||||
ADDS(name);
|
||||
}
|
||||
break;
|
||||
case 'P':
|
||||
if (port)
|
||||
ADDS(port);
|
||||
else if (p == -1)
|
||||
ADDNA();
|
||||
else {
|
||||
getnameinfo(sa, (socklen_t)sa->sa_len, NULL, 0,
|
||||
port = pbuf, sizeof(pbuf), 0);
|
||||
ADDS(port);
|
||||
}
|
||||
break;
|
||||
case 'I':
|
||||
if (sdl && addr != abuf) {
|
||||
ADDS(abuf);
|
||||
@ -184,9 +215,14 @@ sockaddr_snprintf(char *buf, size_t len, const char *fmt,
|
||||
break;
|
||||
default:
|
||||
ADDC('%');
|
||||
if (na == 0)
|
||||
ADDC('?');
|
||||
if (*ptr == '\0')
|
||||
goto done;
|
||||
ADDC(*ptr);
|
||||
break;
|
||||
}
|
||||
na = 1;
|
||||
}
|
||||
done:
|
||||
ADDN();
|
||||
|
Loading…
Reference in New Issue
Block a user