17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*4bb0471cSblu * Common Development and Distribution License (the "License"). 6*4bb0471cSblu * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*4bb0471cSblu * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*4bb0471cSblu * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * References used throughout this code: 307c478bd9Sstevel@tonic-gate * 317c478bd9Sstevel@tonic-gate * [RFC1001] : PROTOCOL STANDARD FOR A NetBIOS SERVICE 327c478bd9Sstevel@tonic-gate * ON A TCP/UDP TRANSPORT: 337c478bd9Sstevel@tonic-gate * CONCEPTS AND METHODS 347c478bd9Sstevel@tonic-gate * NetBIOS Working Group, March 1987 357c478bd9Sstevel@tonic-gate * 367c478bd9Sstevel@tonic-gate * [RFC1002] : PROTOCOL STANDARD FOR A NetBIOS SERVICE 377c478bd9Sstevel@tonic-gate * ON A TCP/UDP TRANSPORT: 387c478bd9Sstevel@tonic-gate * DETAILED SPECIFICATIONS 397c478bd9Sstevel@tonic-gate * NetBIOS Working Group, March 1987 407c478bd9Sstevel@tonic-gate */ 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate #include <fcntl.h> 437c478bd9Sstevel@tonic-gate #include "snoop.h" 447c478bd9Sstevel@tonic-gate #include <stdio.h> 457c478bd9Sstevel@tonic-gate #include <ctype.h> 467c478bd9Sstevel@tonic-gate #include "snoop.h" 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate extern char *dlc_header; 497c478bd9Sstevel@tonic-gate char *show_type(); 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate /* See snoop_smb.c */ 527c478bd9Sstevel@tonic-gate extern void interpret_smb(int flags, uchar_t *data, int len); 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate /* 557c478bd9Sstevel@tonic-gate * NBT Session Packet Header 567c478bd9Sstevel@tonic-gate * [RFC 1002, Sec. 4.3.1] 577c478bd9Sstevel@tonic-gate */ 587c478bd9Sstevel@tonic-gate struct nbt_ss { 597c478bd9Sstevel@tonic-gate uchar_t type; 607c478bd9Sstevel@tonic-gate uchar_t flags; 617c478bd9Sstevel@tonic-gate ushort_t length; 627c478bd9Sstevel@tonic-gate }; 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate /* 657c478bd9Sstevel@tonic-gate * NBT Session Request Packet trailer 667c478bd9Sstevel@tonic-gate * [RFC 1002, Sec. 4.3.2] 677c478bd9Sstevel@tonic-gate */ 687c478bd9Sstevel@tonic-gate struct callnames { 697c478bd9Sstevel@tonic-gate uchar_t space; /* padding */ 707c478bd9Sstevel@tonic-gate uchar_t calledname[32]; 717c478bd9Sstevel@tonic-gate uchar_t nullchar; /* padding */ 727c478bd9Sstevel@tonic-gate uchar_t space2; /* padding */ 737c478bd9Sstevel@tonic-gate uchar_t callingname[32]; 747c478bd9Sstevel@tonic-gate uchar_t nullchar2; /* padding */ 757c478bd9Sstevel@tonic-gate }; 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate static void interpret_netbios_names(int flags, uchar_t *data, int len, 797c478bd9Sstevel@tonic-gate char *xtra); 807c478bd9Sstevel@tonic-gate static void netbiosname2ascii(char *asciiname, uchar_t *netbiosname); 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate /* 837c478bd9Sstevel@tonic-gate * Helpers to read network-order values, 847c478bd9Sstevel@tonic-gate * with NO alignment assumed. 857c478bd9Sstevel@tonic-gate */ 867c478bd9Sstevel@tonic-gate static ushort_t 877c478bd9Sstevel@tonic-gate getshort(uchar_t *p) { 887c478bd9Sstevel@tonic-gate return (p[1] + (p[0]<<8)); 897c478bd9Sstevel@tonic-gate } 907c478bd9Sstevel@tonic-gate static uint_t 917c478bd9Sstevel@tonic-gate getlong(uchar_t *p) 927c478bd9Sstevel@tonic-gate { 937c478bd9Sstevel@tonic-gate return (p[3] + (p[2]<<8) + (p[1]<<16) + (p[0]<<24)); 947c478bd9Sstevel@tonic-gate } 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate /* 977c478bd9Sstevel@tonic-gate * NM_FLAGS fields in the NetBIOS Name Service Packet header. 987c478bd9Sstevel@tonic-gate * [RFC 1002, Sec. 4.2.1.1] 997c478bd9Sstevel@tonic-gate */ 1007c478bd9Sstevel@tonic-gate static void 1017c478bd9Sstevel@tonic-gate print_flag_details(int headerflags) 1027c478bd9Sstevel@tonic-gate { 1037c478bd9Sstevel@tonic-gate if (headerflags & 1<<4) 1047c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), " - Broadcast"); 1057c478bd9Sstevel@tonic-gate if (headerflags & 1<<7) 1067c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), " - Recursion Available"); 1077c478bd9Sstevel@tonic-gate if (headerflags & 1<<8) 1087c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), " - Recursion Desired"); 1097c478bd9Sstevel@tonic-gate if (headerflags & 1<<9) 1107c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), " - Truncation Flag"); 1117c478bd9Sstevel@tonic-gate if (headerflags & 1<<10) 1127c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), " - Authoritative Answer"); 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* 1167c478bd9Sstevel@tonic-gate * Possible errors in NetBIOS name service packets. 1177c478bd9Sstevel@tonic-gate * [RFC 1002, Sec. 4.2.6, 4.2.11, 4.2.14] 1187c478bd9Sstevel@tonic-gate */ 1197c478bd9Sstevel@tonic-gate static void 1207c478bd9Sstevel@tonic-gate getrcodeerr(int headerflags, char *errortype) 1217c478bd9Sstevel@tonic-gate { 1227c478bd9Sstevel@tonic-gate int error = (headerflags & 0xf); 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate switch (error) { 1257c478bd9Sstevel@tonic-gate case 0: 1267c478bd9Sstevel@tonic-gate sprintf(errortype, "Success"); 1277c478bd9Sstevel@tonic-gate break; 1287c478bd9Sstevel@tonic-gate case 1: 1297c478bd9Sstevel@tonic-gate sprintf(errortype, "Format Error"); 1307c478bd9Sstevel@tonic-gate break; 1317c478bd9Sstevel@tonic-gate case 2: 1327c478bd9Sstevel@tonic-gate sprintf(errortype, "Server Failure"); 1337c478bd9Sstevel@tonic-gate break; 1347c478bd9Sstevel@tonic-gate case 3: 1357c478bd9Sstevel@tonic-gate sprintf(errortype, "Name Error"); 1367c478bd9Sstevel@tonic-gate break; 1377c478bd9Sstevel@tonic-gate case 4: 1387c478bd9Sstevel@tonic-gate sprintf(errortype, "Unsupported Request Error"); 1397c478bd9Sstevel@tonic-gate break; 1407c478bd9Sstevel@tonic-gate case 5: 1417c478bd9Sstevel@tonic-gate sprintf(errortype, "Refused Error"); 1427c478bd9Sstevel@tonic-gate break; 1437c478bd9Sstevel@tonic-gate case 6: 1447c478bd9Sstevel@tonic-gate sprintf(errortype, "Active Error"); 1457c478bd9Sstevel@tonic-gate break; 1467c478bd9Sstevel@tonic-gate case 7: 1477c478bd9Sstevel@tonic-gate sprintf(errortype, "Name in Conflict Error"); 1487c478bd9Sstevel@tonic-gate break; 1497c478bd9Sstevel@tonic-gate default: 1507c478bd9Sstevel@tonic-gate sprintf(errortype, "Unknown Error"); 1517c478bd9Sstevel@tonic-gate break; 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate /* 1567c478bd9Sstevel@tonic-gate * OPCODE fields in the NetBIOS Name Service Packet header. 1577c478bd9Sstevel@tonic-gate * [RFC 1002, Sec. 4.2.1.1] 1587c478bd9Sstevel@tonic-gate */ 1597c478bd9Sstevel@tonic-gate static void 1607c478bd9Sstevel@tonic-gate print_ns_type(int flags, int headerflags, char *xtra) 1617c478bd9Sstevel@tonic-gate { 1627c478bd9Sstevel@tonic-gate int opcode = (headerflags & 0x7800)>>11; 1637c478bd9Sstevel@tonic-gate int response = (headerflags & 1<<15); 1647c478bd9Sstevel@tonic-gate char *resptype = response ? "Response" : "Request"; 1657c478bd9Sstevel@tonic-gate char *optype; 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate switch (opcode) { 1687c478bd9Sstevel@tonic-gate case 0: 1697c478bd9Sstevel@tonic-gate optype = "Query"; 1707c478bd9Sstevel@tonic-gate break; 1717c478bd9Sstevel@tonic-gate case 5: 1727c478bd9Sstevel@tonic-gate optype = "Registration"; 1737c478bd9Sstevel@tonic-gate break; 1747c478bd9Sstevel@tonic-gate case 6: 1757c478bd9Sstevel@tonic-gate optype = "Release"; 1767c478bd9Sstevel@tonic-gate break; 1777c478bd9Sstevel@tonic-gate case 7: 1787c478bd9Sstevel@tonic-gate optype = "WACK"; 1797c478bd9Sstevel@tonic-gate break; 1807c478bd9Sstevel@tonic-gate case 8: 1817c478bd9Sstevel@tonic-gate optype = "Refresh"; 1827c478bd9Sstevel@tonic-gate break; 1837c478bd9Sstevel@tonic-gate default: 1847c478bd9Sstevel@tonic-gate optype = "Unknown"; 1857c478bd9Sstevel@tonic-gate break; 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate if (flags & F_DTAIL) 1897c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Type = %s %s", optype, resptype); 1907c478bd9Sstevel@tonic-gate else 1917c478bd9Sstevel@tonic-gate sprintf(xtra, "%s %s", optype, resptype); 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate /* 1967c478bd9Sstevel@tonic-gate * Interpret Datagram Packets 1977c478bd9Sstevel@tonic-gate * [RFC 1002, Sec. 4.4] 1987c478bd9Sstevel@tonic-gate */ 1997c478bd9Sstevel@tonic-gate void 2007c478bd9Sstevel@tonic-gate interpret_netbios_datagram(int flags, uchar_t *data, int len) 2017c478bd9Sstevel@tonic-gate { 2027c478bd9Sstevel@tonic-gate char name[24]; 2037c478bd9Sstevel@tonic-gate int packettype = data[0]; 2047c478bd9Sstevel@tonic-gate int packetlen; 2057c478bd9Sstevel@tonic-gate data++; 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate if (packettype < 0x10 || packettype > 0x11) 2087c478bd9Sstevel@tonic-gate return; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 2117c478bd9Sstevel@tonic-gate data += 14; 2127c478bd9Sstevel@tonic-gate netbiosname2ascii(name, data); 2137c478bd9Sstevel@tonic-gate sprintf(get_sum_line(), 2147c478bd9Sstevel@tonic-gate "NBT Datagram Service Type=%d Source=%s", 2157c478bd9Sstevel@tonic-gate packettype, name); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate if (flags & F_DTAIL) { 2197c478bd9Sstevel@tonic-gate show_header("NBT: ", "Netbios Datagram Service Header", len); 2207c478bd9Sstevel@tonic-gate show_space(); 2217c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Datagram Packet Type = 0x%.2x", 2227c478bd9Sstevel@tonic-gate packettype); 2237c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Datagram Flags = 0x%.2x", 2247c478bd9Sstevel@tonic-gate data[0]); 2257c478bd9Sstevel@tonic-gate data++; 2267c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Datagram ID = 0x%.4x", 2277c478bd9Sstevel@tonic-gate getshort(data)); 2287c478bd9Sstevel@tonic-gate data += 2; 2297c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Source IP = %d.%d.%d.%d", 2307c478bd9Sstevel@tonic-gate data[0], data[1], data[2], data[3]); 2317c478bd9Sstevel@tonic-gate data += 4; 2327c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Source Port = %d", 2337c478bd9Sstevel@tonic-gate getshort(data)); 2347c478bd9Sstevel@tonic-gate data += 2; 2357c478bd9Sstevel@tonic-gate packetlen = getshort(data); 2367c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Datagram Length = 0x%.4x", 2377c478bd9Sstevel@tonic-gate packetlen); 2387c478bd9Sstevel@tonic-gate data += 2; 2397c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Packet Offset = 0x%.4x", 2407c478bd9Sstevel@tonic-gate getshort(data)); 2417c478bd9Sstevel@tonic-gate data += 3; 2427c478bd9Sstevel@tonic-gate netbiosname2ascii(name, data); 2437c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Source Name = %s", name); 2447c478bd9Sstevel@tonic-gate data += 34; 2457c478bd9Sstevel@tonic-gate netbiosname2ascii(name, data); 2467c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Destination Name = %s", name); 2477c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Number of data bytes remaining = %d", 2487c478bd9Sstevel@tonic-gate packetlen - 68); 2497c478bd9Sstevel@tonic-gate show_trailer(); 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate /* 2547c478bd9Sstevel@tonic-gate * Interpret NetBIOS Name Service packets. 2557c478bd9Sstevel@tonic-gate * [RFC 1002, Sec. 4.2] 2567c478bd9Sstevel@tonic-gate */ 2577c478bd9Sstevel@tonic-gate void 2587c478bd9Sstevel@tonic-gate interpret_netbios_ns(int flags, uchar_t *data, int len) 2597c478bd9Sstevel@tonic-gate { 2607c478bd9Sstevel@tonic-gate int headerflags, qcount, acount, nscount, arcount; 2617c478bd9Sstevel@tonic-gate int transid; 2627c478bd9Sstevel@tonic-gate char name[24]; 2637c478bd9Sstevel@tonic-gate char extra[256]; 2647c478bd9Sstevel@tonic-gate char errortype[50]; 2657c478bd9Sstevel@tonic-gate int rdatalen; 2667c478bd9Sstevel@tonic-gate int rrflags; 2677c478bd9Sstevel@tonic-gate int nameptr; 2687c478bd9Sstevel@tonic-gate int nodecode; 2697c478bd9Sstevel@tonic-gate char *nodetype; 2707c478bd9Sstevel@tonic-gate uchar_t *data0 = data; 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate transid = getshort(data); data += 2; 2737c478bd9Sstevel@tonic-gate headerflags = getshort(data); data += 2; 2747c478bd9Sstevel@tonic-gate qcount = getshort(data); data += 2; 2757c478bd9Sstevel@tonic-gate acount = getshort(data); data += 2; 2767c478bd9Sstevel@tonic-gate nscount = getshort(data); data += 2; 2777c478bd9Sstevel@tonic-gate arcount = getshort(data); data += 2; 2787c478bd9Sstevel@tonic-gate getrcodeerr(headerflags, errortype); 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 2817c478bd9Sstevel@tonic-gate print_ns_type(flags, headerflags, extra); 2827c478bd9Sstevel@tonic-gate data++; 2837c478bd9Sstevel@tonic-gate netbiosname2ascii(name, data); 2847c478bd9Sstevel@tonic-gate sprintf(get_sum_line(), "NBT NS %s for %s, %s", 2857c478bd9Sstevel@tonic-gate extra, name, errortype); 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate if (flags & F_DTAIL) { 2917c478bd9Sstevel@tonic-gate show_header("NBT: ", "Netbios Name Service Header", len); 2927c478bd9Sstevel@tonic-gate show_space(); 2937c478bd9Sstevel@tonic-gate print_ns_type(flags, headerflags, 0); 2947c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Status = %s", errortype); 2957c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Transaction ID = 0x%.4x", transid); 2967c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Flags Summary = 0x%.4x", 2977c478bd9Sstevel@tonic-gate headerflags); 2987c478bd9Sstevel@tonic-gate print_flag_details(headerflags); 2997c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Question count = %d", qcount); 3007c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Answer Count = %d", acount); 3017c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Name Service Count = %d", nscount); 3027c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 3037c478bd9Sstevel@tonic-gate "Additional Record Count = %d", arcount); 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate /* 3067c478bd9Sstevel@tonic-gate * Question Section Packet Description from 3077c478bd9Sstevel@tonic-gate * [RFC 1002, Sec. 4.2.1.2] 3087c478bd9Sstevel@tonic-gate */ 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate if (qcount) { 3117c478bd9Sstevel@tonic-gate data++; 3127c478bd9Sstevel@tonic-gate netbiosname2ascii(name, data); 3137c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Question Name = %s", name); 3147c478bd9Sstevel@tonic-gate data += 33; 3157c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Question Type = 0x%.4x", 3167c478bd9Sstevel@tonic-gate getshort(data)); 3177c478bd9Sstevel@tonic-gate data += 2; 3187c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Question Class = 0x%.4x", 3197c478bd9Sstevel@tonic-gate getshort(data)); 3207c478bd9Sstevel@tonic-gate data += 2; 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate /* 3247c478bd9Sstevel@tonic-gate * Resrouce Record Packet Description from 3257c478bd9Sstevel@tonic-gate * [RFC 1002, Sec. 4.2.1.3] 3267c478bd9Sstevel@tonic-gate */ 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate if ((acount || nscount || arcount) || 3297c478bd9Sstevel@tonic-gate (qcount+acount+nscount+arcount == 0)) { 3307c478bd9Sstevel@tonic-gate /* Second level encoding from RFC883 (p.31, 32) */ 3317c478bd9Sstevel@tonic-gate if (data[0] & 0xc0) { 3327c478bd9Sstevel@tonic-gate nameptr = getshort(data)&0x3fff; 3337c478bd9Sstevel@tonic-gate netbiosname2ascii(name, (data0+nameptr+1)); 3347c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 3357c478bd9Sstevel@tonic-gate "Resource Record Name = %s", name); 3367c478bd9Sstevel@tonic-gate data += 2; 3377c478bd9Sstevel@tonic-gate } else { 3387c478bd9Sstevel@tonic-gate data++; 3397c478bd9Sstevel@tonic-gate netbiosname2ascii(name, data); 3407c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 3417c478bd9Sstevel@tonic-gate "Resource Record Name = %s", name); 3427c478bd9Sstevel@tonic-gate data += 33; 3437c478bd9Sstevel@tonic-gate } 3447c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 3457c478bd9Sstevel@tonic-gate "Resource Record Type = 0x%.4x", 3467c478bd9Sstevel@tonic-gate getshort(data)); 3477c478bd9Sstevel@tonic-gate data += 2; 3487c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 3497c478bd9Sstevel@tonic-gate "Resource Record Class = 0x%.4x", 3507c478bd9Sstevel@tonic-gate getshort(data)); 3517c478bd9Sstevel@tonic-gate data += 2; 3527c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 3537c478bd9Sstevel@tonic-gate "Time to Live (Milliseconds) = %d", 3547c478bd9Sstevel@tonic-gate getlong(data)); 3557c478bd9Sstevel@tonic-gate data += 4; 3567c478bd9Sstevel@tonic-gate rdatalen = getshort(data); 3577c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "RDATA Length = 0x%.4x", 3587c478bd9Sstevel@tonic-gate rdatalen); 3597c478bd9Sstevel@tonic-gate data += 2; 3607c478bd9Sstevel@tonic-gate /* 15.4.2.1.3 */ 3617c478bd9Sstevel@tonic-gate if (rdatalen == 6) { 3627c478bd9Sstevel@tonic-gate rrflags = getshort(data); 3637c478bd9Sstevel@tonic-gate data += 2; 3647c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 3657c478bd9Sstevel@tonic-gate "Resource Record Flags = 0x%.4x", 3667c478bd9Sstevel@tonic-gate rrflags); 3677c478bd9Sstevel@tonic-gate nodecode = (rrflags>>13)& 0x11; 3687c478bd9Sstevel@tonic-gate if (nodecode == 0) nodetype = "B"; 3697c478bd9Sstevel@tonic-gate if (nodecode == 1) nodetype = "P"; 3707c478bd9Sstevel@tonic-gate if (nodecode == 2) nodetype = "M"; 3717c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), " - %s, %s node", 3727c478bd9Sstevel@tonic-gate (rrflags & 1<<15) ? 3737c478bd9Sstevel@tonic-gate "Group NetBIOS Name": 3747c478bd9Sstevel@tonic-gate "Unique NetBIOS Name", nodetype); 3757c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 3767c478bd9Sstevel@tonic-gate "Owner IP Address = %d.%d.%d.%d", 3777c478bd9Sstevel@tonic-gate data[0], data[1], data[2], data[3]); 3787c478bd9Sstevel@tonic-gate } 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate show_trailer(); 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate /* 3867c478bd9Sstevel@tonic-gate * Interpret NetBIOS session packets. 3877c478bd9Sstevel@tonic-gate * [RFC 1002, Sec. 4.3] 3887c478bd9Sstevel@tonic-gate */ 3897c478bd9Sstevel@tonic-gate void 3907c478bd9Sstevel@tonic-gate interpret_netbios_ses(int flags, uchar_t *data, int len) 3917c478bd9Sstevel@tonic-gate { 3927c478bd9Sstevel@tonic-gate struct nbt_ss *ss; 3937c478bd9Sstevel@tonic-gate uchar_t *trailer; 3947c478bd9Sstevel@tonic-gate int length = len - 4; /* NBT packet length without header */ 3957c478bd9Sstevel@tonic-gate char *type; 3967c478bd9Sstevel@tonic-gate char extrainfo[300]; 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate if (len < sizeof (struct nbt_ss)) 3997c478bd9Sstevel@tonic-gate return; 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate /* 4027c478bd9Sstevel@tonic-gate * Packets that are fragments of a large NetBIOS session 4037c478bd9Sstevel@tonic-gate * message will have no NetBIOS header. (Only the first 4047c478bd9Sstevel@tonic-gate * TCP segment will have a NetBIOS header.) It turns out 4057c478bd9Sstevel@tonic-gate * that very often, such fragments start with SMB data, so 4067c478bd9Sstevel@tonic-gate * we should try to recognize and decode them. 4077c478bd9Sstevel@tonic-gate */ 4087c478bd9Sstevel@tonic-gate if (data[0] == 0xff && 4097c478bd9Sstevel@tonic-gate data[1] == 'S' && 4107c478bd9Sstevel@tonic-gate data[2] == 'M' && 4117c478bd9Sstevel@tonic-gate data[3] == 'B') { 4127c478bd9Sstevel@tonic-gate interpret_smb(flags, data, len); 4137c478bd9Sstevel@tonic-gate return; 4147c478bd9Sstevel@tonic-gate } 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate /* LINTED PTRALIGN */ 4177c478bd9Sstevel@tonic-gate ss = (struct nbt_ss *)data; 4187c478bd9Sstevel@tonic-gate trailer = data + sizeof (*ss); 4197c478bd9Sstevel@tonic-gate extrainfo[0] = '\0'; 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 4227c478bd9Sstevel@tonic-gate switch (ss->type) { 4237c478bd9Sstevel@tonic-gate case 0x00: 4247c478bd9Sstevel@tonic-gate type = "SESSION MESSAGE"; 4257c478bd9Sstevel@tonic-gate break; 4267c478bd9Sstevel@tonic-gate case 0x81: 4277c478bd9Sstevel@tonic-gate type = "SESSION REQUEST"; 4287c478bd9Sstevel@tonic-gate interpret_netbios_names(flags, trailer, 4297c478bd9Sstevel@tonic-gate length, extrainfo); 4307c478bd9Sstevel@tonic-gate break; 4317c478bd9Sstevel@tonic-gate case 0x82: 4327c478bd9Sstevel@tonic-gate type = "POSITIVE SESSION RESPONSE"; 4337c478bd9Sstevel@tonic-gate break; 4347c478bd9Sstevel@tonic-gate case 0x83: 4357c478bd9Sstevel@tonic-gate type = "NEGATIVE SESSION RESPONSE"; 4367c478bd9Sstevel@tonic-gate break; 4377c478bd9Sstevel@tonic-gate case 0x84: 4387c478bd9Sstevel@tonic-gate type = "RETARGET SESSION RESPONSE"; 4397c478bd9Sstevel@tonic-gate break; 4407c478bd9Sstevel@tonic-gate case 0x85: 4417c478bd9Sstevel@tonic-gate type = "SESSION KEEP ALIVE"; 4427c478bd9Sstevel@tonic-gate break; 4437c478bd9Sstevel@tonic-gate default: 4447c478bd9Sstevel@tonic-gate type = "Unknown"; 4457c478bd9Sstevel@tonic-gate break; 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate (void) sprintf(get_sum_line(), 4487c478bd9Sstevel@tonic-gate "NBT Type=%s %sLength=%d", type, extrainfo, length); 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate if (flags & F_DTAIL) { 4527c478bd9Sstevel@tonic-gate show_header("NBT: ", "NBT Header", len); 4537c478bd9Sstevel@tonic-gate show_space(); 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate switch (ss->type) { 4567c478bd9Sstevel@tonic-gate case 0x00: 4577c478bd9Sstevel@tonic-gate (void) sprintf(get_line(0, 0), 4587c478bd9Sstevel@tonic-gate "Type = SESSION MESSAGE"); 4597c478bd9Sstevel@tonic-gate break; 4607c478bd9Sstevel@tonic-gate case 0x81: 4617c478bd9Sstevel@tonic-gate (void) sprintf(get_line(0, 0), 4627c478bd9Sstevel@tonic-gate "Type = SESSION REQUEST"); 4637c478bd9Sstevel@tonic-gate interpret_netbios_names(flags, trailer, length, 0); 4647c478bd9Sstevel@tonic-gate break; 4657c478bd9Sstevel@tonic-gate case 0x82: 4667c478bd9Sstevel@tonic-gate (void) sprintf(get_line(0, 0), 4677c478bd9Sstevel@tonic-gate "Type = POSITIVE SESSION RESPONSE"); 4687c478bd9Sstevel@tonic-gate break; 4697c478bd9Sstevel@tonic-gate case 0x83: 4707c478bd9Sstevel@tonic-gate (void) sprintf(get_line(0, 0), 4717c478bd9Sstevel@tonic-gate "Type = NEGATIVE SESSION RESPONSE"); 4727c478bd9Sstevel@tonic-gate break; 4737c478bd9Sstevel@tonic-gate case 0x84: 4747c478bd9Sstevel@tonic-gate (void) sprintf(get_line(0, 0), 4757c478bd9Sstevel@tonic-gate "Type = RETARGET SESSION RESPONSE"); 4767c478bd9Sstevel@tonic-gate break; 4777c478bd9Sstevel@tonic-gate case 0x85: 4787c478bd9Sstevel@tonic-gate (void) sprintf(get_line(0, 0), 4797c478bd9Sstevel@tonic-gate "Type = SESSION KEEP ALIVE"); 4807c478bd9Sstevel@tonic-gate break; 4817c478bd9Sstevel@tonic-gate default: 4827c478bd9Sstevel@tonic-gate (void) sprintf(get_line(0, 0), 4837c478bd9Sstevel@tonic-gate "Type = Unknown"); 4847c478bd9Sstevel@tonic-gate break; 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate (void) sprintf(get_line(0, 0), "Length = %d bytes", length); 4887c478bd9Sstevel@tonic-gate show_trailer(); 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate /* 4927c478bd9Sstevel@tonic-gate * SMB packets have { 0xff, 'S', 'M', 'B' } 4937c478bd9Sstevel@tonic-gate * in the first four bytes. If we find that, 4947c478bd9Sstevel@tonic-gate * let snoop_smb.c have a look at it. 4957c478bd9Sstevel@tonic-gate */ 4967c478bd9Sstevel@tonic-gate if (ss->type == 0x00 && 4977c478bd9Sstevel@tonic-gate length > 0 && 4987c478bd9Sstevel@tonic-gate trailer[0] == 0xff && 4997c478bd9Sstevel@tonic-gate trailer[1] == 'S' && 5007c478bd9Sstevel@tonic-gate trailer[2] == 'M' && 5017c478bd9Sstevel@tonic-gate trailer[3] == 'B') 502*4bb0471cSblu interpret_smb(flags, trailer, length); 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate /* 5067c478bd9Sstevel@tonic-gate * NetBIOS name encoding (First Level Encoding) 5077c478bd9Sstevel@tonic-gate * [RFC 1001, Sec. 4.1] 5087c478bd9Sstevel@tonic-gate */ 5097c478bd9Sstevel@tonic-gate static void 5107c478bd9Sstevel@tonic-gate netbiosname2ascii(char *aname, uchar_t *nbname) 5117c478bd9Sstevel@tonic-gate { 5127c478bd9Sstevel@tonic-gate int c, i, j; 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate i = j = 0; 5157c478bd9Sstevel@tonic-gate for (;;) { 5167c478bd9Sstevel@tonic-gate c = nbname[i++] - 'A'; 5177c478bd9Sstevel@tonic-gate c = (c << 4) + 5187c478bd9Sstevel@tonic-gate nbname[i++] - 'A'; 5197c478bd9Sstevel@tonic-gate /* 16th char is the "type" */ 5207c478bd9Sstevel@tonic-gate if (i >= 32) 5217c478bd9Sstevel@tonic-gate break; 5227c478bd9Sstevel@tonic-gate if (iscntrl(c)) 5237c478bd9Sstevel@tonic-gate c = '.'; 5247c478bd9Sstevel@tonic-gate if (c != ' ') 5257c478bd9Sstevel@tonic-gate aname[j++] = c; 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate sprintf(&aname[j], "[%x]", c); 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate /* 5317c478bd9Sstevel@tonic-gate * Interpret the names in a Session Request packet. 5327c478bd9Sstevel@tonic-gate * [RFC 1002, Sec. 4.3.2] 5337c478bd9Sstevel@tonic-gate */ 5347c478bd9Sstevel@tonic-gate static void 5357c478bd9Sstevel@tonic-gate interpret_netbios_names(int flags, uchar_t *data, int len, char *xtra) 5367c478bd9Sstevel@tonic-gate { 5377c478bd9Sstevel@tonic-gate char calledname[24]; 5387c478bd9Sstevel@tonic-gate char callingname[24]; 5397c478bd9Sstevel@tonic-gate struct callnames *names = (struct callnames *)data; 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate if (len < sizeof (*names)) 5427c478bd9Sstevel@tonic-gate return; 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate netbiosname2ascii(calledname, names->calledname); 5457c478bd9Sstevel@tonic-gate netbiosname2ascii(callingname, names->callingname); 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 5487c478bd9Sstevel@tonic-gate sprintf(xtra, "Dest=%s Source=%s ", calledname, callingname); 5497c478bd9Sstevel@tonic-gate } 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate if (flags & F_DTAIL) { 5527c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Destination = %s", calledname); 5537c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Source = %s", callingname); 5547c478bd9Sstevel@tonic-gate } 5557c478bd9Sstevel@tonic-gate } 556