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