Annotation of 43BSD/old/berknet/prot.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.