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