1 /* $NetBSD: hd_subr.c,v 1.16 2003/08/07 16:33:00 agc Exp $ */
2
3 /*
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * the Laboratory for Computation Vision and the Computer Science Department
9 * of the University of British Columbia.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)hd_subr.c 8.1 (Berkeley) 6/10/93
36 */
37
38 /*
39 * Copyright (c) 1984 University of British Columbia.
40 *
41 * This code is derived from software contributed to Berkeley by
42 * the Laboratory for Computation Vision and the Computer Science Department
43 * of the University of British Columbia.
44 *
45 * Redistribution and use in source and binary forms, with or without
46 * modification, are permitted provided that the following conditions
47 * are met:
48 * 1. Redistributions of source code must retain the above copyright
49 * notice, this list of conditions and the following disclaimer.
50 * 2. Redistributions in binary form must reproduce the above copyright
51 * notice, this list of conditions and the following disclaimer in the
52 * documentation and/or other materials provided with the distribution.
53 * 3. All advertising materials mentioning features or use of this software
54 * must display the following acknowledgement:
55 * This product includes software developed by the University of
56 * California, Berkeley and its contributors.
57 * 4. Neither the name of the University nor the names of its contributors
58 * may be used to endorse or promote products derived from this software
59 * without specific prior written permission.
60 *
61 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
65 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
66 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
67 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
71 * SUCH DAMAGE.
72 *
73 * @(#)hd_subr.c 8.1 (Berkeley) 6/10/93
74 */
75
76 #include <sys/cdefs.h>
77 __KERNEL_RCSID(0, "$NetBSD: hd_subr.c,v 1.16 2003/08/07 16:33:00 agc Exp $");
78
79 #include <sys/param.h>
80 #include <sys/systm.h>
81 #include <sys/mbuf.h>
82 #include <sys/domain.h>
83 #include <sys/socket.h>
84 #include <sys/socketvar.h>
85 #include <sys/protosw.h>
86 #include <sys/errno.h>
87 #include <sys/time.h>
88 #include <sys/kernel.h>
89
90 #include <net/if.h>
91
92 #include <netccitt/hdlc.h>
93 #include <netccitt/hd_var.h>
94 #include <netccitt/x25.h>
95 #include <netccitt/pk_var.h>
96 #include <netccitt/pk_extern.h>
97
98 void
99 hd_init()
100 {
101
102 hdintrq.ifq_maxlen = IFQ_MAXLEN;
103 }
104
105 void *
106 hd_ctlinput(prc, addr, ext)
107 int prc;
108 struct sockaddr *addr;
109 void *ext;
110 {
111 struct x25config *xcp = (struct x25config *) addr;
112 struct hdcb *hdp;
113 struct ifaddr *ifa;
114 struct ifnet *ifp;
115
116 if (addr->sa_family != AF_CCITT)
117 return (void *) (EAFNOSUPPORT);
118 if (xcp->xc_lptype != HDLCPROTO_LAPB)
119 return (void *) (EPROTONOSUPPORT);
120 ifa = ifa_ifwithaddr(addr);
121 if (ifa == 0 || ifa->ifa_addr->sa_family != AF_CCITT ||
122 (ifp = ifa->ifa_ifp) == 0)
123 panic("hd_ctlinput");
124 for (hdp = hdcbhead; hdp; hdp = hdp->hd_next)
125 if (hdp->hd_ifp == ifp)
126 break;
127
128 if (hdp == 0) { /* new interface */
129
130 /* an hdcb is now too big to fit in an mbuf */
131 MALLOC(hdp, struct hdcb *, sizeof(*hdp), M_PCB, M_DONTWAIT);
132 if (hdp == 0)
133 return (void *) (ENOBUFS);
134 bzero((caddr_t) hdp, sizeof(*hdp));
135 hdp->hd_pkp =
136 (caddr_t) pk_newlink((struct x25_ifaddr *) ifa,
137 (caddr_t) hdp);
138 ((struct x25_ifaddr *) ifa)->ia_pkcb =
139 (struct pkcb *) hdp->hd_pkp;
140 if (hdp->hd_pkp == 0) {
141 free(hdp, M_PCB);
142 return (void *) (ENOBUFS);
143 }
144 hdp->hd_ifp = ifp;
145 IFAREF(ifa);
146 hdp->hd_ifa = ifa;
147 hdp->hd_xcp = xcp;
148 hdp->hd_state = INIT;
149 hdp->hd_output = hd_ifoutput;
150 hdp->hd_next = hdcbhead;
151 hdcbhead = hdp;
152 } else if (hdp->hd_pkp == 0) { /* interface got reconfigured */
153 hdp->hd_pkp =
154 (caddr_t) pk_newlink((struct x25_ifaddr *) ifa,
155 (caddr_t) hdp);
156 ((struct x25_ifaddr *) ifa)->ia_pkcb =
157 (struct pkcb *) hdp->hd_pkp;
158 if (hdp->hd_pkp == 0) {
159 free(hdp, M_PCB);
160 return (void *) (ENOBUFS);
161 }
162 }
163 switch (prc) {
164 case PRC_IFUP:
165 if (xcp->xc_lwsize == 0 ||
166 xcp->xc_lwsize > MAX_WINDOW_SIZE)
167 xcp->xc_lwsize = MAX_WINDOW_SIZE;
168 if (hdp->hd_state == INIT)
169 SET_TIMER(hdp);
170 break;
171
172 case PRC_IFDOWN:
173 if (hdp->hd_state == ABM)
174 hd_message(hdp, "Operator shutdown: link closed");
175 (void) pk_ctlinput(PRC_LINKDOWN,
176 (struct sockaddr *) hdp->hd_pkp, NULL);
177
178 /* fall thru to ... */
179
180 case PRC_DISCONNECT_REQUEST:
181 /* drop reference to pkcb --- it's dead meat */
182 hdp->hd_pkp = (caddr_t) 0;
183 ((struct x25_ifaddr *) ifa)->ia_pkcb = (struct pkcb *) 0;
184
185 hd_writeinternal(hdp, DISC, POLLON);
186 hdp->hd_state = DISC_SENT;
187 SET_TIMER(hdp);
188 }
189 return (void *) (0);
190 }
191
192 void
193 hd_initvars(hdp)
194 struct hdcb *hdp;
195 {
196 struct mbuf *m;
197 int i;
198
199 /* Clear Transmit queue. */
200 while ((m = hd_remove(&hdp->hd_txq)) != NULL)
201 m_freem(m);
202
203 /* Clear Retransmit queue. */
204 i = hdp->hd_lastrxnr;
205 while (i != hdp->hd_retxqi) {
206 m_freem(hdp->hd_retxq[i]);
207 i = (i + 1) % MODULUS;
208 }
209 hdp->hd_retxqi = 0;
210
211 hdp->hd_vs = hdp->hd_vr = 0;
212 hdp->hd_lasttxnr = hdp->hd_lastrxnr = 0;
213 hdp->hd_rrtimer = 0;
214 KILL_TIMER(hdp);
215 hdp->hd_retxcnt = 0;
216 hdp->hd_condition = 0;
217 }
218
219 int
220 hd_decode(hdp, frame)
221 struct hdcb *hdp;
222 struct Hdlc_frame *frame;
223 {
224 int frametype = ILLEGAL;
225 struct Hdlc_iframe *iframe = (struct Hdlc_iframe *) frame;
226 struct Hdlc_sframe *sframe = (struct Hdlc_sframe *) frame;
227 struct Hdlc_uframe *uframe = (struct Hdlc_uframe *) frame;
228
229 if (iframe->hdlc_0 == 0) {
230 frametype = IFRAME;
231 hdp->hd_iframes_in++;
232 } else if (sframe->hdlc_01 == 1) {
233 /* Supervisory format. */
234 switch (sframe->s2) {
235 case 0:
236 frametype = RR;
237 hdp->hd_rrs_in++;
238 break;
239
240 case 1:
241 frametype = RNR;
242 hdp->hd_rnrs_in++;
243 break;
244
245 case 2:
246 frametype = REJ;
247 hdp->hd_rejs_in++;
248 }
249 } else if (uframe->hdlc_11 == 3) {
250 /* Unnumbered format. */
251 switch (uframe->m3) {
252 case 0:
253 frametype = DM;
254 break;
255
256 case 1:
257 frametype = SABM;
258 break;
259
260 case 2:
261 frametype = DISC;
262 break;
263
264 case 3:
265 frametype = UA;
266 break;
267
268 case 4:
269 frametype = FRMR;
270 hdp->hd_frmrs_in++;
271 }
272 }
273 return (frametype);
274 }
275
276 /*
277 * This routine is called when the HDLC layer internally generates a command
278 * or response for the remote machine ( eg. RR, UA etc. ). Only
279 * supervisory or unnumbered frames are processed.
280 */
281
282 void
283 hd_writeinternal(hdp, frametype, pf)
284 struct hdcb *hdp;
285 int frametype, pf;
286 {
287 struct mbuf *buf;
288 struct Hdlc_frame *frame;
289 struct Hdlc_sframe *sframe;
290 struct Hdlc_uframe *uframe;
291
292 MGETHDR(buf, M_DONTWAIT, MT_HEADER);
293 if (buf == 0)
294 return;
295 frame = mtod(buf, struct Hdlc_frame *);
296 sframe = mtod(buf, struct Hdlc_sframe *);
297 uframe = mtod(buf, struct Hdlc_uframe *);
298
299 /* Assume a response - address structure for DTE */
300 frame->address = ADDRESS_A;
301 buf->m_len = 2;
302 buf->m_nextpkt = buf->m_next = NULL;
303
304 switch (frametype) {
305 case RR:
306 frame->control = RR_CONTROL;
307 hdp->hd_rrs_out++;
308 break;
309
310 case RNR:
311 frame->control = RNR_CONTROL;
312 hdp->hd_rnrs_out++;
313 break;
314
315 case REJ:
316 frame->control = REJ_CONTROL;
317 hdp->hd_rejs_out++;
318 break;
319
320 case SABM:
321 frame->control = SABM_CONTROL;
322 frame->address = ADDRESS_B;
323 break;
324
325 case DISC:
326 if ((hdp->hd_ifp->if_flags & IFF_UP) == 0) {
327 hdp->hd_state = DISCONNECTED;
328 (void) m_freem(buf);
329 hd_flush(hdp->hd_ifp);
330 return;
331 }
332 frame->control = DISC_CONTROL;
333 frame->address = ADDRESS_B;
334 break;
335
336 case DM:
337 frame->control = DM_CONTROL;
338 break;
339
340 case UA:
341 frame->control = UA_CONTROL;
342 break;
343
344 case FRMR:
345 frame->control = FRMR_CONTROL;
346 bcopy((caddr_t) & hd_frmr, (caddr_t) frame->info, 3);
347 buf->m_len = 5;
348 hdp->hd_frmrs_out++;
349
350 }
351
352 if (sframe->hdlc_01 == 1) {
353 /* Supervisory format - RR, REJ, or RNR. */
354 sframe->nr = hdp->hd_vr;
355 sframe->pf = pf;
356 hdp->hd_lasttxnr = hdp->hd_vr;
357 hdp->hd_rrtimer = 0;
358 } else
359 uframe->pf = pf;
360
361 hd_trace(hdp, TX, buf);
362 buf->m_pkthdr.len = buf->m_len;
363 (*hdp->hd_output) (buf, hdp, NULL);
364 }
365
366 struct mbuf *
367 hd_remove(q)
368 struct hdtxq *q;
369 {
370 struct mbuf *m;
371
372 m = q->head;
373 if (m) {
374 if ((q->head = m->m_nextpkt) == NULL)
375 q->tail = NULL;
376 m->m_nextpkt = 0;
377 }
378 return (m);
379 }
380
381 void
382 hd_append(q, m)
383 struct hdtxq *q;
384 struct mbuf *m;
385 {
386
387 m->m_nextpkt = NULL;
388 if (q->tail == NULL)
389 q->head = m;
390 else
391 q->tail->m_nextpkt = m;
392 q->tail = m;
393 }
394
395 void
396 hd_flush(ifp)
397 struct ifnet *ifp;
398 {
399 struct mbuf *m;
400 int s;
401
402 while (1) {
403 s = splnet();
404 IF_DEQUEUE(&ifp->if_snd, m);
405 splx(s);
406 if (m == 0)
407 break;
408 m_freem(m);
409 }
410 }
411
412 void
413 hd_message(hdp, msg)
414 struct hdcb *hdp;
415 char *msg;
416 {
417 if (hdcbhead->hd_next)
418 printf("HDLC(%s): %s\n", format_ntn(hdp->hd_xcp), msg);
419 else
420 printf("HDLC: %s\n", msg);
421 }
422
423 #ifdef HDLCDEBUG
424 void
425 hd_status(hdp)
426 struct hdcb *hdp;
427 {
428 printf("HDLC STATUS:\n V(S)=%d, V(R)=%d, retxqi=%d,\n",
429 hdp->hd_vs, hdp->hd_vr, hdp->hd_retxqi);
430
431 printf("Last_rx_nr=%d, Last_tx_nr=%d,\n Condition=%d, Xx=%d\n",
432 hdp->hd_lastrxnr, hdp->hd_lasttxnr, hdp->hd_condition, hdp->hd_xx);
433 }
434 #endif
Cache object: 6d787ff4d26c90e00a688cd20e8ca305
|