Annotation of 40BSD/cmd/berknet/prot.c, revision 1.1.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.