Annotation of 41BSD/cmd/berknet/prot.c, revision 1.1

1.1     ! root        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 (use8bit) 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_use8bit)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_use8bit)
        !           442:                                        ch = getc(netd.dp_rdfile);
        !           443:                                *q++ = ch;
        !           444:                        }
        !           445:                        if(netd.dp_use8bit)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: }

unix.superglobalmegacorp.com

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