Home | History | Annotate | Download | only in snoop
      1     0  stevel /*
      2     0  stevel  * CDDL HEADER START
      3     0  stevel  *
      4     0  stevel  * The contents of this file are subject to the terms of the
      5  7280     blu  * Common Development and Distribution License (the "License").
      6  7280     blu  * You may not use this file except in compliance with the License.
      7     0  stevel  *
      8     0  stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9     0  stevel  * or http://www.opensolaris.org/os/licensing.
     10     0  stevel  * See the License for the specific language governing permissions
     11     0  stevel  * and limitations under the License.
     12     0  stevel  *
     13     0  stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14     0  stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15     0  stevel  * If applicable, add the following below this CDDL HEADER, with the
     16     0  stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17     0  stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18     0  stevel  *
     19     0  stevel  * CDDL HEADER END
     20     0  stevel  */
     21     0  stevel /*
     22  7280     blu  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23  7280     blu  * Use is subject to license terms.
     24     0  stevel  */
     25     0  stevel 
     26     0  stevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27     0  stevel 
     28     0  stevel /*
     29     0  stevel  * References used throughout this code:
     30     0  stevel  *
     31     0  stevel  * [RFC1001] :	PROTOCOL STANDARD FOR A NetBIOS SERVICE
     32     0  stevel  *			ON A TCP/UDP TRANSPORT:
     33     0  stevel  *			CONCEPTS AND METHODS
     34     0  stevel  *		NetBIOS Working Group, March 1987
     35     0  stevel  *
     36     0  stevel  * [RFC1002] :	PROTOCOL STANDARD FOR A NetBIOS SERVICE
     37     0  stevel  *			ON A TCP/UDP TRANSPORT:
     38     0  stevel  *			DETAILED SPECIFICATIONS
     39     0  stevel  *		NetBIOS Working Group, March 1987
     40     0  stevel  */
     41     0  stevel 
     42     0  stevel #include <fcntl.h>
     43     0  stevel #include "snoop.h"
     44     0  stevel #include <stdio.h>
     45     0  stevel #include <ctype.h>
     46     0  stevel #include "snoop.h"
     47     0  stevel 
     48     0  stevel extern char *dlc_header;
     49     0  stevel char *show_type();
     50     0  stevel 
     51     0  stevel /* See snoop_smb.c */
     52     0  stevel extern void interpret_smb(int flags, uchar_t *data, int len);
     53     0  stevel 
     54     0  stevel /*
     55     0  stevel  * NBT Session Packet Header
     56     0  stevel  * [RFC 1002, Sec. 4.3.1]
     57     0  stevel  */
     58     0  stevel struct nbt_ss {
     59     0  stevel 	uchar_t type;
     60     0  stevel 	uchar_t flags;
     61     0  stevel 	ushort_t length;
     62     0  stevel };
     63     0  stevel 
     64     0  stevel /*
     65     0  stevel  * NBT Session Request Packet trailer
     66     0  stevel  * [RFC 1002, Sec. 4.3.2]
     67     0  stevel  */
     68     0  stevel struct callnames {
     69     0  stevel 	uchar_t space;		/* padding */
     70     0  stevel 	uchar_t calledname[32];
     71     0  stevel 	uchar_t nullchar;		/* padding */
     72     0  stevel 	uchar_t space2;		/* padding */
     73     0  stevel 	uchar_t callingname[32];
     74     0  stevel 	uchar_t nullchar2;	/* padding */
     75     0  stevel };
     76     0  stevel 
     77     0  stevel 
     78     0  stevel static void interpret_netbios_names(int flags, uchar_t *data, int len,
     79     0  stevel 					char *xtra);
     80     0  stevel static void netbiosname2ascii(char *asciiname, uchar_t *netbiosname);
     81     0  stevel 
     82     0  stevel /*
     83     0  stevel  * Helpers to read network-order values,
     84     0  stevel  * with NO alignment assumed.
     85     0  stevel  */
     86     0  stevel static ushort_t
     87     0  stevel getshort(uchar_t *p) {
     88     0  stevel 	return (p[1] + (p[0]<<8));
     89     0  stevel }
     90     0  stevel static uint_t
     91     0  stevel getlong(uchar_t *p)
     92     0  stevel {
     93     0  stevel 	return (p[3] + (p[2]<<8) + (p[1]<<16) + (p[0]<<24));
     94     0  stevel }
     95     0  stevel 
     96     0  stevel /*
     97     0  stevel  * NM_FLAGS fields in the NetBIOS Name Service Packet header.
     98     0  stevel  * [RFC 1002,  Sec. 4.2.1.1]
     99     0  stevel  */
    100     0  stevel static void
    101     0  stevel print_flag_details(int headerflags)
    102     0  stevel {
    103     0  stevel 	if (headerflags & 1<<4)
    104     0  stevel 		sprintf(get_line(0, 0), "   - Broadcast");
    105     0  stevel 	if (headerflags & 1<<7)
    106     0  stevel 		sprintf(get_line(0, 0), "   - Recursion Available");
    107     0  stevel 	if (headerflags & 1<<8)
    108     0  stevel 		sprintf(get_line(0, 0), "   - Recursion Desired");
    109     0  stevel 	if (headerflags & 1<<9)
    110     0  stevel 		sprintf(get_line(0, 0), "   - Truncation Flag");
    111     0  stevel 	if (headerflags & 1<<10)
    112     0  stevel 		sprintf(get_line(0, 0), "   - Authoritative Answer");
    113     0  stevel }
    114     0  stevel 
    115     0  stevel /*
    116     0  stevel  * Possible errors in NetBIOS name service packets.
    117     0  stevel  * [RFC 1002,  Sec. 4.2.6, 4.2.11, 4.2.14]
    118     0  stevel  */
    119     0  stevel static void
    120     0  stevel getrcodeerr(int headerflags, char *errortype)
    121     0  stevel {
    122     0  stevel 	int error = (headerflags & 0xf);
    123     0  stevel 
    124     0  stevel 	switch (error) {
    125     0  stevel 	case 0:
    126     0  stevel 		sprintf(errortype, "Success");
    127     0  stevel 		break;
    128     0  stevel 	case 1:
    129     0  stevel 		sprintf(errortype, "Format Error");
    130     0  stevel 		break;
    131     0  stevel 	case 2:
    132     0  stevel 		sprintf(errortype, "Server Failure");
    133     0  stevel 		break;
    134     0  stevel 	case 3:
    135     0  stevel 		sprintf(errortype, "Name Error");
    136     0  stevel 		break;
    137     0  stevel 	case 4:
    138     0  stevel 		sprintf(errortype, "Unsupported Request Error");
    139     0  stevel 		break;
    140     0  stevel 	case 5:
    141     0  stevel 		sprintf(errortype, "Refused Error");
    142     0  stevel 		break;
    143     0  stevel 	case 6:
    144     0  stevel 		sprintf(errortype, "Active Error");
    145     0  stevel 		break;
    146     0  stevel 	case 7:
    147     0  stevel 		sprintf(errortype, "Name in Conflict Error");
    148     0  stevel 		break;
    149     0  stevel 	default:
    150     0  stevel 		sprintf(errortype, "Unknown Error");
    151     0  stevel 		break;
    152     0  stevel 	}
    153     0  stevel }
    154     0  stevel 
    155     0  stevel /*
    156     0  stevel  * OPCODE fields in the NetBIOS Name Service Packet header.
    157     0  stevel  * [RFC 1002, Sec. 4.2.1.1]
    158     0  stevel  */
    159     0  stevel static void
    160     0  stevel print_ns_type(int flags, int headerflags, char *xtra)
    161     0  stevel {
    162     0  stevel 	int opcode = (headerflags & 0x7800)>>11;
    163     0  stevel 	int response = (headerflags & 1<<15);
    164     0  stevel 	char *resptype = response ? "Response" : "Request";
    165     0  stevel 	char *optype;
    166     0  stevel 
    167     0  stevel 	switch (opcode) {
    168     0  stevel 	case 0:
    169     0  stevel 		optype = "Query";
    170     0  stevel 		break;
    171     0  stevel 	case 5:
    172     0  stevel 		optype = "Registration";
    173     0  stevel 		break;
    174     0  stevel 	case 6:
    175     0  stevel 		optype = "Release";
    176     0  stevel 		break;
    177     0  stevel 	case 7:
    178     0  stevel 		optype = "WACK";
    179     0  stevel 		break;
    180     0  stevel 	case 8:
    181     0  stevel 		optype = "Refresh";
    182     0  stevel 		break;
    183     0  stevel 	default:
    184     0  stevel 		optype = "Unknown";
    185     0  stevel 		break;
    186     0  stevel 	}
    187     0  stevel 
    188     0  stevel 	if (flags & F_DTAIL)
    189     0  stevel 		sprintf(get_line(0, 0), "Type = %s %s", optype, resptype);
    190     0  stevel 	else
    191     0  stevel 		sprintf(xtra, "%s %s", optype, resptype);
    192     0  stevel }
    193     0  stevel 
    194     0  stevel 
    195     0  stevel /*
    196     0  stevel  * Interpret Datagram Packets
    197     0  stevel  * [RFC 1002, Sec. 4.4]
    198     0  stevel  */
    199     0  stevel void
    200     0  stevel interpret_netbios_datagram(int flags, uchar_t *data, int len)
    201     0  stevel {
    202     0  stevel 	char name[24];
    203     0  stevel 	int packettype = data[0];
    204     0  stevel 	int packetlen;
    205     0  stevel 	data++;
    206     0  stevel 
    207     0  stevel 	if (packettype < 0x10 || packettype > 0x11)
    208     0  stevel 		return;
    209     0  stevel 
    210     0  stevel 	if (flags & F_SUM) {
    211     0  stevel 		data += 14;
    212     0  stevel 		netbiosname2ascii(name, data);
    213     0  stevel 		sprintf(get_sum_line(),
    214     0  stevel 				"NBT Datagram Service Type=%d Source=%s",
    215     0  stevel 				packettype, name);
    216     0  stevel 	}
    217     0  stevel 
    218     0  stevel 	if (flags & F_DTAIL) {
    219     0  stevel 		show_header("NBT:  ", "Netbios Datagram Service Header", len);
    220     0  stevel 		show_space();
    221     0  stevel 		sprintf(get_line(0, 0), "Datagram Packet Type = 0x%.2x",
    222     0  stevel 					packettype);
    223     0  stevel 		sprintf(get_line(0, 0), "Datagram Flags = 0x%.2x",
    224     0  stevel 					data[0]);
    225     0  stevel 		data++;
    226     0  stevel 		sprintf(get_line(0, 0), "Datagram ID = 0x%.4x",
    227     0  stevel 					getshort(data));
    228     0  stevel 		data += 2;
    229     0  stevel 		sprintf(get_line(0, 0), "Source IP = %d.%d.%d.%d",
    230     0  stevel 					data[0], data[1], data[2], data[3]);
    231     0  stevel 		data += 4;
    232     0  stevel 		sprintf(get_line(0, 0), "Source Port = %d",
    233     0  stevel 					getshort(data));
    234     0  stevel 		data += 2;
    235     0  stevel 		packetlen = getshort(data);
    236     0  stevel 		sprintf(get_line(0, 0), "Datagram Length = 0x%.4x",
    237     0  stevel 					packetlen);
    238     0  stevel 		data += 2;
    239     0  stevel 		sprintf(get_line(0, 0), "Packet Offset = 0x%.4x",
    240     0  stevel 					getshort(data));
    241     0  stevel 		data += 3;
    242     0  stevel 		netbiosname2ascii(name, data);
    243     0  stevel 		sprintf(get_line(0, 0), "Source Name = %s", name);
    244     0  stevel 		data += 34;
    245     0  stevel 		netbiosname2ascii(name, data);
    246     0  stevel 		sprintf(get_line(0, 0), "Destination Name = %s", name);
    247     0  stevel 		sprintf(get_line(0, 0), "Number of data bytes remaining = %d",
    248     0  stevel 					packetlen - 68);
    249     0  stevel 		show_trailer();
    250     0  stevel 	}
    251     0  stevel }
    252     0  stevel 
    253     0  stevel /*
    254     0  stevel  * Interpret NetBIOS Name Service packets.
    255     0  stevel  * [RFC 1002, Sec. 4.2]
    256     0  stevel  */
    257     0  stevel void
    258     0  stevel interpret_netbios_ns(int flags, uchar_t *data, int len)
    259     0  stevel {
    260     0  stevel 	int headerflags, qcount, acount, nscount, arcount;
    261     0  stevel 	int transid;
    262     0  stevel 	char name[24];
    263     0  stevel 	char extra[256];
    264     0  stevel 	char errortype[50];
    265     0  stevel 	int rdatalen;
    266     0  stevel 	int rrflags;
    267     0  stevel 	int nameptr;
    268     0  stevel 	int nodecode;
    269     0  stevel 	char *nodetype;
    270     0  stevel 	uchar_t *data0 = data;
    271     0  stevel 
    272     0  stevel 	transid = getshort(data); data += 2;
    273     0  stevel 	headerflags = getshort(data); data += 2;
    274     0  stevel 	qcount = getshort(data); data += 2;
    275     0  stevel 	acount = getshort(data); data += 2;
    276     0  stevel 	nscount = getshort(data); data += 2;
    277     0  stevel 	arcount = getshort(data); data += 2;
    278     0  stevel 	getrcodeerr(headerflags, errortype);
    279     0  stevel 
    280     0  stevel 	if (flags & F_SUM) {
    281     0  stevel 		print_ns_type(flags, headerflags, extra);
    282     0  stevel 		data++;
    283     0  stevel 		netbiosname2ascii(name, data);
    284     0  stevel 		sprintf(get_sum_line(), "NBT NS %s for %s, %s",
    285     0  stevel 			extra, name, errortype);
    286     0  stevel 
    287     0  stevel 	}
    288     0  stevel 
    289     0  stevel 
    290     0  stevel 	if (flags & F_DTAIL) {
    291     0  stevel 		show_header("NBT:  ", "Netbios Name Service Header", len);
    292     0  stevel 		show_space();
    293     0  stevel 		print_ns_type(flags, headerflags, 0);
    294     0  stevel 		sprintf(get_line(0, 0), "Status = %s", errortype);
    295     0  stevel 		sprintf(get_line(0, 0), "Transaction ID = 0x%.4x", transid);
    296     0  stevel 		sprintf(get_line(0, 0), "Flags Summary = 0x%.4x",
    297     0  stevel 					headerflags);
    298     0  stevel 		print_flag_details(headerflags);
    299     0  stevel 		sprintf(get_line(0, 0), "Question count = %d", qcount);
    300     0  stevel 		sprintf(get_line(0, 0), "Answer Count = %d", acount);
    301     0  stevel 		sprintf(get_line(0, 0), "Name Service Count = %d", nscount);
    302     0  stevel 		sprintf(get_line(0, 0),
    303     0  stevel 				"Additional Record Count = %d", arcount);
    304     0  stevel 
    305     0  stevel 		/*
    306     0  stevel 		 * Question Section Packet Description from
    307     0  stevel 		 * [RFC 1002, Sec. 4.2.1.2]
    308     0  stevel 		 */
    309     0  stevel 
    310     0  stevel 		if (qcount) {
    311     0  stevel 			data++;
    312     0  stevel 			netbiosname2ascii(name, data);
    313     0  stevel 			sprintf(get_line(0, 0), "Question Name = %s", name);
    314     0  stevel 			data += 33;
    315     0  stevel 			sprintf(get_line(0, 0), "Question Type = 0x%.4x",
    316     0  stevel 						getshort(data));
    317     0  stevel 			data += 2;
    318     0  stevel 			sprintf(get_line(0, 0), "Question Class = 0x%.4x",
    319     0  stevel 						getshort(data));
    320     0  stevel 			data += 2;
    321     0  stevel 		}
    322     0  stevel 
    323     0  stevel 		/*
    324     0  stevel 		 * Resrouce Record Packet Description from
    325     0  stevel 		 * [RFC 1002, Sec. 4.2.1.3]
    326     0  stevel 		 */
    327     0  stevel 
    328     0  stevel 		if ((acount || nscount || arcount) ||
    329     0  stevel 		    (qcount+acount+nscount+arcount == 0)) {
    330     0  stevel 			/* Second level encoding from RFC883 (p.31, 32) */
    331     0  stevel 			if (data[0] & 0xc0) {
    332     0  stevel 				nameptr = getshort(data)&0x3fff;
    333     0  stevel 				netbiosname2ascii(name, (data0+nameptr+1));
    334     0  stevel 				sprintf(get_line(0, 0),
    335     0  stevel 					"Resource Record Name = %s", name);
    336     0  stevel 				data += 2;
    337     0  stevel 			} else {
    338     0  stevel 				data++;
    339     0  stevel 				netbiosname2ascii(name, data);
    340     0  stevel 				sprintf(get_line(0, 0),
    341     0  stevel 					"Resource Record Name = %s", name);
    342     0  stevel 				data += 33;
    343     0  stevel 			}
    344     0  stevel 			sprintf(get_line(0, 0),
    345     0  stevel 					"Resource Record Type = 0x%.4x",
    346     0  stevel 					getshort(data));
    347     0  stevel 			data += 2;
    348     0  stevel 			sprintf(get_line(0, 0),
    349     0  stevel 					"Resource Record Class = 0x%.4x",
    350     0  stevel 					getshort(data));
    351     0  stevel 			data += 2;
    352     0  stevel 			sprintf(get_line(0, 0),
    353     0  stevel 				"Time to Live (Milliseconds) = %d",
    354     0  stevel 				getlong(data));
    355     0  stevel 			data += 4;
    356     0  stevel 			rdatalen = getshort(data);
    357     0  stevel 			sprintf(get_line(0, 0), "RDATA Length = 0x%.4x",
    358     0  stevel 						rdatalen);
    359     0  stevel 			data += 2;
    360     0  stevel 			/* 15.4.2.1.3 */
    361     0  stevel 			if (rdatalen == 6) {
    362     0  stevel 				rrflags = getshort(data);
    363     0  stevel 				data += 2;
    364     0  stevel 				sprintf(get_line(0, 0),
    365     0  stevel 					"Resource Record Flags = 0x%.4x",
    366     0  stevel 					rrflags);
    367     0  stevel 				nodecode = (rrflags>>13)& 0x11;
    368     0  stevel 				if (nodecode == 0) nodetype = "B";
    369     0  stevel 				if (nodecode == 1) nodetype = "P";
    370     0  stevel 				if (nodecode == 2) nodetype = "M";
    371     0  stevel 				sprintf(get_line(0, 0), "   - %s, %s node",
    372     0  stevel 					(rrflags & 1<<15) ?
    373     0  stevel 					"Group NetBIOS Name":
    374     0  stevel 					"Unique NetBIOS Name", nodetype);
    375     0  stevel 				sprintf(get_line(0, 0),
    376     0  stevel 					"Owner IP Address = %d.%d.%d.%d",
    377     0  stevel 					data[0], data[1], data[2], data[3]);
    378     0  stevel 			}
    379     0  stevel 		}
    380     0  stevel 		show_trailer();
    381     0  stevel 
    382     0  stevel 	}
    383     0  stevel }
    384     0  stevel 
    385     0  stevel /*
    386     0  stevel  * Interpret NetBIOS session packets.
    387     0  stevel  * [RFC 1002, Sec. 4.3]
    388     0  stevel  */
    389     0  stevel void
    390     0  stevel interpret_netbios_ses(int flags, uchar_t *data, int len)
    391     0  stevel {
    392     0  stevel 	struct nbt_ss *ss;
    393     0  stevel 	uchar_t *trailer;
    394     0  stevel 	int length = len - 4;   /* NBT packet length without header */
    395     0  stevel 	char *type;
    396     0  stevel 	char extrainfo[300];
    397     0  stevel 
    398     0  stevel 	if (len < sizeof (struct nbt_ss))
    399     0  stevel 		return;
    400     0  stevel 
    401     0  stevel 	/*
    402     0  stevel 	 * Packets that are fragments of a large NetBIOS session
    403     0  stevel 	 * message will have no NetBIOS header.  (Only the first
    404     0  stevel 	 * TCP segment will have a NetBIOS header.)  It turns out
    405     0  stevel 	 * that very often, such fragments start with SMB data, so
    406     0  stevel 	 * we should try to recognize and decode them.
    407     0  stevel 	 */
    408     0  stevel 	if (data[0] == 0xff &&
    409     0  stevel 	    data[1] == 'S' &&
    410     0  stevel 	    data[2] == 'M' &&
    411     0  stevel 	    data[3] == 'B') {
    412     0  stevel 		interpret_smb(flags, data, len);
    413     0  stevel 		return;
    414     0  stevel 	}
    415     0  stevel 
    416     0  stevel 	/* LINTED PTRALIGN */
    417     0  stevel 	ss = (struct nbt_ss *)data;
    418     0  stevel 	trailer = data + sizeof (*ss);
    419     0  stevel 	extrainfo[0] = '\0';
    420     0  stevel 
    421     0  stevel 	if (flags & F_SUM) {
    422     0  stevel 		switch (ss->type) {
    423     0  stevel 		case 0x00:
    424     0  stevel 			type = "SESSION MESSAGE";
    425     0  stevel 			break;
    426     0  stevel 		case 0x81:
    427     0  stevel 			type = "SESSION REQUEST";
    428     0  stevel 			interpret_netbios_names(flags, trailer,
    429     0  stevel 						length, extrainfo);
    430     0  stevel 			break;
    431     0  stevel 		case 0x82:
    432     0  stevel 			type = "POSITIVE SESSION RESPONSE";
    433     0  stevel 			break;
    434     0  stevel 		case 0x83:
    435     0  stevel 			type = "NEGATIVE SESSION RESPONSE";
    436     0  stevel 			break;
    437     0  stevel 		case 0x84:
    438     0  stevel 			type = "RETARGET SESSION RESPONSE";
    439     0  stevel 			break;
    440     0  stevel 		case 0x85:
    441     0  stevel 			type = "SESSION KEEP ALIVE";
    442     0  stevel 			break;
    443     0  stevel 		default:
    444     0  stevel 			type = "Unknown";
    445     0  stevel 			break;
    446     0  stevel 		}
    447     0  stevel 		(void) sprintf(get_sum_line(),
    448     0  stevel 			"NBT Type=%s %sLength=%d", type, extrainfo, length);
    449     0  stevel 	}
    450     0  stevel 
    451     0  stevel 	if (flags & F_DTAIL) {
    452     0  stevel 		show_header("NBT:  ", "NBT Header", len);
    453     0  stevel 		show_space();
    454     0  stevel 
    455     0  stevel 		switch (ss->type) {
    456     0  stevel 		case 0x00:
    457     0  stevel 			(void) sprintf(get_line(0, 0),
    458     0  stevel 			"Type = SESSION MESSAGE");
    459     0  stevel 			break;
    460     0  stevel 		case 0x81:
    461     0  stevel 			(void) sprintf(get_line(0, 0),
    462     0  stevel 			"Type = SESSION REQUEST");
    463     0  stevel 			interpret_netbios_names(flags, trailer, length, 0);
    464     0  stevel 			break;
    465     0  stevel 		case 0x82:
    466     0  stevel 			(void) sprintf(get_line(0, 0),
    467     0  stevel 			"Type = POSITIVE SESSION RESPONSE");
    468     0  stevel 			break;
    469     0  stevel 		case 0x83:
    470     0  stevel 			(void) sprintf(get_line(0, 0),
    471     0  stevel 			"Type = NEGATIVE SESSION RESPONSE");
    472     0  stevel 			break;
    473     0  stevel 		case 0x84:
    474     0  stevel 			(void) sprintf(get_line(0, 0),
    475     0  stevel 			"Type = RETARGET SESSION RESPONSE");
    476     0  stevel 			break;
    477     0  stevel 		case 0x85:
    478     0  stevel 			(void) sprintf(get_line(0, 0),
    479     0  stevel 			"Type = SESSION KEEP ALIVE");
    480     0  stevel 			break;
    481     0  stevel 		default:
    482     0  stevel 			(void) sprintf(get_line(0, 0),
    483     0  stevel 			"Type = Unknown");
    484     0  stevel 			break;
    485     0  stevel 		}
    486     0  stevel 
    487     0  stevel 		(void) sprintf(get_line(0, 0), "Length = %d bytes", length);
    488     0  stevel 		show_trailer();
    489     0  stevel 	}
    490     0  stevel 
    491     0  stevel 	/*
    492     0  stevel 	 * SMB packets have { 0xff, 'S', 'M', 'B' }
    493     0  stevel 	 * in the first four bytes.  If we find that,
    494     0  stevel 	 * let snoop_smb.c have a look at it.
    495     0  stevel 	 */
    496     0  stevel 	if (ss->type == 0x00 &&
    497     0  stevel 	    length > 0 &&
    498     0  stevel 	    trailer[0] == 0xff &&
    499     0  stevel 	    trailer[1] == 'S' &&
    500     0  stevel 	    trailer[2] == 'M' &&
    501     0  stevel 	    trailer[3] == 'B')
    502  7280     blu 		interpret_smb(flags, trailer, length);
    503     0  stevel }
    504     0  stevel 
    505     0  stevel /*
    506     0  stevel  * NetBIOS name encoding (First Level Encoding)
    507     0  stevel  * [RFC 1001, Sec. 4.1]
    508     0  stevel  */
    509     0  stevel static void
    510     0  stevel netbiosname2ascii(char *aname, uchar_t *nbname)
    511     0  stevel {
    512     0  stevel 	int c, i, j;
    513     0  stevel 
    514     0  stevel 	i = j = 0;
    515     0  stevel 	for (;;) {
    516     0  stevel 		c = nbname[i++] - 'A';
    517     0  stevel 		c = (c << 4) +
    518     0  stevel 			nbname[i++] - 'A';
    519     0  stevel 		/* 16th char is the "type" */
    520     0  stevel 		if (i >= 32)
    521     0  stevel 			break;
    522     0  stevel 		if (iscntrl(c))
    523     0  stevel 			c = '.';
    524     0  stevel 		if (c != ' ')
    525     0  stevel 			aname[j++] = c;
    526     0  stevel 	}
    527     0  stevel 	sprintf(&aname[j], "[%x]", c);
    528     0  stevel }
    529     0  stevel 
    530     0  stevel /*
    531     0  stevel  * Interpret the names in a Session Request packet.
    532     0  stevel  * [RFC 1002, Sec. 4.3.2]
    533     0  stevel  */
    534     0  stevel static void
    535     0  stevel interpret_netbios_names(int flags, uchar_t *data, int len, char *xtra)
    536     0  stevel {
    537     0  stevel 	char  calledname[24];
    538     0  stevel 	char callingname[24];
    539     0  stevel 	struct callnames *names = (struct callnames *)data;
    540     0  stevel 
    541     0  stevel 	if (len < sizeof (*names))
    542     0  stevel 		return;
    543     0  stevel 
    544     0  stevel 	netbiosname2ascii(calledname, names->calledname);
    545     0  stevel 	netbiosname2ascii(callingname, names->callingname);
    546     0  stevel 
    547     0  stevel 	if (flags & F_SUM) {
    548     0  stevel 		sprintf(xtra, "Dest=%s Source=%s ", calledname, callingname);
    549     0  stevel 	}
    550     0  stevel 
    551     0  stevel 	if (flags & F_DTAIL) {
    552     0  stevel 		sprintf(get_line(0, 0), "Destination = %s", calledname);
    553     0  stevel 		sprintf(get_line(0, 0), "Source = %s", callingname);
    554     0  stevel 	}
    555     0  stevel }
    556