source: rtems-libbsd/freebsd/contrib/tcpdump/print-smb.c @ 0b9be9f

5
Last change on this file since 0b9be9f was 4525674, checked in by Sebastian Huber <sebastian.huber@…>, on 11/10/17 at 13:04:48

tcpdump: Fix import/export

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