DNS updates from Brian Wellington.
svn path=/trunk/; revision=2486
This commit is contained in:
parent
677abe54e1
commit
788a6283ff
8
AUTHORS
8
AUTHORS
|
@ -393,6 +393,14 @@ Jack Keane <jkeane@OpenReach.com> {
|
|||
ISAKMP fixes to handle malformed packets
|
||||
}
|
||||
|
||||
Brian Wellington <bwelling@xbill.org> {
|
||||
Support for DNS CERT, KX, TSIG, and TKEY records
|
||||
Support for NOTIFY and UPDATE DNS opcodes
|
||||
Support for YXDOMAIN, YXRRSSET, NXRRRSET, NOTAUTH, NOTZONE, and
|
||||
TSIG/TKEY error DNS reply codes
|
||||
Partial support for DNS-over-TCP
|
||||
}
|
||||
|
||||
Alain Magloire <alainm@rcsm.ece.mcgill.ca> was kind enough to
|
||||
give his permission to use his version of snprintf.c.
|
||||
|
||||
|
|
|
@ -987,6 +987,7 @@ B<http://www.ethereal.com>.
|
|||
Craig Metz <cmetz@inner.net>
|
||||
Per Flock <per.flock@axis.com>
|
||||
Jack Keane <jkeane@OpenReach.com>
|
||||
Brian Wellington <bwelling@xbill.org>
|
||||
|
||||
Alain Magloire <alainm@rcsm.ece.mcgill.ca> was kind enough to give his
|
||||
permission to use his version of snprintf.c.
|
||||
|
|
488
packet-dns.c
488
packet-dns.c
|
@ -1,7 +1,7 @@
|
|||
/* packet-dns.c
|
||||
* Routines for DNS packet disassembly
|
||||
*
|
||||
* $Id: packet-dns.c,v 1.54 2000/10/02 17:42:29 guy Exp $
|
||||
* $Id: packet-dns.c,v 1.55 2000/10/11 04:12:05 guy Exp $
|
||||
*
|
||||
* Ethereal - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@zing.org>
|
||||
|
@ -61,8 +61,9 @@ static gint ett_t_key_flags = -1;
|
|||
|
||||
/* DNS structs and definitions */
|
||||
|
||||
/* Port used for DNS. */
|
||||
/* Ports used for DNS. */
|
||||
#define UDP_PORT_DNS 53
|
||||
#define TCP_PORT_DNS 53
|
||||
|
||||
/* Offsets of fields in the DNS header. */
|
||||
#define DNS_ID 0
|
||||
|
@ -99,21 +100,25 @@ static gint ett_t_key_flags = -1;
|
|||
#define T_RT 21 /* route-through (RFC 1183) */
|
||||
#define T_NSAP 22 /* OSI NSAP (RFC 1706) */
|
||||
#define T_NSAP_PTR 23 /* PTR equivalent for OSI NSAP (RFC 1348 - obsolete) */
|
||||
#define T_SIG 24 /* digital signature (RFC 2065) */
|
||||
#define T_KEY 25 /* public key (RFC 2065) */
|
||||
#define T_SIG 24 /* digital signature (RFC 2535) */
|
||||
#define T_KEY 25 /* public key (RFC 2535) */
|
||||
#define T_PX 26 /* pointer to X.400/RFC822 mapping info (RFC 1664) */
|
||||
#define T_GPOS 27 /* geographical position (RFC 1712) */
|
||||
#define T_AAAA 28 /* IPv6 address (RFC 1886) */
|
||||
#define T_LOC 29 /* geographical location (RFC 1876) */
|
||||
#define T_NXT 30 /* "next" name (RFC 2065) */
|
||||
#define T_NXT 30 /* "next" name (RFC 2535) */
|
||||
#define T_EID 31 /* ??? (Nimrod?) */
|
||||
#define T_NIMLOC 32 /* ??? (Nimrod?) */
|
||||
#define T_SRV 33 /* service location (RFC 2052) */
|
||||
#define T_ATMA 34 /* ??? */
|
||||
#define T_NAPTR 35 /* naming authority pointer (RFC 2168) */
|
||||
#define T_KX 36 /* Key Exchange (RFC 2230) */
|
||||
#define T_CERT 37 /* Certificate (RFC 2538) */
|
||||
#define T_A6 38 /* IPv6 address with indirection (RFC 2874) */
|
||||
#define T_DNAME 39 /* Non-terminal DNS name redirection (RFC 2672) */
|
||||
#define T_OPT 41 /* OPT pseudo-RR (RFC 2671) */
|
||||
#define T_TKEY 249 /* Transaction Key (RFC 2930) */
|
||||
#define T_TSIG 250 /* Transaction Signature (RFC 2845) */
|
||||
#define T_WINS 65281 /* Microsoft's WINS RR */
|
||||
#define T_WINS_R 65282 /* Microsoft's WINS-R RR */
|
||||
|
||||
|
@ -122,6 +127,8 @@ static gint ett_t_key_flags = -1;
|
|||
#define C_CS 2 /* CSNET (obsolete) */
|
||||
#define C_CH 3 /* CHAOS */
|
||||
#define C_HS 4 /* Hesiod */
|
||||
#define C_NONE 254 /* none */
|
||||
#define C_ANY 255 /* any */
|
||||
|
||||
/* Bit fields in the flags */
|
||||
#define F_RESPONSE (1<<15) /* packet is response */
|
||||
|
@ -138,14 +145,58 @@ static gint ett_t_key_flags = -1;
|
|||
#define OPCODE_QUERY (0<<11) /* standard query */
|
||||
#define OPCODE_IQUERY (1<<11) /* inverse query */
|
||||
#define OPCODE_STATUS (2<<11) /* server status request */
|
||||
#define OPCODE_NOTIFY (4<<11) /* zone change notification */
|
||||
#define OPCODE_UPDATE (5<<11) /* dynamic update */
|
||||
|
||||
/* Reply codes */
|
||||
#define RCODE_NOERROR (0<<0)
|
||||
#define RCODE_FMTERROR (1<<0)
|
||||
#define RCODE_FORMERR (1<<0)
|
||||
#define RCODE_SERVFAIL (2<<0)
|
||||
#define RCODE_NAMEERROR (3<<0)
|
||||
#define RCODE_NXDOMAIN (3<<0)
|
||||
#define RCODE_NOTIMPL (4<<0)
|
||||
#define RCODE_REFUSED (5<<0)
|
||||
#define RCODE_YXDOMAIN (6<<0)
|
||||
#define RCODE_YXRRSET (7<<0)
|
||||
#define RCODE_NXRRSET (8<<0)
|
||||
#define RCODE_NOTAUTH (9<<0)
|
||||
#define RCODE_NOTZONE (10<<0)
|
||||
|
||||
static const value_string rcode_vals[] = {
|
||||
{ RCODE_NOERROR, "No error" },
|
||||
{ RCODE_FORMERR, "Format error" },
|
||||
{ RCODE_SERVFAIL, "Server failure" },
|
||||
{ RCODE_NXDOMAIN, "No such name" },
|
||||
{ RCODE_NOTIMPL, "Not implemented" },
|
||||
{ RCODE_REFUSED, "Refused" },
|
||||
{ RCODE_YXDOMAIN, "Name exists" },
|
||||
{ RCODE_YXRRSET, "RRset exists" },
|
||||
{ RCODE_NXRRSET, "RRset does not exist" },
|
||||
{ RCODE_NOTAUTH, "Not authoritative" },
|
||||
{ RCODE_NOTZONE, "Name out of zone" },
|
||||
{ 0, NULL } };
|
||||
|
||||
/* TSIG/TKEY extended errors */
|
||||
#define TSIGERROR_BADSIG (16)
|
||||
#define TSIGERROR_BADKEY (17)
|
||||
#define TSIGERROR_BADTIME (18)
|
||||
#define TSIGERROR_BADMODE (19)
|
||||
#define TSIGERROR_BADNAME (20)
|
||||
#define TSIGERROR_BADALG (21)
|
||||
|
||||
static const value_string tsigerror_vals[] = {
|
||||
{ TSIGERROR_BADSIG, "Bad signature" },
|
||||
{ TSIGERROR_BADKEY, "Bad key" },
|
||||
{ TSIGERROR_BADTIME, "Bad time failure" },
|
||||
{ TSIGERROR_BADMODE, "Bad mode such name" },
|
||||
{ TSIGERROR_BADNAME, "Bad name implemented" },
|
||||
{ TSIGERROR_BADALG, "Bad algorithm" },
|
||||
{ 0, NULL } };
|
||||
|
||||
#define TKEYMODE_SERVERASSIGNED (1)
|
||||
#define TKEYMODE_DIFFIEHELLMAN (2)
|
||||
#define TKEYMODE_GSSAPI (3)
|
||||
#define TKEYMODE_RESOLVERASSIGNED (4)
|
||||
#define TKEYMODE_DELETE (5)
|
||||
|
||||
/* See RFC 1035 for all RR types for which no RFC is listed, except for
|
||||
the ones with "???", and for the Microsoft WINS and WINS-R RRs, for
|
||||
|
@ -186,20 +237,20 @@ dns_type_name (u_int type)
|
|||
"RT", /* RFC 1183 */
|
||||
"NSAP", /* RFC 1706 */
|
||||
"NSAP-PTR", /* RFC 1348 */
|
||||
"SIG", /* RFC 2065 */
|
||||
"KEY", /* RFC 2065 */
|
||||
"SIG", /* RFC 2535 */
|
||||
"KEY", /* RFC 2535 */
|
||||
"PX", /* RFC 1664 */
|
||||
"GPOS", /* RFC 1712 */
|
||||
"AAAA", /* RFC 1886 */
|
||||
"LOC", /* RFC 1876 */
|
||||
"NXT", /* RFC 2065 */
|
||||
"NXT", /* RFC 2535 */
|
||||
"EID",
|
||||
"NIMLOC",
|
||||
"SRV", /* RFC 2052 */
|
||||
"ATMA",
|
||||
"NAPTR", /* RFC 2168 */
|
||||
NULL,
|
||||
NULL,
|
||||
"KX", /* RFC 2230 */
|
||||
"CERT", /* RFC 2538 */
|
||||
"A6", /* RFC 2874 */
|
||||
"DNAME", /* RFC 2672 */
|
||||
NULL,
|
||||
|
@ -226,6 +277,12 @@ dns_type_name (u_int type)
|
|||
case T_WINS_R:
|
||||
return "WINS-R";
|
||||
|
||||
/* meta */
|
||||
case T_TKEY:
|
||||
return "TKEY";
|
||||
case T_TSIG:
|
||||
return "TSIG";
|
||||
|
||||
/* queries */
|
||||
case 251:
|
||||
return "IXFR"; /* RFC 1995 */
|
||||
|
@ -272,20 +329,20 @@ dns_long_type_name (u_int type)
|
|||
"Route through", /* RFC 1183 */
|
||||
"OSI NSAP", /* RFC 1706 */
|
||||
"OSI NSAP name pointer", /* RFC 1348 */
|
||||
"Signature", /* RFC 2065 */
|
||||
"Public key", /* RFC 2065 */
|
||||
"Signature", /* RFC 2535 */
|
||||
"Public key", /* RFC 2535 */
|
||||
"Pointer to X.400/RFC822 mapping info", /* RFC 1664 */
|
||||
"Geographical position", /* RFC 1712 */
|
||||
"IPv6 address", /* RFC 1886 */
|
||||
"Location", /* RFC 1876 */
|
||||
"Next", /* RFC 2065 */
|
||||
"Next", /* RFC 2535 */
|
||||
"EID",
|
||||
"NIMLOC",
|
||||
"Service location", /* RFC 2052 */
|
||||
"ATMA",
|
||||
"Naming authority pointer", /* RFC 2168 */
|
||||
NULL,
|
||||
NULL,
|
||||
"Key Exchange", /* RFC 2230 */
|
||||
"Certificate", /* RFC 2538 */
|
||||
"IPv6 address with indirection", /* RFC 2874 */
|
||||
"Non-terminal DNS name redirection", /* RFC 2672 */
|
||||
NULL,
|
||||
|
@ -313,6 +370,12 @@ dns_long_type_name (u_int type)
|
|||
case T_WINS_R:
|
||||
return "WINS-R";
|
||||
|
||||
/* meta */
|
||||
case T_TKEY:
|
||||
return "Transaction Key";
|
||||
case T_TSIG:
|
||||
return "Transaction Signature";
|
||||
|
||||
/* queries */
|
||||
case 251:
|
||||
return "Request for incremental zone transfer"; /* RFC 1995 */
|
||||
|
@ -349,6 +412,12 @@ dns_class_name(int class)
|
|||
case C_HS:
|
||||
class_name = "hesiod";
|
||||
break;
|
||||
case C_NONE:
|
||||
class_name = "none";
|
||||
break;
|
||||
case C_ANY:
|
||||
class_name = "any";
|
||||
break;
|
||||
default:
|
||||
class_name = "unknown";
|
||||
}
|
||||
|
@ -667,7 +736,7 @@ add_opt_rr_to_tree(proto_item *trr, int rr_type, int offset, const char *name,
|
|||
}
|
||||
|
||||
/*
|
||||
* SIG and KEY RR algorithms.
|
||||
* SIG, KEY, and CERT RR algorithms.
|
||||
*/
|
||||
#define DNS_ALGO_RSAMD5 1 /* RSA/MD5 */
|
||||
#define DNS_ALGO_DH 2 /* Diffie-Hellman */
|
||||
|
@ -688,6 +757,21 @@ static const value_string algo_vals[] = {
|
|||
{ 0, NULL }
|
||||
};
|
||||
|
||||
#define DNS_CERT_PGP 1 /* PGP */
|
||||
#define DNS_CERT_PKIX 2 /* PKIX */
|
||||
#define DNS_CERT_SPKI 3 /* SPKI */
|
||||
#define DNS_CERT_PRIVATEURI 253 /* Private, URI */
|
||||
#define DNS_CERT_PRIVATEOID 254 /* Private, OID */
|
||||
|
||||
static const value_string cert_vals[] = {
|
||||
{ DNS_CERT_PGP, "PGP" },
|
||||
{ DNS_CERT_PKIX, "PKIX" },
|
||||
{ DNS_CERT_SPKI, "SPKI" },
|
||||
{ DNS_CERT_PRIVATEURI, "Private, URI" },
|
||||
{ DNS_CERT_PRIVATEOID, "Private, OID" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static int
|
||||
dissect_dns_answer(const u_char *pd, int offset, int dns_data_offset,
|
||||
frame_data *fd, proto_tree *dns_tree)
|
||||
|
@ -1592,6 +1676,103 @@ dissect_dns_answer(const u_char *pd, int offset, int dns_data_offset,
|
|||
}
|
||||
break;
|
||||
|
||||
case T_KX:
|
||||
{
|
||||
guint16 preference = 0;
|
||||
char kx_name[MAXDNAME];
|
||||
int kx_name_len;
|
||||
|
||||
if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
if (dns_tree != NULL) {
|
||||
proto_item_set_text(trr,
|
||||
"%s: type %s, class %s, <preference goes past end of captured data in packet>",
|
||||
name, type_name, class_name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
preference = pntohs(&pd[cur_offset]);
|
||||
kx_name_len = get_dns_name(pd, cur_offset + 2, dns_data_offset, kx_name, sizeof(kx_name));
|
||||
if (kx_name_len < 0) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
if (dns_tree != NULL) {
|
||||
proto_item_set_text(trr,
|
||||
"%s: type %s, class %s, preference %u, <kx goes past end of captured data in packet>",
|
||||
name, type_name, class_name, preference);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (fd != NULL)
|
||||
col_append_fstr(fd, COL_INFO, " %u %s", preference, kx_name);
|
||||
if (dns_tree != NULL) {
|
||||
proto_item_set_text(trr,
|
||||
"%s: type %s, class %s, preference %u, kx %s",
|
||||
name, type_name, class_name, preference, kx_name);
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2, "Preference: %u", preference);
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset + 2, kx_name_len, "Key exchange: %s",
|
||||
kx_name);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case T_CERT:
|
||||
{
|
||||
guint16 cert_type, cert_keytag;
|
||||
guint8 cert_keyalg;
|
||||
int rr_len = data_len;
|
||||
|
||||
if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
if (dns_tree != NULL) {
|
||||
proto_item_set_text(trr,
|
||||
"%s: type %s, class %s, <preference goes past end of captured data in packet>",
|
||||
name, type_name, class_name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
cert_type = pntohs(&pd[cur_offset]);
|
||||
cur_offset += 2;
|
||||
rr_len -= 2;
|
||||
if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
if (dns_tree != NULL) {
|
||||
proto_item_set_text(trr,
|
||||
"%s: type %s, class %s, <preference goes past end of captured data in packet>",
|
||||
name, type_name, class_name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
cert_keytag = pntohs(&pd[cur_offset]);
|
||||
cur_offset += 2;
|
||||
rr_len -= 2;
|
||||
if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
if (dns_tree != NULL) {
|
||||
proto_item_set_text(trr,
|
||||
"%s: type %s, class %s, <preference goes past end of captured data in packet>",
|
||||
name, type_name, class_name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
cert_keyalg = pd[cur_offset];
|
||||
cur_offset += 1;
|
||||
rr_len -= 1;
|
||||
|
||||
if (dns_tree != NULL) {
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Type: %s",
|
||||
val_to_str(cert_keyalg, cert_vals,
|
||||
"Unknown (0x%02X)"));
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2, "Key footprint: 0x%04x",
|
||||
cert_keytag);
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Algorithm: %s",
|
||||
val_to_str(cert_keyalg, algo_vals,
|
||||
"Unknown (0x%02X)"));
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset, rr_len, "Public key");
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case T_OPT:
|
||||
if (dns_tree != NULL) {
|
||||
proto_item_set_text(trr, "%s: type %s", name, type_name);
|
||||
|
@ -1599,6 +1780,221 @@ dissect_dns_answer(const u_char *pd, int offset, int dns_data_offset,
|
|||
}
|
||||
break;
|
||||
|
||||
case T_TKEY:
|
||||
{
|
||||
char tkey_algname[MAXDNAME];
|
||||
int tkey_algname_len;
|
||||
guint16 tkey_mode, tkey_error, tkey_keylen, tkey_otherlen;
|
||||
int rr_len = data_len;
|
||||
struct timeval unixtime;
|
||||
static const value_string tkey_modes[] = {
|
||||
{ TKEYMODE_SERVERASSIGNED, "Server assigned" },
|
||||
{ TKEYMODE_DIFFIEHELLMAN, "Diffie Hellman" },
|
||||
{ TKEYMODE_GSSAPI, "GSSAPI " },
|
||||
{ TKEYMODE_RESOLVERASSIGNED, "Resolver assigned" },
|
||||
{ TKEYMODE_DELETE, "Delete" },
|
||||
{ 0, NULL } };
|
||||
|
||||
if (dns_tree != NULL) {
|
||||
proto_item_set_text(trr,
|
||||
"%s: type %s, class %s", name, type_name, class_name);
|
||||
tkey_algname_len = get_dns_name(pd, cur_offset, dns_data_offset, tkey_algname, sizeof(tkey_algname));
|
||||
if (tkey_algname_len < 0) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
return 0;
|
||||
}
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset, tkey_algname_len,
|
||||
"Algorithm name: %s", tkey_algname);
|
||||
cur_offset += tkey_algname_len;
|
||||
rr_len -= tkey_algname_len;
|
||||
|
||||
if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
return 0;
|
||||
}
|
||||
unixtime.tv_sec = pntohl(&pd[cur_offset]);
|
||||
unixtime.tv_usec = 0;
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Signature inception: %s",
|
||||
abs_time_to_str(&unixtime));
|
||||
cur_offset += 4;
|
||||
rr_len -= 4;
|
||||
|
||||
if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
return 0;
|
||||
}
|
||||
unixtime.tv_sec = pntohl(&pd[cur_offset]);
|
||||
unixtime.tv_usec = 0;
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Signature expiration: %s",
|
||||
abs_time_to_str(&unixtime));
|
||||
cur_offset += 4;
|
||||
rr_len -= 4;
|
||||
|
||||
if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
return 0;
|
||||
}
|
||||
tkey_mode = pntohs(&pd[cur_offset]);
|
||||
cur_offset += 2;
|
||||
rr_len -= 2;
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Mode: %s",
|
||||
val_to_str(tkey_mode, tkey_modes,
|
||||
"Unknown (0x%02X)"));
|
||||
|
||||
tkey_error = pntohs(&pd[cur_offset]);
|
||||
cur_offset += 2;
|
||||
rr_len -= 2;
|
||||
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Error: %s",
|
||||
val_to_str(tkey_error, rcode_vals,
|
||||
val_to_str(tkey_error, tsigerror_vals, "Unknown error (%x)")));
|
||||
|
||||
tkey_keylen = pntohs(&pd[cur_offset]);
|
||||
cur_offset += 2;
|
||||
rr_len -= 2;
|
||||
|
||||
if (!BYTES_ARE_IN_FRAME(cur_offset, tkey_keylen)) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset, tkey_keylen, "Key");
|
||||
cur_offset += tkey_keylen;
|
||||
rr_len -= tkey_keylen;
|
||||
|
||||
tkey_otherlen = pntohs(&pd[cur_offset]);
|
||||
cur_offset += 2;
|
||||
rr_len -= 2;
|
||||
|
||||
if (!BYTES_ARE_IN_FRAME(cur_offset, tkey_otherlen)) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset, tkey_otherlen, "Other");
|
||||
cur_offset += tkey_otherlen;
|
||||
rr_len -= tkey_otherlen;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case T_TSIG:
|
||||
{
|
||||
guint8 tsig_fudge;
|
||||
guint16 tsig_originalid, tsig_error, tsig_timehi, tsig_siglen, tsig_otherlen;
|
||||
guint32 tsig_timelo;
|
||||
char tsig_algname[MAXDNAME];
|
||||
int tsig_algname_len;
|
||||
struct timeval unixtime;
|
||||
int rr_len = data_len;
|
||||
|
||||
if (dns_tree != NULL) {
|
||||
proto_item_set_text(trr,
|
||||
"%s: type %s, class %s", name, type_name, class_name);
|
||||
tsig_algname_len = get_dns_name(pd, cur_offset, dns_data_offset, tsig_algname, sizeof(tsig_algname));
|
||||
if (tsig_algname_len < 0) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
return 0;
|
||||
}
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset, tsig_algname_len,
|
||||
"Algorithm name: %s", tsig_algname);
|
||||
cur_offset += tsig_algname_len;
|
||||
rr_len -= tsig_algname_len;
|
||||
|
||||
if (!BYTES_ARE_IN_FRAME(cur_offset, 6)) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
tsig_timehi = pntohs(&pd[cur_offset]);
|
||||
cur_offset += 2;
|
||||
rr_len -= 2;
|
||||
|
||||
tsig_timelo = pntohl(&pd[cur_offset]);
|
||||
cur_offset += 4;
|
||||
rr_len -= 4;
|
||||
|
||||
unixtime.tv_sec = tsig_timelo;
|
||||
unixtime.tv_usec = 0;
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset, 6, "Time signed: %s%s",
|
||||
abs_time_to_str(&unixtime), tsig_timehi == 0 ? "" : "(high bits set)");
|
||||
|
||||
if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
tsig_fudge = pntohs(&pd[cur_offset]);
|
||||
cur_offset += 2;
|
||||
rr_len -= 2;
|
||||
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2, "Fudge: %d",
|
||||
tsig_fudge);
|
||||
|
||||
if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
tsig_siglen = pntohs(&pd[cur_offset]);
|
||||
cur_offset += 2;
|
||||
rr_len -= 2;
|
||||
|
||||
if (!BYTES_ARE_IN_FRAME(cur_offset, tsig_siglen)) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset, tsig_siglen, "Signature");
|
||||
cur_offset += tsig_siglen;
|
||||
rr_len -= tsig_siglen;
|
||||
|
||||
if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
tsig_originalid = pntohs(&pd[cur_offset]);
|
||||
cur_offset += 2;
|
||||
rr_len -= 2;
|
||||
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Original id: %d",
|
||||
tsig_originalid);
|
||||
|
||||
if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
tsig_error = pntohs(&pd[cur_offset]);
|
||||
cur_offset += 2;
|
||||
rr_len -= 2;
|
||||
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Error: %s",
|
||||
val_to_str(tsig_error, rcode_vals,
|
||||
val_to_str(tsig_error, tsigerror_vals, "Unknown error (%x)")));
|
||||
|
||||
if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
tsig_otherlen = pntohs(&pd[cur_offset]);
|
||||
cur_offset += 2;
|
||||
rr_len -= 2;
|
||||
|
||||
if (!BYTES_ARE_IN_FRAME(cur_offset, tsig_otherlen)) {
|
||||
/* We ran past the end of the captured data in the packet. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
proto_tree_add_text(rr_tree, NullTVB, cur_offset, tsig_otherlen, "Other");
|
||||
cur_offset += tsig_otherlen;
|
||||
rr_len -= tsig_otherlen;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case T_WINS:
|
||||
{
|
||||
int rr_len = data_len;
|
||||
|
@ -1774,7 +2170,7 @@ dissect_dns_answer(const u_char *pd, int offset, int dns_data_offset,
|
|||
|
||||
static int
|
||||
dissect_query_records(const u_char *pd, int cur_off, int dns_data_offset,
|
||||
int count, frame_data *fd, proto_tree *dns_tree)
|
||||
int count, frame_data *fd, proto_tree *dns_tree, int isupdate)
|
||||
{
|
||||
int start_off, add_off;
|
||||
proto_tree *qatree = NULL;
|
||||
|
@ -1782,7 +2178,8 @@ dissect_query_records(const u_char *pd, int cur_off, int dns_data_offset,
|
|||
|
||||
start_off = cur_off;
|
||||
if (dns_tree) {
|
||||
ti = proto_tree_add_text(dns_tree, NullTVB, start_off, 0, "Queries");
|
||||
char *s = (isupdate ? "Zone" : "Queries");
|
||||
ti = proto_tree_add_text(dns_tree, NullTVB, start_off, 0, s);
|
||||
qatree = proto_item_add_subtree(ti, ett_dns_qry);
|
||||
}
|
||||
while (count-- > 0) {
|
||||
|
@ -1835,19 +2232,14 @@ dissect_dns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
|
|||
guint16 id, flags, quest, ans, auth, add;
|
||||
char buf[128+1];
|
||||
int cur_off;
|
||||
int isupdate;
|
||||
static const value_string opcode_vals[] = {
|
||||
{ OPCODE_QUERY, "Standard query" },
|
||||
{ OPCODE_IQUERY, "Inverse query" },
|
||||
{ OPCODE_STATUS, "Server status request" },
|
||||
{ 0, NULL } };
|
||||
static const value_string rcode_vals[] = {
|
||||
{ RCODE_NOERROR, "No error" },
|
||||
{ RCODE_FMTERROR, "Format error" },
|
||||
{ RCODE_SERVFAIL, "Server failure" },
|
||||
{ RCODE_NAMEERROR, "Name error" },
|
||||
{ RCODE_NOTIMPL, "Not implemented" },
|
||||
{ RCODE_REFUSED, "Refused" },
|
||||
{ 0, NULL } };
|
||||
{ OPCODE_QUERY, "Standard query" },
|
||||
{ OPCODE_IQUERY, "Inverse query" },
|
||||
{ OPCODE_STATUS, "Server status request" },
|
||||
{ OPCODE_NOTIFY, "Zone change notification" },
|
||||
{ OPCODE_UPDATE, "Dynamic update" },
|
||||
{ 0, NULL } };
|
||||
|
||||
OLD_CHECK_DISPLAY_AS_DATA(proto_dns, pd, offset, fd, tree);
|
||||
|
||||
|
@ -1856,7 +2248,7 @@ dissect_dns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
|
|||
if (check_col(fd, COL_PROTOCOL))
|
||||
col_add_str(fd, COL_PROTOCOL, "DNS");
|
||||
|
||||
if (pi.captured_len < DNS_HDRLEN) {
|
||||
if (!BYTES_ARE_IN_FRAME(offset, DNS_HDRLEN)) {
|
||||
col_add_str(fd, COL_INFO, "Short DNS packet");
|
||||
old_dissect_data(pd, offset, fd, tree);
|
||||
return;
|
||||
|
@ -1888,6 +2280,10 @@ dissect_dns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
|
|||
is more expensive than a check that a pointer isn't NULL). */
|
||||
fd = NULL;
|
||||
}
|
||||
if ((flags & F_OPCODE) == OPCODE_UPDATE)
|
||||
isupdate = 1;
|
||||
else
|
||||
isupdate = 0;
|
||||
|
||||
if (tree) {
|
||||
ti = proto_tree_add_protocol_format(tree, proto_dns, NullTVB, offset, 4,
|
||||
|
@ -1980,23 +2376,26 @@ dissect_dns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
|
|||
to the summary, just add information about the answers. */
|
||||
cur_off += dissect_query_records(pd, cur_off, dns_data_offset, quest,
|
||||
(!(flags & F_RESPONSE) ? fd : NULL),
|
||||
dns_tree);
|
||||
dns_tree, isupdate);
|
||||
}
|
||||
|
||||
if (ans > 0) {
|
||||
/* If this is a request, don't add information about the answers
|
||||
to the summary, just add information about the queries. */
|
||||
char *s = (isupdate ? "Prerequisites" : "Answers");
|
||||
cur_off += dissect_answer_records(pd, cur_off, dns_data_offset, ans,
|
||||
((flags & F_RESPONSE) ? fd : NULL),
|
||||
dns_tree, "Answers");
|
||||
dns_tree, s);
|
||||
}
|
||||
|
||||
if (tree) {
|
||||
/* Don't add information about the authoritative name servers, or the
|
||||
additional records, to the summary. */
|
||||
if (auth > 0)
|
||||
if (auth > 0) {
|
||||
char *s = (isupdate ? "Updates" : "Authoritative nameservers");
|
||||
cur_off += dissect_answer_records(pd, cur_off, dns_data_offset, auth,
|
||||
NULL, dns_tree, "Authoritative nameservers");
|
||||
NULL, dns_tree, s);
|
||||
}
|
||||
|
||||
if (add > 0)
|
||||
cur_off += dissect_answer_records(pd, cur_off, dns_data_offset, add,
|
||||
|
@ -2004,6 +2403,20 @@ dissect_dns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dissect_dns_tcp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
|
||||
{
|
||||
guint16 plen;
|
||||
|
||||
if (pi.captured_len < 2)
|
||||
return;
|
||||
plen = pntohs(&pd[offset]);
|
||||
offset += 2;
|
||||
if (END_OF_FRAME != plen)
|
||||
return;
|
||||
dissect_dns(pd, offset, fd, tree);
|
||||
}
|
||||
|
||||
void
|
||||
proto_register_dns(void)
|
||||
{
|
||||
|
@ -2060,4 +2473,5 @@ void
|
|||
proto_reg_handoff_dns(void)
|
||||
{
|
||||
old_dissector_add("udp.port", UDP_PORT_DNS, dissect_dns);
|
||||
old_dissector_add("tcp.port", TCP_PORT_DNS, dissect_dns_tcp);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue