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