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