xref: /openbsd-src/usr.sbin/tcpdump/smbutil.c (revision b963d3dd6ef8cb6029fcb15345fdeff353b6b3c8)
1*b963d3ddSmmcc /*	$OpenBSD: smbutil.c,v 1.10 2015/10/25 18:25:41 mmcc Exp $	*/
232d56144Smickey 
332d56144Smickey /*
432d56144Smickey    Copyright (C) Andrew Tridgell 1995-1999
532d56144Smickey 
632d56144Smickey    This software may be distributed either under the terms of the
732d56144Smickey    BSD-style license that accompanies tcpdump or the GNU GPL version 2
832d56144Smickey    or later */
932d56144Smickey 
1032d56144Smickey #ifdef HAVE_CONFIG_H
1132d56144Smickey #include "config.h"
1232d56144Smickey #endif
1332d56144Smickey 
1432d56144Smickey #include <sys/time.h>
1532d56144Smickey #include <sys/types.h>
1632d56144Smickey #include <sys/socket.h>
1732d56144Smickey 
1832d56144Smickey 
1932d56144Smickey #include <netinet/in.h>
2032d56144Smickey 
2132d56144Smickey #include <ctype.h>
2232d56144Smickey #include <stdio.h>
2332d56144Smickey #include <stdlib.h>
2432d56144Smickey #include <string.h>
2532d56144Smickey #include <time.h>
2632d56144Smickey 
2732d56144Smickey #include "interface.h"
2832d56144Smickey #include "smb.h"
2932d56144Smickey 
3032d56144Smickey extern const uchar *startbuf;
3132d56144Smickey 
3232d56144Smickey /*******************************************************************
3332d56144Smickey   interpret a 32 bit dos packed date/time to some parameters
3432d56144Smickey ********************************************************************/
interpret_dos_date(uint32 date,int * year,int * month,int * day,int * hour,int * minute,int * second)3532d56144Smickey static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *hour,int *minute,int *second)
3632d56144Smickey {
3732d56144Smickey   uint32 p0,p1,p2,p3;
3832d56144Smickey 
3932d56144Smickey   p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF;
4032d56144Smickey   p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF;
4132d56144Smickey 
4232d56144Smickey   *second = 2*(p0 & 0x1F);
4332d56144Smickey   *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3);
4432d56144Smickey   *hour = (p1>>3)&0xFF;
4532d56144Smickey   *day = (p2&0x1F);
4632d56144Smickey   *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1;
4732d56144Smickey   *year = ((p3>>1)&0xFF) + 80;
4832d56144Smickey }
4932d56144Smickey 
5032d56144Smickey /*******************************************************************
5132d56144Smickey   create a unix date from a dos date
5232d56144Smickey ********************************************************************/
make_unix_date(const void * date_ptr)5332d56144Smickey static time_t make_unix_date(const void *date_ptr)
5432d56144Smickey {
5532d56144Smickey   uint32 dos_date=0;
5632d56144Smickey   struct tm t;
5732d56144Smickey 
5832d56144Smickey   dos_date = IVAL(date_ptr,0);
5932d56144Smickey 
6032d56144Smickey   if (dos_date == 0) return(0);
6132d56144Smickey 
627fab3b7fSderaadt   memset(&t, 0, sizeof t);
6332d56144Smickey   interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
6432d56144Smickey 		     &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
6532d56144Smickey   t.tm_wday = 1;
6632d56144Smickey   t.tm_yday = 1;
6732d56144Smickey   t.tm_isdst = 0;
6832d56144Smickey 
6932d56144Smickey   return (mktime(&t));
7032d56144Smickey }
7132d56144Smickey 
7232d56144Smickey /*******************************************************************
7332d56144Smickey   create a unix date from a dos date
7432d56144Smickey ********************************************************************/
make_unix_date2(const void * date_ptr)7532d56144Smickey static time_t make_unix_date2(const void *date_ptr)
7632d56144Smickey {
7732d56144Smickey   uint32 x,x2;
7832d56144Smickey 
7932d56144Smickey   x = IVAL(date_ptr,0);
8032d56144Smickey   x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
8132d56144Smickey   SIVAL(&x,0,x2);
8232d56144Smickey 
8332d56144Smickey   return(make_unix_date((void *)&x));
8432d56144Smickey }
8532d56144Smickey 
8632d56144Smickey /****************************************************************************
8732d56144Smickey interpret an 8 byte "filetime" structure to a time_t
8832d56144Smickey It's originally in "100ns units since jan 1st 1601"
8932d56144Smickey ****************************************************************************/
interpret_long_date(const char * p)9032d56144Smickey static time_t interpret_long_date(const char *p)
9132d56144Smickey {
9232d56144Smickey   double d;
9332d56144Smickey   time_t ret;
9432d56144Smickey 
9532d56144Smickey   /* this gives us seconds since jan 1st 1601 (approx) */
9632d56144Smickey   d = (IVAL(p,4)*256.0 + CVAL(p,3)) * (1.0e-7 * (1<<24));
9732d56144Smickey 
9832d56144Smickey   /* now adjust by 369 years to make the secs since 1970 */
9932d56144Smickey   d -= 369.0*365.25*24*60*60;
10032d56144Smickey 
10132d56144Smickey   /* and a fudge factor as we got it wrong by a few days */
10232d56144Smickey   d += (3*24*60*60 + 6*60*60 + 2);
10332d56144Smickey 
10432d56144Smickey   if (d<0)
10532d56144Smickey     return(0);
10632d56144Smickey 
10732d56144Smickey   ret = (time_t)d;
10832d56144Smickey 
10932d56144Smickey   return(ret);
11032d56144Smickey }
11132d56144Smickey 
11232d56144Smickey 
11332d56144Smickey /****************************************************************************
11432d56144Smickey interpret the weird netbios "name". Return the name type, or -1 if
11532d56144Smickey we run past the end of the buffer
11632d56144Smickey ****************************************************************************/
name_interpret(const uchar * in,const uchar * maxbuf,char * out)11732d56144Smickey static int name_interpret(const uchar *in,const uchar *maxbuf,char *out)
11832d56144Smickey {
1199dd8098fSmickey   char *ob = out;
12032d56144Smickey   int ret;
12132d56144Smickey   int len;
12232d56144Smickey 
12332d56144Smickey   if (in >= maxbuf)
12432d56144Smickey     return(-1);	/* name goes past the end of the buffer */
12532d56144Smickey   TCHECK2(*in, 1);
12632d56144Smickey   len = (*in++) / 2;
12732d56144Smickey 
12832d56144Smickey   *out=0;
12932d56144Smickey 
13032d56144Smickey   if (len > 30 || len<1) return(0);
13132d56144Smickey 
13232d56144Smickey   while (len--)
13332d56144Smickey     {
13432d56144Smickey       if (in + 1 >= maxbuf)
13532d56144Smickey 	return(-1);	/* name goes past the end of the buffer */
13632d56144Smickey       TCHECK2(*in, 2);
13732d56144Smickey       if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
1389dd8098fSmickey 	*out++ = 0;
1399dd8098fSmickey 	break;
14032d56144Smickey       }
14132d56144Smickey       *out = ((in[0]-'A')<<4) + (in[1]-'A');
14232d56144Smickey       in += 2;
14332d56144Smickey       out++;
14432d56144Smickey     }
14532d56144Smickey   ret = out[-1];
1469dd8098fSmickey   out--;
1479dd8098fSmickey   while (out[-1] == ' ')
1489dd8098fSmickey     out--;
1499dd8098fSmickey   *out = '\0';
1509dd8098fSmickey   for (; *ob; ob++)
151*b963d3ddSmmcc     if (!isprint((unsigned char)*ob))
1529dd8098fSmickey       *ob = 'X';
15332d56144Smickey 
15432d56144Smickey   return(ret);
15532d56144Smickey 
15632d56144Smickey trunc:
15732d56144Smickey   return(-1);
15832d56144Smickey }
15932d56144Smickey 
16032d56144Smickey /****************************************************************************
16132d56144Smickey find a pointer to a netbios name
16232d56144Smickey ****************************************************************************/
name_ptr(const uchar * buf,int ofs,const uchar * maxbuf)16332d56144Smickey static const uchar *name_ptr(const uchar *buf,int ofs,const uchar *maxbuf)
16432d56144Smickey {
16532d56144Smickey   const uchar *p;
16632d56144Smickey   uchar c;
16732d56144Smickey 
16832d56144Smickey   p = buf+ofs;
16932d56144Smickey   if (p >= maxbuf)
17032d56144Smickey     return(NULL);	/* name goes past the end of the buffer */
17132d56144Smickey   TCHECK2(*p, 1);
17232d56144Smickey 
17332d56144Smickey   c = *p;
17432d56144Smickey 
17532d56144Smickey   /* XXX - this should use the same code that the DNS dissector does */
17632d56144Smickey   if ((c & 0xC0) == 0xC0)
17732d56144Smickey     {
17832d56144Smickey       uint16 l = RSVAL(buf, ofs) & 0x3FFF;
17932d56144Smickey       if (l == 0)
18032d56144Smickey 	{
18132d56144Smickey 	  /* We have a pointer that points to itself. */
18232d56144Smickey 	  return(NULL);
18332d56144Smickey 	}
18432d56144Smickey       p = buf + l;
18532d56144Smickey       if (p >= maxbuf)
18632d56144Smickey 	return(NULL);	/* name goes past the end of the buffer */
18732d56144Smickey       TCHECK2(*p, 1);
18832d56144Smickey       return(buf + l);
18932d56144Smickey     }
19032d56144Smickey   else
19132d56144Smickey     return(buf+ofs);
19232d56144Smickey 
19332d56144Smickey trunc:
19432d56144Smickey   return(NULL);	/* name goes past the end of the buffer */
19532d56144Smickey }
19632d56144Smickey 
19732d56144Smickey /****************************************************************************
19832d56144Smickey extract a netbios name from a buf
19932d56144Smickey ****************************************************************************/
name_extract(const uchar * buf,int ofs,const uchar * maxbuf,char * name)20032d56144Smickey static int name_extract(const uchar *buf,int ofs,const uchar *maxbuf,char *name)
20132d56144Smickey {
20232d56144Smickey   const uchar *p = name_ptr(buf,ofs,maxbuf);
20332d56144Smickey   if (p == NULL)
20432d56144Smickey     return(-1);	/* error (probably name going past end of buffer) */
2059dd8098fSmickey   *name = '\0';
20632d56144Smickey   return(name_interpret(p,maxbuf,name));
20732d56144Smickey }
20832d56144Smickey 
20932d56144Smickey 
21032d56144Smickey /****************************************************************************
21132d56144Smickey return the total storage length of a mangled name
21232d56144Smickey ****************************************************************************/
name_len(const unsigned char * s,const unsigned char * maxbuf)21332d56144Smickey static int name_len(const unsigned char *s, const unsigned char *maxbuf)
21432d56144Smickey {
21532d56144Smickey   const unsigned char *s0 = s;
21632d56144Smickey   unsigned char c;
21732d56144Smickey 
21832d56144Smickey   if (s >= maxbuf)
21932d56144Smickey     return(-1);	/* name goes past the end of the buffer */
22032d56144Smickey   TCHECK2(*s, 1);
22132d56144Smickey   c = *s;
22232d56144Smickey   if ((c & 0xC0) == 0xC0)
22332d56144Smickey     return(2);
22432d56144Smickey   while (*s)
22532d56144Smickey     {
22632d56144Smickey       if (s >= maxbuf)
22732d56144Smickey 	return(-1);	/* name goes past the end of the buffer */
22832d56144Smickey       TCHECK2(*s, 1);
22932d56144Smickey       s += (*s)+1;
23032d56144Smickey     }
23132d56144Smickey   return(PTR_DIFF(s,s0)+1);
23232d56144Smickey 
23332d56144Smickey trunc:
23432d56144Smickey   return(-1);	/* name goes past the end of the buffer */
23532d56144Smickey }
23632d56144Smickey 
name_type_str(int name_type)23732d56144Smickey static char *name_type_str(int name_type)
23832d56144Smickey {
23932d56144Smickey   static char *f = NULL;
24032d56144Smickey   switch (name_type) {
24132d56144Smickey   case 0:    f = "Workstation"; break;
24232d56144Smickey   case 0x03: f = "Client?"; break;
24332d56144Smickey   case 0x20: f = "Server"; break;
24432d56144Smickey   case 0x1d: f = "Master Browser"; break;
24532d56144Smickey   case 0x1b: f = "Domain Controller"; break;
24632d56144Smickey   case 0x1e: f = "Browser Server"; break;
24732d56144Smickey   default:   f = "Unknown"; break;
24832d56144Smickey   }
24932d56144Smickey   return(f);
25032d56144Smickey }
25132d56144Smickey 
write_bits(unsigned int val,char * fmt)25232d56144Smickey static void write_bits(unsigned int val,char *fmt)
25332d56144Smickey {
25432d56144Smickey   char *p = fmt;
25532d56144Smickey   int i=0;
25632d56144Smickey 
25732d56144Smickey   while ((p=strchr(fmt,'|'))) {
25832d56144Smickey     int l = PTR_DIFF(p,fmt);
25932d56144Smickey     if (l && (val & (1<<i)))
26032d56144Smickey       printf("%.*s ",l,fmt);
26132d56144Smickey     fmt = p+1;
26232d56144Smickey     i++;
26332d56144Smickey   }
26432d56144Smickey }
26532d56144Smickey 
26632d56144Smickey /* convert a unicode string */
unistr(const char * s,int * len)26732d56144Smickey static const char *unistr(const char *s, int *len)
26832d56144Smickey {
26932d56144Smickey 	static char buf[1000];
27032d56144Smickey 	int l=0;
27132d56144Smickey 	static int use_unicode = -1;
27232d56144Smickey 
27332d56144Smickey 	if (use_unicode == -1) {
27432d56144Smickey 		char *p = getenv("USE_UNICODE");
27532d56144Smickey 		if (p && (atoi(p) == 1))
27632d56144Smickey 			use_unicode = 1;
27732d56144Smickey 		else
27832d56144Smickey 			use_unicode = 0;
27932d56144Smickey 	}
28032d56144Smickey 
28132d56144Smickey 	/* maybe it isn't unicode - a cheap trick */
28232d56144Smickey 	if (!use_unicode || (s[0] && s[1])) {
28332d56144Smickey 		*len = strlen(s)+1;
28432d56144Smickey 		return s;
28532d56144Smickey 	}
28632d56144Smickey 
28732d56144Smickey 	*len = 0;
28832d56144Smickey 
28932d56144Smickey 	if (s[0] == 0 && s[1] != 0) {
29032d56144Smickey 		s++;
29132d56144Smickey 		*len = 1;
29232d56144Smickey 	}
29332d56144Smickey 
29432d56144Smickey 	while (l < (sizeof(buf)-1) && s[0] && s[1] == 0) {
29532d56144Smickey 		buf[l] = s[0];
29632d56144Smickey 		s += 2; l++;
29732d56144Smickey 		*len += 2;
29832d56144Smickey 	}
29932d56144Smickey 	buf[l] = 0;
30032d56144Smickey 	*len += 2;
30132d56144Smickey 	return buf;
30232d56144Smickey }
30332d56144Smickey 
fdata1(const uchar * buf,const char * fmt,const uchar * maxbuf)30432d56144Smickey static const uchar *fdata1(const uchar *buf, const char *fmt, const uchar *maxbuf)
30532d56144Smickey {
30632d56144Smickey   int reverse=0;
30732d56144Smickey   char *attrib_fmt = "READONLY|HIDDEN|SYSTEM|VOLUME|DIR|ARCHIVE|";
30832d56144Smickey   int len;
30932d56144Smickey 
31032d56144Smickey   while (*fmt && buf<maxbuf) {
31132d56144Smickey     switch (*fmt) {
31232d56144Smickey     case 'a':
31332d56144Smickey       write_bits(CVAL(buf,0),attrib_fmt);
31432d56144Smickey       buf++; fmt++;
31532d56144Smickey       break;
31632d56144Smickey 
31732d56144Smickey     case 'A':
31832d56144Smickey       write_bits(SVAL(buf,0),attrib_fmt);
31932d56144Smickey       buf+=2; fmt++;
32032d56144Smickey       break;
32132d56144Smickey 
32232d56144Smickey     case '{':
32332d56144Smickey       {
32432d56144Smickey 	char bitfmt[128];
32532d56144Smickey 	char *p = strchr(++fmt,'}');
3269f840a03Sderaadt 	strlcpy(bitfmt,fmt,sizeof(bitfmt));
32732d56144Smickey 	fmt = p+1;
32832d56144Smickey 	write_bits(CVAL(buf,0),bitfmt);
32932d56144Smickey 	buf++;
33032d56144Smickey 	break;
33132d56144Smickey       }
33232d56144Smickey 
33332d56144Smickey     case 'P':
33432d56144Smickey       {
33532d56144Smickey 	int l = atoi(fmt+1);
33632d56144Smickey 	buf += l;
33732d56144Smickey 	fmt++;
338*b963d3ddSmmcc 	while (isdigit((unsigned char)*fmt)) fmt++;
33932d56144Smickey 	break;
34032d56144Smickey       }
34132d56144Smickey     case 'r':
34232d56144Smickey       reverse = !reverse;
34332d56144Smickey       fmt++;
34432d56144Smickey       break;
34532d56144Smickey     case 'D':
34632d56144Smickey       {
34732d56144Smickey 	unsigned int x = reverse?RIVAL(buf,0):IVAL(buf,0);
34832d56144Smickey 	printf("%d (0x%x)",x, x);
34932d56144Smickey 	buf += 4;
35032d56144Smickey 	fmt++;
35132d56144Smickey 	break;
35232d56144Smickey       }
35332d56144Smickey     case 'L':
35432d56144Smickey       {
35532d56144Smickey 	unsigned int x1 = reverse?RIVAL(buf,0):IVAL(buf,0);
35632d56144Smickey 	unsigned int x2 = reverse?RIVAL(buf,4):IVAL(buf,4);
35732d56144Smickey 	if (x2) {
35832d56144Smickey 		printf("0x%08x:%08x",x2, x1);
35932d56144Smickey 	} else {
36032d56144Smickey 		printf("%d (0x%08x%08x)",x1, x2, x1);
36132d56144Smickey 	}
36232d56144Smickey 	buf += 8;
36332d56144Smickey 	fmt++;
36432d56144Smickey 	break;
36532d56144Smickey       }
36632d56144Smickey     case 'd':
36732d56144Smickey       {
36832d56144Smickey 	unsigned int x = reverse?RSVAL(buf,0):SVAL(buf,0);
3699dd8098fSmickey 	printf("%d",x);
37032d56144Smickey 	buf += 2;
37132d56144Smickey 	fmt++;
37232d56144Smickey 	break;
37332d56144Smickey       }
37432d56144Smickey     case 'W':
37532d56144Smickey       {
37632d56144Smickey 	unsigned int x = reverse?RIVAL(buf,0):IVAL(buf,0);
37732d56144Smickey 	printf("0x%X",x);
37832d56144Smickey 	buf += 4;
37932d56144Smickey 	fmt++;
38032d56144Smickey 	break;
38132d56144Smickey       }
38232d56144Smickey     case 'w':
38332d56144Smickey       {
38432d56144Smickey 	unsigned int x = reverse?RSVAL(buf,0):SVAL(buf,0);
38532d56144Smickey 	printf("0x%X",x);
38632d56144Smickey 	buf += 2;
38732d56144Smickey 	fmt++;
38832d56144Smickey 	break;
38932d56144Smickey       }
39032d56144Smickey     case 'B':
39132d56144Smickey       {
39232d56144Smickey 	unsigned int x = CVAL(buf,0);
39332d56144Smickey 	printf("0x%X",x);
39432d56144Smickey 	buf += 1;
39532d56144Smickey 	fmt++;
39632d56144Smickey 	break;
39732d56144Smickey       }
39832d56144Smickey     case 'b':
39932d56144Smickey       {
40032d56144Smickey 	unsigned int x = CVAL(buf,0);
4019dd8098fSmickey 	printf("%d",x); 			/* EMF - jesus, use B if you want hex */
40232d56144Smickey 	buf += 1;
40332d56144Smickey 	fmt++;
40432d56144Smickey 	break;
40532d56144Smickey       }
40632d56144Smickey     case 'S':
40732d56144Smickey       {
40832d56144Smickey 	      printf("%.*s",(int)PTR_DIFF(maxbuf,buf),unistr(buf, &len));
40932d56144Smickey 	      buf += len;
41032d56144Smickey 	      fmt++;
41132d56144Smickey 	      break;
41232d56144Smickey       }
41332d56144Smickey     case 'Z':
41432d56144Smickey       {
41532d56144Smickey 	if (*buf != 4 && *buf != 2)
4169dd8098fSmickey 	  printf("Error! ASCIIZ buffer of type %d (safety=%d) ",
41732d56144Smickey 		 *buf,(int)PTR_DIFF(maxbuf,buf));
41832d56144Smickey 	printf("%.*s",(int)PTR_DIFF(maxbuf,buf+1),unistr(buf+1, &len));
41932d56144Smickey 	buf += len+1;
42032d56144Smickey 	fmt++;
42132d56144Smickey 	break;
42232d56144Smickey       }
42332d56144Smickey     case 's':
42432d56144Smickey       {
42532d56144Smickey 	int l = atoi(fmt+1);
42632d56144Smickey 	printf("%-*.*s",l,l,buf);
42732d56144Smickey 	buf += l;
428*b963d3ddSmmcc 	fmt++; while (isdigit((unsigned char)*fmt)) fmt++;
42932d56144Smickey 	break;
43032d56144Smickey       }
43132d56144Smickey     case 'h':
43232d56144Smickey       {
43332d56144Smickey 	int l = atoi(fmt+1);
43432d56144Smickey 	while (l--) printf("%02x",*buf++);
435*b963d3ddSmmcc 	fmt++; while (isdigit((unsigned char)*fmt)) fmt++;
43632d56144Smickey 	break;
43732d56144Smickey       }
43832d56144Smickey     case 'n':
43932d56144Smickey       {
44032d56144Smickey 	int t = atoi(fmt+1);
44132d56144Smickey 	char nbuf[255];
44232d56144Smickey 	int name_type;
44332d56144Smickey 	int len;
44432d56144Smickey 	switch (t) {
44532d56144Smickey 	case 1:
44632d56144Smickey 	  name_type = name_extract(startbuf,PTR_DIFF(buf,startbuf),maxbuf,
44732d56144Smickey 		nbuf);
44832d56144Smickey 	  if (name_type < 0)
44932d56144Smickey 	    goto trunc;
45032d56144Smickey 	  len = name_len(buf,maxbuf);
45132d56144Smickey 	  if (len < 0)
45232d56144Smickey 	    goto trunc;
45332d56144Smickey 	  buf += len;
4549dd8098fSmickey 	  printf("%.15s type 0x%02X (%s)",
45532d56144Smickey 		 nbuf,name_type,name_type_str(name_type));
45632d56144Smickey 	  break;
45732d56144Smickey 	case 2:
45832d56144Smickey 	  name_type = buf[15];
4599dd8098fSmickey 	  printf("%.15s type 0x%02X (%s)",
46032d56144Smickey 		 buf,name_type,name_type_str(name_type));
46132d56144Smickey 	  buf += 16;
46232d56144Smickey 	  break;
46332d56144Smickey 	}
464*b963d3ddSmmcc 	fmt++; while (isdigit((unsigned char)*fmt)) fmt++;
46532d56144Smickey 	break;
46632d56144Smickey       }
46732d56144Smickey     case 'T':
46832d56144Smickey       {
46932d56144Smickey 	time_t t;
47032d56144Smickey 	int x = IVAL(buf,0);
47132d56144Smickey 	switch (atoi(fmt+1)) {
47232d56144Smickey 	case 1:
47332d56144Smickey 	  if (x==0 || x==-1 || x==0xFFFFFFFF)
47432d56144Smickey 	    t = 0;
47532d56144Smickey 	  else
47632d56144Smickey 	    t = make_unix_date(buf);
47732d56144Smickey 	  buf+=4;
47832d56144Smickey 	  break;
47932d56144Smickey 	case 2:
48032d56144Smickey 	  if (x==0 || x==-1 || x==0xFFFFFFFF)
48132d56144Smickey 	    t = 0;
48232d56144Smickey 	  else
48332d56144Smickey 	    t = make_unix_date2(buf);
48432d56144Smickey 	  buf+=4;
48532d56144Smickey 	  break;
48632d56144Smickey 	case 3:
48732d56144Smickey 	  t = interpret_long_date(buf);
48832d56144Smickey 	  buf+=8;
48932d56144Smickey 	  break;
49066cde72eSray 	default:
4911e03ecd6Sray 	  error("fdata1: invalid fmt: %s", fmt);
49232d56144Smickey 	}
4939dd8098fSmickey 	printf("%s",t?asctime(localtime(&t)):"NULL ");
494*b963d3ddSmmcc 	fmt++; while (isdigit((unsigned char)*fmt)) fmt++;
49532d56144Smickey 	break;
49632d56144Smickey       }
49732d56144Smickey     default:
49832d56144Smickey       putchar(*fmt);
49932d56144Smickey       fmt++;
50032d56144Smickey       break;
50132d56144Smickey     }
50232d56144Smickey   }
50332d56144Smickey 
50432d56144Smickey   if (buf>=maxbuf && *fmt)
5059dd8098fSmickey     printf("END OF BUFFER ");
50632d56144Smickey 
50732d56144Smickey   return(buf);
50832d56144Smickey 
50932d56144Smickey trunc:
5109dd8098fSmickey   printf("WARNING: Short packet. Try increasing the snap length ");
51132d56144Smickey   return(NULL);
51232d56144Smickey }
51332d56144Smickey 
fdata(const uchar * buf,const char * fmt,const uchar * maxbuf)51432d56144Smickey const uchar *fdata(const uchar *buf, const char *fmt, const uchar *maxbuf)
51532d56144Smickey {
51632d56144Smickey   static int depth=0;
51732d56144Smickey   char s[128];
51832d56144Smickey   char *p;
51932d56144Smickey 
52032d56144Smickey   while (*fmt) {
52132d56144Smickey     switch (*fmt) {
52232d56144Smickey     case '*':
52332d56144Smickey       fmt++;
52432d56144Smickey       while (buf < maxbuf) {
52532d56144Smickey 	const uchar *buf2;
52632d56144Smickey 	depth++;
52732d56144Smickey 	buf2 = fdata(buf,fmt,maxbuf);
52832d56144Smickey 	depth--;
52932d56144Smickey 	if (buf2 == buf) return(buf);
53032d56144Smickey 	buf = buf2;
53132d56144Smickey       }
53232d56144Smickey       break;
53332d56144Smickey 
53432d56144Smickey     case '|':
53532d56144Smickey       fmt++;
53632d56144Smickey       if (buf>=maxbuf) return(buf);
53732d56144Smickey       break;
53832d56144Smickey 
53932d56144Smickey     case '%':
54032d56144Smickey       fmt++;
54132d56144Smickey       buf=maxbuf;
54232d56144Smickey       break;
54332d56144Smickey 
54432d56144Smickey     case '#':
54532d56144Smickey       fmt++;
54632d56144Smickey       return(buf);
54732d56144Smickey       break;
54832d56144Smickey 
54932d56144Smickey     case '[':
55032d56144Smickey       fmt++;
55132d56144Smickey       if (buf>=maxbuf) return(buf);
55232d56144Smickey       memset(s, 0, sizeof(s));
55332d56144Smickey       p = strchr(fmt,']');
5549f840a03Sderaadt       strncpy(s,fmt,p-fmt);	/* XXX? */
55532d56144Smickey       fmt = p+1;
55632d56144Smickey       buf = fdata1(buf,s,maxbuf);
55732d56144Smickey       if (buf == NULL)
55832d56144Smickey 	return(NULL);
55932d56144Smickey       break;
56032d56144Smickey 
56132d56144Smickey     default:
56232d56144Smickey       putchar(*fmt); fmt++;
56332d56144Smickey       fflush(stdout);
56432d56144Smickey       break;
56532d56144Smickey     }
56632d56144Smickey   }
56732d56144Smickey   if (!depth && buf<maxbuf) {
56832d56144Smickey     int len = PTR_DIFF(maxbuf,buf);
5699dd8098fSmickey     printf("(%d data bytes)",len);
5709dd8098fSmickey     /* EMF -  use -X flag if you want this verbosity
5719dd8098fSmickey      * print_data(buf,len);
5729dd8098fSmickey      */
57332d56144Smickey     return(buf+len);
57432d56144Smickey   }
57532d56144Smickey   return(buf);
57632d56144Smickey }
57732d56144Smickey 
57832d56144Smickey typedef struct
57932d56144Smickey {
58032d56144Smickey   char *name;
58132d56144Smickey   int code;
58232d56144Smickey   char *message;
58332d56144Smickey } err_code_struct;
58432d56144Smickey 
58532d56144Smickey /* Dos Error Messages */
58632d56144Smickey static err_code_struct dos_msgs[] = {
58732d56144Smickey   {"ERRbadfunc",1,"Invalid function."},
58832d56144Smickey   {"ERRbadfile",2,"File not found."},
58932d56144Smickey   {"ERRbadpath",3,"Directory invalid."},
59032d56144Smickey   {"ERRnofids",4,"No file descriptors available"},
59132d56144Smickey   {"ERRnoaccess",5,"Access denied."},
59232d56144Smickey   {"ERRbadfid",6,"Invalid file handle."},
59332d56144Smickey   {"ERRbadmcb",7,"Memory control blocks destroyed."},
59432d56144Smickey   {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
59532d56144Smickey   {"ERRbadmem",9,"Invalid memory block address."},
59632d56144Smickey   {"ERRbadenv",10,"Invalid environment."},
59732d56144Smickey   {"ERRbadformat",11,"Invalid format."},
59832d56144Smickey   {"ERRbadaccess",12,"Invalid open mode."},
59932d56144Smickey   {"ERRbaddata",13,"Invalid data."},
60032d56144Smickey   {"ERR",14,"reserved."},
60132d56144Smickey   {"ERRbaddrive",15,"Invalid drive specified."},
60232d56144Smickey   {"ERRremcd",16,"A Delete Directory request attempted  to  remove  the  server's  current directory."},
60332d56144Smickey   {"ERRdiffdevice",17,"Not same device."},
60432d56144Smickey   {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
60532d56144Smickey   {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing  FIDs  on the file."},
60632d56144Smickey   {"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."},
60732d56144Smickey   {"ERRfilexists",80,"The file named in a Create Directory, Make  New  File  or  Link  request already exists."},
60832d56144Smickey   {"ERRbadpipe",230,"Pipe invalid."},
60932d56144Smickey   {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
61032d56144Smickey   {"ERRpipeclosing",232,"Pipe close in progress."},
61132d56144Smickey   {"ERRnotconnected",233,"No process on other end of pipe."},
61232d56144Smickey   {"ERRmoredata",234,"There is more data to be returned."},
61332d56144Smickey   {NULL,-1,NULL}};
61432d56144Smickey 
61532d56144Smickey /* Server Error Messages */
61632d56144Smickey err_code_struct server_msgs[] = {
61732d56144Smickey   {"ERRerror",1,"Non-specific error code."},
61832d56144Smickey   {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
61932d56144Smickey   {"ERRbadtype",3,"reserved."},
62032d56144Smickey   {"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."},
62132d56144Smickey   {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
62232d56144Smickey   {"ERRinvnetname",6,"Invalid network name in tree connect."},
62332d56144Smickey   {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or  non-printer request made to printer connection."},
62432d56144Smickey   {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
62532d56144Smickey   {"ERRqtoobig",50,"Print queue full -- no space."},
62632d56144Smickey   {"ERRqeof",51,"EOF on print queue dump."},
62732d56144Smickey   {"ERRinvpfid",52,"Invalid print file FID."},
62832d56144Smickey   {"ERRsmbcmd",64,"The server did not recognize the command received."},
62932d56144Smickey   {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
63032d56144Smickey   {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid  combination of values."},
63132d56144Smickey   {"ERRreserved",68,"reserved."},
63232d56144Smickey   {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination.  The server cannot set the requested attribute."},
63332d56144Smickey   {"ERRreserved",70,"reserved."},
63432d56144Smickey   {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
63532d56144Smickey   {"ERRpaused",81,"Server is paused."},
63632d56144Smickey   {"ERRmsgoff",82,"Not receiving messages."},
63732d56144Smickey   {"ERRnoroom",83,"No room to buffer message."},
63832d56144Smickey   {"ERRrmuns",87,"Too many remote user names."},
63932d56144Smickey   {"ERRtimeout",88,"Operation timed out."},
64032d56144Smickey   {"ERRnoresource",89,"No resources currently available for request."},
64132d56144Smickey   {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
64232d56144Smickey   {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
64332d56144Smickey   {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
64432d56144Smickey   {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
64532d56144Smickey   {"ERRcontmpx",252,"Continue in MPX mode."},
64632d56144Smickey   {"ERRreserved",253,"reserved."},
64732d56144Smickey   {"ERRreserved",254,"reserved."},
64832d56144Smickey   {"ERRnosupport",0xFFFF,"Function not supported."},
64932d56144Smickey   {NULL,-1,NULL}};
65032d56144Smickey 
65132d56144Smickey /* Hard Error Messages */
65232d56144Smickey err_code_struct hard_msgs[] = {
65332d56144Smickey   {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
65432d56144Smickey   {"ERRbadunit",20,"Unknown unit."},
65532d56144Smickey   {"ERRnotready",21,"Drive not ready."},
65632d56144Smickey   {"ERRbadcmd",22,"Unknown command."},
65732d56144Smickey   {"ERRdata",23,"Data error (CRC)."},
65832d56144Smickey   {"ERRbadreq",24,"Bad request structure length."},
65932d56144Smickey   {"ERRseek",25 ,"Seek error."},
66032d56144Smickey   {"ERRbadmedia",26,"Unknown media type."},
66132d56144Smickey   {"ERRbadsector",27,"Sector not found."},
66232d56144Smickey   {"ERRnopaper",28,"Printer out of paper."},
66332d56144Smickey   {"ERRwrite",29,"Write fault."},
66432d56144Smickey   {"ERRread",30,"Read fault."},
66532d56144Smickey   {"ERRgeneral",31,"General failure."},
66632d56144Smickey   {"ERRbadshare",32,"A open conflicts with an existing open."},
66732d56144Smickey   {"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."},
66832d56144Smickey   {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
66932d56144Smickey   {"ERRFCBUnavail",35,"No FCBs are available to process request."},
67032d56144Smickey   {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
67132d56144Smickey   {NULL,-1,NULL}};
67232d56144Smickey 
67332d56144Smickey 
67432d56144Smickey static struct
67532d56144Smickey {
67632d56144Smickey   int code;
67732d56144Smickey   char *class;
67832d56144Smickey   err_code_struct *err_msgs;
67932d56144Smickey } err_classes[] = {
68032d56144Smickey   {0,"SUCCESS",NULL},
68132d56144Smickey   {0x01,"ERRDOS",dos_msgs},
68232d56144Smickey   {0x02,"ERRSRV",server_msgs},
68332d56144Smickey   {0x03,"ERRHRD",hard_msgs},
68432d56144Smickey   {0x04,"ERRXOS",NULL},
68532d56144Smickey   {0xE1,"ERRRMX1",NULL},
68632d56144Smickey   {0xE2,"ERRRMX2",NULL},
68732d56144Smickey   {0xE3,"ERRRMX3",NULL},
68832d56144Smickey   {0xFF,"ERRCMD",NULL},
68932d56144Smickey   {-1,NULL,NULL}};
69032d56144Smickey 
69132d56144Smickey 
69232d56144Smickey /****************************************************************************
69332d56144Smickey return a SMB error string from a SMB buffer
69432d56144Smickey ****************************************************************************/
smb_errstr(int class,int num)69532d56144Smickey char *smb_errstr(int class,int num)
69632d56144Smickey {
69732d56144Smickey   static char ret[128];
69832d56144Smickey   int i,j;
69932d56144Smickey 
70032d56144Smickey   ret[0]=0;
70132d56144Smickey 
70232d56144Smickey   for (i=0;err_classes[i].class;i++)
70332d56144Smickey     if (err_classes[i].code == class)
70432d56144Smickey       {
70532d56144Smickey 	if (err_classes[i].err_msgs)
70632d56144Smickey 	  {
70732d56144Smickey 	    err_code_struct *err = err_classes[i].err_msgs;
70832d56144Smickey 	    for (j=0;err[j].name;j++)
70932d56144Smickey 	      if (num == err[j].code)
71032d56144Smickey 		{
7119f840a03Sderaadt 		  snprintf(ret, sizeof(ret), "%s - %s (%s)",
7129f840a03Sderaadt 		    err_classes[i].class,
71332d56144Smickey 		    err[j].name,err[j].message);
71432d56144Smickey 		  return ret;
71532d56144Smickey 		}
71632d56144Smickey 	  }
71732d56144Smickey 
71832d56144Smickey 	snprintf(ret,sizeof(ret),"%s - %d",err_classes[i].class,num);
71932d56144Smickey 	return ret;
72032d56144Smickey       }
72132d56144Smickey 
72232d56144Smickey   snprintf(ret,sizeof(ret),"ERROR: Unknown error (%d,%d)",class,num);
72332d56144Smickey   return(ret);
72432d56144Smickey }
725