xref: /freebsd/contrib/tcpdump/smbutil.c (revision 9afd0c2902649a0007676d044c6ae7fa099e8cf3)
1b0453382SBill Fenner /*
2a90e161bSBill Fenner  * Copyright (C) Andrew Tridgell 1995-1999
3a90e161bSBill Fenner  *
4a90e161bSBill Fenner  * This software may be distributed either under the terms of the
5a90e161bSBill Fenner  * BSD-style license that accompanies tcpdump or the GNU GPL version 2
6a90e161bSBill Fenner  * or later
7a90e161bSBill Fenner  */
8b0453382SBill Fenner 
9b0453382SBill Fenner #ifdef HAVE_CONFIG_H
10b0453382SBill Fenner #include "config.h"
11b0453382SBill Fenner #endif
12b0453382SBill Fenner 
13b0453382SBill Fenner #ifndef lint
14b0453382SBill Fenner static const char rcsid[] =
159afd0c29SBill Fenner      "@(#) $Header: /tcpdump/master/tcpdump/smbutil.c,v 1.18.2.3 2002/07/10 07:29:23 guy Exp $";
16b0453382SBill Fenner #endif
17b0453382SBill Fenner 
18b0453382SBill Fenner #include <sys/param.h>
19b0453382SBill Fenner #include <sys/time.h>
20b0453382SBill Fenner #include <sys/types.h>
21b0453382SBill Fenner #include <sys/socket.h>
22b0453382SBill Fenner 
23b0453382SBill Fenner #include <netinet/in.h>
24b0453382SBill Fenner 
25b0453382SBill Fenner #include <ctype.h>
26b0453382SBill Fenner #include <stdio.h>
27b0453382SBill Fenner #include <stdlib.h>
28b0453382SBill Fenner #include <string.h>
299afd0c29SBill Fenner #ifdef TIME_WITH_SYS_TIME
30685295f4SBill Fenner #include <time.h>
319afd0c29SBill Fenner #endif
32b0453382SBill Fenner 
33b0453382SBill Fenner #include "interface.h"
34a90e161bSBill Fenner #include "extract.h"
35b0453382SBill Fenner #include "smb.h"
36b0453382SBill Fenner 
37a90e161bSBill Fenner extern const u_char *startbuf;
38b0453382SBill Fenner 
39a90e161bSBill Fenner /*
40a90e161bSBill Fenner  * interpret a 32 bit dos packed date/time to some parameters
41a90e161bSBill Fenner  */
42a90e161bSBill Fenner static void
43a90e161bSBill Fenner interpret_dos_date(u_int32_t date, struct tm *tp)
44b0453382SBill Fenner {
45a90e161bSBill Fenner     u_int32_t p0, p1, p2, p3;
46b0453382SBill Fenner 
47a90e161bSBill Fenner     p0 = date & 0xFF;
48a90e161bSBill Fenner     p1 = ((date & 0xFF00) >> 8) & 0xFF;
49a90e161bSBill Fenner     p2 = ((date & 0xFF0000) >> 16) & 0xFF;
50a90e161bSBill Fenner     p3 = ((date & 0xFF000000) >> 24) & 0xFF;
51b0453382SBill Fenner 
52a90e161bSBill Fenner     tp->tm_sec = 2 * (p0 & 0x1F);
53a90e161bSBill Fenner     tp->tm_min = ((p0 >> 5) & 0xFF) + ((p1 & 0x7) << 3);
54a90e161bSBill Fenner     tp->tm_hour = (p1 >> 3) & 0xFF;
55a90e161bSBill Fenner     tp->tm_mday = (p2 & 0x1F);
56a90e161bSBill Fenner     tp->tm_mon = ((p2 >> 5) & 0xFF) + ((p3 & 0x1) << 3) - 1;
57a90e161bSBill Fenner     tp->tm_year = ((p3 >> 1) & 0xFF) + 80;
58b0453382SBill Fenner }
59b0453382SBill Fenner 
60a90e161bSBill Fenner /*
61a90e161bSBill Fenner  * common portion:
62a90e161bSBill Fenner  * create a unix date from a dos date
63a90e161bSBill Fenner  */
64a90e161bSBill Fenner static time_t
65a90e161bSBill Fenner int_unix_date(u_int32_t dos_date)
66b0453382SBill Fenner {
67b0453382SBill Fenner     struct tm t;
68b0453382SBill Fenner 
69a90e161bSBill Fenner     if (dos_date == 0)
70a90e161bSBill Fenner 	return(0);
71b0453382SBill Fenner 
72a90e161bSBill Fenner     interpret_dos_date(dos_date, &t);
73b0453382SBill Fenner     t.tm_wday = 1;
74b0453382SBill Fenner     t.tm_yday = 1;
75b0453382SBill Fenner     t.tm_isdst = 0;
76b0453382SBill Fenner 
77b0453382SBill Fenner     return (mktime(&t));
78b0453382SBill Fenner }
79b0453382SBill Fenner 
80a90e161bSBill Fenner /*
81a90e161bSBill Fenner  * create a unix date from a dos date
82a90e161bSBill Fenner  * in network byte order
83a90e161bSBill Fenner  */
84a90e161bSBill Fenner static time_t
85a90e161bSBill Fenner make_unix_date(const u_char *date_ptr)
86b0453382SBill Fenner {
87a90e161bSBill Fenner     u_int32_t dos_date = 0;
88b0453382SBill Fenner 
89a90e161bSBill Fenner     dos_date = EXTRACT_LE_32BITS(date_ptr);
90b0453382SBill Fenner 
91a90e161bSBill Fenner     return int_unix_date(dos_date);
92b0453382SBill Fenner }
93b0453382SBill Fenner 
94a90e161bSBill Fenner /*
95a90e161bSBill Fenner  * create a unix date from a dos date
96a90e161bSBill Fenner  * in halfword-swapped network byte order!
97a90e161bSBill Fenner  */
98a90e161bSBill Fenner static time_t
99a90e161bSBill Fenner make_unix_date2(const u_char *date_ptr)
100a90e161bSBill Fenner {
101a90e161bSBill Fenner     u_int32_t x, x2;
102a90e161bSBill Fenner 
103a90e161bSBill Fenner     x = EXTRACT_LE_32BITS(date_ptr);
104a90e161bSBill Fenner     x2 = ((x & 0xFFFF) << 16) | ((x & 0xFFFF0000) >> 16);
105a90e161bSBill Fenner     return int_unix_date(x2);
106a90e161bSBill Fenner }
107a90e161bSBill Fenner 
108a90e161bSBill Fenner /*
109a90e161bSBill Fenner  * interpret an 8 byte "filetime" structure to a time_t
110a90e161bSBill Fenner  * It's originally in "100ns units since jan 1st 1601"
111a90e161bSBill Fenner  */
112a90e161bSBill Fenner static time_t
113a90e161bSBill Fenner interpret_long_date(const u_char *p)
114b0453382SBill Fenner {
115b0453382SBill Fenner     double d;
116b0453382SBill Fenner     time_t ret;
117b0453382SBill Fenner 
118a90e161bSBill Fenner     TCHECK2(p[4], 4);
119a90e161bSBill Fenner 
120b0453382SBill Fenner     /* this gives us seconds since jan 1st 1601 (approx) */
121a90e161bSBill Fenner     d = (EXTRACT_LE_32BITS(p + 4) * 256.0 + p[3]) * (1.0e-7 * (1 << 24));
122b0453382SBill Fenner 
123b0453382SBill Fenner     /* now adjust by 369 years to make the secs since 1970 */
124b0453382SBill Fenner     d -= 369.0 * 365.25 * 24 * 60 * 60;
125b0453382SBill Fenner 
126b0453382SBill Fenner     /* and a fudge factor as we got it wrong by a few days */
127b0453382SBill Fenner     d += (3 * 24 * 60 * 60 + 6 * 60 * 60 + 2);
128b0453382SBill Fenner 
129b0453382SBill Fenner     if (d < 0)
130b0453382SBill Fenner 	return(0);
131b0453382SBill Fenner 
132b0453382SBill Fenner     ret = (time_t)d;
133b0453382SBill Fenner 
134b0453382SBill Fenner     return(ret);
135a90e161bSBill Fenner trunc:
136a90e161bSBill Fenner     return(0);
137b0453382SBill Fenner }
138b0453382SBill Fenner 
139a90e161bSBill Fenner /*
140a90e161bSBill Fenner  * interpret the weird netbios "name". Return the name type, or -1 if
141a90e161bSBill Fenner  * we run past the end of the buffer
142a90e161bSBill Fenner  */
143a90e161bSBill Fenner static int
144a90e161bSBill Fenner name_interpret(const u_char *in, const u_char *maxbuf, char *out)
145b0453382SBill Fenner {
146b0453382SBill Fenner     int ret;
147685295f4SBill Fenner     int len;
148685295f4SBill Fenner 
149685295f4SBill Fenner     if (in >= maxbuf)
150685295f4SBill Fenner 	return(-1);	/* name goes past the end of the buffer */
151685295f4SBill Fenner     TCHECK2(*in, 1);
152685295f4SBill Fenner     len = (*in++) / 2;
153b0453382SBill Fenner 
154b0453382SBill Fenner     *out=0;
155b0453382SBill Fenner 
156a90e161bSBill Fenner     if (len > 30 || len < 1)
157a90e161bSBill Fenner 	return(0);
158b0453382SBill Fenner 
159a90e161bSBill Fenner     while (len--) {
160a90e161bSBill Fenner 	TCHECK2(*in, 2);
161685295f4SBill Fenner 	if (in + 1 >= maxbuf)
162685295f4SBill Fenner 	    return(-1);	/* name goes past the end of the buffer */
163b0453382SBill Fenner 	if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
164b0453382SBill Fenner 	    *out = 0;
165b0453382SBill Fenner 	    return(0);
166b0453382SBill Fenner 	}
167b0453382SBill Fenner 	*out = ((in[0] - 'A') << 4) + (in[1] - 'A');
168b0453382SBill Fenner 	in += 2;
169b0453382SBill Fenner 	out++;
170b0453382SBill Fenner     }
171b0453382SBill Fenner     *out = 0;
172b0453382SBill Fenner     ret = out[-1];
173b0453382SBill Fenner 
174b0453382SBill Fenner     return(ret);
175685295f4SBill Fenner 
176685295f4SBill Fenner trunc:
177685295f4SBill Fenner     return(-1);
178b0453382SBill Fenner }
179b0453382SBill Fenner 
180a90e161bSBill Fenner /*
181a90e161bSBill Fenner  * find a pointer to a netbios name
182a90e161bSBill Fenner  */
183a90e161bSBill Fenner static const u_char *
184a90e161bSBill Fenner name_ptr(const u_char *buf, int ofs, const u_char *maxbuf)
185b0453382SBill Fenner {
186a90e161bSBill Fenner     const u_char *p;
187a90e161bSBill Fenner     u_char c;
188b0453382SBill Fenner 
189685295f4SBill Fenner     p = buf + ofs;
190685295f4SBill Fenner     if (p >= maxbuf)
191685295f4SBill Fenner 	return(NULL);	/* name goes past the end of the buffer */
192685295f4SBill Fenner     TCHECK2(*p, 1);
193685295f4SBill Fenner 
194685295f4SBill Fenner     c = *p;
195685295f4SBill Fenner 
196685295f4SBill Fenner     /* XXX - this should use the same code that the DNS dissector does */
197a90e161bSBill Fenner     if ((c & 0xC0) == 0xC0) {
198a90e161bSBill Fenner 	u_int16_t l = EXTRACT_16BITS(buf + ofs) & 0x3FFF;
199a90e161bSBill Fenner 	if (l == 0) {
200685295f4SBill Fenner 	    /* We have a pointer that points to itself. */
201685295f4SBill Fenner 	    return(NULL);
202685295f4SBill Fenner 	}
203685295f4SBill Fenner 	p = buf + l;
204685295f4SBill Fenner 	if (p >= maxbuf)
205685295f4SBill Fenner 	    return(NULL);	/* name goes past the end of the buffer */
206685295f4SBill Fenner 	TCHECK2(*p, 1);
207b0453382SBill Fenner 	return(buf + l);
208a90e161bSBill Fenner     } else
209b0453382SBill Fenner 	return(buf + ofs);
210685295f4SBill Fenner 
211685295f4SBill Fenner trunc:
212685295f4SBill Fenner     return(NULL);	/* name goes past the end of the buffer */
213b0453382SBill Fenner }
214b0453382SBill Fenner 
215a90e161bSBill Fenner /*
216a90e161bSBill Fenner  * extract a netbios name from a buf
217a90e161bSBill Fenner  */
218a90e161bSBill Fenner static int
219a90e161bSBill Fenner name_extract(const u_char *buf, int ofs, const u_char *maxbuf, char *name)
220b0453382SBill Fenner {
221a90e161bSBill Fenner     const u_char *p = name_ptr(buf, ofs, maxbuf);
222685295f4SBill Fenner     if (p == NULL)
223685295f4SBill Fenner 	return(-1);	/* error (probably name going past end of buffer) */
224a90e161bSBill Fenner     name[0] = '\0';
225685295f4SBill Fenner     return(name_interpret(p, maxbuf, name));
226b0453382SBill Fenner }
227b0453382SBill Fenner 
228b0453382SBill Fenner 
229a90e161bSBill Fenner /*
230a90e161bSBill Fenner  * return the total storage length of a mangled name
231a90e161bSBill Fenner  */
232a90e161bSBill Fenner static int
233a90e161bSBill Fenner name_len(const unsigned char *s, const unsigned char *maxbuf)
234b0453382SBill Fenner {
235685295f4SBill Fenner     const unsigned char *s0 = s;
236685295f4SBill Fenner     unsigned char c;
237685295f4SBill Fenner 
238685295f4SBill Fenner     if (s >= maxbuf)
239685295f4SBill Fenner 	return(-1);	/* name goes past the end of the buffer */
240685295f4SBill Fenner     TCHECK2(*s, 1);
241685295f4SBill Fenner     c = *s;
242b0453382SBill Fenner     if ((c & 0xC0) == 0xC0)
243b0453382SBill Fenner 	return(2);
244a90e161bSBill Fenner     while (*s) {
245685295f4SBill Fenner 	if (s >= maxbuf)
246685295f4SBill Fenner 	    return(-1);	/* name goes past the end of the buffer */
247685295f4SBill Fenner 	TCHECK2(*s, 1);
248685295f4SBill Fenner 	s += (*s) + 1;
249685295f4SBill Fenner     }
250b0453382SBill Fenner     return(PTR_DIFF(s, s0) + 1);
251685295f4SBill Fenner 
252685295f4SBill Fenner trunc:
253685295f4SBill Fenner     return(-1);	/* name goes past the end of the buffer */
254b0453382SBill Fenner }
255b0453382SBill Fenner 
256a90e161bSBill Fenner static void
257a90e161bSBill Fenner print_asc(const unsigned char *buf, int len)
258b0453382SBill Fenner {
259b0453382SBill Fenner     int i;
260b0453382SBill Fenner     for (i = 0; i < len; i++)
261a90e161bSBill Fenner 	safeputchar(buf[i]);
262b0453382SBill Fenner }
263b0453382SBill Fenner 
264a90e161bSBill Fenner static char *
265a90e161bSBill Fenner name_type_str(int name_type)
266b0453382SBill Fenner {
267a90e161bSBill Fenner     char *f = NULL;
268a90e161bSBill Fenner 
269b0453382SBill Fenner     switch (name_type) {
270b0453382SBill Fenner     case 0:    f = "Workstation"; break;
271b0453382SBill Fenner     case 0x03: f = "Client?"; break;
272b0453382SBill Fenner     case 0x20: f = "Server"; break;
273b0453382SBill Fenner     case 0x1d: f = "Master Browser"; break;
274b0453382SBill Fenner     case 0x1b: f = "Domain Controller"; break;
275b0453382SBill Fenner     case 0x1e: f = "Browser Server"; break;
276b0453382SBill Fenner     default:   f = "Unknown"; break;
277b0453382SBill Fenner     }
278b0453382SBill Fenner     return(f);
279b0453382SBill Fenner }
280b0453382SBill Fenner 
281a90e161bSBill Fenner void
282a90e161bSBill Fenner print_data(const unsigned char *buf, int len)
283b0453382SBill Fenner {
284b0453382SBill Fenner     int i = 0;
285a90e161bSBill Fenner 
286a90e161bSBill Fenner     if (len <= 0)
287a90e161bSBill Fenner 	return;
288b0453382SBill Fenner     printf("[%03X] ", i);
289a90e161bSBill Fenner     for (i = 0; i < len; /*nothing*/) {
290a90e161bSBill Fenner 	printf("%02X ", buf[i] & 0xff);
291b0453382SBill Fenner 	i++;
292a90e161bSBill Fenner 	if (i%8 == 0)
293a90e161bSBill Fenner 	    printf(" ");
294b0453382SBill Fenner 	if (i % 16 == 0) {
295a90e161bSBill Fenner 	    print_asc(&buf[i - 16], 8);
296a90e161bSBill Fenner 	    printf(" ");
297a90e161bSBill Fenner 	    print_asc(&buf[i - 8], 8);
298a90e161bSBill Fenner 	    printf("\n");
299a90e161bSBill Fenner 	    if (i < len)
300a90e161bSBill Fenner 		printf("[%03X] ", i);
301b0453382SBill Fenner 	}
302b0453382SBill Fenner     }
303b0453382SBill Fenner     if (i % 16) {
304b0453382SBill Fenner 	int n;
305b0453382SBill Fenner 
306b0453382SBill Fenner 	n = 16 - (i % 16);
307b0453382SBill Fenner 	printf(" ");
308a90e161bSBill Fenner 	if (n>8)
309a90e161bSBill Fenner 	    printf(" ");
310a90e161bSBill Fenner 	while (n--)
311a90e161bSBill Fenner 	    printf("   ");
312b0453382SBill Fenner 
313a90e161bSBill Fenner 	n = SMBMIN(8, i % 16);
314a90e161bSBill Fenner 	print_asc(&buf[i - (i % 16)], n);
315a90e161bSBill Fenner 	printf(" ");
316b0453382SBill Fenner 	n = (i % 16) - n;
317a90e161bSBill Fenner 	if (n > 0)
318a90e161bSBill Fenner 	    print_asc(&buf[i - n], n);
319b0453382SBill Fenner 	printf("\n");
320b0453382SBill Fenner     }
321b0453382SBill Fenner }
322b0453382SBill Fenner 
323b0453382SBill Fenner 
324a90e161bSBill Fenner static void
325a90e161bSBill Fenner write_bits(unsigned int val, char *fmt)
326b0453382SBill Fenner {
327b0453382SBill Fenner     char *p = fmt;
328b0453382SBill Fenner     int i = 0;
329b0453382SBill Fenner 
330b0453382SBill Fenner     while ((p = strchr(fmt, '|'))) {
331a90e161bSBill Fenner 	size_t l = PTR_DIFF(p, fmt);
332b0453382SBill Fenner 	if (l && (val & (1 << i)))
333a90e161bSBill Fenner 	    printf("%.*s ", (int)l, fmt);
334b0453382SBill Fenner 	fmt = p + 1;
335b0453382SBill Fenner 	i++;
336b0453382SBill Fenner     }
337b0453382SBill Fenner }
338b0453382SBill Fenner 
339a90e161bSBill Fenner /* convert a UCS2 string into iso-8859-1 string */
340a90e161bSBill Fenner static const char *
3419afd0c29SBill Fenner unistr(const u_char *s, int *len)
342b0453382SBill Fenner {
343b0453382SBill Fenner     static char buf[1000];
344b0453382SBill Fenner     int l=0;
345b0453382SBill Fenner     static int use_unicode = -1;
346b0453382SBill Fenner 
347b0453382SBill Fenner     if (use_unicode == -1) {
348b0453382SBill Fenner 	char *p = getenv("USE_UNICODE");
349b0453382SBill Fenner 	if (p && (atoi(p) == 1))
350b0453382SBill Fenner 	    use_unicode = 1;
351b0453382SBill Fenner 	else
352b0453382SBill Fenner 	    use_unicode = 0;
353b0453382SBill Fenner     }
354b0453382SBill Fenner 
355b0453382SBill Fenner     /* maybe it isn't unicode - a cheap trick */
356b0453382SBill Fenner     if (!use_unicode || (s[0] && s[1])) {
3579afd0c29SBill Fenner 	*len = strlen((const char *)s) + 1;
3589afd0c29SBill Fenner 	return (const char *)s;
359b0453382SBill Fenner     }
360b0453382SBill Fenner 
361b0453382SBill Fenner     *len = 0;
362b0453382SBill Fenner 
363b0453382SBill Fenner     if (s[0] == 0 && s[1] != 0) {
364b0453382SBill Fenner 	s++;
365b0453382SBill Fenner 	*len = 1;
366b0453382SBill Fenner     }
367b0453382SBill Fenner 
368b0453382SBill Fenner     while (l < (sizeof(buf) - 1) && s[0] && s[1] == 0) {
369b0453382SBill Fenner 	buf[l] = s[0];
370a90e161bSBill Fenner 	s += 2;
371a90e161bSBill Fenner 	l++;
372b0453382SBill Fenner 	*len += 2;
373b0453382SBill Fenner     }
374b0453382SBill Fenner     buf[l] = 0;
375b0453382SBill Fenner     *len += 2;
376b0453382SBill Fenner     return buf;
377b0453382SBill Fenner }
378b0453382SBill Fenner 
379a90e161bSBill Fenner static const u_char *
380a90e161bSBill Fenner smb_fdata1(const u_char *buf, const char *fmt, const u_char *maxbuf)
381b0453382SBill Fenner {
382b0453382SBill Fenner     int reverse = 0;
383b0453382SBill Fenner     char *attrib_fmt = "READONLY|HIDDEN|SYSTEM|VOLUME|DIR|ARCHIVE|";
384b0453382SBill Fenner     int len;
385b0453382SBill Fenner 
386b0453382SBill Fenner     while (*fmt && buf<maxbuf) {
387b0453382SBill Fenner 	switch (*fmt) {
388b0453382SBill Fenner 	case 'a':
389a90e161bSBill Fenner 	    write_bits(buf[0], attrib_fmt);
390a90e161bSBill Fenner 	    buf++;
391a90e161bSBill Fenner 	    fmt++;
392b0453382SBill Fenner 	    break;
393b0453382SBill Fenner 
394b0453382SBill Fenner 	case 'A':
395a90e161bSBill Fenner 	    write_bits(EXTRACT_LE_16BITS(buf), attrib_fmt);
396a90e161bSBill Fenner 	    buf += 2;
397a90e161bSBill Fenner 	    fmt++;
398b0453382SBill Fenner 	    break;
399b0453382SBill Fenner 
400b0453382SBill Fenner 	case '{':
401b0453382SBill Fenner 	  {
402b0453382SBill Fenner 	    char bitfmt[128];
4039afd0c29SBill Fenner 	    char *p;
4049afd0c29SBill Fenner 	    int l;
4059afd0c29SBill Fenner 
4069afd0c29SBill Fenner 	    p = strchr(++fmt, '}');
4079afd0c29SBill Fenner 	    l = PTR_DIFF(p, fmt);
408b0453382SBill Fenner 	    strncpy(bitfmt, fmt, l);
409b0453382SBill Fenner 	    bitfmt[l] = 0;
410b0453382SBill Fenner 	    fmt = p + 1;
411a90e161bSBill Fenner 	    write_bits(buf[0], bitfmt);
412b0453382SBill Fenner 	    buf++;
413b0453382SBill Fenner 	    break;
414b0453382SBill Fenner 	  }
415b0453382SBill Fenner 
416b0453382SBill Fenner 	case 'P':
417b0453382SBill Fenner 	  {
418b0453382SBill Fenner 	    int l = atoi(fmt + 1);
419b0453382SBill Fenner 	    buf += l;
420b0453382SBill Fenner 	    fmt++;
4219afd0c29SBill Fenner 	    while (isdigit((unsigned char)*fmt))
422a90e161bSBill Fenner 		fmt++;
423b0453382SBill Fenner 	    break;
424b0453382SBill Fenner 	  }
425b0453382SBill Fenner 	case 'r':
426b0453382SBill Fenner 	    reverse = !reverse;
427b0453382SBill Fenner 	    fmt++;
428b0453382SBill Fenner 	    break;
429b0453382SBill Fenner 	case 'D':
430b0453382SBill Fenner 	  {
431a90e161bSBill Fenner 	    unsigned int x;
432a90e161bSBill Fenner 
433a90e161bSBill Fenner 	    TCHECK2(buf[0], 4);
434a90e161bSBill Fenner 	    x = reverse ? EXTRACT_32BITS(buf) : EXTRACT_LE_32BITS(buf);
435b0453382SBill Fenner 	    printf("%d (0x%x)", x, x);
436b0453382SBill Fenner 	    buf += 4;
437b0453382SBill Fenner 	    fmt++;
438b0453382SBill Fenner 	    break;
439b0453382SBill Fenner 	  }
440b0453382SBill Fenner 	case 'L':
441b0453382SBill Fenner 	  {
442a90e161bSBill Fenner 	    unsigned int x1, x2;
443a90e161bSBill Fenner 
444a90e161bSBill Fenner 	    TCHECK2(buf[4], 4);
445a90e161bSBill Fenner 	    x1 = reverse ? EXTRACT_32BITS(buf) :
446a90e161bSBill Fenner 			   EXTRACT_LE_32BITS(buf);
447a90e161bSBill Fenner 	    x2 = reverse ? EXTRACT_32BITS(buf + 4) :
448a90e161bSBill Fenner 			   EXTRACT_LE_32BITS(buf + 4);
449a90e161bSBill Fenner 	    if (x2)
450b0453382SBill Fenner 		printf("0x%08x:%08x", x2, x1);
451a90e161bSBill Fenner 	    else
452b0453382SBill Fenner 		printf("%d (0x%08x%08x)", x1, x2, x1);
453b0453382SBill Fenner 	    buf += 8;
454b0453382SBill Fenner 	    fmt++;
455b0453382SBill Fenner 	    break;
456b0453382SBill Fenner 	  }
457b0453382SBill Fenner 	case 'd':
458b0453382SBill Fenner 	  {
459a90e161bSBill Fenner 	    unsigned int x;
460a90e161bSBill Fenner 	    TCHECK2(buf[0], 2);
461a90e161bSBill Fenner 	    x = reverse ? EXTRACT_16BITS(buf) :
462a90e161bSBill Fenner 			  EXTRACT_LE_16BITS(buf);
463b0453382SBill Fenner 	    printf("%d (0x%x)", x, x);
464b0453382SBill Fenner 	    buf += 2;
465b0453382SBill Fenner 	    fmt++;
466b0453382SBill Fenner 	    break;
467b0453382SBill Fenner 	  }
468b0453382SBill Fenner 	case 'W':
469b0453382SBill Fenner 	  {
470a90e161bSBill Fenner 	    unsigned int x;
471a90e161bSBill Fenner 	    TCHECK2(buf[0], 4);
472a90e161bSBill Fenner 	    x = reverse ? EXTRACT_32BITS(buf) :
473a90e161bSBill Fenner 			  EXTRACT_LE_32BITS(buf);
474b0453382SBill Fenner 	    printf("0x%X", x);
475b0453382SBill Fenner 	    buf += 4;
476b0453382SBill Fenner 	    fmt++;
477b0453382SBill Fenner 	    break;
478b0453382SBill Fenner 	  }
479b0453382SBill Fenner 	case 'w':
480b0453382SBill Fenner 	  {
481a90e161bSBill Fenner 	    unsigned int x;
482a90e161bSBill Fenner 	    TCHECK2(buf[0], 2);
483a90e161bSBill Fenner 	    x = reverse ? EXTRACT_16BITS(buf) :
484a90e161bSBill Fenner 			  EXTRACT_LE_16BITS(buf);
485b0453382SBill Fenner 	    printf("0x%X", x);
486b0453382SBill Fenner 	    buf += 2;
487b0453382SBill Fenner 	    fmt++;
488b0453382SBill Fenner 	    break;
489b0453382SBill Fenner 	  }
490b0453382SBill Fenner 	case 'B':
491b0453382SBill Fenner 	  {
492a90e161bSBill Fenner 	    unsigned int x;
493a90e161bSBill Fenner 	    TCHECK(buf[0]);
494a90e161bSBill Fenner 	    x = buf[0];
495b0453382SBill Fenner 	    printf("0x%X", x);
496b0453382SBill Fenner 	    buf += 1;
497b0453382SBill Fenner 	    fmt++;
498b0453382SBill Fenner 	    break;
499b0453382SBill Fenner 	  }
500b0453382SBill Fenner 	case 'b':
501b0453382SBill Fenner 	  {
502a90e161bSBill Fenner 	    unsigned int x;
503a90e161bSBill Fenner 	    TCHECK(buf[0]);
504a90e161bSBill Fenner 	    x = buf[0];
505a90e161bSBill Fenner 	    printf("%u (0x%x)", x, x);
506b0453382SBill Fenner 	    buf += 1;
507b0453382SBill Fenner 	    fmt++;
508b0453382SBill Fenner 	    break;
509b0453382SBill Fenner 	  }
510b0453382SBill Fenner 	case 'S':
511b0453382SBill Fenner 	  {
512a90e161bSBill Fenner 	    /*XXX unistr() */
513b0453382SBill Fenner 	    printf("%.*s", (int)PTR_DIFF(maxbuf, buf), unistr(buf, &len));
514b0453382SBill Fenner 	    buf += len;
515b0453382SBill Fenner 	    fmt++;
516b0453382SBill Fenner 	    break;
517b0453382SBill Fenner 	  }
518b0453382SBill Fenner 	case 'Z':
519b0453382SBill Fenner 	  {
520b0453382SBill Fenner 	    if (*buf != 4 && *buf != 2)
521a90e161bSBill Fenner 		printf("Error! ASCIIZ buffer of type %u (safety=%lu)\n", *buf,
522a90e161bSBill Fenner 		    (unsigned long)PTR_DIFF(maxbuf, buf));
523a90e161bSBill Fenner 	    printf("%.*s", (int)PTR_DIFF(maxbuf, buf + 1),
524a90e161bSBill Fenner 		unistr(buf + 1, &len));
525b0453382SBill Fenner 	    buf += len + 1;
526b0453382SBill Fenner 	    fmt++;
527b0453382SBill Fenner 	    break;
528b0453382SBill Fenner 	  }
529b0453382SBill Fenner 	case 's':
530b0453382SBill Fenner 	  {
531b0453382SBill Fenner 	    int l = atoi(fmt + 1);
532b0453382SBill Fenner 	    printf("%-*.*s", l, l, buf);
533b0453382SBill Fenner 	    buf += l;
534a90e161bSBill Fenner 	    fmt++;
5359afd0c29SBill Fenner 	    while (isdigit((unsigned char)*fmt))
536a90e161bSBill Fenner 		fmt++;
537b0453382SBill Fenner 	    break;
538b0453382SBill Fenner 	  }
539b0453382SBill Fenner 	case 'h':
540b0453382SBill Fenner 	  {
541b0453382SBill Fenner 	    int l = atoi(fmt + 1);
542a90e161bSBill Fenner 	    while (l--)
543a90e161bSBill Fenner 		printf("%02x", *buf++);
544a90e161bSBill Fenner 	    fmt++;
5459afd0c29SBill Fenner 	    while (isdigit((unsigned char)*fmt))
546a90e161bSBill Fenner 		fmt++;
547b0453382SBill Fenner 	    break;
548b0453382SBill Fenner 	  }
549b0453382SBill Fenner 	case 'n':
550b0453382SBill Fenner 	  {
551b0453382SBill Fenner 	    int t = atoi(fmt+1);
552b0453382SBill Fenner 	    char nbuf[255];
553b0453382SBill Fenner 	    int name_type;
554685295f4SBill Fenner 	    int len;
555a90e161bSBill Fenner 
556b0453382SBill Fenner 	    switch (t) {
557b0453382SBill Fenner 	    case 1:
558a90e161bSBill Fenner 		name_type = name_extract(startbuf, PTR_DIFF(buf, startbuf),
559a90e161bSBill Fenner 		    maxbuf, nbuf);
560685295f4SBill Fenner 		if (name_type < 0)
561685295f4SBill Fenner 		    goto trunc;
562685295f4SBill Fenner 		len = name_len(buf, maxbuf);
563685295f4SBill Fenner 		if (len < 0)
564685295f4SBill Fenner 		    goto trunc;
565685295f4SBill Fenner 		buf += len;
566a90e161bSBill Fenner 		printf("%-15.15s NameType=0x%02X (%s)", nbuf, name_type,
567a90e161bSBill Fenner 		    name_type_str(name_type));
568b0453382SBill Fenner 		break;
569b0453382SBill Fenner 	    case 2:
570b0453382SBill Fenner 		name_type = buf[15];
571a90e161bSBill Fenner 		printf("%-15.15s NameType=0x%02X (%s)", buf, name_type,
572a90e161bSBill Fenner 		    name_type_str(name_type));
573b0453382SBill Fenner 		buf += 16;
574b0453382SBill Fenner 		break;
575b0453382SBill Fenner 	    }
576a90e161bSBill Fenner 	    fmt++;
5779afd0c29SBill Fenner 	    while (isdigit((unsigned char)*fmt))
578a90e161bSBill Fenner 		fmt++;
579b0453382SBill Fenner 	    break;
580b0453382SBill Fenner 	  }
581b0453382SBill Fenner 	case 'T':
582b0453382SBill Fenner 	  {
583b0453382SBill Fenner 	    time_t t;
584a90e161bSBill Fenner 	    int x;
585a90e161bSBill Fenner 	    x = EXTRACT_LE_32BITS(buf);
586a90e161bSBill Fenner 
587b0453382SBill Fenner 	    switch (atoi(fmt + 1)) {
588b0453382SBill Fenner 	    case 1:
589b0453382SBill Fenner 		if (x == 0 || x == -1 || x == 0xFFFFFFFF)
590b0453382SBill Fenner 		    t = 0;
591b0453382SBill Fenner 		else
592b0453382SBill Fenner 		    t = make_unix_date(buf);
593b0453382SBill Fenner 		buf += 4;
594b0453382SBill Fenner 		break;
595b0453382SBill Fenner 	    case 2:
596b0453382SBill Fenner 		if (x == 0 || x == -1 || x == 0xFFFFFFFF)
597b0453382SBill Fenner 		    t = 0;
598b0453382SBill Fenner 		else
599b0453382SBill Fenner 		    t = make_unix_date2(buf);
600b0453382SBill Fenner 		buf += 4;
601b0453382SBill Fenner 		break;
602b0453382SBill Fenner 	    case 3:
603b0453382SBill Fenner 		t = interpret_long_date(buf);
604b0453382SBill Fenner 		buf += 8;
605b0453382SBill Fenner 		break;
606b0453382SBill Fenner 	    }
607b0453382SBill Fenner 	    printf("%s", t ? asctime(localtime(&t)) : "NULL\n");
608a90e161bSBill Fenner 	    fmt++;
6099afd0c29SBill Fenner 	    while (isdigit((unsigned char)*fmt))
610a90e161bSBill Fenner 		fmt++;
611b0453382SBill Fenner 	    break;
612b0453382SBill Fenner 	  }
613b0453382SBill Fenner 	default:
614b0453382SBill Fenner 	    putchar(*fmt);
615b0453382SBill Fenner 	    fmt++;
616b0453382SBill Fenner 	    break;
617b0453382SBill Fenner 	}
618b0453382SBill Fenner     }
619b0453382SBill Fenner 
620b0453382SBill Fenner     if (buf >= maxbuf && *fmt)
621b0453382SBill Fenner 	printf("END OF BUFFER\n");
622b0453382SBill Fenner 
623b0453382SBill Fenner     return(buf);
624685295f4SBill Fenner 
625685295f4SBill Fenner trunc:
626685295f4SBill Fenner     printf("\n");
627685295f4SBill Fenner     printf("WARNING: Short packet. Try increasing the snap length\n");
628685295f4SBill Fenner     return(NULL);
629b0453382SBill Fenner }
630b0453382SBill Fenner 
631a90e161bSBill Fenner const u_char *
632a90e161bSBill Fenner smb_fdata(const u_char *buf, const char *fmt, const u_char *maxbuf)
633b0453382SBill Fenner {
634b0453382SBill Fenner     static int depth = 0;
635b0453382SBill Fenner     char s[128];
636b0453382SBill Fenner     char *p;
637b0453382SBill Fenner 
638b0453382SBill Fenner     while (*fmt) {
639b0453382SBill Fenner 	switch (*fmt) {
640b0453382SBill Fenner 	case '*':
641b0453382SBill Fenner 	    fmt++;
642b0453382SBill Fenner 	    while (buf < maxbuf) {
643a90e161bSBill Fenner 		const u_char *buf2;
644b0453382SBill Fenner 		depth++;
645a90e161bSBill Fenner 		buf2 = smb_fdata(buf, fmt, maxbuf);
646b0453382SBill Fenner 		depth--;
647a90e161bSBill Fenner 		if (buf2 == NULL)
648a90e161bSBill Fenner 		    return(NULL);
649a90e161bSBill Fenner 		if (buf2 == buf)
650a90e161bSBill Fenner 		    return(buf);
651b0453382SBill Fenner 		buf = buf2;
652b0453382SBill Fenner 	    }
653a90e161bSBill Fenner 	    return(buf);
654b0453382SBill Fenner 
655b0453382SBill Fenner 	case '|':
656b0453382SBill Fenner 	    fmt++;
657a90e161bSBill Fenner 	    if (buf >= maxbuf)
658a90e161bSBill Fenner 		return(buf);
659b0453382SBill Fenner 	    break;
660b0453382SBill Fenner 
661b0453382SBill Fenner 	case '%':
662b0453382SBill Fenner 	    fmt++;
663b0453382SBill Fenner 	    buf = maxbuf;
664b0453382SBill Fenner 	    break;
665b0453382SBill Fenner 
666b0453382SBill Fenner 	case '#':
667b0453382SBill Fenner 	    fmt++;
668b0453382SBill Fenner 	    return(buf);
669b0453382SBill Fenner 	    break;
670b0453382SBill Fenner 
671b0453382SBill Fenner 	case '[':
672b0453382SBill Fenner 	    fmt++;
673a90e161bSBill Fenner 	    if (buf >= maxbuf)
674a90e161bSBill Fenner 		return(buf);
675685295f4SBill Fenner 	    memset(s, 0, sizeof(s));
676b0453382SBill Fenner 	    p = strchr(fmt, ']');
677a90e161bSBill Fenner 	    if (p - fmt + 1 > sizeof(s)) {
678a90e161bSBill Fenner 		/* overrun */
679a90e161bSBill Fenner 		return(buf);
680a90e161bSBill Fenner 	    }
681b0453382SBill Fenner 	    strncpy(s, fmt, p - fmt);
682a90e161bSBill Fenner 	    s[p - fmt] = '\0';
683b0453382SBill Fenner 	    fmt = p + 1;
684a90e161bSBill Fenner 	    buf = smb_fdata1(buf, s, maxbuf);
685685295f4SBill Fenner 	    if (buf == NULL)
686685295f4SBill Fenner 		return(NULL);
687b0453382SBill Fenner 	    break;
688b0453382SBill Fenner 
689b0453382SBill Fenner 	default:
690a90e161bSBill Fenner 	    putchar(*fmt);
691a90e161bSBill Fenner 	    fmt++;
692b0453382SBill Fenner 	    fflush(stdout);
693b0453382SBill Fenner 	    break;
694b0453382SBill Fenner 	}
695b0453382SBill Fenner     }
696b0453382SBill Fenner     if (!depth && buf < maxbuf) {
697a90e161bSBill Fenner 	size_t len = PTR_DIFF(maxbuf, buf);
698a90e161bSBill Fenner 	printf("Data: (%lu bytes)\n", (unsigned long)len);
699b0453382SBill Fenner 	print_data(buf, len);
700b0453382SBill Fenner 	return(buf + len);
701b0453382SBill Fenner     }
702b0453382SBill Fenner     return(buf);
703b0453382SBill Fenner }
704b0453382SBill Fenner 
705a90e161bSBill Fenner typedef struct {
706a90e161bSBill Fenner     const char *name;
707b0453382SBill Fenner     int code;
708a90e161bSBill Fenner     const char *message;
709b0453382SBill Fenner } err_code_struct;
710b0453382SBill Fenner 
711b0453382SBill Fenner /* Dos Error Messages */
712b0453382SBill Fenner static err_code_struct dos_msgs[] = {
713b0453382SBill Fenner     { "ERRbadfunc", 1, "Invalid function." },
714b0453382SBill Fenner     { "ERRbadfile", 2, "File not found." },
715b0453382SBill Fenner     { "ERRbadpath", 3, "Directory invalid." },
716b0453382SBill Fenner     { "ERRnofids", 4, "No file descriptors available" },
717b0453382SBill Fenner     { "ERRnoaccess", 5, "Access denied." },
718b0453382SBill Fenner     { "ERRbadfid", 6, "Invalid file handle." },
719b0453382SBill Fenner     { "ERRbadmcb", 7, "Memory control blocks destroyed." },
720b0453382SBill Fenner     { "ERRnomem", 8, "Insufficient server memory to perform the requested function." },
721b0453382SBill Fenner     { "ERRbadmem", 9, "Invalid memory block address." },
722b0453382SBill Fenner     { "ERRbadenv", 10, "Invalid environment." },
723b0453382SBill Fenner     { "ERRbadformat", 11, "Invalid format." },
724b0453382SBill Fenner     { "ERRbadaccess", 12, "Invalid open mode." },
725b0453382SBill Fenner     { "ERRbaddata", 13, "Invalid data." },
726b0453382SBill Fenner     { "ERR", 14, "reserved." },
727b0453382SBill Fenner     { "ERRbaddrive", 15, "Invalid drive specified." },
728b0453382SBill Fenner     { "ERRremcd", 16, "A Delete Directory request attempted  to  remove  the  server's  current directory." },
729b0453382SBill Fenner     { "ERRdiffdevice", 17, "Not same device." },
730b0453382SBill Fenner     { "ERRnofiles", 18, "A File Search command can find no more files matching the specified criteria." },
731b0453382SBill Fenner     { "ERRbadshare", 32, "The sharing mode specified for an Open conflicts with existing  FIDs  on the file." },
732b0453382SBill Fenner     { "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." },
733b0453382SBill Fenner     { "ERRfilexists", 80, "The file named in a Create Directory,  Make  New  File  or  Link  request already exists." },
734b0453382SBill Fenner     { "ERRbadpipe", 230, "Pipe invalid." },
735b0453382SBill Fenner     { "ERRpipebusy", 231, "All instances of the requested pipe are busy." },
736b0453382SBill Fenner     { "ERRpipeclosing", 232, "Pipe close in progress." },
737b0453382SBill Fenner     { "ERRnotconnected", 233, "No process on other end of pipe." },
738b0453382SBill Fenner     { "ERRmoredata", 234, "There is more data to be returned." },
739a90e161bSBill Fenner     { NULL, -1, NULL }
740a90e161bSBill Fenner  };
741b0453382SBill Fenner 
742b0453382SBill Fenner /* Server Error Messages */
743b0453382SBill Fenner err_code_struct server_msgs[] = {
744b0453382SBill Fenner     { "ERRerror", 1, "Non-specific error code." },
745b0453382SBill Fenner     { "ERRbadpw", 2, "Bad password - name/password pair in a Tree Connect or Session Setup are invalid." },
746b0453382SBill Fenner     { "ERRbadtype", 3, "reserved." },
747b0453382SBill Fenner     { "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." },
748b0453382SBill Fenner     { "ERRinvnid", 5, "The tree ID (TID) specified in a command was invalid." },
749b0453382SBill Fenner     { "ERRinvnetname", 6, "Invalid network name in tree connect." },
750b0453382SBill Fenner     { "ERRinvdevice", 7, "Invalid device - printer request made to non-printer connection or  non-printer request made to printer connection." },
751b0453382SBill Fenner     { "ERRqfull", 49, "Print queue full (files) -- returned by open print file." },
752b0453382SBill Fenner     { "ERRqtoobig", 50, "Print queue full -- no space." },
753b0453382SBill Fenner     { "ERRqeof", 51, "EOF on print queue dump." },
754b0453382SBill Fenner     { "ERRinvpfid", 52, "Invalid print file FID." },
755b0453382SBill Fenner     { "ERRsmbcmd", 64, "The server did not recognize the command received." },
756b0453382SBill Fenner     { "ERRsrverror", 65, "The server encountered an internal error,  e.g.,  system file unavailable." },
757b0453382SBill Fenner     { "ERRfilespecs", 67, "The file handle (FID) and pathname parameters contained an invalid  combination of values." },
758b0453382SBill Fenner     { "ERRreserved", 68, "reserved." },
759b0453382SBill Fenner     { "ERRbadpermits", 69, "The access permissions specified for a file or directory are not a valid combination.  The server cannot set the requested attribute." },
760b0453382SBill Fenner     { "ERRreserved", 70, "reserved." },
761b0453382SBill Fenner     { "ERRsetattrmode", 71, "The attribute mode in the Set File Attribute request is invalid." },
762b0453382SBill Fenner     { "ERRpaused", 81, "Server is paused." },
763b0453382SBill Fenner     { "ERRmsgoff", 82, "Not receiving messages." },
764b0453382SBill Fenner     { "ERRnoroom", 83, "No room to buffer message." },
765b0453382SBill Fenner     { "ERRrmuns", 87, "Too many remote user names." },
766b0453382SBill Fenner     { "ERRtimeout", 88, "Operation timed out." },
767b0453382SBill Fenner     { "ERRnoresource", 89, "No resources currently available for request." },
768b0453382SBill Fenner     { "ERRtoomanyuids", 90, "Too many UIDs active on this session." },
769b0453382SBill Fenner     { "ERRbaduid", 91, "The UID is not known as a valid ID on this session." },
770b0453382SBill Fenner     { "ERRusempx", 250, "Temp unable to support Raw,  use MPX mode." },
771b0453382SBill Fenner     { "ERRusestd", 251, "Temp unable to support Raw,  use standard read/write." },
772b0453382SBill Fenner     { "ERRcontmpx", 252, "Continue in MPX mode." },
773b0453382SBill Fenner     { "ERRreserved", 253, "reserved." },
774b0453382SBill Fenner     { "ERRreserved", 254, "reserved." },
775b0453382SBill Fenner     { "ERRnosupport", 0xFFFF, "Function not supported." },
776a90e161bSBill Fenner     { NULL, -1, NULL }
777a90e161bSBill Fenner };
778b0453382SBill Fenner 
779b0453382SBill Fenner /* Hard Error Messages */
780b0453382SBill Fenner err_code_struct hard_msgs[] = {
781b0453382SBill Fenner     { "ERRnowrite", 19, "Attempt to write on write-protected diskette." },
782b0453382SBill Fenner     { "ERRbadunit", 20, "Unknown unit." },
783b0453382SBill Fenner     { "ERRnotready", 21, "Drive not ready." },
784b0453382SBill Fenner     { "ERRbadcmd", 22, "Unknown command." },
785b0453382SBill Fenner     { "ERRdata", 23, "Data error (CRC)." },
786b0453382SBill Fenner     { "ERRbadreq", 24, "Bad request structure length." },
787b0453382SBill Fenner     { "ERRseek", 25 , "Seek error." },
788b0453382SBill Fenner     { "ERRbadmedia", 26, "Unknown media type." },
789b0453382SBill Fenner     { "ERRbadsector", 27, "Sector not found." },
790b0453382SBill Fenner     { "ERRnopaper", 28, "Printer out of paper." },
791b0453382SBill Fenner     { "ERRwrite", 29, "Write fault." },
792b0453382SBill Fenner     { "ERRread", 30, "Read fault." },
793b0453382SBill Fenner     { "ERRgeneral", 31, "General failure." },
794b0453382SBill Fenner     { "ERRbadshare", 32, "A open conflicts with an existing open." },
795b0453382SBill Fenner     { "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." },
796b0453382SBill Fenner     { "ERRwrongdisk", 34, "The wrong disk was found in a drive." },
797b0453382SBill Fenner     { "ERRFCBUnavail", 35, "No FCBs are available to process request." },
798b0453382SBill Fenner     { "ERRsharebufexc", 36, "A sharing buffer has been exceeded." },
799a90e161bSBill Fenner     { NULL, -1, NULL }
800a90e161bSBill Fenner };
801b0453382SBill Fenner 
802a90e161bSBill Fenner static struct {
803b0453382SBill Fenner     int code;
804b0453382SBill Fenner     char *class;
805b0453382SBill Fenner     err_code_struct *err_msgs;
806b0453382SBill Fenner } err_classes[] = {
807b0453382SBill Fenner     { 0, "SUCCESS", NULL },
808b0453382SBill Fenner     { 0x01, "ERRDOS", dos_msgs },
809b0453382SBill Fenner     { 0x02, "ERRSRV", server_msgs },
810b0453382SBill Fenner     { 0x03, "ERRHRD", hard_msgs },
811b0453382SBill Fenner     { 0x04, "ERRXOS", NULL },
812b0453382SBill Fenner     { 0xE1, "ERRRMX1", NULL },
813b0453382SBill Fenner     { 0xE2, "ERRRMX2", NULL },
814b0453382SBill Fenner     { 0xE3, "ERRRMX3", NULL },
815b0453382SBill Fenner     { 0xFF, "ERRCMD", NULL },
816a90e161bSBill Fenner     { -1, NULL, NULL }
817a90e161bSBill Fenner };
818b0453382SBill Fenner 
819a90e161bSBill Fenner /*
820a90e161bSBill Fenner  * return a SMB error string from a SMB buffer
821a90e161bSBill Fenner  */
822a90e161bSBill Fenner char *
823a90e161bSBill Fenner smb_errstr(int class, int num)
824b0453382SBill Fenner {
825b0453382SBill Fenner     static char ret[128];
826b0453382SBill Fenner     int i, j;
827b0453382SBill Fenner 
828b0453382SBill Fenner     ret[0] = 0;
829b0453382SBill Fenner 
830b0453382SBill Fenner     for (i = 0; err_classes[i].class; i++)
831a90e161bSBill Fenner 	if (err_classes[i].code == class) {
832a90e161bSBill Fenner 	    if (err_classes[i].err_msgs) {
833b0453382SBill Fenner 		err_code_struct *err = err_classes[i].err_msgs;
834b0453382SBill Fenner 		for (j = 0; err[j].name; j++)
835a90e161bSBill Fenner 		    if (num == err[j].code) {
836a90e161bSBill Fenner 			snprintf(ret, sizeof(ret), "%s - %s (%s)",
837a90e161bSBill Fenner 			    err_classes[i].class, err[j].name, err[j].message);
838b0453382SBill Fenner 			return ret;
839b0453382SBill Fenner 		    }
840b0453382SBill Fenner 	    }
841b0453382SBill Fenner 
842685295f4SBill Fenner 	    snprintf(ret, sizeof(ret), "%s - %d", err_classes[i].class, num);
843b0453382SBill Fenner 	    return ret;
844b0453382SBill Fenner 	}
845b0453382SBill Fenner 
846685295f4SBill Fenner     snprintf(ret, sizeof(ret), "ERROR: Unknown error (%d,%d)", class, num);
847b0453382SBill Fenner     return(ret);
848b0453382SBill Fenner }
849