1*6826Ssam 2*6826Ssam #include "../h/param.h" 3*6826Ssam #include "../h/systm.h" 4*6826Ssam #include "../h/mbuf.h" 5*6826Ssam #include "../h/protosw.h" 6*6826Ssam #include "../h/socket.h" 7*6826Ssam #include "../h/socketvar.h" 8*6826Ssam #include "../net/dn_systm.h" 9*6826Ssam #include "../net/nsp.h" 10*6826Ssam #include "../net/nsp_var.h" 11*6826Ssam #include "../errno.h" 12*6826Ssam 13*6826Ssam int nspidebug = 1; 14*6826Ssam #define printd if(nspidebug)printf 15*6826Ssam /* 16*6826Ssam * NSP input routine: decode incoming packet and dispatch 17*6826Ssam * to appropriate socket. Called from the software interrupt 18*6826Ssam * at splnet. 19*6826Ssam * 20*6826Ssam * TODO: 21*6826Ssam * count occurances of various error conditions. 22*6826Ssam */ 23*6826Ssam 24*6826Ssam nspintr() 25*6826Ssam { 26*6826Ssam struct mbuf *m; 27*6826Ssam struct tprh *t; 28*6826Ssam int s, bom, eom; 29*6826Ssam u_short srcnode; 30*6826Ssam char *p; 31*6826Ssam struct nspcb *np; 32*6826Ssam 33*6826Ssam /* 34*6826Ssam * Loop pulling packets off the interrupt queue. 35*6826Ssam */ 36*6826Ssam next: 37*6826Ssam s = splimp(); 38*6826Ssam IF_DEQUEUE(&nspintrq, m); 39*6826Ssam splx(s); 40*6826Ssam printd("nsp_input: m 0x%x", m); 41*6826Ssam if (m == 0) 42*6826Ssam return; 43*6826Ssam t = mtod(m, struct tprh *); 44*6826Ssam srcnode = t->tprh_srcnode; 45*6826Ssam m->m_len -= sizeof (struct tprh); /* use m_adj??? */ 46*6826Ssam m->m_off += sizeof (struct tprh); 47*6826Ssam printd(", srcnode %d, len %d", srcnode, m->m_len); 48*6826Ssam if (m->m_len <= 0) { 49*6826Ssam m_freem(m); 50*6826Ssam goto next; 51*6826Ssam } 52*6826Ssam 53*6826Ssam /* 54*6826Ssam * Switch on the type of the message. 55*6826Ssam */ 56*6826Ssam p = mtod(m, char *); 57*6826Ssam switch (*p) { 58*6826Ssam 59*6826Ssam /* 60*6826Ssam * Got a Data message, possibly with EOM and 61*6826Ssam * BOM flags set. Call nsp_chkaddr to do ack 62*6826Ssam * and flow controll processing, then pass the 63*6826Ssam * data to the user. 64*6826Ssam */ 65*6826Ssam case NSP_DATA|NSP_EOM|NSP_BOM: 66*6826Ssam eom = bom = 1; 67*6826Ssam goto data; 68*6826Ssam 69*6826Ssam case NSP_DATA|NSP_EOM: 70*6826Ssam eom = 1; 71*6826Ssam goto data; 72*6826Ssam 73*6826Ssam case NSP_DATA|NSP_BOM: 74*6826Ssam bom = 1; 75*6826Ssam 76*6826Ssam case NSP_DATA: 77*6826Ssam data: 78*6826Ssam printd(", DATA (%d,%d)", bom, eom); 79*6826Ssam np = nsp_chkaddr(m, srcnode, NSP_DATA, &segnum); 80*6826Ssam if (np == 0) { 81*6826Ssam m_freem(m); 82*6826Ssam goto next; 83*6826Ssam } 84*6826Ssam 85*6826Ssam /* 86*6826Ssam * Data messages only valid in Run state 87*6826Ssam */ 88*6826Ssam if (np->n_state != NS_RUN) { 89*6826Ssam printf(", !RUN (%d)\n", np->n_state); 90*6826Ssam m_freem(m); 91*6826Ssam goto next; 92*6826Ssam } 93*6826Ssam if (SEQ_GTR(segnum, np->na_xmtdat)) { 94*6826Ssam /* SHOULD DO SEGMENT RECONSTRUCTION HERE */ 95*6826Ssam printd(", got data!"); 96*6826Ssam sbpappend(m, &np->n_socket->sb_rcv); 97*6826Ssam } else 98*6826Ssam np->n_flags |= NF_DATACK; 99*6826Ssam break; 100*6826Ssam 101*6826Ssam /* 102*6826Ssam * Got an interrupt message. Call nsp_chkaddr 103*6826Ssam * (as usual). Save the interrupt data for the 104*6826Ssam * user. 105*6826Ssam * GENERATE A SIGNAL OF SOME SORT??? 106*6826Ssam */ 107*6826Ssam case NSP_INTR: 108*6826Ssam printd(", INTR"); 109*6826Ssam np = nsp_chkaddr(m, srcnode, NSP_INTR, &segnum); 110*6826Ssam if (np == 0) { 111*6826Ssam m_freem(m); 112*6826Ssam goto next; 113*6826Ssam } 114*6826Ssam 115*6826Ssam /* 116*6826Ssam * If we are in the Connect Confirm state then 117*6826Ssam * this Interrupt packet causes the transition 118*6826Ssam * to the Run state. Otherwise we better be in 119*6826Ssam * the Run state already. 120*6826Ssam */ 121*6826Ssam if (np->n_state == NS_CC) 122*6826Ssam np->n_state = NS_RUN; 123*6826Ssam else if (np->n_state != NS_RUN) { 124*6826Ssam printf(", !RUN %d\n", np->n_state); 125*6826Ssam m_freem(m); 126*6826Ssam goto next; 127*6826Ssam } 128*6826Ssam 129*6826Ssam /* 130*6826Ssam * If this segment is the one after the last 131*6826Ssam * other data segment we acked, and there is 132*6826Ssam * no waiting interrupt message, then queue 133*6826Ssam * this one up. 134*6826Ssam */ 135*6826Ssam if (segnum == SEQ_ADD(np->na_xmtoth, 1) && 136*6826Ssam np->nf_locint == NFL_EMPTY) { 137*6826Ssam if (np->nb_rcv) { 138*6826Ssam printd(", flush old intr data"); 139*6826Ssam m_freem(np->nb_rcv); 140*6826Ssam } 141*6826Ssam if (m->m_len > 16) { 142*6826Ssam printd(", intr data too long\n"); 143*6826Ssam m_freem(m); 144*6826Ssam goto next; 145*6826Ssam } 146*6826Ssam np->nb_rcv = m; 147*6826Ssam np->nf_locint = NFL_INTR; 148*6826Ssam np->na_xmtoth = segnum; /* really += 1 */ 149*6826Ssam np->n_flags |= NF_OTHACK; 150*6826Ssam } else if (SEQ_LEQ(segnum, np->na_xmtoth)) 151*6826Ssam np->n_flags |= NF_OTHACK; 152*6826Ssam break; 153*6826Ssam 154*6826Ssam /* 155*6826Ssam * Got a Link Service message. Process options 156*6826Ssam * to modify flow control values. 157*6826Ssam */ 158*6826Ssam case NSP_LS: 159*6826Ssam printd(", LS"); 160*6826Ssam np = nsp_chkaddr(m, srcnode, NSP_LS, &segnum); 161*6826Ssam if (np == 0) { 162*6826Ssam m_freem(m); 163*6826Ssam goto next; 164*6826Ssam } 165*6826Ssam 166*6826Ssam /* 167*6826Ssam * If we are in the Connect Confirm state then 168*6826Ssam * this Link Service packet causes the transition 169*6826Ssam * to the Run state. Otherwise we better be in 170*6826Ssam * the Run state already. 171*6826Ssam */ 172*6826Ssam if (np->n_state == NS_CC) 173*6826Ssam np->n_state = NS_RUN; 174*6826Ssam else if (np->n_state != NS_RUN) { 175*6826Ssam printd(", !RUN %d\n", np->n_state); 176*6826Ssam m_freem(m); 177*6826Ssam goto next; 178*6826Ssam } 179*6826Ssam p = mtod(m, char *); 180*6826Ssam lsf = *p++; 181*6826Ssam fcval = *p; 182*6826Ssam printd(", lsf 0x%x, fcval %d", lsf, fcval); 183*6826Ssam switch (lsf & NSPLS_FCVALINT) { 184*6826Ssam case NSPLS_DATREQ: 185*6826Ssam if (seqnum == SEQ_ADD(np->na_xmtoth, 1)) { 186*6826Ssam if (np->nf_remdat + fcval >= -128 && 187*6826Ssam np->nf_remdat + fcval <= 127) { 188*6826Ssam np->nf_remdat += fcval; 189*6826Ssam np->na_xmtoth = segnum; 190*6826Ssam np->n_flags |= NF_OTHACK; 191*6826Ssam switch (lsf & NSPLS_FCMOD) { 192*6826Ssam case NSPLS_NOCHANGE: 193*6826Ssam break; 194*6826Ssam case NSPLS_ON: 195*6826Ssam np->n_flags &= ~NF_DATOFF; 196*6826Ssam break; 197*6826Ssam case NSPLS_OFF: 198*6826Ssam np->n_flags |= NF_DATOFF; 199*6826Ssam break; 200*6826Ssam default: 201*6826Ssam printd(", bad fcmod"); 202*6826Ssam } 203*6826Ssam } 204*6826Ssam } else if (SEQ_LEQ(segnum, np->na_xmtoth)) 205*6826Ssam np->n_flags |= NF_OTHACK; 206*6826Ssam break; 207*6826Ssam 208*6826Ssam case NSPLS_INTREQ: 209*6826Ssam if (seqnum == SEQ_ADD(np->na_xmtoth, 1)) { 210*6826Ssam if (fcval >= 0 && np->nf_remint+fcval <= 127) { 211*6826Ssam np->nf_remint += fcval; 212*6826Ssam np->na_xmtoth = segnum; 213*6826Ssam np->n_flags |= NF_OTHACK; 214*6826Ssam } else if (SEQ_LEQ(segnum, np->na_xmtoth)) 215*6826Ssam np->n_flags |= NF_OTHACK; 216*6826Ssam break; 217*6826Ssam 218*6826Ssam default: 219*6826Ssam printd(", bad fcvalint"); 220*6826Ssam } 221*6826Ssam break; 222*6826Ssam 223*6826Ssam /* 224*6826Ssam * Got an acknowledgement for a Data message. 225*6826Ssam * Nsp_chkaddr processes the ack, nothing else 226*6826Ssam * to do. 227*6826Ssam */ 228*6826Ssam case NSP_DATACK: 229*6826Ssam printd(", DATACK"); 230*6826Ssam np = nsp_chkaddr(m, srcnode, NSP_DATACK, &segnum); 231*6826Ssam if (np == 0) { 232*6826Ssam m_freem(m); 233*6826Ssam goto next; 234*6826Ssam } 235*6826Ssam break; 236*6826Ssam 237*6826Ssam /* 238*6826Ssam * Got an acknowledgement for an Other Data message. 239*6826Ssam * Nsp_chkaddr processes the ack, nothing else to do. 240*6826Ssam */ 241*6826Ssam case NSP_OTHACK: 242*6826Ssam printd(", OTHACK"); 243*6826Ssam np = nsp_chkaddr(m, srcnode, NSP_OTHACK, &segnum); 244*6826Ssam if (np == 0) { 245*6826Ssam m_freem(m); 246*6826Ssam goto next; 247*6826Ssam } 248*6826Ssam break; 249*6826Ssam 250*6826Ssam /* 251*6826Ssam * Got a Connect Acknowledgement. Just verify 252*6826Ssam * the address and perform the state transition. 253*6826Ssam */ 254*6826Ssam case NSP_CONACK: 255*6826Ssam DOIT 256*6826Ssam break; 257*6826Ssam 258*6826Ssam /* 259*6826Ssam * Got an unknown message, count it and flush it. 260*6826Ssam */ 261*6826Ssam default: 262*6826Ssam printd(", UNKNOWN!!!"); 263*6826Ssam m_freem(m); 264*6826Ssam break; 265*6826Ssam } 266*6826Ssam printd("\n"); 267*6826Ssam goto next; 268*6826Ssam } 269