1*671dfc47SDavid du Colombier /*
2*671dfc47SDavid du Colombier * netbios dial, read, write
3*671dfc47SDavid du Colombier */
4*671dfc47SDavid du Colombier
5*671dfc47SDavid du Colombier #include <u.h>
6*671dfc47SDavid du Colombier #include <libc.h>
7*671dfc47SDavid du Colombier #include <ctype.h>
8*671dfc47SDavid du Colombier #include <fcall.h>
9*671dfc47SDavid du Colombier #include <thread.h>
10*671dfc47SDavid du Colombier #include <9p.h>
11*671dfc47SDavid du Colombier #include "cifs.h"
12*671dfc47SDavid du Colombier
13*671dfc47SDavid du Colombier enum {
14*671dfc47SDavid du Colombier MAXNBPKT = 8096, /* max netbios packet size */
15*671dfc47SDavid du Colombier NBquery = 0, /* packet type - query */
16*671dfc47SDavid du Colombier
17*671dfc47SDavid du Colombier NBAdapterStatus = 0x21, /* get host interface info */
18*671dfc47SDavid du Colombier NBInternet = 1, /* scope for info */
19*671dfc47SDavid du Colombier
20*671dfc47SDavid du Colombier NBmessage = 0x00, /* Netbios packet types */
21*671dfc47SDavid du Colombier NBrequest = 0x81,
22*671dfc47SDavid du Colombier NBpositive,
23*671dfc47SDavid du Colombier NBnegative,
24*671dfc47SDavid du Colombier NBretarget,
25*671dfc47SDavid du Colombier NBkeepalive,
26*671dfc47SDavid du Colombier
27*671dfc47SDavid du Colombier ISgroup = 0x8000,
28*671dfc47SDavid du Colombier };
29*671dfc47SDavid du Colombier
30*671dfc47SDavid du Colombier
31*671dfc47SDavid du Colombier static char *NBerr[] = {
32*671dfc47SDavid du Colombier [0] "not listening on called name",
33*671dfc47SDavid du Colombier [1] "not listening for calling name",
34*671dfc47SDavid du Colombier [2] "called name not present",
35*671dfc47SDavid du Colombier [3] "insufficient resources",
36*671dfc47SDavid du Colombier [15] "unspecified error"
37*671dfc47SDavid du Colombier };
38*671dfc47SDavid du Colombier
39*671dfc47SDavid du Colombier
40*671dfc47SDavid du Colombier static ulong
GL32(uchar ** p)41*671dfc47SDavid du Colombier GL32(uchar **p)
42*671dfc47SDavid du Colombier {
43*671dfc47SDavid du Colombier ulong n;
44*671dfc47SDavid du Colombier
45*671dfc47SDavid du Colombier n = *(*p)++;
46*671dfc47SDavid du Colombier n |= *(*p)++ << 8;
47*671dfc47SDavid du Colombier n |= *(*p)++ << 16;
48*671dfc47SDavid du Colombier n |= *(*p)++ << 24;
49*671dfc47SDavid du Colombier return n;
50*671dfc47SDavid du Colombier }
51*671dfc47SDavid du Colombier
52*671dfc47SDavid du Colombier static ushort
GL16(uchar ** p)53*671dfc47SDavid du Colombier GL16(uchar **p)
54*671dfc47SDavid du Colombier {
55*671dfc47SDavid du Colombier ushort n;
56*671dfc47SDavid du Colombier
57*671dfc47SDavid du Colombier n = *(*p)++;
58*671dfc47SDavid du Colombier n |= *(*p)++ << 8;
59*671dfc47SDavid du Colombier return n;
60*671dfc47SDavid du Colombier }
61*671dfc47SDavid du Colombier
62*671dfc47SDavid du Colombier void
Gmem(uchar ** p,void * v,int n)63*671dfc47SDavid du Colombier Gmem(uchar **p, void *v, int n)
64*671dfc47SDavid du Colombier {
65*671dfc47SDavid du Colombier uchar *str = v;
66*671dfc47SDavid du Colombier
67*671dfc47SDavid du Colombier while(n--)
68*671dfc47SDavid du Colombier *str++ = *(*p)++;
69*671dfc47SDavid du Colombier }
70*671dfc47SDavid du Colombier
71*671dfc47SDavid du Colombier
72*671dfc47SDavid du Colombier static ulong
GB32(uchar ** p)73*671dfc47SDavid du Colombier GB32(uchar **p)
74*671dfc47SDavid du Colombier {
75*671dfc47SDavid du Colombier ulong n;
76*671dfc47SDavid du Colombier
77*671dfc47SDavid du Colombier n = *(*p)++ << 24;
78*671dfc47SDavid du Colombier n |= *(*p)++ << 16;
79*671dfc47SDavid du Colombier n |= *(*p)++ << 8;
80*671dfc47SDavid du Colombier n |= *(*p)++;
81*671dfc47SDavid du Colombier return n;
82*671dfc47SDavid du Colombier }
83*671dfc47SDavid du Colombier
84*671dfc47SDavid du Colombier static ushort
GB16(uchar ** p)85*671dfc47SDavid du Colombier GB16(uchar **p)
86*671dfc47SDavid du Colombier {
87*671dfc47SDavid du Colombier ushort n;
88*671dfc47SDavid du Colombier
89*671dfc47SDavid du Colombier n = *(*p)++ << 8;
90*671dfc47SDavid du Colombier n |= *(*p)++;
91*671dfc47SDavid du Colombier return n;
92*671dfc47SDavid du Colombier }
93*671dfc47SDavid du Colombier
94*671dfc47SDavid du Colombier static uchar
G8(uchar ** p)95*671dfc47SDavid du Colombier G8(uchar **p)
96*671dfc47SDavid du Colombier {
97*671dfc47SDavid du Colombier return *(*p)++;
98*671dfc47SDavid du Colombier }
99*671dfc47SDavid du Colombier
100*671dfc47SDavid du Colombier static void
PB16(uchar ** p,uint n)101*671dfc47SDavid du Colombier PB16(uchar **p, uint n)
102*671dfc47SDavid du Colombier {
103*671dfc47SDavid du Colombier *(*p)++ = n >> 8;
104*671dfc47SDavid du Colombier *(*p)++ = n;
105*671dfc47SDavid du Colombier }
106*671dfc47SDavid du Colombier
107*671dfc47SDavid du Colombier static void
P8(uchar ** p,uint n)108*671dfc47SDavid du Colombier P8(uchar **p, uint n)
109*671dfc47SDavid du Colombier {
110*671dfc47SDavid du Colombier *(*p)++ = n;
111*671dfc47SDavid du Colombier }
112*671dfc47SDavid du Colombier
113*671dfc47SDavid du Colombier
114*671dfc47SDavid du Colombier static void
nbname(uchar ** p,char * name,char pad)115*671dfc47SDavid du Colombier nbname(uchar **p, char *name, char pad)
116*671dfc47SDavid du Colombier {
117*671dfc47SDavid du Colombier char c;
118*671dfc47SDavid du Colombier int i;
119*671dfc47SDavid du Colombier int done = 0;
120*671dfc47SDavid du Colombier
121*671dfc47SDavid du Colombier *(*p)++ = 0x20;
122*671dfc47SDavid du Colombier for(i = 0; i < 16; i++) {
123*671dfc47SDavid du Colombier c = pad;
124*671dfc47SDavid du Colombier if(!done && name[i] == '\0')
125*671dfc47SDavid du Colombier done = 1;
126*671dfc47SDavid du Colombier if(!done)
127*671dfc47SDavid du Colombier c = toupper(name[i]);
128*671dfc47SDavid du Colombier *(*p)++ = ((uchar)c >> 4) + 'A';
129*671dfc47SDavid du Colombier *(*p)++ = (c & 0xf) + 'A';
130*671dfc47SDavid du Colombier }
131*671dfc47SDavid du Colombier *(*p)++ = 0;
132*671dfc47SDavid du Colombier }
133*671dfc47SDavid du Colombier
134*671dfc47SDavid du Colombier int
calledname(char * host,char * name)135*671dfc47SDavid du Colombier calledname(char *host, char *name)
136*671dfc47SDavid du Colombier {
137*671dfc47SDavid du Colombier char *addr;
138*671dfc47SDavid du Colombier uchar buf[1024], *p;
139*671dfc47SDavid du Colombier static char tmp[20];
140*671dfc47SDavid du Colombier int num, flg, svs, j, i, fd, trn;
141*671dfc47SDavid du Colombier
142*671dfc47SDavid du Colombier trn = (getpid() ^ time(0)) & 0xffff;
143*671dfc47SDavid du Colombier if((addr = netmkaddr(host, "udp", "137")) == nil)
144*671dfc47SDavid du Colombier return -1;
145*671dfc47SDavid du Colombier
146*671dfc47SDavid du Colombier if((fd = dial(addr, "137", 0, 0)) < 0)
147*671dfc47SDavid du Colombier return -1;
148*671dfc47SDavid du Colombier p = buf;
149*671dfc47SDavid du Colombier
150*671dfc47SDavid du Colombier PB16(&p, trn); /* TRNid */
151*671dfc47SDavid du Colombier P8(&p, 0); /* flags */
152*671dfc47SDavid du Colombier P8(&p, 0x10); /* type */
153*671dfc47SDavid du Colombier PB16(&p, 1); /* # questions */
154*671dfc47SDavid du Colombier PB16(&p, 0); /* # answers */
155*671dfc47SDavid du Colombier PB16(&p, 0); /* # authority RRs */
156*671dfc47SDavid du Colombier PB16(&p, 0); /* # Aditional RRs */
157*671dfc47SDavid du Colombier nbname(&p, "*", 0);
158*671dfc47SDavid du Colombier PB16(&p, NBAdapterStatus);
159*671dfc47SDavid du Colombier PB16(&p, NBInternet);
160*671dfc47SDavid du Colombier
161*671dfc47SDavid du Colombier if(Debug && strstr(Debug, "dump"))
162*671dfc47SDavid du Colombier xd(nil, buf, p-buf);
163*671dfc47SDavid du Colombier
164*671dfc47SDavid du Colombier if(write(fd, buf, p-buf) != p-buf)
165*671dfc47SDavid du Colombier return -1;
166*671dfc47SDavid du Colombier
167*671dfc47SDavid du Colombier p = buf;
168*671dfc47SDavid du Colombier for(i = 0; i < 3; i++){
169*671dfc47SDavid du Colombier memset(buf, 0, sizeof(buf));
170*671dfc47SDavid du Colombier alarm(NBNSTOUT);
171*671dfc47SDavid du Colombier read(fd, buf, sizeof(buf));
172*671dfc47SDavid du Colombier alarm(0);
173*671dfc47SDavid du Colombier if(GB16(&p) == trn)
174*671dfc47SDavid du Colombier break;
175*671dfc47SDavid du Colombier }
176*671dfc47SDavid du Colombier close(fd);
177*671dfc47SDavid du Colombier if(i >= 3)
178*671dfc47SDavid du Colombier return -1;
179*671dfc47SDavid du Colombier
180*671dfc47SDavid du Colombier p = buf +56;
181*671dfc47SDavid du Colombier num = G8(&p); /* number of names */
182*671dfc47SDavid du Colombier
183*671dfc47SDavid du Colombier for(i = 0; i < num; i++){
184*671dfc47SDavid du Colombier memset(tmp, 0, sizeof(tmp));
185*671dfc47SDavid du Colombier Gmem(&p, tmp, 15);
186*671dfc47SDavid du Colombier svs = G8(&p);
187*671dfc47SDavid du Colombier flg = GB16(&p);
188*671dfc47SDavid du Colombier for(j = 14; j >= 0 && tmp[j] == ' '; j--)
189*671dfc47SDavid du Colombier tmp[j] = 0;
190*671dfc47SDavid du Colombier if(svs == 0 && !(flg & ISgroup))
191*671dfc47SDavid du Colombier strcpy(name, tmp);
192*671dfc47SDavid du Colombier }
193*671dfc47SDavid du Colombier return 0;
194*671dfc47SDavid du Colombier }
195*671dfc47SDavid du Colombier
196*671dfc47SDavid du Colombier
197*671dfc47SDavid du Colombier int
nbtdial(char * addr,char * called,char * sysname)198*671dfc47SDavid du Colombier nbtdial(char *addr, char *called, char *sysname)
199*671dfc47SDavid du Colombier {
200*671dfc47SDavid du Colombier char redir[20];
201*671dfc47SDavid du Colombier uchar *p, *lenp, buf[1024];
202*671dfc47SDavid du Colombier int type, len, err, fd, nkeepalive, nretarg;
203*671dfc47SDavid du Colombier
204*671dfc47SDavid du Colombier nretarg = 0;
205*671dfc47SDavid du Colombier nkeepalive = 0;
206*671dfc47SDavid du Colombier Redial:
207*671dfc47SDavid du Colombier if((addr = netmkaddr(addr, "tcp", "139")) == nil ||
208*671dfc47SDavid du Colombier (fd = dial(addr, 0, 0, 0)) < 0)
209*671dfc47SDavid du Colombier return -1;
210*671dfc47SDavid du Colombier
211*671dfc47SDavid du Colombier memset(buf, 0, sizeof(buf));
212*671dfc47SDavid du Colombier
213*671dfc47SDavid du Colombier p = buf;
214*671dfc47SDavid du Colombier P8(&p, NBrequest); /* type */
215*671dfc47SDavid du Colombier P8(&p, 0); /* flags */
216*671dfc47SDavid du Colombier lenp = p; PB16(&p, 0); /* length placeholder */
217*671dfc47SDavid du Colombier nbname(&p, called, ' '); /* remote NetBios name */
218*671dfc47SDavid du Colombier nbname(&p, sysname, ' '); /* our machine name */
219*671dfc47SDavid du Colombier PB16(&lenp, p-lenp -2); /* length re-write */
220*671dfc47SDavid du Colombier
221*671dfc47SDavid du Colombier if(Debug && strstr(Debug, "dump"))
222*671dfc47SDavid du Colombier xd(nil, buf, p-buf);
223*671dfc47SDavid du Colombier if(write(fd, buf, p-buf) != p-buf)
224*671dfc47SDavid du Colombier goto Error;
225*671dfc47SDavid du Colombier Reread:
226*671dfc47SDavid du Colombier p = buf;
227*671dfc47SDavid du Colombier memset(buf, 0, sizeof(buf));
228*671dfc47SDavid du Colombier if(readn(fd, buf, 4) < 4)
229*671dfc47SDavid du Colombier goto Error;
230*671dfc47SDavid du Colombier
231*671dfc47SDavid du Colombier type = G8(&p);
232*671dfc47SDavid du Colombier G8(&p); /* flags */
233*671dfc47SDavid du Colombier len = GB16(&p);
234*671dfc47SDavid du Colombier
235*671dfc47SDavid du Colombier if(readn(fd, buf +4, len -4) < len -4)
236*671dfc47SDavid du Colombier goto Error;
237*671dfc47SDavid du Colombier
238*671dfc47SDavid du Colombier if(Debug && strstr(Debug, "dump"))
239*671dfc47SDavid du Colombier xd(nil, buf, len+4);
240*671dfc47SDavid du Colombier
241*671dfc47SDavid du Colombier switch(type) {
242*671dfc47SDavid du Colombier case NBpositive:
243*671dfc47SDavid du Colombier return fd;
244*671dfc47SDavid du Colombier case NBnegative:
245*671dfc47SDavid du Colombier if(len < 1) {
246*671dfc47SDavid du Colombier werrstr("nbdial: bad error pkt");
247*671dfc47SDavid du Colombier goto Error;
248*671dfc47SDavid du Colombier }
249*671dfc47SDavid du Colombier err = G8(&p);
250*671dfc47SDavid du Colombier if(err < 0 || err > nelem(NBerr) || NBerr[err] == nil)
251*671dfc47SDavid du Colombier werrstr("NBT: %d - unknown error", err);
252*671dfc47SDavid du Colombier else
253*671dfc47SDavid du Colombier werrstr("NBT: %s", NBerr[err]);
254*671dfc47SDavid du Colombier
255*671dfc47SDavid du Colombier goto Error;
256*671dfc47SDavid du Colombier case NBkeepalive:
257*671dfc47SDavid du Colombier if(++nkeepalive >= 16){
258*671dfc47SDavid du Colombier werrstr("nbdial: too many keepalives");
259*671dfc47SDavid du Colombier goto Error;
260*671dfc47SDavid du Colombier }
261*671dfc47SDavid du Colombier goto Reread;
262*671dfc47SDavid du Colombier
263*671dfc47SDavid du Colombier case NBretarget:
264*671dfc47SDavid du Colombier if(++nretarg >= 16) {
265*671dfc47SDavid du Colombier werrstr("nbdial: too many redirects");
266*671dfc47SDavid du Colombier goto Error;
267*671dfc47SDavid du Colombier }
268*671dfc47SDavid du Colombier if(len < 4) {
269*671dfc47SDavid du Colombier werrstr("nbdial: bad redirect pkt");
270*671dfc47SDavid du Colombier goto Error;
271*671dfc47SDavid du Colombier }
272*671dfc47SDavid du Colombier sprint(redir, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
273*671dfc47SDavid du Colombier addr = redir;
274*671dfc47SDavid du Colombier goto Redial;
275*671dfc47SDavid du Colombier
276*671dfc47SDavid du Colombier default:
277*671dfc47SDavid du Colombier werrstr("nbdial: 0x%x - unknown packet in netbios handshake", type);
278*671dfc47SDavid du Colombier goto Error;
279*671dfc47SDavid du Colombier }
280*671dfc47SDavid du Colombier Error:
281*671dfc47SDavid du Colombier close(fd);
282*671dfc47SDavid du Colombier return -1;
283*671dfc47SDavid du Colombier }
284*671dfc47SDavid du Colombier
285*671dfc47SDavid du Colombier void
nbthdr(Pkt * p)286*671dfc47SDavid du Colombier nbthdr(Pkt *p)
287*671dfc47SDavid du Colombier {
288*671dfc47SDavid du Colombier p->pos = p->buf;
289*671dfc47SDavid du Colombier memset(p->buf, 0xa5, MTU);
290*671dfc47SDavid du Colombier
291*671dfc47SDavid du Colombier p8(p, NBmessage); /* type */
292*671dfc47SDavid du Colombier p8(p, 0); /* flags */
293*671dfc47SDavid du Colombier pb16(p, 0); /* length (filled in later) */
294*671dfc47SDavid du Colombier }
295*671dfc47SDavid du Colombier
296*671dfc47SDavid du Colombier int
nbtrpc(Pkt * p)297*671dfc47SDavid du Colombier nbtrpc(Pkt *p)
298*671dfc47SDavid du Colombier {
299*671dfc47SDavid du Colombier int len, got, type, nkeep;
300*671dfc47SDavid du Colombier
301*671dfc47SDavid du Colombier len = p->pos - p->buf;
302*671dfc47SDavid du Colombier
303*671dfc47SDavid du Colombier p->pos = p->buf +2;
304*671dfc47SDavid du Colombier pb16(p, len - NBHDRLEN); /* length */
305*671dfc47SDavid du Colombier
306*671dfc47SDavid du Colombier if(Debug && strstr(Debug, "dump"))
307*671dfc47SDavid du Colombier xd("tx", p->buf, len);
308*671dfc47SDavid du Colombier
309*671dfc47SDavid du Colombier alarm(NBRPCTOUT);
310*671dfc47SDavid du Colombier if(write(p->s->fd, p->buf, len) != len){
311*671dfc47SDavid du Colombier werrstr("nbtrpc: write failed - %r");
312*671dfc47SDavid du Colombier alarm(0);
313*671dfc47SDavid du Colombier return -1;
314*671dfc47SDavid du Colombier }
315*671dfc47SDavid du Colombier
316*671dfc47SDavid du Colombier nkeep = 0;
317*671dfc47SDavid du Colombier retry:
318*671dfc47SDavid du Colombier p->pos = p->buf;
319*671dfc47SDavid du Colombier memset(p->buf, 0xa5, MTU);
320*671dfc47SDavid du Colombier
321*671dfc47SDavid du Colombier got = readn(p->s->fd, p->buf, NBHDRLEN);
322*671dfc47SDavid du Colombier
323*671dfc47SDavid du Colombier if(got < NBHDRLEN){
324*671dfc47SDavid du Colombier werrstr("nbtrpc: short read - %r");
325*671dfc47SDavid du Colombier alarm(0);
326*671dfc47SDavid du Colombier return -1;
327*671dfc47SDavid du Colombier }
328*671dfc47SDavid du Colombier p->eop = p->buf + got;
329*671dfc47SDavid du Colombier
330*671dfc47SDavid du Colombier type = g8(p); /* NBT type (session) */
331*671dfc47SDavid du Colombier if(type == NBkeepalive){
332*671dfc47SDavid du Colombier if(++nkeep > 16) {
333*671dfc47SDavid du Colombier werrstr("nbtrpc: too many keepalives (%d attempts)", nkeep);
334*671dfc47SDavid du Colombier alarm(0);
335*671dfc47SDavid du Colombier return -1;
336*671dfc47SDavid du Colombier }
337*671dfc47SDavid du Colombier goto retry;
338*671dfc47SDavid du Colombier }
339*671dfc47SDavid du Colombier
340*671dfc47SDavid du Colombier g8(p); /* NBT flags (none) */
341*671dfc47SDavid du Colombier
342*671dfc47SDavid du Colombier len = gb16(p); /* NBT payload length */
343*671dfc47SDavid du Colombier if((len +NBHDRLEN) > MTU){
344*671dfc47SDavid du Colombier werrstr("nbtrpc: packet bigger than MTU, (%d > %d)", len, MTU);
345*671dfc47SDavid du Colombier alarm(0);
346*671dfc47SDavid du Colombier return -1;
347*671dfc47SDavid du Colombier }
348*671dfc47SDavid du Colombier
349*671dfc47SDavid du Colombier got = readn(p->s->fd, p->buf +NBHDRLEN, len);
350*671dfc47SDavid du Colombier alarm(0);
351*671dfc47SDavid du Colombier
352*671dfc47SDavid du Colombier if(Debug && strstr(Debug, "dump"))
353*671dfc47SDavid du Colombier xd("rx", p->buf, got +NBHDRLEN);
354*671dfc47SDavid du Colombier
355*671dfc47SDavid du Colombier if(got < 0)
356*671dfc47SDavid du Colombier return -1;
357*671dfc47SDavid du Colombier p->eop = p->buf + got +NBHDRLEN;
358*671dfc47SDavid du Colombier return got+NBHDRLEN;
359*671dfc47SDavid du Colombier }
360*671dfc47SDavid du Colombier
361*671dfc47SDavid du Colombier
362*671dfc47SDavid du Colombier void
xd(char * str,void * buf,int n)363*671dfc47SDavid du Colombier xd(char *str, void *buf, int n)
364*671dfc47SDavid du Colombier {
365*671dfc47SDavid du Colombier int fd, flg, flags2, cmd;
366*671dfc47SDavid du Colombier uint sum;
367*671dfc47SDavid du Colombier long err;
368*671dfc47SDavid du Colombier uchar *p, *end;
369*671dfc47SDavid du Colombier
370*671dfc47SDavid du Colombier if(n == 0)
371*671dfc47SDavid du Colombier return;
372*671dfc47SDavid du Colombier
373*671dfc47SDavid du Colombier p = buf;
374*671dfc47SDavid du Colombier end = (uchar *)buf +n;
375*671dfc47SDavid du Colombier
376*671dfc47SDavid du Colombier if(Debug && strstr(Debug, "log") != nil){
377*671dfc47SDavid du Colombier if((fd = open("pkt.log", ORDWR)) == -1)
378*671dfc47SDavid du Colombier return;
379*671dfc47SDavid du Colombier seek(fd, 0, 2);
380*671dfc47SDavid du Colombier fprint(fd, "%d ", 0);
381*671dfc47SDavid du Colombier while(p < end)
382*671dfc47SDavid du Colombier fprint(fd, "%02x ", *p++);
383*671dfc47SDavid du Colombier fprint(fd, "\n");
384*671dfc47SDavid du Colombier close(fd);
385*671dfc47SDavid du Colombier return;
386*671dfc47SDavid du Colombier }
387*671dfc47SDavid du Colombier
388*671dfc47SDavid du Colombier if(!str)
389*671dfc47SDavid du Colombier goto Raw;
390*671dfc47SDavid du Colombier
391*671dfc47SDavid du Colombier p = (uchar *)buf + 4;
392*671dfc47SDavid du Colombier if(GL32(&p) == 0x424d53ff){
393*671dfc47SDavid du Colombier buf = (uchar *)buf + 4;
394*671dfc47SDavid du Colombier n -= 4;
395*671dfc47SDavid du Colombier }
396*671dfc47SDavid du Colombier end = (uchar *)buf + n;
397*671dfc47SDavid du Colombier
398*671dfc47SDavid du Colombier sum = 0;
399*671dfc47SDavid du Colombier p = buf;
400*671dfc47SDavid du Colombier while(p < end)
401*671dfc47SDavid du Colombier sum += *p++;
402*671dfc47SDavid du Colombier p = buf;
403*671dfc47SDavid du Colombier
404*671dfc47SDavid du Colombier fprint(2, "%s : len=%ud sum=%d\n", str, n, sum);
405*671dfc47SDavid du Colombier
406*671dfc47SDavid du Colombier fprint(2, "mag=0x%ulx ", GL32(&p));
407*671dfc47SDavid du Colombier fprint(2, "cmd=0x%ux ", cmd = G8(&p));
408*671dfc47SDavid du Colombier fprint(2, "err=0x%ulx ", err=GL32(&p));
409*671dfc47SDavid du Colombier fprint(2, "flg=0x%02ux ", flg = G8(&p));
410*671dfc47SDavid du Colombier fprint(2, "flg2=0x%04ux\n", flags2= GL16(&p));
411*671dfc47SDavid du Colombier fprint(2, "dfs=%s\n", (flags2 & FL2_DFS)? "y": "n");
412*671dfc47SDavid du Colombier
413*671dfc47SDavid du Colombier fprint(2, "pidl=%ud ", GL16(&p));
414*671dfc47SDavid du Colombier fprint(2, "res=%uld ", GL32(&p));
415*671dfc47SDavid du Colombier fprint(2, "sid=%ud ", GL16(&p));
416*671dfc47SDavid du Colombier fprint(2, "seq=0x%ux ", GL16(&p));
417*671dfc47SDavid du Colombier fprint(2, "pad=%ud ", GL16(&p));
418*671dfc47SDavid du Colombier
419*671dfc47SDavid du Colombier fprint(2, "tid=%ud ", GL16(&p));
420*671dfc47SDavid du Colombier fprint(2, "pid=%ud ", GL16(&p));
421*671dfc47SDavid du Colombier fprint(2, "uid=%ud ", GL16(&p));
422*671dfc47SDavid du Colombier fprint(2, "mid=%ud\n", GL16(&p));
423*671dfc47SDavid du Colombier
424*671dfc47SDavid du Colombier if(cmd == 0x32 && (flg & 0x80) == 0){ /* TRANS 2, TX */
425*671dfc47SDavid du Colombier fprint(2, "words=%ud ", G8(&p));
426*671dfc47SDavid du Colombier fprint(2, "totparams=%ud ", GL16(&p));
427*671dfc47SDavid du Colombier fprint(2, "totdata=%ud ", GL16(&p));
428*671dfc47SDavid du Colombier fprint(2, "maxparam=%ud ", GL16(&p));
429*671dfc47SDavid du Colombier fprint(2, "maxdata=%ud\n", GL16(&p));
430*671dfc47SDavid du Colombier fprint(2, "maxsetup=%ud ", G8(&p));
431*671dfc47SDavid du Colombier fprint(2, "reserved=%ud ", G8(&p));
432*671dfc47SDavid du Colombier fprint(2, "flags=%ud ", GL16(&p));
433*671dfc47SDavid du Colombier fprint(2, "timeout=%uld\n", GL32(&p));
434*671dfc47SDavid du Colombier fprint(2, "reserved=%ud ", GL16(&p));
435*671dfc47SDavid du Colombier fprint(2, "paramcnt=%ud ", GL16(&p));
436*671dfc47SDavid du Colombier fprint(2, "paramoff=%ud ", GL16(&p));
437*671dfc47SDavid du Colombier fprint(2, "datacnt=%ud ", GL16(&p));
438*671dfc47SDavid du Colombier fprint(2, "dataoff=%ud ", GL16(&p));
439*671dfc47SDavid du Colombier fprint(2, "setupcnt=%ud ", G8(&p));
440*671dfc47SDavid du Colombier fprint(2, "reserved=%ud\n", G8(&p));
441*671dfc47SDavid du Colombier fprint(2, "trans2=0x%02x ", GL16(&p));
442*671dfc47SDavid du Colombier fprint(2, "data-words=%d ", G8(&p));
443*671dfc47SDavid du Colombier fprint(2, "padding=%d\n", G8(&p));
444*671dfc47SDavid du Colombier }
445*671dfc47SDavid du Colombier if(cmd == 0x32 && (flg & 0x80) == 0x80){ /* TRANS 2, RX */
446*671dfc47SDavid du Colombier fprint(2, "words=%ud ", G8(&p));
447*671dfc47SDavid du Colombier fprint(2, "totparams=%ud ", GL16(&p));
448*671dfc47SDavid du Colombier fprint(2, "totdata=%ud ", GL16(&p));
449*671dfc47SDavid du Colombier fprint(2, "reserved=%ud ", GL16(&p));
450*671dfc47SDavid du Colombier fprint(2, "paramcnt=%ud\n", GL16(&p));
451*671dfc47SDavid du Colombier fprint(2, "paramoff=%ud ", GL16(&p));
452*671dfc47SDavid du Colombier fprint(2, "paramdisp=%ud ", GL16(&p));
453*671dfc47SDavid du Colombier fprint(2, "datacnt=%ud\n", GL16(&p));
454*671dfc47SDavid du Colombier fprint(2, "dataoff=%ud ", GL16(&p));
455*671dfc47SDavid du Colombier fprint(2, "datadisp=%ud ", GL16(&p));
456*671dfc47SDavid du Colombier fprint(2, "setupcnt=%ud ", G8(&p));
457*671dfc47SDavid du Colombier fprint(2, "reserved=%ud\n", G8(&p));
458*671dfc47SDavid du Colombier }
459*671dfc47SDavid du Colombier if(err)
460*671dfc47SDavid du Colombier if(flags2 & FL2_NT_ERRCODES)
461*671dfc47SDavid du Colombier fprint(2, "err=%s\n", nterrstr(err));
462*671dfc47SDavid du Colombier else
463*671dfc47SDavid du Colombier fprint(2, "err=%s\n", doserrstr(err));
464*671dfc47SDavid du Colombier Raw:
465*671dfc47SDavid du Colombier fprint(2, "\n");
466*671dfc47SDavid du Colombier for(; p < end; p++){
467*671dfc47SDavid du Colombier if((p - (uchar *)buf) % 16 == 0)
468*671dfc47SDavid du Colombier fprint(2, "\n%06lx\t", p - (uchar *)buf);
469*671dfc47SDavid du Colombier if(isprint((char)*p))
470*671dfc47SDavid du Colombier fprint(2, "%c ", (char )*p);
471*671dfc47SDavid du Colombier else
472*671dfc47SDavid du Colombier fprint(2, "%02ux ", *p);
473*671dfc47SDavid du Colombier }
474*671dfc47SDavid du Colombier fprint(2, "\n");
475*671dfc47SDavid du Colombier }
476