restore original UBC Copyright
[unix-history] / usr / src / sys / netccitt / hd_subr.c
CommitLineData
21e3a7bd
KS
1/*
2 * Copyright (c) University of British Columbia, 1984
3 * Copyright (c) 1990 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * the Laboratory for Computation Vision and the Computer Science Department
8 * of the University of British Columbia.
9 *
10 * %sccs.include.redist.c%
11 *
dfa4fd4b 12 * @(#)hd_subr.c 7.8 (Berkeley) %G%
21e3a7bd 13 */
edc74019 14
5548a02f
KB
15#include <sys/param.h>
16#include <sys/systm.h>
17#include <sys/mbuf.h>
18#include <sys/domain.h>
19#include <sys/socket.h>
20#include <sys/protosw.h>
21#include <sys/errno.h>
22#include <sys/time.h>
23#include <sys/kernel.h>
edc74019 24
5548a02f 25#include <net/if.h>
edc74019 26
5548a02f
KB
27#include <netccitt/hdlc.h>
28#include <netccitt/hd_var.h>
29#include <netccitt/x25.h>
edc74019
KS
30
31hd_init ()
32{
33
34 hdintrq.ifq_maxlen = IFQ_MAXLEN;
35}
36
37hd_ctlinput (prc, addr)
42963956 38struct sockaddr *addr;
edc74019
KS
39{
40 register struct x25config *xcp = (struct x25config *)addr;
edc74019
KS
41 register struct hdcb *hdp;
42 register struct ifaddr *ifa;
42963956 43 struct ifnet *ifp;
315951e8 44 caddr_t pk_newlink();
edc74019 45
42963956 46 if (addr->sa_family != AF_CCITT)
edc74019
KS
47 return (EAFNOSUPPORT);
48 if (xcp->xc_lptype != HDLCPROTO_LAPB)
49 return (EPROTONOSUPPORT);
42963956
KS
50 ifa = ifa_ifwithaddr(addr);
51 if (ifa == 0 || ifa->ifa_addr->sa_family != AF_CCITT ||
52 (ifp = ifa->ifa_ifp) == 0)
edc74019
KS
53 panic ("hd_ctlinput");
54 for (hdp = hdcbhead; hdp; hdp = hdp->hd_next)
55 if (hdp->hd_ifp == ifp)
56 break;
57
58 if (hdp == 0) { /* new interface */
42963956 59 int error, hd_ifoutput(), hd_output();
edc74019 60
42963956
KS
61 /* an hdcb is now too big to fit in an mbuf */
62 MALLOC(hdp, struct hdcb *, sizeof (*hdp), M_PCB, M_DONTWAIT);
63 if (hdp == 0)
edc74019 64 return (ENOBUFS);
42963956 65 bzero((caddr_t)hdp, sizeof(*hdp));
315951e8 66 hdp->hd_pkp =
dfa4fd4b
KS
67 (caddr_t) pk_newlink ((struct x25_ifaddr *) ifa,
68 (caddr_t) hdp);
69 ((struct x25_ifaddr *)ifa)->ia_pkcb =
70 (struct pkcb *) hdp->hd_pkp;
315951e8
KS
71 if (hdp -> hd_pkp == 0) {
72 free(hdp, M_PCB);
73 return (ENOBUFS);
edc74019 74 }
42963956
KS
75 hdp->hd_ifp = ifp;
76 hdp->hd_ifa = ifa;
77 hdp->hd_xcp = xcp;
edc74019 78 hdp->hd_state = INIT;
42963956 79 hdp->hd_output = hd_ifoutput;
315951e8
KS
80 hdp->hd_next = hdcbhead;
81 hdcbhead = hdp;
dfa4fd4b
KS
82 } else if (hdp->hd_pkp == 0) { /* interface got reconfigured */
83 hdp->hd_pkp =
84 (caddr_t) pk_newlink ((struct x25_ifaddr *) ifa,
85 (caddr_t) hdp);
86 ((struct x25_ifaddr *)ifa)->ia_pkcb =
87 (struct pkcb *) hdp->hd_pkp;
88 if (hdp -> hd_pkp == 0) {
89 free(hdp, M_PCB);
90 return (ENOBUFS);
91 }
edc74019
KS
92 }
93
94 switch (prc) {
95 case PRC_IFUP:
96 if (xcp->xc_lwsize == 0 ||
97 xcp->xc_lwsize > MAX_WINDOW_SIZE)
98 xcp->xc_lwsize = MAX_WINDOW_SIZE;
99 if (hdp->hd_state == INIT)
100 SET_TIMER (hdp);
101 break;
102
103 case PRC_IFDOWN:
104 if (hdp->hd_state == ABM)
105 hd_message (hdp, "Operator shutdown: link closed");
315951e8 106 (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp);
dfa4fd4b
KS
107
108 /* fall thru to ... */
109
110 case PRC_DISCONNECT_REQUEST:
111 /* drop reference to pkcb --- it's dead meat */
112 hdp->hd_pkp = (caddr_t) 0;
113 ((struct x25_ifaddr *)ifa)->ia_pkcb = (struct pkcb *) 0;
114
edc74019
KS
115 hd_writeinternal (hdp, DISC, POLLON);
116 hdp->hd_state = DISC_SENT;
117 SET_TIMER (hdp);
118 }
119 return (0);
120}
121
122hd_initvars (hdp)
123register struct hdcb *hdp;
124{
125 register struct mbuf *m;
126 register int i;
127
128 /* Clear Transmit queue. */
129 while ((m = hd_remove (&hdp->hd_txq)) != NULL)
130 m_freem (m);
131
132 /* Clear Retransmit queue. */
133 i = hdp->hd_lastrxnr;
134 while (i != hdp->hd_retxqi) {
135 m_freem (hdp->hd_retxq[i]);
136 i = (i + 1) % MODULUS;
137 }
138 hdp->hd_retxqi = 0;
139
140 hdp->hd_vs = hdp->hd_vr = 0;
141 hdp->hd_lasttxnr = hdp->hd_lastrxnr = 0;
142 hdp->hd_rrtimer = 0;
143 KILL_TIMER(hdp);
144 hdp->hd_retxcnt = 0;
145 hdp->hd_condition = 0;
146}
147
148hd_decode (hdp, frame)
149register struct hdcb *hdp;
150struct Hdlc_frame *frame;
151{
152 register int frametype = ILLEGAL;
153 register struct Hdlc_iframe *iframe = (struct Hdlc_iframe *) frame;
154 register struct Hdlc_sframe *sframe = (struct Hdlc_sframe *) frame;
155 register struct Hdlc_uframe *uframe = (struct Hdlc_uframe *) frame;
156
157 if (iframe -> hdlc_0 == 0) {
158 frametype = IFRAME;
159 hdp->hd_iframes_in++;
160 }
161
162 else if (sframe -> hdlc_01 == 1) {
163 /* Supervisory format. */
164 switch (sframe -> s2) {
165 case 0:
166 frametype = RR;
167 hdp->hd_rrs_in++;
168 break;
169
170 case 1:
171 frametype = RNR;
172 hdp->hd_rnrs_in++;
173 break;
174
175 case 2:
176 frametype = REJ;
177 hdp->hd_rejs_in++;
178 }
179 }
180 else if (uframe -> hdlc_11 == 3) {
181 /* Unnumbered format. */
182 switch (uframe -> m3) {
183 case 0:
184 frametype = DM;
185 break;
186
187 case 1:
188 frametype = SABM;
189 break;
190
191 case 2:
192 frametype = DISC;
193 break;
194
195 case 3:
196 frametype = UA;
197 break;
198
199 case 4:
200 frametype = FRMR;
201 hdp->hd_frmrs_in++;
202 }
203 }
204 return (frametype);
205}
206
207/*
208 * This routine is called when the HDLC layer internally generates a
209 * command or response for the remote machine ( eg. RR, UA etc. ).
210 * Only supervisory or unnumbered frames are processed.
211 */
212
213hd_writeinternal (hdp, frametype, pf)
214register struct hdcb *hdp;
215register int frametype, pf;
216{
217 register struct mbuf *buf;
218 struct Hdlc_frame *frame;
219 register struct Hdlc_sframe *sframe;
220 register struct Hdlc_uframe *uframe;
221
42963956 222 MGETHDR (buf, M_DONTWAIT, MT_HEADER);
edc74019
KS
223 if (buf == 0)
224 return;
225 frame = mtod (buf, struct Hdlc_frame *);
226 sframe = mtod (buf, struct Hdlc_sframe *);
227 uframe = mtod (buf, struct Hdlc_uframe *);
228
229 /* Assume a response - address structure for DTE */
230 frame -> address = ADDRESS_A;
231 buf -> m_len = 2;
232 buf -> m_act = buf -> m_next = NULL;
233
234 switch (frametype) {
235 case RR:
236 frame -> control = RR_CONTROL;
237 hdp->hd_rrs_out++;
238 break;
239
240 case RNR:
241 frame -> control = RNR_CONTROL;
242 hdp->hd_rnrs_out++;
243 break;
244
245 case REJ:
246 frame -> control = REJ_CONTROL;
247 hdp->hd_rejs_out++;
248 break;
249
250 case SABM:
251 frame -> control = SABM_CONTROL;
252 frame -> address = ADDRESS_B;
253 break;
254
255 case DISC:
42963956
KS
256 if ((hdp->hd_ifp->if_flags & IFF_UP) == 0) {
257 hdp->hd_state = DISCONNECTED;
258 (void) m_freem (buf);
259 hd_flush (hdp->hd_ifp);
260 return;
261 }
edc74019
KS
262 frame -> control = DISC_CONTROL;
263 frame -> address = ADDRESS_B;
264 break;
265
266 case DM:
267 frame -> control = DM_CONTROL;
268 break;
269
270 case UA:
271 frame -> control = UA_CONTROL;
272 break;
273
274 case FRMR:
275 frame -> control = FRMR_CONTROL;
276 bcopy ((caddr_t)&hd_frmr, (caddr_t)frame -> info, 3);
277 buf -> m_len = 5;
278 hdp->hd_frmrs_out++;
279
280 }
281
282 if (sframe -> hdlc_01 == 1) {
283 /* Supervisory format - RR, REJ, or RNR. */
284 sframe -> nr = hdp->hd_vr;
285 sframe -> pf = pf;
286 hdp->hd_lasttxnr = hdp->hd_vr;
287 hdp->hd_rrtimer = 0;
288 }
289 else
290 uframe -> pf = pf;
291
292 hd_trace (hdp, TX, frame);
42963956
KS
293 buf -> m_pkthdr.len = buf -> m_len;
294 (*hdp->hd_output) (hdp, buf);
edc74019
KS
295}
296
297struct mbuf *
298hd_remove (q)
299struct hdtxq *q;
300{
301 register struct mbuf *m;
302
303 m = q -> head;
304 if (m) {
305 if ((q -> head = m -> m_act) == NULL)
306 q -> tail = NULL;
307 m -> m_act = 0;
308 }
309 return (m);
310}
311
312hd_append (q, m)
313register struct hdtxq *q;
314register struct mbuf *m;
315{
316
317 m -> m_act = NULL;
318 if (q -> tail == NULL)
319 q -> head = m;
320 else
321 q -> tail -> m_act = m;
322 q -> tail = m;
323}
324
325hd_flush (ifp)
326struct ifnet *ifp;
327{
328 register struct mbuf *m;
329 register int s;
330
331 while (1) {
42963956 332 s = splimp ();
edc74019
KS
333 IF_DEQUEUE (&ifp->if_snd, m);
334 splx (s);
335 if (m == 0)
336 break;
337 m_freem (m);
338 }
339}
340
341hd_message (hdp, msg)
342struct hdcb *hdp;
343char *msg;
344{
345 char *format_ntn ();
346
347 if (hdcbhead -> hd_next)
348 printf ("HDLC(%s): %s\n", format_ntn (hdp->hd_xcp), msg);
349 else
350 printf ("HDLC: %s\n", msg);
351}
352
353#ifdef HDLCDEBUG
354hd_status (hdp)
355struct hdcb *hdp;
356{
357 printf ("HDLC STATUS:\n V(S)=%d, V(R)=%d, retxqi=%d,\n",
358 hdp->hd_vs, hdp->hd_vr, hdp->hd_retxqi);
359
360 printf ("Last_rx_nr=%d, Last_tx_nr=%d,\n Condition=%d, Xx=%d\n",
361 hdp->hd_lastrxnr, hdp->hd_lasttxnr, hdp->hd_condition, hdp->hd_xx);
362}
363#endif