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