1*8204Smckusick static char sccsid[] = "@(#)prot.c 4.1 (Berkeley) 09/12/82";
2*8204Smckusick
3*8204Smckusick /* Protocol driver, user level, Berkeley network */
4*8204Smckusick /*
5*8204Smckusick This code is a little complicated because of a number of different
6*8204Smckusick protocols used. Here is an explanation:
7*8204Smckusick
8*8204Smckusick Level Description
9*8204Smckusick
10*8204Smckusick 0 Normal Case (6 bit with no kernel driver support)
11*8204Smckusick
12*8204Smckusick 1 Line Discipline -- uses NETLDISP in sgtty.h and ioctl to set the
13*8204Smckusick line discipline. At Berkeley this means avoiding interrupting on
14*8204Smckusick every character by using a Silo on a DH or DZ board, and (optionally)
15*8204Smckusick bypassing the canonicalization in the tty code by putting the charactars
16*8204Smckusick directly in a buffer.
17*8204Smckusick condition (netd.dp_bnetldis != 0)
18*8204Smckusick
19*8204Smckusick 2 8-bit TTY protocol -- implies Level 1 and inserts record separators(012)
20*8204Smckusick and escapes other occurrences of 012. Since the driver on the other
21*8204Smckusick end must interpolate the escapes, this is an asymmetric protocol where
22*8204Smckusick the sender puts in the escapes but the receiver at the user level knows
23*8204Smckusick they have already been removed.
24*8204Smckusick condition (netd.dp_bnetldis != 0 && netd.dp_use8bit != 0)
25*8204Smckusick
26*8204Smckusick 3 8-bit Block Device protocol -- this is for a DMC-11, it writes fixed
27*8204Smckusick length blocks in both directions with no quoting.
28*8204Smckusick condition (netd.dp_bnetldis != 0 && netd.dp_usehighspeed != 0)
29*8204Smckusick
30*8204Smckusick 4 RAND 8-bit protocol -- included for completeness, is not
31*8204Smckusick correctly specified here.
32*8204Smckusick Specified by an IFDEF.
33*8204Smckusick
34*8204Smckusick If the daemons are being simulated by pipes, then netd.dp_pipesim != 0
35*8204Smckusick and each of the 4 levels (except RAND) are simulated.
36*8204Smckusick In this case at level 2 (use8bit) on the receiver end it does the quoting.
37*8204Smckusick
38*8204Smckusick Timing statistics: We estimate 300 micros for queue/dequeue and then
39*8204Smckusick 20 micros per interrupt for 30 cps => 2.5% of system for 9600 Baud line
40*8204Smckusick
41*8204Smckusick Max packet lengths=> to CSVAX with 1k buffers and 6-bit prot = 758 chars
42*8204Smckusick to Ing70 with 512 byte buffers and no NETLDISC, only 182 chars
43*8204Smckusick
44*8204Smckusick */
45*8204Smckusick # include "defs.h"
46*8204Smckusick
47*8204Smckusick /* global */
48*8204Smckusick struct dumpstruc dump;
49*8204Smckusick struct daemonparms netd;
50*8204Smckusick
51*8204Smckusick /* local */
52*8204Smckusick static int bufleft;
53*8204Smckusick static char retransmit;
54*8204Smckusick static jmp_buf env;
55*8204Smckusick static short masterseqno, lastseqno;
56*8204Smckusick /* writing packet */
57*8204Smckusick static char wpack[MAXNBUF];
58*8204Smckusick
59*8204Smckusick /*
60*8204Smckusick one problem has been character loss on
61*8204Smckusick overloaded systems due to the daemon
62*8204Smckusick taking too long to swap in
63*8204Smckusick and losing characters.
64*8204Smckusick A high priority process of small size
65*8204Smckusick with a pipe would do the job.
66*8204Smckusick */
alarmint()67*8204Smckusick alarmint(){
68*8204Smckusick errno = 100;
69*8204Smckusick signal(SIGALRM,SIG_IGN); /* alarm off */
70*8204Smckusick longjmp(env,0); /* ugh */
71*8204Smckusick }
72*8204Smckusick /* returns number of bytes written, error returns WRITEFAIL (-3) */
73*8204Smckusick /* inbuf is buffer of amt chars to be written */
xwrite(inbuf,amt)74*8204Smckusick xwrite(inbuf,amt)
75*8204Smckusick char *inbuf;
76*8204Smckusick {
77*8204Smckusick register char *p, *b;
78*8204Smckusick register int i;
79*8204Smckusick int cnt, num, savetime;
80*8204Smckusick struct packet *rpp, *xptr;
81*8204Smckusick
82*8204Smckusick xptr = (struct packet *)wpack;
83*8204Smckusick cnt = 0;
84*8204Smckusick retransmit = 0;
85*8204Smckusick savetime = netd.dp_atime;
86*8204Smckusick while(amt > 0){
87*8204Smckusick if(retransmit > netd.dp_maxbread){
88*8204Smckusick debug("xwrite fail");
89*8204Smckusick return(WRITEFAIL);
90*8204Smckusick }
91*8204Smckusick /* format the packet to send */
92*8204Smckusick num = min(netd.dp_datasize,amt);
93*8204Smckusick /* set the length down if escapes are being used */
94*8204Smckusick if(netd.dp_use8bit)num = min(num,MAXNBUF/2);
95*8204Smckusick xptr->pcode = REQUEST;
96*8204Smckusick xptr->seqno = masterseqno;
97*8204Smckusick xptr->len = num;
98*8204Smckusick p = xptr->data;
99*8204Smckusick i = num;
100*8204Smckusick b = inbuf+cnt;
101*8204Smckusick while(i--)*p++ = *b++;
102*8204Smckusick /* send it */
103*8204Smckusick sendpacket(xptr);
104*8204Smckusick rpp = getpacket();
105*8204Smckusick if(rpp == NULL){
106*8204Smckusick netd.dp_atime += 3; /* wait three more secs */
107*8204Smckusick retransmit++;
108*8204Smckusick dump.nretrans++;
109*8204Smckusick continue;
110*8204Smckusick }
111*8204Smckusick /* various errors */
112*8204Smckusick if(rpp->chksum != 0 || rpp->pcode != ACK
113*8204Smckusick || rpp->seqno != xptr->seqno ){
114*8204Smckusick if(rpp->seqno == 1 && rpp->pcode == REQUEST){
115*8204Smckusick error("collision");
116*8204Smckusick return(WRITEFAIL);
117*8204Smckusick }
118*8204Smckusick if(rpp->chksum != 0)
119*8204Smckusick error("chksum %d",rpp->seqno);
120*8204Smckusick else if(rpp->pcode != ACK)
121*8204Smckusick error("not ack %d %d",rpp->pcode,rpp->seqno);
122*8204Smckusick else if(rpp->seqno != xptr ->seqno)
123*8204Smckusick error("WRSQNO got %d request %d",rpp->seqno,
124*8204Smckusick xptr->seqno);
125*8204Smckusick netd.dp_atime += 3;
126*8204Smckusick retransmit++;
127*8204Smckusick dump.nretrans++;
128*8204Smckusick continue;
129*8204Smckusick }
130*8204Smckusick masterseqno++;
131*8204Smckusick retransmit = 0;
132*8204Smckusick amt -= num;
133*8204Smckusick cnt += num;
134*8204Smckusick }
135*8204Smckusick netd.dp_atime = savetime;
136*8204Smckusick return(cnt);
137*8204Smckusick }
138*8204Smckusick /* return the number of bytes read, or error = BROKENREAD (-2) */
nread(bptr,num)139*8204Smckusick nread(bptr,num)
140*8204Smckusick register char *bptr;
141*8204Smckusick {
142*8204Smckusick register char *p;
143*8204Smckusick register struct packet *pp;
144*8204Smckusick register char *q;
145*8204Smckusick int bcnt = 0;
146*8204Smckusick int n,j,cnt;
147*8204Smckusick static char savebuf[MAXNBUF];
148*8204Smckusick
149*8204Smckusick /* first see if theres any left from the last packet */
150*8204Smckusick cnt = 0;
151*8204Smckusick if(bufleft > 0){
152*8204Smckusick p = savebuf;
153*8204Smckusick cnt = n = min(bufleft,num);
154*8204Smckusick while(n--)*bptr++ = *p++;
155*8204Smckusick num -= cnt;
156*8204Smckusick bufleft -= cnt;
157*8204Smckusick if(bufleft > 0){
158*8204Smckusick q = savebuf;
159*8204Smckusick n = bufleft;
160*8204Smckusick while(n--)*q++ = *p++;
161*8204Smckusick }
162*8204Smckusick }
163*8204Smckusick if(num <= 0)
164*8204Smckusick return(cnt);
165*8204Smckusick /* now read a packet */
166*8204Smckusick retransmit = 0;
167*8204Smckusick for(;;){
168*8204Smckusick pp = getpacket();
169*8204Smckusick if(pp == NULL){
170*8204Smckusick if(++bcnt >= netd.dp_maxbread){
171*8204Smckusick debug("read timeout");
172*8204Smckusick return(BROKENREAD);
173*8204Smckusick }
174*8204Smckusick continue;
175*8204Smckusick }
176*8204Smckusick /* various errors */
177*8204Smckusick if(pp->chksum != 0){
178*8204Smckusick error("chksum %d",pp->seqno);
179*8204Smckusick retransmit++;
180*8204Smckusick continue;
181*8204Smckusick }
182*8204Smckusick if(pp->pcode & ~REQUEST){
183*8204Smckusick error("pcode %d %d",pp->pcode,pp->seqno);
184*8204Smckusick retransmit++;
185*8204Smckusick continue;
186*8204Smckusick }
187*8204Smckusick /* this is the normal case, so we ack it */
188*8204Smckusick else { /* else was a REQUEST packet, no chksum errs */
189*8204Smckusick /*
190*8204Smckusick if(pp->seqno == 1)debug("^R ");
191*8204Smckusick */
192*8204Smckusick pp->pcode = ACK;
193*8204Smckusick n = pp->len;
194*8204Smckusick pp->len = 0;
195*8204Smckusick sendpacket(pp); /* send ACK */
196*8204Smckusick pp->len = n;
197*8204Smckusick break;
198*8204Smckusick }
199*8204Smckusick }
200*8204Smckusick /* now process this packet, bptr points to where we left off */
201*8204Smckusick retransmit = 0;
202*8204Smckusick j = n = min(num,pp->len);
203*8204Smckusick cnt += j;
204*8204Smckusick p = pp->data;
205*8204Smckusick while(n--)*bptr++ = *p++;
206*8204Smckusick if(pp->len > num){
207*8204Smckusick n = bufleft = pp->len - num;
208*8204Smckusick bptr = savebuf;
209*8204Smckusick while(n--)*bptr++ = *p++;
210*8204Smckusick }
211*8204Smckusick return(cnt);
212*8204Smckusick }
printpacket(pp,dest)213*8204Smckusick printpacket(pp,dest)
214*8204Smckusick char *dest;
215*8204Smckusick struct packet *pp; {
216*8204Smckusick char *s;
217*8204Smckusick int i;
218*8204Smckusick char c;
219*8204Smckusick dest[0] = 0;
220*8204Smckusick if(pp == NULL)return;
221*8204Smckusick if(pp->pcode == REQUEST)c='r';
222*8204Smckusick else if(pp->pcode == ACK)c = 'a';
223*8204Smckusick else if(pp->pcode == PURGE)c = 'p';
224*8204Smckusick else c = 'u';
225*8204Smckusick sprintf(dest,"p:%d len:%d c:%c d:", pp->seqno, pp->len, c);
226*8204Smckusick s = dest + strlen(dest);
227*8204Smckusick for(i=0; i<pp->len && pp->data[i]; i++)*s++ = pp->data[i];
228*8204Smckusick *s = 0;
229*8204Smckusick }
230*8204Smckusick /*
231*8204Smckusick * A purge can always be sent -
232*8204Smckusick * the receiver totally ignores it.
233*8204Smckusick * It is used to push the packet terminator
234*8204Smckusick * down the wire in case of a crash
235*8204Smckusick * leaving the receiver half reading.
236*8204Smckusick */
sendpurge()237*8204Smckusick sendpurge()
238*8204Smckusick {
239*8204Smckusick struct packet *xptr;
240*8204Smckusick xptr = (struct packet *)wpack;
241*8204Smckusick xptr->pcode = PURGE;
242*8204Smckusick xptr->seqno = 0;
243*8204Smckusick xptr->len = 0;
244*8204Smckusick debug("send purge");
245*8204Smckusick sendpacket(xptr);
246*8204Smckusick }
247*8204Smckusick /* init sequence numbers */
initseqno()248*8204Smckusick initseqno(){
249*8204Smckusick masterseqno = 1;
250*8204Smckusick lastseqno = 0;
251*8204Smckusick bufleft = 0; /* if any chars are left in buffer, flush them*/
252*8204Smckusick netd.dp_atime = netd.dp_oatime + ((rand()>>8)%15);
253*8204Smckusick }
254*8204Smckusick /*
255*8204Smckusick * Just sends packet pp
256*8204Smckusick * Calculates the chksum
257*8204Smckusick */
258*8204Smckusick sendpacket(pp)
259*8204Smckusick struct packet *pp; {
260*8204Smckusick register char *q, *p;
261*8204Smckusick register int j;
262*8204Smckusick char *finalp;
263*8204Smckusick static char raw[MAXNBUF];
264*8204Smckusick int len, n, i;
265*8204Smckusick
266*8204Smckusick /* writes the data to be sent in array raw */
267*8204Smckusick /* finalp will point to either pp or raw */
268*8204Smckusick dump.nbytesent += pp->len;
269*8204Smckusick dump.npacksent++;
270*8204Smckusick pp->chksum = 0;
271*8204Smckusick n = 0;
272*8204Smckusick p = (char *)pp;
273*8204Smckusick len = ACKLENGTH + pp->len;
274*8204Smckusick for(j = 0; j < len; j++)n ^= *p++;
275*8204Smckusick pp->chksum = n;
276*8204Smckusick # ifdef SWAB
277*8204Smckusick switchem(pp);
278*8204Smckusick # endif
279*8204Smckusick # ifndef RAND
280*8204Smckusick if(netd.dp_usehispeed)finalp = (char *)pp;
281*8204Smckusick else if(netd.dp_use8bit){
282*8204Smckusick if(len >= MAXNBUF){
283*8204Smckusick fprintf(stderr,"Packet size too big- error\n");
284*8204Smckusick exit(1);
285*8204Smckusick }
286*8204Smckusick /* add escapes */
287*8204Smckusick p = (char *)pp;
288*8204Smckusick q = raw;
289*8204Smckusick i = len;
290*8204Smckusick len = 0;
291*8204Smckusick for(j = 0; j < i; j++){
292*8204Smckusick if(*p == '\n' || *p == '\\'){
293*8204Smckusick *q++ = '\\';
294*8204Smckusick *q++ = *p++;
295*8204Smckusick len++;
296*8204Smckusick len++;
297*8204Smckusick }
298*8204Smckusick else {
299*8204Smckusick *q++ = *p++;
300*8204Smckusick len++;
301*8204Smckusick }
302*8204Smckusick }
303*8204Smckusick *q = '\n';
304*8204Smckusick len++;
305*8204Smckusick finalp = raw;
306*8204Smckusick }
307*8204Smckusick else {
308*8204Smckusick /* now change 8-bit data to 6-bit data */
309*8204Smckusick if(((len+2)*4)/3 >= MAXNBUF){
310*8204Smckusick fprintf(stderr,"Packet size too big- error\n");
311*8204Smckusick exit(1);
312*8204Smckusick }
313*8204Smckusick p = raw;
314*8204Smckusick q = (char *)pp;
315*8204Smckusick len = n = (len+2)/3;
316*8204Smckusick while(n--){
317*8204Smckusick *p++ = (*q & 077) + INCR;
318*8204Smckusick j = (*q++ >> 6) &03;
319*8204Smckusick *p++ = (((*q << 2) | j) & 077) + INCR;
320*8204Smckusick j = (*q++ >> 4) & 017;
321*8204Smckusick *p++ = (((*q << 4) | j) & 077) + INCR;
322*8204Smckusick *p++ = ((*q++ >> 2) & 077) + INCR;
323*8204Smckusick }
324*8204Smckusick *p++ = '\n';
325*8204Smckusick *p = 0;
326*8204Smckusick /* because of bugs in processing around erase and kill in v6 */
327*8204Smckusick for(p=raw; *p; p++)
328*8204Smckusick if(*p == '\\')*p = '}';
329*8204Smckusick len = len * 4 + 1;
330*8204Smckusick finalp = raw;
331*8204Smckusick }
332*8204Smckusick /*
333*8204Smckusick debug("send %d <<%s>>",len,raw);
334*8204Smckusick */
335*8204Smckusick if(netd.dp_usehispeed){
336*8204Smckusick if(len > SENDLEN)error("send length too long");
337*8204Smckusick len = SENDLEN;
338*8204Smckusick }
339*8204Smckusick if(netd.dp_pipesim) i = write(netd.dp_pwritefd,finalp,len);
340*8204Smckusick else i = write(netd.dp_linefd,finalp,len);
341*8204Smckusick dump.braw += i;
342*8204Smckusick dump.brawtot += i;
343*8204Smckusick # ifdef SWAB
344*8204Smckusick switchem(pp);
345*8204Smckusick # endif
346*8204Smckusick # else
347*8204Smckusick /* for RAND */
348*8204Smckusick i = write(netd.dp_linefd, (char *)pp,len);
349*8204Smckusick # endif
350*8204Smckusick /*
351*8204Smckusick debug("count %d",i);
352*8204Smckusick */
353*8204Smckusick }
354*8204Smckusick
355*8204Smckusick static int tooshort;
356*8204Smckusick /*
357*8204Smckusick * returns NULL if couldn't get a packet with correct seqno
358*8204Smckusick * chksum not checked here
359*8204Smckusick * because other programs may want to interrogate checksum
360*8204Smckusick */
getpacket()361*8204Smckusick struct packet *getpacket() {
362*8204Smckusick register struct packet *gptr;
363*8204Smckusick register char *p;
364*8204Smckusick register int i;
365*8204Smckusick int n, bcnt, len;
366*8204Smckusick struct packet *decpacket();
367*8204Smckusick
368*8204Smckusick bcnt = 0;
369*8204Smckusick errno = 0;
370*8204Smckusick setjmp(env);
371*8204Smckusick alarm(0);
372*8204Smckusick signal(SIGALRM,alarmint);
373*8204Smckusick for(;;){
374*8204Smckusick if(bcnt++ > netd.dp_maxbread)errno = 100; /* give up */
375*8204Smckusick if(errno == 100){
376*8204Smckusick if(debugflg)putchar('^');
377*8204Smckusick return(NULL);
378*8204Smckusick }
379*8204Smckusick /* decode the buffer, including 6-8 bit conv, etc. */
380*8204Smckusick gptr = decpacket();
381*8204Smckusick if(gptr == NULL){
382*8204Smckusick error("getpacket fails");
383*8204Smckusick return(NULL);
384*8204Smckusick }
385*8204Smckusick if(tooshort || gptr->len < 0 || gptr->len > MAXNBUF){
386*8204Smckusick error("too short p:%d l:%d",gptr->seqno,gptr->len);
387*8204Smckusick continue;
388*8204Smckusick }
389*8204Smckusick if(gptr->seqno == 1 && gptr->pcode != ACK){
390*8204Smckusick debug("got reset");
391*8204Smckusick addtolog(remote,"^R ");
392*8204Smckusick }
393*8204Smckusick if(gptr->pcode == PURGE){
394*8204Smckusick debug("got purge");
395*8204Smckusick continue; /* never seen */
396*8204Smckusick }
397*8204Smckusick if(gptr->seqno == lastseqno){
398*8204Smckusick if(retransmit)break;
399*8204Smckusick /* send ACK - it was lost first time thru */
400*8204Smckusick len = gptr->len;
401*8204Smckusick n = gptr->pcode;
402*8204Smckusick gptr->len = 0;
403*8204Smckusick gptr->pcode = ACK;
404*8204Smckusick sendpacket(gptr);
405*8204Smckusick gptr->len = len;
406*8204Smckusick gptr->pcode = n;
407*8204Smckusick error("sendlostack %d",lastseqno);
408*8204Smckusick break;
409*8204Smckusick }
410*8204Smckusick /* this is the correct case */
411*8204Smckusick if(gptr->seqno == lastseqno + 1)break;
412*8204Smckusick error("Wrong seq no g: %d last: %d",gptr->seqno,
413*8204Smckusick lastseqno);
414*8204Smckusick }
415*8204Smckusick lastseqno = gptr->seqno;
416*8204Smckusick n = 0;
417*8204Smckusick len = gptr->len + ACKLENGTH;
418*8204Smckusick p = (char *)gptr;
419*8204Smckusick for(i=0; i < len; i++)n ^= *p++;
420*8204Smckusick gptr->chksum = n;
421*8204Smckusick if(n != 0)dump.ncksum++;
422*8204Smckusick dump.nbytercv += gptr->len;
423*8204Smckusick dump.npackrcv++;
424*8204Smckusick return(gptr);
425*8204Smckusick }
426*8204Smckusick /* read in and decode packet */
427*8204Smckusick /* as a side effect sets "tooshort" */
decpacket()428*8204Smckusick static struct packet *decpacket()
429*8204Smckusick {
430*8204Smckusick # ifndef RAND
431*8204Smckusick register char *p, *q;
432*8204Smckusick register int i,j;
433*8204Smckusick int n, len, ch;
434*8204Smckusick struct packet *pp;
435*8204Smckusick static char cooked[MAXNBUF], raw[MAXNBUF];
436*8204Smckusick
437*8204Smckusick /* read in chars to raw, if processed then return in cooked, otherwise
438*8204Smckusick return in raw */
439*8204Smckusick alarm(netd.dp_atime);
440*8204Smckusick tooshort = 0;
441*8204Smckusick if(netd.dp_pipesim){
442*8204Smckusick if(netd.dp_usehispeed)
443*8204Smckusick len = read(fileno(netd.dp_rdfile),raw,SENDLEN);
444*8204Smckusick else {
445*8204Smckusick q = raw;
446*8204Smckusick len = 0;
447*8204Smckusick for(;;){
448*8204Smckusick ch = getc(netd.dp_rdfile);
449*8204Smckusick len++;
450*8204Smckusick if(ch == '\n'){
451*8204Smckusick *q++ = '\n';
452*8204Smckusick break;
453*8204Smckusick }
454*8204Smckusick /* eat up the backslashes */
455*8204Smckusick if(ch == '\\' && netd.dp_use8bit)
456*8204Smckusick ch = getc(netd.dp_rdfile);
457*8204Smckusick *q++ = ch;
458*8204Smckusick }
459*8204Smckusick if(netd.dp_use8bit)len--;
460*8204Smckusick }
461*8204Smckusick }
462*8204Smckusick else if(netd.dp_usehispeed)
463*8204Smckusick len = read(fileno(netd.dp_rdfile),raw,SENDLEN);
464*8204Smckusick else len = read(netd.dp_linefd,raw,MAXNBUF);
465*8204Smckusick alarm(0);
466*8204Smckusick if(len == 0)fprintf(stderr,"eof pip %d\n",fileno(netd.dp_rdfile));
467*8204Smckusick if(len <= 0)return(NULL);
468*8204Smckusick raw[len] = 0;
469*8204Smckusick dump.braw += len;
470*8204Smckusick dump.brawtot += len;
471*8204Smckusick /*
472*8204Smckusick debug("receive %d <<%s>>",len,raw);
473*8204Smckusick */
474*8204Smckusick /* if 8 bit the all we need to do is return */
475*8204Smckusick if(netd.dp_usehispeed)return((struct packet *)raw);
476*8204Smckusick if(netd.dp_use8bit){
477*8204Smckusick pp = (struct packet *)raw;
478*8204Smckusick if(len != ACKLENGTH + pp->len)tooshort = 1;
479*8204Smckusick return(pp);
480*8204Smckusick }
481*8204Smckusick /* remove this loop later */
482*8204Smckusick for(p=raw; *p; p++)
483*8204Smckusick if(*p == '}')*p = '\\';
484*8204Smckusick p = raw;
485*8204Smckusick q = cooked;
486*8204Smckusick n = (len+3) /4;
487*8204Smckusick while(n--){
488*8204Smckusick if(*p == '\n')break;
489*8204Smckusick if(*p < INCR || *p & 0200)error("bad char %o\n",*p);
490*8204Smckusick i = *p++ - INCR;
491*8204Smckusick j = *p++ - INCR;
492*8204Smckusick *q++ = ((j & 03) << 6) | (i & 077);
493*8204Smckusick i = *p++ -INCR;
494*8204Smckusick *q++ = ((i & 017) << 4) | ((j >> 2) & 017);
495*8204Smckusick j = *p++ - INCR;
496*8204Smckusick *q++ = ((j & 077) << 2) | ((i >> 4) & 03);
497*8204Smckusick }
498*8204Smckusick *q = 0;
499*8204Smckusick pp = (struct packet *)cooked;
500*8204Smckusick # ifdef SWAB
501*8204Smckusick switchem(pp);
502*8204Smckusick # endif
503*8204Smckusick if(len != ((ACKLENGTH + pp->len + 2)/3)*4 + 1) tooshort = 1;
504*8204Smckusick # else
505*8204Smckusick /* for RAND */
506*8204Smckusick /* not sure of the length computation */
507*8204Smckusick if(len != ACKLENGTH + gptr->len) tooshort = 1;
508*8204Smckusick # endif
509*8204Smckusick return((struct packet *)cooked);
510*8204Smckusick }
511*8204Smckusick
512*8204Smckusick # ifdef SWAB
switchem(pp)513*8204Smckusick switchem(pp)
514*8204Smckusick register struct packet *pp; {
515*8204Smckusick register short *p;
516*8204Smckusick p = &(pp->seqno);
517*8204Smckusick swab(p, p, 2);
518*8204Smckusick p = &(pp->len);
519*8204Smckusick swab(p, p, 2);
520*8204Smckusick }
521*8204Smckusick # endif
522