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