2 * Routines for NetBIOS Name Service packet disassembly
3 * Gilbert Ramirez <gram@verdict.uthscsa.edu>
4 * Much stuff added by Guy Harris <guy@netapp.com>
6 * $Id: packet-nbns.c,v 1.12 1999/01/05 08:48:39 guy Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@zing.org>
10 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 #ifdef HAVE_SYS_TYPES_H
39 # include <sys/types.h>
42 #ifdef HAVE_NETINET_IN_H
43 # include <netinet/in.h>
48 #include "packet-dns.h"
51 /* Packet structure taken from RFC 1002. See also RFC 1001.
52 * Opcode, flags, and rcode treated as "flags", similarly to DNS,
53 * to make it easier to lift the dissection code from "packet-dns.c". */
55 /* Offsets of fields in the NBNS header. */
63 /* Length of NBNS header. */
64 #define NBNS_HDRLEN 12
67 #define T_NB 32 /* NetBIOS name service RR */
68 #define T_NBSTAT 33 /* NetBIOS node status RR */
70 /* NetBIOS datagram packet, from RFC 1002, page 32 */
82 /* For packets with data */
86 /* For error packets */
90 /* Bit fields in the flags */
91 #define F_RESPONSE (1<<15) /* packet is response */
92 #define F_OPCODE (0xF<<11) /* query opcode */
93 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
94 #define F_TRUNCATED (1<<9) /* response is truncated */
95 #define F_RECDESIRED (1<<8) /* recursion desired */
96 #define F_RECAVAIL (1<<7) /* recursion available */
97 #define F_BROADCAST (1<<4) /* broadcast/multicast packet */
98 #define F_RCODE (0xF<<0) /* reply code */
101 #define OPCODE_QUERY (0<<11) /* standard query */
102 #define OPCODE_REGISTRATION (5<<11) /* registration */
103 #define OPCODE_RELEASE (6<<11) /* release name */
104 #define OPCODE_WACK (7<<11) /* wait for acknowledgement */
105 #define OPCODE_REFRESH (8<<11) /* refresh registration */
106 #define OPCODE_REFRESHALT (9<<11) /* refresh registration (alternate opcode) */
107 #define OPCODE_MHREGISTRATION (15<<11) /* multi-homed registration */
110 #define RCODE_NOERROR (0<<0)
111 #define RCODE_FMTERROR (1<<0)
112 #define RCODE_SERVFAIL (2<<0)
113 #define RCODE_NAMEERROR (3<<0)
114 #define RCODE_NOTIMPL (4<<0)
115 #define RCODE_REFUSED (5<<0)
116 #define RCODE_ACTIVE (6<<0)
117 #define RCODE_CONFLICT (7<<0)
119 /* Values for the "NB_FLAGS" field of RR data. From RFC 1001 and 1002,
120 * except for NB_FLAGS_ONT_H_NODE, which was discovered by looking at
122 #define NB_FLAGS_ONT (3<<(15-2)) /* bits for node type */
123 #define NB_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
124 #define NB_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
125 #define NB_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
126 #define NB_FLAGS_ONT_H_NODE (3<<(15-2)) /* H-mode node */
128 #define NB_FLAGS_G (1<<(15-0)) /* group name */
130 /* Values for the "NAME_FLAGS" field of a NODE_NAME entry in T_NBSTAT
131 * RR data. From RFC 1001 and 1002, except for NAME_FLAGS_ONT_H_NODE,
132 * which was discovered by looking at packet traces. */
133 #define NAME_FLAGS_PRM (1<<(15-6)) /* name is permanent node name */
135 #define NAME_FLAGS_ACT (1<<(15-5)) /* name is active */
137 #define NAME_FLAGS_CNF (1<<(15-4)) /* name is in conflict */
139 #define NAME_FLAGS_DRG (1<<(15-3)) /* name is being deregistered */
141 #define NAME_FLAGS_ONT (3<<(15-2)) /* bits for node type */
142 #define NAME_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
143 #define NAME_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
144 #define NAME_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
146 #define NAME_FLAGS_G (1<<(15-0)) /* group name */
148 static const value_string opcode_vals[] = {
149 { OPCODE_QUERY, "Name query" },
150 { OPCODE_REGISTRATION, "Registration" },
151 { OPCODE_RELEASE, "Release" },
152 { OPCODE_WACK, "Wait for acknowledgment" },
153 { OPCODE_REFRESH, "Refresh" },
154 { OPCODE_REFRESHALT, "Refresh (alternate opcode)" },
155 { OPCODE_MHREGISTRATION, "Multi-homed registration" },
160 nbns_type_name (int type)
172 /* "Canonicalize" a 16-character NetBIOS name by:
174 * removing and saving the last byte;
176 * stripping trailing blanks;
178 * appending the trailing byte, as a hex number, in square brackets. */
180 canonicalize_netbios_name(char *nbname)
185 /* Get the last character of the name, as it's a special number
186 * indicating the type of the name, rather than part of the name
188 pnbname = nbname + 15; /* point to the 16th character */
189 lastchar = *(unsigned char *)pnbname;
191 /* Now strip off any trailing blanks used to pad it to
193 while (pnbname > &nbname[0]) {
194 if (*(pnbname - 1) != ' ')
195 break; /* found non-blank character */
196 pnbname--; /* blank - skip over it */
199 /* Replace the last character with its hex value, in square
200 * brackets, to make it easier to tell what it is. */
201 sprintf(pnbname, "[%02X]", lastchar);
207 get_nbns_name(const u_char *nbns_data_ptr, const u_char *pd,
208 int offset, char *name_ret)
212 char nbname[MAXDNAME+4]; /* 4 for [<last char>] */
213 char *pname, *pnbname, cname, cnbname;
215 name_len = get_dns_name(nbns_data_ptr, pd, offset, name, sizeof(name));
217 /* OK, now undo the first-level encoding. */
219 pnbname = &nbname[0];
221 /* Every two characters of the first level-encoded name
222 * turn into one character in the decoded name. */
225 break; /* no more characters */
227 break; /* scope ID follows */
228 if (cname < 'A' || cname > 'Z') {
231 "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
235 cnbname = cname << 4;
239 if (cname == '\0' || cname == '.') {
240 /* No more characters in the name - but we're in
241 * the middle of a pair. Not legal. */
243 "Illegal NetBIOS name (odd number of bytes)");
246 if (cname < 'A' || cname > 'Z') {
249 "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
256 /* Store the character. */
257 *pnbname++ = cnbname;
260 /* NetBIOS names are supposed to be exactly 16 bytes long. */
261 if (pnbname - nbname == 16) {
262 /* This one is; canonicalize its name. */
263 pnbname = canonicalize_netbios_name(nbname);
265 sprintf(nbname, "Illegal NetBIOS name (%ld bytes long)",
266 (long)(pnbname - nbname));
270 /* We have a scope ID, starting at "pname"; append that to
271 * the decoded host name. */
272 strcpy(pnbname, pname);
274 /* Terminate the decoded host name. */
279 strcpy (name_ret, nbname);
285 get_nbns_name_type_class(const u_char *nbns_data_ptr, const u_char *pd,
286 int offset, char *name_ret, int *name_len_ret, int *type_ret,
293 name_len = get_nbns_name(nbns_data_ptr, pd, offset, name_ret);
296 type = pntohs(&pd[offset]);
298 class = pntohs(&pd[offset]);
302 *name_len_ret = name_len;
309 dissect_nbns_query(const u_char *nbns_data_ptr, const u_char *pd, int offset,
310 GtkWidget *nbns_tree)
320 const u_char *data_start;
321 GtkWidget *q_tree, *tq;
323 data_start = dptr = pd + offset;
325 len = get_nbns_name_type_class(nbns_data_ptr, pd, offset, name,
326 &name_len, &type, &class);
329 type_name = nbns_type_name(type);
330 class_name = dns_class_name(class);
332 tq = add_item_to_tree(nbns_tree, offset, len, "%s: type %s, class %s",
333 name, type_name, class_name);
334 q_tree = gtk_tree_new();
335 add_subtree(tq, q_tree, ETT_NBNS_QD);
337 add_item_to_tree(q_tree, offset, name_len, "Name: %s", name);
340 add_item_to_tree(q_tree, offset, 2, "Type: %s", type_name);
343 add_item_to_tree(q_tree, offset, 2, "Class: %s", class_name);
346 return dptr - data_start;
350 nbns_add_nbns_flags(GtkWidget *nbns_tree, int offset, u_short flags,
354 GtkWidget *field_tree, *tf;
355 static const value_string rcode_vals[] = {
356 { RCODE_NOERROR, "No error" },
357 { RCODE_FMTERROR, "Format error" },
358 { RCODE_SERVFAIL, "Server failure" },
359 { RCODE_NAMEERROR, "Name error" },
360 { RCODE_NOTIMPL, "Not implemented" },
361 { RCODE_REFUSED, "Refused" },
362 { RCODE_ACTIVE, "Name is active" },
363 { RCODE_CONFLICT, "Name is in conflict" },
367 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals,
369 if (flags & F_RESPONSE && !is_wack) {
370 strcat(buf, " response");
372 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
373 "Unknown error (%x)"));
375 tf = add_item_to_tree(nbns_tree, offset, 2,
376 "Flags: 0x%04x (%s)", flags, buf);
377 field_tree = gtk_tree_new();
378 add_subtree(tf, field_tree, ETT_NBNS_FLAGS);
379 add_item_to_tree(field_tree, offset, 2, "%s",
380 decode_boolean_bitfield(flags, F_RESPONSE,
381 2*8, "Response", "Query"));
382 add_item_to_tree(field_tree, offset, 2, "%s",
383 decode_enumerated_bitfield(flags, F_OPCODE,
384 2*8, opcode_vals, "%s"));
385 if (flags & F_RESPONSE) {
386 add_item_to_tree(field_tree, offset, 2,
388 decode_boolean_bitfield(flags, F_AUTHORITATIVE,
390 "Server is an authority for domain",
391 "Server isn't an authority for domain"));
393 add_item_to_tree(field_tree, offset, 2, "%s",
394 decode_boolean_bitfield(flags, F_TRUNCATED,
396 "Message is truncated",
397 "Message is not truncated"));
398 add_item_to_tree(field_tree, offset, 2, "%s",
399 decode_boolean_bitfield(flags, F_RECDESIRED,
401 "Do query recursively",
402 "Don't do query recursively"));
403 if (flags & F_RESPONSE) {
404 add_item_to_tree(field_tree, offset, 2,
406 decode_boolean_bitfield(flags, F_RECAVAIL,
408 "Server can do recursive queries",
409 "Server can't do recursive queries"));
411 add_item_to_tree(field_tree, offset, 2, "%s",
412 decode_boolean_bitfield(flags, F_BROADCAST,
415 "Not a broadcast packet"));
416 if (flags & F_RESPONSE && !is_wack) {
417 add_item_to_tree(field_tree, offset, 2,
419 decode_enumerated_bitfield(flags, F_RCODE,
426 nbns_add_nb_flags(GtkWidget *rr_tree, int offset, u_short flags)
429 GtkWidget *field_tree, *tf;
430 static const value_string nb_flags_ont_vals[] = {
431 { NB_FLAGS_ONT_B_NODE, "B-node" },
432 { NB_FLAGS_ONT_P_NODE, "P-node" },
433 { NB_FLAGS_ONT_M_NODE, "M-node" },
434 { NB_FLAGS_ONT_H_NODE, "H-node" },
438 strcpy(buf, val_to_str(flags & NB_FLAGS_ONT, nb_flags_ont_vals,
441 if (flags & NB_FLAGS_G)
442 strcat(buf, "group");
444 strcat(buf, "unique");
445 tf = add_item_to_tree(rr_tree, offset, 2, "Flags: 0x%x (%s)", flags,
447 field_tree = gtk_tree_new();
448 add_subtree(tf, field_tree, ETT_NBNS_NB_FLAGS);
449 add_item_to_tree(field_tree, offset, 2, "%s",
450 decode_boolean_bitfield(flags, NB_FLAGS_G,
454 add_item_to_tree(field_tree, offset, 2, "%s",
455 decode_enumerated_bitfield(flags, NB_FLAGS_ONT,
456 2*8, nb_flags_ont_vals, "%s"));
460 nbns_add_name_flags(GtkWidget *rr_tree, int offset, u_short flags)
463 GtkWidget *field_tree, *tf;
464 static const value_string name_flags_ont_vals[] = {
465 { NAME_FLAGS_ONT_B_NODE, "B-node" },
466 { NAME_FLAGS_ONT_P_NODE, "P-node" },
467 { NAME_FLAGS_ONT_M_NODE, "M-node" },
471 strcpy(buf, val_to_str(flags & NAME_FLAGS_ONT, name_flags_ont_vals,
474 if (flags & NAME_FLAGS_G)
475 strcat(buf, "group");
477 strcat(buf, "unique");
478 if (flags & NAME_FLAGS_DRG)
479 strcat(buf, ", being deregistered");
480 if (flags & NAME_FLAGS_CNF)
481 strcat(buf, ", in conflict");
482 if (flags & NAME_FLAGS_ACT)
483 strcat(buf, ", active");
484 if (flags & NAME_FLAGS_PRM)
485 strcat(buf, ", permanent node name");
486 tf = add_item_to_tree(rr_tree, offset, 2, "Name flags: 0x%x (%s)",
488 field_tree = gtk_tree_new();
489 add_subtree(tf, field_tree, ETT_NBNS_NAME_FLAGS);
490 add_item_to_tree(field_tree, offset, 2, "%s",
491 decode_boolean_bitfield(flags, NAME_FLAGS_G,
495 add_item_to_tree(field_tree, offset, 2, "%s",
496 decode_enumerated_bitfield(flags, NAME_FLAGS_ONT,
497 2*8, name_flags_ont_vals, "%s"));
498 add_item_to_tree(field_tree, offset, 2, "%s",
499 decode_boolean_bitfield(flags, NAME_FLAGS_DRG,
501 "Name is being deregistered",
502 "Name is not being deregistered"));
503 add_item_to_tree(field_tree, offset, 2, "%s",
504 decode_boolean_bitfield(flags, NAME_FLAGS_CNF,
506 "Name is in conflict",
507 "Name is not in conflict"));
508 add_item_to_tree(field_tree, offset, 2, "%s",
509 decode_boolean_bitfield(flags, NAME_FLAGS_ACT,
512 "Name is not active"));
513 add_item_to_tree(field_tree, offset, 2, "%s",
514 decode_boolean_bitfield(flags, NAME_FLAGS_PRM,
516 "Permanent node name",
517 "Not permanent node name"));
521 dissect_nbns_answer(const u_char *nbns_data_ptr, const u_char *pd, int offset,
522 GtkWidget *nbns_tree, int opcode)
532 const u_char *data_start;
536 GtkWidget *rr_tree, *trr;
538 data_start = dptr = pd + offset;
540 len = get_nbns_name_type_class(nbns_data_ptr, pd, offset, name,
541 &name_len, &type, &class);
544 type_name = nbns_type_name(type);
545 class_name = dns_class_name(class);
550 data_len = pntohs(dptr);
554 case T_NB: /* "NB" record */
555 trr = add_item_to_tree(nbns_tree, offset,
556 (dptr - data_start) + data_len,
557 "%s: type %s, class %s",
558 name, type_name, class_name);
559 rr_tree = add_rr_to_tree(trr, ETT_NBNS_RR, offset, name,
560 name_len, type_name, class_name, ttl, data_len);
561 offset += (dptr - data_start);
562 while (data_len > 0) {
563 if (opcode == OPCODE_WACK) {
564 /* WACK response. This doesn't contain the
565 * same type of RR data as other T_NB
568 add_item_to_tree(rr_tree, offset,
569 data_len, "(incomplete entry)");
572 flags = pntohs(dptr);
574 nbns_add_nbns_flags(rr_tree, offset, flags, 1);
579 add_item_to_tree(rr_tree, offset,
580 data_len, "(incomplete entry)");
583 flags = pntohs(dptr);
585 nbns_add_nb_flags(rr_tree, offset, flags);
590 add_item_to_tree(rr_tree, offset,
591 data_len, "(incomplete entry)");
594 add_item_to_tree(rr_tree, offset, 4,
596 ip_to_str((guint8 *)dptr));
604 case T_NBSTAT: /* "NBSTAT" record */
607 char nbname[16+4+1]; /* 4 for [<last char>] */
610 trr = add_item_to_tree(nbns_tree, offset,
611 (dptr - data_start) + data_len,
612 "%s: type %s, class %s",
613 name, type_name, class_name);
614 rr_tree = add_rr_to_tree(trr, ETT_NBNS_RR, offset, name,
615 name_len, type_name, class_name, ttl, data_len);
616 offset += (dptr - data_start);
618 add_item_to_tree(rr_tree, offset,
619 data_len, "(incomplete entry)");
624 add_item_to_tree(rr_tree, offset, 2,
625 "Number of names: %u", num_names);
628 while (num_names != 0) {
630 add_item_to_tree(rr_tree, offset,
631 data_len, "(incomplete entry)");
634 memcpy(nbname, dptr, 16);
636 canonicalize_netbios_name(nbname);
637 add_item_to_tree(rr_tree, offset, 16,
643 add_item_to_tree(rr_tree, offset,
644 data_len, "(incomplete entry)");
647 name_flags = pntohs(dptr);
649 nbns_add_name_flags(rr_tree, offset, name_flags);
657 add_item_to_tree(rr_tree, offset,
658 data_len, "(incomplete entry)");
661 add_item_to_tree(rr_tree, offset, 6,
663 ether_to_str((guint8 *)dptr));
669 add_item_to_tree(rr_tree, offset,
670 data_len, "(incomplete entry)");
673 add_item_to_tree(rr_tree, offset, 1,
674 "Jumpers: 0x%x", *dptr);
680 add_item_to_tree(rr_tree, offset,
681 data_len, "(incomplete entry)");
684 add_item_to_tree(rr_tree, offset, 1,
685 "Test result: 0x%x", *dptr);
691 add_item_to_tree(rr_tree, offset,
692 data_len, "(incomplete entry)");
695 add_item_to_tree(rr_tree, offset, 2,
696 "Version number: 0x%x", pntohs(dptr));
702 add_item_to_tree(rr_tree, offset,
703 data_len, "(incomplete entry)");
706 add_item_to_tree(rr_tree, offset, 2,
707 "Period of statistics: 0x%x", pntohs(dptr));
713 add_item_to_tree(rr_tree, offset,
714 data_len, "(incomplete entry)");
717 add_item_to_tree(rr_tree, offset, 2,
718 "Number of CRCs: %u", pntohs(dptr));
724 add_item_to_tree(rr_tree, offset,
725 data_len, "(incomplete entry)");
728 add_item_to_tree(rr_tree, offset, 2,
729 "Number of alignment errors: %u", pntohs(dptr));
735 add_item_to_tree(rr_tree, offset,
736 data_len, "(incomplete entry)");
739 add_item_to_tree(rr_tree, offset, 2,
740 "Number of collisions: %u", pntohs(dptr));
746 add_item_to_tree(rr_tree, offset,
747 data_len, "(incomplete entry)");
750 add_item_to_tree(rr_tree, offset, 2,
751 "Number of send aborts: %u", pntohs(dptr));
757 add_item_to_tree(rr_tree, offset,
758 data_len, "(incomplete entry)");
761 add_item_to_tree(rr_tree, offset, 4,
762 "Number of good sends: %u", pntohl(dptr));
768 add_item_to_tree(rr_tree, offset,
769 data_len, "(incomplete entry)");
772 add_item_to_tree(rr_tree, offset, 4,
773 "Number of good receives: %u", pntohl(dptr));
779 add_item_to_tree(rr_tree, offset,
780 data_len, "(incomplete entry)");
783 add_item_to_tree(rr_tree, offset, 2,
784 "Number of retransmits: %u", pntohs(dptr));
790 add_item_to_tree(rr_tree, offset,
791 data_len, "(incomplete entry)");
794 add_item_to_tree(rr_tree, offset, 2,
795 "Number of no resource conditions: %u", pntohs(dptr));
801 add_item_to_tree(rr_tree, offset,
802 data_len, "(incomplete entry)");
805 add_item_to_tree(rr_tree, offset, 2,
806 "Number of command blocks: %u", pntohs(dptr));
812 add_item_to_tree(rr_tree, offset,
813 data_len, "(incomplete entry)");
816 add_item_to_tree(rr_tree, offset, 2,
817 "Number of pending sessions: %u", pntohs(dptr));
823 add_item_to_tree(rr_tree, offset,
824 data_len, "(incomplete entry)");
827 add_item_to_tree(rr_tree, offset, 2,
828 "Max number of pending sessions: %u", pntohs(dptr));
832 add_item_to_tree(rr_tree, offset, 2,
833 "Max total sessions possible: %u", pntohs(dptr));
839 add_item_to_tree(rr_tree, offset,
840 data_len, "(incomplete entry)");
843 add_item_to_tree(rr_tree, offset, 2,
844 "Session data packet size: %u", pntohs(dptr));
853 trr = add_item_to_tree(nbns_tree, offset,
854 (dptr - data_start) + data_len,
855 "%s: type %s, class %s",
856 name, type_name, class_name);
857 rr_tree = add_rr_to_tree(trr, ETT_NBNS_RR, offset, name,
858 name_len, type_name, class_name, ttl, data_len);
859 offset += (dptr - data_start);
860 add_item_to_tree(rr_tree, offset, data_len, "Data");
865 return dptr - data_start;
869 dissect_query_records(const u_char *nbns_data_ptr, int count, const u_char *pd,
870 int cur_off, GtkWidget *nbns_tree)
873 GtkWidget *qatree, *ti;
876 ti = add_item_to_tree(GTK_WIDGET(nbns_tree),
877 start_off, 0, "Queries");
878 qatree = gtk_tree_new();
879 add_subtree(ti, qatree, ETT_NBNS_QRY);
881 cur_off += dissect_nbns_query(nbns_data_ptr, pd, cur_off, qatree);
882 set_item_len(ti, cur_off - start_off);
884 return cur_off - start_off;
890 dissect_answer_records(const u_char *nbns_data_ptr, int count,
891 const u_char *pd, int cur_off, GtkWidget *nbns_tree, int opcode, char *name)
894 GtkWidget *qatree, *ti;
897 ti = add_item_to_tree(GTK_WIDGET(nbns_tree),
899 qatree = gtk_tree_new();
900 add_subtree(ti, qatree, ETT_NBNS_ANS);
902 cur_off += dissect_nbns_answer(nbns_data_ptr, pd, cur_off,
904 set_item_len(ti, cur_off - start_off);
905 return cur_off - start_off;
909 dissect_nbns(const u_char *pd, int offset, frame_data *fd, GtkTree *tree)
911 const u_char *nbns_data_ptr;
912 GtkWidget *nbns_tree, *ti;
913 guint16 id, flags, quest, ans, auth, add;
916 nbns_data_ptr = &pd[offset];
918 /* To do: check for runts, errs, etc. */
919 id = pntohs(&pd[offset + NBNS_ID]);
920 flags = pntohs(&pd[offset + NBNS_FLAGS]);
921 quest = pntohs(&pd[offset + NBNS_QUEST]);
922 ans = pntohs(&pd[offset + NBNS_ANS]);
923 auth = pntohs(&pd[offset + NBNS_AUTH]);
924 add = pntohs(&pd[offset + NBNS_ADD]);
926 if (check_col(fd, COL_PROTOCOL))
927 col_add_str(fd, COL_PROTOCOL, "NBNS (UDP)");
928 if (check_col(fd, COL_INFO)) {
929 col_add_fstr(fd, COL_INFO, "%s%s",
930 val_to_str(flags & F_OPCODE, opcode_vals,
931 "Unknown operation (%x)"),
932 (flags & F_RESPONSE) ? " response" : "");
936 ti = add_item_to_tree(GTK_WIDGET(tree), offset, END_OF_FRAME,
937 "NetBIOS Name Service");
938 nbns_tree = gtk_tree_new();
939 add_subtree(ti, nbns_tree, ETT_NBNS);
941 add_item_to_tree(nbns_tree, offset + NBNS_ID, 2,
942 "Transaction ID: 0x%04X", id);
944 nbns_add_nbns_flags(nbns_tree, offset + NBNS_FLAGS, flags, 0);
945 add_item_to_tree(nbns_tree, offset + NBNS_QUEST, 2,
948 add_item_to_tree(nbns_tree, offset + NBNS_ANS, 2,
951 add_item_to_tree(nbns_tree, offset + NBNS_AUTH, 2,
954 add_item_to_tree(nbns_tree, offset + NBNS_ADD, 2,
955 "Additional RRs: %d",
958 cur_off = offset + NBNS_HDRLEN;
961 cur_off += dissect_query_records(nbns_data_ptr,
962 quest, pd, cur_off, nbns_tree);
965 cur_off += dissect_answer_records(nbns_data_ptr,
966 ans, pd, cur_off, nbns_tree,
971 cur_off += dissect_answer_records(nbns_data_ptr,
972 auth, pd, cur_off, nbns_tree,
974 "Authoritative nameservers");
977 cur_off += dissect_answer_records(nbns_data_ptr,
978 add, pd, cur_off, nbns_tree,
980 "Additional records");
986 dissect_nbdgm(const u_char *pd, int offset, frame_data *fd, GtkTree *tree)
988 GtkWidget *nbdgm_tree, *ti;
989 struct nbdgm_header header;
995 "Direct_unique datagram",
996 "Direct_group datagram",
997 "Broadcast datagram",
999 "Datagram query request",
1000 "Datagram positive query response",
1001 "Datagram negative query response"
1011 static value_string error_codes[] = {
1012 { 0x82, "Destination name not present" },
1013 { 0x83, "Invalid source name format" },
1014 { 0x84, "Invalid destination name format" },
1018 char *yesno[] = { "No", "Yes" };
1023 header.msg_type = pd[offset];
1025 flags = pd[offset+1];
1026 header.flags.more = flags & 1;
1027 header.flags.first = (flags & 2) >> 1;
1028 header.flags.node_type = (flags & 12) >> 2;
1030 header.dgm_id = pntohs(&pd[offset+2]);
1031 memcpy(&header.src_ip, &pd[offset+4], 4);
1032 header.src_port = pntohs(&pd[offset+8]);
1034 if (header.msg_type == 0x10 ||
1035 header.msg_type == 0x11 || header.msg_type == 0x12) {
1036 header.dgm_length = pntohs(&pd[offset+10]);
1037 header.pkt_offset = pntohs(&pd[offset+12]);
1039 else if (header.msg_type == 0x13) {
1040 header.error_code = pntohs(&pd[offset+10]);
1043 message_index = header.msg_type - 0x0f;
1044 if (message_index < 1 || message_index > 8) {
1048 if (check_col(fd, COL_PROTOCOL))
1049 col_add_str(fd, COL_PROTOCOL, "NBDS (UDP)");
1050 if (check_col(fd, COL_INFO)) {
1051 col_add_fstr(fd, COL_INFO, "%s", message[message_index]);
1055 ti = add_item_to_tree(GTK_WIDGET(tree), offset, header.dgm_length,
1056 "NetBIOS Datagram Service");
1057 nbdgm_tree = gtk_tree_new();
1058 add_subtree(ti, nbdgm_tree, ETT_NBDGM);
1060 add_item_to_tree(nbdgm_tree, offset, 1, "Message Type: %s",
1061 message[message_index]);
1062 add_item_to_tree(nbdgm_tree, offset+1, 1, "More fragments follow: %s",
1063 yesno[header.flags.more]);
1064 add_item_to_tree(nbdgm_tree, offset+1, 1, "This is first fragment: %s",
1065 yesno[header.flags.first]);
1066 add_item_to_tree(nbdgm_tree, offset+1, 1, "Node Type: %s",
1067 node[header.flags.node_type]);
1069 add_item_to_tree(nbdgm_tree, offset+2, 2, "Datagram ID: 0x%04X",
1071 add_item_to_tree(nbdgm_tree, offset+4, 4, "Source IP: %s",
1072 ip_to_str((guint8 *)&header.src_ip));
1073 add_item_to_tree(nbdgm_tree, offset+8, 2, "Source Port: %d",
1078 if (header.msg_type == 0x10 ||
1079 header.msg_type == 0x11 || header.msg_type == 0x12) {
1081 add_item_to_tree(nbdgm_tree, offset, 2,
1082 "Datagram length: %d bytes", header.dgm_length);
1083 add_item_to_tree(nbdgm_tree, offset+2, 2,
1084 "Packet offset: %d bytes", header.pkt_offset);
1089 len = get_nbns_name(&pd[offset], pd, offset, name);
1091 add_item_to_tree(nbdgm_tree, offset, len, "Source name: %s",
1095 /* Destination name */
1096 len = get_nbns_name(&pd[offset], pd, offset, name);
1098 add_item_to_tree(nbdgm_tree, offset, len, "Destination name: %s",
1102 /* here we can pass the packet off to the next protocol */
1103 dissect_data(pd, offset, fd, GTK_TREE(nbdgm_tree));
1105 else if (header.msg_type == 0x13) {
1106 add_item_to_tree(nbdgm_tree, offset, 1, "Error code: %s",
1107 val_to_str(header.error_code, error_codes, "Unknown (0x%x)"));
1109 else if (header.msg_type == 0x14 ||
1110 header.msg_type == 0x15 || header.msg_type == 0x16) {
1111 /* Destination name */
1112 len = get_nbns_name(&pd[offset], pd, offset, name);
1114 add_item_to_tree(nbdgm_tree, offset, len, "Destination name: %s",