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