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

Defined functions

alarmint defined in line 59; used 1 times
decpacket defined in line 414; used 2 times
getpacket defined in line 347; used 3 times
initseqno defined in line 240; never used
nread defined in line 131; used 10 times
printpacket defined in line 205; never used
sendpacket defined in line 250; used 4 times
sendpurge defined in line 229; used 1 times
xwrite defined in line 66; used 4 times

Defined variables

bufleft defined in line 44; used 7 times
dump defined in line 40; used 11 times
env defined in line 46; used 2 times
lastseqno defined in line 47; used 6 times
masterseqno defined in line 47; used 3 times
netd defined in line 41; used 32 times
retransmit defined in line 45; used 10 times
tooshort defined in line 341; used 5 times
wpack defined in line 49; used 2 times
Last modified: 1980-07-16
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1273
Valid CSS Valid XHTML 1.0 Strict