Annotation of 43BSD/old/berknet/prot.c, revision 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.