summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/tcpdump/Makefile4
-rw-r--r--usr.sbin/tcpdump/interface.h11
-rw-r--r--usr.sbin/tcpdump/print-llc.c50
-rw-r--r--usr.sbin/tcpdump/print-smb.c1047
-rw-r--r--usr.sbin/tcpdump/print-tcp.c14
-rw-r--r--usr.sbin/tcpdump/print-udp.c8
-rw-r--r--usr.sbin/tcpdump/smb.h154
-rw-r--r--usr.sbin/tcpdump/smbutil.c759
8 files changed, 2034 insertions, 13 deletions
diff --git a/usr.sbin/tcpdump/Makefile b/usr.sbin/tcpdump/Makefile
index 63689daf937..52e4c803887 100644
--- a/usr.sbin/tcpdump/Makefile
+++ b/usr.sbin/tcpdump/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.24 2000/12/07 21:52:38 mickey Exp $
+# $OpenBSD: Makefile,v 1.25 2000/12/07 22:36:45 mickey Exp $
#
# Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
# The Regents of the University of California. All rights reserved.
@@ -38,7 +38,7 @@ SRCS= tcpdump.c addrtoname.c \
print-atalk.c print-domain.c print-tftp.c print-bootp.c print-nfs.c \
print-icmp.c print-sl.c print-ppp.c print-rip.c \
print-snmp.c print-ntp.c print-null.c print-egp.c print-ospf.c \
- print-fddi.c print-llc.c print-sunrpc.c \
+ print-fddi.c print-llc.c print-smb.c smbutil.c print-sunrpc.c \
print-vrrp.c print-wb.c print-decnet.c print-isoclns.c print-ipx.c \
print-atm.c print-dvmrp.c print-krb.c print-pim.c print-netbios.c \
util.c bpf_dump.c parsenfsfh.c version.c machdep.c print-igrp.c \
diff --git a/usr.sbin/tcpdump/interface.h b/usr.sbin/tcpdump/interface.h
index 2e31910fa20..56e9e2fabc7 100644
--- a/usr.sbin/tcpdump/interface.h
+++ b/usr.sbin/tcpdump/interface.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: interface.h,v 1.19 2000/12/07 21:52:38 mickey Exp $ */
+/* $OpenBSD: interface.h,v 1.20 2000/12/07 22:36:45 mickey Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
@@ -20,7 +20,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/interface.h,v 1.19 2000/12/07 21:52:38 mickey Exp $ (LBL)
+ * @(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/interface.h,v 1.20 2000/12/07 22:36:45 mickey Exp $ (LBL)
*/
#ifndef tcpdump_interface_h
@@ -198,6 +198,13 @@ extern void ipx_print(const u_char *, u_int);
extern void isoclns_print(const u_char *, u_int, u_int, const u_char *,
const u_char *);
extern void krb_print(const u_char *, u_int);
+extern void netbeui_print(u_short, const u_char *, const u_char *);
+extern void ipx_netbios_print(const u_char *, const u_char *);
+extern void nbt_tcp_print(const u_char *, int);
+extern void nbt_udp137_print(const u_char *data, int);
+extern void nbt_udp138_print(const u_char *data, int);
+extern char *smb_errstr(int, int);
+extern void print_data(const unsigned char *, int);
extern void l2tp_print(const u_char *dat, u_int length);
extern void vrrp_print(const u_char *bp, u_int len, int ttl);
extern void nfsreply_print(const u_char *, u_int, const u_char *);
diff --git a/usr.sbin/tcpdump/print-llc.c b/usr.sbin/tcpdump/print-llc.c
index 7352d61363f..ebea850705b 100644
--- a/usr.sbin/tcpdump/print-llc.c
+++ b/usr.sbin/tcpdump/print-llc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: print-llc.c,v 1.10 2000/10/19 16:31:42 jason Exp $ */
+/* $OpenBSD: print-llc.c,v 1.11 2000/12/07 22:36:45 mickey Exp $ */
/*
* Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997
@@ -26,7 +26,7 @@
#ifndef lint
static const char rcsid[] =
- "@(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/print-llc.c,v 1.10 2000/10/19 16:31:42 jason Exp $";
+ "@(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/print-llc.c,v 1.11 2000/12/07 22:36:45 mickey Exp $";
#endif
#include <sys/param.h>
@@ -68,6 +68,7 @@ llc_print(const u_char *p, u_int length, u_int caplen,
{
struct llc llc;
register u_short et;
+ u_short control;
register int ret;
if (caplen < 3) {
@@ -136,6 +137,42 @@ llc_print(const u_char *p, u_int length, u_int caplen,
return (1);
}
+ if (llc.ssap == 0xf0 && llc.dsap == 0xf0) {
+ /*
+ * we don't actually have a full netbeui parser yet, but the
+ * smb parser can handle many smb-in-netbeui packets, which
+ * is very useful, so we call that
+ */
+
+ /*
+ * Skip the DSAP and LSAP.
+ */
+ p += 2;
+ length -= 2;
+ caplen -= 2;
+
+ /*
+ * OK, what type of LLC frame is this? The length
+ * of the control field depends on that - S or I
+ * frames have a two-byte control field, and U frames
+ * have a one-byte control field.
+ */
+ if ((llc.llcu & LLC_U_FMT) == LLC_U_FMT) {
+ control = llc.llcu;
+ p += 1;
+ length -= 1;
+ caplen -= 1;
+ } else {
+ control = llc.llcis;
+ p += 2;
+ length -= 2;
+ caplen -= 2;
+ }
+
+ netbeui_print(control, p, p + min(caplen, length));
+ return (1);
+ }
+
if ((llc.ssap & ~LLC_GSAP) == llc.dsap) {
if (eflag)
(void)printf("%s ", llcsap_string(llc.dsap));
@@ -187,6 +224,15 @@ llc_print(const u_char *p, u_int length, u_int caplen,
caplen -= 3;
}
}
+
+ if (!strcmp(m,"ui") && f=='C') {
+ /*
+ * we don't have a proper ipx decoder yet, but there
+ * is a partial one in the smb code
+ */
+ ipx_netbios_print(p,p+min(caplen,length));
+ }
+
} else {
char f;
llc.llcis = ntohs(llc.llcis);
diff --git a/usr.sbin/tcpdump/print-smb.c b/usr.sbin/tcpdump/print-smb.c
new file mode 100644
index 00000000000..be4e611ca16
--- /dev/null
+++ b/usr.sbin/tcpdump/print-smb.c
@@ -0,0 +1,1047 @@
+/* $OpenBSD: print-smb.c,v 1.1 2000/12/07 22:36:46 mickey Exp $ */
+
+/*
+ Copyright (C) Andrew Tridgell 1995-1999
+
+ This software may be distributed either under the terms of the
+ BSD-style license that accompanies tcpdump or the GNU GPL version 2
+ or later */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef lint
+static const char rcsid[] =
+ "@(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/print-smb.c,v 1.1 2000/12/07 22:36:46 mickey Exp $";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "interface.h"
+#include "smb.h"
+
+static int request=0;
+
+const uchar *startbuf=NULL;
+
+struct smbdescript
+{
+ char *req_f1;
+ char *req_f2;
+ char *rep_f1;
+ char *rep_f2;
+ void (*fn)(); /* sometimes (u_char *, u_char *, u_char *, u_char *)
+ and sometimes (u_char *, u_char *, int, int) */
+};
+
+struct smbfns
+{
+ int id;
+ char *name;
+ int flags;
+ struct smbdescript descript;
+};
+
+#define DEFDESCRIPT {NULL,NULL,NULL,NULL,NULL}
+
+#define FLG_CHAIN (1<<0)
+
+static struct smbfns *smbfind(int id,struct smbfns *list)
+{
+ int sindex;
+
+ for (sindex=0;list[sindex].name;sindex++)
+ if (list[sindex].id == id) return(&list[sindex]);
+
+ return(&list[0]);
+}
+
+static void trans2_findfirst(uchar *param,uchar *data,int pcnt,int dcnt)
+{
+ char *fmt;
+
+ if (request) {
+ fmt = "Attribute=[A]\nSearchCount=[d]\nFlags=[w]\nLevel=[dP5]\nFile=[S]\n";
+ } else {
+ fmt = "Handle=[w]\nCount=[d]\nEOS=[w]\nEoffset=[d]\nLastNameOfs=[w]\n";
+ }
+
+ fdata(param,fmt,param+pcnt);
+ if (dcnt) {
+ printf("data:\n");
+ print_data(data,dcnt);
+ }
+}
+
+static void trans2_qfsinfo(uchar *param,uchar *data,int pcnt,int dcnt)
+{
+ static int level=0;
+ char *fmt="";
+
+ if (request) {
+ level = SVAL(param,0);
+ fmt = "InfoLevel=[d]\n";
+ fdata(param,fmt,param+pcnt);
+ } else {
+ switch (level) {
+ case 1:
+ fmt = "idFileSystem=[W]\nSectorUnit=[D]\nUnit=[D]\nAvail=[D]\nSectorSize=[d]\n";
+ break;
+ case 2:
+ fmt = "CreationTime=[T2]VolNameLength=[B]\nVolumeLabel=[s12]\n";
+ break;
+ case 0x105:
+ fmt = "Capabilities=[W]\nMaxFileLen=[D]\nVolNameLen=[D]\nVolume=[S]\n";
+ break;
+ default:
+ fmt = "UnknownLevel\n";
+ }
+ fdata(data,fmt,data+dcnt);
+ }
+ if (dcnt) {
+ printf("data:\n");
+ print_data(data,dcnt);
+ }
+}
+
+struct smbfns trans2_fns[] = {
+{0,"TRANSACT2_OPEN",0,
+ {"Flags2=[w]\nMode=[w]\nSearchAttrib=[A]\nAttrib=[A]\nTime=[T2]\nOFun=[w]\nSize=[D]\nRes=([w,w,w,w,w])\nPath=[S]",NULL,
+ "Handle=[d]\nAttrib=[A]\nTime=[T2]\nSize=[D]\nAccess=[w]\nType=[w]\nState=[w]\nAction=[w]\nInode=[W]\nOffErr=[d]\n|EALength=[d]\n",NULL,NULL}},
+
+{1,"TRANSACT2_FINDFIRST",0,
+ {NULL,NULL,NULL,NULL,trans2_findfirst}},
+
+{2,"TRANSACT2_FINDNEXT",0,DEFDESCRIPT},
+
+{3,"TRANSACT2_QFSINFO",0,
+ {NULL,NULL,NULL,NULL,trans2_qfsinfo}},
+
+{4,"TRANSACT2_SETFSINFO",0,DEFDESCRIPT},
+{5,"TRANSACT2_QPATHINFO",0,DEFDESCRIPT},
+{6,"TRANSACT2_SETPATHINFO",0,DEFDESCRIPT},
+{7,"TRANSACT2_QFILEINFO",0,DEFDESCRIPT},
+{8,"TRANSACT2_SETFILEINFO",0,DEFDESCRIPT},
+{9,"TRANSACT2_FSCTL",0,DEFDESCRIPT},
+{10,"TRANSACT2_IOCTL",0,DEFDESCRIPT},
+{11,"TRANSACT2_FINDNOTIFYFIRST",0,DEFDESCRIPT},
+{12,"TRANSACT2_FINDNOTIFYNEXT",0,DEFDESCRIPT},
+{13,"TRANSACT2_MKDIR",0,DEFDESCRIPT},
+{-1,NULL,0,DEFDESCRIPT}};
+
+
+static void print_trans2(uchar *words,uchar *dat,uchar *buf,uchar *maxbuf)
+{
+ static struct smbfns *fn = &trans2_fns[0];
+ uchar *data,*param;
+ uchar *f1=NULL,*f2=NULL;
+ int pcnt,dcnt;
+
+ if (request) {
+ fn = smbfind(SVAL(words+1,14*2),trans2_fns);
+ data = buf+SVAL(words+1,12*2);
+ param = buf+SVAL(words+1,10*2);
+ pcnt = SVAL(words+1,9*2);
+ dcnt = SVAL(words+1,11*2);
+ } else {
+ data = buf+SVAL(words+1,7*2);
+ param = buf+SVAL(words+1,4*2);
+ pcnt = SVAL(words+1,3*2);
+ dcnt = SVAL(words+1,6*2);
+ }
+
+ printf("%s param_length=%d data_length=%d\n",
+ fn->name,pcnt,dcnt);
+
+ if (request) {
+ if (CVAL(words,0) == 8) {
+ fdata(words+1,"Trans2Secondary\nTotParam=[d]\nTotData=[d]\nParamCnt=[d]\nParamOff=[d]\nParamDisp=[d]\nDataCnt=[d]\nDataOff=[d]\nDataDisp=[d]\nHandle=[d]\n",maxbuf);
+ return;
+ } else {
+ fdata(words+1,"TotParam=[d]\nTotData=[d]\nMaxParam=[d]\nMaxData=[d]\nMaxSetup=[d]\nFlags=[w]\nTimeOut=[D]\nRes1=[w]\nParamCnt=[d]\nParamOff=[d]\nDataCnt=[d]\nDataOff=[d]\nSetupCnt=[d]\n",words+1+14*2);
+ fdata(data+1,"TransactionName=[S]\n%",maxbuf);
+ }
+ f1 = fn->descript.req_f1;
+ f2 = fn->descript.req_f2;
+ } else {
+ if (CVAL(words,0) == 0) {
+ printf("Trans2Interim\n");
+ return;
+ } else {
+ fdata(words+1,"TotParam=[d]\nTotData=[d]\nRes1=[w]\nParamCnt=[d]\nParamOff=[d]\nParamDisp[d]\nDataCnt=[d]\nDataOff=[d]\nDataDisp=[d]\nSetupCnt=[d]\n",words+1+10*2);
+ }
+ f1 = fn->descript.rep_f1;
+ f2 = fn->descript.rep_f2;
+ }
+
+ if (fn->descript.fn) {
+ fn->descript.fn(param,data,pcnt,dcnt);
+ } else {
+ fdata(param,f1?f1:(uchar*)"Paramaters=\n",param+pcnt);
+ fdata(data,f2?f2:(uchar*)"Data=\n",data+dcnt);
+ }
+}
+
+
+static void print_browse(uchar *param,int paramlen,const uchar *data,int datalen)
+{
+ const uchar *maxbuf = data + datalen;
+ int command = CVAL(data,0);
+
+ fdata(param,"BROWSE PACKET\n|Param ",param+paramlen);
+
+ switch (command) {
+ case 0xF:
+ data = fdata(data,"BROWSE PACKET:\nType=[B] (LocalMasterAnnouncement)\nUpdateCount=[w]\nRes1=[B]\nAnnounceInterval=[d]\nName=[n2]\nMajorVersion=[B]\nMinorVersion=[B]\nServerType=[W]\nElectionVersion=[w]\nBrowserConstant=[w]\n",maxbuf);
+ break;
+
+ case 0x1:
+ data = fdata(data,"BROWSE PACKET:\nType=[B] (HostAnnouncement)\nUpdateCount=[w]\nRes1=[B]\nAnnounceInterval=[d]\nName=[n2]\nMajorVersion=[B]\nMinorVersion=[B]\nServerType=[W]\nElectionVersion=[w]\nBrowserConstant=[w]\n",maxbuf);
+ break;
+
+ case 0x2:
+ data = fdata(data,"BROWSE PACKET:\nType=[B] (AnnouncementRequest)\nFlags=[B]\nReplySystemName=[S]\n",maxbuf);
+ break;
+
+ case 0xc:
+ data = fdata(data,"BROWSE PACKET:\nType=[B] (WorkgroupAnnouncement)\nUpdateCount=[w]\nRes1=[B]\nAnnounceInterval=[d]\nName=[n2]\nMajorVersion=[B]\nMinorVersion=[B]\nServerType=[W]\nCommentPointer=[W]\nServerName=[S]\n",maxbuf);
+ break;
+
+ case 0x8:
+ data = fdata(data,"BROWSE PACKET:\nType=[B] (ElectionFrame)\nElectionVersion=[B]\nOSSummary=[W]\nUptime=[(W,W)]\nServerName=[S]\n",maxbuf);
+ break;
+
+ case 0xb:
+ data = fdata(data,"BROWSE PACKET:\nType=[B] (BecomeBackupBrowser)\nName=[S]\n",maxbuf);
+ break;
+
+ case 0x9:
+ data = fdata(data,"BROWSE PACKET:\nType=[B] (GetBackupList)\nListCount?=[B]\nToken?=[B]\n",maxbuf);
+ break;
+
+ case 0xa:
+ data = fdata(data,"BROWSE PACKET:\nType=[B] (BackupListResponse)\nServerCount?=[B]\nToken?=[B]*Name=[S]\n",maxbuf);
+ break;
+
+ case 0xd:
+ data = fdata(data,"BROWSE PACKET:\nType=[B] (MasterAnnouncement)\nMasterName=[S]\n",maxbuf);
+ break;
+
+ case 0xe:
+ data = fdata(data,"BROWSE PACKET:\nType=[B] (ResetBrowser)\nOptions=[B]\n",maxbuf);
+ break;
+
+ default:
+ data = fdata(data,"Unknown Browser Frame ",maxbuf);
+ break;
+ }
+}
+
+
+static void print_ipc(uchar *param,int paramlen,uchar *data,int datalen)
+{
+ if (paramlen)
+ fdata(param,"Command=[w]\nStr1=[S]\nStr2=[S]\n",param+paramlen);
+ if (datalen)
+ fdata(data,"IPC ",data+datalen);
+}
+
+
+static void print_trans(uchar *words,uchar *data1,uchar *buf,uchar *maxbuf)
+{
+ uchar *f1,*f2,*f3,*f4;
+ uchar *data,*param;
+ int datalen,paramlen;
+
+ if (request) {
+ paramlen = SVAL(words+1,9*2);
+ param = buf + SVAL(words+1,10*2);
+ datalen = SVAL(words+1,11*2);
+ data = buf + SVAL(words+1,12*2);
+ 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";
+ f2 = "|Name=[S]\n";
+ f3 = "|Param ";
+ f4 = "|Data ";
+ } else {
+ paramlen = SVAL(words+1,3*2);
+ param = buf + SVAL(words+1,4*2);
+ datalen = SVAL(words+1,6*2);
+ data = buf + SVAL(words+1,7*2);
+ f1 = "TotParamCnt=[d] \nTotDataCnt=[d] \nRes1=[d]\nParamCnt=[d] \nParamOff=[d] \nRes2=[d] \nDataCnt=[d] \nDataOff=[d] \nRes3=[d]\nLsetup=[d]\n";
+ f2 = "|Unknown ";
+ f3 = "|Param ";
+ f4 = "|Data ";
+ }
+
+ fdata(words+1,f1,MIN(words+1+2*CVAL(words,0),maxbuf));
+ fdata(data1+2,f2,maxbuf - (paramlen + datalen));
+
+ if (!strcmp(data1+2,"\\MAILSLOT\\BROWSE")) {
+ print_browse(param,paramlen,data,datalen);
+ return;
+ }
+
+ if (!strcmp(data1+2,"\\PIPE\\LANMAN")) {
+ print_ipc(param,paramlen,data,datalen);
+ return;
+ }
+
+ if (paramlen) fdata(param,f3,MIN(param+paramlen,maxbuf));
+ if (datalen) fdata(data,f4,MIN(data+datalen,maxbuf));
+}
+
+
+
+static void print_negprot(uchar *words,uchar *data,uchar *buf,uchar *maxbuf)
+{
+ uchar *f1=NULL,*f2=NULL;
+
+ if (request) {
+ f2 = "*|Dialect=[Z]\n";
+ } else {
+ if (CVAL(words,0) == 1) {
+ f1 = "Core Protocol\nDialectIndex=[d]";
+ } else if (CVAL(words,0) == 17) {
+ f1 = "NT1 Protocol\nDialectIndex=[d]\nSecMode=[B]\nMaxMux=[d]\nNumVcs=[d]\nMaxBuffer=[D]\nRawSize=[D]\nSessionKey=[W]\nCapabilities=[W]\nServerTime=[T3]TimeZone=[d]\nCryptKey=";
+ } else if (CVAL(words,0) == 13) {
+ 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=";
+ }
+ }
+
+ if (f1)
+ fdata(words+1,f1,MIN(words + 1 + CVAL(words,0)*2,maxbuf));
+ else
+ print_data(words+1,MIN(CVAL(words,0)*2,PTR_DIFF(maxbuf,words+1)));
+
+ if (f2)
+ fdata(data+2,f2,MIN(data + 2 + SVAL(data,0),maxbuf));
+ else
+ print_data(data+2,MIN(SVAL(data,0),PTR_DIFF(maxbuf,data+2)));
+
+}
+
+static void print_sesssetup(uchar *words,uchar *data,uchar *buf,uchar *maxbuf)
+{
+ int wcnt = CVAL(words,0);
+ uchar *f1=NULL,*f2=NULL;
+
+ if (request) {
+ if (wcnt==10) {
+ f1 = "Com2=[w]\nOff2=[d]\nBufSize=[d]\nMpxMax=[d]\nVcNum=[d]\nSessionKey=[W]\nPassLen=[d]\nCryptLen=[d]\nCryptOff=[d]\nPass&Name=\n";
+ } else {
+ 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";
+ }
+ } else {
+ if (CVAL(words,0) == 3) {
+ f1 = "Com2=[w]\nOff2=[d]\nAction=[w]\n";
+ } else if (CVAL(words,0) == 13) {
+ f1 = "Com2=[B]\nRes=[B]\nOff2=[d]\nAction=[w]\n";
+ f2 = "NativeOS=[S]\nNativeLanMan=[S]\nPrimaryDomain=[S]\n";
+ }
+ }
+
+ if (f1)
+ fdata(words+1,f1,MIN(words + 1 + CVAL(words,0)*2,maxbuf));
+ else
+ print_data(words+1,MIN(CVAL(words,0)*2,PTR_DIFF(maxbuf,words+1)));
+
+ if (f2)
+ fdata(data+2,f2,MIN(data + 2 + SVAL(data,0),maxbuf));
+ else
+ print_data(data+2,MIN(SVAL(data,0),PTR_DIFF(maxbuf,data+2)));
+}
+
+
+static struct smbfns smb_fns[] =
+{
+{-1,"SMBunknown",0,DEFDESCRIPT},
+
+{SMBtcon,"SMBtcon",0,
+ {NULL,"Path=[Z]\nPassword=[Z]\nDevice=[Z]\n",
+ "MaxXmit=[d]\nTreeId=[d]\n",NULL,
+ NULL}},
+
+
+{SMBtdis,"SMBtdis",0,DEFDESCRIPT},
+{SMBexit,"SMBexit",0,DEFDESCRIPT},
+{SMBioctl,"SMBioctl",0,DEFDESCRIPT},
+
+{SMBecho,"SMBecho",0,
+ {"ReverbCount=[d]\n",NULL,
+ "SequenceNum=[d]\n",NULL,
+ NULL}},
+
+{SMBulogoffX, "SMBulogoffX",FLG_CHAIN,DEFDESCRIPT},
+
+{SMBgetatr,"SMBgetatr",0,
+ {NULL,"Path=[Z]\n",
+ "Attribute=[A]\nTime=[T2]Size=[D]\nRes=([w,w,w,w,w])\n",NULL,
+ NULL}},
+
+{SMBsetatr,"SMBsetatr",0,
+ {"Attribute=[A]\nTime=[T2]Res=([w,w,w,w,w])\n","Path=[Z]\n",
+ NULL,NULL,NULL}},
+
+{SMBchkpth,"SMBchkpth",0,
+ {NULL,"Path=[Z]\n",NULL,NULL,NULL}},
+
+{SMBsearch,"SMBsearch",0,
+{"Count=[d]\nAttrib=[A]\n","Path=[Z]\nBlkType=[B]\nBlkLen=[d]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\nRes2=[W]\n",
+"Count=[d]\n","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",NULL}},
+
+
+{SMBopen,"SMBopen",0,
+ {"Mode=[w]\nAttribute=[A]\n","Path=[Z]\n",
+ "Handle=[d]\nOAttrib=[A]\nTime=[T2]Size=[D]\nAccess=[w]\n",NULL,
+ NULL}},
+
+{SMBcreate,"SMBcreate",0,
+ {"Attrib=[A]\nTime=[T2]","Path=[Z]\n",
+ "Handle=[d]\n",NULL,
+ NULL}},
+
+{SMBmknew,"SMBmknew",0,
+ {"Attrib=[A]\nTime=[T2]","Path=[Z]\n",
+ "Handle=[d]\n",NULL,
+ NULL}},
+
+{SMBunlink,"SMBunlink",0,
+ {"Attrib=[A]\n","Path=[Z]\n",NULL,NULL,NULL}},
+
+{SMBread,"SMBread",0,
+ {"Handle=[d]\nByteCount=[d]\nOffset=[D]\nCountLeft=[d]\n",NULL,
+ "Count=[d]\nRes=([w,w,w,w])\n",NULL,NULL}},
+
+{SMBwrite,"SMBwrite",0,
+ {"Handle=[d]\nByteCount=[d]\nOffset=[D]\nCountLeft=[d]\n",NULL,
+ "Count=[d]\n",NULL,NULL}},
+
+{SMBclose,"SMBclose",0,
+ {"Handle=[d]\nTime=[T2]",NULL,NULL,NULL,NULL}},
+
+{SMBmkdir,"SMBmkdir",0,
+ {NULL,"Path=[Z]\n",NULL,NULL,NULL}},
+
+{SMBrmdir,"SMBrmdir",0,
+ {NULL,"Path=[Z]\n",NULL,NULL,NULL}},
+
+{SMBdskattr,"SMBdskattr",0,
+{NULL,NULL,
+"TotalUnits=[d]\nBlocksPerUnit=[d]\nBlockSize=[d]\nFreeUnits=[d]\nMedia=[w]\n",
+NULL,NULL}},
+
+{SMBmv,"SMBmv",0,
+ {"Attrib=[A]\n","OldPath=[Z]\nNewPath=[Z]\n",NULL,NULL,NULL}},
+
+/* this is a Pathworks specific call, allowing the
+ changing of the root path */
+{pSETDIR,"SMBsetdir",0,
+ {NULL,"Path=[Z]\n",NULL,NULL,NULL}},
+
+{SMBlseek,"SMBlseek",0,
+ {"Handle=[d]\nMode=[w]\nOffset=[D]\n","Offset=[D]\n",NULL,NULL}},
+
+{SMBflush,"SMBflush",0,
+ {"Handle=[d]\n",NULL,NULL,NULL,NULL}},
+
+{SMBsplopen,"SMBsplopen",0,
+ {"SetupLen=[d]\nMode=[w]\n","Ident=[Z]\n","Handle=[d]\n",NULL,NULL}},
+
+{SMBsplclose,"SMBsplclose",0,
+ {"Handle=[d]\n",NULL,NULL,NULL,NULL}},
+
+{SMBsplretq,"SMBsplretq",0,
+ {"MaxCount=[d]\nStartIndex=[d]\n",NULL,
+ "Count=[d]\nIndex=[d]\n",
+ "*Time=[T2]Status=[B]\nJobID=[d]\nSize=[D]\nRes=[B]Name=[s16]\n",
+ NULL}},
+
+{SMBsplwr,"SMBsplwr",0,
+ {"Handle=[d]\n",NULL,NULL,NULL,NULL}},
+
+{SMBlock,"SMBlock",0,
+ {"Handle=[d]\nCount=[D]\nOffset=[D]\n",NULL,NULL,NULL,NULL}},
+
+{SMBunlock,"SMBunlock",0,
+ {"Handle=[d]\nCount=[D]\nOffset=[D]\n",NULL,NULL,NULL,NULL}},
+
+/* CORE+ PROTOCOL FOLLOWS */
+
+{SMBreadbraw,"SMBreadbraw",0,
+{"Handle=[d]\nOffset=[D]\nMaxCount=[d]\nMinCount=[d]\nTimeOut=[D]\nRes=[d]\n",
+ NULL,NULL,NULL,NULL}},
+
+{SMBwritebraw,"SMBwritebraw",0,
+{"Handle=[d]\nTotalCount=[d]\nRes=[w]\nOffset=[D]\nTimeOut=[D]\nWMode=[w]\nRes2=[W]\n|DataSize=[d]\nDataOff=[d]\n",
+NULL,"WriteRawAck",NULL,NULL}},
+
+{SMBwritec,"SMBwritec",0,
+ {NULL,NULL,"Count=[d]\n",NULL,NULL}},
+
+{SMBwriteclose,"SMBwriteclose",0,
+ {"Handle=[d]\nCount=[d]\nOffset=[D]\nTime=[T2]Res=([w,w,w,w,w,w])",NULL,
+ "Count=[d]\n",NULL,NULL}},
+
+{SMBlockread,"SMBlockread",0,
+ {"Handle=[d]\nByteCount=[d]\nOffset=[D]\nCountLeft=[d]\n",NULL,
+ "Count=[d]\nRes=([w,w,w,w])\n",NULL,NULL}},
+
+{SMBwriteunlock,"SMBwriteunlock",0,
+ {"Handle=[d]\nByteCount=[d]\nOffset=[D]\nCountLeft=[d]\n",NULL,
+ "Count=[d]\n",NULL,NULL}},
+
+{SMBreadBmpx,"SMBreadBmpx",0,
+{"Handle=[d]\nOffset=[D]\nMaxCount=[d]\nMinCount=[d]\nTimeOut=[D]\nRes=[w]\n",
+NULL,
+"Offset=[D]\nTotCount=[d]\nRemaining=[d]\nRes=([w,w])\nDataSize=[d]\nDataOff=[d]\n",
+NULL,NULL}},
+
+{SMBwriteBmpx,"SMBwriteBmpx",0,
+{"Handle=[d]\nTotCount=[d]\nRes=[w]\nOffset=[D]\nTimeOut=[D]\nWMode=[w]\nRes2=[W]\nDataSize=[d]\nDataOff=[d]\n",NULL,
+"Remaining=[d]\n",NULL,NULL}},
+
+{SMBwriteBs,"SMBwriteBs",0,
+ {"Handle=[d]\nTotCount=[d]\nOffset=[D]\nRes=[W]\nDataSize=[d]\nDataOff=[d]\n",NULL,
+ "Count=[d]\n",NULL,NULL}},
+
+{SMBsetattrE,"SMBsetattrE",0,
+ {"Handle=[d]\nCreationTime=[T2]AccessTime=[T2]ModifyTime=[T2]",NULL,
+ NULL,NULL,NULL}},
+
+{SMBgetattrE,"SMBgetattrE",0,
+{"Handle=[d]\n",NULL,
+ "CreationTime=[T2]AccessTime=[T2]ModifyTime=[T2]Size=[D]\nAllocSize=[D]\nAttribute=[A]\n",NULL,NULL}},
+
+{SMBtranss,"SMBtranss",0,DEFDESCRIPT},
+{SMBioctls,"SMBioctls",0,DEFDESCRIPT},
+
+{SMBcopy,"SMBcopy",0,
+ {"TreeID2=[d]\nOFun=[w]\nFlags=[w]\n","Path=[S]\nNewPath=[S]\n",
+ "CopyCount=[d]\n","|ErrStr=[S]\n",NULL}},
+
+{SMBmove,"SMBmove",0,
+ {"TreeID2=[d]\nOFun=[w]\nFlags=[w]\n","Path=[S]\nNewPath=[S]\n",
+ "MoveCount=[d]\n","|ErrStr=[S]\n",NULL}},
+
+{SMBopenX,"SMBopenX",FLG_CHAIN,
+{"Com2=[w]\nOff2=[d]\nFlags=[w]\nMode=[w]\nSearchAttrib=[A]\nAttrib=[A]\nTime=[T2]OFun=[w]\nSize=[D]\nTimeOut=[D]\nRes=[W]\n","Path=[S]\n",
+"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",NULL,NULL}},
+
+{SMBreadX,"SMBreadX",FLG_CHAIN,
+{"Com2=[w]\nOff2=[d]\nHandle=[d]\nOffset=[D]\nMaxCount=[d]\nMinCount=[d]\nTimeOut=[D]\nCountLeft=[d]\n",NULL,
+"Com2=[w]\nOff2=[d]\nRemaining=[d]\nRes=[W]\nDataSize=[d]\nDataOff=[d]\nRes=([w,w,w,w])\n",NULL,NULL}},
+
+{SMBwriteX,"SMBwriteX",FLG_CHAIN,
+{"Com2=[w]\nOff2=[d]\nHandle=[d]\nOffset=[D]\nTimeOut=[D]\nWMode=[w]\nCountLeft=[d]\nRes=[w]\nDataSize=[d]\nDataOff=[d]\n",NULL,
+"Com2=[w]\nOff2=[d]\nCount=[d]\nRemaining=[d]\nRes=[W]\n",NULL,NULL}},
+
+{SMBlockingX,"SMBlockingX",FLG_CHAIN,
+{"Com2=[w]\nOff2=[d]\nHandle=[d]\nLockType=[w]\nTimeOut=[D]\nUnlockCount=[d]\nLockCount=[d]\n",
+"*Process=[d]\nOffset=[D]\nLength=[D]\n",
+"Com2=[w]\nOff2=[d]\n"}},
+
+{SMBffirst,"SMBffirst",0,
+{"Count=[d]\nAttrib=[A]\n","Path=[Z]\nBlkType=[B]\nBlkLen=[d]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\n",
+"Count=[d]\n","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",NULL}},
+
+{SMBfunique,"SMBfunique",0,
+{"Count=[d]\nAttrib=[A]\n","Path=[Z]\nBlkType=[B]\nBlkLen=[d]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\n",
+"Count=[d]\n","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",NULL}},
+
+{SMBfclose,"SMBfclose",0,
+{"Count=[d]\nAttrib=[A]\n","Path=[Z]\nBlkType=[B]\nBlkLen=[d]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\n",
+"Count=[d]\n","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",NULL}},
+
+{SMBfindnclose, "SMBfindnclose", 0,
+ {"Handle=[d]\n",NULL,NULL,NULL,NULL}},
+
+{SMBfindclose, "SMBfindclose", 0,
+ {"Handle=[d]\n",NULL,NULL,NULL,NULL}},
+
+{SMBsends,"SMBsends",0,
+ {NULL,"Source=[Z]\nDest=[Z]\n",NULL,NULL,NULL}},
+
+{SMBsendstrt,"SMBsendstrt",0,
+ {NULL,"Source=[Z]\nDest=[Z]\n","GroupID=[d]\n",NULL,NULL}},
+
+{SMBsendend,"SMBsendend",0,
+ {"GroupID=[d]\n",NULL,NULL,NULL,NULL}},
+
+{SMBsendtxt,"SMBsendtxt",0,
+ {"GroupID=[d]\n",NULL,NULL,NULL,NULL}},
+
+{SMBsendb,"SMBsendb",0,
+ {NULL,"Source=[Z]\nDest=[Z]\n",NULL,NULL,NULL}},
+
+{SMBfwdname,"SMBfwdname",0,DEFDESCRIPT},
+{SMBcancelf,"SMBcancelf",0,DEFDESCRIPT},
+{SMBgetmac,"SMBgetmac",0,DEFDESCRIPT},
+
+{SMBnegprot,"SMBnegprot",0,
+ {NULL,NULL,NULL,NULL,print_negprot}},
+
+{SMBsesssetupX,"SMBsesssetupX",FLG_CHAIN,
+ {NULL,NULL,NULL,NULL,print_sesssetup}},
+
+{SMBtconX,"SMBtconX",FLG_CHAIN,
+{"Com2=[w]\nOff2=[d]\nFlags=[w]\nPassLen=[d]\nPasswd&Path&Device=\n",NULL,
+ "Com2=[w]\nOff2=[d]\n","ServiceType=[S]\n",NULL}},
+
+{SMBtrans2, "SMBtrans2",0,{NULL,NULL,NULL,NULL,print_trans2}},
+
+{SMBtranss2, "SMBtranss2", 0,DEFDESCRIPT},
+{SMBctemp,"SMBctemp",0,DEFDESCRIPT},
+{SMBreadBs,"SMBreadBs",0,DEFDESCRIPT},
+{SMBtrans,"SMBtrans",0,{NULL,NULL,NULL,NULL,print_trans}},
+
+{SMBnttrans,"SMBnttrans", 0, DEFDESCRIPT},
+{SMBnttranss,"SMBnttranss", 0, DEFDESCRIPT},
+
+{SMBntcreateX,"SMBntcreateX", FLG_CHAIN,
+{"Com2=[w]\nOff2=[d]\nRes=[b]\nNameLen=[d]\nFlags=[W]\nRootDirectoryFid=[D]\nAccessMask=[W]\nAllocationSize=[L]\nExtFileAttributes=[W]\nShareAccess=[W]\nCreateDisposition=[W]\nCreateOptions=[W]\nImpersonationLevel=[W]\nSecurityFlags=[b]\n","Path=[S]\n",
+ "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", NULL}},
+
+{SMBntcancel,"SMBntcancel", 0, DEFDESCRIPT},
+
+{-1,NULL,0,DEFDESCRIPT}};
+
+
+/*******************************************************************
+print a SMB message
+********************************************************************/
+static void print_smb(const uchar *buf, const uchar *maxbuf)
+{
+ int command;
+ const uchar *words, *data;
+ struct smbfns *fn;
+ char *fmt_smbheader =
+"[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";
+
+ request = (CVAL(buf,9)&0x80)?0:1;
+
+ command = CVAL(buf,4);
+
+ fn = smbfind(command,smb_fns);
+
+ printf("\nSMB PACKET: %s (%s)\n",fn->name,request?"REQUEST":"REPLY");
+
+ if (vflag == 0) return;
+
+ /* print out the header */
+ fdata(buf,fmt_smbheader,buf+33);
+
+ if (CVAL(buf,5)) {
+ int class = CVAL(buf,5);
+ int num = SVAL(buf,7);
+ printf("SMBError = %s\n",smb_errstr(class,num));
+ }
+
+ words = buf+32;
+ data = words + 1 + CVAL(words,0)*2;
+
+
+ while (words && data)
+ {
+ char *f1,*f2;
+ int wct = CVAL(words,0);
+
+ if (request) {
+ f1 = fn->descript.req_f1;
+ f2 = fn->descript.req_f2;
+ } else {
+ f1 = fn->descript.rep_f1;
+ f2 = fn->descript.rep_f2;
+ }
+
+ if (fn->descript.fn) {
+ fn->descript.fn(words,data,buf,maxbuf);
+ } else {
+ if (f1) {
+ printf("smbvwv[]=\n");
+ fdata(words+1,f1,words + 1 + wct*2);
+ } else if (wct) {
+ int i;
+ int v;
+ printf("smbvwv[]=\n");
+ for (i=0;i<wct;i++) {
+ v = SVAL(words+1,2*i);
+ printf("smb_vwv[%d]=%d (0x%X)\n",i,v,v);
+ }
+ }
+
+ if (f2) {
+ printf("smbbuf[]=\n");
+ fdata(data+2,f2,maxbuf);
+ } else {
+ int bcc = SVAL(data,0);
+ printf("smb_bcc=%d\n",bcc);
+ if (bcc>0) {
+ printf("smb_buf[]=\n");
+ print_data(data + 2, MIN(bcc,PTR_DIFF(maxbuf,data+2)));
+ }
+ }
+ }
+
+ if ((fn->flags & FLG_CHAIN) && CVAL(words,0) && SVAL(words,1)!=0xFF) {
+ command = SVAL(words,1);
+ words = buf + SVAL(words,3);
+ data = words + 1 + CVAL(words,0)*2;
+
+ fn = smbfind(command,smb_fns);
+
+ printf("\nSMB PACKET: %s (%s) (CHAINED)\n",fn->name,request?"REQUEST":"REPLY");
+ } else {
+ words = data = NULL;
+ }
+ }
+
+ printf("\n");
+}
+
+
+/*
+ print a NBT packet received across tcp on port 139
+*/
+void nbt_tcp_print(const uchar *data,int length)
+{
+ const uchar *maxbuf = data + length;
+ int flags = CVAL(data,0);
+ int nbt_len = RSVAL(data,2);
+
+ startbuf = data;
+ if (maxbuf <= data) return;
+
+ printf("\n>>> NBT Packet\n");
+
+ switch (flags) {
+ case 1:
+ printf("flags=0x%x\n", flags);
+ case 0:
+ data = fdata(data,"NBT Session Packet\nFlags=[rw]\nLength=[rd]\n",data+4);
+ if (data == NULL)
+ break;
+ if (memcmp(data,"\377SMB",4)==0) {
+ if (nbt_len>PTR_DIFF(maxbuf,data))
+ printf("WARNING: Short packet. Try increasing the snap length (%ld)\n",
+ PTR_DIFF(maxbuf,data));
+ print_smb(data,maxbuf>data+nbt_len?data+nbt_len:maxbuf);
+ } else {
+ printf("Session packet:(raw data?)\n");
+ }
+ break;
+
+ case 0x81:
+ data = fdata(data,"NBT Session Request\nFlags=[rW]\nDestination=[n1]\nSource=[n1]\n",maxbuf);
+ break;
+
+ case 0x82:
+ data = fdata(data,"NBT Session Granted\nFlags=[rW]\n",maxbuf);
+ break;
+
+ case 0x83:
+ {
+ int ecode = CVAL(data,4);
+ data = fdata(data,"NBT SessionReject\nFlags=[rW]\nReason=[B]\n",maxbuf);
+ switch (ecode) {
+ case 0x80:
+ printf("Not listening on called name\n");
+ break;
+ case 0x81:
+ printf("Not listening for calling name\n");
+ break;
+ case 0x82:
+ printf("Called name not present\n");
+ break;
+ case 0x83:
+ printf("Called name present, but insufficient resources\n");
+ break;
+ default:
+ printf("Unspecified error 0x%X\n",ecode);
+ break;
+ }
+ }
+ break;
+
+ case 0x85:
+ data = fdata(data,"NBT Session Keepalive\nFlags=[rW]\n",maxbuf);
+ break;
+
+ default:
+ printf("flags=0x%x\n", flags);
+ data = fdata(data,"NBT - Unknown packet type\nType=[rW]\n",maxbuf);
+ }
+ printf("\n");
+ fflush(stdout);
+}
+
+
+/*
+ print a NBT packet received across udp on port 137
+*/
+void nbt_udp137_print(const uchar *data, int length)
+{
+ const uchar *maxbuf = data + length;
+ int name_trn_id = RSVAL(data,0);
+ int response = (CVAL(data,2)>>7);
+ int opcode = (CVAL(data,2) >> 3) & 0xF;
+ int nm_flags = ((CVAL(data,2) & 0x7) << 4) + (CVAL(data,3)>>4);
+ int rcode = CVAL(data,3) & 0xF;
+ int qdcount = RSVAL(data,4);
+ int ancount = RSVAL(data,6);
+ int nscount = RSVAL(data,8);
+ int arcount = RSVAL(data,10);
+ char *opcodestr;
+ const char *p;
+
+ startbuf = data;
+
+ if (maxbuf <= data) return;
+
+ printf("\n>>> NBT UDP PACKET(137): ");
+
+ switch (opcode) {
+ case 0: opcodestr = "QUERY"; break;
+ case 5: opcodestr = "REGISTRATION"; break;
+ case 6: opcodestr = "RELEASE"; break;
+ case 7: opcodestr = "WACK"; break;
+ case 8: opcodestr = "REFRESH(8)"; break;
+ case 9: opcodestr = "REFRESH"; break;
+ default: opcodestr = "OPUNKNOWN"; break;
+ }
+ printf("%s", opcodestr);
+ if (response) {
+ if (rcode)
+ printf("; NEGATIVE");
+ else
+ printf("; POSITIVE");
+ }
+
+ if (response)
+ printf("; RESPONSE");
+ else
+ printf("; REQUEST");
+
+ if (nm_flags&1)
+ printf("; BROADCAST");
+ else
+ printf("; UNICAST");
+
+ if (vflag == 0) return;
+
+ printf("\nTrnID=0x%X\nOpCode=%d\nNmFlags=0x%X\nRcode=%d\nQueryCount=%d\nAnswerCount=%d\nAuthorityCount=%d\nAddressRecCount=%d\n",
+ name_trn_id,opcode,nm_flags,rcode,qdcount,ancount,nscount,arcount);
+
+ p = data + 12;
+
+ {
+ int total = ancount+nscount+arcount;
+ int i;
+
+ if (qdcount>100 || total>100) {
+ printf("Corrupt packet??\n");
+ return;
+ }
+
+ if (qdcount) {
+ printf("QuestionRecords:\n");
+ for (i=0;i<qdcount;i++)
+ p = fdata(p,"|Name=[n1]\nQuestionType=[rw]\nQuestionClass=[rw]\n#",maxbuf);
+ if (p == NULL)
+ goto out;
+ }
+
+ if (total) {
+ printf("\nResourceRecords:\n");
+ for (i=0;i<total;i++) {
+ int rdlen;
+ int restype;
+ p = fdata(p,"Name=[n1]\n#",maxbuf);
+ if (p == NULL)
+ goto out;
+ restype = RSVAL(p,0);
+ p = fdata(p,"ResType=[rw]\nResClass=[rw]\nTTL=[rD]\n",p+8);
+ if (p == NULL)
+ goto out;
+ rdlen = RSVAL(p,0);
+ printf("ResourceLength=%d\nResourceData=\n",rdlen);
+ p += 2;
+ if (rdlen == 6) {
+ p = fdata(p,"AddrType=[rw]\nAddress=[b.b.b.b]\n",p+rdlen);
+ if (p == NULL)
+ goto out;
+ } else {
+ if (restype == 0x21) {
+ int numnames = CVAL(p,0);
+ p = fdata(p,"NumNames=[B]\n",p+1);
+ if (p == NULL)
+ goto out;
+ while (numnames--) {
+ p = fdata(p,"Name=[n2]\t#",maxbuf);
+ if (p[0] & 0x80) printf("<GROUP> ");
+ switch (p[0] & 0x60) {
+ case 0x00: printf("B "); break;
+ case 0x20: printf("P "); break;
+ case 0x40: printf("M "); break;
+ case 0x60: printf("_ "); break;
+ }
+ if (p[0] & 0x10) printf("<DEREGISTERING> ");
+ if (p[0] & 0x08) printf("<CONFLICT> ");
+ if (p[0] & 0x04) printf("<ACTIVE> ");
+ if (p[0] & 0x02) printf("<PERMANENT> ");
+ printf("\n");
+ p += 2;
+ }
+ } else {
+ print_data(p,rdlen);
+ p += rdlen;
+ }
+ }
+ }
+ }
+ }
+
+ if ((uchar*)p < maxbuf) {
+ fdata(p,"AdditionalData:\n",maxbuf);
+ }
+
+out:
+ printf("\n");
+ fflush(stdout);
+}
+
+
+
+/*
+ print a NBT packet received across udp on port 138
+*/
+void nbt_udp138_print(const uchar *data, int length)
+{
+ const uchar *maxbuf = data + length;
+ startbuf = data;
+ if (maxbuf <= data) return;
+
+ data = fdata(data,"\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#",maxbuf);
+
+ if (data != NULL)
+ print_smb(data,maxbuf);
+
+ printf("\n");
+ fflush(stdout);
+}
+
+
+
+/*
+ print netbeui frames
+*/
+void netbeui_print(u_short control, const uchar *data, const uchar *maxbuf)
+{
+ int len = SVAL(data,0);
+ int command = CVAL(data,4);
+ const uchar *data2 = data + len;
+ int is_truncated = 0;
+
+ if (data2 >= maxbuf) {
+ data2 = maxbuf;
+ is_truncated = 1;
+ }
+
+ startbuf = data;
+
+ printf("\n>>> NetBeui Packet\nType=0x%X ", control);
+ data = fdata(data,"Length=[d] Signature=[w] Command=[B]\n#",maxbuf);
+ if (data == NULL)
+ goto out;
+
+ switch (command) {
+ case 0xA:
+ data = fdata(data,"NameQuery:[P1]\nSessionNumber=[B]\nNameType=[B][P2]\nResponseCorrelator=[w]\nDestination=[n2]\nSource=[n2]\n",data2);
+ break;
+
+ case 0x8:
+ data = fdata(data,"NetbiosDataGram:[P7]\nDestination=[n2]\nSource=[n2]\n",data2);
+ break;
+
+ case 0xE:
+ data = fdata(data,"NameRecognise:\n[P1]\nData2=[w]\nTransmitCorrelator=[w]\nResponseCorelator=[w]\nDestination=[n2]\nSource=[n2]\n",data2);
+ break;
+
+ case 0x19:
+ data = fdata(data,"SessionInitialise:\nData1=[B]\nData2=[w]\nTransmitCorrelator=[w]\nResponseCorelator=[w]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n",data2);
+ break;
+
+ case 0x17:
+ data = fdata(data,"SessionConfirm:\nData1=[B]\nData2=[w]\nTransmitCorrelator=[w]\nResponseCorelator=[w]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n",data2);
+ break;
+
+ case 0x16:
+ data = fdata(data,"NetbiosDataOnlyLast:\nFlags=[{|NO_ACK|PIGGYBACK_ACK_ALLOWED|PIGGYBACK_ACK_INCLUDED|}]\nResyncIndicator=[w][P2]\nResponseCorelator=[w]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n",data2);
+ break;
+
+ case 0x14:
+ data = fdata(data,"NetbiosDataAck:\n[P3]TransmitCorrelator=[w][P2]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n",data2);
+ break;
+
+ case 0x18:
+ data = fdata(data,"SessionEnd:\n[P1]Data2=[w][P4]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n",data2);
+ break;
+
+ case 0x1f:
+ data = fdata(data,"SessionAlive\n",data2);
+ break;
+
+ default:
+ data = fdata(data,"Unknown Netbios Command ",data2);
+ break;
+ }
+ if (data == NULL)
+ goto out;
+
+ if (is_truncated) {
+ /* data2 was past the end of the buffer */
+ goto out;
+ }
+
+ if (memcmp(data2,"\377SMB",4)==0) {
+ print_smb(data2,maxbuf);
+ } else {
+ int i;
+ for (i=0;i<128;i++) {
+ if (&data2[i] >= maxbuf)
+ break;
+ if (memcmp(&data2[i],"\377SMB",4)==0) {
+ printf("found SMB packet at %d\n", i);
+ print_smb(&data2[i],maxbuf);
+ break;
+ }
+ }
+ }
+
+out:
+ printf("\n");
+}
+
+
+/*
+ print IPX-Netbios frames
+*/
+void ipx_netbios_print(const uchar *data, const uchar *maxbuf)
+{
+ /* this is a hack till I work out how to parse the rest of the IPX stuff */
+ int i;
+ startbuf = data;
+ for (i=0;i<128;i++)
+ if (memcmp(&data[i],"\377SMB",4)==0) {
+ fdata(data,"\n>>> IPX transport ",&data[i]);
+ if (data != NULL)
+ print_smb(&data[i],maxbuf);
+ printf("\n");
+ fflush(stdout);
+ break;
+ }
+ if (i==128)
+ fdata(data,"\n>>> Unknown IPX ",maxbuf);
+}
diff --git a/usr.sbin/tcpdump/print-tcp.c b/usr.sbin/tcpdump/print-tcp.c
index c0cd9f7701f..823cdca157a 100644
--- a/usr.sbin/tcpdump/print-tcp.c
+++ b/usr.sbin/tcpdump/print-tcp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: print-tcp.c,v 1.13 2000/12/05 08:17:45 jakob Exp $ */
+/* $OpenBSD: print-tcp.c,v 1.14 2000/12/07 22:36:46 mickey Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] =
- "@(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/print-tcp.c,v 1.13 2000/12/05 08:17:45 jakob Exp $ (LBL)";
+ "@(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/print-tcp.c,v 1.14 2000/12/07 22:36:46 mickey Exp $ (LBL)";
#endif
#include <sys/param.h>
@@ -119,6 +119,11 @@ struct tcp_seq_hash {
static struct tcp_seq_hash tcp_seq_hash[TSEQ_HASHSIZE];
+#ifndef BGP_PORT
+#define BGP_PORT 179
+#endif
+#define NETBIOS_SSN_PORT 139
+
static int tcp_cksum(register const struct ip *ip,
register const struct tcphdr *tp,
register int len)
@@ -556,12 +561,11 @@ tcp_print(register const u_char *bp, register u_int length,
/*
* Decode payload if necessary.
*/
-#ifndef BGP_PORT
-#define BGP_PORT 179
-#endif
bp += (tp->th_off * 4);
if (sport == BGP_PORT || dport == BGP_PORT)
bgp_print(bp, length);
+ else if (sport == NETBIOS_SSN_PORT || dport == NETBIOS_SSN_PORT)
+ nbt_tcp_print(bp, length);
return;
bad:
fputs("[bad opt]", stdout);
diff --git a/usr.sbin/tcpdump/print-udp.c b/usr.sbin/tcpdump/print-udp.c
index 5905e952c1c..5523f676566 100644
--- a/usr.sbin/tcpdump/print-udp.c
+++ b/usr.sbin/tcpdump/print-udp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: print-udp.c,v 1.15 2000/12/05 08:17:45 jakob Exp $ */
+/* $OpenBSD: print-udp.c,v 1.16 2000/12/07 22:36:46 mickey Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] =
- "@(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/print-udp.c,v 1.15 2000/12/05 08:17:45 jakob Exp $ (LBL)";
+ "@(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/print-udp.c,v 1.16 2000/12/07 22:36:46 mickey Exp $ (LBL)";
#endif
#include <sys/param.h>
@@ -578,6 +578,10 @@ udp_print(register const u_char *bp, u_int length, register const u_char *bp2)
l2tp_print((const u_char *)(up + 1), length);
else if (ISPORT(ISAKMP_PORT))
isakmp_print((const u_char *)(up + 1), length);
+ else if (ISPORT(NETBIOS_NS_PORT))
+ nbt_udp137_print((const u_char *)(up + 1), length);
+ else if (ISPORT(NETBIOS_DGRAM_PORT))
+ nbt_udp138_print((const u_char *)(up + 1), length);
else if (ISPORT(OLD_RADIUS_AUTH_PORT) ||
ISPORT(OLD_RADIUS_ACCT_PORT) ||
ISPORT(RADIUS_AUTH_PORT) ||
diff --git a/usr.sbin/tcpdump/smb.h b/usr.sbin/tcpdump/smb.h
new file mode 100644
index 00000000000..e2d32618ca2
--- /dev/null
+++ b/usr.sbin/tcpdump/smb.h
@@ -0,0 +1,154 @@
+/* $OpenBSD: smb.h,v 1.1 2000/12/07 22:36:46 mickey Exp $ */
+
+/*
+ Copyright (C) Andrew Tridgell 1995-1999
+
+ This software may be distributed either under the terms of the
+ BSD-style license that accompanies tcpdump or the GNU GPL version 2
+ or later */
+
+#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
+#define PVAL(buf,pos) ((unsigned)CVAL(buf,pos))
+#define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val))
+
+#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
+#define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16)
+#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
+#define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16))
+#define SVALS(buf,pos) ((int16)SVAL(buf,pos))
+#define IVALS(buf,pos) ((int32)IVAL(buf,pos))
+#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16)(val)))
+#define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32)(val)))
+#define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16)(val)))
+#define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32)(val)))
+
+/* now the reverse routines - these are used in nmb packets (mostly) */
+#define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
+#define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16)))
+
+#define RSVAL(buf,pos) SREV(SVAL(buf,pos))
+#define RIVAL(buf,pos) IREV(IVAL(buf,pos))
+#define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val))
+#define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val))
+
+#define uint16 unsigned short
+#define uint32 unsigned int
+#ifndef uchar
+#define uchar unsigned char
+#endif
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+
+/* the complete */
+#define SMBmkdir 0x00 /* create directory */
+#define SMBrmdir 0x01 /* delete directory */
+#define SMBopen 0x02 /* open file */
+#define SMBcreate 0x03 /* create file */
+#define SMBclose 0x04 /* close file */
+#define SMBflush 0x05 /* flush file */
+#define SMBunlink 0x06 /* delete file */
+#define SMBmv 0x07 /* rename file */
+#define SMBgetatr 0x08 /* get file attributes */
+#define SMBsetatr 0x09 /* set file attributes */
+#define SMBread 0x0A /* read from file */
+#define SMBwrite 0x0B /* write to file */
+#define SMBlock 0x0C /* lock byte range */
+#define SMBunlock 0x0D /* unlock byte range */
+#define SMBctemp 0x0E /* create temporary file */
+#define SMBmknew 0x0F /* make new file */
+#define SMBchkpth 0x10 /* check directory path */
+#define SMBexit 0x11 /* process exit */
+#define SMBlseek 0x12 /* seek */
+#define SMBtcon 0x70 /* tree connect */
+#define SMBtconX 0x75 /* tree connect and X*/
+#define SMBtdis 0x71 /* tree disconnect */
+#define SMBnegprot 0x72 /* negotiate protocol */
+#define SMBdskattr 0x80 /* get disk attributes */
+#define SMBsearch 0x81 /* search directory */
+#define SMBsplopen 0xC0 /* open print spool file */
+#define SMBsplwr 0xC1 /* write to print spool file */
+#define SMBsplclose 0xC2 /* close print spool file */
+#define SMBsplretq 0xC3 /* return print queue */
+#define SMBsends 0xD0 /* send single block message */
+#define SMBsendb 0xD1 /* send broadcast message */
+#define SMBfwdname 0xD2 /* forward user name */
+#define SMBcancelf 0xD3 /* cancel forward */
+#define SMBgetmac 0xD4 /* get machine name */
+#define SMBsendstrt 0xD5 /* send start of multi-block message */
+#define SMBsendend 0xD6 /* send end of multi-block message */
+#define SMBsendtxt 0xD7 /* send text of multi-block message */
+
+/* Core+ protocol */
+#define SMBlockread 0x13 /* Lock a range and read */
+#define SMBwriteunlock 0x14 /* Unlock a range then write */
+#define SMBreadbraw 0x1a /* read a block of data with no smb header */
+#define SMBwritebraw 0x1d /* write a block of data with no smb header */
+#define SMBwritec 0x20 /* secondary write request */
+#define SMBwriteclose 0x2c /* write a file then close it */
+
+/* dos extended protocol */
+#define SMBreadBraw 0x1A /* read block raw */
+#define SMBreadBmpx 0x1B /* read block multiplexed */
+#define SMBreadBs 0x1C /* read block (secondary response) */
+#define SMBwriteBraw 0x1D /* write block raw */
+#define SMBwriteBmpx 0x1E /* write block multiplexed */
+#define SMBwriteBs 0x1F /* write block (secondary request) */
+#define SMBwriteC 0x20 /* write complete response */
+#define SMBsetattrE 0x22 /* set file attributes expanded */
+#define SMBgetattrE 0x23 /* get file attributes expanded */
+#define SMBlockingX 0x24 /* lock/unlock byte ranges and X */
+#define SMBtrans 0x25 /* transaction - name, bytes in/out */
+#define SMBtranss 0x26 /* transaction (secondary request/response) */
+#define SMBioctl 0x27 /* IOCTL */
+#define SMBioctls 0x28 /* IOCTL (secondary request/response) */
+#define SMBcopy 0x29 /* copy */
+#define SMBmove 0x2A /* move */
+#define SMBecho 0x2B /* echo */
+#define SMBopenX 0x2D /* open and X */
+#define SMBreadX 0x2E /* read and X */
+#define SMBwriteX 0x2F /* write and X */
+#define SMBsesssetupX 0x73 /* Session Set Up & X (including User Logon) */
+#define SMBffirst 0x82 /* find first */
+#define SMBfunique 0x83 /* find unique */
+#define SMBfclose 0x84 /* find close */
+#define SMBinvalid 0xFE /* invalid command */
+
+/* Extended 2.0 protocol */
+#define SMBtrans2 0x32 /* TRANS2 protocol set */
+#define SMBtranss2 0x33 /* TRANS2 protocol set, secondary command */
+#define SMBfindclose 0x34 /* Terminate a TRANSACT2_FINDFIRST */
+#define SMBfindnclose 0x35 /* Terminate a TRANSACT2_FINDNOTIFYFIRST */
+#define SMBulogoffX 0x74 /* user logoff */
+
+/* NT SMB extensions. */
+#define SMBnttrans 0xA0 /* NT transact */
+#define SMBnttranss 0xA1 /* NT transact secondary */
+#define SMBntcreateX 0xA2 /* NT create and X */
+#define SMBntcancel 0xA4 /* NT cancel */
+
+/* pathworks special */
+#define pSETDIR '\377'
+
+
+/* these are the TRANS2 sub commands */
+#define TRANSACT2_OPEN 0
+#define TRANSACT2_FINDFIRST 1
+#define TRANSACT2_FINDNEXT 2
+#define TRANSACT2_QFSINFO 3
+#define TRANSACT2_SETFSINFO 4
+#define TRANSACT2_QPATHINFO 5
+#define TRANSACT2_SETPATHINFO 6
+#define TRANSACT2_QFILEINFO 7
+#define TRANSACT2_SETFILEINFO 8
+#define TRANSACT2_FSCTL 9
+#define TRANSACT2_IOCTL 10
+#define TRANSACT2_FINDNOTIFYFIRST 11
+#define TRANSACT2_FINDNOTIFYNEXT 12
+#define TRANSACT2_MKDIR 13
+
+#define PTR_DIFF(p1,p2) ((unsigned long)(((char *)(p1)) - (char *)(p2)))
+
+/* some protos */
+const uchar *fdata(const uchar *buf, const char *fmt, const uchar *maxbuf);
diff --git a/usr.sbin/tcpdump/smbutil.c b/usr.sbin/tcpdump/smbutil.c
new file mode 100644
index 00000000000..725ac6982a0
--- /dev/null
+++ b/usr.sbin/tcpdump/smbutil.c
@@ -0,0 +1,759 @@
+/* $OpenBSD: smbutil.c,v 1.1 2000/12/07 22:36:46 mickey Exp $ */
+
+/*
+ Copyright (C) Andrew Tridgell 1995-1999
+
+ This software may be distributed either under the terms of the
+ BSD-style license that accompanies tcpdump or the GNU GPL version 2
+ or later */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef lint
+static const char rcsid[] =
+ "@(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/smbutil.c,v 1.1 2000/12/07 22:36:46 mickey Exp $";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+
+#include <netinet/in.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "interface.h"
+#include "smb.h"
+
+extern const uchar *startbuf;
+
+/*******************************************************************
+ interpret a 32 bit dos packed date/time to some parameters
+********************************************************************/
+static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *hour,int *minute,int *second)
+{
+ uint32 p0,p1,p2,p3;
+
+ p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF;
+ p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF;
+
+ *second = 2*(p0 & 0x1F);
+ *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3);
+ *hour = (p1>>3)&0xFF;
+ *day = (p2&0x1F);
+ *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1;
+ *year = ((p3>>1)&0xFF) + 80;
+}
+
+/*******************************************************************
+ create a unix date from a dos date
+********************************************************************/
+static time_t make_unix_date(const void *date_ptr)
+{
+ uint32 dos_date=0;
+ struct tm t;
+
+ dos_date = IVAL(date_ptr,0);
+
+ if (dos_date == 0) return(0);
+
+ interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
+ &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
+ t.tm_wday = 1;
+ t.tm_yday = 1;
+ t.tm_isdst = 0;
+
+ return (mktime(&t));
+}
+
+/*******************************************************************
+ create a unix date from a dos date
+********************************************************************/
+static time_t make_unix_date2(const void *date_ptr)
+{
+ uint32 x,x2;
+
+ x = IVAL(date_ptr,0);
+ x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
+ SIVAL(&x,0,x2);
+
+ return(make_unix_date((void *)&x));
+}
+
+/****************************************************************************
+interpret an 8 byte "filetime" structure to a time_t
+It's originally in "100ns units since jan 1st 1601"
+****************************************************************************/
+static time_t interpret_long_date(const char *p)
+{
+ double d;
+ time_t ret;
+
+ /* this gives us seconds since jan 1st 1601 (approx) */
+ d = (IVAL(p,4)*256.0 + CVAL(p,3)) * (1.0e-7 * (1<<24));
+
+ /* now adjust by 369 years to make the secs since 1970 */
+ d -= 369.0*365.25*24*60*60;
+
+ /* and a fudge factor as we got it wrong by a few days */
+ d += (3*24*60*60 + 6*60*60 + 2);
+
+ if (d<0)
+ return(0);
+
+ ret = (time_t)d;
+
+ return(ret);
+}
+
+
+/****************************************************************************
+interpret the weird netbios "name". Return the name type, or -1 if
+we run past the end of the buffer
+****************************************************************************/
+static int name_interpret(const uchar *in,const uchar *maxbuf,char *out)
+{
+ int ret;
+ int len;
+
+ if (in >= maxbuf)
+ return(-1); /* name goes past the end of the buffer */
+ TCHECK2(*in, 1);
+ len = (*in++) / 2;
+
+ *out=0;
+
+ if (len > 30 || len<1) return(0);
+
+ while (len--)
+ {
+ if (in + 1 >= maxbuf)
+ return(-1); /* name goes past the end of the buffer */
+ TCHECK2(*in, 2);
+ if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
+ *out = 0;
+ return(0);
+ }
+ *out = ((in[0]-'A')<<4) + (in[1]-'A');
+ in += 2;
+ out++;
+ }
+ *out = 0;
+ ret = out[-1];
+
+ return(ret);
+
+trunc:
+ return(-1);
+}
+
+/****************************************************************************
+find a pointer to a netbios name
+****************************************************************************/
+static const uchar *name_ptr(const uchar *buf,int ofs,const uchar *maxbuf)
+{
+ const uchar *p;
+ uchar c;
+
+ p = buf+ofs;
+ if (p >= maxbuf)
+ return(NULL); /* name goes past the end of the buffer */
+ TCHECK2(*p, 1);
+
+ c = *p;
+
+ /* XXX - this should use the same code that the DNS dissector does */
+ if ((c & 0xC0) == 0xC0)
+ {
+ uint16 l = RSVAL(buf, ofs) & 0x3FFF;
+ if (l == 0)
+ {
+ /* We have a pointer that points to itself. */
+ return(NULL);
+ }
+ p = buf + l;
+ if (p >= maxbuf)
+ return(NULL); /* name goes past the end of the buffer */
+ TCHECK2(*p, 1);
+ return(buf + l);
+ }
+ else
+ return(buf+ofs);
+
+trunc:
+ return(NULL); /* name goes past the end of the buffer */
+}
+
+/****************************************************************************
+extract a netbios name from a buf
+****************************************************************************/
+static int name_extract(const uchar *buf,int ofs,const uchar *maxbuf,char *name)
+{
+ const uchar *p = name_ptr(buf,ofs,maxbuf);
+ if (p == NULL)
+ return(-1); /* error (probably name going past end of buffer) */
+ strcpy(name,"");
+ return(name_interpret(p,maxbuf,name));
+}
+
+
+/****************************************************************************
+return the total storage length of a mangled name
+****************************************************************************/
+static int name_len(const unsigned char *s, const unsigned char *maxbuf)
+{
+ const unsigned char *s0 = s;
+ unsigned char c;
+
+ if (s >= maxbuf)
+ return(-1); /* name goes past the end of the buffer */
+ TCHECK2(*s, 1);
+ c = *s;
+ if ((c & 0xC0) == 0xC0)
+ return(2);
+ while (*s)
+ {
+ if (s >= maxbuf)
+ return(-1); /* name goes past the end of the buffer */
+ TCHECK2(*s, 1);
+ s += (*s)+1;
+ }
+ return(PTR_DIFF(s,s0)+1);
+
+trunc:
+ return(-1); /* name goes past the end of the buffer */
+}
+
+static void print_asc(const unsigned char *buf,int len)
+{
+ int i;
+ for (i=0;i<len;i++)
+ printf("%c",isprint(buf[i])?buf[i]:'.');
+}
+
+static char *name_type_str(int name_type)
+{
+ static char *f = NULL;
+ switch (name_type) {
+ case 0: f = "Workstation"; break;
+ case 0x03: f = "Client?"; break;
+ case 0x20: f = "Server"; break;
+ case 0x1d: f = "Master Browser"; break;
+ case 0x1b: f = "Domain Controller"; break;
+ case 0x1e: f = "Browser Server"; break;
+ default: f = "Unknown"; break;
+ }
+ return(f);
+}
+
+void print_data(const unsigned char *buf, int len)
+{
+ int i=0;
+ if (len<=0) return;
+ printf("[%03X] ",i);
+ for (i=0;i<len;) {
+ printf("%02X ",(int)buf[i]);
+ i++;
+ if (i%8 == 0) printf(" ");
+ if (i%16 == 0) {
+ print_asc(&buf[i-16],8); printf(" ");
+ print_asc(&buf[i-8],8); printf("\n");
+ if (i<len) printf("[%03X] ",i);
+ }
+ }
+ if (i%16) {
+ int n;
+
+ n = 16 - (i%16);
+ printf(" ");
+ if (n>8) printf(" ");
+ while (n--) printf(" ");
+
+ n = MIN(8,i%16);
+ print_asc(&buf[i-(i%16)],n); printf(" ");
+ n = (i%16) - n;
+ if (n>0) print_asc(&buf[i-n],n);
+ printf("\n");
+ }
+}
+
+
+static void write_bits(unsigned int val,char *fmt)
+{
+ char *p = fmt;
+ int i=0;
+
+ while ((p=strchr(fmt,'|'))) {
+ int l = PTR_DIFF(p,fmt);
+ if (l && (val & (1<<i)))
+ printf("%.*s ",l,fmt);
+ fmt = p+1;
+ i++;
+ }
+}
+
+/* convert a unicode string */
+static const char *unistr(const char *s, int *len)
+{
+ static char buf[1000];
+ int l=0;
+ static int use_unicode = -1;
+
+ if (use_unicode == -1) {
+ char *p = getenv("USE_UNICODE");
+ if (p && (atoi(p) == 1))
+ use_unicode = 1;
+ else
+ use_unicode = 0;
+ }
+
+ /* maybe it isn't unicode - a cheap trick */
+ if (!use_unicode || (s[0] && s[1])) {
+ *len = strlen(s)+1;
+ return s;
+ }
+
+ *len = 0;
+
+ if (s[0] == 0 && s[1] != 0) {
+ s++;
+ *len = 1;
+ }
+
+ while (l < (sizeof(buf)-1) && s[0] && s[1] == 0) {
+ buf[l] = s[0];
+ s += 2; l++;
+ *len += 2;
+ }
+ buf[l] = 0;
+ *len += 2;
+ return buf;
+}
+
+static const uchar *fdata1(const uchar *buf, const char *fmt, const uchar *maxbuf)
+{
+ int reverse=0;
+ char *attrib_fmt = "READONLY|HIDDEN|SYSTEM|VOLUME|DIR|ARCHIVE|";
+ int len;
+
+ while (*fmt && buf<maxbuf) {
+ switch (*fmt) {
+ case 'a':
+ write_bits(CVAL(buf,0),attrib_fmt);
+ buf++; fmt++;
+ break;
+
+ case 'A':
+ write_bits(SVAL(buf,0),attrib_fmt);
+ buf+=2; fmt++;
+ break;
+
+ case '{':
+ {
+ char bitfmt[128];
+ char *p = strchr(++fmt,'}');
+ int l = PTR_DIFF(p,fmt);
+ strncpy(bitfmt,fmt,l);
+ bitfmt[l]=0;
+ fmt = p+1;
+ write_bits(CVAL(buf,0),bitfmt);
+ buf++;
+ break;
+ }
+
+ case 'P':
+ {
+ int l = atoi(fmt+1);
+ buf += l;
+ fmt++;
+ while (isdigit(*fmt)) fmt++;
+ break;
+ }
+ case 'r':
+ reverse = !reverse;
+ fmt++;
+ break;
+ case 'D':
+ {
+ unsigned int x = reverse?RIVAL(buf,0):IVAL(buf,0);
+ printf("%d (0x%x)",x, x);
+ buf += 4;
+ fmt++;
+ break;
+ }
+ case 'L':
+ {
+ unsigned int x1 = reverse?RIVAL(buf,0):IVAL(buf,0);
+ unsigned int x2 = reverse?RIVAL(buf,4):IVAL(buf,4);
+ if (x2) {
+ printf("0x%08x:%08x",x2, x1);
+ } else {
+ printf("%d (0x%08x%08x)",x1, x2, x1);
+ }
+ buf += 8;
+ fmt++;
+ break;
+ }
+ case 'd':
+ {
+ unsigned int x = reverse?RSVAL(buf,0):SVAL(buf,0);
+ printf("%d (0x%x)",x, x);
+ buf += 2;
+ fmt++;
+ break;
+ }
+ case 'W':
+ {
+ unsigned int x = reverse?RIVAL(buf,0):IVAL(buf,0);
+ printf("0x%X",x);
+ buf += 4;
+ fmt++;
+ break;
+ }
+ case 'w':
+ {
+ unsigned int x = reverse?RSVAL(buf,0):SVAL(buf,0);
+ printf("0x%X",x);
+ buf += 2;
+ fmt++;
+ break;
+ }
+ case 'B':
+ {
+ unsigned int x = CVAL(buf,0);
+ printf("0x%X",x);
+ buf += 1;
+ fmt++;
+ break;
+ }
+ case 'b':
+ {
+ unsigned int x = CVAL(buf,0);
+ printf("%d (0x%x)",x, x);
+ buf += 1;
+ fmt++;
+ break;
+ }
+ case 'S':
+ {
+ printf("%.*s",(int)PTR_DIFF(maxbuf,buf),unistr(buf, &len));
+ buf += len;
+ fmt++;
+ break;
+ }
+ case 'Z':
+ {
+ if (*buf != 4 && *buf != 2)
+ printf("Error! ASCIIZ buffer of type %d (safety=%d)\n",
+ *buf,(int)PTR_DIFF(maxbuf,buf));
+ printf("%.*s",(int)PTR_DIFF(maxbuf,buf+1),unistr(buf+1, &len));
+ buf += len+1;
+ fmt++;
+ break;
+ }
+ case 's':
+ {
+ int l = atoi(fmt+1);
+ printf("%-*.*s",l,l,buf);
+ buf += l;
+ fmt++; while (isdigit(*fmt)) fmt++;
+ break;
+ }
+ case 'h':
+ {
+ int l = atoi(fmt+1);
+ while (l--) printf("%02x",*buf++);
+ fmt++; while (isdigit(*fmt)) fmt++;
+ break;
+ }
+ case 'n':
+ {
+ int t = atoi(fmt+1);
+ char nbuf[255];
+ int name_type;
+ int len;
+ switch (t) {
+ case 1:
+ name_type = name_extract(startbuf,PTR_DIFF(buf,startbuf),maxbuf,
+ nbuf);
+ if (name_type < 0)
+ goto trunc;
+ len = name_len(buf,maxbuf);
+ if (len < 0)
+ goto trunc;
+ buf += len;
+ printf("%-15.15s NameType=0x%02X (%s)",
+ nbuf,name_type,name_type_str(name_type));
+ break;
+ case 2:
+ name_type = buf[15];
+ printf("%-15.15s NameType=0x%02X (%s)",
+ buf,name_type,name_type_str(name_type));
+ buf += 16;
+ break;
+ }
+ fmt++; while (isdigit(*fmt)) fmt++;
+ break;
+ }
+ case 'T':
+ {
+ time_t t;
+ int x = IVAL(buf,0);
+ switch (atoi(fmt+1)) {
+ case 1:
+ if (x==0 || x==-1 || x==0xFFFFFFFF)
+ t = 0;
+ else
+ t = make_unix_date(buf);
+ buf+=4;
+ break;
+ case 2:
+ if (x==0 || x==-1 || x==0xFFFFFFFF)
+ t = 0;
+ else
+ t = make_unix_date2(buf);
+ buf+=4;
+ break;
+ case 3:
+ t = interpret_long_date(buf);
+ buf+=8;
+ break;
+ }
+ printf("%s",t?asctime(localtime(&t)):"NULL\n");
+ fmt++; while (isdigit(*fmt)) fmt++;
+ break;
+ }
+ default:
+ putchar(*fmt);
+ fmt++;
+ break;
+ }
+ }
+
+ if (buf>=maxbuf && *fmt)
+ printf("END OF BUFFER\n");
+
+ return(buf);
+
+trunc:
+ printf("\n");
+ printf("WARNING: Short packet. Try increasing the snap length\n");
+ return(NULL);
+}
+
+const uchar *fdata(const uchar *buf, const char *fmt, const uchar *maxbuf)
+{
+ static int depth=0;
+ char s[128];
+ char *p;
+
+ while (*fmt) {
+ switch (*fmt) {
+ case '*':
+ fmt++;
+ while (buf < maxbuf) {
+ const uchar *buf2;
+ depth++;
+ buf2 = fdata(buf,fmt,maxbuf);
+ depth--;
+ if (buf2 == buf) return(buf);
+ buf = buf2;
+ }
+ break;
+
+ case '|':
+ fmt++;
+ if (buf>=maxbuf) return(buf);
+ break;
+
+ case '%':
+ fmt++;
+ buf=maxbuf;
+ break;
+
+ case '#':
+ fmt++;
+ return(buf);
+ break;
+
+ case '[':
+ fmt++;
+ if (buf>=maxbuf) return(buf);
+ memset(s, 0, sizeof(s));
+ p = strchr(fmt,']');
+ strncpy(s,fmt,p-fmt);
+ fmt = p+1;
+ buf = fdata1(buf,s,maxbuf);
+ if (buf == NULL)
+ return(NULL);
+ break;
+
+ default:
+ putchar(*fmt); fmt++;
+ fflush(stdout);
+ break;
+ }
+ }
+ if (!depth && buf<maxbuf) {
+ int len = PTR_DIFF(maxbuf,buf);
+ printf("Data: (%d bytes)\n",len);
+ print_data(buf,len);
+ return(buf+len);
+ }
+ return(buf);
+}
+
+typedef struct
+{
+ char *name;
+ int code;
+ char *message;
+} err_code_struct;
+
+/* Dos Error Messages */
+static err_code_struct dos_msgs[] = {
+ {"ERRbadfunc",1,"Invalid function."},
+ {"ERRbadfile",2,"File not found."},
+ {"ERRbadpath",3,"Directory invalid."},
+ {"ERRnofids",4,"No file descriptors available"},
+ {"ERRnoaccess",5,"Access denied."},
+ {"ERRbadfid",6,"Invalid file handle."},
+ {"ERRbadmcb",7,"Memory control blocks destroyed."},
+ {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
+ {"ERRbadmem",9,"Invalid memory block address."},
+ {"ERRbadenv",10,"Invalid environment."},
+ {"ERRbadformat",11,"Invalid format."},
+ {"ERRbadaccess",12,"Invalid open mode."},
+ {"ERRbaddata",13,"Invalid data."},
+ {"ERR",14,"reserved."},
+ {"ERRbaddrive",15,"Invalid drive specified."},
+ {"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."},
+ {"ERRdiffdevice",17,"Not same device."},
+ {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
+ {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."},
+ {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
+ {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."},
+ {"ERRbadpipe",230,"Pipe invalid."},
+ {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
+ {"ERRpipeclosing",232,"Pipe close in progress."},
+ {"ERRnotconnected",233,"No process on other end of pipe."},
+ {"ERRmoredata",234,"There is more data to be returned."},
+ {NULL,-1,NULL}};
+
+/* Server Error Messages */
+err_code_struct server_msgs[] = {
+ {"ERRerror",1,"Non-specific error code."},
+ {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
+ {"ERRbadtype",3,"reserved."},
+ {"ERRaccess",4,"The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."},
+ {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
+ {"ERRinvnetname",6,"Invalid network name in tree connect."},
+ {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
+ {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
+ {"ERRqtoobig",50,"Print queue full -- no space."},
+ {"ERRqeof",51,"EOF on print queue dump."},
+ {"ERRinvpfid",52,"Invalid print file FID."},
+ {"ERRsmbcmd",64,"The server did not recognize the command received."},
+ {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
+ {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."},
+ {"ERRreserved",68,"reserved."},
+ {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
+ {"ERRreserved",70,"reserved."},
+ {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
+ {"ERRpaused",81,"Server is paused."},
+ {"ERRmsgoff",82,"Not receiving messages."},
+ {"ERRnoroom",83,"No room to buffer message."},
+ {"ERRrmuns",87,"Too many remote user names."},
+ {"ERRtimeout",88,"Operation timed out."},
+ {"ERRnoresource",89,"No resources currently available for request."},
+ {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
+ {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
+ {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
+ {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
+ {"ERRcontmpx",252,"Continue in MPX mode."},
+ {"ERRreserved",253,"reserved."},
+ {"ERRreserved",254,"reserved."},
+ {"ERRnosupport",0xFFFF,"Function not supported."},
+ {NULL,-1,NULL}};
+
+/* Hard Error Messages */
+err_code_struct hard_msgs[] = {
+ {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
+ {"ERRbadunit",20,"Unknown unit."},
+ {"ERRnotready",21,"Drive not ready."},
+ {"ERRbadcmd",22,"Unknown command."},
+ {"ERRdata",23,"Data error (CRC)."},
+ {"ERRbadreq",24,"Bad request structure length."},
+ {"ERRseek",25 ,"Seek error."},
+ {"ERRbadmedia",26,"Unknown media type."},
+ {"ERRbadsector",27,"Sector not found."},
+ {"ERRnopaper",28,"Printer out of paper."},
+ {"ERRwrite",29,"Write fault."},
+ {"ERRread",30,"Read fault."},
+ {"ERRgeneral",31,"General failure."},
+ {"ERRbadshare",32,"A open conflicts with an existing open."},
+ {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
+ {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
+ {"ERRFCBUnavail",35,"No FCBs are available to process request."},
+ {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
+ {NULL,-1,NULL}};
+
+
+static struct
+{
+ int code;
+ char *class;
+ err_code_struct *err_msgs;
+} err_classes[] = {
+ {0,"SUCCESS",NULL},
+ {0x01,"ERRDOS",dos_msgs},
+ {0x02,"ERRSRV",server_msgs},
+ {0x03,"ERRHRD",hard_msgs},
+ {0x04,"ERRXOS",NULL},
+ {0xE1,"ERRRMX1",NULL},
+ {0xE2,"ERRRMX2",NULL},
+ {0xE3,"ERRRMX3",NULL},
+ {0xFF,"ERRCMD",NULL},
+ {-1,NULL,NULL}};
+
+
+/****************************************************************************
+return a SMB error string from a SMB buffer
+****************************************************************************/
+char *smb_errstr(int class,int num)
+{
+ static char ret[128];
+ int i,j;
+
+ ret[0]=0;
+
+ for (i=0;err_classes[i].class;i++)
+ if (err_classes[i].code == class)
+ {
+ if (err_classes[i].err_msgs)
+ {
+ err_code_struct *err = err_classes[i].err_msgs;
+ for (j=0;err[j].name;j++)
+ if (num == err[j].code)
+ {
+ snprintf(ret,sizeof(ret),"%s - %s (%s)",err_classes[i].class,
+ err[j].name,err[j].message);
+ return ret;
+ }
+ }
+
+ snprintf(ret,sizeof(ret),"%s - %d",err_classes[i].class,num);
+ return ret;
+ }
+
+ snprintf(ret,sizeof(ret),"ERROR: Unknown error (%d,%d)",class,num);
+ return(ret);
+}