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