198524Sfenner/*
298524Sfenner * Copyright (C) Andrew Tridgell 1995-1999
398524Sfenner *
498524Sfenner * This software may be distributed either under the terms of the
598524Sfenner * BSD-style license that accompanies tcpdump or the GNU GPL version 2
698524Sfenner * or later
798524Sfenner */
856893Sfenner
956893Sfenner#ifdef HAVE_CONFIG_H
1056893Sfenner#include "config.h"
1156893Sfenner#endif
1256893Sfenner
1356893Sfenner#ifndef lint
14127668Sbmsstatic const char rcsid[] _U_ =
15214478Srpaulo     "@(#) $Header: /tcpdump/master/tcpdump/print-smb.c,v 1.47 2007-12-09 00:30:47 guy Exp $";
1656893Sfenner#endif
1756893Sfenner
18127668Sbms#include <tcpdump-stdinc.h>
19127668Sbms
2056893Sfenner#include <stdio.h>
2156893Sfenner#include <string.h>
2256893Sfenner
2356893Sfenner#include "interface.h"
2498524Sfenner#include "extract.h"
2556893Sfenner#include "smb.h"
2656893Sfenner
2798524Sfennerstatic int request = 0;
28146773Ssamstatic int unicodestr = 0;
2956893Sfenner
3098524Sfennerconst u_char *startbuf = NULL;
3156893Sfenner
3298524Sfennerstruct smbdescript {
3398524Sfenner    const char *req_f1;
3498524Sfenner    const char *req_f2;
3598524Sfenner    const char *rep_f1;
3698524Sfenner    const char *rep_f2;
3798524Sfenner    void (*fn)(const u_char *, const u_char *, const u_char *, const u_char *);
3856893Sfenner};
3956893Sfenner
4098524Sfennerstruct smbdescriptint {
4198524Sfenner    const char *req_f1;
4298524Sfenner    const char *req_f2;
4398524Sfenner    const char *rep_f1;
4498524Sfenner    const char *rep_f2;
4598524Sfenner    void (*fn)(const u_char *, const u_char *, int, int);
4698524Sfenner};
4798524Sfenner
4856893Sfennerstruct smbfns
4956893Sfenner{
5098524Sfenner    int id;
5198524Sfenner    const char *name;
5298524Sfenner    int flags;
5398524Sfenner    struct smbdescript descript;
5456893Sfenner};
5556893Sfenner
5698524Sfennerstruct smbfnsint
5798524Sfenner{
5898524Sfenner    int id;
5998524Sfenner    const char *name;
6098524Sfenner    int flags;
6198524Sfenner    struct smbdescriptint descript;
6298524Sfenner};
6356893Sfenner
6498524Sfenner#define DEFDESCRIPT	{ NULL, NULL, NULL, NULL, NULL }
6556893Sfenner
6698524Sfenner#define FLG_CHAIN	(1 << 0)
6798524Sfenner
6898524Sfennerstatic struct smbfns *
6998524Sfennersmbfind(int id, struct smbfns *list)
7056893Sfenner{
7198524Sfenner    int sindex;
7256893Sfenner
7398524Sfenner    for (sindex = 0; list[sindex].name; sindex++)
7498524Sfenner	if (list[sindex].id == id)
7598524Sfenner	    return(&list[sindex]);
7656893Sfenner
7798524Sfenner    return(&list[0]);
7856893Sfenner}
7956893Sfenner
8098524Sfennerstatic struct smbfnsint *
8198524Sfennersmbfindint(int id, struct smbfnsint *list)
8256893Sfenner{
8398524Sfenner    int sindex;
8456893Sfenner
8598524Sfenner    for (sindex = 0; list[sindex].name; sindex++)
8698524Sfenner	if (list[sindex].id == id)
8798524Sfenner	    return(&list[sindex]);
8856893Sfenner
8998524Sfenner    return(&list[0]);
9056893Sfenner}
9156893Sfenner
9298524Sfennerstatic void
9398524Sfennertrans2_findfirst(const u_char *param, const u_char *data, int pcnt, int dcnt)
9456893Sfenner{
9598524Sfenner    const char *fmt;
9656893Sfenner
9798524Sfenner    if (request)
98146773Ssam	fmt = "Attribute=[A]\nSearchCount=[d]\nFlags=[w]\nLevel=[dP4]\nFile=[S]\n";
9998524Sfenner    else
10098524Sfenner	fmt = "Handle=[w]\nCount=[d]\nEOS=[w]\nEoffset=[d]\nLastNameOfs=[w]\n";
10198524Sfenner
102146773Ssam    smb_fdata(param, fmt, param + pcnt, unicodestr);
10398524Sfenner    if (dcnt) {
10498524Sfenner	printf("data:\n");
10598524Sfenner	print_data(data, dcnt);
10656893Sfenner    }
10756893Sfenner}
10856893Sfenner
10998524Sfennerstatic void
11098524Sfennertrans2_qfsinfo(const u_char *param, const u_char *data, int pcnt, int dcnt)
11198524Sfenner{
11298524Sfenner    static int level = 0;
11398524Sfenner    const char *fmt="";
11456893Sfenner
11598524Sfenner    if (request) {
11698524Sfenner	TCHECK2(*param, 2);
11798524Sfenner	level = EXTRACT_LE_16BITS(param);
11898524Sfenner	fmt = "InfoLevel=[d]\n";
119146773Ssam	smb_fdata(param, fmt, param + pcnt, unicodestr);
12098524Sfenner    } else {
12198524Sfenner	switch (level) {
12298524Sfenner	case 1:
12398524Sfenner	    fmt = "idFileSystem=[W]\nSectorUnit=[D]\nUnit=[D]\nAvail=[D]\nSectorSize=[d]\n";
12498524Sfenner	    break;
12598524Sfenner	case 2:
126146773Ssam	    fmt = "CreationTime=[T2]VolNameLength=[lb]\nVolumeLabel=[c]\n";
12798524Sfenner	    break;
12898524Sfenner	case 0x105:
129146773Ssam	    fmt = "Capabilities=[W]\nMaxFileLen=[D]\nVolNameLen=[lD]\nVolume=[C]\n";
13098524Sfenner	    break;
13198524Sfenner	default:
13298524Sfenner	    fmt = "UnknownLevel\n";
13398524Sfenner	    break;
13498524Sfenner	}
135146773Ssam	smb_fdata(data, fmt, data + dcnt, unicodestr);
13698524Sfenner    }
13798524Sfenner    if (dcnt) {
13898524Sfenner	printf("data:\n");
13998524Sfenner	print_data(data, dcnt);
14098524Sfenner    }
14198524Sfenner    return;
14298524Sfennertrunc:
14398524Sfenner    printf("[|SMB]");
14498524Sfenner    return;
14598524Sfenner}
14656893Sfenner
14798524Sfennerstruct smbfnsint trans2_fns[] = {
14898524Sfenner    { 0, "TRANSACT2_OPEN", 0,
14998524Sfenner	{ "Flags2=[w]\nMode=[w]\nSearchAttrib=[A]\nAttrib=[A]\nTime=[T2]\nOFun=[w]\nSize=[D]\nRes=([w, w, w, w, w])\nPath=[S]",
15098524Sfenner	  NULL,
15198524Sfenner	  "Handle=[d]\nAttrib=[A]\nTime=[T2]\nSize=[D]\nAccess=[w]\nType=[w]\nState=[w]\nAction=[w]\nInode=[W]\nOffErr=[d]\n|EALength=[d]\n",
15298524Sfenner	  NULL, NULL }},
15398524Sfenner    { 1, "TRANSACT2_FINDFIRST", 0,
15498524Sfenner	{ NULL, NULL, NULL, NULL, trans2_findfirst }},
15598524Sfenner    { 2, "TRANSACT2_FINDNEXT", 0, DEFDESCRIPT },
15698524Sfenner    { 3, "TRANSACT2_QFSINFO", 0,
15798524Sfenner	{ NULL, NULL, NULL, NULL, trans2_qfsinfo }},
15898524Sfenner    { 4, "TRANSACT2_SETFSINFO", 0, DEFDESCRIPT },
15998524Sfenner    { 5, "TRANSACT2_QPATHINFO", 0, DEFDESCRIPT },
16098524Sfenner    { 6, "TRANSACT2_SETPATHINFO", 0, DEFDESCRIPT },
16198524Sfenner    { 7, "TRANSACT2_QFILEINFO", 0, DEFDESCRIPT },
16298524Sfenner    { 8, "TRANSACT2_SETFILEINFO", 0, DEFDESCRIPT },
16398524Sfenner    { 9, "TRANSACT2_FSCTL", 0, DEFDESCRIPT },
16498524Sfenner    { 10, "TRANSACT2_IOCTL", 0, DEFDESCRIPT },
16598524Sfenner    { 11, "TRANSACT2_FINDNOTIFYFIRST", 0, DEFDESCRIPT },
16698524Sfenner    { 12, "TRANSACT2_FINDNOTIFYNEXT", 0, DEFDESCRIPT },
16798524Sfenner    { 13, "TRANSACT2_MKDIR", 0, DEFDESCRIPT },
16898524Sfenner    { -1, NULL, 0, DEFDESCRIPT }
16998524Sfenner};
17056893Sfenner
17156893Sfenner
17298524Sfennerstatic void
173146773Ssamprint_trans2(const u_char *words, const u_char *dat, const u_char *buf, const u_char *maxbuf)
17456893Sfenner{
175146773Ssam    u_int bcc;
17698524Sfenner    static struct smbfnsint *fn = &trans2_fns[0];
17798524Sfenner    const u_char *data, *param;
17898524Sfenner    const u_char *w = words + 1;
179111726Sfenner    const char *f1 = NULL, *f2 = NULL;
18098524Sfenner    int pcnt, dcnt;
18156893Sfenner
18298524Sfenner    TCHECK(words[0]);
18398524Sfenner    if (request) {
18498524Sfenner	TCHECK2(w[14 * 2], 2);
18598524Sfenner	pcnt = EXTRACT_LE_16BITS(w + 9 * 2);
18698524Sfenner	param = buf + EXTRACT_LE_16BITS(w + 10 * 2);
18798524Sfenner	dcnt = EXTRACT_LE_16BITS(w + 11 * 2);
18898524Sfenner	data = buf + EXTRACT_LE_16BITS(w + 12 * 2);
18998524Sfenner	fn = smbfindint(EXTRACT_LE_16BITS(w + 14 * 2), trans2_fns);
19098524Sfenner    } else {
19198524Sfenner	if (words[0] == 0) {
19298524Sfenner	    printf("%s\n", fn->name);
19398524Sfenner	    printf("Trans2Interim\n");
19498524Sfenner	    return;
19598524Sfenner	}
19698524Sfenner	TCHECK2(w[7 * 2], 2);
19798524Sfenner	pcnt = EXTRACT_LE_16BITS(w + 3 * 2);
19898524Sfenner	param = buf + EXTRACT_LE_16BITS(w + 4 * 2);
19998524Sfenner	dcnt = EXTRACT_LE_16BITS(w + 6 * 2);
20098524Sfenner	data = buf + EXTRACT_LE_16BITS(w + 7 * 2);
20198524Sfenner    }
20256893Sfenner
20398524Sfenner    printf("%s param_length=%d data_length=%d\n", fn->name, pcnt, dcnt);
20456893Sfenner
20598524Sfenner    if (request) {
20698524Sfenner	if (words[0] == 8) {
20798524Sfenner	    smb_fdata(words + 1,
20898524Sfenner		"Trans2Secondary\nTotParam=[d]\nTotData=[d]\nParamCnt=[d]\nParamOff=[d]\nParamDisp=[d]\nDataCnt=[d]\nDataOff=[d]\nDataDisp=[d]\nHandle=[d]\n",
209146773Ssam		maxbuf, unicodestr);
21098524Sfenner	    return;
21198524Sfenner	} else {
21298524Sfenner	    smb_fdata(words + 1,
213146773Ssam		"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",
214146773Ssam		words + 1 + 14 * 2, unicodestr);
21598524Sfenner	}
21698524Sfenner	f1 = fn->descript.req_f1;
21798524Sfenner	f2 = fn->descript.req_f2;
21856893Sfenner    } else {
21998524Sfenner	smb_fdata(words + 1,
220146773Ssam	    "TotParam=[d]\nTotData=[d]\nRes1=[w]\nParamCnt=[d]\nParamOff=[d]\nParamDisp[d]\nDataCnt=[d]\nDataOff=[d]\nDataDisp=[d]\nSetupCnt=[b][P1]\n",
221146773Ssam	    words + 1 + 10 * 2, unicodestr);
22298524Sfenner	f1 = fn->descript.rep_f1;
22398524Sfenner	f2 = fn->descript.rep_f2;
22456893Sfenner    }
22598524Sfenner
226146773Ssam    TCHECK2(*dat, 2);
227146773Ssam    bcc = EXTRACT_LE_16BITS(dat);
228146773Ssam    printf("smb_bcc=%u\n", bcc);
22998524Sfenner    if (fn->descript.fn)
23098524Sfenner	(*fn->descript.fn)(param, data, pcnt, dcnt);
23198524Sfenner    else {
232146773Ssam	smb_fdata(param, f1 ? f1 : "Parameters=\n", param + pcnt, unicodestr);
233146773Ssam	smb_fdata(data, f2 ? f2 : "Data=\n", data + dcnt, unicodestr);
23456893Sfenner    }
23598524Sfenner    return;
23698524Sfennertrunc:
23798524Sfenner    printf("[|SMB]");
23898524Sfenner    return;
23956893Sfenner}
24056893Sfenner
24156893Sfenner
24298524Sfennerstatic void
24398524Sfennerprint_browse(const u_char *param, int paramlen, const u_char *data, int datalen)
24456893Sfenner{
24598524Sfenner    const u_char *maxbuf = data + datalen;
24698524Sfenner    int command;
24756893Sfenner
24898524Sfenner    TCHECK(data[0]);
24998524Sfenner    command = data[0];
25056893Sfenner
251146773Ssam    smb_fdata(param, "BROWSE PACKET\n|Param ", param+paramlen, unicodestr);
25256893Sfenner
25398524Sfenner    switch (command) {
25498524Sfenner    case 0xF:
25598524Sfenner	data = smb_fdata(data,
25698524Sfenner	    "BROWSE PACKET:\nType=[B] (LocalMasterAnnouncement)\nUpdateCount=[w]\nRes1=[B]\nAnnounceInterval=[d]\nName=[n2]\nMajorVersion=[B]\nMinorVersion=[B]\nServerType=[W]\nElectionVersion=[w]\nBrowserConstant=[w]\n",
257146773Ssam	    maxbuf, unicodestr);
25898524Sfenner	break;
25998524Sfenner
26098524Sfenner    case 0x1:
26198524Sfenner	data = smb_fdata(data,
26298524Sfenner	    "BROWSE PACKET:\nType=[B] (HostAnnouncement)\nUpdateCount=[w]\nRes1=[B]\nAnnounceInterval=[d]\nName=[n2]\nMajorVersion=[B]\nMinorVersion=[B]\nServerType=[W]\nElectionVersion=[w]\nBrowserConstant=[w]\n",
263146773Ssam	    maxbuf, unicodestr);
26498524Sfenner	break;
26598524Sfenner
26698524Sfenner    case 0x2:
26798524Sfenner	data = smb_fdata(data,
26898524Sfenner	    "BROWSE PACKET:\nType=[B] (AnnouncementRequest)\nFlags=[B]\nReplySystemName=[S]\n",
269146773Ssam	    maxbuf, unicodestr);
27098524Sfenner	break;
27198524Sfenner
27298524Sfenner    case 0xc:
27398524Sfenner	data = smb_fdata(data,
27498524Sfenner	    "BROWSE PACKET:\nType=[B] (WorkgroupAnnouncement)\nUpdateCount=[w]\nRes1=[B]\nAnnounceInterval=[d]\nName=[n2]\nMajorVersion=[B]\nMinorVersion=[B]\nServerType=[W]\nCommentPointer=[W]\nServerName=[S]\n",
275146773Ssam	    maxbuf, unicodestr);
27698524Sfenner	break;
27798524Sfenner
27898524Sfenner    case 0x8:
27998524Sfenner	data = smb_fdata(data,
28098524Sfenner	    "BROWSE PACKET:\nType=[B] (ElectionFrame)\nElectionVersion=[B]\nOSSummary=[W]\nUptime=[(W, W)]\nServerName=[S]\n",
281146773Ssam	    maxbuf, unicodestr);
28298524Sfenner	break;
28398524Sfenner
28498524Sfenner    case 0xb:
28598524Sfenner	data = smb_fdata(data,
28698524Sfenner	    "BROWSE PACKET:\nType=[B] (BecomeBackupBrowser)\nName=[S]\n",
287146773Ssam	    maxbuf, unicodestr);
28898524Sfenner	break;
28998524Sfenner
29098524Sfenner    case 0x9:
29198524Sfenner	data = smb_fdata(data,
292146773Ssam	    "BROWSE PACKET:\nType=[B] (GetBackupList)\nListCount?=[B]\nToken=[W]\n",
293146773Ssam	    maxbuf, unicodestr);
29498524Sfenner	break;
29598524Sfenner
29698524Sfenner    case 0xa:
29798524Sfenner	data = smb_fdata(data,
298146773Ssam	    "BROWSE PACKET:\nType=[B] (BackupListResponse)\nServerCount?=[B]\nToken=[W]\n*Name=[S]\n",
299146773Ssam	    maxbuf, unicodestr);
30098524Sfenner	break;
30198524Sfenner
30298524Sfenner    case 0xd:
30398524Sfenner	data = smb_fdata(data,
30498524Sfenner	    "BROWSE PACKET:\nType=[B] (MasterAnnouncement)\nMasterName=[S]\n",
305146773Ssam	    maxbuf, unicodestr);
30698524Sfenner	break;
30798524Sfenner
30898524Sfenner    case 0xe:
30998524Sfenner	data = smb_fdata(data,
310146773Ssam	    "BROWSE PACKET:\nType=[B] (ResetBrowser)\nOptions=[B]\n", maxbuf, unicodestr);
31198524Sfenner	break;
31298524Sfenner
31398524Sfenner    default:
314146773Ssam	data = smb_fdata(data, "Unknown Browser Frame ", maxbuf, unicodestr);
31598524Sfenner	break;
31698524Sfenner    }
31798524Sfenner    return;
31898524Sfennertrunc:
31998524Sfenner    printf("[|SMB]");
32098524Sfenner    return;
32156893Sfenner}
32256893Sfenner
32356893Sfenner
32498524Sfennerstatic void
32598524Sfennerprint_ipc(const u_char *param, int paramlen, const u_char *data, int datalen)
32656893Sfenner{
32798524Sfenner    if (paramlen)
328146773Ssam	smb_fdata(param, "Command=[w]\nStr1=[S]\nStr2=[S]\n", param + paramlen,
329146773Ssam	    unicodestr);
33098524Sfenner    if (datalen)
331146773Ssam	smb_fdata(data, "IPC ", data + datalen, unicodestr);
33256893Sfenner}
33356893Sfenner
33456893Sfenner
33598524Sfennerstatic void
33698524Sfennerprint_trans(const u_char *words, const u_char *data1, const u_char *buf, const u_char *maxbuf)
33756893Sfenner{
338146773Ssam    u_int bcc;
339111726Sfenner    const char *f1, *f2, *f3, *f4;
34098524Sfenner    const u_char *data, *param;
34198524Sfenner    const u_char *w = words + 1;
34298524Sfenner    int datalen, paramlen;
34356893Sfenner
34498524Sfenner    if (request) {
34598524Sfenner	TCHECK2(w[12 * 2], 2);
34698524Sfenner	paramlen = EXTRACT_LE_16BITS(w + 9 * 2);
34798524Sfenner	param = buf + EXTRACT_LE_16BITS(w + 10 * 2);
34898524Sfenner	datalen = EXTRACT_LE_16BITS(w + 11 * 2);
34998524Sfenner	data = buf + EXTRACT_LE_16BITS(w + 12 * 2);
35098524Sfenner	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";
35198524Sfenner	f2 = "|Name=[S]\n";
35298524Sfenner	f3 = "|Param ";
35398524Sfenner	f4 = "|Data ";
35498524Sfenner    } else {
35598524Sfenner	TCHECK2(w[7 * 2], 2);
35698524Sfenner	paramlen = EXTRACT_LE_16BITS(w + 3 * 2);
35798524Sfenner	param = buf + EXTRACT_LE_16BITS(w + 4 * 2);
35898524Sfenner	datalen = EXTRACT_LE_16BITS(w + 6 * 2);
35998524Sfenner	data = buf + EXTRACT_LE_16BITS(w + 7 * 2);
36098524Sfenner	f1 = "TotParamCnt=[d] \nTotDataCnt=[d] \nRes1=[d]\nParamCnt=[d] \nParamOff=[d] \nRes2=[d] \nDataCnt=[d] \nDataOff=[d] \nRes3=[d]\nLsetup=[d]\n";
36198524Sfenner	f2 = "|Unknown ";
36298524Sfenner	f3 = "|Param ";
36398524Sfenner	f4 = "|Data ";
36498524Sfenner    }
36556893Sfenner
366146773Ssam    smb_fdata(words + 1, f1, SMBMIN(words + 1 + 2 * words[0], maxbuf),
367146773Ssam        unicodestr);
36856893Sfenner
369146773Ssam    TCHECK2(*data1, 2);
370146773Ssam    bcc = EXTRACT_LE_16BITS(data1);
371146773Ssam    printf("smb_bcc=%u\n", bcc);
372146773Ssam    if (bcc > 0) {
373146773Ssam	smb_fdata(data1 + 2, f2, maxbuf - (paramlen + datalen), unicodestr);
37456893Sfenner
375146773Ssam	if (strcmp((const char *)(data1 + 2), "\\MAILSLOT\\BROWSE") == 0) {
376146773Ssam	    print_browse(param, paramlen, data, datalen);
377146773Ssam	    return;
378146773Ssam	}
379146773Ssam
380146773Ssam	if (strcmp((const char *)(data1 + 2), "\\PIPE\\LANMAN") == 0) {
381146773Ssam	    print_ipc(param, paramlen, data, datalen);
382146773Ssam	    return;
383146773Ssam	}
384146773Ssam
385146773Ssam	if (paramlen)
386146773Ssam	    smb_fdata(param, f3, SMBMIN(param + paramlen, maxbuf), unicodestr);
387146773Ssam	if (datalen)
388146773Ssam	    smb_fdata(data, f4, SMBMIN(data + datalen, maxbuf), unicodestr);
38998524Sfenner    }
39056893Sfenner    return;
39198524Sfennertrunc:
39298524Sfenner    printf("[|SMB]");
39398524Sfenner    return;
39456893Sfenner}
39556893Sfenner
39656893Sfenner
39798524Sfennerstatic void
398127668Sbmsprint_negprot(const u_char *words, const u_char *data, const u_char *buf _U_, const u_char *maxbuf)
39956893Sfenner{
400146773Ssam    u_int wct, bcc;
401111726Sfenner    const char *f1 = NULL, *f2 = NULL;
40256893Sfenner
40398524Sfenner    TCHECK(words[0]);
404146773Ssam    wct = words[0];
40598524Sfenner    if (request)
406146773Ssam	f2 = "*|Dialect=[Y]\n";
40798524Sfenner    else {
408146773Ssam	if (wct == 1)
40998524Sfenner	    f1 = "Core Protocol\nDialectIndex=[d]";
410146773Ssam	else if (wct == 17)
41198524Sfenner	    f1 = "NT1 Protocol\nDialectIndex=[d]\nSecMode=[B]\nMaxMux=[d]\nNumVcs=[d]\nMaxBuffer=[D]\nRawSize=[D]\nSessionKey=[W]\nCapabilities=[W]\nServerTime=[T3]TimeZone=[d]\nCryptKey=";
412146773Ssam	else if (wct == 13)
41398524Sfenner	    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=";
41456893Sfenner    }
41556893Sfenner
41698524Sfenner    if (f1)
417146773Ssam	smb_fdata(words + 1, f1, SMBMIN(words + 1 + wct * 2, maxbuf),
418146773Ssam	    unicodestr);
41998524Sfenner    else
420146773Ssam	print_data(words + 1, SMBMIN(wct * 2, PTR_DIFF(maxbuf, words + 1)));
42198524Sfenner
42298524Sfenner    TCHECK2(*data, 2);
423146773Ssam    bcc = EXTRACT_LE_16BITS(data);
424146773Ssam    printf("smb_bcc=%u\n", bcc);
425146773Ssam    if (bcc > 0) {
426146773Ssam	if (f2)
427146773Ssam	    smb_fdata(data + 2, f2, SMBMIN(data + 2 + EXTRACT_LE_16BITS(data),
428146773Ssam		maxbuf), unicodestr);
429146773Ssam	else
430146773Ssam	    print_data(data + 2, SMBMIN(EXTRACT_LE_16BITS(data), PTR_DIFF(maxbuf, data + 2)));
431146773Ssam    }
43298524Sfenner    return;
43398524Sfennertrunc:
43498524Sfenner    printf("[|SMB]");
43598524Sfenner    return;
43656893Sfenner}
43756893Sfenner
43898524Sfennerstatic void
439127668Sbmsprint_sesssetup(const u_char *words, const u_char *data, const u_char *buf _U_, const u_char *maxbuf)
44056893Sfenner{
441146773Ssam    u_int wct, bcc;
442111726Sfenner    const char *f1 = NULL, *f2 = NULL;
44356893Sfenner
44498524Sfenner    TCHECK(words[0]);
445146773Ssam    wct = words[0];
44698524Sfenner    if (request) {
447146773Ssam	if (wct == 10)
44898524Sfenner	    f1 = "Com2=[w]\nOff2=[d]\nBufSize=[d]\nMpxMax=[d]\nVcNum=[d]\nSessionKey=[W]\nPassLen=[d]\nCryptLen=[d]\nCryptOff=[d]\nPass&Name=\n";
44998524Sfenner	else
45098524Sfenner	    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";
45156893Sfenner    } else {
452146773Ssam	if (wct == 3) {
45398524Sfenner	    f1 = "Com2=[w]\nOff2=[d]\nAction=[w]\n";
454146773Ssam	} else if (wct == 13) {
45598524Sfenner	    f1 = "Com2=[B]\nRes=[B]\nOff2=[d]\nAction=[w]\n";
45698524Sfenner	    f2 = "NativeOS=[S]\nNativeLanMan=[S]\nPrimaryDomain=[S]\n";
45798524Sfenner	}
45856893Sfenner    }
45956893Sfenner
46098524Sfenner    if (f1)
461146773Ssam	smb_fdata(words + 1, f1, SMBMIN(words + 1 + wct * 2, maxbuf),
462146773Ssam	    unicodestr);
46398524Sfenner    else
464146773Ssam	print_data(words + 1, SMBMIN(wct * 2, PTR_DIFF(maxbuf, words + 1)));
46598524Sfenner
46698524Sfenner    TCHECK2(*data, 2);
467146773Ssam    bcc = EXTRACT_LE_16BITS(data);
468146773Ssam    printf("smb_bcc=%u\n", bcc);
469146773Ssam    if (bcc > 0) {
470146773Ssam	if (f2)
471146773Ssam	    smb_fdata(data + 2, f2, SMBMIN(data + 2 + EXTRACT_LE_16BITS(data),
472146773Ssam		maxbuf), unicodestr);
473146773Ssam	else
474146773Ssam	    print_data(data + 2, SMBMIN(EXTRACT_LE_16BITS(data), PTR_DIFF(maxbuf, data + 2)));
475146773Ssam    }
47698524Sfenner    return;
47798524Sfennertrunc:
47898524Sfenner    printf("[|SMB]");
47998524Sfenner    return;
48056893Sfenner}
48156893Sfenner
482146773Ssamstatic void
483146773Ssamprint_lockingandx(const u_char *words, const u_char *data, const u_char *buf _U_, const u_char *maxbuf)
484146773Ssam{
485146773Ssam    u_int wct, bcc;
486146773Ssam    const u_char *maxwords;
487146773Ssam    const char *f1 = NULL, *f2 = NULL;
48856893Sfenner
489146773Ssam    TCHECK(words[0]);
490146773Ssam    wct = words[0];
491146773Ssam    if (request) {
492146773Ssam	f1 = "Com2=[w]\nOff2=[d]\nHandle=[d]\nLockType=[w]\nTimeOut=[D]\nUnlockCount=[d]\nLockCount=[d]\n";
493146773Ssam	TCHECK(words[7]);
494146773Ssam	if (words[7] & 0x10)
495146773Ssam	    f2 = "*Process=[d]\n[P2]Offset=[M]\nLength=[M]\n";
496146773Ssam	else
497146773Ssam	    f2 = "*Process=[d]\nOffset=[D]\nLength=[D]\n";
498146773Ssam    } else {
499146773Ssam	f1 = "Com2=[w]\nOff2=[d]\n";
500146773Ssam    }
501146773Ssam
502146773Ssam    maxwords = SMBMIN(words + 1 + wct * 2, maxbuf);
503146773Ssam    if (wct)
504146773Ssam	smb_fdata(words + 1, f1, maxwords, unicodestr);
505146773Ssam
506146773Ssam    TCHECK2(*data, 2);
507146773Ssam    bcc = EXTRACT_LE_16BITS(data);
508146773Ssam    printf("smb_bcc=%u\n", bcc);
509146773Ssam    if (bcc > 0) {
510146773Ssam	if (f2)
511146773Ssam	    smb_fdata(data + 2, f2, SMBMIN(data + 2 + EXTRACT_LE_16BITS(data),
512146773Ssam		maxbuf), unicodestr);
513146773Ssam	else
514146773Ssam	    print_data(data + 2, SMBMIN(EXTRACT_LE_16BITS(data), PTR_DIFF(maxbuf, data + 2)));
515146773Ssam    }
516146773Ssam    return;
517146773Ssamtrunc:
518146773Ssam    printf("[|SMB]");
519146773Ssam    return;
520146773Ssam}
521146773Ssam
522146773Ssam
52398524Sfennerstatic struct smbfns smb_fns[] = {
52498524Sfenner    { -1, "SMBunknown", 0, DEFDESCRIPT },
52556893Sfenner
52698524Sfenner    { SMBtcon, "SMBtcon", 0,
52798524Sfenner	{ NULL, "Path=[Z]\nPassword=[Z]\nDevice=[Z]\n",
52898524Sfenner	  "MaxXmit=[d]\nTreeId=[d]\n", NULL,
52998524Sfenner	  NULL } },
53056893Sfenner
53198524Sfenner    { SMBtdis, "SMBtdis", 0, DEFDESCRIPT },
53298524Sfenner    { SMBexit,  "SMBexit", 0, DEFDESCRIPT },
53398524Sfenner    { SMBioctl, "SMBioctl", 0, DEFDESCRIPT },
53456893Sfenner
53598524Sfenner    { SMBecho, "SMBecho", 0,
53698524Sfenner	{ "ReverbCount=[d]\n", NULL,
53798524Sfenner	  "SequenceNum=[d]\n", NULL,
53898524Sfenner	  NULL } },
53956893Sfenner
54098524Sfenner    { SMBulogoffX, "SMBulogoffX", FLG_CHAIN, DEFDESCRIPT },
54156893Sfenner
54298524Sfenner    { SMBgetatr, "SMBgetatr", 0,
54398524Sfenner	{ NULL, "Path=[Z]\n",
54498524Sfenner	  "Attribute=[A]\nTime=[T2]Size=[D]\nRes=([w,w,w,w,w])\n", NULL,
54598524Sfenner	  NULL } },
54656893Sfenner
54798524Sfenner    { SMBsetatr, "SMBsetatr", 0,
54898524Sfenner	{ "Attribute=[A]\nTime=[T2]Res=([w,w,w,w,w])\n", "Path=[Z]\n",
54998524Sfenner	  NULL, NULL, NULL } },
55056893Sfenner
55198524Sfenner    { SMBchkpth, "SMBchkpth", 0,
55298524Sfenner       { NULL, "Path=[Z]\n", NULL, NULL, NULL } },
55356893Sfenner
55498524Sfenner    { SMBsearch, "SMBsearch", 0,
55598524Sfenner	{ "Count=[d]\nAttrib=[A]\n",
55698524Sfenner	  "Path=[Z]\nBlkType=[B]\nBlkLen=[d]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\nRes2=[W]\n",
55798524Sfenner	  "Count=[d]\n",
55898524Sfenner	  "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",
55998524Sfenner	  NULL } },
56056893Sfenner
56198524Sfenner    { SMBopen, "SMBopen", 0,
56298524Sfenner	{ "Mode=[w]\nAttribute=[A]\n", "Path=[Z]\n",
56398524Sfenner	  "Handle=[d]\nOAttrib=[A]\nTime=[T2]Size=[D]\nAccess=[w]\n",
56498524Sfenner	  NULL, NULL } },
56556893Sfenner
56698524Sfenner    { SMBcreate, "SMBcreate", 0,
56798524Sfenner	{ "Attrib=[A]\nTime=[T2]", "Path=[Z]\n", "Handle=[d]\n", NULL, NULL } },
56856893Sfenner
56998524Sfenner    { SMBmknew, "SMBmknew", 0,
57098524Sfenner	{ "Attrib=[A]\nTime=[T2]", "Path=[Z]\n", "Handle=[d]\n", NULL, NULL } },
57156893Sfenner
57298524Sfenner    { SMBunlink, "SMBunlink", 0,
57398524Sfenner	{ "Attrib=[A]\n", "Path=[Z]\n", NULL, NULL, NULL } },
57456893Sfenner
57598524Sfenner    { SMBread, "SMBread", 0,
57698524Sfenner	{ "Handle=[d]\nByteCount=[d]\nOffset=[D]\nCountLeft=[d]\n", NULL,
57798524Sfenner	  "Count=[d]\nRes=([w,w,w,w])\n", NULL, NULL } },
57856893Sfenner
57998524Sfenner    { SMBwrite, "SMBwrite", 0,
58098524Sfenner	{ "Handle=[d]\nByteCount=[d]\nOffset=[D]\nCountLeft=[d]\n", NULL,
58198524Sfenner	  "Count=[d]\n", NULL, NULL } },
58256893Sfenner
58398524Sfenner    { SMBclose, "SMBclose", 0,
58498524Sfenner	{ "Handle=[d]\nTime=[T2]", NULL, NULL, NULL, NULL } },
58556893Sfenner
58698524Sfenner    { SMBmkdir, "SMBmkdir", 0,
58798524Sfenner	{ NULL, "Path=[Z]\n", NULL, NULL, NULL } },
58856893Sfenner
58998524Sfenner    { SMBrmdir, "SMBrmdir", 0,
59098524Sfenner	{ NULL, "Path=[Z]\n", NULL, NULL, NULL } },
59156893Sfenner
59298524Sfenner    { SMBdskattr, "SMBdskattr", 0,
59398524Sfenner	{ NULL, NULL,
59498524Sfenner	  "TotalUnits=[d]\nBlocksPerUnit=[d]\nBlockSize=[d]\nFreeUnits=[d]\nMedia=[w]\n",
59598524Sfenner	  NULL, NULL } },
59656893Sfenner
59798524Sfenner    { SMBmv, "SMBmv", 0,
59898524Sfenner	{ "Attrib=[A]\n", "OldPath=[Z]\nNewPath=[Z]\n", NULL, NULL, NULL } },
59956893Sfenner
60098524Sfenner    /*
60198524Sfenner     * this is a Pathworks specific call, allowing the
60298524Sfenner     * changing of the root path
60398524Sfenner     */
60498524Sfenner    { pSETDIR, "SMBsetdir", 0, { NULL, "Path=[Z]\n", NULL, NULL, NULL } },
60556893Sfenner
60698524Sfenner    { SMBlseek, "SMBlseek", 0,
607127668Sbms	{ "Handle=[d]\nMode=[w]\nOffset=[D]\n", "Offset=[D]\n", NULL, NULL, NULL } },
60856893Sfenner
60998524Sfenner    { SMBflush, "SMBflush", 0, { "Handle=[d]\n", NULL, NULL, NULL, NULL } },
61056893Sfenner
61198524Sfenner    { SMBsplopen, "SMBsplopen", 0,
61298524Sfenner	{ "SetupLen=[d]\nMode=[w]\n", "Ident=[Z]\n", "Handle=[d]\n",
61398524Sfenner	  NULL, NULL } },
61456893Sfenner
61598524Sfenner    { SMBsplclose, "SMBsplclose", 0,
61698524Sfenner	{ "Handle=[d]\n", NULL, NULL, NULL, NULL } },
61756893Sfenner
61898524Sfenner    { SMBsplretq, "SMBsplretq", 0,
61998524Sfenner	{ "MaxCount=[d]\nStartIndex=[d]\n", NULL,
62098524Sfenner	  "Count=[d]\nIndex=[d]\n",
62198524Sfenner	  "*Time=[T2]Status=[B]\nJobID=[d]\nSize=[D]\nRes=[B]Name=[s16]\n",
62298524Sfenner	  NULL } },
62356893Sfenner
62498524Sfenner    { SMBsplwr, "SMBsplwr", 0,
62598524Sfenner	{ "Handle=[d]\n", NULL, NULL, NULL, NULL } },
62656893Sfenner
62798524Sfenner    { SMBlock, "SMBlock", 0,
62898524Sfenner	{ "Handle=[d]\nCount=[D]\nOffset=[D]\n", NULL, NULL, NULL, NULL } },
62956893Sfenner
63098524Sfenner    { SMBunlock, "SMBunlock", 0,
63198524Sfenner	{ "Handle=[d]\nCount=[D]\nOffset=[D]\n", NULL, NULL, NULL, NULL } },
63256893Sfenner
63398524Sfenner    /* CORE+ PROTOCOL FOLLOWS */
63456893Sfenner
63598524Sfenner    { SMBreadbraw, "SMBreadbraw", 0,
63698524Sfenner	{ "Handle=[d]\nOffset=[D]\nMaxCount=[d]\nMinCount=[d]\nTimeOut=[D]\nRes=[d]\n",
63798524Sfenner	  NULL, NULL, NULL, NULL } },
63856893Sfenner
63998524Sfenner    { SMBwritebraw, "SMBwritebraw", 0,
64098524Sfenner	{ "Handle=[d]\nTotalCount=[d]\nRes=[w]\nOffset=[D]\nTimeOut=[D]\nWMode=[w]\nRes2=[W]\n|DataSize=[d]\nDataOff=[d]\n",
64198524Sfenner	  NULL, "WriteRawAck", NULL, NULL } },
64256893Sfenner
64398524Sfenner    { SMBwritec, "SMBwritec", 0,
64498524Sfenner	{ NULL, NULL, "Count=[d]\n", NULL, NULL } },
64556893Sfenner
64698524Sfenner    { SMBwriteclose, "SMBwriteclose", 0,
64798524Sfenner	{ "Handle=[d]\nCount=[d]\nOffset=[D]\nTime=[T2]Res=([w,w,w,w,w,w])",
64898524Sfenner	  NULL, "Count=[d]\n", NULL, NULL } },
64956893Sfenner
65098524Sfenner    { SMBlockread, "SMBlockread", 0,
65198524Sfenner	{ "Handle=[d]\nByteCount=[d]\nOffset=[D]\nCountLeft=[d]\n", NULL,
65298524Sfenner	  "Count=[d]\nRes=([w,w,w,w])\n", NULL, NULL } },
65356893Sfenner
65498524Sfenner    { SMBwriteunlock, "SMBwriteunlock", 0,
65598524Sfenner	{ "Handle=[d]\nByteCount=[d]\nOffset=[D]\nCountLeft=[d]\n", NULL,
65698524Sfenner	  "Count=[d]\n", NULL, NULL } },
65756893Sfenner
65898524Sfenner    { SMBreadBmpx, "SMBreadBmpx", 0,
65998524Sfenner	{ "Handle=[d]\nOffset=[D]\nMaxCount=[d]\nMinCount=[d]\nTimeOut=[D]\nRes=[w]\n",
66098524Sfenner	  NULL,
66198524Sfenner	  "Offset=[D]\nTotCount=[d]\nRemaining=[d]\nRes=([w,w])\nDataSize=[d]\nDataOff=[d]\n",
66298524Sfenner	  NULL, NULL } },
66356893Sfenner
66498524Sfenner    { SMBwriteBmpx, "SMBwriteBmpx", 0,
66598524Sfenner	{ "Handle=[d]\nTotCount=[d]\nRes=[w]\nOffset=[D]\nTimeOut=[D]\nWMode=[w]\nRes2=[W]\nDataSize=[d]\nDataOff=[d]\n", NULL,
66698524Sfenner	  "Remaining=[d]\n", NULL, NULL } },
66756893Sfenner
66898524Sfenner    { SMBwriteBs, "SMBwriteBs", 0,
66998524Sfenner	{ "Handle=[d]\nTotCount=[d]\nOffset=[D]\nRes=[W]\nDataSize=[d]\nDataOff=[d]\n",
67098524Sfenner	  NULL, "Count=[d]\n", NULL, NULL } },
67156893Sfenner
67298524Sfenner    { SMBsetattrE, "SMBsetattrE", 0,
67398524Sfenner	{ "Handle=[d]\nCreationTime=[T2]AccessTime=[T2]ModifyTime=[T2]", NULL,
67498524Sfenner	  NULL, NULL, NULL } },
67556893Sfenner
67698524Sfenner    { SMBgetattrE, "SMBgetattrE", 0,
67798524Sfenner	{ "Handle=[d]\n", NULL,
67898524Sfenner	  "CreationTime=[T2]AccessTime=[T2]ModifyTime=[T2]Size=[D]\nAllocSize=[D]\nAttribute=[A]\n",
67998524Sfenner	  NULL, NULL } },
68056893Sfenner
68198524Sfenner    { SMBtranss, "SMBtranss", 0, DEFDESCRIPT },
68298524Sfenner    { SMBioctls, "SMBioctls", 0, DEFDESCRIPT },
68356893Sfenner
68498524Sfenner    { SMBcopy, "SMBcopy", 0,
68598524Sfenner	{ "TreeID2=[d]\nOFun=[w]\nFlags=[w]\n", "Path=[S]\nNewPath=[S]\n",
68698524Sfenner	  "CopyCount=[d]\n",  "|ErrStr=[S]\n",  NULL } },
68756893Sfenner
68898524Sfenner    { SMBmove, "SMBmove", 0,
68998524Sfenner	{ "TreeID2=[d]\nOFun=[w]\nFlags=[w]\n", "Path=[S]\nNewPath=[S]\n",
69098524Sfenner	  "MoveCount=[d]\n",  "|ErrStr=[S]\n",  NULL } },
69156893Sfenner
69298524Sfenner    { SMBopenX, "SMBopenX", FLG_CHAIN,
69398524Sfenner	{ "Com2=[w]\nOff2=[d]\nFlags=[w]\nMode=[w]\nSearchAttrib=[A]\nAttrib=[A]\nTime=[T2]OFun=[w]\nSize=[D]\nTimeOut=[D]\nRes=[W]\n",
69498524Sfenner	  "Path=[S]\n",
69598524Sfenner	  "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",
69698524Sfenner	  NULL, NULL } },
69756893Sfenner
69898524Sfenner    { SMBreadX, "SMBreadX", FLG_CHAIN,
69998524Sfenner	{ "Com2=[w]\nOff2=[d]\nHandle=[d]\nOffset=[D]\nMaxCount=[d]\nMinCount=[d]\nTimeOut=[D]\nCountLeft=[d]\n",
70098524Sfenner	  NULL,
70198524Sfenner	  "Com2=[w]\nOff2=[d]\nRemaining=[d]\nRes=[W]\nDataSize=[d]\nDataOff=[d]\nRes=([w,w,w,w])\n",
70298524Sfenner	  NULL, NULL } },
70356893Sfenner
70498524Sfenner    { SMBwriteX, "SMBwriteX", FLG_CHAIN,
70598524Sfenner	{ "Com2=[w]\nOff2=[d]\nHandle=[d]\nOffset=[D]\nTimeOut=[D]\nWMode=[w]\nCountLeft=[d]\nRes=[w]\nDataSize=[d]\nDataOff=[d]\n",
70698524Sfenner	  NULL,
70798524Sfenner	  "Com2=[w]\nOff2=[d]\nCount=[d]\nRemaining=[d]\nRes=[W]\n",
70898524Sfenner	  NULL, NULL } },
70956893Sfenner
71098524Sfenner    { SMBffirst, "SMBffirst", 0,
71198524Sfenner	{ "Count=[d]\nAttrib=[A]\n",
71298524Sfenner	  "Path=[Z]\nBlkType=[B]\nBlkLen=[d]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\n",
71398524Sfenner	  "Count=[d]\n",
71498524Sfenner	  "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",
71598524Sfenner	  NULL } },
71656893Sfenner
71798524Sfenner    { SMBfunique, "SMBfunique", 0,
71898524Sfenner	{ "Count=[d]\nAttrib=[A]\n",
71998524Sfenner	  "Path=[Z]\nBlkType=[B]\nBlkLen=[d]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\n",
72098524Sfenner	  "Count=[d]\n",
72198524Sfenner	  "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",
72298524Sfenner	  NULL } },
72356893Sfenner
72498524Sfenner    { SMBfclose, "SMBfclose", 0,
72598524Sfenner	{ "Count=[d]\nAttrib=[A]\n",
72698524Sfenner	  "Path=[Z]\nBlkType=[B]\nBlkLen=[d]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\n",
72798524Sfenner	  "Count=[d]\n",
72898524Sfenner	  "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",
72998524Sfenner	  NULL } },
73056893Sfenner
73198524Sfenner    { SMBfindnclose, "SMBfindnclose", 0,
73298524Sfenner	{ "Handle=[d]\n", NULL, NULL, NULL, NULL } },
73356893Sfenner
73498524Sfenner    { SMBfindclose, "SMBfindclose", 0,
73598524Sfenner	{ "Handle=[d]\n", NULL, NULL, NULL, NULL } },
73656893Sfenner
73798524Sfenner    { SMBsends, "SMBsends", 0,
73898524Sfenner	{ NULL, "Source=[Z]\nDest=[Z]\n", NULL, NULL, NULL } },
73956893Sfenner
74098524Sfenner    { SMBsendstrt, "SMBsendstrt", 0,
74198524Sfenner	{ NULL, "Source=[Z]\nDest=[Z]\n", "GroupID=[d]\n", NULL, NULL } },
74256893Sfenner
74398524Sfenner    { SMBsendend, "SMBsendend", 0,
74498524Sfenner	{ "GroupID=[d]\n", NULL, NULL, NULL, NULL } },
74556893Sfenner
74698524Sfenner    { SMBsendtxt, "SMBsendtxt", 0,
74798524Sfenner	{ "GroupID=[d]\n", NULL, NULL, NULL, NULL } },
74856893Sfenner
74998524Sfenner    { SMBsendb, "SMBsendb", 0,
75098524Sfenner	{ NULL, "Source=[Z]\nDest=[Z]\n", NULL, NULL, NULL } },
75156893Sfenner
75298524Sfenner    { SMBfwdname, "SMBfwdname", 0, DEFDESCRIPT },
75398524Sfenner    { SMBcancelf, "SMBcancelf", 0, DEFDESCRIPT },
75498524Sfenner    { SMBgetmac, "SMBgetmac", 0, DEFDESCRIPT },
75556893Sfenner
75698524Sfenner    { SMBnegprot, "SMBnegprot", 0,
75798524Sfenner	{ NULL, NULL, NULL, NULL, print_negprot } },
75856893Sfenner
75998524Sfenner    { SMBsesssetupX, "SMBsesssetupX", FLG_CHAIN,
76098524Sfenner	{ NULL, NULL, NULL, NULL, print_sesssetup } },
76156893Sfenner
76298524Sfenner    { SMBtconX, "SMBtconX", FLG_CHAIN,
76398524Sfenner	{ "Com2=[w]\nOff2=[d]\nFlags=[w]\nPassLen=[d]\nPasswd&Path&Device=\n",
764146773Ssam	  NULL, "Com2=[w]\nOff2=[d]\n", "ServiceType=[R]\n", NULL } },
76556893Sfenner
766146773Ssam    { SMBlockingX, "SMBlockingX", FLG_CHAIN,
767146773Ssam	{ NULL, NULL, NULL, NULL, print_lockingandx } },
768146773Ssam
76998524Sfenner    { SMBtrans2, "SMBtrans2", 0, { NULL, NULL, NULL, NULL, print_trans2 } },
77056893Sfenner
77198524Sfenner    { SMBtranss2, "SMBtranss2", 0, DEFDESCRIPT },
77298524Sfenner    { SMBctemp, "SMBctemp", 0, DEFDESCRIPT },
77398524Sfenner    { SMBreadBs, "SMBreadBs", 0, DEFDESCRIPT },
77498524Sfenner    { SMBtrans, "SMBtrans", 0, { NULL, NULL, NULL, NULL, print_trans } },
77556893Sfenner
77698524Sfenner    { SMBnttrans, "SMBnttrans", 0, DEFDESCRIPT },
77798524Sfenner    { SMBnttranss, "SMBnttranss", 0, DEFDESCRIPT },
77856893Sfenner
77998524Sfenner    { SMBntcreateX, "SMBntcreateX", FLG_CHAIN,
780146773Ssam	{ "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",
781146773Ssam	  "Path=[C]\n",
78298524Sfenner	  "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",
783127668Sbms	  NULL, NULL } },
78456893Sfenner
78598524Sfenner    { SMBntcancel, "SMBntcancel", 0, DEFDESCRIPT },
78656893Sfenner
78798524Sfenner    { -1, NULL, 0, DEFDESCRIPT }
78898524Sfenner};
78956893Sfenner
79056893Sfenner
79198524Sfenner/*
79298524Sfenner * print a SMB message
79398524Sfenner */
79498524Sfennerstatic void
79598524Sfennerprint_smb(const u_char *buf, const u_char *maxbuf)
79656893Sfenner{
797146773Ssam    u_int16_t flags2;
798146773Ssam    int nterrcodes;
79998524Sfenner    int command;
800146773Ssam    u_int32_t nterror;
801146773Ssam    const u_char *words, *maxwords, *data;
80298524Sfenner    struct smbfns *fn;
803127668Sbms    const char *fmt_smbheader =
80498524Sfenner        "[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";
805146773Ssam    int smboffset;
80656893Sfenner
80798524Sfenner    TCHECK(buf[9]);
80898524Sfenner    request = (buf[9] & 0x80) ? 0 : 1;
809146773Ssam    flags2 = EXTRACT_LE_16BITS(&buf[10]);
810146773Ssam    unicodestr = flags2 & 0x8000;
811146773Ssam    nterrcodes = flags2 & 0x4000;
812146773Ssam    startbuf = buf;
81356893Sfenner
81498524Sfenner    command = buf[4];
81556893Sfenner
81698524Sfenner    fn = smbfind(command, smb_fns);
81756893Sfenner
81898524Sfenner    if (vflag > 1)
81998524Sfenner	printf("\n");
82056893Sfenner
82198524Sfenner    printf("SMB PACKET: %s (%s)\n", fn->name, request ? "REQUEST" : "REPLY");
82256893Sfenner
82398524Sfenner    if (vflag < 2)
82498524Sfenner	return;
82556893Sfenner
82698524Sfenner    /* print out the header */
827146773Ssam    smb_fdata(buf, fmt_smbheader, buf + 33, unicodestr);
82856893Sfenner
829146773Ssam    if (nterrcodes) {
830146773Ssam    	nterror = EXTRACT_LE_32BITS(&buf[5]);
831146773Ssam	if (nterror)
832146773Ssam	    printf("NTError = %s\n", nt_errstr(nterror));
833146773Ssam    } else {
834146773Ssam	if (buf[5])
835146773Ssam	    printf("SMBError = %s\n", smb_errstr(buf[5], EXTRACT_LE_16BITS(&buf[7])));
836146773Ssam    }
83756893Sfenner
838146773Ssam    smboffset = 32;
83956893Sfenner
84098524Sfenner    for (;;) {
841111726Sfenner	const char *f1, *f2;
84298524Sfenner	int wct;
843127668Sbms	u_int bcc;
844146773Ssam	int newsmboffset;
84556893Sfenner
846146773Ssam	words = buf + smboffset;
84798524Sfenner	TCHECK(words[0]);
84898524Sfenner	wct = words[0];
84998524Sfenner	data = words + 1 + wct * 2;
850146773Ssam	maxwords = SMBMIN(data, maxbuf);
85198524Sfenner
85298524Sfenner	if (request) {
85398524Sfenner	    f1 = fn->descript.req_f1;
85498524Sfenner	    f2 = fn->descript.req_f2;
85556893Sfenner	} else {
85698524Sfenner	    f1 = fn->descript.rep_f1;
85798524Sfenner	    f2 = fn->descript.rep_f2;
85856893Sfenner	}
85956893Sfenner
86098524Sfenner	if (fn->descript.fn)
86198524Sfenner	    (*fn->descript.fn)(words, data, buf, maxbuf);
86298524Sfenner	else {
86398524Sfenner	    if (wct) {
86498524Sfenner		if (f1)
865146773Ssam		    smb_fdata(words + 1, f1, words + 1 + wct * 2, unicodestr);
86698524Sfenner		else {
86798524Sfenner		    int i;
86898524Sfenner		    int v;
86956893Sfenner
870146773Ssam		    for (i = 0; &words[1 + 2 * i] < maxwords; i++) {
87198524Sfenner			TCHECK2(words[1 + 2 * i], 2);
87298524Sfenner			v = EXTRACT_LE_16BITS(words + 1 + 2 * i);
87398524Sfenner			printf("smb_vwv[%d]=%d (0x%X)\n", i, v, v);
87498524Sfenner		    }
87598524Sfenner		}
87698524Sfenner	    }
87756893Sfenner
87898524Sfenner	    TCHECK2(*data, 2);
87998524Sfenner	    bcc = EXTRACT_LE_16BITS(data);
880146773Ssam	    printf("smb_bcc=%u\n", bcc);
88198524Sfenner	    if (f2) {
882146773Ssam		if (bcc > 0)
883146773Ssam		    smb_fdata(data + 2, f2, data + 2 + bcc, unicodestr);
88498524Sfenner	    } else {
88598524Sfenner		if (bcc > 0) {
88698524Sfenner		    printf("smb_buf[]=\n");
88798524Sfenner		    print_data(data + 2, SMBMIN(bcc, PTR_DIFF(maxbuf, data + 2)));
88898524Sfenner		}
88998524Sfenner	    }
89098524Sfenner	}
89198524Sfenner
89298524Sfenner	if ((fn->flags & FLG_CHAIN) == 0)
89398524Sfenner	    break;
89498524Sfenner	if (wct == 0)
89598524Sfenner	    break;
89698524Sfenner	TCHECK(words[1]);
897146773Ssam	command = words[1];
89898524Sfenner	if (command == 0xFF)
89998524Sfenner	    break;
90098524Sfenner	TCHECK2(words[3], 2);
901146773Ssam	newsmboffset = EXTRACT_LE_16BITS(words + 3);
90298524Sfenner
90398524Sfenner	fn = smbfind(command, smb_fns);
90498524Sfenner
90598524Sfenner	printf("\nSMB PACKET: %s (%s) (CHAINED)\n",
90698524Sfenner	    fn->name, request ? "REQUEST" : "REPLY");
907172683Smlaier	if (newsmboffset <= smboffset) {
908172683Smlaier	    printf("Bad andX offset: %u <= %u\n", newsmboffset, smboffset);
909146773Ssam	    break;
910146773Ssam	}
911146773Ssam	smboffset = newsmboffset;
91256893Sfenner    }
91356893Sfenner
91498524Sfenner    printf("\n");
91598524Sfenner    return;
91698524Sfennertrunc:
91798524Sfenner    printf("[|SMB]");
91898524Sfenner    return;
91956893Sfenner}
92056893Sfenner
92156893Sfenner
92256893Sfenner/*
92398524Sfenner * print a NBT packet received across tcp on port 139
92498524Sfenner */
92598524Sfennervoid
92698524Sfennernbt_tcp_print(const u_char *data, int length)
92756893Sfenner{
928147899Ssam    int caplen;
929146773Ssam    int type;
930127668Sbms    u_int nbt_len;
931147899Ssam    const u_char *maxbuf;
93256893Sfenner
933147899Ssam    if (length < 4)
934147899Ssam	goto trunc;
935147899Ssam    if (snapend < data)
936147899Ssam	goto trunc;
937147899Ssam    caplen = snapend - data;
938147899Ssam    if (caplen < 4)
939147899Ssam	goto trunc;
940147899Ssam    maxbuf = data + caplen;
941146773Ssam    type = data[0];
94298524Sfenner    nbt_len = EXTRACT_16BITS(data + 2);
943147899Ssam    length -= 4;
944147899Ssam    caplen -= 4;
94556893Sfenner
94698524Sfenner    startbuf = data;
94756893Sfenner
948146773Ssam    if (vflag < 2) {
949146773Ssam	printf(" NBT Session Packet: ");
950146773Ssam	switch (type) {
951146773Ssam	case 0x00:
952146773Ssam	    printf("Session Message");
953146773Ssam	    break;
95456893Sfenner
955146773Ssam	case 0x81:
956146773Ssam	    printf("Session Request");
957146773Ssam	    break;
95856893Sfenner
959146773Ssam	case 0x82:
960146773Ssam	    printf("Session Granted");
961146773Ssam	    break;
96256893Sfenner
963146773Ssam	case 0x83:
964146773Ssam	  {
965146773Ssam	    int ecode;
96698524Sfenner
967147899Ssam	    if (nbt_len < 4)
968147899Ssam		goto trunc;
969147899Ssam	    if (length < 4)
970147899Ssam		goto trunc;
971147899Ssam	    if (caplen < 4)
972147899Ssam		goto trunc;
973146773Ssam	    ecode = data[4];
974146773Ssam
975146773Ssam	    printf("Session Reject, ");
976146773Ssam	    switch (ecode) {
977146773Ssam	    case 0x80:
978146773Ssam		printf("Not listening on called name");
979146773Ssam		break;
980146773Ssam	    case 0x81:
981146773Ssam		printf("Not listening for calling name");
982146773Ssam		break;
983146773Ssam	    case 0x82:
984146773Ssam		printf("Called name not present");
985146773Ssam		break;
986146773Ssam	    case 0x83:
987146773Ssam		printf("Called name present, but insufficient resources");
988146773Ssam		break;
989146773Ssam	    default:
990146773Ssam		printf("Unspecified error 0x%X", ecode);
991146773Ssam		break;
992146773Ssam	    }
993146773Ssam	  }
99498524Sfenner	    break;
99556893Sfenner
996146773Ssam	case 0x85:
997146773Ssam	    printf("Session Keepalive");
998146773Ssam	    break;
999146773Ssam
1000146773Ssam	default:
1001146773Ssam	    data = smb_fdata(data, "Unknown packet type [rB]", maxbuf, 0);
1002146773Ssam	    break;
1003146773Ssam	}
1004146773Ssam    } else {
1005146773Ssam	printf ("\n>>> NBT Session Packet\n");
1006146773Ssam	switch (type) {
1007146773Ssam	case 0x00:
1008146773Ssam	    data = smb_fdata(data, "[P1]NBT Session Message\nFlags=[B]\nLength=[rd]\n",
1009146773Ssam		data + 4, 0);
1010146773Ssam	    if (data == NULL)
1011146773Ssam		break;
1012147899Ssam	    if (nbt_len >= 4 && caplen >= 4 && memcmp(data,"\377SMB",4) == 0) {
1013147899Ssam		if ((int)nbt_len > caplen) {
1014147899Ssam		    if ((int)nbt_len > length)
1015147899Ssam			printf("WARNING: Packet is continued in later TCP segments\n");
1016147899Ssam		    else
1017147899Ssam			printf("WARNING: Short packet. Try increasing the snap length by %d\n",
1018147899Ssam			    nbt_len - caplen);
1019147899Ssam		}
1020146773Ssam		print_smb(data, maxbuf > data + nbt_len ? data + nbt_len : maxbuf);
1021146773Ssam	    } else
1022147899Ssam		printf("Session packet:(raw data or continuation?)\n");
1023146773Ssam	    break;
1024146773Ssam
102598524Sfenner	case 0x81:
102698524Sfenner	    data = smb_fdata(data,
1027146773Ssam		"[P1]NBT Session Request\nFlags=[B]\nLength=[rd]\nDestination=[n1]\nSource=[n1]\n",
1028146773Ssam		maxbuf, 0);
102998524Sfenner	    break;
103056893Sfenner
103198524Sfenner	case 0x82:
1032146773Ssam	    data = smb_fdata(data, "[P1]NBT Session Granted\nFlags=[B]\nLength=[rd]\n", maxbuf, 0);
103398524Sfenner	    break;
103498524Sfenner
103598524Sfenner	case 0x83:
103698524Sfenner	  {
1037147899Ssam	    const u_char *origdata;
103898524Sfenner	    int ecode;
103998524Sfenner
1040147899Ssam	    origdata = data;
1041146773Ssam	    data = smb_fdata(data, "[P1]NBT SessionReject\nFlags=[B]\nLength=[rd]\nReason=[B]\n",
1042146773Ssam		maxbuf, 0);
1043147899Ssam	    if (data == NULL)
104498524Sfenner		break;
1045147899Ssam	    if (nbt_len >= 1 && caplen >= 1) {
1046147899Ssam		ecode = origdata[4];
1047147899Ssam		switch (ecode) {
1048147899Ssam		case 0x80:
1049147899Ssam		    printf("Not listening on called name\n");
1050147899Ssam		    break;
1051147899Ssam		case 0x81:
1052147899Ssam		    printf("Not listening for calling name\n");
1053147899Ssam		    break;
1054147899Ssam		case 0x82:
1055147899Ssam		    printf("Called name not present\n");
1056147899Ssam		    break;
1057147899Ssam		case 0x83:
1058147899Ssam		    printf("Called name present, but insufficient resources\n");
1059147899Ssam		    break;
1060147899Ssam		default:
1061147899Ssam		    printf("Unspecified error 0x%X\n", ecode);
1062147899Ssam		    break;
1063147899Ssam		}
106498524Sfenner	    }
106598524Sfenner	  }
106698524Sfenner	    break;
106798524Sfenner
106898524Sfenner	case 0x85:
1069146773Ssam	    data = smb_fdata(data, "[P1]NBT Session Keepalive\nFlags=[B]\nLength=[rd]\n", maxbuf, 0);
107098524Sfenner	    break;
107198524Sfenner
107298524Sfenner	default:
1073146773Ssam	    data = smb_fdata(data, "NBT - Unknown packet type\nType=[B]\n", maxbuf, 0);
1074146773Ssam	    break;
1075146773Ssam	}
1076146773Ssam	printf("\n");
1077146773Ssam	fflush(stdout);
107898524Sfenner    }
107998524Sfenner    return;
108098524Sfennertrunc:
108198524Sfenner    printf("[|SMB]");
108298524Sfenner    return;
108356893Sfenner}
108456893Sfenner
108556893Sfenner
108656893Sfenner/*
108798524Sfenner * print a NBT packet received across udp on port 137
108898524Sfenner */
108998524Sfennervoid
109098524Sfennernbt_udp137_print(const u_char *data, int length)
109156893Sfenner{
109298524Sfenner    const u_char *maxbuf = data + length;
109398524Sfenner    int name_trn_id, response, opcode, nm_flags, rcode;
109498524Sfenner    int qdcount, ancount, nscount, arcount;
1095127668Sbms    const char *opcodestr;
1096111726Sfenner    const u_char *p;
109798524Sfenner    int total, i;
109856893Sfenner
109998524Sfenner    TCHECK2(data[10], 2);
110098524Sfenner    name_trn_id = EXTRACT_16BITS(data);
110198524Sfenner    response = (data[2] >> 7);
110298524Sfenner    opcode = (data[2] >> 3) & 0xF;
110398524Sfenner    nm_flags = ((data[2] & 0x7) << 4) + (data[3] >> 4);
110498524Sfenner    rcode = data[3] & 0xF;
110598524Sfenner    qdcount = EXTRACT_16BITS(data + 4);
110698524Sfenner    ancount = EXTRACT_16BITS(data + 6);
110798524Sfenner    nscount = EXTRACT_16BITS(data + 8);
110898524Sfenner    arcount = EXTRACT_16BITS(data + 10);
110998524Sfenner    startbuf = data;
111056893Sfenner
111198524Sfenner    if (maxbuf <= data)
111298524Sfenner	return;
111356893Sfenner
111498524Sfenner    if (vflag > 1)
111598524Sfenner	printf("\n>>> ");
111656893Sfenner
111798524Sfenner    printf("NBT UDP PACKET(137): ");
111898524Sfenner
111998524Sfenner    switch (opcode) {
112098524Sfenner    case 0: opcodestr = "QUERY"; break;
112198524Sfenner    case 5: opcodestr = "REGISTRATION"; break;
112298524Sfenner    case 6: opcodestr = "RELEASE"; break;
112398524Sfenner    case 7: opcodestr = "WACK"; break;
112498524Sfenner    case 8: opcodestr = "REFRESH(8)"; break;
112598524Sfenner    case 9: opcodestr = "REFRESH"; break;
112698524Sfenner    case 15: opcodestr = "MULTIHOMED REGISTRATION"; break;
112798524Sfenner    default: opcodestr = "OPUNKNOWN"; break;
112898524Sfenner    }
112998524Sfenner    printf("%s", opcodestr);
113098524Sfenner    if (response) {
113198524Sfenner	if (rcode)
113298524Sfenner	    printf("; NEGATIVE");
113398524Sfenner	else
113498524Sfenner	    printf("; POSITIVE");
113598524Sfenner    }
113698524Sfenner
113798524Sfenner    if (response)
113898524Sfenner	printf("; RESPONSE");
113956893Sfenner    else
114098524Sfenner	printf("; REQUEST");
114156893Sfenner
114298524Sfenner    if (nm_flags & 1)
114398524Sfenner	printf("; BROADCAST");
114498524Sfenner    else
114598524Sfenner	printf("; UNICAST");
114656893Sfenner
114798524Sfenner    if (vflag < 2)
114898524Sfenner	return;
114956893Sfenner
115098524Sfenner    printf("\nTrnID=0x%X\nOpCode=%d\nNmFlags=0x%X\nRcode=%d\nQueryCount=%d\nAnswerCount=%d\nAuthorityCount=%d\nAddressRecCount=%d\n",
115198524Sfenner	name_trn_id, opcode, nm_flags, rcode, qdcount, ancount, nscount,
115298524Sfenner	arcount);
115356893Sfenner
115498524Sfenner    p = data + 12;
115556893Sfenner
115698524Sfenner    total = ancount + nscount + arcount;
115798524Sfenner
115898524Sfenner    if (qdcount > 100 || total > 100) {
115998524Sfenner	printf("Corrupt packet??\n");
116098524Sfenner	return;
116156893Sfenner    }
116256893Sfenner
116356893Sfenner    if (qdcount) {
116498524Sfenner	printf("QuestionRecords:\n");
1165147899Ssam	for (i = 0; i < qdcount; i++) {
116698524Sfenner	    p = smb_fdata(p,
116798524Sfenner		"|Name=[n1]\nQuestionType=[rw]\nQuestionClass=[rw]\n#",
1168146773Ssam		maxbuf, 0);
1169147899Ssam	    if (p == NULL)
1170147899Ssam		goto out;
1171147899Ssam	}
117256893Sfenner    }
117356893Sfenner
117456893Sfenner    if (total) {
117598524Sfenner	printf("\nResourceRecords:\n");
117698524Sfenner	for (i = 0; i < total; i++) {
117798524Sfenner	    int rdlen;
117898524Sfenner	    int restype;
117998524Sfenner
1180146773Ssam	    p = smb_fdata(p, "Name=[n1]\n#", maxbuf, 0);
118175115Sfenner	    if (p == NULL)
118298524Sfenner		goto out;
118398524Sfenner	    restype = EXTRACT_16BITS(p);
1184146773Ssam	    p = smb_fdata(p, "ResType=[rw]\nResClass=[rw]\nTTL=[rD]\n", p + 8, 0);
118598524Sfenner	    if (p == NULL)
118698524Sfenner		goto out;
118798524Sfenner	    rdlen = EXTRACT_16BITS(p);
118898524Sfenner	    printf("ResourceLength=%d\nResourceData=\n", rdlen);
118998524Sfenner	    p += 2;
119098524Sfenner	    if (rdlen == 6) {
1191146773Ssam		p = smb_fdata(p, "AddrType=[rw]\nAddress=[b.b.b.b]\n", p + rdlen, 0);
119298524Sfenner		if (p == NULL)
119398524Sfenner		    goto out;
119498524Sfenner	    } else {
119598524Sfenner		if (restype == 0x21) {
119698524Sfenner		    int numnames;
119798524Sfenner
119898524Sfenner		    TCHECK(*p);
119998524Sfenner		    numnames = p[0];
1200146773Ssam		    p = smb_fdata(p, "NumNames=[B]\n", p + 1, 0);
120198524Sfenner		    if (p == NULL)
120298524Sfenner			goto out;
120398524Sfenner		    while (numnames--) {
1204146773Ssam			p = smb_fdata(p, "Name=[n2]\t#", maxbuf, 0);
1205147899Ssam			if (p == NULL)
1206147899Ssam			    goto out;
120798524Sfenner			TCHECK(*p);
120898524Sfenner			if (p[0] & 0x80)
120998524Sfenner			    printf("<GROUP> ");
121098524Sfenner			switch (p[0] & 0x60) {
121198524Sfenner			case 0x00: printf("B "); break;
121298524Sfenner			case 0x20: printf("P "); break;
121398524Sfenner			case 0x40: printf("M "); break;
121498524Sfenner			case 0x60: printf("_ "); break;
121598524Sfenner			}
121698524Sfenner			if (p[0] & 0x10)
121798524Sfenner			    printf("<DEREGISTERING> ");
121898524Sfenner			if (p[0] & 0x08)
121998524Sfenner			    printf("<CONFLICT> ");
122098524Sfenner			if (p[0] & 0x04)
122198524Sfenner			    printf("<ACTIVE> ");
122298524Sfenner			if (p[0] & 0x02)
122398524Sfenner			    printf("<PERMANENT> ");
122498524Sfenner			printf("\n");
122598524Sfenner			p += 2;
122698524Sfenner		    }
122798524Sfenner		} else {
1228111726Sfenner		    print_data(p, min(rdlen, length - (p - data)));
122998524Sfenner		    p += rdlen;
123098524Sfenner		}
123156893Sfenner	    }
123256893Sfenner	}
123356893Sfenner    }
123456893Sfenner
1235111726Sfenner    if (p < maxbuf)
1236146773Ssam	smb_fdata(p, "AdditionalData:\n", maxbuf, 0);
123798524Sfenner
123875115Sfennerout:
123998524Sfenner    printf("\n");
124098524Sfenner    fflush(stdout);
124198524Sfenner    return;
124298524Sfennertrunc:
124398524Sfenner    printf("[|SMB]");
124498524Sfenner    return;
124556893Sfenner}
124656893Sfenner
1247190207Srpaulo/*
1248190207Srpaulo * Print an SMB-over-TCP packet received across tcp on port 445
1249190207Srpaulo */
1250190207Srpaulovoid
1251190207Srpaulosmb_tcp_print (const u_char * data, int length)
1252190207Srpaulo{
1253190207Srpaulo    int caplen;
1254190207Srpaulo    u_int smb_len;
1255190207Srpaulo    const u_char *maxbuf;
125656893Sfenner
1257190207Srpaulo    if (length < 4)
1258190207Srpaulo	goto trunc;
1259190207Srpaulo    if (snapend < data)
1260190207Srpaulo	goto trunc;
1261190207Srpaulo    caplen = snapend - data;
1262190207Srpaulo    if (caplen < 4)
1263190207Srpaulo	goto trunc;
1264190207Srpaulo    maxbuf = data + caplen;
1265190207Srpaulo    smb_len = EXTRACT_24BITS(data + 1);
1266190207Srpaulo    length -= 4;
1267190207Srpaulo    caplen -= 4;
126856893Sfenner
1269190207Srpaulo    startbuf = data;
1270190207Srpaulo    data += 4;
1271190207Srpaulo
1272190207Srpaulo    if (smb_len >= 4 && caplen >= 4 && memcmp(data,"\377SMB",4) == 0) {
1273190207Srpaulo	if ((int)smb_len > caplen) {
1274190207Srpaulo	    if ((int)smb_len > length)
1275190207Srpaulo		printf("WARNING: Packet is continued in later TCP segments\n");
1276190207Srpaulo	    else
1277190207Srpaulo		printf("WARNING: Short packet. Try increasing the snap length by %d\n",
1278190207Srpaulo		    smb_len - caplen);
1279190207Srpaulo	}
1280190207Srpaulo	print_smb(data, maxbuf > data + smb_len ? data + smb_len : maxbuf);
1281190207Srpaulo    } else
1282190207Srpaulo	printf("SMB-over-TCP packet:(raw data or continuation?)\n");
1283190207Srpaulo    return;
1284190207Srpaulotrunc:
1285190207Srpaulo    printf("[|SMB]");
1286190207Srpaulo    return;
1287190207Srpaulo}
1288190207Srpaulo
128956893Sfenner/*
129098524Sfenner * print a NBT packet received across udp on port 138
129198524Sfenner */
129298524Sfennervoid
129398524Sfennernbt_udp138_print(const u_char *data, int length)
129456893Sfenner{
129598524Sfenner    const u_char *maxbuf = data + length;
129656893Sfenner
129798524Sfenner    if (maxbuf > snapend)
129898524Sfenner	maxbuf = snapend;
129998524Sfenner    if (maxbuf <= data)
130098524Sfenner	return;
130198524Sfenner    startbuf = data;
130256893Sfenner
130398524Sfenner    if (vflag < 2) {
130498524Sfenner	printf("NBT UDP PACKET(138)");
130598524Sfenner	return;
130698524Sfenner    }
130798524Sfenner
130898524Sfenner    data = smb_fdata(data,
130998524Sfenner	"\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#",
1310146773Ssam	maxbuf, 0);
131198524Sfenner
131298524Sfenner    if (data != NULL) {
131398524Sfenner	/* If there isn't enough data for "\377SMB", don't check for it. */
131498524Sfenner	if (&data[3] >= maxbuf)
131598524Sfenner	    goto out;
131698524Sfenner
131798524Sfenner	if (memcmp(data, "\377SMB",4) == 0)
131898524Sfenner	    print_smb(data, maxbuf);
131998524Sfenner    }
132098524Sfennerout:
132198524Sfenner    printf("\n");
132298524Sfenner    fflush(stdout);
132356893Sfenner}
132456893Sfenner
132556893Sfenner
132656893Sfenner/*
132798524Sfenner   print netbeui frames
132856893Sfenner*/
1329146773Ssamstruct nbf_strings {
1330146773Ssam	const char	*name;
1331146773Ssam	const char	*nonverbose;
1332146773Ssam	const char	*verbose;
1333146773Ssam} nbf_strings[0x20] = {
1334146773Ssam	{ "Add Group Name Query", ", [P23]Name to add=[n2]#",
1335146773Ssam	  "[P5]ResponseCorrelator=[w]\n[P16]Name to add=[n2]\n" },
1336146773Ssam	{ "Add Name Query", ", [P23]Name to add=[n2]#",
1337146773Ssam	  "[P5]ResponseCorrelator=[w]\n[P16]Name to add=[n2]\n" },
1338146773Ssam	{ "Name In Conflict", NULL, NULL },
1339146773Ssam	{ "Status Query", NULL, NULL },
1340146773Ssam	{ NULL, NULL, NULL },	/* not used */
1341146773Ssam	{ NULL, NULL, NULL },	/* not used */
1342146773Ssam	{ NULL, NULL, NULL },	/* not used */
1343146773Ssam	{ "Terminate Trace", NULL, NULL },
1344146773Ssam	{ "Datagram", NULL,
1345146773Ssam	  "[P7]Destination=[n2]\nSource=[n2]\n" },
1346146773Ssam	{ "Broadcast Datagram", NULL,
1347146773Ssam	  "[P7]Destination=[n2]\nSource=[n2]\n" },
1348146773Ssam	{ "Name Query", ", [P7]Name=[n2]#",
1349146773Ssam	  "[P1]SessionNumber=[B]\nNameType=[B][P2]\nResponseCorrelator=[w]\nName=[n2]\nName of sender=[n2]\n" },
1350146773Ssam	{ NULL, NULL, NULL },	/* not used */
1351146773Ssam	{ NULL, NULL, NULL },	/* not used */
1352146773Ssam	{ "Add Name Response", ", [P1]GroupName=[w] [P4]Destination=[n2] Source=[n2]#",
1353146773Ssam	  "AddNameInProcess=[B]\nGroupName=[w]\nTransmitCorrelator=[w][P2]\nDestination=[n2]\nSource=[n2]\n" },
1354146773Ssam	{ "Name Recognized", NULL,
1355146773Ssam	  "[P1]Data2=[w]\nTransmitCorrelator=[w]\nResponseCorelator=[w]\nDestination=[n2]\nSource=[n2]\n" },
1356146773Ssam	{ "Status Response", NULL, NULL },
1357146773Ssam	{ NULL, NULL, NULL },	/* not used */
1358146773Ssam	{ NULL, NULL, NULL },	/* not used */
1359146773Ssam	{ NULL, NULL, NULL },	/* not used */
1360146773Ssam	{ "Terminate Trace", NULL, NULL },
1361146773Ssam	{ "Data Ack", NULL,
1362146773Ssam	  "[P3]TransmitCorrelator=[w][P2]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" },
1363146773Ssam	{ "Data First/Middle", NULL,
1364146773Ssam	  "Flags=[{RECEIVE_CONTINUE|NO_ACK||PIGGYBACK_ACK_INCLUDED|}]\nResyncIndicator=[w][P2]\nResponseCorelator=[w]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" },
1365146773Ssam	{ "Data Only/Last", NULL,
1366146773Ssam	  "Flags=[{|NO_ACK|PIGGYBACK_ACK_ALLOWED|PIGGYBACK_ACK_INCLUDED|}]\nResyncIndicator=[w][P2]\nResponseCorelator=[w]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" },
1367146773Ssam	{ "Session Confirm", NULL,
1368146773Ssam	  "Data1=[B]\nData2=[w]\nTransmitCorrelator=[w]\nResponseCorelator=[w]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" },
1369146773Ssam	{ "Session End", NULL,
1370146773Ssam	  "[P1]Data2=[w][P4]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" },
1371146773Ssam	{ "Session Initialize", NULL,
1372146773Ssam	  "Data1=[B]\nData2=[w]\nTransmitCorrelator=[w]\nResponseCorelator=[w]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" },
1373146773Ssam	{ "No Receive", NULL,
1374146773Ssam	  "Flags=[{|SEND_NO_ACK}]\nDataBytesAccepted=[b][P4]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" },
1375146773Ssam	{ "Receive Outstanding", NULL,
1376146773Ssam	  "[P1]DataBytesAccepted=[b][P4]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" },
1377146773Ssam	{ "Receive Continue", NULL,
1378146773Ssam	  "[P2]TransmitCorrelator=[w]\n[P2]RemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" },
1379146773Ssam	{ NULL, NULL, NULL },	/* not used */
1380146773Ssam	{ NULL, NULL, NULL },	/* not used */
1381146773Ssam	{ "Session Alive", NULL, NULL }
1382146773Ssam};
1383146773Ssam
138498524Sfennervoid
138598524Sfennernetbeui_print(u_short control, const u_char *data, int length)
138656893Sfenner{
138798524Sfenner    const u_char *maxbuf = data + length;
138898524Sfenner    int len;
138998524Sfenner    int command;
139098524Sfenner    const u_char *data2;
139198524Sfenner    int is_truncated = 0;
139256893Sfenner
139398524Sfenner    if (maxbuf > snapend)
139498524Sfenner	maxbuf = snapend;
139598524Sfenner    TCHECK(data[4]);
139698524Sfenner    len = EXTRACT_LE_16BITS(data);
139798524Sfenner    command = data[4];
139898524Sfenner    data2 = data + len;
139998524Sfenner    if (data2 >= maxbuf) {
140098524Sfenner	data2 = maxbuf;
140198524Sfenner	is_truncated = 1;
140298524Sfenner    }
140375115Sfenner
140498524Sfenner    startbuf = data;
140556893Sfenner
140698524Sfenner    if (vflag < 2) {
1407146773Ssam	printf("NBF Packet: ");
1408146773Ssam	data = smb_fdata(data, "[P5]#", maxbuf, 0);
1409146773Ssam    } else {
1410146773Ssam	printf("\n>>> NBF Packet\nType=0x%X ", control);
1411146773Ssam	data = smb_fdata(data, "Length=[d] Signature=[w] Command=[B]\n#", maxbuf, 0);
141298524Sfenner    }
141398524Sfenner    if (data == NULL)
141498524Sfenner	goto out;
141556893Sfenner
1416146773Ssam    if (command > 0x1f || nbf_strings[command].name == NULL) {
1417146773Ssam	if (vflag < 2)
1418146773Ssam	    data = smb_fdata(data, "Unknown NBF Command#", data2, 0);
1419146773Ssam	else
1420146773Ssam	    data = smb_fdata(data, "Unknown NBF Command\n", data2, 0);
1421146773Ssam    } else {
1422146773Ssam	if (vflag < 2) {
1423146773Ssam	    printf("%s", nbf_strings[command].name);
1424146773Ssam	    if (nbf_strings[command].nonverbose != NULL)
1425146773Ssam		data = smb_fdata(data, nbf_strings[command].nonverbose, data2, 0);
1426146773Ssam	} else {
1427146773Ssam	    printf("%s:\n", nbf_strings[command].name);
1428146773Ssam	    if (nbf_strings[command].verbose != NULL)
1429146773Ssam		data = smb_fdata(data, nbf_strings[command].verbose, data2, 0);
1430146773Ssam	    else
1431146773Ssam		printf("\n");
1432146773Ssam	}
1433146773Ssam    }
143456893Sfenner
1435146773Ssam    if (vflag < 2)
1436146773Ssam	return;
143756893Sfenner
143898524Sfenner    if (data == NULL)
143998524Sfenner	goto out;
144056893Sfenner
144198524Sfenner    if (is_truncated) {
144298524Sfenner	/* data2 was past the end of the buffer */
144398524Sfenner	goto out;
144498524Sfenner    }
144598524Sfenner
1446146773Ssam    /* If this isn't a command that would contain an SMB message, quit. */
1447146773Ssam    if (command != 0x08 && command != 0x09 && command != 0x15 &&
1448146773Ssam        command != 0x16)
1449146773Ssam	goto out;
1450146773Ssam
145198524Sfenner    /* If there isn't enough data for "\377SMB", don't look for it. */
145298524Sfenner    if (&data2[3] >= maxbuf)
145398524Sfenner	goto out;
145498524Sfenner
145598524Sfenner    if (memcmp(data2, "\377SMB",4) == 0)
145698524Sfenner	print_smb(data2, maxbuf);
145798524Sfenner    else {
145898524Sfenner	int i;
145998524Sfenner	for (i = 0; i < 128; i++) {
146098524Sfenner	    if (&data2[i + 3] >= maxbuf)
146198524Sfenner		break;
146298524Sfenner	    if (memcmp(&data2[i], "\377SMB", 4) == 0) {
146398524Sfenner		printf("found SMB packet at %d\n", i);
146498524Sfenner		print_smb(&data2[i], maxbuf);
146598524Sfenner		break;
146698524Sfenner	    }
146798524Sfenner	}
146898524Sfenner    }
146998524Sfenner
147075115Sfennerout:
147198524Sfenner    printf("\n");
147298524Sfenner    return;
147398524Sfennertrunc:
147498524Sfenner    printf("[|SMB]");
147598524Sfenner    return;
147656893Sfenner}
147756893Sfenner
147856893Sfenner
147956893Sfenner/*
148098524Sfenner * print IPX-Netbios frames
148198524Sfenner */
148298524Sfennervoid
148398524Sfenneripx_netbios_print(const u_char *data, u_int length)
148456893Sfenner{
148598524Sfenner    /*
148698524Sfenner     * this is a hack till I work out how to parse the rest of the
148798524Sfenner     * NetBIOS-over-IPX stuff
148898524Sfenner     */
148998524Sfenner    int i;
149098524Sfenner    const u_char *maxbuf;
149198524Sfenner
149298524Sfenner    maxbuf = data + length;
149398524Sfenner    /* Don't go past the end of the captured data in the packet. */
149498524Sfenner    if (maxbuf > snapend)
149598524Sfenner	maxbuf = snapend;
149698524Sfenner    startbuf = data;
149798524Sfenner    for (i = 0; i < 128; i++) {
149898524Sfenner	if (&data[i + 4] > maxbuf)
149998524Sfenner	    break;
150098524Sfenner	if (memcmp(&data[i], "\377SMB", 4) == 0) {
1501146773Ssam	    smb_fdata(data, "\n>>> IPX transport ", &data[i], 0);
1502190207Srpaulo	    print_smb(&data[i], maxbuf);
150398524Sfenner	    printf("\n");
150498524Sfenner	    fflush(stdout);
150598524Sfenner	    break;
150698524Sfenner	}
150756893Sfenner    }
150898524Sfenner    if (i == 128)
1509146773Ssam	smb_fdata(data, "\n>>> Unknown IPX ", maxbuf, 0);
151056893Sfenner}
1511