Annotation of 43BSD/sys/netns/spp_usrreq.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1984, 1985, 1986 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  *
                      6:  *     @(#)spp_usrreq.c        7.1 (Berkeley) 6/5/86
                      7:  */
                      8: 
                      9: #include "param.h"
                     10: #include "dir.h"
                     11: #include "user.h"
                     12: #include "mbuf.h"
                     13: #include "protosw.h"
                     14: #include "socket.h"
                     15: #include "socketvar.h"
                     16: #include "errno.h"
                     17: 
                     18: #include "../net/if.h"
                     19: #include "../net/route.h"
                     20: #include "../netinet/tcp_fsm.h"
                     21: #include "../netinet/tcp_timer.h"
                     22: 
                     23: #include "ns.h"
                     24: #include "ns_pcb.h"
                     25: #include "idp.h"
                     26: #include "idp_var.h"
                     27: #include "ns_error.h"
                     28: #include "sp.h"
                     29: #include "spidp.h"
                     30: #include "spp_var.h"
                     31: #include "spp_debug.h"
                     32: 
                     33: /*
                     34:  * SP protocol implementation.
                     35:  */
                     36: spp_init()
                     37: {
                     38: 
                     39:        spp_iss = 1; /* WRONG !! should fish it out of TODR */
                     40: }
                     41: struct spidp spp_savesi;
                     42: int traceallspps = 0;
                     43: extern int sppconsdebug;
                     44: int spp_hardnosed;
                     45: int spp_use_delack = 0;
                     46: 
                     47: /*ARGSUSED*/
                     48: spp_input(m, nsp, ifp)
                     49:        register struct mbuf *m;
                     50:        register struct nspcb *nsp;
                     51:        struct ifnet *ifp;
                     52: {
                     53:        register struct sppcb *cb;
                     54:        register struct spidp *si = mtod(m, struct spidp *);
                     55:        register struct socket *so;
                     56:        short ostate;
                     57:        int dropsocket = 0;
                     58: 
                     59: 
                     60:        if (nsp == 0) {
                     61:                panic("No nspcb in spp_input\n");
                     62:                return;
                     63:        }
                     64: 
                     65:        cb = nstosppcb(nsp);
                     66:        if (cb == 0) goto bad;
                     67: 
                     68:        if (m->m_len < sizeof(*si)) {
                     69:                if ((m = m_pullup(m, sizeof(*si))) == 0) {
                     70:                        spp_istat.hdrops++;
                     71:                        return;
                     72:                }
                     73:                si = mtod(m, struct spidp *);
                     74:        }
                     75:        si->si_seq = ntohs(si->si_seq);
                     76:        si->si_ack = ntohs(si->si_ack);
                     77:        si->si_alo = ntohs(si->si_alo);
                     78: 
                     79:        so = nsp->nsp_socket;
                     80:        if (so->so_options & SO_DEBUG || traceallspps) {
                     81:                ostate = cb->s_state;
                     82:                spp_savesi = *si;
                     83:        }
                     84:        if (so->so_options & SO_ACCEPTCONN) {
                     85:                so = sonewconn(so);
                     86:                if (so == 0) {
                     87:                        spp_istat.nonucn++;
                     88:                        goto drop;
                     89:                }
                     90:                /*
                     91:                 * This is ugly, but ....
                     92:                 *
                     93:                 * Mark socket as temporary until we're
                     94:                 * committed to keeping it.  The code at
                     95:                 * ``drop'' and ``dropwithreset'' check the
                     96:                 * flag dropsocket to see if the temporary
                     97:                 * socket created here should be discarded.
                     98:                 * We mark the socket as discardable until
                     99:                 * we're committed to it below in TCPS_LISTEN.
                    100:                 */
                    101:                dropsocket++;
                    102:                nsp = (struct nspcb *)so->so_pcb;
                    103:                nsp->nsp_laddr = si->si_dna;
                    104:                cb = nstosppcb(nsp);
                    105:                cb->s_state = TCPS_LISTEN;
                    106:        }
                    107: 
                    108:        /*
                    109:         * Packet received on connection.
                    110:         * reset idle time and keep-alive timer;
                    111:         */
                    112:        cb->s_idle = 0;
                    113:        cb->s_timer[TCPT_KEEP] = TCPTV_KEEP;
                    114: 
                    115:        switch (cb->s_state) {
                    116: 
                    117:        case TCPS_LISTEN:{
                    118:                struct mbuf *am;
                    119:                register struct sockaddr_ns *sns;
                    120:                struct ns_addr laddr;
                    121: 
                    122:                /*
                    123:                 * If somebody here was carying on a conversation
                    124:                 * and went away, and his pen pal thinks he can
                    125:                 * still talk, we get the misdirected packet.
                    126:                 */
                    127:                if (spp_hardnosed && (si->si_did != 0 || si->si_seq != 0)) {
                    128:                        spp_istat.gonawy++;
                    129:                        goto dropwithreset;
                    130:                }
                    131:                am = m_get(M_DONTWAIT, MT_SONAME);
                    132:                if (am == NULL)
                    133:                        goto drop;
                    134:                am->m_len = sizeof (struct sockaddr_ns);
                    135:                sns = mtod(am, struct sockaddr_ns *);
                    136:                sns->sns_family = AF_NS;
                    137:                sns->sns_addr = si->si_sna;
                    138:                laddr = nsp->nsp_laddr;
                    139:                if (ns_nullhost(laddr))
                    140:                        nsp->nsp_laddr = si->si_dna;
                    141:                if (ns_pcbconnect(nsp, am)) {
                    142:                        nsp->nsp_laddr = laddr;
                    143:                        (void) m_free(am);
                    144:                        spp_istat.noconn++;
                    145:                        goto drop;
                    146:                }
                    147:                (void) m_free(am);
                    148:                spp_template(cb);
                    149:                dropsocket = 0;         /* committed to socket */
                    150:                cb->s_did = si->si_sid;
                    151:                cb->s_rack = si->si_ack;
                    152:                cb->s_ralo = si->si_alo;
                    153: #define THREEWAYSHAKE
                    154: #ifdef THREEWAYSHAKE
                    155:                cb->s_state = TCPS_SYN_RECEIVED;
                    156:                cb->s_force = 1 + TCPT_REXMT;
                    157:                cb->s_timer[TCPT_REXMT] = 2 * TCPTV_MIN;
                    158:                }
                    159:                break;
                    160:        /*
                    161:         * This state means that we have heard a response
                    162:         * to our acceptance of their connection
                    163:         * It is probably logically unnecessary in this
                    164:         * implementation.
                    165:         */
                    166:         case TCPS_SYN_RECEIVED:
                    167:                if (si->si_did!=cb->s_sid) {
                    168:                        spp_istat.wrncon++;
                    169:                        goto drop;
                    170:                }
                    171: #endif
                    172:                nsp->nsp_fport =  si->si_sport;
                    173:                cb->s_timer[TCPT_REXMT] = 0;
                    174:                cb->s_timer[TCPT_KEEP] = TCPTV_KEEP;
                    175:                soisconnected(so);
                    176:                cb->s_state = TCPS_ESTABLISHED;
                    177:                break;
                    178: 
                    179:        /*
                    180:         * This state means that we have gotten a response
                    181:         * to our attempt to establish a connection.
                    182:         * We fill in the data from the other side,
                    183:         * telling us which port to respond to, instead of the well-
                    184:         * known one we might have sent to in the first place.
                    185:         * We also require that this is a response to our
                    186:         * connection id.
                    187:         */
                    188:        case TCPS_SYN_SENT:
                    189:                if (si->si_did!=cb->s_sid) {
                    190:                        spp_istat.notme++;
                    191:                        goto drop;
                    192:                }
                    193:                cb->s_did = si->si_sid;
                    194:                cb->s_rack = si->si_ack;
                    195:                cb->s_ralo = si->si_alo;
                    196:                cb->s_dport = nsp->nsp_fport =  si->si_sport;
                    197:                cb->s_timer[TCPT_REXMT] = 0;
                    198:                cb->s_flags |= SF_AK;
                    199:                soisconnected(so);
                    200:                cb->s_state = TCPS_ESTABLISHED;
                    201:        }
                    202:        if (so->so_options & SO_DEBUG || traceallspps)
                    203:                spp_trace(SA_INPUT, (u_char)ostate, cb, &spp_savesi, 0);
                    204: 
                    205:        m->m_len -= sizeof (struct idp);
                    206:        m->m_off += sizeof (struct idp);
                    207: 
                    208:        if (spp_reass(cb, si)) {
                    209:                m_freem(m);
                    210:        }
                    211:        (void) spp_output(cb, (struct mbuf *)0);
                    212:        return;
                    213: 
                    214: dropwithreset:
                    215:        if (dropsocket)
                    216:                (void) soabort(so);
                    217:        si->si_seq = ntohs(si->si_seq);
                    218:        si->si_ack = ntohs(si->si_ack);
                    219:        si->si_alo = ntohs(si->si_alo);
                    220:        ns_error(dtom(si), NS_ERR_NOSOCK, 0);
                    221:        if (cb->s_nspcb->nsp_socket->so_options & SO_DEBUG || traceallspps)
                    222:                spp_trace(SA_DROP, (u_char)ostate, cb, &spp_savesi, 0);
                    223:        return;
                    224: 
                    225: drop:
                    226: bad:
                    227:        if (cb == 0 || cb->s_nspcb->nsp_socket->so_options & SO_DEBUG || traceallspps)
                    228:                spp_trace(SA_DROP, (u_char)ostate, cb, &spp_savesi, 0);
                    229:        m_freem(m);
                    230: }
                    231: 
                    232: /*
                    233:  * This is structurally similar to the tcp reassembly routine
                    234:  * but its function is somewhat different:  It merely queues
                    235:  * packets up, and suppresses duplicates.
                    236:  */
                    237: spp_reass(cb, si)
                    238: register struct sppcb *cb;
                    239: register struct spidp *si;
                    240: {
                    241:        register struct spidp_q *q;
                    242:        register struct mbuf *m;
                    243:        struct socket *so = cb->s_nspcb->nsp_socket;
                    244:        struct sockbuf *sb = & (so->so_rcv);
                    245:        char packetp = cb->s_flags & SF_HI;
                    246:        char wakeup = 0;
                    247: 
                    248: 
                    249:        if (si == SI(0))
                    250:                goto present;
                    251:        /*
                    252:         * Update our news from them.
                    253:         */
                    254:        if (si->si_cc & SP_SA)
                    255:                cb->s_flags |= (spp_use_delack ? SF_DELACK : SF_AK);
                    256:        if (SSEQ_GT(si->si_ack, cb->s_rack)) {
                    257:                cb->s_rack = si->si_ack;
                    258:                /*
                    259:                 * If there are other packets outstanding,
                    260:                 * restart the timer for them.
                    261:                 */
                    262:                if (SSEQ_GEQ(cb->s_snt, si->si_ack)) {
                    263:                        TCPT_RANGESET(cb->s_timer[TCPT_REXMT],
                    264:                                tcp_beta * cb->s_srtt, TCPTV_MIN,
                    265:                                TCPTV_MAX);
                    266:                        cb->s_rxtshift = 0;
                    267:                } else
                    268:                        cb->s_timer[TCPT_REXMT] = 0;
                    269:                /*
                    270:                 * If transmit timer is running and timed sequence
                    271:                 * number was acked, update smoothed round trip time.
                    272:                 */
                    273:                if (cb->s_rtt && SSEQ_GT(si->si_ack, cb->s_rtseq)) {
                    274:                        if (cb->s_srtt == 0)
                    275:                                cb->s_srtt = cb->s_rtt;
                    276:                        else
                    277:                                cb->s_srtt =
                    278:                                    tcp_alpha * cb->s_srtt +
                    279:                                    (1 - tcp_alpha) * cb->s_rtt;
                    280:                        cb->s_rtt = 0;
                    281:                }
                    282:        }
                    283:        if (SSEQ_GT(si->si_alo, cb->s_ralo)) {
                    284:                cb->s_ralo = si->si_alo;
                    285:                cb->s_timer[TCPT_PERSIST] = 0;
                    286:        }
                    287:        /*
                    288:         * If this is a system packet, we don't need to
                    289:         * queue it up, and won't update acknowledge #
                    290:         */
                    291:        if (si->si_cc & SP_SP) {
                    292:                m_freem(dtom(si));
                    293:                return (0);
                    294:        }
                    295: 
                    296:        /*
                    297:         * If this packet number has a sequence number less
                    298:         * than that of the first packet not yet seen coming
                    299:         * from them, this must be a duplicate, so drop.
                    300:         */
                    301:        if (SSEQ_LT(si->si_seq, cb->s_ack)) {
                    302:                spp_istat.bdreas++;
                    303:                if (si->si_seq == cb->s_ack-1)
                    304:                        spp_istat.lstdup++;
                    305:                return (1);
                    306:        }
                    307:        /*
                    308:         * If this packet number is higher than that which
                    309:         * we have allocated refuse it, unless urgent
                    310:         */
                    311:        if (SSEQ_GT(si->si_seq, cb->s_alo)) {
                    312:                if (si->si_cc & SP_OB) {
                    313:                        if (SSEQ_GT(si->si_seq, cb->s_alo + 60)) {
                    314:                                ns_error(dtom(si), NS_ERR_FULLUP, 0);
                    315:                                return (0);
                    316:                        } /* else queue this packet; */
                    317:                } else {
                    318:                        spp_istat.notyet++;
                    319:                        return (1);
                    320:                }
                    321:        }
                    322: 
                    323:        /*
                    324:         * Loop through all packets queued up to insert in
                    325:         * appropriate sequence.
                    326:         */
                    327: 
                    328:        for (q = cb->s_q.si_next; q!=&cb->s_q; q = q->si_next) {
                    329:            if (si->si_seq == SI(q)->si_seq) return (1); /*duplicate */
                    330:            if (SSEQ_LT(si->si_seq, SI(q)->si_seq)) break;
                    331:        }
                    332:        insque(si, q->si_prev);
                    333:        /*
                    334:         * If this packet is urgent, inform process
                    335:         */
                    336:        if (si->si_cc & SP_OB) {
                    337:                cb->s_iobc = ((char *)si)[1 + sizeof(*si)];
                    338:                sohasoutofband(so);
                    339:                cb->s_oobflags |= SF_IOOB;
                    340:        }
                    341: present:
                    342: #define SPINC sizeof(struct sphdr)
                    343:        /*
                    344:         * Loop through all packets queued up to update acknowledge
                    345:         * number, and present all acknowledged data to user;
                    346:         * If in packet interface mode, show packet headers.
                    347:         */
                    348:        for (q = cb->s_q.si_next; q!=&cb->s_q; q = q->si_next) {
                    349:                  if (SI(q)->si_seq == cb->s_ack) {
                    350:                        cb->s_ack++;
                    351:                        m = dtom(q);
                    352:                        if (SI(q)->si_cc & SP_OB) {
                    353:                                cb->s_oobflags &= ~SF_IOOB;
                    354:                                if (sb->sb_cc)
                    355:                                        so->so_oobmark = sb->sb_cc;
                    356:                                else
                    357:                                        so->so_state |= SS_RCVATMARK;
                    358:                        }
                    359:                        q = q->si_prev;
                    360:                        remque(q->si_next);
                    361:                        wakeup = 1;
                    362:                        if (packetp) {
                    363:                                sbappendrecord(sb, m);
                    364:                        } else {
                    365:                                cb->s_rhdr = *mtod(m, struct sphdr *);
                    366:                                m->m_off += SPINC;
                    367:                                m->m_len -= SPINC;
                    368:                                sbappend(sb, m);
                    369:                        }
                    370:                  } else
                    371:                        break;
                    372:        }
                    373:        if (wakeup) sorwakeup(so);
                    374:        return (0);
                    375: }
                    376: 
                    377: spp_ctlinput(cmd, arg)
                    378:        int cmd;
                    379:        caddr_t arg;
                    380: {
                    381:        struct ns_addr *na;
                    382:        extern u_char nsctlerrmap[];
                    383:        extern spp_abort();
                    384:        extern struct nspcb *idp_drop();
                    385:        struct ns_errp *errp;
                    386:        struct nspcb *nsp;
                    387:        struct sockaddr_ns *sns;
                    388:        int type;
                    389: 
                    390:        if (cmd < 0 || cmd > PRC_NCMDS)
                    391:                return;
                    392:        type = NS_ERR_UNREACH_HOST;
                    393: 
                    394:        switch (cmd) {
                    395: 
                    396:        case PRC_ROUTEDEAD:
                    397:        case PRC_QUENCH:
                    398:                break;
                    399: 
                    400:        case PRC_IFDOWN:
                    401:        case PRC_HOSTDEAD:
                    402:        case PRC_HOSTUNREACH:
                    403:                sns = (struct sockaddr_ns *)arg;
                    404:                if (sns->sns_family != AF_NS)
                    405:                        return;
                    406:                na = &sns->sns_addr;
                    407:                break;
                    408: 
                    409:        default:
                    410:                errp = (struct ns_errp *)arg;
                    411:                na = &errp->ns_err_idp.idp_dna;
                    412:                type = errp->ns_err_num;
                    413:                type = ntohs((u_short)type);
                    414:        }
                    415:        switch (type) {
                    416: 
                    417:        case NS_ERR_UNREACH_HOST:
                    418:                ns_pcbnotify(na, (int)nsctlerrmap[cmd], spp_abort, (long) 0);
                    419:                break;
                    420: 
                    421:        case NS_ERR_TOO_BIG:
                    422:        case NS_ERR_NOSOCK:
                    423:                nsp = ns_pcblookup(na, errp->ns_err_idp.idp_sna.x_port,
                    424:                        NS_WILDCARD);
                    425:                if (nsp) {
                    426:                        if(nsp->nsp_pcb)
                    427:                                (void) spp_drop((struct sppcb *)nsp->nsp_pcb,
                    428:                                                (int)nsctlerrmap[cmd]);
                    429:                        else
                    430:                                (void) idp_drop(nsp, (int)nsctlerrmap[cmd]);
                    431:                }
                    432:        }
                    433: }
                    434: 
                    435: #ifdef notdef
                    436: int
                    437: spp_fixmtu(nsp)
                    438: register struct nspcb *nsp;
                    439: {
                    440:        register struct sppcb *cb = (struct sppcb *)(nsp->nsp_pcb);
                    441:        register struct mbuf *m;
                    442:        register struct spidp *si;
                    443:        struct ns_errp *ep;
                    444:        struct sockbuf *sb;
                    445:        int badseq, len;
                    446:        struct mbuf *firstbad, *m0;
                    447: 
                    448:        if (cb) {
                    449:                /* 
                    450:                 * The notification that we have sent
                    451:                 * too much is bad news -- we will
                    452:                 * have to go through queued up so far
                    453:                 * splitting ones which are too big and
                    454:                 * reassigning sequence numbers and checksums.
                    455:                 * we should then retransmit all packets from
                    456:                 * one above the offending packet to the last one
                    457:                 * we had sent (or our allocation)
                    458:                 * then the offending one so that the any queued
                    459:                 * data at our destination will be discarded.
                    460:                 */
                    461:                 ep = (struct ns_errp *)nsp->nsp_notify_param;
                    462:                 sb = &nsp->nsp_socket->so_snd;
                    463:                 cb->s_mtu = ep->ns_err_param;
                    464:                 badseq = SI(&ep->ns_err_idp)->si_seq;
                    465:                 for (m = sb->sb_mb; m; m = m->m_act) {
                    466:                        si = mtod(m, struct spidp *);
                    467:                        if (si->si_seq == badseq)
                    468:                                break;
                    469:                 }
                    470:                 if (m == 0) return;
                    471:                 firstbad = m;
                    472:                 /*for (;;) {*/
                    473:                        /* calculate length */
                    474:                        for (m0 = m, len = 0; m ; m = m->m_next)
                    475:                                len += m->m_len;
                    476:                        if (len > cb->s_mtu) {
                    477:                        }
                    478:                /* FINISH THIS
                    479:                } */
                    480:        }
                    481: }
                    482: #endif
                    483: 
                    484: int spp_output_cnt = 0;
                    485: 
                    486: spp_output(cb, m0)
                    487:        register struct sppcb *cb;
                    488:        struct mbuf *m0;
                    489: {
                    490:        struct socket *so = cb->s_nspcb->nsp_socket;
                    491:        register struct mbuf *m;
                    492:        register struct spidp *si = (struct spidp *) 0;
                    493:        register struct sockbuf *sb = &(so->so_snd);
                    494:        register int len = 0;
                    495:        int error = 0;
                    496:        u_short lookfor = 0;
                    497:        struct mbuf *mprev;
                    498:        extern int idpcksum;
                    499: 
                    500:        if (m0) {
                    501:                int mtu = cb->s_mtu;
                    502:                int datalen;
                    503:                /*
                    504:                 * Make sure that packet isn't too big.
                    505:                 */
                    506:                for (m = m0; m ; m = m->m_next) {
                    507:                        mprev = m;
                    508:                        len += m->m_len;
                    509:                }
                    510:                datalen = (cb->s_flags & SF_HO) ?
                    511:                                len - sizeof (struct sphdr) : len;
                    512:                if (datalen > mtu) {
                    513:                        if (cb->s_flags & SF_PI) {
                    514:                                m_freem(m0);
                    515:                                return (EMSGSIZE);
                    516:                        } else {
                    517:                                int off = 0;
                    518:                                int oldEM = cb->s_cc & SP_EM;
                    519: 
                    520:                                cb->s_cc &= ~SP_EM;
                    521:                                while (len > mtu) {
                    522:                                        m = m_copy(m0, off, mtu);
                    523:                                        if (m == NULL) {
                    524:                                                error = ENOBUFS;
                    525:                                                goto bad_copy;
                    526:                                        }
                    527:                                        error = spp_output(cb, m);
                    528:                                        if (error) {
                    529:                                        bad_copy:
                    530:                                                cb->s_cc |= oldEM;
                    531:                                                m_freem(m0);
                    532:                                                return(error);
                    533:                                        }
                    534:                                        m_adj(m0, mtu);
                    535:                                        len -= mtu;
                    536:                                }
                    537:                                cb->s_cc |= oldEM;
                    538:                        }
                    539:                }
                    540:                /*
                    541:                 * Force length even, by adding a "garbage byte" if
                    542:                 * necessary.
                    543:                 */
                    544:                if (len & 1) {
                    545:                        m = mprev;
                    546:                        if (m->m_len + m->m_off < MMAXOFF)
                    547:                                m->m_len++;
                    548:                        else {
                    549:                                struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA);
                    550: 
                    551:                                if (m1 == 0) {
                    552:                                        m_freem(m0);
                    553:                                        return (ENOBUFS);
                    554:                                }
                    555:                                m1->m_len = 1;
                    556:                                m1->m_off = MMAXOFF - 1;
                    557:                                m->m_next = m1;
                    558:                        }
                    559:                }
                    560:                m = m_get(M_DONTWAIT, MT_HEADER);
                    561:                if (m == 0) {
                    562:                        m_freem(m0);
                    563:                        return (ENOBUFS);
                    564:                }
                    565:                /*
                    566:                 * Fill in mbuf with extended SP header
                    567:                 * and addresses and length put into network format.
                    568:                 * Long align so prepended ip headers will work on Gould.
                    569:                 */
                    570:                m->m_off = MMAXOFF - sizeof (struct spidp) - 2;
                    571:                m->m_len = sizeof (struct spidp);
                    572:                m->m_next = m0;
                    573:                si = mtod(m, struct spidp *);
                    574:                *si = cb->s_shdr;
                    575:                if ((cb->s_flags & SF_PI) && (cb->s_flags & SF_HO)) {
                    576:                        register struct sphdr *sh;
                    577:                        if (m0->m_len < sizeof (*sh)) {
                    578:                                if((m0 = m_pullup(m0, sizeof(*sh))) == NULL) {
                    579:                                        (void) m_free(m);
                    580:                                        m_freem(m0);
                    581:                                        return (EINVAL);
                    582:                                }
                    583:                                m->m_next = m0;
                    584:                        }
                    585:                        sh = mtod(m0, struct sphdr *);
                    586:                        si->si_dt = sh->sp_dt;
                    587:                        si->si_cc |= sh->sp_cc & SP_EM;
                    588:                        m0->m_len -= sizeof (*sh);
                    589:                        m0->m_off += sizeof (*sh);
                    590:                        len -= sizeof (*sh);
                    591:                }
                    592:                len += sizeof(*si);
                    593:                if (cb->s_oobflags & SF_SOOB) {
                    594:                        /*
                    595:                         * Per jqj@cornell:
                    596:                         * make sure OB packets convey exactly 1 byte.
                    597:                         * If the packet is 1 byte or larger, we
                    598:                         * have already guaranted there to be at least
                    599:                         * one garbage byte for the checksum, and
                    600:                         * extra bytes shouldn't hurt!
                    601:                         */
                    602:                        if (len > sizeof(*si)) {
                    603:                                si->si_cc |= SP_OB;
                    604:                                len = (1 + sizeof(*si));
                    605:                        }
                    606:                }
                    607:                si->si_len = htons((u_short)len);
                    608:                /*
                    609:                 * queue stuff up for output
                    610:                 */
                    611:                sbappendrecord(sb, m);
                    612:                cb->s_seq++;
                    613:        }
                    614:        /*
                    615:         * update window
                    616:         */
                    617:        {
                    618:                register struct sockbuf *sb2 = &so->so_rcv;
                    619:                int credit = ((((int)sb2->sb_mbmax) - (int)sb2->sb_mbcnt) /
                    620:                                                ((short)cb->s_mtu));
                    621:                int alo = cb->s_ack + (credit > 0 ? credit : 0) - 1;
                    622: 
                    623:                if (cb->s_alo < alo) {
                    624:                        /* If the amount we are raising the window
                    625:                           is more than his remaining headroom, tell
                    626:                           him about it.  In particular, if he is at
                    627:                           his limit, any amount at all will do! */
                    628:                        u_short raise = alo - cb->s_alo;
                    629:                        u_short headroom = 1 + cb->s_alo - cb->s_ack;
                    630: 
                    631:                        if(SSEQ_LT(headroom, raise))
                    632:                                cb->s_flags |= SF_AK;
                    633:                        cb->s_alo = alo;
                    634:                }
                    635:        }
                    636: 
                    637:        if (cb->s_oobflags & SF_SOOB) {
                    638:                /*
                    639:                 * must transmit this out of band packet
                    640:                 */
                    641:                cb->s_oobflags &= ~ SF_SOOB;
                    642:        } else {
                    643:                /*
                    644:                 * Decide what to transmit:
                    645:                 * If it is time to retransmit a packet,
                    646:                 * send that.
                    647:                 * If we have a new packet, send that
                    648:                 * (So long as it is in our allocation)
                    649:                 * Otherwise, see if it time to bang on them
                    650:                 * to ask for our current allocation.
                    651:                 */
                    652:                if (cb->s_force == (1+TCPT_REXMT)) {
                    653:                        lookfor = cb->s_rack;
                    654:                } else if (SSEQ_LT(cb->s_snt, cb->s_ralo)) {
                    655:                        lookfor = cb->s_snt + 1;
                    656:                } else if (SSEQ_LT(cb->s_ralo, cb->s_seq)) {
                    657:                        lookfor = 0;
                    658:                        if (cb->s_timer[TCPT_PERSIST] == 0) {
                    659:                                spp_setpersist(cb);
                    660:                                /* tcp has cb->s_rxtshift = 0; here */
                    661:                        }
                    662:                }
                    663:                m = sb->sb_mb;
                    664:                while (m) {
                    665:                        si = mtod(m, struct spidp *);
                    666:                        m = m->m_act;
                    667:                        if (SSEQ_LT(si->si_seq, cb->s_rack)) {
                    668:                                if ((sb->sb_flags & SB_WAIT)
                    669:                                     || so->so_snd.sb_sel)
                    670:                                         sowwakeup(so);
                    671:                                sbdroprecord(sb);
                    672:                                si = 0;
                    673:                                continue;
                    674:                        } 
                    675:                        if (SSEQ_LT(si->si_seq, lookfor))
                    676:                                continue;
                    677:                        break;
                    678:                }
                    679:                if (si && (si->si_seq != lookfor))
                    680:                        si = 0;
                    681:        }
                    682:        cb->s_want = lookfor;
                    683: 
                    684:        if (si) {
                    685:                /*
                    686:                 * must make a copy of this packet for
                    687:                 * idp_output to monkey with
                    688:                 */
                    689:                 m = m_copy(dtom(si), 0, (int)M_COPYALL);
                    690:                 if (m == NULL)
                    691:                        return (ENOBUFS);
                    692:                 m0 = m;
                    693:                 si = mtod(m, struct spidp *);
                    694:        } else if (cb->s_force || cb->s_flags & SF_AK) {
                    695:                /*
                    696:                 * Must send an acknowledgement or a probe
                    697:                 */
                    698:                m = m_get(M_DONTWAIT, MT_HEADER);
                    699:                if (m == 0)
                    700:                        return (ENOBUFS);
                    701:                /*
                    702:                 * Fill in mbuf with extended SP header
                    703:                 * and addresses and length put into network format.
                    704:                 */
                    705:                m->m_off = MMAXOFF - sizeof (struct spidp);
                    706:                m->m_len = sizeof (*si);
                    707:                m->m_next = 0;
                    708:                si = mtod(m, struct spidp *);
                    709:                *si = cb->s_shdr;
                    710:                si->si_seq = cb->s_snt + 1;
                    711:                si->si_len = htons(sizeof (*si));
                    712:                si->si_cc |= SP_SP;
                    713:        }
                    714:        /*
                    715:         * Stuff checksum and output datagram.
                    716:         */
                    717:        if (si) {
                    718:                if (cb->s_flags & (SF_AK|SF_DELACK))
                    719:                        cb->s_flags &= ~(SF_AK|SF_DELACK);
                    720:                /*
                    721:                 * If we are almost out of allocation
                    722:                 * or one of the timers has gone off
                    723:                 * request an ack.
                    724:                 */
                    725:                if (SSEQ_GEQ(cb->s_seq, cb->s_ralo))
                    726:                        si->si_cc |= SP_SA;
                    727:                if (cb->s_force) {
                    728:                        si->si_cc |= SP_SA;
                    729:                        cb->s_force = 0;
                    730:                }
                    731:                /*
                    732:                 * If this is a new packet (and not a system packet),
                    733:                 * and we are not currently timing anything,
                    734:                 * time this one and ask for an ack.
                    735:                 */
                    736:                if (SSEQ_LT(cb->s_snt, si->si_seq) && (!(si->si_cc & SP_SP))) {
                    737:                        cb->s_snt = si->si_seq;
                    738:                        if (cb->s_rtt == 0) {
                    739:                                cb->s_rtseq = si->si_seq;
                    740:                                cb->s_rtt = 1;
                    741:                                si->si_cc |= SP_SA;
                    742:                        }
                    743:                        /*
                    744:                         * If the retransmit timer has not been set
                    745:                         * and this is a real packet
                    746:                         * then start the retransmit timer
                    747:                         */
                    748:                        if (cb->s_timer[TCPT_REXMT] == 0) {
                    749:                                TCPT_RANGESET(cb->s_timer[TCPT_REXMT],
                    750:                                        tcp_beta * cb->s_srtt, TCPTV_MIN,
                    751:                                        TCPTV_MAX);
                    752:                                cb->s_rxtshift = 0;
                    753:                        }
                    754:                }
                    755:                si->si_seq = htons(si->si_seq);
                    756:                si->si_alo = htons(cb->s_alo);
                    757:                si->si_ack = htons(cb->s_ack);
                    758: 
                    759:                if (idpcksum) {
                    760:                        si->si_sum = 0;
                    761:                        len = ntohs(si->si_len);
                    762:                        if (len & 1)
                    763:                                len++;
                    764:                        si->si_sum = ns_cksum(dtom(si), len);
                    765:                } else
                    766:                        si->si_sum = 0xffff;
                    767: 
                    768:                if (so->so_options & SO_DEBUG || traceallspps)
                    769:                        spp_trace(SA_OUTPUT, cb->s_state, cb, si, 0);
                    770:                spp_output_cnt++;
                    771:                if (so->so_options & SO_DONTROUTE)
                    772:                        error = ns_output(m, (struct route *)0, NS_ROUTETOIF);
                    773:                else
                    774:                        error = ns_output(m, &cb->s_nspcb->nsp_route, 0);
                    775:                if (traceallspps && sppconsdebug) {
                    776:                        printf("spp_out: %x\n", error);
                    777:                }
                    778:                if (so->so_options & SO_DEBUG || traceallspps)
                    779:                        spp_trace(SA_OUTPUT, cb->s_state, cb, si, 0);
                    780:        }
                    781:        return (error);
                    782: }
                    783: 
                    784: /*ARGSUSED*/
                    785: spp_ctloutput(req, so, level, name, value)
                    786:        int req;
                    787:        struct socket *so;
                    788:        int name;
                    789:        struct mbuf **value;
                    790: {
                    791:        register struct mbuf *m;
                    792:        struct nspcb *nsp = sotonspcb(so);
                    793:        register struct sppcb *cb;
                    794:        int mask, error = 0;
                    795: 
                    796:        if (level != NSPROTO_SPP) {
                    797:                /* This will have to be changed when we do more general
                    798:                   stacking of protocols */
                    799:                return (idp_ctloutput(req, so, level, name, value));
                    800:        }
                    801:        if (nsp == NULL) {
                    802:                error = EINVAL;
                    803:                goto release;
                    804:        } else
                    805:                cb = nstosppcb(nsp);
                    806: 
                    807:        switch (req) {
                    808: 
                    809:        case PRCO_GETOPT:
                    810:                if (value == NULL)
                    811:                        return (EINVAL);
                    812:                m = m_get(M_DONTWAIT, MT_DATA);
                    813:                if (m == NULL)
                    814:                        return (ENOBUFS);
                    815:                switch (name) {
                    816: 
                    817:                case SO_HEADERS_ON_INPUT:
                    818:                        mask = SF_HI;
                    819:                        goto get_flags;
                    820: 
                    821:                case SO_HEADERS_ON_OUTPUT:
                    822:                        mask = SF_HO;
                    823:                get_flags:
                    824:                        m->m_len = sizeof(short);
                    825:                        m->m_off = MMAXOFF - sizeof(short);
                    826:                        *mtod(m, short *) = cb->s_flags & mask;
                    827:                        break;
                    828: 
                    829:                case SO_MTU:
                    830:                        m->m_len = sizeof(u_short);
                    831:                        m->m_off = MMAXOFF - sizeof(short);
                    832:                        *mtod(m, short *) = cb->s_mtu;
                    833:                        break;
                    834: 
                    835:                case SO_LAST_HEADER:
                    836:                        m->m_len = sizeof(struct sphdr);
                    837:                        m->m_off = MMAXOFF - sizeof(struct sphdr);
                    838:                        *mtod(m, struct sphdr *) = cb->s_rhdr;
                    839:                        break;
                    840: 
                    841:                case SO_DEFAULT_HEADERS:
                    842:                        m->m_len = sizeof(struct spidp);
                    843:                        m->m_off = MMAXOFF - sizeof(struct sphdr);
                    844:                        *mtod(m, struct sphdr *) = cb->s_shdr.si_s;
                    845:                        break;
                    846: 
                    847:                default:
                    848:                        error = EINVAL;
                    849:                }
                    850:                *value = m;
                    851:                break;
                    852: 
                    853:        case PRCO_SETOPT:
                    854:                if (value == 0 || *value == 0) {
                    855:                        error = EINVAL;
                    856:                        break;
                    857:                }
                    858:                switch (name) {
                    859:                        int *ok;
                    860: 
                    861:                case SO_HEADERS_ON_INPUT:
                    862:                        mask = SF_HI;
                    863:                        goto set_head;
                    864: 
                    865:                case SO_HEADERS_ON_OUTPUT:
                    866:                        mask = SF_HO;
                    867:                set_head:
                    868:                        if (cb->s_flags & SF_PI) {
                    869:                                ok = mtod(*value, int *);
                    870:                                if (*ok)
                    871:                                        cb->s_flags |= mask;
                    872:                                else
                    873:                                        cb->s_flags &= ~mask;
                    874:                        } else error = EINVAL;
                    875:                        break;
                    876: 
                    877:                case SO_MTU:
                    878:                        cb->s_mtu = *(mtod(*value, u_short *));
                    879:                        break;
                    880: 
                    881:                case SO_DEFAULT_HEADERS:
                    882:                        {
                    883:                                register struct sphdr *sp
                    884:                                                = mtod(*value, struct sphdr *);
                    885:                                cb->s_dt = sp->sp_dt;
                    886:                                cb->s_cc = sp->sp_cc & SP_EM;
                    887:                        }
                    888:                        break;
                    889: 
                    890:                default:
                    891:                        error = EINVAL;
                    892:                }
                    893:                m_freem(*value);
                    894:                break;
                    895:        }
                    896:        release:
                    897:                return (error);
                    898: }
                    899: 
                    900: /*ARGSUSED*/
                    901: spp_usrreq(so, req, m, nam, rights)
                    902:        struct socket *so;
                    903:        int req;
                    904:        struct mbuf *m, *nam, *rights;
                    905: {
                    906:        struct nspcb *nsp = sotonspcb(so);
                    907:        register struct sppcb *cb;
                    908:        int s = splnet();
                    909:        int error = 0, ostate;
                    910: 
                    911:        if (req == PRU_CONTROL)
                    912:                 return (ns_control(so, (int)m, (caddr_t)nam,
                    913:                        (struct ifnet *)rights));
                    914:        if (rights && rights->m_len) {
                    915:                error = EINVAL;
                    916:                goto release;
                    917:        }
                    918:        if (nsp == NULL) {
                    919:                if (req != PRU_ATTACH) {
                    920:                        error = EINVAL;
                    921:                        goto release;
                    922:                }
                    923:        } else
                    924:                cb = nstosppcb(nsp);
                    925: 
                    926:        ostate = cb ? cb->s_state : 0;
                    927: 
                    928:        switch (req) {
                    929: 
                    930:        case PRU_ATTACH:
                    931:                if (nsp != NULL) {
                    932:                        error = EISCONN;
                    933:                        break;
                    934:                }
                    935:                error = ns_pcballoc(so, &nspcb);
                    936:                if (error)
                    937:                        break;
                    938:                error = soreserve(so, 2048, 2048);
                    939:                if (error)
                    940:                        break;
                    941:                nsp = sotonspcb(so);
                    942:                {
                    943:                        struct mbuf *mm = m_getclr(M_DONTWAIT, MT_PCB);
                    944: 
                    945:                        if (mm == NULL) {
                    946:                                error = ENOBUFS;
                    947:                                break;
                    948:                        }
                    949:                        cb = mtod(mm, struct sppcb *);
                    950:                        cb->s_state = TCPS_LISTEN;
                    951:                        cb->s_snt = -1;
                    952:                        cb->s_q.si_next = cb->s_q.si_prev = &cb->s_q;
                    953:                        cb->s_nspcb = nsp;
                    954:                        nsp->nsp_pcb = (caddr_t) cb; 
                    955:                }
                    956:                break;
                    957: 
                    958:        case PRU_DETACH:
                    959:                if (nsp == NULL) {
                    960:                        error = ENOTCONN;
                    961:                        break;
                    962:                }
                    963:                if (cb->s_state > TCPS_LISTEN)
                    964:                        cb = spp_disconnect(cb);
                    965:                else
                    966:                        cb = spp_close(cb);
                    967:                break;
                    968: 
                    969:        case PRU_BIND:
                    970:                error = ns_pcbbind(nsp, nam);
                    971:                break;
                    972: 
                    973:        case PRU_LISTEN:
                    974:                if (nsp->nsp_lport == 0)
                    975:                        error = ns_pcbbind(nsp, (struct mbuf *)0);
                    976:                if (error == 0)
                    977:                        cb->s_state = TCPS_LISTEN;
                    978:                break;
                    979: 
                    980:        /*
                    981:         * Initiate connection to peer.
                    982:         * Enter SYN_SENT state, and mark socket as connecting.
                    983:         * Start keep-alive timer, setup prototype header,
                    984:         * Send initial system packet requesting connection.
                    985:         */
                    986:        case PRU_CONNECT:
                    987:                if (nsp->nsp_lport == 0) {
                    988:                        error = ns_pcbbind(nsp, (struct mbuf *)0);
                    989:                        if (error)
                    990:                                break;
                    991:                }
                    992:                error = ns_pcbconnect(nsp, nam);
                    993:                if (error)
                    994:                        break;
                    995:                soisconnecting(so);
                    996:                cb->s_state = TCPS_SYN_SENT;
                    997:                cb->s_did = 0;
                    998:                spp_template(cb);
                    999:                cb->s_timer[TCPT_KEEP] = TCPTV_KEEP;
                   1000:                cb->s_force = 1 + TCPTV_KEEP;
                   1001:                /*
                   1002:                 * Other party is required to respond to
                   1003:                 * the port I send from, but he is not
                   1004:                 * required to answer from where I am sending to,
                   1005:                 * so allow wildcarding.
                   1006:                 * original port I am sending to is still saved in
                   1007:                 * cb->s_dport.
                   1008:                 */
                   1009:                nsp->nsp_fport = 0;
                   1010:                error = spp_output(cb, (struct mbuf *) 0);
                   1011:                break;
                   1012: 
                   1013:        case PRU_CONNECT2:
                   1014:                error = EOPNOTSUPP;
                   1015:                break;
                   1016: 
                   1017:        /*
                   1018:         * We may decide later to implement connection closing
                   1019:         * handshaking at the spp level optionally.
                   1020:         * here is the hook to do it:
                   1021:         */
                   1022:        case PRU_DISCONNECT:
                   1023:                cb = spp_disconnect(cb);
                   1024:                break;
                   1025: 
                   1026:        /*
                   1027:         * Accept a connection.  Essentially all the work is
                   1028:         * done at higher levels; just return the address
                   1029:         * of the peer, storing through addr.
                   1030:         */
                   1031:        case PRU_ACCEPT: {
                   1032:                struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *);
                   1033: 
                   1034:                nam->m_len = sizeof (struct sockaddr_ns);
                   1035:                sns->sns_family = AF_NS;
                   1036:                sns->sns_addr = nsp->nsp_faddr;
                   1037:                break;
                   1038:                }
                   1039: 
                   1040:        case PRU_SHUTDOWN:
                   1041:                socantsendmore(so);
                   1042:                cb = spp_usrclosed(cb);
                   1043:                if (cb)
                   1044:                        error = spp_output(cb, (struct mbuf *) 0);
                   1045:                break;
                   1046: 
                   1047:        /*
                   1048:         * After a receive, possibly send acknowledgment
                   1049:         * updating allocation.
                   1050:         */
                   1051:        case PRU_RCVD:
                   1052:                (void) spp_output(cb, (struct mbuf *) 0);
                   1053:                break;
                   1054: 
                   1055:        case PRU_ABORT:
                   1056:                (void) spp_drop(cb, ECONNABORTED);
                   1057:                break;
                   1058: 
                   1059:        case PRU_SENSE:
                   1060:        case PRU_CONTROL:
                   1061:                m = NULL;
                   1062:                error = EOPNOTSUPP;
                   1063:                break;
                   1064: 
                   1065:        case PRU_RCVOOB:
                   1066:                if ((cb->s_oobflags & SF_IOOB) || so->so_oobmark ||
                   1067:                    (so->so_state & SS_RCVATMARK)) {
                   1068:                        m->m_len = 1;
                   1069:                        *mtod(m, caddr_t) = cb->s_iobc;
                   1070:                        break;
                   1071:                }
                   1072:                error = EINVAL;
                   1073:                break;
                   1074: 
                   1075:        case PRU_SENDOOB:
                   1076:                if (sbspace(&so->so_snd) < -512) {
                   1077:                        error = ENOBUFS;
                   1078:                        break;
                   1079:                }
                   1080:                cb->s_oobflags |= SF_SOOB;
                   1081:                /* fall into */
                   1082:        case PRU_SEND:
                   1083:                error = spp_output(cb, m);
                   1084:                m = NULL;
                   1085:                break;
                   1086: 
                   1087:        case PRU_SOCKADDR:
                   1088:                ns_setsockaddr(nsp, nam);
                   1089:                break;
                   1090: 
                   1091:        case PRU_PEERADDR:
                   1092:                ns_setpeeraddr(nsp, nam);
                   1093:                break;
                   1094: 
                   1095:        case PRU_SLOWTIMO:
                   1096:                cb = spp_timers(cb, (int)nam);
                   1097:                break;
                   1098: 
                   1099:        case PRU_FASTTIMO:
                   1100:        case PRU_PROTORCV:
                   1101:        case PRU_PROTOSEND:
                   1102:                error =  EOPNOTSUPP;
                   1103:                break;
                   1104: 
                   1105:        default:
                   1106:                panic("sp_usrreq");
                   1107:        }
                   1108:        if (cb && (so->so_options & SO_DEBUG || traceallspps))
                   1109:                spp_trace(SA_USER, (u_char)ostate, cb, (struct spidp *)0, req);
                   1110: release:
                   1111:        if (m != NULL)
                   1112:                m_freem(m);
                   1113:        splx(s);
                   1114:        return (error);
                   1115: }
                   1116: 
                   1117: spp_usrreq_sp(so, req, m, nam, rights)
                   1118:        struct socket *so;
                   1119:        int req;
                   1120:        struct mbuf *m, *nam, *rights;
                   1121: {
                   1122:        int error = spp_usrreq(so, req, m, nam, rights);
                   1123: 
                   1124:        if (req == PRU_ATTACH && error == 0) {
                   1125:                struct nspcb *nsp = sotonspcb(so);
                   1126:                ((struct sppcb *)nsp->nsp_pcb)->s_flags |=
                   1127:                                        (SF_HI | SF_HO | SF_PI);
                   1128:        }
                   1129:        return (error);
                   1130: }
                   1131: 
                   1132: /*
                   1133:  * Create template to be used to send spp packets on a connection.
                   1134:  * Called after host entry created, fills
                   1135:  * in a skeletal spp header (choosing connection id),
                   1136:  * minimizing the amount of work necessary when the connection is used.
                   1137:  */
                   1138: spp_template(cb)
                   1139:        struct sppcb *cb;
                   1140: {
                   1141:        register struct nspcb *nsp = cb->s_nspcb;
                   1142:        register struct spidp *n = &(cb->s_shdr);
                   1143: 
                   1144:        cb->s_mtu = 576 - sizeof (struct spidp);
                   1145:        n->si_pt = NSPROTO_SPP;
                   1146:        n->si_sna = nsp->nsp_laddr;
                   1147:        n->si_dna = nsp->nsp_faddr;
                   1148:        n->si_sid = htons(spp_iss);
                   1149:        spp_iss += SPP_ISSINCR/2;
                   1150:        n->si_alo = 1;
                   1151: }
                   1152: 
                   1153: /*
                   1154:  * Close a SPIP control block:
                   1155:  *     discard spp control block itself
                   1156:  *     discard ns protocol control block
                   1157:  *     wake up any sleepers
                   1158:  */
                   1159: struct sppcb *
                   1160: spp_close(cb)
                   1161:        register struct sppcb *cb;
                   1162: {
                   1163:        register struct spidp_q *s;
                   1164:        struct nspcb *nsp = cb->s_nspcb;
                   1165:        struct socket *so = nsp->nsp_socket;
                   1166:        register struct mbuf *m;
                   1167: 
                   1168:        s = cb->s_q.si_next;
                   1169:        while (s != &(cb->s_q)) {
                   1170:                s = s->si_next;
                   1171:                m = dtom(s->si_prev);
                   1172:                remque(s->si_prev);
                   1173:                m_freem(m);
                   1174:        }
                   1175:        (void) m_free(dtom(cb));
                   1176:        nsp->nsp_pcb = 0;
                   1177:        soisdisconnected(so);
                   1178:        ns_pcbdetach(nsp);
                   1179:        return ((struct sppcb *)0);
                   1180: }
                   1181: /*
                   1182:  *     Someday we may do level 3 handshaking
                   1183:  *     to close a connection or send a xerox style error.
                   1184:  *     For now, just close.
                   1185:  */
                   1186: struct sppcb *
                   1187: spp_usrclosed(cb)
                   1188:        register struct sppcb *cb;
                   1189: {
                   1190:        return (spp_close(cb));
                   1191: }
                   1192: struct sppcb *
                   1193: spp_disconnect(cb)
                   1194:        register struct sppcb *cb;
                   1195: {
                   1196:        return (spp_close(cb));
                   1197: }
                   1198: /*
                   1199:  * Drop connection, reporting
                   1200:  * the specified error.
                   1201:  */
                   1202: struct sppcb *
                   1203: spp_drop(cb, errno)
                   1204:        register struct sppcb *cb;
                   1205:        int errno;
                   1206: {
                   1207:        struct socket *so = cb->s_nspcb->nsp_socket;
                   1208: 
                   1209:        /*
                   1210:         * someday, in the xerox world
                   1211:         * we will generate error protocol packets
                   1212:         * announcing that the socket has gone away.
                   1213:         */
                   1214:        /*if (TCPS_HAVERCVDSYN(tp->t_state)) {
                   1215:                tp->t_state = TCPS_CLOSED;
                   1216:                (void) tcp_output(tp);
                   1217:        }*/
                   1218:        so->so_error = errno;
                   1219:        return (spp_close(cb));
                   1220: }
                   1221: 
                   1222: spp_abort(nsp)
                   1223:        struct nspcb *nsp;
                   1224: {
                   1225: 
                   1226:        (void) spp_close((struct sppcb *)nsp->nsp_pcb);
                   1227: }
                   1228: 
                   1229: spp_setpersist(cb)
                   1230:        register struct sppcb *cb;
                   1231: {
                   1232: 
                   1233:        /*if (cb->s_timer[TCPT_REXMT])
                   1234:                panic("spp_output REXMT");*/
                   1235:        /*
                   1236:         * Start/restart persistance timer.
                   1237:         */
                   1238:        TCPT_RANGESET(cb->s_timer[TCPT_PERSIST],
                   1239:            ((int)(tcp_beta * cb->s_srtt)) << cb->s_rxtshift,
                   1240:            TCPTV_PERSMIN, TCPTV_MAX);
                   1241:        cb->s_rxtshift++;
                   1242:        if (cb->s_rxtshift >= TCP_MAXRXTSHIFT)
                   1243:                cb->s_rxtshift = 0;
                   1244: }
                   1245: /*
                   1246:  * Fast timeout routine for processing delayed acks
                   1247:  */
                   1248: int spp_ftcnt;
                   1249: spp_fasttimo()
                   1250: {
                   1251:        register struct nspcb *nsp;
                   1252:        register struct sppcb *cb;
                   1253:        int s = splnet();
                   1254: 
                   1255:        nsp = nspcb.nsp_next;
                   1256:        spp_ftcnt++;
                   1257:        if (nsp)
                   1258:        for (; nsp != &nspcb; nsp = nsp->nsp_next)
                   1259:                if ((cb = (struct sppcb *)nsp->nsp_pcb) &&
                   1260:                    (cb->s_flags & SF_DELACK)) {
                   1261:                        cb->s_flags &= ~SF_DELACK;
                   1262:                        cb->s_flags |= SF_AK;
                   1263:                        (void) spp_output(cb, (struct mbuf *) 0);
                   1264:                }
                   1265:        splx(s);
                   1266: }
                   1267: 
                   1268: /*
                   1269:  * spp protocol timeout routine called every 500 ms.
                   1270:  * Updates the timers in all active pcb's and
                   1271:  * causes finite state machine actions if timers expire.
                   1272:  */
                   1273: spp_slowtimo()
                   1274: {
                   1275:        register struct nspcb *ip, *ipnxt;
                   1276:        register struct sppcb *cb;
                   1277:        int s = splnet();
                   1278:        register int i;
                   1279: 
                   1280:        /*
                   1281:         * Search through tcb's and update active timers.
                   1282:         */
                   1283:        ip = nspcb.nsp_next;
                   1284:        if (ip == 0) {
                   1285:                splx(s);
                   1286:                return;
                   1287:        }
                   1288:        while (ip != &nspcb) {
                   1289:                cb = nstosppcb(ip);
                   1290:                ipnxt = ip->nsp_next;
                   1291:                if (cb == 0)
                   1292:                        goto tpgone;
                   1293:                for (i = 0; i < TCPT_NTIMERS; i++) {
                   1294:                        if (cb->s_timer[i] && --cb->s_timer[i] == 0) {
                   1295:                                (void) spp_usrreq(cb->s_nspcb->nsp_socket,
                   1296:                                    PRU_SLOWTIMO, (struct mbuf *)0,
                   1297:                                    (struct mbuf *)i, (struct mbuf *)0);
                   1298:                                if (ipnxt->nsp_prev != ip)
                   1299:                                        goto tpgone;
                   1300:                        }
                   1301:                }
                   1302:                cb->s_idle++;
                   1303:                if (cb->s_rtt)
                   1304:                        cb->s_rtt++;
                   1305: tpgone:
                   1306:                ip = ipnxt;
                   1307:        }
                   1308:        spp_iss += SPP_ISSINCR/PR_SLOWHZ;               /* increment iss */
                   1309:        splx(s);
                   1310: }
                   1311: 
                   1312: float  spp_backoff[TCP_MAXRXTSHIFT] =
                   1313:     { 1.0, 1.2, 1.4, 1.7, 2.0, 3.0, 5.0, 8.0, 16.0, 32.0 };
                   1314: int sppexprexmtbackoff = 0;
                   1315: /*
                   1316:  * SPP timer processing.
                   1317:  */
                   1318: struct sppcb *
                   1319: spp_timers(cb, timer)
                   1320:        register struct sppcb *cb;
                   1321:        int timer;
                   1322: {
                   1323: 
                   1324:        cb->s_force = 1 + timer;
                   1325:        switch (timer) {
                   1326: 
                   1327:        /*
                   1328:         * 2 MSL timeout in shutdown went off.  Delete connection
                   1329:         * control block.
                   1330:         */
                   1331:        case TCPT_2MSL:
                   1332:                cb = spp_close(cb);
                   1333:                break;
                   1334: 
                   1335:        /*
                   1336:         * Retransmission timer went off.  Message has not
                   1337:         * been acked within retransmit interval.  Back off
                   1338:         * to a longer retransmit interval and retransmit all
                   1339:         * unacknowledged messages in the window.
                   1340:         */
                   1341:        case TCPT_REXMT:
                   1342:                cb->s_rxtshift++;
                   1343:                if (cb->s_rxtshift > TCP_MAXRXTSHIFT) {
                   1344:                        cb = spp_drop(cb, ETIMEDOUT);
                   1345:                        break;
                   1346:                }
                   1347:                (void) spp_output(cb, (struct mbuf *) 0);
                   1348:                TCPT_RANGESET(cb->s_timer[TCPT_REXMT],
                   1349:                    (int)cb->s_srtt, TCPTV_MIN, TCPTV_MAX);
                   1350:                if (sppexprexmtbackoff) {
                   1351:                        TCPT_RANGESET(cb->s_timer[TCPT_REXMT],
                   1352:                            cb->s_timer[TCPT_REXMT] << cb->s_rxtshift,
                   1353:                            TCPTV_MIN, TCPTV_MAX);
                   1354:                } else {
                   1355:                        TCPT_RANGESET(cb->s_timer[TCPT_REXMT],
                   1356:                            cb->s_timer[TCPT_REXMT] *
                   1357:                                spp_backoff[cb->s_rxtshift - 1],
                   1358:                            TCPTV_MIN, TCPTV_MAX);
                   1359:                }
                   1360:                break;
                   1361: 
                   1362:        /*
                   1363:         * Persistance timer into zero window.
                   1364:         * Force a probe to be sent.
                   1365:         */
                   1366:        case TCPT_PERSIST:
                   1367:                (void) spp_output(cb, (struct mbuf *) 0);
                   1368:                spp_setpersist(cb);
                   1369:                break;
                   1370: 
                   1371:        /*
                   1372:         * Keep-alive timer went off; send something
                   1373:         * or drop connection if idle for too long.
                   1374:         */
                   1375:        case TCPT_KEEP:
                   1376:                if (cb->s_state < TCPS_ESTABLISHED)
                   1377:                        goto dropit;
                   1378:                if (cb->s_nspcb->nsp_socket->so_options & SO_KEEPALIVE) {
                   1379:                        if (cb->s_idle >= TCPTV_MAXIDLE)
                   1380:                                goto dropit;
                   1381:                        (void) spp_output(cb, (struct mbuf *) 0);
                   1382:                } else
                   1383:                        cb->s_idle = 0;
                   1384:                cb->s_timer[TCPT_KEEP] = TCPTV_KEEP;
                   1385:                break;
                   1386:        dropit:
                   1387:                cb = spp_drop(cb, ETIMEDOUT);
                   1388:                break;
                   1389:        }
                   1390:        return (cb);
                   1391: }

unix.superglobalmegacorp.com

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