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 #include <config.h> 12 13 #include "netdissect-stdinc.h" 14 15 #include <string.h> 16 17 #include "netdissect.h" 18 #include "extract.h" 19 #include "smb.h" 20 21 22 static int request = 0; 23 static int unicodestr = 0; 24 25 extern const u_char *startbuf; 26 27 const u_char *startbuf = NULL; 28 29 struct smbdescript { 30 const char *req_f1; 31 const char *req_f2; 32 const char *rep_f1; 33 const char *rep_f2; 34 void (*fn)(netdissect_options *, const u_char *, const u_char *, const u_char *, const u_char *); 35 }; 36 37 struct smbdescriptint { 38 const char *req_f1; 39 const char *req_f2; 40 const char *rep_f1; 41 const char *rep_f2; 42 void (*fn)(netdissect_options *, const u_char *, const u_char *, u_int, u_int); 43 }; 44 45 struct smbfns 46 { 47 int id; 48 const char *name; 49 int flags; 50 struct smbdescript descript; 51 }; 52 53 struct smbfnsint 54 { 55 int id; 56 const char *name; 57 int flags; 58 struct smbdescriptint descript; 59 }; 60 61 #define DEFDESCRIPT { NULL, NULL, NULL, NULL, NULL } 62 63 #define FLG_CHAIN (1 << 0) 64 65 static const struct smbfns * 66 smbfind(int id, const struct smbfns *list) 67 { 68 int sindex; 69 70 for (sindex = 0; list[sindex].name; sindex++) 71 if (list[sindex].id == id) 72 return(&list[sindex]); 73 74 return(&list[0]); 75 } 76 77 static const struct smbfnsint * 78 smbfindint(int id, const struct smbfnsint *list) 79 { 80 int sindex; 81 82 for (sindex = 0; list[sindex].name; sindex++) 83 if (list[sindex].id == id) 84 return(&list[sindex]); 85 86 return(&list[0]); 87 } 88 89 static void 90 trans2_findfirst(netdissect_options *ndo, 91 const u_char *param, const u_char *data, u_int pcnt, u_int dcnt) 92 { 93 const char *fmt; 94 95 if (request) 96 fmt = "Attribute=[A]\nSearchCount=[u]\nFlags=[w]\nLevel=[uP4]\nFile=[S]\n"; 97 else 98 fmt = "Handle=[w]\nCount=[u]\nEOS=[w]\nEoffset=[u]\nLastNameOfs=[w]\n"; 99 100 smb_fdata(ndo, param, fmt, param + pcnt, unicodestr); 101 if (dcnt) { 102 ND_PRINT("data:\n"); 103 smb_data_print(ndo, data, dcnt); 104 } 105 } 106 107 static void 108 trans2_qfsinfo(netdissect_options *ndo, 109 const u_char *param, const u_char *data, u_int pcnt, u_int dcnt) 110 { 111 static u_int level = 0; 112 const char *fmt=""; 113 114 if (request) { 115 level = GET_LE_U_2(param); 116 fmt = "InfoLevel=[u]\n"; 117 smb_fdata(ndo, param, fmt, param + pcnt, unicodestr); 118 } else { 119 switch (level) { 120 case 1: 121 fmt = "idFileSystem=[W]\nSectorUnit=[U]\nUnit=[U]\nAvail=[U]\nSectorSize=[u]\n"; 122 break; 123 case 2: 124 fmt = "CreationTime=[T2]VolNameLength=[lb]\nVolumeLabel=[c]\n"; 125 break; 126 case 0x105: 127 fmt = "Capabilities=[W]\nMaxFileLen=[U]\nVolNameLen=[lU]\nVolume=[C]\n"; 128 break; 129 default: 130 fmt = "UnknownLevel\n"; 131 break; 132 } 133 smb_fdata(ndo, data, fmt, data + dcnt, unicodestr); 134 } 135 if (dcnt) { 136 ND_PRINT("data:\n"); 137 smb_data_print(ndo, data, dcnt); 138 } 139 } 140 141 static const struct smbfnsint trans2_fns[] = { 142 { 0, "TRANSACT2_OPEN", 0, 143 { "Flags2=[w]\nMode=[w]\nSearchAttrib=[A]\nAttrib=[A]\nTime=[T2]\nOFun=[w]\nSize=[U]\nRes=([w, w, w, w, w])\nPath=[S]", 144 NULL, 145 "Handle=[u]\nAttrib=[A]\nTime=[T2]\nSize=[U]\nAccess=[w]\nType=[w]\nState=[w]\nAction=[w]\nInode=[W]\nOffErr=[u]\n|EALength=[u]\n", 146 NULL, NULL }}, 147 { 1, "TRANSACT2_FINDFIRST", 0, 148 { NULL, NULL, NULL, NULL, trans2_findfirst }}, 149 { 2, "TRANSACT2_FINDNEXT", 0, DEFDESCRIPT }, 150 { 3, "TRANSACT2_QFSINFO", 0, 151 { NULL, NULL, NULL, NULL, trans2_qfsinfo }}, 152 { 4, "TRANSACT2_SETFSINFO", 0, DEFDESCRIPT }, 153 { 5, "TRANSACT2_QPATHINFO", 0, DEFDESCRIPT }, 154 { 6, "TRANSACT2_SETPATHINFO", 0, DEFDESCRIPT }, 155 { 7, "TRANSACT2_QFILEINFO", 0, DEFDESCRIPT }, 156 { 8, "TRANSACT2_SETFILEINFO", 0, DEFDESCRIPT }, 157 { 9, "TRANSACT2_FSCTL", 0, DEFDESCRIPT }, 158 { 10, "TRANSACT2_IOCTL", 0, DEFDESCRIPT }, 159 { 11, "TRANSACT2_FINDNOTIFYFIRST", 0, DEFDESCRIPT }, 160 { 12, "TRANSACT2_FINDNOTIFYNEXT", 0, DEFDESCRIPT }, 161 { 13, "TRANSACT2_MKDIR", 0, DEFDESCRIPT }, 162 { -1, NULL, 0, DEFDESCRIPT } 163 }; 164 165 166 static void 167 print_trans2(netdissect_options *ndo, 168 const u_char *words, const u_char *dat, const u_char *buf, const u_char *maxbuf) 169 { 170 u_int bcc; 171 static const struct smbfnsint *fn = &trans2_fns[0]; 172 const u_char *data, *param; 173 const u_char *w = words + 1; 174 const char *f1 = NULL, *f2 = NULL; 175 u_int pcnt, dcnt; 176 177 ND_TCHECK_1(words); 178 if (request) { 179 ND_TCHECK_2(w + (14 * 2)); 180 pcnt = GET_LE_U_2(w + 9 * 2); 181 param = buf + GET_LE_U_2(w + 10 * 2); 182 dcnt = GET_LE_U_2(w + 11 * 2); 183 data = buf + GET_LE_U_2(w + 12 * 2); 184 fn = smbfindint(GET_LE_U_2(w + 14 * 2), trans2_fns); 185 } else { 186 if (GET_U_1(words) == 0) { 187 ND_PRINT("%s\n", fn->name); 188 ND_PRINT("Trans2Interim\n"); 189 return; 190 } 191 ND_TCHECK_2(w + (7 * 2)); 192 pcnt = GET_LE_U_2(w + 3 * 2); 193 param = buf + GET_LE_U_2(w + 4 * 2); 194 dcnt = GET_LE_U_2(w + 6 * 2); 195 data = buf + GET_LE_U_2(w + 7 * 2); 196 } 197 198 ND_PRINT("%s param_length=%u data_length=%u\n", fn->name, pcnt, dcnt); 199 200 if (request) { 201 if (GET_U_1(words) == 8) { 202 smb_fdata(ndo, words + 1, 203 "Trans2Secondary\nTotParam=[u]\nTotData=[u]\nParamCnt=[u]\nParamOff=[u]\nParamDisp=[u]\nDataCnt=[u]\nDataOff=[u]\nDataDisp=[u]\nHandle=[u]\n", 204 maxbuf, unicodestr); 205 return; 206 } else { 207 smb_fdata(ndo, words + 1, 208 "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", 209 words + 1 + 14 * 2, unicodestr); 210 } 211 f1 = fn->descript.req_f1; 212 f2 = fn->descript.req_f2; 213 } else { 214 smb_fdata(ndo, words + 1, 215 "TotParam=[u]\nTotData=[u]\nRes1=[w]\nParamCnt=[u]\nParamOff=[u]\nParamDisp[u]\nDataCnt=[u]\nDataOff=[u]\nDataDisp=[u]\nSetupCnt=[b][P1]\n", 216 words + 1 + 10 * 2, unicodestr); 217 f1 = fn->descript.rep_f1; 218 f2 = fn->descript.rep_f2; 219 } 220 221 bcc = GET_LE_U_2(dat); 222 ND_PRINT("smb_bcc=%u\n", bcc); 223 if (fn->descript.fn) 224 (*fn->descript.fn)(ndo, param, data, pcnt, dcnt); 225 else { 226 smb_fdata(ndo, param, f1 ? f1 : "Parameters=\n", param + pcnt, unicodestr); 227 smb_fdata(ndo, data, f2 ? f2 : "Data=\n", data + dcnt, unicodestr); 228 } 229 return; 230 trunc: 231 nd_print_trunc(ndo); 232 } 233 234 static void 235 print_browse(netdissect_options *ndo, 236 const u_char *param, u_int paramlen, const u_char *data, u_int datalen) 237 { 238 const u_char *maxbuf = data + datalen; 239 u_int command; 240 241 command = GET_U_1(data); 242 243 smb_fdata(ndo, param, "BROWSE PACKET\n|Param ", param+paramlen, unicodestr); 244 245 switch (command) { 246 case 0xF: 247 data = smb_fdata(ndo, data, 248 "BROWSE PACKET:\nType=[B] (LocalMasterAnnouncement)\nUpdateCount=[w]\nRes1=[B]\nAnnounceInterval=[u]\nName=[n2]\nMajorVersion=[B]\nMinorVersion=[B]\nServerType=[W]\nElectionVersion=[w]\nBrowserConstant=[w]\n", 249 maxbuf, unicodestr); 250 break; 251 252 case 0x1: 253 data = smb_fdata(ndo, data, 254 "BROWSE PACKET:\nType=[B] (HostAnnouncement)\nUpdateCount=[w]\nRes1=[B]\nAnnounceInterval=[u]\nName=[n2]\nMajorVersion=[B]\nMinorVersion=[B]\nServerType=[W]\nElectionVersion=[w]\nBrowserConstant=[w]\n", 255 maxbuf, unicodestr); 256 break; 257 258 case 0x2: 259 data = smb_fdata(ndo, data, 260 "BROWSE PACKET:\nType=[B] (AnnouncementRequest)\nFlags=[B]\nReplySystemName=[S]\n", 261 maxbuf, unicodestr); 262 break; 263 264 case 0xc: 265 data = smb_fdata(ndo, data, 266 "BROWSE PACKET:\nType=[B] (WorkgroupAnnouncement)\nUpdateCount=[w]\nRes1=[B]\nAnnounceInterval=[u]\nName=[n2]\nMajorVersion=[B]\nMinorVersion=[B]\nServerType=[W]\nCommentPointer=[W]\nServerName=[S]\n", 267 maxbuf, unicodestr); 268 break; 269 270 case 0x8: 271 data = smb_fdata(ndo, data, 272 "BROWSE PACKET:\nType=[B] (ElectionFrame)\nElectionVersion=[B]\nOSSummary=[W]\nUptime=[(W, W)]\nServerName=[S]\n", 273 maxbuf, unicodestr); 274 break; 275 276 case 0xb: 277 data = smb_fdata(ndo, data, 278 "BROWSE PACKET:\nType=[B] (BecomeBackupBrowser)\nName=[S]\n", 279 maxbuf, unicodestr); 280 break; 281 282 case 0x9: 283 data = smb_fdata(ndo, data, 284 "BROWSE PACKET:\nType=[B] (GetBackupList)\nListCount?=[B]\nToken=[W]\n", 285 maxbuf, unicodestr); 286 break; 287 288 case 0xa: 289 data = smb_fdata(ndo, data, 290 "BROWSE PACKET:\nType=[B] (BackupListResponse)\nServerCount?=[B]\nToken=[W]\n*Name=[S]\n", 291 maxbuf, unicodestr); 292 break; 293 294 case 0xd: 295 data = smb_fdata(ndo, data, 296 "BROWSE PACKET:\nType=[B] (MasterAnnouncement)\nMasterName=[S]\n", 297 maxbuf, unicodestr); 298 break; 299 300 case 0xe: 301 data = smb_fdata(ndo, data, 302 "BROWSE PACKET:\nType=[B] (ResetBrowser)\nOptions=[B]\n", maxbuf, unicodestr); 303 break; 304 305 default: 306 data = smb_fdata(ndo, data, "Unknown Browser Frame ", maxbuf, unicodestr); 307 break; 308 } 309 } 310 311 312 static void 313 print_ipc(netdissect_options *ndo, 314 const u_char *param, u_int paramlen, const u_char *data, u_int datalen) 315 { 316 if (paramlen) 317 smb_fdata(ndo, param, "Command=[w]\nStr1=[S]\nStr2=[S]\n", param + paramlen, 318 unicodestr); 319 if (datalen) 320 smb_fdata(ndo, data, "IPC ", data + datalen, unicodestr); 321 } 322 323 324 static void 325 print_trans(netdissect_options *ndo, 326 const u_char *words, const u_char *data1, const u_char *buf, const u_char *maxbuf) 327 { 328 u_int bcc; 329 const char *f1, *f2, *f3, *f4; 330 const u_char *data, *param; 331 const u_char *w = words + 1; 332 u_int datalen, paramlen; 333 334 if (request) { 335 ND_TCHECK_2(w + (12 * 2)); 336 paramlen = GET_LE_U_2(w + 9 * 2); 337 param = buf + GET_LE_U_2(w + 10 * 2); 338 datalen = GET_LE_U_2(w + 11 * 2); 339 data = buf + GET_LE_U_2(w + 12 * 2); 340 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"; 341 f2 = "|Name=[S]\n"; 342 f3 = "|Param "; 343 f4 = "|Data "; 344 } else { 345 ND_TCHECK_2(w + (7 * 2)); 346 paramlen = GET_LE_U_2(w + 3 * 2); 347 param = buf + GET_LE_U_2(w + 4 * 2); 348 datalen = GET_LE_U_2(w + 6 * 2); 349 data = buf + GET_LE_U_2(w + 7 * 2); 350 f1 = "TotParamCnt=[u]\nTotDataCnt=[u]\nRes1=[u]\nParamCnt=[u]\nParamOff=[u]\nRes2=[u]\nDataCnt=[u]\nDataOff=[u]\nRes3=[u]\nLsetup=[u]\n"; 351 f2 = "|Unknown "; 352 f3 = "|Param "; 353 f4 = "|Data "; 354 } 355 356 smb_fdata(ndo, words + 1, f1, 357 ND_MIN(words + 1 + 2 * GET_U_1(words), maxbuf), 358 unicodestr); 359 360 bcc = GET_LE_U_2(data1); 361 ND_PRINT("smb_bcc=%u\n", bcc); 362 if (bcc > 0) { 363 smb_fdata(ndo, data1 + 2, f2, maxbuf - (paramlen + datalen), unicodestr); 364 365 #define MAILSLOT_BROWSE_STR "\\MAILSLOT\\BROWSE" 366 ND_TCHECK_LEN(data1 + 2, strlen(MAILSLOT_BROWSE_STR) + 1); 367 if (strcmp((const char *)(data1 + 2), MAILSLOT_BROWSE_STR) == 0) { 368 print_browse(ndo, param, paramlen, data, datalen); 369 return; 370 } 371 #undef MAILSLOT_BROWSE_STR 372 373 #define PIPE_LANMAN_STR "\\PIPE\\LANMAN" 374 ND_TCHECK_LEN(data1 + 2, strlen(PIPE_LANMAN_STR) + 1); 375 if (strcmp((const char *)(data1 + 2), PIPE_LANMAN_STR) == 0) { 376 print_ipc(ndo, param, paramlen, data, datalen); 377 return; 378 } 379 #undef PIPE_LANMAN_STR 380 381 if (paramlen) 382 smb_fdata(ndo, param, f3, ND_MIN(param + paramlen, maxbuf), unicodestr); 383 if (datalen) 384 smb_fdata(ndo, data, f4, ND_MIN(data + datalen, maxbuf), unicodestr); 385 } 386 return; 387 trunc: 388 nd_print_trunc(ndo); 389 } 390 391 392 static void 393 print_negprot(netdissect_options *ndo, 394 const u_char *words, const u_char *data, const u_char *buf _U_, const u_char *maxbuf) 395 { 396 u_int wct, bcc; 397 const char *f1 = NULL, *f2 = NULL; 398 399 wct = GET_U_1(words); 400 if (request) 401 f2 = "*|Dialect=[Y]\n"; 402 else { 403 if (wct == 1) 404 f1 = "Core Protocol\nDialectIndex=[u]"; 405 else if (wct == 17) 406 f1 = "NT1 Protocol\nDialectIndex=[u]\nSecMode=[B]\nMaxMux=[u]\nNumVcs=[u]\nMaxBuffer=[U]\nRawSize=[U]\nSessionKey=[W]\nCapabilities=[W]\nServerTime=[T3]TimeZone=[u]\nCryptKey="; 407 else if (wct == 13) 408 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="; 409 } 410 411 if (f1) 412 smb_fdata(ndo, words + 1, f1, ND_MIN(words + 1 + wct * 2, maxbuf), 413 unicodestr); 414 else 415 smb_data_print(ndo, words + 1, 416 ND_MIN(wct * 2, ND_BYTES_BETWEEN(words + 1, maxbuf))); 417 418 bcc = GET_LE_U_2(data); 419 ND_PRINT("smb_bcc=%u\n", bcc); 420 if (bcc > 0) { 421 if (f2) 422 smb_fdata(ndo, data + 2, f2, ND_MIN(data + 2 + GET_LE_U_2(data), 423 maxbuf), unicodestr); 424 else 425 smb_data_print(ndo, data + 2, 426 ND_MIN(GET_LE_U_2(data), ND_BYTES_BETWEEN(data + 2, maxbuf))); 427 } 428 } 429 430 static void 431 print_sesssetup(netdissect_options *ndo, 432 const u_char *words, const u_char *data, const u_char *buf _U_, const u_char *maxbuf) 433 { 434 u_int wct, bcc; 435 const char *f1 = NULL, *f2 = NULL; 436 437 wct = GET_U_1(words); 438 if (request) { 439 if (wct == 10) 440 f1 = "Com2=[w]\nOff2=[u]\nBufSize=[u]\nMpxMax=[u]\nVcNum=[u]\nSessionKey=[W]\nPassLen=[u]\nCryptLen=[u]\nCryptOff=[u]\nPass&Name=\n"; 441 else 442 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"; 443 } else { 444 if (wct == 3) { 445 f1 = "Com2=[w]\nOff2=[u]\nAction=[w]\n"; 446 } else if (wct == 13) { 447 f1 = "Com2=[B]\nRes=[B]\nOff2=[u]\nAction=[w]\n"; 448 f2 = "NativeOS=[S]\nNativeLanMan=[S]\nPrimaryDomain=[S]\n"; 449 } 450 } 451 452 if (f1) 453 smb_fdata(ndo, words + 1, f1, ND_MIN(words + 1 + wct * 2, maxbuf), 454 unicodestr); 455 else 456 smb_data_print(ndo, words + 1, 457 ND_MIN(wct * 2, ND_BYTES_BETWEEN(words + 1, maxbuf))); 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(data + 2, maxbuf))); 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(data + 2, maxbuf))); 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, 875 ND_MIN(bcc, ND_BYTES_BETWEEN(data + 2, maxbuf))); 876 } 877 } 878 } 879 880 if ((fn->flags & FLG_CHAIN) == 0) 881 break; 882 if (wct == 0) 883 break; 884 command = GET_U_1(words + 1); 885 if (command == 0xFF) 886 break; 887 newsmboffset = GET_LE_U_2(words + 3); 888 889 fn = smbfind(command, smb_fns); 890 891 ND_PRINT("\nSMB PACKET: %s (%s) (CHAINED)\n", 892 fn->name, request ? "REQUEST" : "REPLY"); 893 if (newsmboffset <= smboffset) { 894 ND_PRINT("Bad andX offset: %u <= %u\n", newsmboffset, smboffset); 895 break; 896 } 897 smboffset = newsmboffset; 898 } 899 } 900 901 902 /* 903 * print a NBT packet received across tcp on port 139 904 */ 905 void 906 nbt_tcp_print(netdissect_options *ndo, 907 const u_char *data, u_int length) 908 { 909 u_int caplen; 910 u_int type; 911 u_int nbt_len; 912 const u_char *maxbuf; 913 914 ndo->ndo_protocol = "nbt_tcp"; 915 if (length < 4) 916 goto trunc; 917 if (ndo->ndo_snapend < data) 918 goto trunc; 919 caplen = ND_BYTES_AVAILABLE_AFTER(data); 920 if (caplen < 4) 921 goto trunc; 922 maxbuf = data + caplen; 923 type = GET_U_1(data); 924 nbt_len = GET_BE_U_2(data + 2); 925 length -= 4; 926 caplen -= 4; 927 928 startbuf = data; 929 930 if (ndo->ndo_vflag < 2) { 931 ND_PRINT(" NBT Session Packet: "); 932 switch (type) { 933 case 0x00: 934 ND_PRINT("Session Message"); 935 break; 936 937 case 0x81: 938 ND_PRINT("Session Request"); 939 break; 940 941 case 0x82: 942 ND_PRINT("Session Granted"); 943 break; 944 945 case 0x83: 946 { 947 u_int ecode; 948 949 if (nbt_len < 4) 950 goto trunc; 951 if (length < 4) 952 goto trunc; 953 if (caplen < 4) 954 goto trunc; 955 ecode = GET_U_1(data + 4); 956 957 ND_PRINT("Session Reject, "); 958 switch (ecode) { 959 case 0x80: 960 ND_PRINT("Not listening on called name"); 961 break; 962 case 0x81: 963 ND_PRINT("Not listening for calling name"); 964 break; 965 case 0x82: 966 ND_PRINT("Called name not present"); 967 break; 968 case 0x83: 969 ND_PRINT("Called name present, but insufficient resources"); 970 break; 971 default: 972 ND_PRINT("Unspecified error 0x%X", ecode); 973 break; 974 } 975 } 976 break; 977 978 case 0x85: 979 ND_PRINT("Session Keepalive"); 980 break; 981 982 default: 983 data = smb_fdata(ndo, data, "Unknown packet type [rB]", maxbuf, 0); 984 break; 985 } 986 } else { 987 ND_PRINT("\n>>> NBT Session Packet\n"); 988 switch (type) { 989 case 0x00: 990 data = smb_fdata(ndo, data, "[P1]NBT Session Message\nFlags=[B]\nLength=[ru]\n", 991 data + 4, 0); 992 if (data == NULL) 993 break; 994 if (nbt_len >= 4 && caplen >= 4 && memcmp(data,"\377SMB",4) == 0) { 995 if (nbt_len > caplen) { 996 if (nbt_len > length) 997 ND_PRINT("WARNING: Packet is continued in later TCP segments\n"); 998 else 999 ND_PRINT("WARNING: Short packet. Try increasing the snap length by %u\n", 1000 nbt_len - caplen); 1001 } 1002 print_smb(ndo, data, maxbuf > data + nbt_len ? data + nbt_len : maxbuf); 1003 } else 1004 ND_PRINT("Session packet:(raw data or continuation?)\n"); 1005 break; 1006 1007 case 0x81: 1008 data = smb_fdata(ndo, data, 1009 "[P1]NBT Session Request\nFlags=[B]\nLength=[ru]\nDestination=[n1]\nSource=[n1]\n", 1010 maxbuf, 0); 1011 break; 1012 1013 case 0x82: 1014 data = smb_fdata(ndo, data, "[P1]NBT Session Granted\nFlags=[B]\nLength=[ru]\n", maxbuf, 0); 1015 break; 1016 1017 case 0x83: 1018 { 1019 const u_char *origdata; 1020 u_int ecode; 1021 1022 origdata = data; 1023 data = smb_fdata(ndo, data, "[P1]NBT SessionReject\nFlags=[B]\nLength=[ru]\nReason=[B]\n", 1024 maxbuf, 0); 1025 if (data == NULL) 1026 break; 1027 if (nbt_len >= 1 && caplen >= 1) { 1028 ecode = GET_U_1(origdata + 4); 1029 switch (ecode) { 1030 case 0x80: 1031 ND_PRINT("Not listening on called name\n"); 1032 break; 1033 case 0x81: 1034 ND_PRINT("Not listening for calling name\n"); 1035 break; 1036 case 0x82: 1037 ND_PRINT("Called name not present\n"); 1038 break; 1039 case 0x83: 1040 ND_PRINT("Called name present, but insufficient resources\n"); 1041 break; 1042 default: 1043 ND_PRINT("Unspecified error 0x%X\n", ecode); 1044 break; 1045 } 1046 } 1047 } 1048 break; 1049 1050 case 0x85: 1051 data = smb_fdata(ndo, data, "[P1]NBT Session Keepalive\nFlags=[B]\nLength=[ru]\n", maxbuf, 0); 1052 break; 1053 1054 default: 1055 data = smb_fdata(ndo, data, "NBT - Unknown packet type\nType=[B]\n", maxbuf, 0); 1056 break; 1057 } 1058 } 1059 return; 1060 trunc: 1061 nd_print_trunc(ndo); 1062 } 1063 1064 static const struct tok opcode_str[] = { 1065 { 0, "QUERY" }, 1066 { 5, "REGISTRATION" }, 1067 { 6, "RELEASE" }, 1068 { 7, "WACK" }, 1069 { 8, "REFRESH(8)" }, 1070 { 9, "REFRESH" }, 1071 { 15, "MULTIHOMED REGISTRATION" }, 1072 { 0, NULL } 1073 }; 1074 1075 /* 1076 * print a NBT packet received across udp on port 137 1077 */ 1078 void 1079 nbt_udp137_print(netdissect_options *ndo, 1080 const u_char *data, u_int length) 1081 { 1082 const u_char *maxbuf = data + length; 1083 u_int name_trn_id, response, opcode, nm_flags, rcode; 1084 u_int qdcount, ancount, nscount, arcount; 1085 const u_char *p; 1086 u_int total, i; 1087 1088 ndo->ndo_protocol = "nbt_udp137"; 1089 name_trn_id = GET_BE_U_2(data); 1090 response = (GET_U_1(data + 2) >> 7); 1091 opcode = (GET_U_1(data + 2) >> 3) & 0xF; 1092 nm_flags = ((GET_U_1(data + 2) & 0x7) << 4) + (GET_U_1(data + 3) >> 4); 1093 rcode = GET_U_1(data + 3) & 0xF; 1094 qdcount = GET_BE_U_2(data + 4); 1095 ancount = GET_BE_U_2(data + 6); 1096 nscount = GET_BE_U_2(data + 8); 1097 arcount = GET_BE_U_2(data + 10); 1098 startbuf = data; 1099 1100 if (maxbuf <= data) 1101 return; 1102 1103 if (ndo->ndo_vflag > 1) 1104 ND_PRINT("\n>>> "); 1105 1106 ND_PRINT("NBT UDP PACKET(137): %s", tok2str(opcode_str, "OPUNKNOWN", opcode)); 1107 if (response) { 1108 ND_PRINT("; %s", rcode ? "NEGATIVE" : "POSITIVE"); 1109 } 1110 ND_PRINT("; %s; %s", response ? "RESPONSE" : "REQUEST", 1111 (nm_flags & 1) ? "BROADCAST" : "UNICAST"); 1112 1113 if (ndo->ndo_vflag < 2) 1114 return; 1115 1116 ND_PRINT("\nTrnID=0x%X\nOpCode=%u\nNmFlags=0x%X\nRcode=%u\nQueryCount=%u\nAnswerCount=%u\nAuthorityCount=%u\nAddressRecCount=%u\n", 1117 name_trn_id, opcode, nm_flags, rcode, qdcount, ancount, nscount, 1118 arcount); 1119 1120 p = data + 12; 1121 1122 total = ancount + nscount + arcount; 1123 1124 if (qdcount > 100 || total > 100) { 1125 ND_PRINT("Corrupt packet??\n"); 1126 return; 1127 } 1128 1129 if (qdcount) { 1130 ND_PRINT("QuestionRecords:\n"); 1131 for (i = 0; i < qdcount; i++) { 1132 p = smb_fdata(ndo, p, 1133 "|Name=[n1]\nQuestionType=[rw]\nQuestionClass=[rw]\n#", 1134 maxbuf, 0); 1135 if (p == NULL) 1136 goto out; 1137 } 1138 } 1139 1140 if (total) { 1141 ND_PRINT("\nResourceRecords:\n"); 1142 for (i = 0; i < total; i++) { 1143 u_int rdlen; 1144 u_int restype; 1145 1146 p = smb_fdata(ndo, p, "Name=[n1]\n#", maxbuf, 0); 1147 if (p == NULL) 1148 goto out; 1149 restype = GET_BE_U_2(p); 1150 p = smb_fdata(ndo, p, "ResType=[rw]\nResClass=[rw]\nTTL=[rU]\n", p + 8, 0); 1151 if (p == NULL) 1152 goto out; 1153 rdlen = GET_BE_U_2(p); 1154 ND_PRINT("ResourceLength=%u\nResourceData=\n", rdlen); 1155 p += 2; 1156 if (rdlen == 6) { 1157 p = smb_fdata(ndo, p, "AddrType=[rw]\nAddress=[b.b.b.b]\n", p + rdlen, 0); 1158 if (p == NULL) 1159 goto out; 1160 } else { 1161 if (restype == 0x21) { 1162 u_int numnames; 1163 1164 numnames = GET_U_1(p); 1165 p = smb_fdata(ndo, p, "NumNames=[B]\n", p + 1, 0); 1166 if (p == NULL) 1167 goto out; 1168 while (numnames) { 1169 p = smb_fdata(ndo, p, "Name=[n2]\t#", maxbuf, 0); 1170 if (p == NULL) 1171 goto out; 1172 ND_TCHECK_1(p); 1173 if (p >= maxbuf) 1174 goto out; 1175 if (GET_U_1(p) & 0x80) 1176 ND_PRINT("<GROUP> "); 1177 switch (GET_U_1(p) & 0x60) { 1178 case 0x00: ND_PRINT("B "); break; 1179 case 0x20: ND_PRINT("P "); break; 1180 case 0x40: ND_PRINT("M "); break; 1181 case 0x60: ND_PRINT("_ "); break; 1182 } 1183 if (GET_U_1(p) & 0x10) 1184 ND_PRINT("<DEREGISTERING> "); 1185 if (GET_U_1(p) & 0x08) 1186 ND_PRINT("<CONFLICT> "); 1187 if (GET_U_1(p) & 0x04) 1188 ND_PRINT("<ACTIVE> "); 1189 if (GET_U_1(p) & 0x02) 1190 ND_PRINT("<PERMANENT> "); 1191 ND_PRINT("\n"); 1192 p += 2; 1193 numnames--; 1194 } 1195 } else { 1196 if (p >= maxbuf) 1197 goto out; 1198 smb_data_print(ndo, p, 1199 ND_MIN(rdlen, length - ND_BYTES_BETWEEN(data, p))); 1200 p += rdlen; 1201 } 1202 } 1203 } 1204 } 1205 1206 if (p < maxbuf) 1207 smb_fdata(ndo, p, "AdditionalData:\n", maxbuf, 0); 1208 1209 out: 1210 return; 1211 trunc: 1212 nd_print_trunc(ndo); 1213 } 1214 1215 /* 1216 * Print an SMB-over-TCP packet received across tcp on port 445 1217 */ 1218 void 1219 smb_tcp_print(netdissect_options *ndo, 1220 const u_char * data, u_int length) 1221 { 1222 u_int caplen; 1223 u_int smb_len; 1224 const u_char *maxbuf; 1225 1226 ndo->ndo_protocol = "smb_tcp"; 1227 if (length < 4) 1228 goto trunc; 1229 if (ndo->ndo_snapend < data) 1230 goto trunc; 1231 caplen = ND_BYTES_AVAILABLE_AFTER(data); 1232 if (caplen < 4) 1233 goto trunc; 1234 maxbuf = data + caplen; 1235 smb_len = GET_BE_U_3(data + 1); 1236 length -= 4; 1237 caplen -= 4; 1238 1239 startbuf = data; 1240 data += 4; 1241 1242 if (smb_len >= 4 && caplen >= 4 && memcmp(data,"\377SMB",4) == 0) { 1243 if (smb_len > caplen) { 1244 if (smb_len > length) 1245 ND_PRINT(" WARNING: Packet is continued in later TCP segments\n"); 1246 else 1247 ND_PRINT(" WARNING: Short packet. Try increasing the snap length by %u\n", 1248 smb_len - caplen); 1249 } else 1250 ND_PRINT(" "); 1251 print_smb(ndo, data, maxbuf > data + smb_len ? data + smb_len : maxbuf); 1252 } else 1253 ND_PRINT(" SMB-over-TCP packet:(raw data or continuation?)\n"); 1254 return; 1255 trunc: 1256 nd_print_trunc(ndo); 1257 } 1258 1259 /* 1260 * print a NBT packet received across udp on port 138 1261 */ 1262 void 1263 nbt_udp138_print(netdissect_options *ndo, 1264 const u_char *data, u_int length) 1265 { 1266 const u_char *maxbuf = data + length; 1267 1268 ndo->ndo_protocol = "nbt_udp138"; 1269 if (maxbuf > ndo->ndo_snapend) 1270 maxbuf = ndo->ndo_snapend; 1271 if (maxbuf <= data) 1272 return; 1273 startbuf = data; 1274 1275 if (ndo->ndo_vflag < 2) { 1276 ND_PRINT("NBT UDP PACKET(138)"); 1277 return; 1278 } 1279 1280 data = smb_fdata(ndo, data, 1281 "\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#", 1282 maxbuf, 0); 1283 1284 if (data != NULL) { 1285 /* If there isn't enough data for "\377SMB", don't check for it. */ 1286 if ((data + 3) >= maxbuf) 1287 goto out; 1288 1289 if (memcmp(data, "\377SMB",4) == 0) 1290 print_smb(ndo, data, maxbuf); 1291 } 1292 out: 1293 return; 1294 } 1295 1296 1297 /* 1298 print netbeui frames 1299 */ 1300 static struct nbf_strings { 1301 const char *name; 1302 const char *nonverbose; 1303 const char *verbose; 1304 } nbf_strings[0x20] = { 1305 { "Add Group Name Query", ", [P23]Name to add=[n2]#", 1306 "[P5]ResponseCorrelator=[w]\n[P16]Name to add=[n2]\n" }, 1307 { "Add Name Query", ", [P23]Name to add=[n2]#", 1308 "[P5]ResponseCorrelator=[w]\n[P16]Name to add=[n2]\n" }, 1309 { "Name In Conflict", NULL, NULL }, 1310 { "Status Query", NULL, NULL }, 1311 { NULL, NULL, NULL }, /* not used */ 1312 { NULL, NULL, NULL }, /* not used */ 1313 { NULL, NULL, NULL }, /* not used */ 1314 { "Terminate Trace", NULL, NULL }, 1315 { "Datagram", NULL, 1316 "[P7]Destination=[n2]\nSource=[n2]\n" }, 1317 { "Broadcast Datagram", NULL, 1318 "[P7]Destination=[n2]\nSource=[n2]\n" }, 1319 { "Name Query", ", [P7]Name=[n2]#", 1320 "[P1]SessionNumber=[B]\nNameType=[B][P2]\nResponseCorrelator=[w]\nName=[n2]\nName of sender=[n2]\n" }, 1321 { NULL, NULL, NULL }, /* not used */ 1322 { NULL, NULL, NULL }, /* not used */ 1323 { "Add Name Response", ", [P1]GroupName=[w] [P4]Destination=[n2] Source=[n2]#", 1324 "AddNameInProcess=[B]\nGroupName=[w]\nTransmitCorrelator=[w][P2]\nDestination=[n2]\nSource=[n2]\n" }, 1325 { "Name Recognized", NULL, 1326 "[P1]Data2=[w]\nTransmitCorrelator=[w]\nResponseCorelator=[w]\nDestination=[n2]\nSource=[n2]\n" }, 1327 { "Status Response", 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 { "Data Ack", NULL, 1333 "[P3]TransmitCorrelator=[w][P2]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" }, 1334 { "Data First/Middle", NULL, 1335 "Flags=[{RECEIVE_CONTINUE|NO_ACK||PIGGYBACK_ACK_INCLUDED|}]\nResyncIndicator=[w][P2]\nResponseCorelator=[w]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" }, 1336 { "Data Only/Last", NULL, 1337 "Flags=[{|NO_ACK|PIGGYBACK_ACK_ALLOWED|PIGGYBACK_ACK_INCLUDED|}]\nResyncIndicator=[w][P2]\nResponseCorelator=[w]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" }, 1338 { "Session Confirm", NULL, 1339 "Data1=[B]\nData2=[w]\nTransmitCorrelator=[w]\nResponseCorelator=[w]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" }, 1340 { "Session End", NULL, 1341 "[P1]Data2=[w][P4]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" }, 1342 { "Session Initialize", NULL, 1343 "Data1=[B]\nData2=[w]\nTransmitCorrelator=[w]\nResponseCorelator=[w]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" }, 1344 { "No Receive", NULL, 1345 "Flags=[{|SEND_NO_ACK}]\nDataBytesAccepted=[b][P4]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" }, 1346 { "Receive Outstanding", NULL, 1347 "[P1]DataBytesAccepted=[b][P4]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" }, 1348 { "Receive Continue", NULL, 1349 "[P2]TransmitCorrelator=[w]\n[P2]RemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" }, 1350 { NULL, NULL, NULL }, /* not used */ 1351 { NULL, NULL, NULL }, /* not used */ 1352 { "Session Alive", NULL, NULL } 1353 }; 1354 1355 void 1356 netbeui_print(netdissect_options *ndo, 1357 u_short control, const u_char *data, u_int length) 1358 { 1359 const u_char *maxbuf = data + length; 1360 u_int len; 1361 u_int command; 1362 const u_char *data2; 1363 int is_truncated = 0; 1364 1365 ndo->ndo_protocol = "netbeui"; 1366 if (maxbuf > ndo->ndo_snapend) 1367 maxbuf = ndo->ndo_snapend; 1368 len = GET_LE_U_2(data); 1369 command = GET_U_1(data + 4); 1370 data2 = data + len; 1371 if (data2 >= maxbuf) { 1372 data2 = maxbuf; 1373 is_truncated = 1; 1374 } 1375 1376 startbuf = data; 1377 1378 if (ndo->ndo_vflag < 2) { 1379 ND_PRINT("NBF Packet: "); 1380 data = smb_fdata(ndo, data, "[P5]#", maxbuf, 0); 1381 } else { 1382 ND_PRINT("\n>>> NBF Packet\nType=0x%X ", control); 1383 data = smb_fdata(ndo, data, "Length=[u] Signature=[w] Command=[B]\n#", maxbuf, 0); 1384 } 1385 if (data == NULL) 1386 goto out; 1387 1388 if (command > 0x1f || nbf_strings[command].name == NULL) { 1389 if (ndo->ndo_vflag < 2) 1390 data = smb_fdata(ndo, data, "Unknown NBF Command#", data2, 0); 1391 else 1392 data = smb_fdata(ndo, data, "Unknown NBF Command\n", data2, 0); 1393 } else { 1394 if (ndo->ndo_vflag < 2) { 1395 ND_PRINT("%s", nbf_strings[command].name); 1396 if (nbf_strings[command].nonverbose != NULL) 1397 data = smb_fdata(ndo, data, nbf_strings[command].nonverbose, data2, 0); 1398 } else { 1399 ND_PRINT("%s:\n", nbf_strings[command].name); 1400 if (nbf_strings[command].verbose != NULL) 1401 data = smb_fdata(ndo, data, nbf_strings[command].verbose, data2, 0); 1402 else 1403 ND_PRINT("\n"); 1404 } 1405 } 1406 1407 if (ndo->ndo_vflag < 2) 1408 return; 1409 1410 if (data == NULL) 1411 goto out; 1412 1413 if (is_truncated) { 1414 /* data2 was past the end of the buffer */ 1415 goto out; 1416 } 1417 1418 /* If this isn't a command that would contain an SMB message, quit. */ 1419 if (command != 0x08 && command != 0x09 && command != 0x15 && 1420 command != 0x16) 1421 goto out; 1422 1423 /* If there isn't enough data for "\377SMB", don't look for it. */ 1424 if ((data2 + 3) >= maxbuf) 1425 goto out; 1426 1427 if (memcmp(data2, "\377SMB",4) == 0) 1428 print_smb(ndo, data2, maxbuf); 1429 else { 1430 u_int i; 1431 for (i = 0; i < 128; i++) { 1432 if ((data2 + i + 3) >= maxbuf) 1433 break; 1434 if (memcmp(data2 + i, "\377SMB", 4) == 0) { 1435 ND_PRINT("found SMB packet at %u\n", i); 1436 print_smb(ndo, data2 + i, maxbuf); 1437 break; 1438 } 1439 } 1440 } 1441 1442 out: 1443 return; 1444 } 1445 1446 1447 /* 1448 * print IPX-Netbios frames 1449 */ 1450 void 1451 ipx_netbios_print(netdissect_options *ndo, 1452 const u_char *data, u_int length) 1453 { 1454 /* 1455 * this is a hack till I work out how to parse the rest of the 1456 * NetBIOS-over-IPX stuff 1457 */ 1458 u_int i; 1459 const u_char *maxbuf; 1460 1461 ndo->ndo_protocol = "ipx_netbios"; 1462 maxbuf = data + length; 1463 /* Don't go past the end of the captured data in the packet. */ 1464 if (maxbuf > ndo->ndo_snapend) 1465 maxbuf = ndo->ndo_snapend; 1466 startbuf = data; 1467 for (i = 0; i < 128; i++) { 1468 if ((data + i + 4) > maxbuf) 1469 break; 1470 if (memcmp(data + i, "\377SMB", 4) == 0) { 1471 smb_fdata(ndo, data, "\n>>> IPX transport ", data + i, 0); 1472 print_smb(ndo, data + i, maxbuf); 1473 break; 1474 } 1475 } 1476 if (i == 128) 1477 smb_fdata(ndo, data, "\n>>> Unknown IPX ", maxbuf, 0); 1478 } 1479