Added support for LLMNR.

svn path=/trunk/; revision=27425
This commit is contained in:
Stig Bjørlykke 2009-02-11 13:25:00 +00:00
parent 49ec933f2b
commit 29f106a07d
1 changed files with 89 additions and 21 deletions

View File

@ -28,6 +28,7 @@
* RFC 2136 for dynamic DNS
* http://files.multicastdns.org/draft-cheshire-dnsext-multicastdns.txt
* for multicast DNS
* RFC 4795 for link-local multicast name resolution (LLMNR)
*/
#ifdef HAVE_CONFIG_H
@ -55,8 +56,11 @@ static int hf_dns_flags = -1;
static int hf_dns_flags_response = -1;
static int hf_dns_flags_opcode = -1;
static int hf_dns_flags_authoritative = -1;
static int hf_dns_flags_conflict_query = -1;
static int hf_dns_flags_conflict_response = -1;
static int hf_dns_flags_truncated = -1;
static int hf_dns_flags_recdesired = -1;
static int hf_dns_flags_tentative = -1;
static int hf_dns_flags_recavail = -1;
static int hf_dns_flags_z = -1;
static int hf_dns_flags_authenticated = -1;
@ -141,6 +145,7 @@ typedef struct _dns_conv_info_t {
#define TCP_PORT_DNS 53
#define UDP_PORT_MDNS 5353
#define TCP_PORT_MDNS 5353
#define UDP_PORT_LLMNR 5355
/* Offsets of fields in the DNS header. */
#define DNS_ID 0
@ -222,10 +227,12 @@ typedef struct _dns_conv_info_t {
#define F_OPCODE (0xF<<11) /* query opcode */
#define OPCODE_SHIFT 11
#define F_AUTHORITATIVE (1<<10) /* response is authoritative */
#define F_CONFLICT (1<<10) /* conflict detected */
#define F_TRUNCATED (1<<9) /* response is truncated */
#define F_RECDESIRED (1<<8) /* recursion desired */
#define F_TENTATIVE (1<<8) /* response is tentative */
#define F_RECAVAIL (1<<7) /* recursion available */
#define F_Z (1<<6) /* Z */
#define F_Z (1<<6) /* Z */
#define F_AUTHENTIC (1<<5) /* authentic data (RFC2535) */
#define F_CHECKDISABLE (1<<4) /* checking disabled (RFC2535) */
#define F_RCODE (0xF<<0) /* reply code */
@ -240,6 +247,16 @@ static const true_false_string tfs_flags_authoritative = {
"Server is not an authority for domain"
};
static const true_false_string tfs_flags_conflict_query = {
"The sender received multiple responses",
"None"
};
static const true_false_string tfs_flags_conflict_response = {
"The name is not considered unique",
"The name is considered unique"
};
static const true_false_string tfs_flags_truncated = {
"Message is truncated",
"Message is not truncated"
@ -250,6 +267,11 @@ static const true_false_string tfs_flags_recdesired = {
"Don't do query recursively"
};
static const true_false_string tfs_flags_tentative = {
"Tentative",
"Not tentative"
};
static const true_false_string tfs_flags_recavail = {
"Server can do recursive queries",
"Server can't do recursive queries"
@ -2579,7 +2601,7 @@ dissect_answer_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
static void
dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
gboolean is_tcp, gboolean is_mdns)
gboolean is_tcp, gboolean is_mdns, gboolean is_llmnr)
{
int offset = is_tcp ? 2 : 0;
int dns_data_offset;
@ -2640,8 +2662,13 @@ dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
isupdate = FALSE;
if (tree) {
ti = proto_tree_add_protocol_format(tree, proto_dns, tvb, 0, -1,
"Domain Name System (%s)", (flags & F_RESPONSE) ? "response" : "query");
if (is_llmnr) {
ti = proto_tree_add_protocol_format(tree, proto_dns, tvb, 0, -1,
"Link-local Multicast Name Resolution (%s)", (flags & F_RESPONSE) ? "response" : "query");
} else {
ti = proto_tree_add_protocol_format(tree, proto_dns, tvb, 0, -1,
"Domain Name System (%s)", (flags & F_RESPONSE) ? "response" : "query");
}
dns_tree = proto_item_add_subtree(ti, ett_dns);
}
@ -2748,28 +2775,46 @@ dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
tvb, offset + DNS_FLAGS, 2, FALSE);
proto_tree_add_item(field_tree, hf_dns_flags_opcode,
tvb, offset + DNS_FLAGS, 2, FALSE);
if (flags & F_RESPONSE) {
proto_tree_add_item(field_tree, hf_dns_flags_authoritative,
if (is_llmnr) {
if (flags & F_RESPONSE) {
proto_tree_add_item(field_tree, hf_dns_flags_conflict_response,
tvb, offset + DNS_FLAGS, 2, FALSE);
}
proto_tree_add_item(field_tree, hf_dns_flags_truncated,
} else {
proto_tree_add_item(field_tree, hf_dns_flags_conflict_query,
tvb, offset + DNS_FLAGS, 2, FALSE);
proto_tree_add_item(field_tree, hf_dns_flags_recdesired,
}
proto_tree_add_item(field_tree, hf_dns_flags_truncated,
tvb, offset + DNS_FLAGS, 2, FALSE);
if (flags & F_RESPONSE) {
proto_tree_add_item(field_tree, hf_dns_flags_recavail,
proto_tree_add_item(field_tree, hf_dns_flags_tentative,
tvb, offset + DNS_FLAGS, 2, FALSE);
proto_tree_add_item(field_tree, hf_dns_flags_z,
tvb, offset + DNS_FLAGS, 2, FALSE);
proto_tree_add_item(field_tree, hf_dns_flags_authenticated,
tvb, offset + DNS_FLAGS, 2, FALSE);
proto_tree_add_item(field_tree, hf_dns_flags_rcode,
if (flags & F_RESPONSE) {
proto_tree_add_item(field_tree, hf_dns_flags_rcode,
tvb, offset + DNS_FLAGS, 2, FALSE);
}
} else {
proto_tree_add_item(field_tree, hf_dns_flags_z,
if (flags & F_RESPONSE) {
proto_tree_add_item(field_tree, hf_dns_flags_authoritative,
tvb, offset + DNS_FLAGS, 2, FALSE);
}
proto_tree_add_item(field_tree, hf_dns_flags_truncated,
tvb, offset + DNS_FLAGS, 2, FALSE);
proto_tree_add_item(field_tree, hf_dns_flags_checkdisable,
proto_tree_add_item(field_tree, hf_dns_flags_recdesired,
tvb, offset + DNS_FLAGS, 2, FALSE);
if (flags & F_RESPONSE) {
proto_tree_add_item(field_tree, hf_dns_flags_recavail,
tvb, offset + DNS_FLAGS, 2, FALSE);
proto_tree_add_item(field_tree, hf_dns_flags_z,
tvb, offset + DNS_FLAGS, 2, FALSE);
proto_tree_add_item(field_tree, hf_dns_flags_authenticated,
tvb, offset + DNS_FLAGS, 2, FALSE);
proto_tree_add_item(field_tree, hf_dns_flags_rcode,
tvb, offset + DNS_FLAGS, 2, FALSE);
} else {
proto_tree_add_item(field_tree, hf_dns_flags_z,
tvb, offset + DNS_FLAGS, 2, FALSE);
proto_tree_add_item(field_tree, hf_dns_flags_checkdisable,
tvb, offset + DNS_FLAGS, 2, FALSE);
}
}
quest = tvb_get_ntohs(tvb, offset + DNS_QUEST);
@ -2851,7 +2896,7 @@ dissect_dns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNS");
dissect_dns_common(tvb, pinfo, tree, FALSE, FALSE);
dissect_dns_common(tvb, pinfo, tree, FALSE, FALSE, FALSE);
}
static void
@ -2860,9 +2905,17 @@ dissect_mdns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "MDNS");
dissect_dns_common(tvb, pinfo, tree, FALSE, TRUE);
dissect_dns_common(tvb, pinfo, tree, FALSE, TRUE, FALSE);
}
static void
dissect_llmnr_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "LLMNR");
dissect_dns_common(tvb, pinfo, tree, FALSE, FALSE, TRUE);
}
static guint
get_dns_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
@ -2886,7 +2939,7 @@ dissect_dns_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNS");
dissect_dns_common(tvb, pinfo, tree, TRUE, FALSE);
dissect_dns_common(tvb, pinfo, tree, TRUE, FALSE, FALSE);
}
static void
@ -2920,6 +2973,14 @@ proto_register_dns(void)
{ "Authoritative", "dns.flags.authoritative",
FT_BOOLEAN, 16, TFS(&tfs_flags_authoritative), F_AUTHORITATIVE,
"Is the server is an authority for the domain?", HFILL }},
{ &hf_dns_flags_conflict_query,
{ "Conflict", "dns.flags.conflict",
FT_BOOLEAN, 16, TFS(&tfs_flags_conflict_query), F_CONFLICT,
"Did we receive multiple responses to a query?", HFILL }},
{ &hf_dns_flags_conflict_response,
{ "Conflict", "dns.flags.conflict",
FT_BOOLEAN, 16, TFS(&tfs_flags_conflict_response), F_CONFLICT,
"Is the name considered unique?", HFILL }},
{ &hf_dns_flags_truncated,
{ "Truncated", "dns.flags.truncated",
FT_BOOLEAN, 16, TFS(&tfs_flags_truncated), F_TRUNCATED,
@ -2928,6 +2989,10 @@ proto_register_dns(void)
{ "Recursion desired", "dns.flags.recdesired",
FT_BOOLEAN, 16, TFS(&tfs_flags_recdesired), F_RECDESIRED,
"Do query recursively?", HFILL }},
{ &hf_dns_flags_tentative,
{ "Tentative", "dns.flags.tentative",
FT_BOOLEAN, 16, TFS(&tfs_flags_tentative), F_TENTATIVE,
"Is the responder authoritative for the name, but not yet verified the uniqueness?", HFILL }},
{ &hf_dns_flags_recavail,
{ "Recursion available", "dns.flags.recavail",
FT_BOOLEAN, 16, TFS(&tfs_flags_recavail), F_RECAVAIL,
@ -3139,15 +3204,18 @@ proto_reg_handoff_dns(void)
dissector_handle_t dns_udp_handle;
dissector_handle_t dns_tcp_handle;
dissector_handle_t mdns_udp_handle;
dissector_handle_t llmnr_udp_handle;
dns_udp_handle = create_dissector_handle(dissect_dns_udp, proto_dns);
dns_tcp_handle = create_dissector_handle(dissect_dns_tcp, proto_dns);
mdns_udp_handle = create_dissector_handle(dissect_mdns_udp, proto_dns);
llmnr_udp_handle = create_dissector_handle(dissect_llmnr_udp, proto_dns);
dissector_add("udp.port", UDP_PORT_DNS, dns_udp_handle);
dissector_add("tcp.port", TCP_PORT_DNS, dns_tcp_handle);
dissector_add("udp.port", UDP_PORT_MDNS, mdns_udp_handle);
dissector_add("tcp.port", TCP_PORT_MDNS, dns_tcp_handle);
dissector_add("udp.port", UDP_PORT_LLMNR, llmnr_udp_handle);
gssapi_handle = find_dissector("gssapi");
ntlmssp_handle = find_dissector("ntlmssp");