DNS compression support.

be more picky about DNS label validation.
(sync with kame)
This commit is contained in:
itojun 2000-08-09 14:36:00 +00:00
parent f714bfb0d8
commit 1b2be13d48
2 changed files with 499 additions and 244 deletions

View File

@ -1,5 +1,5 @@
.\" $NetBSD: ping6.8,v 1.8 2000/06/12 16:21:04 itojun Exp $
.\" $KAME: ping6.8,v 1.23 2000/06/12 16:16:09 itojun Exp $
.\" $NetBSD: ping6.8,v 1.9 2000/08/09 14:36:00 itojun Exp $
.\" $KAME: ping6.8,v 1.26 2000/08/03 15:26:34 jinmei Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
@ -39,9 +39,9 @@ packets to network hosts
.Sh SYNOPSIS
.Nm ping6
.\" without ipsec, or new ipsec
.Op Fl dfHnNqRvw
.Op Fl dfHnNqRtvw
.\" old ipsec
.\" .Op Fl AdEfnNqRvw
.\" .Op Fl AdEfnNqRtvw
.Bk -words
.Op Fl a Ar addrtype
.Ek
@ -258,6 +258,13 @@ header data.
You may need to specify
.Fl b
as well to extend socket buffer size.
.It Fl t
Generate ICMPv6 Node Information supported query types query,
rather than echo-request.
.Fl s
has no effect if
.Fl t
is specified.
.It Fl v
Verbose output.
.Tn ICMP
@ -265,7 +272,7 @@ packets other than
.Tn ECHO_RESPONSE
that are received are listed.
.It Fl w
Generate ICMPv6 Node Information FQDN query, rather than echo-request.
Generate ICMPv6 Node Information DNS Name query, rather than echo-request.
.Fl s
has no effect if
.Fl w
@ -402,8 +409,8 @@ and non-zero if the arguments are incorrect or the host is not responding.
.Rs
.%A Matt Crawford
.%T "IPv6 Node Information Queries"
.%N draft-ietf-ipngwg-icmp-name-lookups-05.txt
.%D October 22, 1999
.%N draft-ietf-ipngwg-icmp-name-lookups-06.txt
.%D July 2000
.%O work in progress material
.Re
.Sh HISTORY

View File

@ -1,5 +1,5 @@
/* $NetBSD: ping6.c,v 1.16 2000/07/07 12:29:10 itojun Exp $ */
/* $KAME: ping6.c,v 1.56 2000/07/07 12:17:15 itojun Exp $ */
/* $NetBSD: ping6.c,v 1.17 2000/08/09 14:36:01 itojun Exp $ */
/* $KAME: ping6.c,v 1.66 2000/08/09 14:34:15 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -81,7 +81,7 @@ static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93";
#else
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: ping6.c,v 1.16 2000/07/07 12:29:10 itojun Exp $");
__RCSID("$NetBSD: ping6.c,v 1.17 2000/08/09 14:36:01 itojun Exp $");
#endif
#endif
@ -123,6 +123,7 @@ __RCSID("$NetBSD: ping6.c,v 1.16 2000/07/07 12:29:10 itojun Exp $");
#include <netinet/ip6.h>
#include <netinet/icmp6.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <netdb.h>
#include <ctype.h>
@ -147,7 +148,8 @@ __RCSID("$NetBSD: ping6.c,v 1.16 2000/07/07 12:29:10 itojun Exp $");
#define ICMP6ECHOLEN 8 /* icmp echo header len excluding time */
#define ICMP6ECHOTMLEN sizeof(struct timeval)
#define ICMP6_NIQLEN (ICMP6ECHOLEN + 8)
#define ICMP6_NIRLEN (ICMP6ECHOLEN + 12) /* 64 bits of nonce + 32 bits ttl */
/* FQDN case, 64 bits of nonce + 32 bits ttl */
#define ICMP6_NIRLEN (ICMP6ECHOLEN + 12)
#define EXTRA 256 /* for AH and various other headers. weird. */
#define DEFDATALEN ICMP6ECHOTMLEN
#define MAXDATALEN MAXPACKETLEN - IP6LEN - ICMP6ECHOLEN
@ -185,6 +187,8 @@ __RCSID("$NetBSD: ping6.c,v 1.16 2000/07/07 12:29:10 itojun Exp $");
#define F_HOSTNAME 0x10000
#define F_FQDNOLD 0x20000
#define F_NIGROUP 0x40000
#define F_SUPTYPES 0x80000
#define F_NOUSERDATA (F_NODEADDR | F_FQDN | F_FQDNOLD | F_SUPTYPES)
u_int options;
#define IN6LEN sizeof(struct in6_addr)
@ -212,6 +216,7 @@ char BSPACE = '\b'; /* characters written for flood */
char DOT = '.';
char *hostname;
int ident; /* process id to identify our packets */
u_int8_t nonce[8]; /* nonce field for node information */
struct in6_addr srcaddr;
/* counters */
@ -248,6 +253,10 @@ const char *pr_addr __P((struct sockaddr_in6 *));
void pr_icmph __P((struct icmp6_hdr *, u_char *));
void pr_iph __P((struct ip6_hdr *));
void pr_nodeaddr __P((struct icmp6_nodeinfo *, int));
int myechoreply __P((const struct icmp6_hdr *));
int mynireply __P((const struct icmp6_nodeinfo *));
char *dnsdecode __P((const u_char **, const u_char *, const u_char *,
u_char *, size_t));
void pr_pack __P((u_char *, int, struct msghdr *));
void pr_exthdrs __P((struct msghdr *));
void pr_ip6opt __P((void *));
@ -281,6 +290,7 @@ main(argc, argv)
#ifdef USE_RFC2292BIS
struct ip6_rthdr *rthdr = NULL;
#endif
struct timeval tv;
#ifdef IPSEC_POLICY_IPSEC
char *policy_in = NULL;
char *policy_out = NULL;
@ -293,24 +303,24 @@ main(argc, argv)
preload = 0;
datap = &outpack[ICMP6ECHOLEN + ICMP6ECHOTMLEN];
#ifndef IPSEC
while ((ch = getopt(argc, argv, "a:b:c:dfHh:I:i:l:nNp:qRS:s:vwW")) != EOF)
while ((ch = getopt(argc, argv, "a:b:c:dfHh:I:i:l:nNp:qRS:s:tvwW")) != EOF)
#else
#ifdef IPSEC_POLICY_IPSEC
while ((ch = getopt(argc, argv, "a:b:c:dfHh:I:i:l:nNp:qRS:s:vwWP:")) != EOF)
while ((ch = getopt(argc, argv, "a:b:c:dfHh:I:i:l:nNp:qRS:s:tvwWP:")) != EOF)
#else
while ((ch = getopt(argc, argv, "a:b:c:dfHh:I:i:l:nNp:qRS:s:vwWAE")) != EOF)
while ((ch = getopt(argc, argv, "a:b:c:dfHh:I:i:l:nNp:qRS:s:tvwWAE")) != EOF)
#endif /*IPSEC_POLICY_IPSEC*/
#endif
{
switch(ch) {
switch (ch) {
case 'a':
{
char *cp;
options &= ~F_NOUSERDATA;
options |= F_NODEADDR;
datalen = 2048; /* XXX: enough? */
for (cp = optarg; *cp != '\0'; cp++) {
switch(*cp) {
switch (*cp) {
case 'a':
naflags |= NI_NODEADDR_FLAG_ALL;
break;
@ -428,18 +438,25 @@ main(argc, argv)
datalen = strtol(optarg, &e, 10);
if (datalen <= 0 || *optarg == '\0' || *e != '\0')
errx(1, "illegal datalen value -- %s", optarg);
if (datalen > MAXDATALEN)
if (datalen > MAXDATALEN) {
errx(1,
"datalen value too large, maximum is %d",
MAXDATALEN);
}
break;
case 't':
options &= ~F_NOUSERDATA;
options |= F_SUPTYPES;
break;
case 'v':
options |= F_VERBOSE;
break;
case 'w':
options &= ~F_NOUSERDATA;
options |= F_FQDN;
break;
case 'W':
options &= ~F_NOUSERDATA;
options |= F_FQDNOLD;
break;
#ifdef IPSEC
@ -476,9 +493,10 @@ main(argc, argv)
}
if (argc > 1) {
#ifdef USE_SIN6_SCOPE_ID
ip6optlen += CMSG_SPACE(inet6_rth_space(IPV6_RTHDR_TYPE_0, argc - 1));
#else /* old advanced API */
#ifdef IPV6_RECVRTHDR /* 2292bis */
ip6optlen += CMSG_SPACE(inet6_rth_space(IPV6_RTHDR_TYPE_0,
argc - 1));
#else /* RFC2292 */
ip6optlen += inet6_rthdr_space(IPV6_RTHDR_TYPE_0, argc - 1);
#endif
}
@ -518,16 +536,28 @@ main(argc, argv)
if (options & F_FLOOD && options & F_INTERVAL)
errx(1, "-f and -i incompatible options");
if (datalen >= sizeof(struct timeval)) /* can we time transfer */
if ((options & F_NOUSERDATA) == 0 &&
datalen >= sizeof(struct timeval)) {
/* can we time transfer */
timing = 1;
} else {
/* suppress timing for node information query */
timing = 0;
datalen = 2048;
}
packlen = datalen + IP6LEN + ICMP6ECHOLEN + EXTRA;
if (!(packet = (u_char *)malloc((u_int)packlen)))
err(1, "Unable to allocate packet");
if (!(options & F_PINGFILLED))
for (i = 8; i < datalen; ++i)
for (i = ICMP6ECHOLEN; i < packlen; ++i)
*datap++ = i;
ident = getpid() & 0xFFFF;
gettimeofday(&tv, NULL);
srand((unsigned int)(tv.tv_sec ^ tv.tv_usec ^ (long)ident));
memset(nonce, 0, sizeof(nonce));
for (i = 0; i < sizeof(nonce); i += sizeof(int))
*((int *)&nonce[i]) = rand();
if ((s = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
err(1, "socket");
@ -579,7 +609,7 @@ main(argc, argv)
if (!(options & F_VERBOSE)) {
ICMP6_FILTER_SETBLOCKALL(&filt);
if ((options & F_FQDN) || (options & F_FQDNOLD) ||
(options & F_NODEADDR))
(options & F_NODEADDR) || (options & F_SUPTYPES))
ICMP6_FILTER_SETPASS(ICMP6_NI_REPLY, &filt);
else
ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filt);
@ -963,26 +993,25 @@ pinger()
struct icmp6_hdr *icp;
struct iovec iov[2];
int i, cc;
struct icmp6_nodeinfo *nip;
int seq;
icp = (struct icmp6_hdr *)outpack;
nip = (struct icmp6_nodeinfo *)outpack;
memset(icp, 0, sizeof(*icp));
icp->icmp6_code = 0;
icp->icmp6_cksum = 0;
icp->icmp6_seq = ntransmitted++; /* htons later */
icp->icmp6_id = htons(ident); /* ID */
CLR(icp->icmp6_seq % mx_dup_ck);
icp->icmp6_seq = htons(icp->icmp6_seq);
seq = ntransmitted++;
CLR(seq % mx_dup_ck);
if (options & F_FQDN) {
icp->icmp6_type = ICMP6_NI_QUERY;
icp->icmp6_code = ICMP6_NI_SUBJ_IPV6;
/* XXX: overwrite icmp6_id */
((struct icmp6_nodeinfo *)icp)->ni_qtype = htons(NI_QTYPE_FQDN);
((struct icmp6_nodeinfo *)icp)->ni_flags = htons(0);
if (timing)
(void)gettimeofday((struct timeval *)
&outpack[ICMP6ECHOLEN], NULL);
nip->ni_qtype = htons(NI_QTYPE_FQDN);
nip->ni_flags = htons(0);
memcpy(nip->icmp6_ni_nonce, nonce, sizeof(nip->icmp6_ni_nonce));
*(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq);
memcpy(&outpack[ICMP6_NIQLEN], &dst.sin6_addr,
sizeof(dst.sin6_addr));
cc = ICMP6_NIQLEN + sizeof(dst.sin6_addr);
@ -990,33 +1019,43 @@ pinger()
} else if (options & F_FQDNOLD) {
/* packet format in 03 draft - no Subject data on queries */
icp->icmp6_type = ICMP6_NI_QUERY;
/* code field is always 0 */
/* XXX: overwrite icmp6_id */
((struct icmp6_nodeinfo *)icp)->ni_qtype = htons(NI_QTYPE_FQDN);
((struct icmp6_nodeinfo *)icp)->ni_flags = htons(0);
if (timing)
(void)gettimeofday((struct timeval *)
&outpack[ICMP6ECHOLEN], NULL);
icp->icmp6_code = 0; /* code field is always 0 */
nip->ni_qtype = htons(NI_QTYPE_FQDN);
nip->ni_flags = htons(0);
memcpy(nip->icmp6_ni_nonce, nonce, sizeof(nip->icmp6_ni_nonce));
*(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq);
cc = ICMP6_NIQLEN;
datalen = 0;
} else if (options & F_NODEADDR) {
icp->icmp6_type = ICMP6_NI_QUERY;
icp->icmp6_code = ICMP6_NI_SUBJ_IPV6;
/* XXX: overwrite icmp6_id */
((struct icmp6_nodeinfo *)icp)->ni_qtype =
htons(NI_QTYPE_NODEADDR);
((struct icmp6_nodeinfo *)icp)->ni_flags = htons(0);
if (timing)
(void)gettimeofday((struct timeval *)
&outpack[ICMP6ECHOLEN], NULL);
nip->ni_qtype = htons(NI_QTYPE_NODEADDR);
nip->ni_flags = naflags;
memcpy(nip->icmp6_ni_nonce, nonce, sizeof(nip->icmp6_ni_nonce));
*(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq);
memcpy(&outpack[ICMP6_NIQLEN], &dst.sin6_addr,
sizeof(dst.sin6_addr));
cc = ICMP6_NIQLEN + sizeof(dst.sin6_addr);
datalen = 0;
((struct icmp6_nodeinfo *)icp)->ni_flags = naflags;
}
else {
} else if (options & F_SUPTYPES) {
icp->icmp6_type = ICMP6_NI_QUERY;
icp->icmp6_code = ICMP6_NI_SUBJ_FQDN; /*empty*/
nip->ni_qtype = htons(NI_QTYPE_SUPTYPES);
nip->ni_flags = 0; /* do not support compressed bitmap */
memcpy(nip->icmp6_ni_nonce, nonce, sizeof(nip->icmp6_ni_nonce));
*(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq);
cc = ICMP6_NIQLEN;
datalen = 0;
} else {
icp->icmp6_type = ICMP6_ECHO_REQUEST;
icp->icmp6_code = 0;
icp->icmp6_id = htons(ident);
icp->icmp6_seq = ntohs(seq);
if (timing)
(void)gettimeofday((struct timeval *)
&outpack[ICMP6ECHOLEN], NULL);
@ -1043,6 +1082,98 @@ pinger()
(void)write(STDOUT_FILENO, &DOT, 1);
}
int
myechoreply(icp)
const struct icmp6_hdr *icp;
{
if (ntohs(icp->icmp6_id) == ident)
return 1;
else
return 0;
}
int
mynireply(nip)
const struct icmp6_nodeinfo *nip;
{
if (memcmp(nip->icmp6_ni_nonce + sizeof(u_int16_t),
nonce + sizeof(u_int16_t),
sizeof(nonce) - sizeof(u_int16_t)) == 0)
return 1;
else
return 0;
}
char *
dnsdecode(sp, ep, base, buf, bufsiz)
const u_char **sp;
const u_char *ep;
const u_char *base; /*base for compressed name*/
u_char *buf;
size_t bufsiz;
{
int i, l;
const u_char *cp;
char *q;
const char *eq;
char cresult[MAXDNAME + 1];
const u_char *comp;
cp = *sp;
q = buf;
eq = buf + bufsiz;
if (cp >= ep)
return NULL;
while (cp < ep) {
i = *cp;
if (i == 0 || cp != *sp) {
if (q >= eq - 1)
return NULL; /*result overrun*/
*q++ = '.';
}
if (i == 0)
break;
cp++;
if ((i & 0xc0) == 0xc0 && cp - base > (i & 0x3f)) {
/* DNS compression */
if (!base)
return NULL;
comp = base + (i & 0x3f);
if (dnsdecode(&comp, cp, base, cresult,
sizeof(cresult)) == NULL)
return NULL;
if (eq - q < strlen(cresult) + 1)
return NULL; /*result overrun*/
strcpy(q, cresult); /*XXX should be strlcpy*/
q += strlen(q);
break;
} else if ((i & 0x3f) == i) {
if (i > ep - cp)
return NULL; /*source overrun*/
while (i-- > 0 && cp < ep) {
if (eq - q < (isprint(*cp) ? 2 : 5))
return NULL; /*result overrun*/
l = snprintf(q, eq - q,
isprint(*cp) ? "%c" : "\\%03o", *cp & 0xff);
cp++;
q += l;
}
} else
return NULL; /*invalid label*/
}
if (q >= eq)
return NULL; /*result overrun*/
if (i != 0)
return NULL; /*not terminated*/
cp++;
*q = '\0';
*sp = cp;
return buf;
}
/*
* pr_pack --
* Print out the packet, if it came from us. This logic is necessary
@ -1058,6 +1189,7 @@ pr_pack(buf, cc, mhdr)
{
#define safeputc(c) printf((isprint((c)) ? "%c" : "\\%03o"), c)
struct icmp6_hdr *icp;
struct icmp6_nodeinfo *ni;
int i;
int hoplim;
struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
@ -1068,6 +1200,8 @@ pr_pack(buf, cc, mhdr)
int dupflag;
size_t off;
int oldfqdn;
u_int16_t seq;
char dnsname[MAXDNAME + 1];
(void)gettimeofday(&tv, NULL);
@ -1078,6 +1212,7 @@ pr_pack(buf, cc, mhdr)
return;
}
icp = (struct icmp6_hdr *)buf;
ni = (struct icmp6_nodeinfo *)buf;
off = 0;
if ((hoplim = get_hoplim(mhdr)) == -1) {
@ -1089,11 +1224,8 @@ pr_pack(buf, cc, mhdr)
return;
}
if (icp->icmp6_type == ICMP6_ECHO_REPLY) {
/* XXX the following line overwrites the original packet */
icp->icmp6_seq = ntohs(icp->icmp6_seq);
if (ntohs(icp->icmp6_id) != ident)
return; /* It was not our ECHO */
if (icp->icmp6_type == ICMP6_ECHO_REPLY && myechoreply(icp)) {
seq = ntohs(icp->icmp6_seq);
++nreceived;
if (timing) {
tp = (struct timeval *)(icp + 1);
@ -1107,12 +1239,12 @@ pr_pack(buf, cc, mhdr)
tmax = triptime;
}
if (TST(icp->icmp6_seq % mx_dup_ck)) {
if (TST(seq % mx_dup_ck)) {
++nrepeats;
--nreceived;
dupflag = 1;
} else {
SET(icp->icmp6_seq % mx_dup_ck);
SET(seq % mx_dup_ck);
dupflag = 0;
}
@ -1123,8 +1255,7 @@ pr_pack(buf, cc, mhdr)
(void)write(STDOUT_FILENO, &BSPACE, 1);
else {
(void)printf("%d bytes from %s, icmp_seq=%u", cc,
pr_addr(from),
icp->icmp6_seq);
pr_addr(from), seq);
(void)printf(" hlim=%d", hoplim);
if ((options & F_VERBOSE) != 0) {
struct sockaddr_in6 dstsa;
@ -1150,18 +1281,54 @@ pr_pack(buf, cc, mhdr)
}
}
}
} else if (icp->icmp6_type == ICMP6_NI_REPLY) { /* ICMP6_NI_REPLY */
struct icmp6_nodeinfo *ni = (struct icmp6_nodeinfo *)(buf + off);
} else if (icp->icmp6_type == ICMP6_NI_REPLY && mynireply(ni)) {
seq = ntohs(*(u_int16_t *)ni->icmp6_ni_nonce);
++nreceived;
if (TST(seq % mx_dup_ck)) {
++nrepeats;
--nreceived;
dupflag = 1;
} else {
SET(seq % mx_dup_ck);
dupflag = 0;
}
(void)printf("%d bytes from %s: ", cc,
pr_addr(from));
if (options & F_QUIET)
return;
switch(ntohs(ni->ni_qtype)) {
(void)printf("%d bytes from %s: ", cc, pr_addr(from));
switch (ntohs(ni->ni_code)) {
case ICMP6_NI_SUCCESS:
break;
case ICMP6_NI_REFUSED:
printf("refused, type 0x%x", ntohs(ni->ni_type));
goto fqdnend;
case ICMP6_NI_UNKNOWN:
printf("unknown, type 0x%x", ntohs(ni->ni_type));
goto fqdnend;
default:
printf("unknown code 0x%x, type 0x%x",
ntohs(ni->ni_code), ntohs(ni->ni_type));
goto fqdnend;
}
switch (ntohs(ni->ni_qtype)) {
case NI_QTYPE_NOOP:
printf("NodeInfo NOOP");
break;
case NI_QTYPE_SUPTYPES:
printf("NodeInfo Supported Qtypes");
if ((ni->ni_flags & NI_SUPTYPE_FLAG_COMPRESS) != 0) {
printf(", compressed bitmap");
break;
}
cp = (u_char *)(ni + 1);
if (cp + 4 != end) {
printf(", invalid length");
break;
}
printf(", bitmap = 0x%08x", ntohl(*(u_int32_t *)cp));
break;
case NI_QTYPE_NODEADDR:
pr_nodeaddr(ni, end - (u_char *)ni);
@ -1175,38 +1342,31 @@ pr_pack(buf, cc, mhdr)
else
oldfqdn = 0;
if (oldfqdn) {
cp++;
cp++; /* skip length */
while (cp < end) {
safeputc(*cp & 0xff);
cp++;
}
} else {
i = 0;
while (cp < end) {
i = *cp++;
if (i) {
if (i > end - cp) {
if (dnsdecode((const u_char **)&cp, end,
(const u_char *)(ni + 1), dnsname,
sizeof(dnsname)) == NULL) {
printf("???");
break;
}
while (i-- && cp < end) {
safeputc(*cp & 0xff);
/*
* name-lookup special handling for
* truncated name
*/
if (cp + 1 < end && !*cp &&
strlen(dnsname) > 0) {
dnsname[strlen(dnsname) - 1] = '\0';
cp++;
}
if (cp + 1 < end && *cp)
printf(".");
} else {
if (cp == end) {
/* FQDN */
printf(".");
} else if (cp + 1 == end &&
*cp == '\0') {
/* truncated */
} else {
/* invalid */
printf("???");
}
break;
}
printf("%s%s", i > 0 ? "," : "",
dnsname);
}
}
if (options & F_VERBOSE) {
@ -1215,7 +1375,7 @@ pr_pack(buf, cc, mhdr)
(void)printf(" ("); /*)*/
switch(ni->ni_code) {
switch (ni->ni_code) {
case ICMP6_NI_REFUSED:
(void)printf("refused");
comma++;
@ -1233,10 +1393,10 @@ pr_pack(buf, cc, mhdr)
ttl = (int32_t)ntohl(*(u_long *)&buf[off+ICMP6ECHOLEN+8]);
if (comma)
printf(",");
if (!(ni->ni_flags & NI_FQDN_FLAG_VALIDTTL))
if (!(ni->ni_flags & NI_FQDN_FLAG_VALIDTTL)) {
(void)printf("TTL=%d:meaningless",
(int)ttl);
else {
} else {
if (ttl < 0) {
(void)printf("TTL=%d:invalid",
ttl);
@ -1279,8 +1439,7 @@ pr_pack(buf, cc, mhdr)
/* We've got something other than an ECHOREPLY */
if (!(options & F_VERBOSE))
return;
(void)printf("%d bytes from %s: ", cc,
pr_addr(from));
(void)printf("%d bytes from %s: ", cc, pr_addr(from));
pr_icmph(icp, end);
}
@ -1304,7 +1463,7 @@ pr_exthdrs(mhdr)
if (cm->cmsg_level != IPPROTO_IPV6)
continue;
switch(cm->cmsg_type) {
switch (cm->cmsg_type) {
case IPV6_HOPOPTS:
printf(" HbH Options: ");
pr_ip6opt(CMSG_DATA(cm));
@ -1437,7 +1596,7 @@ pr_nodeaddr(ni, nilen)
nilen -= sizeof(struct icmp6_nodeinfo);
if (options & F_VERBOSE) {
switch(ni->ni_code) {
switch (ni->ni_code) {
case ICMP6_NI_REFUSED:
(void)printf("refused");
break;
@ -1569,21 +1728,18 @@ summary()
}
}
#ifdef notdef
static char *ttab[] = {
"Echo Reply", /* ip + seq + udata */
"Dest Unreachable", /* net, host, proto, port, frag, sr + IP */
"Source Quench", /* IP */
"Redirect", /* redirect type, gateway, + IP */
"Echo",
"Time Exceeded", /* transit, frag reassem + IP */
"Parameter Problem", /* pointer + IP */
"Timestamp", /* id + seq + three timestamps */
"Timestamp Reply", /* " */
"Info Request", /* id + sq */
"Info Reply" /* " */
/*subject type*/
static char *niqcode[] = {
"IPv6 address",
"DNS label", /*or empty*/
"IPv4 address",
};
#endif
/*result code*/
static char *nircode[] = {
"Success", "Refused", "Unknown",
};
/*
* pr_icmph --
@ -1595,10 +1751,15 @@ pr_icmph(icp, end)
u_char *end;
{
char ntop_buf[INET6_ADDRSTRLEN];
struct nd_redirect *red;
struct icmp6_nodeinfo *ni;
char dnsname[MAXDNAME + 1];
const u_char *cp;
size_t l;
switch(icp->icmp6_type) {
switch (icp->icmp6_type) {
case ICMP6_DST_UNREACH:
switch(icp->icmp6_code) {
switch (icp->icmp6_code) {
case ICMP6_DST_UNREACH_NOROUTE:
(void)printf("No Route to Destination\n");
break;
@ -1629,7 +1790,7 @@ pr_icmph(icp, end)
pr_retip((struct ip6_hdr *)(icp + 1), end);
break;
case ICMP6_TIME_EXCEEDED:
switch(icp->icmp6_code) {
switch (icp->icmp6_code) {
case ICMP6_TIME_EXCEED_TRANSIT:
(void)printf("Time to live exceeded\n");
break;
@ -1645,7 +1806,7 @@ pr_icmph(icp, end)
break;
case ICMP6_PARAM_PROB:
(void)printf("Parameter problem: ");
switch(icp->icmp6_code) {
switch (icp->icmp6_code) {
case ICMP6_PARAMPROB_HEADER:
(void)printf("Erroneous Header ");
break;
@ -1693,9 +1854,7 @@ pr_icmph(icp, end)
(void)printf("Neighbor Advertisement");
break;
case ND_REDIRECT:
{
struct nd_redirect *red = (struct nd_redirect *)icp;
red = (struct nd_redirect *)icp;
(void)printf("Redirect\n");
(void)printf("Destination: %s",
inet_ntop(AF_INET6, &red->nd_rd_dst,
@ -1704,14 +1863,105 @@ pr_icmph(icp, end)
inet_ntop(AF_INET6, &red->nd_rd_target,
ntop_buf, sizeof(ntop_buf)));
break;
}
case ICMP6_NI_QUERY:
(void)printf("Node Information Query");
/* XXX ID + Seq + Data */
ni = (struct icmp6_nodeinfo *)icp;
l = end - (u_char *)(ni + 1);
printf(", ");
switch (ntohs(ni->ni_qtype)) {
case NI_QTYPE_NOOP:
(void)printf("NOOP");
break;
case NI_QTYPE_SUPTYPES:
(void)printf("Supported qtypes");
break;
case NI_QTYPE_FQDN:
(void)printf("DNS name");
break;
case NI_QTYPE_NODEADDR:
(void)printf("nodeaddr");
break;
case NI_QTYPE_IPV4ADDR:
(void)printf("IPv4 nodeaddr");
break;
default:
(void)printf("unknown qtype");
break;
}
if (options & F_VERBOSE) {
switch (ni->ni_code) {
case ICMP6_NI_SUBJ_IPV6:
if (l == sizeof(struct in6_addr) &&
inet_ntop(AF_INET6, ni + 1, ntop_buf, sizeof(ntop_buf)) != NULL) {
(void)printf(", subject=%s(%s)",
niqcode[ni->ni_code], ntop_buf);
} else {
#if 1
/* backward compat to -W */
(void)printf(", oldfqdn");
#else
(void)printf(", invalid");
#endif
}
break;
case ICMP6_NI_SUBJ_FQDN:
if (end == (u_char *)(ni + 1)) {
(void)printf(", no subject");
break;
}
printf(", subject=%s", niqcode[ni->ni_code]);
cp = (const u_char *)(ni + 1);
if (dnsdecode(&cp, end, NULL, dnsname, sizeof(dnsname)) != NULL)
printf("(%s)", dnsname);
else
printf("(invalid)");
break;
case ICMP6_NI_SUBJ_IPV4:
if (l == sizeof(struct in_addr) &&
inet_ntop(AF_INET, ni + 1, ntop_buf, sizeof(ntop_buf)) != NULL) {
(void)printf(", subject=%s(%s)",
niqcode[ni->ni_code], ntop_buf);
} else
(void)printf(", invalid");
break;
default:
(void)printf(", invalid");
break;
}
}
break;
case ICMP6_NI_REPLY:
(void)printf("Node Information Reply");
/* XXX ID + Seq + Data */
ni = (struct icmp6_nodeinfo *)icp;
printf(", ");
switch (ntohs(ni->ni_qtype)) {
case NI_QTYPE_NOOP:
(void)printf("NOOP");
break;
case NI_QTYPE_SUPTYPES:
(void)printf("Supported qtypes");
break;
case NI_QTYPE_FQDN:
(void)printf("DNS name");
break;
case NI_QTYPE_NODEADDR:
(void)printf("nodeaddr");
break;
case NI_QTYPE_IPV4ADDR:
(void)printf("IPv4 nodeaddr");
break;
default:
(void)printf("unknown qtype");
break;
}
if (options & F_VERBOSE) {
if (ni->ni_code > sizeof(nircode) / sizeof(nircode[0]))
printf(", invalid");
else
printf(", %s", nircode[ni->ni_code]);
}
break;
default:
(void)printf("Bad ICMP type: %d", icp->icmp6_type);
@ -1759,14 +2009,15 @@ pr_addr(addr)
if ((options & F_HOSTNAME) == 0)
flag |= NI_NUMERICHOST;
#ifdef KAME_SCOPEID
#ifdef NI_WITHSCOPEID
flag |= NI_WITHSCOPEID;
#endif
getnameinfo((struct sockaddr *)addr, addr->sin6_len, buf, sizeof(buf),
NULL, 0, flag);
if (getnameinfo((struct sockaddr *)addr, addr->sin6_len,
buf, sizeof(buf), NULL, 0, flag) == 0)
return (buf);
else
return "?";
}
/*
@ -1820,8 +2071,7 @@ pr_retip(ip6, end)
break;
#endif
case IPPROTO_ICMPV6:
printf("ICMP6: type = %d, code = %d\n",
*cp, *(cp + 1));
printf("ICMP6: type = %d, code = %d\n", *cp, *(cp + 1));
return;
case IPPROTO_ESP:
printf("ESP\n");
@ -1937,10 +2187,8 @@ nigroup(name)
MD5Update(&ctxt, name, p - name);
MD5Final(digest, &ctxt);
bzero(&in6, sizeof(in6));
in6.s6_addr[0] = 0xff;
in6.s6_addr[1] = 0x02;
in6.s6_addr[11] = 0x02;
if (inet_pton(AF_INET6, "ff02::2:0000:0000", &in6) != 1)
return NULL; /*XXX*/
bcopy(digest, &in6.s6_addr[12], 4);
if (inet_ntop(AF_INET6, &in6, hbuf, sizeof(hbuf)) == NULL)