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