aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packet-dns.c146
-rw-r--r--packet-nbns.c259
-rw-r--r--packet.h4
3 files changed, 279 insertions, 130 deletions
diff --git a/packet-dns.c b/packet-dns.c
index b057972291..bb3d28f44d 100644
--- a/packet-dns.c
+++ b/packet-dns.c
@@ -1,7 +1,7 @@
/* packet-dns.c
* Routines for DNS packet disassembly
*
- * $Id: packet-dns.c,v 1.12 1998/12/20 01:47:05 guy Exp $
+ * $Id: packet-dns.c,v 1.13 1999/01/04 09:13:46 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -30,6 +30,7 @@
#include <gtk/gtk.h>
#include <stdio.h>
+#include <string.h>
#include <memory.h>
#ifdef HAVE_SYS_TYPES_H
@@ -43,18 +44,21 @@
#include "ethereal.h"
#include "packet.h"
#include "packet-dns.h"
+#include "util.h"
/* DNS structs and definitions */
-typedef struct _e_dns {
- guint16 dns_id;
- guint16 dns_flags;
- guint16 dns_quest;
- guint16 dns_ans;
- guint16 dns_auth;
- guint16 dns_add;
-} e_dns;
+/* Offsets of fields in the DNS header. */
+#define DNS_ID 0
+#define DNS_FLAGS 2
+#define DNS_QUEST 4
+#define DNS_ANS 6
+#define DNS_AUTH 8
+#define DNS_ADD 10
+
+/* Length of DNS header. */
+#define DNS_HDRLEN 12
/* type values */
#define T_A 1 /* host address */
@@ -68,6 +72,27 @@ typedef struct _e_dns {
#define T_TXT 16 /* text strings */
#define T_AAAA 28 /* IP6 Address */
+/* Bit fields in the flags */
+#define F_RESPONSE (1<<15) /* packet is response */
+#define F_OPCODE (0xF<<11) /* query opcode */
+#define F_AUTHORITATIVE (1<<10) /* response is authoritative */
+#define F_TRUNCATED (1<<9) /* response is truncated */
+#define F_RECDESIRED (1<<8) /* recursion desired */
+#define F_RECAVAIL (1<<7) /* recursion available */
+#define F_RCODE (0xF<<0) /* reply code */
+
+/* Opcodes */
+#define OPCODE_QUERY (0<<11) /* standard query */
+#define OPCODE_IQUERY (1<<11) /* inverse query */
+#define OPCODE_STATUS (2<<11) /* server status request */
+
+/* Reply codes */
+#define RCODE_NOERROR (0<<0)
+#define RCODE_FMTERROR (1<<0)
+#define RCODE_SERVFAIL (2<<0)
+#define RCODE_NAMEERROR (3<<0)
+#define RCODE_NOTIMPL (4<<0)
+#define RCODE_REFUSED (5<<0)
static char *
dns_type_name (int type)
@@ -445,46 +470,103 @@ dissect_answer_records(const u_char *dns_data_ptr, int count,
void
dissect_dns(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
const u_char *dns_data_ptr;
- e_dns *dh;
- GtkWidget *dns_tree, *ti;
+ GtkWidget *dns_tree, *ti, *field_tree, *tf;
guint16 id, flags, quest, ans, auth, add;
- int query = 0;
+ char buf[128+1];
int cur_off;
+ 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 } };
dns_data_ptr = &pd[offset];
- dh = (e_dns *) dns_data_ptr;
/* To do: check for runts, errs, etc. */
- id = ntohs(dh->dns_id);
- flags = ntohs(dh->dns_flags);
- quest = ntohs(dh->dns_quest);
- ans = ntohs(dh->dns_ans);
- auth = ntohs(dh->dns_auth);
- add = ntohs(dh->dns_add);
-
- query = ! (flags & (1 << 15));
+ id = pntohs(&pd[offset + DNS_ID]);
+ flags = pntohs(&pd[offset + DNS_FLAGS]);
+ quest = pntohs(&pd[offset + DNS_QUEST]);
+ ans = pntohs(&pd[offset + DNS_ANS]);
+ auth = pntohs(&pd[offset + DNS_AUTH]);
+ add = pntohs(&pd[offset + DNS_ADD]);
if (check_col(fd, COL_PROTOCOL))
col_add_str(fd, COL_PROTOCOL, "DNS (UDP)");
- if (check_col(fd, COL_INFO))
- col_add_str(fd, COL_INFO, query ? "Query" : "Response");
+ if (check_col(fd, COL_INFO)) {
+ col_add_fstr(fd, COL_INFO, "%s%s",
+ val_to_str(flags & F_OPCODE, opcode_vals,
+ "Unknown operation (%x)"),
+ (flags & F_RESPONSE) ? " response" : "");
+ }
if (tree) {
ti = add_item_to_tree(GTK_WIDGET(tree), offset, 4,
- query ? "DNS query" : "DNS response");
+ (flags & F_RESPONSE) ? "DNS response" : "DNS query");
dns_tree = gtk_tree_new();
add_subtree(ti, dns_tree, ETT_DNS);
- add_item_to_tree(dns_tree, offset, 2, "ID: 0x%04x", id);
-
- add_item_to_tree(dns_tree, offset + 2, 2, "Flags: 0x%04x", flags);
- add_item_to_tree(dns_tree, offset + 4, 2, "Questions: %d", quest);
- add_item_to_tree(dns_tree, offset + 6, 2, "Answer RRs: %d", ans);
- add_item_to_tree(dns_tree, offset + 8, 2, "Authority RRs: %d", auth);
- add_item_to_tree(dns_tree, offset + 10, 2, "Additional RRs: %d", add);
+ add_item_to_tree(dns_tree, offset + DNS_ID, 2, "Transaction ID: 0x%04x",
+ id);
+
+ strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown (%x)"));
+ if (flags & F_RESPONSE) {
+ strcat(buf, " response");
+ strcat(buf, ", ");
+ strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
+ "Unknown error (%x)"));
+ }
+ tf = add_item_to_tree(dns_tree, offset + DNS_FLAGS, 2, "Flags: 0x%04x (%s)",
+ flags, buf);
+ field_tree = gtk_tree_new();
+ add_subtree(tf, field_tree, ETT_DNS_FLAGS);
+ add_item_to_tree(field_tree, offset + DNS_FLAGS, 2, "%s",
+ decode_boolean_bitfield(flags, F_RESPONSE,
+ 2*8, "Response", "Query"));
+ add_item_to_tree(field_tree, offset + DNS_FLAGS, 2, "%s",
+ decode_enumerated_bitfield(flags, F_OPCODE,
+ 2*8, opcode_vals, "%s"));
+ if (flags & F_RESPONSE) {
+ add_item_to_tree(field_tree, offset + DNS_FLAGS, 2, "%s",
+ decode_boolean_bitfield(flags, F_AUTHORITATIVE,
+ 2*8,
+ "Server is an authority for domain",
+ "Server isn't an authority for domain"));
+ }
+ add_item_to_tree(field_tree, offset + DNS_FLAGS, 2, "%s",
+ decode_boolean_bitfield(flags, F_TRUNCATED,
+ 2*8,
+ "Message is truncated",
+ "Message is not truncated"));
+ add_item_to_tree(field_tree, offset + DNS_FLAGS, 2, "%s",
+ decode_boolean_bitfield(flags, F_RECDESIRED,
+ 2*8,
+ "Do query recursively",
+ "Don't do query recursively"));
+ if (flags & F_RESPONSE) {
+ add_item_to_tree(field_tree, offset + DNS_FLAGS, 2, "%s",
+ decode_boolean_bitfield(flags, F_RECAVAIL,
+ 2*8,
+ "Server can do recursive queries",
+ "Server can't do recursive queries"));
+ add_item_to_tree(field_tree, offset + DNS_FLAGS, 2, "%s",
+ decode_enumerated_bitfield(flags, F_RCODE,
+ 2*8, rcode_vals, "%s"));
+ }
+ add_item_to_tree(dns_tree, offset + DNS_QUEST, 2, "Questions: %d", quest);
+ add_item_to_tree(dns_tree, offset + DNS_ANS, 2, "Answer RRs: %d", ans);
+ add_item_to_tree(dns_tree, offset + DNS_AUTH, 2, "Authority RRs: %d", auth);
+ add_item_to_tree(dns_tree, offset + DNS_ADD, 2, "Additional RRs: %d", add);
- cur_off = offset + 12;
+ cur_off = offset + DNS_HDRLEN;
if (quest > 0)
cur_off += dissect_query_records(dns_data_ptr, quest, pd, cur_off,
diff --git a/packet-nbns.c b/packet-nbns.c
index e14b637592..e6ca278528 100644
--- a/packet-nbns.c
+++ b/packet-nbns.c
@@ -3,7 +3,7 @@
* Gilbert Ramirez <gram@verdict.uthscsa.edu>
* Much stuff added by Guy Harris <guy@netapp.com>
*
- * $Id: packet-nbns.c,v 1.10 1998/12/04 05:59:12 guy Exp $
+ * $Id: packet-nbns.c,v 1.11 1999/01/04 09:13:46 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -32,6 +32,7 @@
#include <gtk/gtk.h>
#include <stdio.h>
+#include <string.h>
#include <memory.h>
#ifdef HAVE_SYS_TYPES_H
@@ -45,28 +46,22 @@
#include "ethereal.h"
#include "packet.h"
#include "packet-dns.h"
+#include "util.h"
/* Packet structure taken from RFC 1002. See also RFC 1001.
- * The Samba source code, specifically nmblib.c, also helps a lot. */
+ * Opcode, flags, and rcode treated as "flags", similarly to DNS,
+ * to make it easier to lift the dissection code from "packet-dns.c". */
-struct nbns_header {
+/* Offsets of fields in the NBNS header. */
+#define NBNS_ID 0
+#define NBNS_FLAGS 2
+#define NBNS_QUEST 4
+#define NBNS_ANS 6
+#define NBNS_AUTH 8
+#define NBNS_ADD 10
- guint16 name_tran_id;
- guint8 r;
- guint8 opcode;
- struct {
- guint8 bcast;
- guint8 recursion_available;
- guint8 recursion_desired;
- guint8 trunc;
- guint8 authoritative;
- } nm_flags;
- guint8 rcode;
- guint16 qdcount;
- guint16 ancount;
- guint16 nscount;
- guint16 arcount;
-};
+/* Length of NBNS header. */
+#define NBNS_HDRLEN 12
/* type values */
#define T_NB 32 /* NetBIOS name service RR */
@@ -92,6 +87,35 @@ struct nbdgm_header {
guint8 error_code;
};
+/* Bit fields in the flags */
+#define F_RESPONSE (1<<15) /* packet is response */
+#define F_OPCODE (0xF<<11) /* query opcode */
+#define F_AUTHORITATIVE (1<<10) /* response is authoritative */
+#define F_TRUNCATED (1<<9) /* response is truncated */
+#define F_RECDESIRED (1<<8) /* recursion desired */
+#define F_RECAVAIL (1<<7) /* recursion available */
+#define F_BROADCAST (1<<4) /* broadcast/multicast packet */
+#define F_RCODE (0xF<<0) /* reply code */
+
+/* Opcodes */
+#define OPCODE_QUERY (0<<11) /* standard query */
+#define OPCODE_REGISTRATION (5<<11) /* registration */
+#define OPCODE_RELEASE (6<<11) /* release name */
+#define OPCODE_WACK (7<<11) /* wait for acknowledgement */
+#define OPCODE_REFRESH (8<<11) /* refresh registration */
+#define OPCODE_REFRESHALT (9<<11) /* refresh registration (alternate opcode) */
+#define OPCODE_MHREGISTRATION (15<<11) /* multi-homed registration */
+
+/* Reply codes */
+#define RCODE_NOERROR (0<<0)
+#define RCODE_FMTERROR (1<<0)
+#define RCODE_SERVFAIL (2<<0)
+#define RCODE_NAMEERROR (3<<0)
+#define RCODE_NOTIMPL (4<<0)
+#define RCODE_REFUSED (5<<0)
+#define RCODE_ACTIVE (6<<0)
+#define RCODE_CONFLICT (7<<0)
+
static char *
nbns_type_name (int type)
@@ -327,7 +351,7 @@ dissect_nbns_answer(const u_char *nbns_data_ptr, const u_char *pd, int offset,
name_len, type_name, class_name, ttl, data_len);
offset += (dptr - data_start);
while (data_len > 0) {
- if (opcode == 0x7) {
+ if (opcode == OPCODE_WACK) {
/* WACK response. This doesn't contain the
* same type of RR data as other T_NB
* responses. */
@@ -678,61 +702,50 @@ dissect_answer_records(const u_char *nbns_data_ptr, int count,
void
dissect_nbns(const u_char *pd, int offset, frame_data *fd, GtkTree *tree)
{
- GtkWidget *nbns_tree, *ti;
- struct nbns_header header;
- int nm_flags;
const u_char *nbns_data_ptr;
+ GtkWidget *nbns_tree, *ti, *field_tree, *tf;
+ guint16 id, flags, quest, ans, auth, add;
+ char buf[128+1];
int cur_off;
-
- char *opcode[] = {
- "Query",
- "Unknown operation (1)",
- "Unknown operation (2)",
- "Unknown operation (3)",
- "Unknown operation (4)",
- "Registration",
- "Release",
- "Wait and Acknowledge",
- "Refresh",
- "Refresh(altcode)",
- "Unknown operation (10)",
- "Unknown operation (11)",
- "Unknown operation (12)",
- "Unknown operation (13)",
- "Unknown operation (14)",
- "Multi-Homed Registration",
+ static const value_string opcode_vals[] = {
+ { OPCODE_QUERY, "Name query" },
+ { OPCODE_REGISTRATION, "Registration" },
+ { OPCODE_RELEASE, "Release" },
+ { OPCODE_WACK, "Wait for acknowledgment" },
+ { OPCODE_REFRESH, "Refresh" },
+ { OPCODE_REFRESHALT, "Refresh (alternate opcode)" },
+ { OPCODE_MHREGISTRATION, "Multi-homed registration" },
+ { 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" },
+ { RCODE_ACTIVE, "Name is active" },
+ { RCODE_CONFLICT, "Name is in conflict" },
+ { 0, NULL }
};
nbns_data_ptr = &pd[offset];
- /* This is taken from samba/source/nmlib.c, parse_nmb() */
- header.name_tran_id = pntohs(&pd[offset]);
- header.opcode = (pd[offset+2] >> 3) & 0xf;
- header.r = (pd[offset+2] >> 7) & 1;
-
- nm_flags = ((pd[offset+2] & 0x7) << 4) + (pd[offset+3] >> 4);
- header.nm_flags.bcast = (nm_flags & 1) ? 1 : 0;
- header.nm_flags.recursion_available = (nm_flags & 8) ? 1 : 0;
- header.nm_flags.recursion_desired = (nm_flags & 0x10) ? 1 : 0;
- header.nm_flags.trunc = (nm_flags & 0x20) ? 1 : 0;
- header.nm_flags.authoritative = (nm_flags & 0x40) ? 1 : 0;
-
- header.rcode = pd[offset+3] & 0xf;
- header.qdcount = pntohs(&pd[offset+4]);
- header.ancount = pntohs(&pd[offset+6]);
- header.nscount = pntohs(&pd[offset+8]);
- header.arcount = pntohs(&pd[offset+10]);
+ /* To do: check for runts, errs, etc. */
+ id = pntohs(&pd[offset + NBNS_ID]);
+ flags = pntohs(&pd[offset + NBNS_FLAGS]);
+ quest = pntohs(&pd[offset + NBNS_QUEST]);
+ ans = pntohs(&pd[offset + NBNS_ANS]);
+ auth = pntohs(&pd[offset + NBNS_AUTH]);
+ add = pntohs(&pd[offset + NBNS_ADD]);
if (check_col(fd, COL_PROTOCOL))
col_add_str(fd, COL_PROTOCOL, "NBNS (UDP)");
if (check_col(fd, COL_INFO)) {
- if (header.opcode <= 15) {
- col_add_fstr(fd, COL_INFO, "%s %s",
- opcode[header.opcode], header.r ? "reply" : "request");
- } else {
- col_add_fstr(fd, COL_INFO, "Unknown operation (%d) %s",
- header.opcode, header.r ? "reply" : "request");
- }
+ col_add_fstr(fd, COL_INFO, "%s%s",
+ val_to_str(flags & F_OPCODE, opcode_vals,
+ "Unknown operation (%x)"),
+ (flags & F_RESPONSE) ? " response" : "");
}
if (tree) {
@@ -741,49 +754,101 @@ dissect_nbns(const u_char *pd, int offset, frame_data *fd, GtkTree *tree)
nbns_tree = gtk_tree_new();
add_subtree(ti, nbns_tree, ETT_NBNS);
- add_item_to_tree(nbns_tree, offset, 2, "Transaction ID: 0x%04X",
- header.name_tran_id);
- add_item_to_tree(nbns_tree, offset + 2, 1, "Type: %s",
- header.r == 0 ? "Request" : "Response" );
-
- if (header.opcode <= 15) {
- add_item_to_tree(nbns_tree, offset + 2, 1, "Operation: %s (%d)",
- opcode[header.opcode], header.opcode);
+ add_item_to_tree(nbns_tree, offset + NBNS_ID, 2,
+ "Transaction ID: 0x%04X", id);
+
+ strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals,
+ "Unknown (%x)"));
+ if (flags & F_RESPONSE) {
+ strcat(buf, " response");
+ strcat(buf, ", ");
+ strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
+ "Unknown error (%x)"));
+ }
+ tf = add_item_to_tree(nbns_tree, offset + NBNS_FLAGS, 2,
+ "Flags: 0x%04x (%s)", flags, buf);
+ field_tree = gtk_tree_new();
+ add_subtree(tf, field_tree, ETT_NBNS_FLAGS);
+ add_item_to_tree(field_tree, offset + NBNS_FLAGS, 2, "%s",
+ decode_boolean_bitfield(flags, F_RESPONSE,
+ 2*8, "Response", "Query"));
+ add_item_to_tree(field_tree, offset + NBNS_FLAGS, 2, "%s",
+ decode_enumerated_bitfield(flags, F_OPCODE,
+ 2*8, opcode_vals, "%s"));
+ if (flags & F_RESPONSE) {
+ add_item_to_tree(field_tree, offset + NBNS_FLAGS, 2,
+ "%s",
+ decode_boolean_bitfield(flags, F_AUTHORITATIVE,
+ 2*8,
+ "Server is an authority for domain",
+ "Server isn't an authority for domain"));
+ }
+ add_item_to_tree(field_tree, offset + NBNS_FLAGS, 2, "%s",
+ decode_boolean_bitfield(flags, F_TRUNCATED,
+ 2*8,
+ "Message is truncated",
+ "Message is not truncated"));
+ add_item_to_tree(field_tree, offset + NBNS_FLAGS, 2, "%s",
+ decode_boolean_bitfield(flags, F_RECDESIRED,
+ 2*8,
+ "Do query recursively",
+ "Don't do query recursively"));
+ if (flags & F_RESPONSE) {
+ add_item_to_tree(field_tree, offset + NBNS_FLAGS, 2,
+ "%s",
+ decode_boolean_bitfield(flags, F_RECAVAIL,
+ 2*8,
+ "Server can do recursive queries",
+ "Server can't do recursive queries"));
}
- else {
- add_item_to_tree(nbns_tree, offset + 2, 1, "Operation: Unknown (%d)",
- header.opcode);
+ add_item_to_tree(field_tree, offset + NBNS_FLAGS, 2, "%s",
+ decode_boolean_bitfield(flags, F_BROADCAST,
+ 2*8,
+ "Broadcast packet",
+ "Not a broadcast packet"));
+ if (flags & F_RESPONSE) {
+ add_item_to_tree(field_tree, offset + NBNS_FLAGS, 2,
+ "%s",
+ decode_enumerated_bitfield(flags, F_RCODE,
+ 2*8,
+ rcode_vals, "%s"));
}
- add_item_to_tree(nbns_tree, offset + 4, 2, "Questions: %d",
- header.qdcount);
- add_item_to_tree(nbns_tree, offset + 6, 2, "Answer RRs: %d",
- header.ancount);
- add_item_to_tree(nbns_tree, offset + 8, 2, "Authority RRs: %d",
- header.nscount);
- add_item_to_tree(nbns_tree, offset + 10, 2, "Additional RRs: %d",
- header.arcount);
-
- cur_off = offset + 12;
+ add_item_to_tree(nbns_tree, offset + NBNS_QUEST, 2,
+ "Questions: %d",
+ quest);
+ add_item_to_tree(nbns_tree, offset + NBNS_ANS, 2,
+ "Answer RRs: %d",
+ ans);
+ add_item_to_tree(nbns_tree, offset + NBNS_AUTH, 2,
+ "Authority RRs: %d",
+ auth);
+ add_item_to_tree(nbns_tree, offset + NBNS_ADD, 2,
+ "Additional RRs: %d",
+ add);
+
+ cur_off = offset + NBNS_HDRLEN;
- if (header.qdcount > 0)
+ if (quest > 0)
cur_off += dissect_query_records(nbns_data_ptr,
- header.qdcount, pd, cur_off, nbns_tree);
+ quest, pd, cur_off, nbns_tree);
- if (header.ancount > 0)
+ if (ans > 0)
cur_off += dissect_answer_records(nbns_data_ptr,
- header.ancount, pd, cur_off, nbns_tree,
- header.opcode, "Answers");
+ ans, pd, cur_off, nbns_tree,
+ flags & F_OPCODE,
+ "Answers");
- if (header.nscount > 0)
+ if (auth > 0)
cur_off += dissect_answer_records(nbns_data_ptr,
- header.nscount, pd, cur_off, nbns_tree,
- header.opcode,
+ auth, pd, cur_off, nbns_tree,
+ flags & F_OPCODE,
"Authoritative nameservers");
- if (header.arcount > 0)
+ if (add > 0)
cur_off += dissect_answer_records(nbns_data_ptr,
- header.arcount, pd, cur_off, nbns_tree,
- header.opcode, "Additional records");
+ add, pd, cur_off, nbns_tree,
+ flags & F_OPCODE,
+ "Additional records");
}
}
diff --git a/packet.h b/packet.h
index 90193e05dc..7275b2b1fb 100644
--- a/packet.h
+++ b/packet.h
@@ -1,7 +1,7 @@
/* packet.h
* Definitions for packet disassembly structures and routines
*
- * $Id: packet.h,v 1.30 1999/01/02 06:10:54 gram Exp $
+ * $Id: packet.h,v 1.31 1999/01/04 09:13:45 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -412,6 +412,7 @@ enum {
ETT_SPX,
ETT_NCP,
ETT_DNS,
+ ETT_DNS_FLAGS,
ETT_DNS_QRY,
ETT_DNS_QD,
ETT_DNS_ANS,
@@ -443,6 +444,7 @@ enum {
ETT_IPXSAP,
ETT_IPXSAP_SERVER,
ETT_NBNS,
+ ETT_NBNS_FLAGS,
ETT_NBNS_QRY,
ETT_NBNS_QD,
ETT_NBNS_ANS,