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