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