1 /* 2 * Copyright (C) Andrew Tridgell 1995-1999 3 * 4 * This software may be distributed either under the terms of the 5 * BSD-style license that accompanies tcpdump or the GNU GPL version 2 6 * or later 7 */ 8 9 #include <sys/cdefs.h> 10 #ifndef lint 11 __RCSID("$NetBSD: print-smb.c,v 1.5 2015/03/31 21:59:35 christos Exp $"); 12 #endif 13 14 #define NETDISSECT_REWORKED 15 #ifdef HAVE_CONFIG_H 16 #include "config.h" 17 #endif 18 19 #include <tcpdump-stdinc.h> 20 21 #include <string.h> 22 23 #include "interface.h" 24 #include "extract.h" 25 #include "smb.h" 26 27 static const char tstr[] = "[|SMB]"; 28 29 static int request = 0; 30 static int unicodestr = 0; 31 32 const u_char *startbuf = NULL; 33 34 struct smbdescript { 35 const char *req_f1; 36 const char *req_f2; 37 const char *rep_f1; 38 const char *rep_f2; 39 void (*fn)(netdissect_options *, const u_char *, const u_char *, const u_char *, const u_char *); 40 }; 41 42 struct smbdescriptint { 43 const char *req_f1; 44 const char *req_f2; 45 const char *rep_f1; 46 const char *rep_f2; 47 void (*fn)(netdissect_options *, const u_char *, const u_char *, int, int); 48 }; 49 50 struct smbfns 51 { 52 int id; 53 const char *name; 54 int flags; 55 struct smbdescript descript; 56 }; 57 58 struct smbfnsint 59 { 60 int id; 61 const char *name; 62 int flags; 63 struct smbdescriptint descript; 64 }; 65 66 #define DEFDESCRIPT { NULL, NULL, NULL, NULL, NULL } 67 68 #define FLG_CHAIN (1 << 0) 69 70 static const struct smbfns * 71 smbfind(int id, const struct smbfns *list) 72 { 73 int sindex; 74 75 for (sindex = 0; list[sindex].name; sindex++) 76 if (list[sindex].id == id) 77 return(&list[sindex]); 78 79 return(&list[0]); 80 } 81 82 static const struct smbfnsint * 83 smbfindint(int id, const struct smbfnsint *list) 84 { 85 int sindex; 86 87 for (sindex = 0; list[sindex].name; sindex++) 88 if (list[sindex].id == id) 89 return(&list[sindex]); 90 91 return(&list[0]); 92 } 93 94 static void 95 trans2_findfirst(netdissect_options *ndo, 96 const u_char *param, const u_char *data, int pcnt, int dcnt) 97 { 98 const char *fmt; 99 100 if (request) 101 fmt = "Attribute=[A]\nSearchCount=[d]\nFlags=[w]\nLevel=[dP4]\nFile=[S]\n"; 102 else 103 fmt = "Handle=[w]\nCount=[d]\nEOS=[w]\nEoffset=[d]\nLastNameOfs=[w]\n"; 104 105 smb_fdata(ndo, param, fmt, param + pcnt, unicodestr); 106 if (dcnt) { 107 ND_PRINT((ndo, "data:\n")); 108 print_data(ndo, data, dcnt); 109 } 110 } 111 112 static void 113 trans2_qfsinfo(netdissect_options *ndo, 114 const u_char *param, const u_char *data, int pcnt, int dcnt) 115 { 116 static int level = 0; 117 const char *fmt=""; 118 119 if (request) { 120 ND_TCHECK2(*param, 2); 121 level = EXTRACT_LE_16BITS(param); 122 fmt = "InfoLevel=[d]\n"; 123 smb_fdata(ndo, param, fmt, param + pcnt, unicodestr); 124 } else { 125 switch (level) { 126 case 1: 127 fmt = "idFileSystem=[W]\nSectorUnit=[D]\nUnit=[D]\nAvail=[D]\nSectorSize=[d]\n"; 128 break; 129 case 2: 130 fmt = "CreationTime=[T2]VolNameLength=[lb]\nVolumeLabel=[c]\n"; 131 break; 132 case 0x105: 133 fmt = "Capabilities=[W]\nMaxFileLen=[D]\nVolNameLen=[lD]\nVolume=[C]\n"; 134 break; 135 default: 136 fmt = "UnknownLevel\n"; 137 break; 138 } 139 smb_fdata(ndo, data, fmt, data + dcnt, unicodestr); 140 } 141 if (dcnt) { 142 ND_PRINT((ndo, "data:\n")); 143 print_data(ndo, data, dcnt); 144 } 145 return; 146 trunc: 147 ND_PRINT((ndo, "%s", tstr)); 148 } 149 150 static const struct smbfnsint trans2_fns[] = { 151 { 0, "TRANSACT2_OPEN", 0, 152 { "Flags2=[w]\nMode=[w]\nSearchAttrib=[A]\nAttrib=[A]\nTime=[T2]\nOFun=[w]\nSize=[D]\nRes=([w, w, w, w, w])\nPath=[S]", 153 NULL, 154 "Handle=[d]\nAttrib=[A]\nTime=[T2]\nSize=[D]\nAccess=[w]\nType=[w]\nState=[w]\nAction=[w]\nInode=[W]\nOffErr=[d]\n|EALength=[d]\n", 155 NULL, NULL }}, 156 { 1, "TRANSACT2_FINDFIRST", 0, 157 { NULL, NULL, NULL, NULL, trans2_findfirst }}, 158 { 2, "TRANSACT2_FINDNEXT", 0, DEFDESCRIPT }, 159 { 3, "TRANSACT2_QFSINFO", 0, 160 { NULL, NULL, NULL, NULL, trans2_qfsinfo }}, 161 { 4, "TRANSACT2_SETFSINFO", 0, DEFDESCRIPT }, 162 { 5, "TRANSACT2_QPATHINFO", 0, DEFDESCRIPT }, 163 { 6, "TRANSACT2_SETPATHINFO", 0, DEFDESCRIPT }, 164 { 7, "TRANSACT2_QFILEINFO", 0, DEFDESCRIPT }, 165 { 8, "TRANSACT2_SETFILEINFO", 0, DEFDESCRIPT }, 166 { 9, "TRANSACT2_FSCTL", 0, DEFDESCRIPT }, 167 { 10, "TRANSACT2_IOCTL", 0, DEFDESCRIPT }, 168 { 11, "TRANSACT2_FINDNOTIFYFIRST", 0, DEFDESCRIPT }, 169 { 12, "TRANSACT2_FINDNOTIFYNEXT", 0, DEFDESCRIPT }, 170 { 13, "TRANSACT2_MKDIR", 0, DEFDESCRIPT }, 171 { -1, NULL, 0, DEFDESCRIPT } 172 }; 173 174 175 static void 176 print_trans2(netdissect_options *ndo, 177 const u_char *words, const u_char *dat, const u_char *buf, const u_char *maxbuf) 178 { 179 u_int bcc; 180 static const struct smbfnsint *fn = &trans2_fns[0]; 181 const u_char *data, *param; 182 const u_char *w = words + 1; 183 const char *f1 = NULL, *f2 = NULL; 184 int pcnt, dcnt; 185 186 ND_TCHECK(words[0]); 187 if (request) { 188 ND_TCHECK2(w[14 * 2], 2); 189 pcnt = EXTRACT_LE_16BITS(w + 9 * 2); 190 param = buf + EXTRACT_LE_16BITS(w + 10 * 2); 191 dcnt = EXTRACT_LE_16BITS(w + 11 * 2); 192 data = buf + EXTRACT_LE_16BITS(w + 12 * 2); 193 fn = smbfindint(EXTRACT_LE_16BITS(w + 14 * 2), trans2_fns); 194 } else { 195 if (words[0] == 0) { 196 ND_PRINT((ndo, "%s\n", fn->name)); 197 ND_PRINT((ndo, "Trans2Interim\n")); 198 return; 199 } 200 ND_TCHECK2(w[7 * 2], 2); 201 pcnt = EXTRACT_LE_16BITS(w + 3 * 2); 202 param = buf + EXTRACT_LE_16BITS(w + 4 * 2); 203 dcnt = EXTRACT_LE_16BITS(w + 6 * 2); 204 data = buf + EXTRACT_LE_16BITS(w + 7 * 2); 205 } 206 207 ND_PRINT((ndo, "%s param_length=%d data_length=%d\n", fn->name, pcnt, dcnt)); 208 209 if (request) { 210 if (words[0] == 8) { 211 smb_fdata(ndo, words + 1, 212 "Trans2Secondary\nTotParam=[d]\nTotData=[d]\nParamCnt=[d]\nParamOff=[d]\nParamDisp=[d]\nDataCnt=[d]\nDataOff=[d]\nDataDisp=[d]\nHandle=[d]\n", 213 maxbuf, unicodestr); 214 return; 215 } else { 216 smb_fdata(ndo, words + 1, 217 "TotParam=[d]\nTotData=[d]\nMaxParam=[d]\nMaxData=[d]\nMaxSetup=[b][P1]\nFlags=[w]\nTimeOut=[D]\nRes1=[w]\nParamCnt=[d]\nParamOff=[d]\nDataCnt=[d]\nDataOff=[d]\nSetupCnt=[b][P1]\n", 218 words + 1 + 14 * 2, unicodestr); 219 } 220 f1 = fn->descript.req_f1; 221 f2 = fn->descript.req_f2; 222 } else { 223 smb_fdata(ndo, words + 1, 224 "TotParam=[d]\nTotData=[d]\nRes1=[w]\nParamCnt=[d]\nParamOff=[d]\nParamDisp[d]\nDataCnt=[d]\nDataOff=[d]\nDataDisp=[d]\nSetupCnt=[b][P1]\n", 225 words + 1 + 10 * 2, unicodestr); 226 f1 = fn->descript.rep_f1; 227 f2 = fn->descript.rep_f2; 228 } 229 230 ND_TCHECK2(*dat, 2); 231 bcc = EXTRACT_LE_16BITS(dat); 232 ND_PRINT((ndo, "smb_bcc=%u\n", bcc)); 233 if (fn->descript.fn) 234 (*fn->descript.fn)(ndo, param, data, pcnt, dcnt); 235 else { 236 smb_fdata(ndo, param, f1 ? f1 : "Parameters=\n", param + pcnt, unicodestr); 237 smb_fdata(ndo, data, f2 ? f2 : "Data=\n", data + dcnt, unicodestr); 238 } 239 return; 240 trunc: 241 ND_PRINT((ndo, "%s", tstr)); 242 } 243 244 static void 245 print_browse(netdissect_options *ndo, 246 const u_char *param, int paramlen, const u_char *data, int datalen) 247 { 248 const u_char *maxbuf = data + datalen; 249 int command; 250 251 ND_TCHECK(data[0]); 252 command = data[0]; 253 254 smb_fdata(ndo, param, "BROWSE PACKET\n|Param ", param+paramlen, unicodestr); 255 256 switch (command) { 257 case 0xF: 258 data = smb_fdata(ndo, data, 259 "BROWSE PACKET:\nType=[B] (LocalMasterAnnouncement)\nUpdateCount=[w]\nRes1=[B]\nAnnounceInterval=[d]\nName=[n2]\nMajorVersion=[B]\nMinorVersion=[B]\nServerType=[W]\nElectionVersion=[w]\nBrowserConstant=[w]\n", 260 maxbuf, unicodestr); 261 break; 262 263 case 0x1: 264 data = smb_fdata(ndo, data, 265 "BROWSE PACKET:\nType=[B] (HostAnnouncement)\nUpdateCount=[w]\nRes1=[B]\nAnnounceInterval=[d]\nName=[n2]\nMajorVersion=[B]\nMinorVersion=[B]\nServerType=[W]\nElectionVersion=[w]\nBrowserConstant=[w]\n", 266 maxbuf, unicodestr); 267 break; 268 269 case 0x2: 270 data = smb_fdata(ndo, data, 271 "BROWSE PACKET:\nType=[B] (AnnouncementRequest)\nFlags=[B]\nReplySystemName=[S]\n", 272 maxbuf, unicodestr); 273 break; 274 275 case 0xc: 276 data = smb_fdata(ndo, data, 277 "BROWSE PACKET:\nType=[B] (WorkgroupAnnouncement)\nUpdateCount=[w]\nRes1=[B]\nAnnounceInterval=[d]\nName=[n2]\nMajorVersion=[B]\nMinorVersion=[B]\nServerType=[W]\nCommentPointer=[W]\nServerName=[S]\n", 278 maxbuf, unicodestr); 279 break; 280 281 case 0x8: 282 data = smb_fdata(ndo, data, 283 "BROWSE PACKET:\nType=[B] (ElectionFrame)\nElectionVersion=[B]\nOSSummary=[W]\nUptime=[(W, W)]\nServerName=[S]\n", 284 maxbuf, unicodestr); 285 break; 286 287 case 0xb: 288 data = smb_fdata(ndo, data, 289 "BROWSE PACKET:\nType=[B] (BecomeBackupBrowser)\nName=[S]\n", 290 maxbuf, unicodestr); 291 break; 292 293 case 0x9: 294 data = smb_fdata(ndo, data, 295 "BROWSE PACKET:\nType=[B] (GetBackupList)\nListCount?=[B]\nToken=[W]\n", 296 maxbuf, unicodestr); 297 break; 298 299 case 0xa: 300 data = smb_fdata(ndo, data, 301 "BROWSE PACKET:\nType=[B] (BackupListResponse)\nServerCount?=[B]\nToken=[W]\n*Name=[S]\n", 302 maxbuf, unicodestr); 303 break; 304 305 case 0xd: 306 data = smb_fdata(ndo, data, 307 "BROWSE PACKET:\nType=[B] (MasterAnnouncement)\nMasterName=[S]\n", 308 maxbuf, unicodestr); 309 break; 310 311 case 0xe: 312 data = smb_fdata(ndo, data, 313 "BROWSE PACKET:\nType=[B] (ResetBrowser)\nOptions=[B]\n", maxbuf, unicodestr); 314 break; 315 316 default: 317 data = smb_fdata(ndo, data, "Unknown Browser Frame ", maxbuf, unicodestr); 318 break; 319 } 320 return; 321 trunc: 322 ND_PRINT((ndo, "%s", tstr)); 323 } 324 325 326 static void 327 print_ipc(netdissect_options *ndo, 328 const u_char *param, int paramlen, const u_char *data, int datalen) 329 { 330 if (paramlen) 331 smb_fdata(ndo, param, "Command=[w]\nStr1=[S]\nStr2=[S]\n", param + paramlen, 332 unicodestr); 333 if (datalen) 334 smb_fdata(ndo, data, "IPC ", data + datalen, unicodestr); 335 } 336 337 338 static void 339 print_trans(netdissect_options *ndo, 340 const u_char *words, const u_char *data1, const u_char *buf, const u_char *maxbuf) 341 { 342 u_int bcc; 343 const char *f1, *f2, *f3, *f4; 344 const u_char *data, *param; 345 const u_char *w = words + 1; 346 int datalen, paramlen; 347 348 if (request) { 349 ND_TCHECK2(w[12 * 2], 2); 350 paramlen = EXTRACT_LE_16BITS(w + 9 * 2); 351 param = buf + EXTRACT_LE_16BITS(w + 10 * 2); 352 datalen = EXTRACT_LE_16BITS(w + 11 * 2); 353 data = buf + EXTRACT_LE_16BITS(w + 12 * 2); 354 f1 = "TotParamCnt=[d] \nTotDataCnt=[d] \nMaxParmCnt=[d] \nMaxDataCnt=[d]\nMaxSCnt=[d] \nTransFlags=[w] \nRes1=[w] \nRes2=[w] \nRes3=[w]\nParamCnt=[d] \nParamOff=[d] \nDataCnt=[d] \nDataOff=[d] \nSUCnt=[d]\n"; 355 f2 = "|Name=[S]\n"; 356 f3 = "|Param "; 357 f4 = "|Data "; 358 } else { 359 ND_TCHECK2(w[7 * 2], 2); 360 paramlen = EXTRACT_LE_16BITS(w + 3 * 2); 361 param = buf + EXTRACT_LE_16BITS(w + 4 * 2); 362 datalen = EXTRACT_LE_16BITS(w + 6 * 2); 363 data = buf + EXTRACT_LE_16BITS(w + 7 * 2); 364 f1 = "TotParamCnt=[d] \nTotDataCnt=[d] \nRes1=[d]\nParamCnt=[d] \nParamOff=[d] \nRes2=[d] \nDataCnt=[d] \nDataOff=[d] \nRes3=[d]\nLsetup=[d]\n"; 365 f2 = "|Unknown "; 366 f3 = "|Param "; 367 f4 = "|Data "; 368 } 369 370 smb_fdata(ndo, words + 1, f1, min(words + 1 + 2 * words[0], maxbuf), 371 unicodestr); 372 373 ND_TCHECK2(*data1, 2); 374 bcc = EXTRACT_LE_16BITS(data1); 375 ND_PRINT((ndo, "smb_bcc=%u\n", bcc)); 376 if (bcc > 0) { 377 smb_fdata(ndo, data1 + 2, f2, maxbuf - (paramlen + datalen), unicodestr); 378 379 if (strcmp((const char *)(data1 + 2), "\\MAILSLOT\\BROWSE") == 0) { 380 print_browse(ndo, param, paramlen, data, datalen); 381 return; 382 } 383 384 if (strcmp((const char *)(data1 + 2), "\\PIPE\\LANMAN") == 0) { 385 print_ipc(ndo, param, paramlen, data, datalen); 386 return; 387 } 388 389 if (paramlen) 390 smb_fdata(ndo, param, f3, min(param + paramlen, maxbuf), unicodestr); 391 if (datalen) 392 smb_fdata(ndo, data, f4, min(data + datalen, maxbuf), unicodestr); 393 } 394 return; 395 trunc: 396 ND_PRINT((ndo, "%s", tstr)); 397 } 398 399 400 static void 401 print_negprot(netdissect_options *ndo, 402 const u_char *words, const u_char *data, const u_char *buf _U_, const u_char *maxbuf) 403 { 404 u_int wct, bcc; 405 const char *f1 = NULL, *f2 = NULL; 406 407 ND_TCHECK(words[0]); 408 wct = words[0]; 409 if (request) 410 f2 = "*|Dialect=[Y]\n"; 411 else { 412 if (wct == 1) 413 f1 = "Core Protocol\nDialectIndex=[d]"; 414 else if (wct == 17) 415 f1 = "NT1 Protocol\nDialectIndex=[d]\nSecMode=[B]\nMaxMux=[d]\nNumVcs=[d]\nMaxBuffer=[D]\nRawSize=[D]\nSessionKey=[W]\nCapabilities=[W]\nServerTime=[T3]TimeZone=[d]\nCryptKey="; 416 else if (wct == 13) 417 f1 = "Coreplus/Lanman1/Lanman2 Protocol\nDialectIndex=[d]\nSecMode=[w]\nMaxXMit=[d]\nMaxMux=[d]\nMaxVcs=[d]\nBlkMode=[w]\nSessionKey=[W]\nServerTime=[T1]TimeZone=[d]\nRes=[W]\nCryptKey="; 418 } 419 420 if (f1) 421 smb_fdata(ndo, words + 1, f1, min(words + 1 + wct * 2, maxbuf), 422 unicodestr); 423 else 424 print_data(ndo, words + 1, min(wct * 2, PTR_DIFF(maxbuf, words + 1))); 425 426 ND_TCHECK2(*data, 2); 427 bcc = EXTRACT_LE_16BITS(data); 428 ND_PRINT((ndo, "smb_bcc=%u\n", bcc)); 429 if (bcc > 0) { 430 if (f2) 431 smb_fdata(ndo, data + 2, f2, min(data + 2 + EXTRACT_LE_16BITS(data), 432 maxbuf), unicodestr); 433 else 434 print_data(ndo, data + 2, min(EXTRACT_LE_16BITS(data), PTR_DIFF(maxbuf, data + 2))); 435 } 436 return; 437 trunc: 438 ND_PRINT((ndo, "%s", tstr)); 439 } 440 441 static void 442 print_sesssetup(netdissect_options *ndo, 443 const u_char *words, const u_char *data, const u_char *buf _U_, const u_char *maxbuf) 444 { 445 u_int wct, bcc; 446 const char *f1 = NULL, *f2 = NULL; 447 448 ND_TCHECK(words[0]); 449 wct = words[0]; 450 if (request) { 451 if (wct == 10) 452 f1 = "Com2=[w]\nOff2=[d]\nBufSize=[d]\nMpxMax=[d]\nVcNum=[d]\nSessionKey=[W]\nPassLen=[d]\nCryptLen=[d]\nCryptOff=[d]\nPass&Name=\n"; 453 else 454 f1 = "Com2=[B]\nRes1=[B]\nOff2=[d]\nMaxBuffer=[d]\nMaxMpx=[d]\nVcNumber=[d]\nSessionKey=[W]\nCaseInsensitivePasswordLength=[d]\nCaseSensitivePasswordLength=[d]\nRes=[W]\nCapabilities=[W]\nPass1&Pass2&Account&Domain&OS&LanMan=\n"; 455 } else { 456 if (wct == 3) { 457 f1 = "Com2=[w]\nOff2=[d]\nAction=[w]\n"; 458 } else if (wct == 13) { 459 f1 = "Com2=[B]\nRes=[B]\nOff2=[d]\nAction=[w]\n"; 460 f2 = "NativeOS=[S]\nNativeLanMan=[S]\nPrimaryDomain=[S]\n"; 461 } 462 } 463 464 if (f1) 465 smb_fdata(ndo, words + 1, f1, min(words + 1 + wct * 2, maxbuf), 466 unicodestr); 467 else 468 print_data(ndo, words + 1, min(wct * 2, PTR_DIFF(maxbuf, words + 1))); 469 470 ND_TCHECK2(*data, 2); 471 bcc = EXTRACT_LE_16BITS(data); 472 ND_PRINT((ndo, "smb_bcc=%u\n", bcc)); 473 if (bcc > 0) { 474 if (f2) 475 smb_fdata(ndo, data + 2, f2, min(data + 2 + EXTRACT_LE_16BITS(data), 476 maxbuf), unicodestr); 477 else 478 print_data(ndo, data + 2, min(EXTRACT_LE_16BITS(data), PTR_DIFF(maxbuf, data + 2))); 479 } 480 return; 481 trunc: 482 ND_PRINT((ndo, "%s", tstr)); 483 } 484 485 static void 486 print_lockingandx(netdissect_options *ndo, 487 const u_char *words, const u_char *data, const u_char *buf _U_, const u_char *maxbuf) 488 { 489 u_int wct, bcc; 490 const u_char *maxwords; 491 const char *f1 = NULL, *f2 = NULL; 492 493 ND_TCHECK(words[0]); 494 wct = words[0]; 495 if (request) { 496 f1 = "Com2=[w]\nOff2=[d]\nHandle=[d]\nLockType=[w]\nTimeOut=[D]\nUnlockCount=[d]\nLockCount=[d]\n"; 497 ND_TCHECK(words[7]); 498 if (words[7] & 0x10) 499 f2 = "*Process=[d]\n[P2]Offset=[M]\nLength=[M]\n"; 500 else 501 f2 = "*Process=[d]\nOffset=[D]\nLength=[D]\n"; 502 } else { 503 f1 = "Com2=[w]\nOff2=[d]\n"; 504 } 505 506 maxwords = min(words + 1 + wct * 2, maxbuf); 507 if (wct) 508 smb_fdata(ndo, words + 1, f1, maxwords, unicodestr); 509 510 ND_TCHECK2(*data, 2); 511 bcc = EXTRACT_LE_16BITS(data); 512 ND_PRINT((ndo, "smb_bcc=%u\n", bcc)); 513 if (bcc > 0) { 514 if (f2) 515 smb_fdata(ndo, data + 2, f2, min(data + 2 + EXTRACT_LE_16BITS(data), 516 maxbuf), unicodestr); 517 else 518 print_data(ndo, data + 2, min(EXTRACT_LE_16BITS(data), PTR_DIFF(maxbuf, data + 2))); 519 } 520 return; 521 trunc: 522 ND_PRINT((ndo, "%s", tstr)); 523 } 524 525 526 static const struct smbfns smb_fns[] = { 527 { -1, "SMBunknown", 0, DEFDESCRIPT }, 528 529 { SMBtcon, "SMBtcon", 0, 530 { NULL, "Path=[Z]\nPassword=[Z]\nDevice=[Z]\n", 531 "MaxXmit=[d]\nTreeId=[d]\n", NULL, 532 NULL } }, 533 534 { SMBtdis, "SMBtdis", 0, DEFDESCRIPT }, 535 { SMBexit, "SMBexit", 0, DEFDESCRIPT }, 536 { SMBioctl, "SMBioctl", 0, DEFDESCRIPT }, 537 538 { SMBecho, "SMBecho", 0, 539 { "ReverbCount=[d]\n", NULL, 540 "SequenceNum=[d]\n", NULL, 541 NULL } }, 542 543 { SMBulogoffX, "SMBulogoffX", FLG_CHAIN, DEFDESCRIPT }, 544 545 { SMBgetatr, "SMBgetatr", 0, 546 { NULL, "Path=[Z]\n", 547 "Attribute=[A]\nTime=[T2]Size=[D]\nRes=([w,w,w,w,w])\n", NULL, 548 NULL } }, 549 550 { SMBsetatr, "SMBsetatr", 0, 551 { "Attribute=[A]\nTime=[T2]Res=([w,w,w,w,w])\n", "Path=[Z]\n", 552 NULL, NULL, NULL } }, 553 554 { SMBchkpth, "SMBchkpth", 0, 555 { NULL, "Path=[Z]\n", NULL, NULL, NULL } }, 556 557 { SMBsearch, "SMBsearch", 0, 558 { "Count=[d]\nAttrib=[A]\n", 559 "Path=[Z]\nBlkType=[B]\nBlkLen=[d]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\nRes2=[W]\n", 560 "Count=[d]\n", 561 "BlkType=[B]\nBlkLen=[d]\n*\nRes1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\nRes2=[W]\nAttrib=[a]\nTime=[T1]Size=[D]\nName=[s13]\n", 562 NULL } }, 563 564 { SMBopen, "SMBopen", 0, 565 { "Mode=[w]\nAttribute=[A]\n", "Path=[Z]\n", 566 "Handle=[d]\nOAttrib=[A]\nTime=[T2]Size=[D]\nAccess=[w]\n", 567 NULL, NULL } }, 568 569 { SMBcreate, "SMBcreate", 0, 570 { "Attrib=[A]\nTime=[T2]", "Path=[Z]\n", "Handle=[d]\n", NULL, NULL } }, 571 572 { SMBmknew, "SMBmknew", 0, 573 { "Attrib=[A]\nTime=[T2]", "Path=[Z]\n", "Handle=[d]\n", NULL, NULL } }, 574 575 { SMBunlink, "SMBunlink", 0, 576 { "Attrib=[A]\n", "Path=[Z]\n", NULL, NULL, NULL } }, 577 578 { SMBread, "SMBread", 0, 579 { "Handle=[d]\nByteCount=[d]\nOffset=[D]\nCountLeft=[d]\n", NULL, 580 "Count=[d]\nRes=([w,w,w,w])\n", NULL, NULL } }, 581 582 { SMBwrite, "SMBwrite", 0, 583 { "Handle=[d]\nByteCount=[d]\nOffset=[D]\nCountLeft=[d]\n", NULL, 584 "Count=[d]\n", NULL, NULL } }, 585 586 { SMBclose, "SMBclose", 0, 587 { "Handle=[d]\nTime=[T2]", NULL, NULL, NULL, NULL } }, 588 589 { SMBmkdir, "SMBmkdir", 0, 590 { NULL, "Path=[Z]\n", NULL, NULL, NULL } }, 591 592 { SMBrmdir, "SMBrmdir", 0, 593 { NULL, "Path=[Z]\n", NULL, NULL, NULL } }, 594 595 { SMBdskattr, "SMBdskattr", 0, 596 { NULL, NULL, 597 "TotalUnits=[d]\nBlocksPerUnit=[d]\nBlockSize=[d]\nFreeUnits=[d]\nMedia=[w]\n", 598 NULL, NULL } }, 599 600 { SMBmv, "SMBmv", 0, 601 { "Attrib=[A]\n", "OldPath=[Z]\nNewPath=[Z]\n", NULL, NULL, NULL } }, 602 603 /* 604 * this is a Pathworks specific call, allowing the 605 * changing of the root path 606 */ 607 { pSETDIR, "SMBsetdir", 0, { NULL, "Path=[Z]\n", NULL, NULL, NULL } }, 608 609 { SMBlseek, "SMBlseek", 0, 610 { "Handle=[d]\nMode=[w]\nOffset=[D]\n", "Offset=[D]\n", NULL, NULL, NULL } }, 611 612 { SMBflush, "SMBflush", 0, { "Handle=[d]\n", NULL, NULL, NULL, NULL } }, 613 614 { SMBsplopen, "SMBsplopen", 0, 615 { "SetupLen=[d]\nMode=[w]\n", "Ident=[Z]\n", "Handle=[d]\n", 616 NULL, NULL } }, 617 618 { SMBsplclose, "SMBsplclose", 0, 619 { "Handle=[d]\n", NULL, NULL, NULL, NULL } }, 620 621 { SMBsplretq, "SMBsplretq", 0, 622 { "MaxCount=[d]\nStartIndex=[d]\n", NULL, 623 "Count=[d]\nIndex=[d]\n", 624 "*Time=[T2]Status=[B]\nJobID=[d]\nSize=[D]\nRes=[B]Name=[s16]\n", 625 NULL } }, 626 627 { SMBsplwr, "SMBsplwr", 0, 628 { "Handle=[d]\n", NULL, NULL, NULL, NULL } }, 629 630 { SMBlock, "SMBlock", 0, 631 { "Handle=[d]\nCount=[D]\nOffset=[D]\n", NULL, NULL, NULL, NULL } }, 632 633 { SMBunlock, "SMBunlock", 0, 634 { "Handle=[d]\nCount=[D]\nOffset=[D]\n", NULL, NULL, NULL, NULL } }, 635 636 /* CORE+ PROTOCOL FOLLOWS */ 637 638 { SMBreadbraw, "SMBreadbraw", 0, 639 { "Handle=[d]\nOffset=[D]\nMaxCount=[d]\nMinCount=[d]\nTimeOut=[D]\nRes=[d]\n", 640 NULL, NULL, NULL, NULL } }, 641 642 { SMBwritebraw, "SMBwritebraw", 0, 643 { "Handle=[d]\nTotalCount=[d]\nRes=[w]\nOffset=[D]\nTimeOut=[D]\nWMode=[w]\nRes2=[W]\n|DataSize=[d]\nDataOff=[d]\n", 644 NULL, "WriteRawAck", NULL, NULL } }, 645 646 { SMBwritec, "SMBwritec", 0, 647 { NULL, NULL, "Count=[d]\n", NULL, NULL } }, 648 649 { SMBwriteclose, "SMBwriteclose", 0, 650 { "Handle=[d]\nCount=[d]\nOffset=[D]\nTime=[T2]Res=([w,w,w,w,w,w])", 651 NULL, "Count=[d]\n", NULL, NULL } }, 652 653 { SMBlockread, "SMBlockread", 0, 654 { "Handle=[d]\nByteCount=[d]\nOffset=[D]\nCountLeft=[d]\n", NULL, 655 "Count=[d]\nRes=([w,w,w,w])\n", NULL, NULL } }, 656 657 { SMBwriteunlock, "SMBwriteunlock", 0, 658 { "Handle=[d]\nByteCount=[d]\nOffset=[D]\nCountLeft=[d]\n", NULL, 659 "Count=[d]\n", NULL, NULL } }, 660 661 { SMBreadBmpx, "SMBreadBmpx", 0, 662 { "Handle=[d]\nOffset=[D]\nMaxCount=[d]\nMinCount=[d]\nTimeOut=[D]\nRes=[w]\n", 663 NULL, 664 "Offset=[D]\nTotCount=[d]\nRemaining=[d]\nRes=([w,w])\nDataSize=[d]\nDataOff=[d]\n", 665 NULL, NULL } }, 666 667 { SMBwriteBmpx, "SMBwriteBmpx", 0, 668 { "Handle=[d]\nTotCount=[d]\nRes=[w]\nOffset=[D]\nTimeOut=[D]\nWMode=[w]\nRes2=[W]\nDataSize=[d]\nDataOff=[d]\n", NULL, 669 "Remaining=[d]\n", NULL, NULL } }, 670 671 { SMBwriteBs, "SMBwriteBs", 0, 672 { "Handle=[d]\nTotCount=[d]\nOffset=[D]\nRes=[W]\nDataSize=[d]\nDataOff=[d]\n", 673 NULL, "Count=[d]\n", NULL, NULL } }, 674 675 { SMBsetattrE, "SMBsetattrE", 0, 676 { "Handle=[d]\nCreationTime=[T2]AccessTime=[T2]ModifyTime=[T2]", NULL, 677 NULL, NULL, NULL } }, 678 679 { SMBgetattrE, "SMBgetattrE", 0, 680 { "Handle=[d]\n", NULL, 681 "CreationTime=[T2]AccessTime=[T2]ModifyTime=[T2]Size=[D]\nAllocSize=[D]\nAttribute=[A]\n", 682 NULL, NULL } }, 683 684 { SMBtranss, "SMBtranss", 0, DEFDESCRIPT }, 685 { SMBioctls, "SMBioctls", 0, DEFDESCRIPT }, 686 687 { SMBcopy, "SMBcopy", 0, 688 { "TreeID2=[d]\nOFun=[w]\nFlags=[w]\n", "Path=[S]\nNewPath=[S]\n", 689 "CopyCount=[d]\n", "|ErrStr=[S]\n", NULL } }, 690 691 { SMBmove, "SMBmove", 0, 692 { "TreeID2=[d]\nOFun=[w]\nFlags=[w]\n", "Path=[S]\nNewPath=[S]\n", 693 "MoveCount=[d]\n", "|ErrStr=[S]\n", NULL } }, 694 695 { SMBopenX, "SMBopenX", FLG_CHAIN, 696 { "Com2=[w]\nOff2=[d]\nFlags=[w]\nMode=[w]\nSearchAttrib=[A]\nAttrib=[A]\nTime=[T2]OFun=[w]\nSize=[D]\nTimeOut=[D]\nRes=[W]\n", 697 "Path=[S]\n", 698 "Com2=[w]\nOff2=[d]\nHandle=[d]\nAttrib=[A]\nTime=[T2]Size=[D]\nAccess=[w]\nType=[w]\nState=[w]\nAction=[w]\nFileID=[W]\nRes=[w]\n", 699 NULL, NULL } }, 700 701 { SMBreadX, "SMBreadX", FLG_CHAIN, 702 { "Com2=[w]\nOff2=[d]\nHandle=[d]\nOffset=[D]\nMaxCount=[d]\nMinCount=[d]\nTimeOut=[D]\nCountLeft=[d]\n", 703 NULL, 704 "Com2=[w]\nOff2=[d]\nRemaining=[d]\nRes=[W]\nDataSize=[d]\nDataOff=[d]\nRes=([w,w,w,w])\n", 705 NULL, NULL } }, 706 707 { SMBwriteX, "SMBwriteX", FLG_CHAIN, 708 { "Com2=[w]\nOff2=[d]\nHandle=[d]\nOffset=[D]\nTimeOut=[D]\nWMode=[w]\nCountLeft=[d]\nRes=[w]\nDataSize=[d]\nDataOff=[d]\n", 709 NULL, 710 "Com2=[w]\nOff2=[d]\nCount=[d]\nRemaining=[d]\nRes=[W]\n", 711 NULL, NULL } }, 712 713 { SMBffirst, "SMBffirst", 0, 714 { "Count=[d]\nAttrib=[A]\n", 715 "Path=[Z]\nBlkType=[B]\nBlkLen=[d]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\n", 716 "Count=[d]\n", 717 "BlkType=[B]\nBlkLen=[d]\n*\nRes1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\nRes2=[W]\nAttrib=[a]\nTime=[T1]Size=[D]\nName=[s13]\n", 718 NULL } }, 719 720 { SMBfunique, "SMBfunique", 0, 721 { "Count=[d]\nAttrib=[A]\n", 722 "Path=[Z]\nBlkType=[B]\nBlkLen=[d]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\n", 723 "Count=[d]\n", 724 "BlkType=[B]\nBlkLen=[d]\n*\nRes1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\nRes2=[W]\nAttrib=[a]\nTime=[T1]Size=[D]\nName=[s13]\n", 725 NULL } }, 726 727 { SMBfclose, "SMBfclose", 0, 728 { "Count=[d]\nAttrib=[A]\n", 729 "Path=[Z]\nBlkType=[B]\nBlkLen=[d]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\n", 730 "Count=[d]\n", 731 "BlkType=[B]\nBlkLen=[d]\n*\nRes1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\nRes2=[W]\nAttrib=[a]\nTime=[T1]Size=[D]\nName=[s13]\n", 732 NULL } }, 733 734 { SMBfindnclose, "SMBfindnclose", 0, 735 { "Handle=[d]\n", NULL, NULL, NULL, NULL } }, 736 737 { SMBfindclose, "SMBfindclose", 0, 738 { "Handle=[d]\n", NULL, NULL, NULL, NULL } }, 739 740 { SMBsends, "SMBsends", 0, 741 { NULL, "Source=[Z]\nDest=[Z]\n", NULL, NULL, NULL } }, 742 743 { SMBsendstrt, "SMBsendstrt", 0, 744 { NULL, "Source=[Z]\nDest=[Z]\n", "GroupID=[d]\n", NULL, NULL } }, 745 746 { SMBsendend, "SMBsendend", 0, 747 { "GroupID=[d]\n", NULL, NULL, NULL, NULL } }, 748 749 { SMBsendtxt, "SMBsendtxt", 0, 750 { "GroupID=[d]\n", NULL, NULL, NULL, NULL } }, 751 752 { SMBsendb, "SMBsendb", 0, 753 { NULL, "Source=[Z]\nDest=[Z]\n", NULL, NULL, NULL } }, 754 755 { SMBfwdname, "SMBfwdname", 0, DEFDESCRIPT }, 756 { SMBcancelf, "SMBcancelf", 0, DEFDESCRIPT }, 757 { SMBgetmac, "SMBgetmac", 0, DEFDESCRIPT }, 758 759 { SMBnegprot, "SMBnegprot", 0, 760 { NULL, NULL, NULL, NULL, print_negprot } }, 761 762 { SMBsesssetupX, "SMBsesssetupX", FLG_CHAIN, 763 { NULL, NULL, NULL, NULL, print_sesssetup } }, 764 765 { SMBtconX, "SMBtconX", FLG_CHAIN, 766 { "Com2=[w]\nOff2=[d]\nFlags=[w]\nPassLen=[d]\nPasswd&Path&Device=\n", 767 NULL, "Com2=[w]\nOff2=[d]\n", "ServiceType=[R]\n", NULL } }, 768 769 { SMBlockingX, "SMBlockingX", FLG_CHAIN, 770 { NULL, NULL, NULL, NULL, print_lockingandx } }, 771 772 { SMBtrans2, "SMBtrans2", 0, { NULL, NULL, NULL, NULL, print_trans2 } }, 773 774 { SMBtranss2, "SMBtranss2", 0, DEFDESCRIPT }, 775 { SMBctemp, "SMBctemp", 0, DEFDESCRIPT }, 776 { SMBreadBs, "SMBreadBs", 0, DEFDESCRIPT }, 777 { SMBtrans, "SMBtrans", 0, { NULL, NULL, NULL, NULL, print_trans } }, 778 779 { SMBnttrans, "SMBnttrans", 0, DEFDESCRIPT }, 780 { SMBnttranss, "SMBnttranss", 0, DEFDESCRIPT }, 781 782 { SMBntcreateX, "SMBntcreateX", FLG_CHAIN, 783 { "Com2=[w]\nOff2=[d]\nRes=[b]\nNameLen=[ld]\nFlags=[W]\nRootDirectoryFid=[D]\nAccessMask=[W]\nAllocationSize=[L]\nExtFileAttributes=[W]\nShareAccess=[W]\nCreateDisposition=[W]\nCreateOptions=[W]\nImpersonationLevel=[W]\nSecurityFlags=[b]\n", 784 "Path=[C]\n", 785 "Com2=[w]\nOff2=[d]\nOplockLevel=[b]\nFid=[d]\nCreateAction=[W]\nCreateTime=[T3]LastAccessTime=[T3]LastWriteTime=[T3]ChangeTime=[T3]ExtFileAttributes=[W]\nAllocationSize=[L]\nEndOfFile=[L]\nFileType=[w]\nDeviceState=[w]\nDirectory=[b]\n", 786 NULL, NULL } }, 787 788 { SMBntcancel, "SMBntcancel", 0, DEFDESCRIPT }, 789 790 { -1, NULL, 0, DEFDESCRIPT } 791 }; 792 793 794 /* 795 * print a SMB message 796 */ 797 static void 798 print_smb(netdissect_options *ndo, 799 const u_char *buf, const u_char *maxbuf) 800 { 801 uint16_t flags2; 802 int nterrcodes; 803 int command; 804 uint32_t nterror; 805 const u_char *words, *maxwords, *data; 806 const struct smbfns *fn; 807 const char *fmt_smbheader = 808 "[P4]SMB Command = [B]\nError class = [BP1]\nError code = [d]\nFlags1 = [B]\nFlags2 = [B][P13]\nTree ID = [d]\nProc ID = [d]\nUID = [d]\nMID = [d]\nWord Count = [b]\n"; 809 int smboffset; 810 811 ND_TCHECK(buf[9]); 812 request = (buf[9] & 0x80) ? 0 : 1; 813 flags2 = EXTRACT_LE_16BITS(&buf[10]); 814 unicodestr = flags2 & 0x8000; 815 nterrcodes = flags2 & 0x4000; 816 startbuf = buf; 817 818 command = buf[4]; 819 820 fn = smbfind(command, smb_fns); 821 822 if (ndo->ndo_vflag > 1) 823 ND_PRINT((ndo, "\n")); 824 825 ND_PRINT((ndo, "SMB PACKET: %s (%s)\n", fn->name, request ? "REQUEST" : "REPLY")); 826 827 if (ndo->ndo_vflag < 2) 828 return; 829 830 /* print out the header */ 831 smb_fdata(ndo, buf, fmt_smbheader, buf + 33, unicodestr); 832 833 if (nterrcodes) { 834 nterror = EXTRACT_LE_32BITS(&buf[5]); 835 if (nterror) 836 ND_PRINT((ndo, "NTError = %s\n", nt_errstr(nterror))); 837 } else { 838 if (buf[5]) 839 ND_PRINT((ndo, "SMBError = %s\n", smb_errstr(buf[5], EXTRACT_LE_16BITS(&buf[7])))); 840 } 841 842 smboffset = 32; 843 844 for (;;) { 845 const char *f1, *f2; 846 int wct; 847 u_int bcc; 848 int newsmboffset; 849 850 words = buf + smboffset; 851 ND_TCHECK(words[0]); 852 wct = words[0]; 853 data = words + 1 + wct * 2; 854 maxwords = min(data, maxbuf); 855 856 if (request) { 857 f1 = fn->descript.req_f1; 858 f2 = fn->descript.req_f2; 859 } else { 860 f1 = fn->descript.rep_f1; 861 f2 = fn->descript.rep_f2; 862 } 863 864 if (fn->descript.fn) 865 (*fn->descript.fn)(ndo, words, data, buf, maxbuf); 866 else { 867 if (wct) { 868 if (f1) 869 smb_fdata(ndo, words + 1, f1, words + 1 + wct * 2, unicodestr); 870 else { 871 int i; 872 int v; 873 874 for (i = 0; &words[1 + 2 * i] < maxwords; i++) { 875 ND_TCHECK2(words[1 + 2 * i], 2); 876 v = EXTRACT_LE_16BITS(words + 1 + 2 * i); 877 ND_PRINT((ndo, "smb_vwv[%d]=%d (0x%X)\n", i, v, v)); 878 } 879 } 880 } 881 882 ND_TCHECK2(*data, 2); 883 bcc = EXTRACT_LE_16BITS(data); 884 ND_PRINT((ndo, "smb_bcc=%u\n", bcc)); 885 if (f2) { 886 if (bcc > 0) 887 smb_fdata(ndo, data + 2, f2, data + 2 + bcc, unicodestr); 888 } else { 889 if (bcc > 0) { 890 ND_PRINT((ndo, "smb_buf[]=\n")); 891 print_data(ndo, data + 2, min(bcc, PTR_DIFF(maxbuf, data + 2))); 892 } 893 } 894 } 895 896 if ((fn->flags & FLG_CHAIN) == 0) 897 break; 898 if (wct == 0) 899 break; 900 ND_TCHECK(words[1]); 901 command = words[1]; 902 if (command == 0xFF) 903 break; 904 ND_TCHECK2(words[3], 2); 905 newsmboffset = EXTRACT_LE_16BITS(words + 3); 906 907 fn = smbfind(command, smb_fns); 908 909 ND_PRINT((ndo, "\nSMB PACKET: %s (%s) (CHAINED)\n", 910 fn->name, request ? "REQUEST" : "REPLY")); 911 if (newsmboffset <= smboffset) { 912 ND_PRINT((ndo, "Bad andX offset: %u <= %u\n", newsmboffset, smboffset)); 913 break; 914 } 915 smboffset = newsmboffset; 916 } 917 918 ND_PRINT((ndo, "\n")); 919 return; 920 trunc: 921 ND_PRINT((ndo, "%s", tstr)); 922 } 923 924 925 /* 926 * print a NBT packet received across tcp on port 139 927 */ 928 void 929 nbt_tcp_print(netdissect_options *ndo, 930 const u_char *data, int length) 931 { 932 int caplen; 933 int type; 934 u_int nbt_len; 935 const u_char *maxbuf; 936 937 if (length < 4) 938 goto trunc; 939 if (ndo->ndo_snapend < data) 940 goto trunc; 941 caplen = ndo->ndo_snapend - data; 942 if (caplen < 4) 943 goto trunc; 944 maxbuf = data + caplen; 945 type = data[0]; 946 nbt_len = EXTRACT_16BITS(data + 2); 947 length -= 4; 948 caplen -= 4; 949 950 startbuf = data; 951 952 if (ndo->ndo_vflag < 2) { 953 ND_PRINT((ndo, " NBT Session Packet: ")); 954 switch (type) { 955 case 0x00: 956 ND_PRINT((ndo, "Session Message")); 957 break; 958 959 case 0x81: 960 ND_PRINT((ndo, "Session Request")); 961 break; 962 963 case 0x82: 964 ND_PRINT((ndo, "Session Granted")); 965 break; 966 967 case 0x83: 968 { 969 int ecode; 970 971 if (nbt_len < 4) 972 goto trunc; 973 if (length < 4) 974 goto trunc; 975 if (caplen < 4) 976 goto trunc; 977 ecode = data[4]; 978 979 ND_PRINT((ndo, "Session Reject, ")); 980 switch (ecode) { 981 case 0x80: 982 ND_PRINT((ndo, "Not listening on called name")); 983 break; 984 case 0x81: 985 ND_PRINT((ndo, "Not listening for calling name")); 986 break; 987 case 0x82: 988 ND_PRINT((ndo, "Called name not present")); 989 break; 990 case 0x83: 991 ND_PRINT((ndo, "Called name present, but insufficient resources")); 992 break; 993 default: 994 ND_PRINT((ndo, "Unspecified error 0x%X", ecode)); 995 break; 996 } 997 } 998 break; 999 1000 case 0x85: 1001 ND_PRINT((ndo, "Session Keepalive")); 1002 break; 1003 1004 default: 1005 data = smb_fdata(ndo, data, "Unknown packet type [rB]", maxbuf, 0); 1006 break; 1007 } 1008 } else { 1009 ND_PRINT((ndo, "\n>>> NBT Session Packet\n")); 1010 switch (type) { 1011 case 0x00: 1012 data = smb_fdata(ndo, data, "[P1]NBT Session Message\nFlags=[B]\nLength=[rd]\n", 1013 data + 4, 0); 1014 if (data == NULL) 1015 break; 1016 if (nbt_len >= 4 && caplen >= 4 && memcmp(data,"\377SMB",4) == 0) { 1017 if ((int)nbt_len > caplen) { 1018 if ((int)nbt_len > length) 1019 ND_PRINT((ndo, "WARNING: Packet is continued in later TCP segments\n")); 1020 else 1021 ND_PRINT((ndo, "WARNING: Short packet. Try increasing the snap length by %d\n", 1022 nbt_len - caplen)); 1023 } 1024 print_smb(ndo, data, maxbuf > data + nbt_len ? data + nbt_len : maxbuf); 1025 } else 1026 ND_PRINT((ndo, "Session packet:(raw data or continuation?)\n")); 1027 break; 1028 1029 case 0x81: 1030 data = smb_fdata(ndo, data, 1031 "[P1]NBT Session Request\nFlags=[B]\nLength=[rd]\nDestination=[n1]\nSource=[n1]\n", 1032 maxbuf, 0); 1033 break; 1034 1035 case 0x82: 1036 data = smb_fdata(ndo, data, "[P1]NBT Session Granted\nFlags=[B]\nLength=[rd]\n", maxbuf, 0); 1037 break; 1038 1039 case 0x83: 1040 { 1041 const u_char *origdata; 1042 int ecode; 1043 1044 origdata = data; 1045 data = smb_fdata(ndo, data, "[P1]NBT SessionReject\nFlags=[B]\nLength=[rd]\nReason=[B]\n", 1046 maxbuf, 0); 1047 if (data == NULL) 1048 break; 1049 if (nbt_len >= 1 && caplen >= 1) { 1050 ecode = origdata[4]; 1051 switch (ecode) { 1052 case 0x80: 1053 ND_PRINT((ndo, "Not listening on called name\n")); 1054 break; 1055 case 0x81: 1056 ND_PRINT((ndo, "Not listening for calling name\n")); 1057 break; 1058 case 0x82: 1059 ND_PRINT((ndo, "Called name not present\n")); 1060 break; 1061 case 0x83: 1062 ND_PRINT((ndo, "Called name present, but insufficient resources\n")); 1063 break; 1064 default: 1065 ND_PRINT((ndo, "Unspecified error 0x%X\n", ecode)); 1066 break; 1067 } 1068 } 1069 } 1070 break; 1071 1072 case 0x85: 1073 data = smb_fdata(ndo, data, "[P1]NBT Session Keepalive\nFlags=[B]\nLength=[rd]\n", maxbuf, 0); 1074 break; 1075 1076 default: 1077 data = smb_fdata(ndo, data, "NBT - Unknown packet type\nType=[B]\n", maxbuf, 0); 1078 break; 1079 } 1080 ND_PRINT((ndo, "\n")); 1081 } 1082 return; 1083 trunc: 1084 ND_PRINT((ndo, "%s", tstr)); 1085 } 1086 1087 static const struct tok opcode_str[] = { 1088 { 0, "QUERY" }, 1089 { 5, "REGISTRATION" }, 1090 { 6, "RELEASE" }, 1091 { 7, "WACK" }, 1092 { 8, "REFRESH(8)" }, 1093 { 9, "REFRESH" }, 1094 { 15, "MULTIHOMED REGISTRATION" }, 1095 { 0, NULL } 1096 }; 1097 1098 /* 1099 * print a NBT packet received across udp on port 137 1100 */ 1101 void 1102 nbt_udp137_print(netdissect_options *ndo, 1103 const u_char *data, int length) 1104 { 1105 const u_char *maxbuf = data + length; 1106 int name_trn_id, response, opcode, nm_flags, rcode; 1107 int qdcount, ancount, nscount, arcount; 1108 const u_char *p; 1109 int total, i; 1110 1111 ND_TCHECK2(data[10], 2); 1112 name_trn_id = EXTRACT_16BITS(data); 1113 response = (data[2] >> 7); 1114 opcode = (data[2] >> 3) & 0xF; 1115 nm_flags = ((data[2] & 0x7) << 4) + (data[3] >> 4); 1116 rcode = data[3] & 0xF; 1117 qdcount = EXTRACT_16BITS(data + 4); 1118 ancount = EXTRACT_16BITS(data + 6); 1119 nscount = EXTRACT_16BITS(data + 8); 1120 arcount = EXTRACT_16BITS(data + 10); 1121 startbuf = data; 1122 1123 if (maxbuf <= data) 1124 return; 1125 1126 if (ndo->ndo_vflag > 1) 1127 ND_PRINT((ndo, "\n>>> ")); 1128 1129 ND_PRINT((ndo, "NBT UDP PACKET(137): %s", tok2str(opcode_str, "OPUNKNOWN", opcode))); 1130 if (response) { 1131 ND_PRINT((ndo, "; %s", rcode ? "NEGATIVE" : "POSITIVE")); 1132 } 1133 ND_PRINT((ndo, "; %s; %s", response ? "RESPONSE" : "REQUEST", 1134 (nm_flags & 1) ? "BROADCAST" : "UNICAST")); 1135 1136 if (ndo->ndo_vflag < 2) 1137 return; 1138 1139 ND_PRINT((ndo, "\nTrnID=0x%X\nOpCode=%d\nNmFlags=0x%X\nRcode=%d\nQueryCount=%d\nAnswerCount=%d\nAuthorityCount=%d\nAddressRecCount=%d\n", 1140 name_trn_id, opcode, nm_flags, rcode, qdcount, ancount, nscount, 1141 arcount)); 1142 1143 p = data + 12; 1144 1145 total = ancount + nscount + arcount; 1146 1147 if (qdcount > 100 || total > 100) { 1148 ND_PRINT((ndo, "Corrupt packet??\n")); 1149 return; 1150 } 1151 1152 if (qdcount) { 1153 ND_PRINT((ndo, "QuestionRecords:\n")); 1154 for (i = 0; i < qdcount; i++) { 1155 p = smb_fdata(ndo, p, 1156 "|Name=[n1]\nQuestionType=[rw]\nQuestionClass=[rw]\n#", 1157 maxbuf, 0); 1158 if (p == NULL) 1159 goto out; 1160 } 1161 } 1162 1163 if (total) { 1164 ND_PRINT((ndo, "\nResourceRecords:\n")); 1165 for (i = 0; i < total; i++) { 1166 int rdlen; 1167 int restype; 1168 1169 p = smb_fdata(ndo, p, "Name=[n1]\n#", maxbuf, 0); 1170 if (p == NULL) 1171 goto out; 1172 restype = EXTRACT_16BITS(p); 1173 p = smb_fdata(ndo, p, "ResType=[rw]\nResClass=[rw]\nTTL=[rD]\n", p + 8, 0); 1174 if (p == NULL) 1175 goto out; 1176 rdlen = EXTRACT_16BITS(p); 1177 ND_PRINT((ndo, "ResourceLength=%d\nResourceData=\n", rdlen)); 1178 p += 2; 1179 if (rdlen == 6) { 1180 p = smb_fdata(ndo, p, "AddrType=[rw]\nAddress=[b.b.b.b]\n", p + rdlen, 0); 1181 if (p == NULL) 1182 goto out; 1183 } else { 1184 if (restype == 0x21) { 1185 int numnames; 1186 1187 ND_TCHECK(*p); 1188 numnames = p[0]; 1189 p = smb_fdata(ndo, p, "NumNames=[B]\n", p + 1, 0); 1190 if (p == NULL) 1191 goto out; 1192 while (numnames--) { 1193 p = smb_fdata(ndo, p, "Name=[n2]\t#", maxbuf, 0); 1194 if (p == NULL) 1195 goto out; 1196 ND_TCHECK(*p); 1197 if (p[0] & 0x80) 1198 ND_PRINT((ndo, "<GROUP> ")); 1199 switch (p[0] & 0x60) { 1200 case 0x00: ND_PRINT((ndo, "B ")); break; 1201 case 0x20: ND_PRINT((ndo, "P ")); break; 1202 case 0x40: ND_PRINT((ndo, "M ")); break; 1203 case 0x60: ND_PRINT((ndo, "_ ")); break; 1204 } 1205 if (p[0] & 0x10) 1206 ND_PRINT((ndo, "<DEREGISTERING> ")); 1207 if (p[0] & 0x08) 1208 ND_PRINT((ndo, "<CONFLICT> ")); 1209 if (p[0] & 0x04) 1210 ND_PRINT((ndo, "<ACTIVE> ")); 1211 if (p[0] & 0x02) 1212 ND_PRINT((ndo, "<PERMANENT> ")); 1213 ND_PRINT((ndo, "\n")); 1214 p += 2; 1215 } 1216 } else { 1217 print_data(ndo, p, min(rdlen, length - (p - data))); 1218 p += rdlen; 1219 } 1220 } 1221 } 1222 } 1223 1224 if (p < maxbuf) 1225 smb_fdata(ndo, p, "AdditionalData:\n", maxbuf, 0); 1226 1227 out: 1228 ND_PRINT((ndo, "\n")); 1229 return; 1230 trunc: 1231 ND_PRINT((ndo, "%s", tstr)); 1232 } 1233 1234 /* 1235 * Print an SMB-over-TCP packet received across tcp on port 445 1236 */ 1237 void 1238 smb_tcp_print(netdissect_options *ndo, 1239 const u_char * data, int length) 1240 { 1241 int caplen; 1242 u_int smb_len; 1243 const u_char *maxbuf; 1244 1245 if (length < 4) 1246 goto trunc; 1247 if (ndo->ndo_snapend < data) 1248 goto trunc; 1249 caplen = ndo->ndo_snapend - data; 1250 if (caplen < 4) 1251 goto trunc; 1252 maxbuf = data + caplen; 1253 smb_len = EXTRACT_24BITS(data + 1); 1254 length -= 4; 1255 caplen -= 4; 1256 1257 startbuf = data; 1258 data += 4; 1259 1260 if (smb_len >= 4 && caplen >= 4 && memcmp(data,"\377SMB",4) == 0) { 1261 if ((int)smb_len > caplen) { 1262 if ((int)smb_len > length) 1263 ND_PRINT((ndo, " WARNING: Packet is continued in later TCP segments\n")); 1264 else 1265 ND_PRINT((ndo, " WARNING: Short packet. Try increasing the snap length by %d\n", 1266 smb_len - caplen)); 1267 } else 1268 ND_PRINT((ndo, " ")); 1269 print_smb(ndo, data, maxbuf > data + smb_len ? data + smb_len : maxbuf); 1270 } else 1271 ND_PRINT((ndo, " SMB-over-TCP packet:(raw data or continuation?)\n")); 1272 return; 1273 trunc: 1274 ND_PRINT((ndo, "%s", tstr)); 1275 } 1276 1277 /* 1278 * print a NBT packet received across udp on port 138 1279 */ 1280 void 1281 nbt_udp138_print(netdissect_options *ndo, 1282 const u_char *data, int length) 1283 { 1284 const u_char *maxbuf = data + length; 1285 1286 if (maxbuf > ndo->ndo_snapend) 1287 maxbuf = ndo->ndo_snapend; 1288 if (maxbuf <= data) 1289 return; 1290 startbuf = data; 1291 1292 if (ndo->ndo_vflag < 2) { 1293 ND_PRINT((ndo, "NBT UDP PACKET(138)")); 1294 return; 1295 } 1296 1297 data = smb_fdata(ndo, data, 1298 "\n>>> NBT UDP PACKET(138) Res=[rw] ID=[rw] IP=[b.b.b.b] Port=[rd] Length=[rd] Res2=[rw]\nSourceName=[n1]\nDestName=[n1]\n#", 1299 maxbuf, 0); 1300 1301 if (data != NULL) { 1302 /* If there isn't enough data for "\377SMB", don't check for it. */ 1303 if (&data[3] >= maxbuf) 1304 goto out; 1305 1306 if (memcmp(data, "\377SMB",4) == 0) 1307 print_smb(ndo, data, maxbuf); 1308 } 1309 out: 1310 ND_PRINT((ndo, "\n")); 1311 } 1312 1313 1314 /* 1315 print netbeui frames 1316 */ 1317 struct nbf_strings { 1318 const char *name; 1319 const char *nonverbose; 1320 const char *verbose; 1321 } nbf_strings[0x20] = { 1322 { "Add Group Name Query", ", [P23]Name to add=[n2]#", 1323 "[P5]ResponseCorrelator=[w]\n[P16]Name to add=[n2]\n" }, 1324 { "Add Name Query", ", [P23]Name to add=[n2]#", 1325 "[P5]ResponseCorrelator=[w]\n[P16]Name to add=[n2]\n" }, 1326 { "Name In Conflict", NULL, NULL }, 1327 { "Status Query", NULL, NULL }, 1328 { NULL, NULL, NULL }, /* not used */ 1329 { NULL, NULL, NULL }, /* not used */ 1330 { NULL, NULL, NULL }, /* not used */ 1331 { "Terminate Trace", NULL, NULL }, 1332 { "Datagram", NULL, 1333 "[P7]Destination=[n2]\nSource=[n2]\n" }, 1334 { "Broadcast Datagram", NULL, 1335 "[P7]Destination=[n2]\nSource=[n2]\n" }, 1336 { "Name Query", ", [P7]Name=[n2]#", 1337 "[P1]SessionNumber=[B]\nNameType=[B][P2]\nResponseCorrelator=[w]\nName=[n2]\nName of sender=[n2]\n" }, 1338 { NULL, NULL, NULL }, /* not used */ 1339 { NULL, NULL, NULL }, /* not used */ 1340 { "Add Name Response", ", [P1]GroupName=[w] [P4]Destination=[n2] Source=[n2]#", 1341 "AddNameInProcess=[B]\nGroupName=[w]\nTransmitCorrelator=[w][P2]\nDestination=[n2]\nSource=[n2]\n" }, 1342 { "Name Recognized", NULL, 1343 "[P1]Data2=[w]\nTransmitCorrelator=[w]\nResponseCorelator=[w]\nDestination=[n2]\nSource=[n2]\n" }, 1344 { "Status Response", NULL, NULL }, 1345 { NULL, NULL, NULL }, /* not used */ 1346 { NULL, NULL, NULL }, /* not used */ 1347 { NULL, NULL, NULL }, /* not used */ 1348 { "Terminate Trace", NULL, NULL }, 1349 { "Data Ack", NULL, 1350 "[P3]TransmitCorrelator=[w][P2]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" }, 1351 { "Data First/Middle", NULL, 1352 "Flags=[{RECEIVE_CONTINUE|NO_ACK||PIGGYBACK_ACK_INCLUDED|}]\nResyncIndicator=[w][P2]\nResponseCorelator=[w]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" }, 1353 { "Data Only/Last", NULL, 1354 "Flags=[{|NO_ACK|PIGGYBACK_ACK_ALLOWED|PIGGYBACK_ACK_INCLUDED|}]\nResyncIndicator=[w][P2]\nResponseCorelator=[w]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" }, 1355 { "Session Confirm", NULL, 1356 "Data1=[B]\nData2=[w]\nTransmitCorrelator=[w]\nResponseCorelator=[w]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" }, 1357 { "Session End", NULL, 1358 "[P1]Data2=[w][P4]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" }, 1359 { "Session Initialize", NULL, 1360 "Data1=[B]\nData2=[w]\nTransmitCorrelator=[w]\nResponseCorelator=[w]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" }, 1361 { "No Receive", NULL, 1362 "Flags=[{|SEND_NO_ACK}]\nDataBytesAccepted=[b][P4]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" }, 1363 { "Receive Outstanding", NULL, 1364 "[P1]DataBytesAccepted=[b][P4]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" }, 1365 { "Receive Continue", NULL, 1366 "[P2]TransmitCorrelator=[w]\n[P2]RemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" }, 1367 { NULL, NULL, NULL }, /* not used */ 1368 { NULL, NULL, NULL }, /* not used */ 1369 { "Session Alive", NULL, NULL } 1370 }; 1371 1372 void 1373 netbeui_print(netdissect_options *ndo, 1374 u_short control, const u_char *data, int length) 1375 { 1376 const u_char *maxbuf = data + length; 1377 int len; 1378 int command; 1379 const u_char *data2; 1380 int is_truncated = 0; 1381 1382 if (maxbuf > ndo->ndo_snapend) 1383 maxbuf = ndo->ndo_snapend; 1384 ND_TCHECK(data[4]); 1385 len = EXTRACT_LE_16BITS(data); 1386 command = data[4]; 1387 data2 = data + len; 1388 if (data2 >= maxbuf) { 1389 data2 = maxbuf; 1390 is_truncated = 1; 1391 } 1392 1393 startbuf = data; 1394 1395 if (ndo->ndo_vflag < 2) { 1396 ND_PRINT((ndo, "NBF Packet: ")); 1397 data = smb_fdata(ndo, data, "[P5]#", maxbuf, 0); 1398 } else { 1399 ND_PRINT((ndo, "\n>>> NBF Packet\nType=0x%X ", control)); 1400 data = smb_fdata(ndo, data, "Length=[d] Signature=[w] Command=[B]\n#", maxbuf, 0); 1401 } 1402 if (data == NULL) 1403 goto out; 1404 1405 if (command > 0x1f || nbf_strings[command].name == NULL) { 1406 if (ndo->ndo_vflag < 2) 1407 data = smb_fdata(ndo, data, "Unknown NBF Command#", data2, 0); 1408 else 1409 data = smb_fdata(ndo, data, "Unknown NBF Command\n", data2, 0); 1410 } else { 1411 if (ndo->ndo_vflag < 2) { 1412 ND_PRINT((ndo, "%s", nbf_strings[command].name)); 1413 if (nbf_strings[command].nonverbose != NULL) 1414 data = smb_fdata(ndo, data, nbf_strings[command].nonverbose, data2, 0); 1415 } else { 1416 ND_PRINT((ndo, "%s:\n", nbf_strings[command].name)); 1417 if (nbf_strings[command].verbose != NULL) 1418 data = smb_fdata(ndo, data, nbf_strings[command].verbose, data2, 0); 1419 else 1420 ND_PRINT((ndo, "\n")); 1421 } 1422 } 1423 1424 if (ndo->ndo_vflag < 2) 1425 return; 1426 1427 if (data == NULL) 1428 goto out; 1429 1430 if (is_truncated) { 1431 /* data2 was past the end of the buffer */ 1432 goto out; 1433 } 1434 1435 /* If this isn't a command that would contain an SMB message, quit. */ 1436 if (command != 0x08 && command != 0x09 && command != 0x15 && 1437 command != 0x16) 1438 goto out; 1439 1440 /* If there isn't enough data for "\377SMB", don't look for it. */ 1441 if (&data2[3] >= maxbuf) 1442 goto out; 1443 1444 if (memcmp(data2, "\377SMB",4) == 0) 1445 print_smb(ndo, data2, maxbuf); 1446 else { 1447 int i; 1448 for (i = 0; i < 128; i++) { 1449 if (&data2[i + 3] >= maxbuf) 1450 break; 1451 if (memcmp(&data2[i], "\377SMB", 4) == 0) { 1452 ND_PRINT((ndo, "found SMB packet at %d\n", i)); 1453 print_smb(ndo, &data2[i], maxbuf); 1454 break; 1455 } 1456 } 1457 } 1458 1459 out: 1460 ND_PRINT((ndo, "\n")); 1461 return; 1462 trunc: 1463 ND_PRINT((ndo, "%s", tstr)); 1464 } 1465 1466 1467 /* 1468 * print IPX-Netbios frames 1469 */ 1470 void 1471 ipx_netbios_print(netdissect_options *ndo, 1472 const u_char *data, u_int length) 1473 { 1474 /* 1475 * this is a hack till I work out how to parse the rest of the 1476 * NetBIOS-over-IPX stuff 1477 */ 1478 int i; 1479 const u_char *maxbuf; 1480 1481 maxbuf = data + length; 1482 /* Don't go past the end of the captured data in the packet. */ 1483 if (maxbuf > ndo->ndo_snapend) 1484 maxbuf = ndo->ndo_snapend; 1485 startbuf = data; 1486 for (i = 0; i < 128; i++) { 1487 if (&data[i + 4] > maxbuf) 1488 break; 1489 if (memcmp(&data[i], "\377SMB", 4) == 0) { 1490 smb_fdata(ndo, data, "\n>>> IPX transport ", &data[i], 0); 1491 print_smb(ndo, &data[i], maxbuf); 1492 ND_PRINT((ndo, "\n")); 1493 break; 1494 } 1495 } 1496 if (i == 128) 1497 smb_fdata(ndo, data, "\n>>> Unknown IPX ", maxbuf, 0); 1498 } 1499