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