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