Annotation of lucent/sys/src/9/port/tcpinput.c, revision 1.1.1.1

1.1       root        1: #include       "u.h"
                      2: #include       "../port/lib.h"
                      3: #include       "mem.h"
                      4: #include       "dat.h"
                      5: #include       "fns.h"
                      6: #include       "../port/error.h"
                      7: #include       "arp.h"
                      8: #include       "../port/ipdat.h"
                      9: 
                     10: int    tcpdbg = 0;
                     11: ushort tcp_mss = DEF_MSS;      /* Maximum segment size to be sent with SYN */
                     12: int    tcp_irtt = DEF_RTT;     /* Initial guess at round trip time */
                     13: 
                     14: #define DPRINT if(tcpdbg) print
                     15: #define LPRINT  if(tcpdbg) print
                     16: 
                     17: char *tcpstate[] =
                     18: {
                     19:        "Closed",       "Listen",       "Syn_sent", "Syn_received",
                     20:        "Established",  "Finwait1",     "Finwait2", "Close_wait",
                     21:        "Closing",      "Last_ack",     "Time_wait"
                     22: };
                     23: 
                     24: void
                     25: sndrst(Ipaddr source, Ipaddr dest, ushort length, Tcp *seg)
                     26: {
                     27:        Block *hbp;
                     28:        Port tmp;
                     29:        char rflags;
                     30:        Tcphdr ph;
                     31: 
                     32:        if(seg->flags & RST)
                     33:                return;
                     34: 
                     35:        hnputl(ph.tcpsrc, dest);
                     36:        hnputl(ph.tcpdst, source);
                     37:        ph.proto = IP_TCPPROTO;
                     38:        hnputs(ph.tcplen, TCP_HDRSIZE);
                     39: 
                     40:        /* Swap port numbers */
                     41:        tmp = seg->dest;
                     42:        seg->dest = seg->source;
                     43:        seg->source = tmp;
                     44: 
                     45:        rflags = RST;
                     46: 
                     47:        /* convince the other end that this reset is in band */
                     48:        if(seg->flags & ACK) {
                     49:                seg->seq = seg->ack;
                     50:                seg->ack = 0;
                     51:        }
                     52:        else {
                     53:                rflags |= ACK;
                     54:                seg->ack = seg->seq;
                     55:                seg->seq = 0;
                     56:                if(seg->flags & SYN)
                     57:                        seg->ack++;
                     58:                seg->ack += length;
                     59:                if(seg->flags & FIN)
                     60:                        seg->ack++;
                     61:        }
                     62:        seg->flags = rflags;
                     63:        seg->wnd = 0;
                     64:        seg->up = 0;
                     65:        seg->mss = 0;
                     66:        if((hbp = htontcp(seg, 0, &ph)) == 0)
                     67:                return;
                     68: 
                     69:        ipmuxoput(0, hbp);
                     70: }
                     71: 
                     72: /*
                     73:  *  flush an incoming call; send a reset to the remote side and close the
                     74:  *  conversation
                     75:  */
                     76: void
                     77: tcpflushincoming(Ipconv *s)
                     78: {
                     79:        Tcp seg;
                     80:        Tcpctl *tcb;
                     81:        uchar dst[4];           
                     82: 
                     83:        tcb = &s->tcpctl;
                     84:        seg.source = s->pdst;
                     85:        seg.dest = s->psrc;
                     86:        seg.flags = ACK;        
                     87:        seg.seq = tcb->snd.ptr;
                     88:        tcb->last_ack = tcb->rcv.nxt;
                     89:        seg.ack = tcb->rcv.nxt;
                     90: 
                     91:        if(s->src == 0){
                     92:                hnputl(dst, s->dst);
                     93:                s->src = ipgetsrc(dst);
                     94:        }
                     95:        sndrst(s->dst, s->src, 0, &seg);
                     96:        localclose(s, 0);
                     97: }
                     98: 
                     99: static void
                    100: tcpmove(struct Tctl *to, struct Tctl *from)
                    101: {
                    102:        memmove(to, from, sizeof(struct Tctl));
                    103: }
                    104: 
                    105: Ipconv*
                    106: tcpincoming(Ipifc *ifc, Ipconv *s, Tcp *segp, Ipaddr source, Ipaddr dest)
                    107: {
                    108:        Ipconv *new;
                    109: 
                    110:        qlock(s);
                    111:        if(s->curlog >= s->backlog){
                    112:                qunlock(s);
                    113:                return 0;
                    114:        }
                    115: 
                    116:        new = ipincoming(ifc, s);
                    117:        if(new == 0){
                    118:                qunlock(s);
                    119:                return 0;
                    120:        }
                    121: 
                    122:        s->curlog++;
                    123:        qunlock(s);
                    124:        new->psrc = segp->dest;
                    125:        new->pdst = segp->source;
                    126:        new->dst = source;
                    127:        new->src = dest;
                    128:        tcpmove(&new->tcpctl, &s->tcpctl);
                    129:        new->tcpctl.flags &= ~CLONE;
                    130:        new->tcpctl.timer.arg = new;
                    131:        new->tcpctl.timer.state = TimerOFF;
                    132:        new->tcpctl.acktimer.arg = new;
                    133:        new->tcpctl.acktimer.state = TimerOFF;
                    134:        new->newcon = s;
                    135: 
                    136:        wakeup(&s->listenr);
                    137:        return new;
                    138: }
                    139: 
                    140: void
                    141: tcpinput(Ipifc *ifc, Block *bp)
                    142: {
                    143:        Tcp seg;
                    144:        char tos;
                    145:        Tcphdr *h;
                    146:        int hdrlen;     
                    147:        Tcpctl *tcb;            
                    148:        ushort length;
                    149:        Ipconv *spec, *gen;
                    150:        Ipaddr source, dest;
                    151:        Ipconv *s, **p, **etab;
                    152: 
                    153:        h = (Tcphdr *)(bp->rptr);
                    154:        dest = nhgetl(h->tcpdst);
                    155:        source = nhgetl(h->tcpsrc);
                    156: 
                    157:        tos = h->tos;
                    158:        length = nhgets(h->length);
                    159: 
                    160:        h->Unused = 0;
                    161:        hnputs(h->tcplen, length - (TCP_IPLEN+TCP_PHDRSIZE));
                    162:        if(ptcl_csum(bp, TCP_EHSIZE+TCP_IPLEN, length - TCP_IPLEN)) {
                    163:                freeb(bp);
                    164:                return;
                    165:        }
                    166: 
                    167:        if((hdrlen = ntohtcp(&seg, &bp)) < 0)
                    168:                return;
                    169: 
                    170:        /* trim the packet to the size claimed by the datagram */
                    171:        length -= (hdrlen+TCP_IPLEN+TCP_PHDRSIZE);
                    172:        bp = btrim(bp, hdrlen+TCP_PKT, length);
                    173:        if(bp == 0)
                    174:                return;
                    175:        
                    176:        /* Look for a connection. failing that look for a listener. */
                    177:        s = ip_conn(ifc, seg.dest, seg.source, source);
                    178:        if(s && s->tcpctl.state == Listen)
                    179:                s = 0;  /* can't talk directly to a listener */
                    180: 
                    181:        if (s == 0) {
                    182:                if(seg.flags & SYN){
                    183:                        /*
                    184:                         *  dump packets with bogus flags
                    185:                         */
                    186:                        if(seg.flags & RST){
                    187:                                freeb(bp);
                    188:                                return;
                    189:                        }
                    190:                        if(seg.flags & ACK) {
                    191:                                freeb(bp);
                    192:                                sndrst(source, dest, length, &seg);
                    193:                                return;
                    194:                        }
                    195: 
                    196:                        /*
                    197:                         *  find a listener specific to this port (spec) or,
                    198:                         *  failing that, a general one (gen)
                    199:                         */
                    200:                        spec = 0;
                    201:                        gen = 0;
                    202:                        etab = &ifc->conv[Nipconv];
                    203:                        for(p = ifc->conv; p < etab && *p; p++) {
                    204:                                s = *p;
                    205:                                if(s->tcpctl.state == Listen)
                    206:                                if(s->pdst == 0)
                    207:                                if(s->dst == 0) {
                    208:                                        if(s->psrc == seg.dest){
                    209:                                                spec = s;
                    210:                                                break;
                    211:                                        }
                    212:                                        if(s->psrc == 0)
                    213:                                                gen = s;
                    214:                                }
                    215:                        }
                    216:                        if(spec)
                    217:                                s = tcpincoming(ifc, spec, &seg, source, dest);
                    218:                        else if(gen)
                    219:                                s = tcpincoming(ifc, gen, &seg, source, dest);
                    220:                        else
                    221:                                s = 0;
                    222:                }
                    223:                if(s == 0){
                    224:                        freeb(bp);   
                    225:                        sndrst(source, dest, length, &seg);
                    226:                        return;
                    227:                }
                    228:        }
                    229: 
                    230:        /* The rest of the input state machine is run with the control block
                    231:         * locked and implements the state machine directly out of the RFC
                    232:         * Out-of-band data is ignored - it was always a bad idea.
                    233:         */
                    234:        tcb = &s->tcpctl;
                    235:        qlock(tcb);
                    236: 
                    237:        switch(tcb->state) {
                    238:        case Closed:
                    239:                freeb(bp);
                    240:                sndrst(source, dest, length, &seg);
                    241:                goto done;
                    242:        case Listen:
                    243:                if((seg.flags & (SYN|RST|ACK)) != SYN) {
                    244:                        /* ignore bogus packets */
                    245: print("packet to channel in listen state %d <- %d\n", s->psrc, s->pdst);
                    246:                        freeb(bp);
                    247:                        goto done;
                    248:                }
                    249: 
                    250:                proc_syn(s, tos, &seg);
                    251:                tcpsndsyn(tcb);
                    252:                tcpsetstate(s, Syn_received);           
                    253:                if(length != 0 || (seg.flags & FIN)) 
                    254:                        break;
                    255:                freeb(bp);
                    256:                goto output;
                    257:        case Syn_sent:
                    258:                if(seg.flags & ACK) {
                    259:                        if(!seq_within(seg.ack, tcb->iss+1, tcb->snd.nxt)) {
                    260:                                freeb(bp);
                    261:                                sndrst(source, dest, length, &seg);
                    262:                                goto done;
                    263:                        }
                    264:                }
                    265:                if(seg.flags & RST) {
                    266:                        if(seg.flags & ACK)
                    267:                                localclose(s, Econrefused);
                    268:                        freeb(bp);
                    269:                        goto done;
                    270:                }
                    271: 
                    272:                if(seg.flags & ACK)
                    273:                if(PREC(tos) != PREC(tcb->tos)){
                    274:                        freeb(bp);
                    275:                        sndrst(source, dest, length, &seg);
                    276:                        goto done;
                    277:                }
                    278: 
                    279:                if(seg.flags & SYN) {
                    280:                        proc_syn(s, tos, &seg);
                    281:                        if(seg.flags & ACK){
                    282:                                update(s, &seg);
                    283:                                tcpsetstate(s, Established);
                    284:                        }
                    285:                        else 
                    286:                                tcpsetstate(s, Syn_received);
                    287: 
                    288:                        if(length != 0 || (seg.flags & FIN))
                    289:                                break;
                    290: 
                    291:                        freeb(bp);
                    292:                        goto output;
                    293:                }
                    294:                else 
                    295:                        freeb(bp);
                    296:                goto done;
                    297:        }
                    298: 
                    299:        /* Cut the data to fit the receive window */
                    300:        if(trim(tcb, &seg, &bp, &length) == -1) {
                    301:                if(!(seg.flags & RST)) {
                    302:                        tcb->flags |= FORCE;
                    303:                        goto output;
                    304:                }
                    305:                goto done;
                    306:        }
                    307: 
                    308:        /* Cannot accept so answer with a rst */
                    309:        if(length)
                    310:        if(s->readq == 0)
                    311:        if(tcb->state == Closed) {
                    312:                freeb(bp);
                    313:                sndrst(source, dest, length, &seg);
                    314:                goto done;
                    315:        }
                    316: 
                    317:        /* The segment is beyond the current receive pointer so
                    318:         * queue the data in the resequence queue
                    319:         */
                    320:        if(seg.seq != tcb->rcv.nxt)
                    321:        if(length != 0 || (seg.flags & (SYN|FIN))) {
                    322:                add_reseq(tcb, tos, &seg, bp, length);
                    323:                tcb->flags |= FORCE;
                    324:                goto output;
                    325:        }
                    326: 
                    327:        /*
                    328:         *  keep looping till we've processed this packet plus any
                    329:         *  adjacent packets in the resequence queue
                    330:         */
                    331:        for(;;) {
                    332:                if(seg.flags & RST) {
                    333:                        localclose(s, Econrefused);
                    334: 
                    335:                        freeb(bp);
                    336:                        goto done;
                    337:                }
                    338: 
                    339:                /* This tos stuff should be removed */
                    340:                if(PREC(tos) != PREC(tcb->tos) || (seg.flags & SYN)){
                    341:                        freeb(bp);
                    342:                        sndrst(source, dest, length, &seg);
                    343:                        goto done;
                    344:                }
                    345: 
                    346:                if(!(seg.flags & ACK)) {
                    347:                        freeb(bp);      
                    348:                        goto done;
                    349:                }
                    350: 
                    351:                switch(tcb->state) {
                    352:                case Syn_received:
                    353:                        if(!seq_within(seg.ack, tcb->snd.una+1, tcb->snd.nxt)){
                    354:                                freeb(bp);
                    355:                                sndrst(source, dest, length, &seg);
                    356:                                goto done;
                    357:                        }
                    358:                        update(s, &seg);
                    359:                        tcpsetstate(s, Established);
                    360:                case Established:
                    361:                case Close_wait:
                    362:                        update(s, &seg);
                    363:                        break;
                    364:                case Finwait1:
                    365:                        update(s, &seg);
                    366:                        if(tcb->sndcnt == 0){
                    367:                                tcb->kacounter = MAXBACKOFF;
                    368:                                tcpsetstate(s, Finwait2);
                    369:                                tcb->timer.start = MSL2 * (1000 / MSPTICK);
                    370:                                tcpgo(&tcb->timer);
                    371:                        }
                    372:                        break;
                    373:                case Finwait2:
                    374:                        update(s, &seg);
                    375:                        break;
                    376:                case Closing:
                    377:                        update(s, &seg);
                    378:                        if(tcb->sndcnt == 0) {
                    379:                                tcpsetstate(s, Time_wait);
                    380:                                tcb->timer.start = MSL2 * (1000 / MSPTICK);
                    381:                                tcpgo(&tcb->timer);
                    382:                        }
                    383:                        break;
                    384:                case Last_ack:
                    385:                        update(s, &seg);
                    386:                        if(tcb->sndcnt == 0) {
                    387:                                freeb(bp);
                    388:                                localclose(s, 0);
                    389:                                goto done;
                    390:                        }                       
                    391:                case Time_wait:
                    392:                        tcb->flags |= FORCE;
                    393:                        tcpgo(&tcb->timer);
                    394:                }
                    395: 
                    396:                if((seg.flags&URG) && seg.up) {
                    397:                        if(seq_gt(seg.up + seg.seq, tcb->rcv.up)) {
                    398:                                tcb->rcv.up = seg.up + seg.seq;
                    399:                                pullb(&bp, seg.up);
                    400:                        }
                    401:                } 
                    402:                else if(seq_gt(tcb->rcv.nxt, tcb->rcv.up))
                    403:                        tcb->rcv.up = tcb->rcv.nxt;
                    404: 
                    405:                if(length == 0){
                    406:                        if(bp)
                    407:                                freeb(bp);
                    408:                }
                    409:                else {
                    410:                        switch(tcb->state){
                    411:                        default:
                    412:                                /* Ignore segment text */
                    413:                                if(bp)
                    414:                                        freeb(bp);
                    415:                                break;
                    416: 
                    417:                        case Syn_received:
                    418:                        case Established:
                    419:                        case Finwait1:
                    420:                                /* If we still have some data place on receive queue */
                    421:                                tcb->rcvcnt += blen(bp);
                    422:                                if(bp){
                    423:                                        if(s->readq)
                    424:                                                PUTNEXT(s->readq, bp);
                    425:                                        else
                    426:                                                putb(&tcb->rcvq, bp);
                    427:                                        bp = 0;
                    428:                                }
                    429:                                tcb->rcv.nxt += length;
                    430: 
                    431:                                tcprcvwin(s);
                    432:        
                    433:                                if(tcb->acktimer.state != TimerON)
                    434:                                        tcpgo(&tcb->acktimer);
                    435: 
                    436:                                if(tcb->rcv.nxt-tcb->last_ack > Streamhi/2)
                    437:                                        tcb->flags |= FORCE;
                    438: 
                    439:                                break;
                    440:                        case Finwait2:
                    441:                                /* no process to read the data, send a reset */
                    442:                                if(bp)
                    443:                                        freeb(bp);
                    444:                                sndrst(source, dest, length, &seg);
                    445:                                goto done;
                    446:                        }
                    447:                }
                    448: 
                    449:                if(seg.flags & FIN) {
                    450:                        tcb->flags |= FORCE;
                    451: 
                    452:                        switch(tcb->state) {
                    453:                        case Syn_received:
                    454:                        case Established:
                    455:                                tcb->rcv.nxt++;
                    456:                                tcpsetstate(s, Close_wait);
                    457:                                break;
                    458:                        case Finwait1:
                    459:                                tcb->rcv.nxt++;
                    460:                                if(tcb->sndcnt == 0) {
                    461:                                        tcpsetstate(s, Time_wait);
                    462:                                        tcb->timer.start = MSL2 * (1000/MSPTICK);
                    463:                                        tcpgo(&tcb->timer);
                    464:                                }
                    465:                                else 
                    466:                                        tcpsetstate(s, Closing);
                    467:                                break;
                    468:                        case Finwait2:
                    469:                                tcb->rcv.nxt++;
                    470:                                tcpsetstate(s, Time_wait);
                    471:                                tcb->timer.start = MSL2 * (1000/MSPTICK);
                    472:                                tcpgo(&tcb->timer);
                    473:                                break;
                    474:                        case Close_wait:
                    475:                        case Closing:
                    476:                        case Last_ack:
                    477:                                break;
                    478:                        case Time_wait:
                    479:                                tcpgo(&tcb->timer);
                    480:                                break;
                    481:                        }
                    482:                }
                    483: 
                    484:                /*
                    485:                 *  get next adjacent segment from the requence queue.
                    486:                 *  dump/trim any overlapping segments
                    487:                 */
                    488:                for(;;) {
                    489:                        if(tcb->reseq == 0)
                    490:                                goto output;
                    491: 
                    492:                        if(seq_ge(tcb->rcv.nxt, tcb->reseq->seg.seq) == 0)
                    493:                                goto output;
                    494: 
                    495:                        get_reseq(tcb, &tos, &seg, &bp, &length);
                    496: 
                    497:                        if(trim(tcb, &seg, &bp, &length) == 0)
                    498:                                break;
                    499:                }
                    500:        }
                    501: output:
                    502:        tcpoutput(s);
                    503: done:
                    504:        qunlock(tcb);
                    505: }
                    506: 
                    507: void
                    508: update(Ipconv *s, Tcp *seg)
                    509: {
                    510:        int rtt;
                    511:        ushort acked;
                    512:        ushort expand;
                    513:        Tcpctl *tcb = &s->tcpctl;
                    514: 
                    515:        tcb->kacounter = MAXBACKOFF;    /* keep alive count down */
                    516: 
                    517:        if(seq_gt(seg->ack, tcb->snd.nxt)) {
                    518:                tcb->flags |= FORCE;
                    519:                return;
                    520:        }
                    521: 
                    522:        if(seq_ge(seg->ack,tcb->snd.wl2))
                    523:        if(seq_gt(seg->seq,tcb->snd.wl1) || (seg->seq == tcb->snd.wl1)) {
                    524:                if(seg->wnd != 0)
                    525:                if(tcb->snd.wnd == 0)
                    526:                        tcb->snd.ptr = tcb->snd.una;
                    527: 
                    528:                tcb->snd.wnd = seg->wnd;
                    529:                tcb->snd.wl1 = seg->seq;
                    530:                tcb->snd.wl2 = seg->ack;
                    531:        }
                    532: 
                    533:        if(!seq_gt(seg->ack, tcb->snd.una))
                    534:                return; 
                    535: 
                    536:        /* Compute the new send window size */
                    537:        acked = seg->ack - tcb->snd.una;
                    538:        if(tcb->cwind < tcb->snd.wnd) {
                    539:                if(tcb->cwind < tcb->ssthresh)
                    540:                        expand = MIN(acked,tcb->mss);
                    541:                else
                    542:                        expand = ((long)tcb->mss * tcb->mss) / tcb->cwind;
                    543: 
                    544:                if(tcb->cwind + expand < tcb->cwind)
                    545:                        expand = 65535 - tcb->cwind;
                    546:                if(tcb->cwind + expand > tcb->snd.wnd)
                    547:                        expand = tcb->snd.wnd - tcb->cwind;
                    548:                if(expand != 0)
                    549:                        tcb->cwind += expand;
                    550:        }
                    551: 
                    552:        /* Adjust the timers acorrding to the round trip time */
                    553:        if(run_timer(&tcb->rtt_timer))
                    554:        if(seq_ge(seg->ack, tcb->rttseq)) {
                    555:                tcphalt(&tcb->rtt_timer);
                    556:                if((tcb->flags&RETRAN) == 0) {
                    557:                        tcb->backoff = 0;
                    558:                        rtt = tcb->rtt_timer.start - tcb->rtt_timer.count;
                    559:                        rtt *= MSPTICK;
                    560:                        if(rtt > tcb->srtt &&
                    561:                          (tcb->state == Syn_sent || tcb->state == Syn_received))
                    562:                                tcb->srtt = rtt;
                    563:                        else {
                    564:                                tcb->srtt = ((AGAIN-1)*tcb->srtt + rtt) / AGAIN;
                    565:                                rtt = abs(rtt - tcb->srtt);
                    566:                                tcb->mdev = ((DGAIN-1)*tcb->mdev + rtt) / DGAIN;
                    567:                        }
                    568:                }
                    569:        }
                    570: 
                    571:        if((tcb->flags & SYNACK) == 0){
                    572:                tcb->flags |= SYNACK;
                    573:                acked--;
                    574:                tcb->sndcnt--;
                    575:        }
                    576: 
                    577:        pullb(&tcb->sndq, acked);
                    578: 
                    579:        tcb->sndcnt -= acked;
                    580:        tcb->snd.una = seg->ack;
                    581:        if(seq_gt(seg->ack, tcb->snd.up))
                    582:                tcb->snd.up = seg->ack;
                    583: 
                    584:        tcphalt(&tcb->timer);
                    585:        if(tcb->snd.una != tcb->snd.nxt)
                    586:                tcpgo(&tcb->timer);
                    587: 
                    588:        if(seq_lt(tcb->snd.ptr, tcb->snd.una))
                    589:                tcb->snd.ptr = tcb->snd.una;
                    590: 
                    591:        tcb->flags &= ~RETRAN;
                    592:        tcb->backoff = 0;
                    593: 
                    594:        if(tcb->sndfull && tcb->sndcnt < Streamhi/2){
                    595:                wakeup(&tcb->sndr);
                    596:                tcb->sndfull = 0;
                    597:        }
                    598: }
                    599: 
                    600: int
                    601: in_window(Tcpctl *tcb, int seq)
                    602: {
                    603:        return seq_within(seq, tcb->rcv.nxt, tcb->rcv.nxt+tcb->rcv.wnd-1);
                    604: }
                    605: 
                    606: void
                    607: proc_syn(Ipconv *s, char tos, Tcp *seg)
                    608: {
                    609:        Tcpctl *tcb = &s->tcpctl;
                    610:        ushort mtu;
                    611: 
                    612: 
                    613:        tcb->flags |= FORCE;
                    614: 
                    615:        if(PREC(tos) > PREC(tcb->tos))
                    616:                tcb->tos = tos;
                    617: 
                    618:        tcb->rcv.up = tcb->rcv.nxt = seg->seq + 1;
                    619:        tcb->snd.wl1 = tcb->irs = seg->seq;
                    620:        tcb->snd.wnd = seg->wnd;
                    621: 
                    622:        if(seg->mss != 0)
                    623:                tcb->mss = seg->mss;
                    624: 
                    625:        tcb->max_snd = seg->wnd;
                    626: /* FIX MTU!!! */
                    627:        if((mtu = 1500) != 0) {
                    628:                mtu -= TCP_HDRSIZE + TCP_EHSIZE + TCP_PHDRSIZE; 
                    629:                tcb->cwind = tcb->mss = MIN(mtu, tcb->mss);
                    630:        }
                    631: }
                    632: 
                    633: /* Generate an initial sequence number and put a SYN on the send queue */
                    634: void
                    635: tcpsndsyn(Tcpctl *tcb)
                    636: {
                    637:        static int start;
                    638: 
                    639:        if(start == 0)
                    640:                start = rtctime();
                    641:        else
                    642:                start += 250000;
                    643:        tcb->iss = start;
                    644:        tcb->rttseq = tcb->iss;
                    645:        tcb->snd.wl2 = tcb->iss;
                    646:        tcb->snd.una = tcb->iss;
                    647:        tcb->snd.ptr = tcb->snd.nxt = tcb->rttseq;
                    648:        tcb->sndcnt++;
                    649:        tcb->flags |= FORCE;
                    650: }
                    651: 
                    652: void
                    653: add_reseq(Tcpctl *tcb, char tos, Tcp *seg, Block *bp, ushort length)
                    654: {
                    655:        Reseq *rp, *rp1;
                    656: 
                    657:        rp = malloc(sizeof(Reseq));
                    658:        if(rp == 0){
                    659:                freeb(bp);      /* bp always consumed by add_reseq */
                    660:                return;
                    661:        }
                    662: 
                    663:        rp->seg = *seg;
                    664:        rp->tos = tos;
                    665:        rp->bp = bp;
                    666:        rp->length = length;
                    667: 
                    668:        /* Place on reassembly list sorting by starting seq number */
                    669:        rp1 = tcb->reseq;
                    670:        if(rp1 == 0 || seq_lt(seg->seq, rp1->seg.seq)) {
                    671:                rp->next = rp1;
                    672:                tcb->reseq = rp;
                    673:                return;
                    674:        }
                    675: 
                    676:        for(;;) {
                    677:                if(rp1->next == 0 || seq_lt(seg->seq, rp1->next->seg.seq)) {
                    678:                        rp->next = rp1->next;
                    679:                        rp1->next = rp;
                    680:                        break;
                    681:                }
                    682:                rp1 = rp1->next;
                    683:        }
                    684: }
                    685: 
                    686: void
                    687: get_reseq(Tcpctl *tcb, char *tos, Tcp *seg, Block **bp, ushort *length)
                    688: {
                    689:        Reseq *rp;
                    690: 
                    691:        rp = tcb->reseq;
                    692:        if(rp == 0)
                    693:                return;
                    694: 
                    695:        tcb->reseq = rp->next;
                    696: 
                    697:        *tos = rp->tos;
                    698:        *seg = rp->seg;
                    699:        *bp = rp->bp;
                    700:        *length = rp->length;
                    701: 
                    702:        free(rp);
                    703: }
                    704: 
                    705: int
                    706: trim(Tcpctl *tcb, Tcp *seg, Block **bp, ushort *length)
                    707: {
                    708:        Block *nbp;
                    709:        long dupcnt;
                    710:        long excess;
                    711:        ushort len;
                    712:        char accept;
                    713: 
                    714:        accept = 0;
                    715:        len = *length;
                    716:        if(seg->flags & SYN)
                    717:                len++;
                    718:        if(seg->flags & FIN)
                    719:                len++;
                    720: 
                    721:        if(tcb->rcv.wnd == 0) {
                    722:                if(len == 0)
                    723:                if(seg->seq == tcb->rcv.nxt)
                    724:                        return 0;
                    725:        }
                    726:        else {
                    727:                /* Some part of the segment should be in the window */
                    728:                if(in_window(tcb,seg->seq))
                    729:                        accept++;
                    730:                else
                    731:                if(len != 0) {
                    732:                        if(in_window(tcb, seg->seq+len-1) || 
                    733:                        seq_within(tcb->rcv.nxt, seg->seq,seg->seq+len-1))
                    734:                                accept++;
                    735:                }
                    736:        }
                    737:        if(!accept) {
                    738:                freeb(*bp);
                    739:                return -1;
                    740:        }
                    741:        dupcnt = tcb->rcv.nxt - seg->seq;
                    742:        if(dupcnt > 0){
                    743:                tcb->rerecv += dupcnt;
                    744:                if(seg->flags & SYN){
                    745:                        seg->flags &= ~SYN;
                    746:                        seg->seq++;
                    747: 
                    748:                        if (seg->up > 1)
                    749:                                seg->up--;
                    750:                        else
                    751:                                seg->flags &= ~URG;
                    752:                        dupcnt--;
                    753:                }
                    754:                if(dupcnt > 0){
                    755:                        pullb(bp, (ushort)dupcnt);
                    756:                        seg->seq += dupcnt;
                    757:                        *length -= dupcnt;
                    758: 
                    759:                        if (seg->up > dupcnt)
                    760:                                seg->up -= dupcnt;
                    761:                        else {
                    762:                                seg->flags &= ~URG;
                    763:                                seg->up = 0;
                    764:                        }
                    765:                }
                    766:        }
                    767:        excess = seg->seq + *length - (tcb->rcv.nxt + tcb->rcv.wnd);
                    768:        if(excess > 0) {
                    769:                tcb->rerecv += excess;
                    770:                *length -= excess;
                    771:                nbp = copyb(*bp, *length);
                    772:                freeb(*bp);
                    773:                *bp = nbp;
                    774:                seg->flags &= ~FIN;
                    775:        }
                    776:        return 0;
                    777: }
                    778: 
                    779: int
                    780: pullb(Block **bph, int count)
                    781: {
                    782:        int n, bytes;
                    783:        Block *bp;
                    784: 
                    785:        bytes = 0;
                    786:        if(bph == 0)
                    787:                return 0;
                    788: 
                    789:        while(*bph && count != 0) {
                    790:                bp = *bph;
                    791:                n = MIN(count, BLEN(bp));
                    792:                bytes += n;
                    793:                count -= n;
                    794:                bp->rptr += n;
                    795:                if(BLEN(bp) == 0) {
                    796:                        *bph = bp->next;
                    797:                        bp->next = 0;
                    798:                        freeb(bp);
                    799:                }
                    800:        }
                    801:        return bytes;
                    802: }
                    803: 
                    804: int
                    805: dupb(Block **hp, Block *bp, int offset, int count)
                    806: {
                    807:        int i, blen, bytes = 0;
                    808:        uchar *addr;
                    809:        
                    810:        *hp = allocb(count);
                    811:        if(*hp == 0)
                    812:                return 0;
                    813: 
                    814:        /* Correct to front of data area */
                    815:        while(bp && offset && offset >= BLEN(bp)) {
                    816:                offset -= BLEN(bp);
                    817:                bp = bp->next;
                    818:        }
                    819:        if(bp == 0)
                    820:                return 0;
                    821: 
                    822:        addr = bp->rptr + offset;
                    823:        blen = BLEN(bp) - offset;
                    824: 
                    825:        while(count) {
                    826:                i = MIN(count, blen);
                    827:                memmove((*hp)->wptr, addr, i);
                    828:                (*hp)->wptr += i;
                    829:                bytes += i;
                    830:                count -= i;
                    831:                bp = bp->next;
                    832:                if(!bp)
                    833:                        break;
                    834:                blen = BLEN(bp);
                    835:                addr = bp->rptr;
                    836:        }
                    837: 
                    838:        return bytes;
                    839: }
                    840: 
                    841: static void
                    842: cleartcp(struct Tctl *a)
                    843: {
                    844:        memset(a, 0, sizeof(struct Tctl));
                    845: }
                    846: 
                    847: void
                    848: init_tcpctl(Ipconv *s)
                    849: {
                    850: 
                    851:        Tcpctl *tcb = &s->tcpctl;
                    852: 
                    853:        cleartcp(tcb);
                    854: 
                    855:        tcb->cwind = tcb->mss = tcp_mss;
                    856:        tcb->ssthresh = 65535;
                    857:        tcb->srtt = tcp_irtt;
                    858: 
                    859:        tcb->timer.start = tcb->srtt / MSPTICK;
                    860:        tcb->timer.func = tcptimeout;
                    861:        tcb->timer.arg = s;
                    862:        tcb->rtt_timer.start = MAX_TIME; 
                    863:        tcb->acktimer.start = TCP_ACK / MSPTICK;
                    864:        tcb->acktimer.func = tcpacktimer;
                    865:        tcb->acktimer.arg = s;
                    866: }
                    867: 
                    868: /*
                    869:  *  called with tcb locked
                    870:  */
                    871: void
                    872: localclose(Ipconv *s, char *reason)
                    873: {
                    874:        Reseq *rp,*rp1;
                    875:        Tcpctl *tcb = &s->tcpctl;
                    876:        Block *bp;
                    877: 
                    878:        tcphalt(&tcb->timer);
                    879:        tcphalt(&tcb->rtt_timer);
                    880:        s->err = reason;
                    881: 
                    882:        /* flush receive queue */
                    883:        while(bp = getb(&tcb->rcvq))
                    884:                freeb(bp);
                    885: 
                    886:        /* Flush reassembly queue; nothing more can arrive */
                    887:        for(rp = tcb->reseq;rp != 0;rp = rp1){
                    888:                rp1 = rp->next;
                    889:                freeb(rp->bp);
                    890:                free(rp);
                    891:        }
                    892: 
                    893:        tcb->reseq = 0;
                    894:        s->err = reason;
                    895:        if(tcb->sndq != 0){
                    896:                freeb(tcb->sndq);
                    897:                tcb->sndq = 0;
                    898:        }
                    899:        tcpsetstate(s, Closed);
                    900: }
                    901: 
                    902: int
                    903: seq_within(ulong x, ulong low, ulong high)
                    904: {
                    905:        if(low <= high){
                    906:                if(low <= x && x <= high)
                    907:                        return 1;
                    908:        }
                    909:        else {
                    910:                if(low >= x && x >= high)
                    911:                        return 1;
                    912:        }
                    913:        return 0;
                    914: }
                    915: 
                    916: int
                    917: seq_lt(ulong x, ulong y)
                    918: {
                    919:        return x < y;
                    920: }
                    921: 
                    922: int
                    923: seq_le(ulong x, ulong y)
                    924: {
                    925:        return x <= y;
                    926: }
                    927: 
                    928: int
                    929: seq_gt(ulong x, ulong y)
                    930: {
                    931:        return x > y;
                    932: }
                    933: 
                    934: int
                    935: seq_ge(ulong x, ulong y)
                    936: {
                    937:        return x >= y;
                    938: }
                    939: 
                    940: void
                    941: tcpsetstate(Ipconv *s, char newstate)
                    942: {
                    943:        Tcpctl *tcb;
                    944:        char oldstate;
                    945: 
                    946:        tcb = &s->tcpctl;
                    947: 
                    948:        oldstate = tcb->state;
                    949:        tcb->state = newstate;
                    950:        tcpxstate(s, oldstate, newstate);
                    951: }
                    952: 
                    953: Block *
                    954: htontcp(Tcp *tcph, Block *data, Tcphdr *ph)
                    955: {
                    956:        int dlen;
                    957:        Tcphdr *h;
                    958:        Block *bp;
                    959:        ushort csum;
                    960:        ushort hdrlen;
                    961: 
                    962:        hdrlen = TCP_HDRSIZE;
                    963:        if(tcph->mss)
                    964:                hdrlen += MSS_LENGTH;
                    965: 
                    966:        if(data) {
                    967:                dlen = blen(data);      
                    968:                data = padb(data, hdrlen + TCP_PKT);
                    969:                if(data == 0)
                    970:                        return 0;
                    971:                /* If we collected blocks delimit the end of the chain */
                    972:                for(bp = data; bp->next; bp = bp->next)
                    973:                        bp->flags &= ~S_DELIM;
                    974:                bp->flags |= S_DELIM;
                    975:        }
                    976:        else {
                    977:                dlen = 0;
                    978:                data = allocb(hdrlen + TCP_PKT);
                    979:                if(data == 0)
                    980:                        return 0;
                    981:                data->wptr += hdrlen + TCP_PKT;
                    982:                data->flags |= S_DELIM;
                    983:        }
                    984: 
                    985: 
                    986:        memmove(data->rptr, ph, TCP_PKT);
                    987:        
                    988:        h = (Tcphdr *)(data->rptr);
                    989:        h->proto = IP_TCPPROTO;
                    990:        h->frag[0] = 0;
                    991:        h->frag[1] = 0;
                    992:        hnputs(h->tcplen, hdrlen + dlen);
                    993:        hnputs(h->tcpsport, tcph->source);
                    994:        hnputs(h->tcpdport, tcph->dest);
                    995:        hnputl(h->tcpseq, tcph->seq);
                    996:        hnputl(h->tcpack, tcph->ack);
                    997:        hnputs(h->tcpflag, (hdrlen<<10) | tcph->flags);
                    998:        hnputs(h->tcpwin, tcph->wnd);
                    999:        h->tcpcksum[0] = 0;
                   1000:        h->tcpcksum[1] = 0;
                   1001:        h->Unused = 0;
                   1002:        hnputs(h->tcpurg, tcph->up);
                   1003: 
                   1004:        if(tcph->mss != 0){
                   1005:                h->tcpopt[0] = MSS_KIND;
                   1006:                h->tcpopt[1] = MSS_LENGTH;
                   1007:                hnputs(h->tcpmss, tcph->mss);
                   1008:        }
                   1009:        csum = ptcl_csum(data, TCP_EHSIZE+TCP_IPLEN, hdrlen+dlen+TCP_PHDRSIZE);
                   1010:        hnputs(h->tcpcksum, csum);
                   1011: 
                   1012:        return data;
                   1013: }
                   1014: 
                   1015: int
                   1016: ntohtcp(Tcp *tcph, Block **bpp)
                   1017: {
                   1018:        ushort hdrlen;
                   1019:        ushort i, optlen;
                   1020:        Tcphdr *h;
                   1021:        uchar *optr;
                   1022: 
                   1023:        *bpp = pullup(*bpp, TCP_PKT+TCP_HDRSIZE);
                   1024:        if(*bpp == 0)
                   1025:                return -1;
                   1026: 
                   1027:        h = (Tcphdr *)((*bpp)->rptr);
                   1028:        tcph->source = nhgets(h->tcpsport);
                   1029:        tcph->dest = nhgets(h->tcpdport);
                   1030:        tcph->seq = nhgetl(h->tcpseq);
                   1031:        tcph->ack = nhgetl(h->tcpack);
                   1032: 
                   1033:        hdrlen = (h->tcpflag[0] & 0xf0) >> 2;
                   1034:        if(hdrlen < TCP_HDRSIZE) {
                   1035:                freeb(*bpp);
                   1036:                return -1;
                   1037:        }
                   1038: 
                   1039:        tcph->flags = h->tcpflag[1];
                   1040:        tcph->wnd = nhgets(h->tcpwin);
                   1041:        tcph->up = nhgets(h->tcpurg);
                   1042:        tcph->mss = 0;
                   1043: 
                   1044:        *bpp = pullup(*bpp, hdrlen+TCP_PKT);
                   1045:        if(!*bpp)
                   1046:                return -1;
                   1047: 
                   1048:        optr = h->tcpopt;
                   1049:        for(i = TCP_HDRSIZE; i < hdrlen;) {
                   1050:                switch(*optr++){
                   1051:                case EOL_KIND:
                   1052:                        return hdrlen;
                   1053:                case NOOP_KIND:
                   1054:                        i++;
                   1055:                        break;
                   1056:                case MSS_KIND:
                   1057:                        optlen = *optr++;
                   1058:                        if(optlen == MSS_LENGTH)
                   1059:                                tcph->mss = nhgets(optr);
                   1060:                        i += optlen;
                   1061:                        break;
                   1062:                }
                   1063:        }
                   1064:        return hdrlen;
                   1065: }

unix.superglobalmegacorp.com

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