" NotImp", " Refused", " YXDomain", " YXRRSet",
" NXRRSet", " NotAuth", " NotZone", " Resp11",
" Resp12", " Resp13", " Resp14", " NoChange",
+ " BadVers", "Resp17", " Resp18", " Resp19",
+ " Resp20", "Resp21", " Resp22", " BadCookie",
};
+static const char *
+ns_rcode(u_int rcode) {
+ static char buf[sizeof(" Resp4095")];
+
+ if (rcode < sizeof(ns_resp)/sizeof(ns_resp[0])) {
+ return (ns_resp[rcode]);
+ }
+ snprintf(buf, sizeof(buf), " Resp%u", rcode & 0xfff);
+ return (buf);
+}
+
/* skip over a domain name */
static const u_char *
ns_nskip(netdissect_options *ndo,
if (!ND_TTEST_1(cp))
return (NULL);
- i = EXTRACT_U_1(cp);
+ i = GET_U_1(cp);
cp++;
while (i) {
if ((i & INDIR_MASK) == INDIR_MASK)
return(NULL); /* unknown ELT */
if (!ND_TTEST_1(cp))
return (NULL);
- if ((bitlen = EXTRACT_U_1(cp)) == 0)
+ if ((bitlen = GET_U_1(cp)) == 0)
bitlen = 256;
cp++;
bytelen = (bitlen + 7) / 8;
cp += i;
if (!ND_TTEST_1(cp))
return (NULL);
- i = EXTRACT_U_1(cp);
+ i = GET_U_1(cp);
cp++;
}
return (cp);
}
-/* print a <domain-name> */
static const u_char *
blabel_print(netdissect_options *ndo,
const u_char *cp)
if (!ND_TTEST_1(cp))
return(NULL);
- if ((bitlen = EXTRACT_U_1(cp)) == 0)
+ if ((bitlen = GET_U_1(cp)) == 0)
bitlen = 256;
slen = (bitlen + 3) / 4;
lim = cp + 1 + slen;
ND_PRINT("\\[x");
for (bitp = cp + 1, b = bitlen; bitp < lim && b > 7; b -= 8, bitp++) {
ND_TCHECK_1(bitp);
- ND_PRINT("%02x", EXTRACT_U_1(bitp));
+ ND_PRINT("%02x", GET_U_1(bitp));
}
if (b > 4) {
ND_TCHECK_1(bitp);
- tc = EXTRACT_U_1(bitp);
+ tc = GET_U_1(bitp);
bitp++;
ND_PRINT("%02x", tc & (0xff << (8 - b)));
} else if (b > 0) {
ND_TCHECK_1(bitp);
- tc = EXTRACT_U_1(bitp);
+ tc = GET_U_1(bitp);
bitp++;
ND_PRINT("%1x", ((tc >> 4) & 0x0f) & (0x0f << (4 - b)));
}
if (!ND_TTEST_1(cp))
return(-1);
- i = EXTRACT_U_1(cp);
+ i = GET_U_1(cp);
if ((i & INDIR_MASK) == EDNS0_MASK) {
u_int bitlen, elt;
if ((elt = (i & ~INDIR_MASK)) != EDNS0_ELT_BITLABEL) {
}
if (!ND_TTEST_1(cp + 1))
return(-1);
- if ((bitlen = EXTRACT_U_1(cp + 1)) == 0)
+ if ((bitlen = GET_U_1(cp + 1)) == 0)
bitlen = 256;
return(((bitlen + 7) / 8) + 1);
} else
return(i);
}
+/* print a <domain-name> */
const u_char *
-ns_nprint(netdissect_options *ndo,
+fqdn_print(netdissect_options *ndo,
const u_char *cp, const u_char *bp)
{
u_int i, l;
if (!ND_TTEST_1(cp))
return(NULL);
max_offset = (u_int)(cp - bp);
- i = EXTRACT_U_1(cp);
+ i = GET_U_1(cp);
cp++;
if ((i & INDIR_MASK) != INDIR_MASK) {
compress = 0;
}
if (!ND_TTEST_1(cp))
return(NULL);
- offset = (((i << 8) | EXTRACT_U_1(cp)) & 0x3fff);
+ offset = (((i << 8) | GET_U_1(cp)) & 0x3fff);
/*
* This must move backwards in the packet.
* No RFC explicitly says that, but BIND's
return(NULL);
if (!ND_TTEST_1(cp))
return(NULL);
- i = EXTRACT_U_1(cp);
+ i = GET_U_1(cp);
cp++;
continue;
}
return(NULL);
}
} else {
- if (fn_printn(ndo, cp, l, ndo->ndo_snapend))
+ if (nd_printn(ndo, cp, l, ndo->ndo_snapend))
return(NULL);
}
return(NULL);
if (!ND_TTEST_1(cp))
return(NULL);
- i = EXTRACT_U_1(cp);
+ i = GET_U_1(cp);
cp++;
if (!compress)
rp += l + 1;
if (!ND_TTEST_1(cp))
return (NULL);
- i = EXTRACT_U_1(cp);
+ i = GET_U_1(cp);
cp++;
- if (fn_printn(ndo, cp, i, ndo->ndo_snapend))
+ if (nd_printn(ndo, cp, i, ndo->ndo_snapend))
return (NULL);
return (cp + i);
}
{ T_MAILB, "MAILB" }, /* RFC 1035 */
{ T_MAILA, "MAILA" }, /* RFC 1035 */
{ T_ANY, "ANY" },
+ { T_URI, "URI" }, /* RFC 7553 */
{ 0, NULL }
};
return(NULL);
/* print the qtype */
- i = EXTRACT_BE_U_2(cp);
+ i = GET_BE_U_2(cp);
cp += 2;
ND_PRINT(" %s", tok2str(ns_type2str, "Type%u", i));
/* print the qclass (if it's not IN) */
- i = EXTRACT_BE_U_2(cp);
+ i = GET_BE_U_2(cp);
cp += 2;
if (is_mdns)
class = (i & ~C_QU);
}
ND_PRINT("? ");
- cp = ns_nprint(ndo, np, bp);
+ cp = fqdn_print(ndo, np, bp);
return(cp ? cp + 4 : NULL);
}
if (ndo->ndo_vflag) {
ND_PRINT(" ");
- if ((cp = ns_nprint(ndo, cp, bp)) == NULL)
+ if ((cp = fqdn_print(ndo, cp, bp)) == NULL)
return NULL;
} else
cp = ns_nskip(ndo, cp);
return (ndo->ndo_snapend);
/* print the type/qtype */
- typ = EXTRACT_BE_U_2(cp);
+ typ = GET_BE_U_2(cp);
cp += 2;
/* print the class (if it's not IN and the type isn't OPT) */
- i = EXTRACT_BE_U_2(cp);
+ i = GET_BE_U_2(cp);
cp += 2;
if (is_mdns)
class = (i & ~C_CACHE_FLUSH);
if (typ == T_OPT) {
/* get opt flags */
cp += 2;
- opt_flags = EXTRACT_BE_U_2(cp);
+ opt_flags = GET_BE_U_2(cp);
/* ignore rest of ttl field */
cp += 2;
} else if (ndo->ndo_vflag > 2) {
/* print ttl */
ND_PRINT(" [");
- unsigned_relts_print(ndo, EXTRACT_BE_U_4(cp));
+ unsigned_relts_print(ndo, GET_BE_U_4(cp));
ND_PRINT("]");
cp += 4;
} else {
cp += 4;
}
- len = EXTRACT_BE_U_2(cp);
+ len = GET_BE_U_2(cp);
cp += 2;
rp = cp + len;
switch (typ) {
case T_A:
- if (!ND_TTEST_LEN(cp, sizeof(struct in_addr)))
+ if (!ND_TTEST_LEN(cp, sizeof(nd_ipv4)))
return(NULL);
- ND_PRINT(" %s", intoa(EXTRACT_IPV4_TO_NETWORK_ORDER(cp)));
+ ND_PRINT(" %s", intoa(GET_IPV4_TO_NETWORK_ORDER(cp)));
break;
case T_NS:
case T_DNAME:
#endif
ND_PRINT(" ");
- if (ns_nprint(ndo, cp, bp) == NULL)
+ if (fqdn_print(ndo, cp, bp) == NULL)
return(NULL);
break;
if (!ndo->ndo_vflag)
break;
ND_PRINT(" ");
- if ((cp = ns_nprint(ndo, cp, bp)) == NULL)
+ if ((cp = fqdn_print(ndo, cp, bp)) == NULL)
return(NULL);
ND_PRINT(" ");
- if ((cp = ns_nprint(ndo, cp, bp)) == NULL)
+ if ((cp = fqdn_print(ndo, cp, bp)) == NULL)
return(NULL);
if (!ND_TTEST_LEN(cp, 5 * 4))
return(NULL);
- ND_PRINT(" %u", EXTRACT_BE_U_4(cp));
+ ND_PRINT(" %u", GET_BE_U_4(cp));
cp += 4;
- ND_PRINT(" %u", EXTRACT_BE_U_4(cp));
+ ND_PRINT(" %u", GET_BE_U_4(cp));
cp += 4;
- ND_PRINT(" %u", EXTRACT_BE_U_4(cp));
+ ND_PRINT(" %u", GET_BE_U_4(cp));
cp += 4;
- ND_PRINT(" %u", EXTRACT_BE_U_4(cp));
+ ND_PRINT(" %u", GET_BE_U_4(cp));
cp += 4;
- ND_PRINT(" %u", EXTRACT_BE_U_4(cp));
+ ND_PRINT(" %u", GET_BE_U_4(cp));
cp += 4;
break;
case T_MX:
ND_PRINT(" ");
if (!ND_TTEST_2(cp))
return(NULL);
- if (ns_nprint(ndo, cp + 2, bp) == NULL)
+ if (fqdn_print(ndo, cp + 2, bp) == NULL)
return(NULL);
- ND_PRINT(" %u", EXTRACT_BE_U_2(cp));
+ ND_PRINT(" %u", GET_BE_U_2(cp));
break;
case T_TXT:
ND_PRINT(" ");
if (!ND_TTEST_6(cp))
return(NULL);
- if (ns_nprint(ndo, cp + 6, bp) == NULL)
+ if (fqdn_print(ndo, cp + 6, bp) == NULL)
return(NULL);
- ND_PRINT(":%u %u %u", EXTRACT_BE_U_2(cp + 4),
- EXTRACT_BE_U_2(cp), EXTRACT_BE_U_2(cp + 2));
+ ND_PRINT(":%u %u %u", GET_BE_U_2(cp + 4),
+ GET_BE_U_2(cp), GET_BE_U_2(cp + 2));
break;
case T_AAAA:
{
char ntop_buf[INET6_ADDRSTRLEN];
- if (!ND_TTEST_LEN(cp, sizeof(struct in6_addr)))
+ if (!ND_TTEST_LEN(cp, sizeof(nd_ipv6)))
return(NULL);
ND_PRINT(" %s",
addrtostr6(cp, ntop_buf, sizeof(ntop_buf)));
case T_A6:
{
- struct in6_addr a;
+ nd_ipv6 a;
int pbit, pbyte;
char ntop_buf[INET6_ADDRSTRLEN];
if (!ND_TTEST_1(cp))
return(NULL);
- pbit = EXTRACT_U_1(cp);
+ pbit = GET_U_1(cp);
pbyte = (pbit & ~7) / 8;
if (pbit > 128) {
ND_PRINT(" %u(bad plen)", pbit);
} else if (pbit < 128) {
if (!ND_TTEST_LEN(cp + 1, sizeof(a) - pbyte))
return(NULL);
- memset(&a, 0, sizeof(a));
- memcpy(&a.s6_addr[pbyte], cp + 1, sizeof(a) - pbyte);
+ memset(a, 0, sizeof(a));
+ memcpy(a + pbyte, cp + 1, sizeof(a) - pbyte);
ND_PRINT(" %u %s", pbit,
addrtostr6(&a, ntop_buf, sizeof(ntop_buf)));
}
if (pbit > 0) {
ND_PRINT(" ");
- if (ns_nprint(ndo, cp + 1 + sizeof(a) - pbyte, bp) == NULL)
+ if (fqdn_print(ndo, cp + 1 + sizeof(a) - pbyte, bp) == NULL)
return(NULL);
}
break;
}
+ case T_URI:
+ if (!ND_TTEST_LEN(cp, len))
+ return(NULL);
+ ND_PRINT(" %u %u ", GET_BE_U_2(cp), GET_BE_U_2(cp + 2));
+ if (nd_printn(ndo, cp + 4, len - 4, ndo->ndo_snapend))
+ return(NULL);
+ break;
+
case T_OPT:
ND_PRINT(" UDPsize=%u", class);
if (opt_flags & 0x8000)
case T_UNSPECA: /* One long string */
if (!ND_TTEST_LEN(cp, len))
return(NULL);
- if (fn_printn(ndo, cp, len, ndo->ndo_snapend))
+ if (nd_printn(ndo, cp, len, ndo->ndo_snapend))
return(NULL);
break;
if (!ndo->ndo_vflag)
break;
ND_PRINT(" ");
- if ((cp = ns_nprint(ndo, cp, bp)) == NULL)
+ if ((cp = fqdn_print(ndo, cp, bp)) == NULL)
return(NULL);
cp += 6;
if (!ND_TTEST_2(cp))
return(NULL);
- ND_PRINT(" fudge=%u", EXTRACT_BE_U_2(cp));
+ ND_PRINT(" fudge=%u", GET_BE_U_2(cp));
cp += 2;
if (!ND_TTEST_2(cp))
return(NULL);
- ND_PRINT(" maclen=%u", EXTRACT_BE_U_2(cp));
- cp += 2 + EXTRACT_BE_U_2(cp);
+ ND_PRINT(" maclen=%u", GET_BE_U_2(cp));
+ cp += 2 + GET_BE_U_2(cp);
if (!ND_TTEST_2(cp))
return(NULL);
- ND_PRINT(" origid=%u", EXTRACT_BE_U_2(cp));
+ ND_PRINT(" origid=%u", GET_BE_U_2(cp));
cp += 2;
if (!ND_TTEST_2(cp))
return(NULL);
- ND_PRINT(" error=%u", EXTRACT_BE_U_2(cp));
+ ND_PRINT(" error=%u", GET_BE_U_2(cp));
cp += 2;
if (!ND_TTEST_2(cp))
return(NULL);
- ND_PRINT(" otherlen=%u", EXTRACT_BE_U_2(cp));
+ ND_PRINT(" otherlen=%u", GET_BE_U_2(cp));
cp += 2;
}
}
const u_char *bp, u_int length, int is_mdns)
{
const dns_header_t *np;
- uint16_t flags;
+ uint16_t flags, rcode, rdlen, type;
u_int qdcount, ancount, nscount, arcount;
u_int i;
const u_char *cp;
uint16_t b2;
+ ndo->ndo_protocol = "domain";
np = (const dns_header_t *)bp;
+
+ if(length < sizeof(*np)) {
+ nd_print_protocol(ndo);
+ ND_PRINT(" [length %u < %zu]", length, sizeof(*np));
+ nd_print_invalid(ndo);
+ return;
+ }
+
ND_TCHECK_SIZE(np);
- flags = EXTRACT_BE_U_2(np->flags);
+ flags = GET_BE_U_2(np->flags);
/* get the byte-order right */
- qdcount = EXTRACT_BE_U_2(np->qdcount);
- ancount = EXTRACT_BE_U_2(np->ancount);
- nscount = EXTRACT_BE_U_2(np->nscount);
- arcount = EXTRACT_BE_U_2(np->arcount);
+ qdcount = GET_BE_U_2(np->qdcount);
+ ancount = GET_BE_U_2(np->ancount);
+ nscount = GET_BE_U_2(np->nscount);
+ arcount = GET_BE_U_2(np->arcount);
+
+ /* find the opt record to extract extended rcode */
+ cp = (const u_char *)(np + 1);
+ rcode = DNS_RCODE(flags);
+ for (i = 0; i < qdcount; i++) {
+ if ((cp = ns_nskip(ndo, cp)) == NULL)
+ goto print;
+ cp += 4; /* skip QTYPE and QCLASS */
+ if (cp >= ndo->ndo_snapend)
+ goto print;
+ }
+ for (i = 0; i < ancount + nscount; i++) {
+ if ((cp = ns_nskip(ndo, cp)) == NULL)
+ goto print;
+ cp += 8; /* skip TYPE, CLASS and TTL */
+ if (cp + 2 > ndo->ndo_snapend)
+ goto print;
+ rdlen = GET_BE_U_2(cp);
+ cp += 2 + rdlen;
+ if (cp >= ndo->ndo_snapend)
+ goto print;
+ }
+ for (i = 0; i < arcount; i++) {
+ if ((cp = ns_nskip(ndo, cp)) == NULL)
+ goto print;
+ if (cp + 2 > ndo->ndo_snapend)
+ goto print;
+ type = GET_BE_U_2(cp);
+ cp += 4; /* skip TYPE and CLASS */
+ if (cp + 1 > ndo->ndo_snapend)
+ goto print;
+ if (type == T_OPT) {
+ rcode |= (*cp << 4);
+ goto print;
+ }
+ cp += 4;
+ if (cp + 2 > ndo->ndo_snapend)
+ goto print;
+ rdlen = GET_BE_U_2(cp);
+ cp += 2 + rdlen;
+ if (cp >= ndo->ndo_snapend)
+ goto print;
+ }
+ print:
if (DNS_QR(flags)) {
/* this is a response */
ND_PRINT("%u%s%s%s%s%s%s",
- EXTRACT_BE_U_2(np->id),
+ GET_BE_U_2(np->id),
ns_ops[DNS_OPCODE(flags)],
- ns_resp[DNS_RCODE(flags)],
+ ns_rcode(rcode),
DNS_AA(flags)? "*" : "",
DNS_RA(flags)? "" : "-",
DNS_TC(flags)? "|" : "",
}
else {
/* this is a request */
- ND_PRINT("%u%s%s%s", EXTRACT_BE_U_2(np->id), ns_ops[DNS_OPCODE(flags)],
+ ND_PRINT("%u%s%s%s", GET_BE_U_2(np->id),
+ ns_ops[DNS_OPCODE(flags)],
DNS_RD(flags) ? "+" : "",
DNS_CD(flags) ? "%" : "");
/* any weirdness? */
- b2 = EXTRACT_BE_U_2(((const u_short *)np) + 1);
+ b2 = GET_BE_U_2(((const u_short *)np) + 1);
if (b2 & 0x6cf)
ND_PRINT(" [b2&3=0x%x]", b2);
return;
trunc:
- ND_PRINT("[|domain]");
+ nd_print_trunc(ndo);
}