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