xref: /original-bsd/sys/netccitt/hd_subr.c (revision 374b629e)
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.8 (Berkeley) 12/08/92
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/protosw.h>
21 #include <sys/errno.h>
22 #include <sys/time.h>
23 #include <sys/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 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 			(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;
71 		if (hdp -> hd_pkp == 0) {
72 			free(hdp, M_PCB);
73 			return (ENOBUFS);
74 		}
75 		hdp->hd_ifp = ifp;
76 		hdp->hd_ifa = ifa;
77 		hdp->hd_xcp = xcp;
78 		hdp->hd_state = INIT;
79 		hdp->hd_output = hd_ifoutput;
80 		hdp->hd_next = hdcbhead;
81 		hdcbhead = hdp;
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 		}
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");
106 		(void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp);
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 
115 		hd_writeinternal (hdp, DISC, POLLON);
116 		hdp->hd_state = DISC_SENT;
117 		SET_TIMER (hdp);
118 	}
119 	return (0);
120 }
121 
122 hd_initvars (hdp)
123 register 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 
148 hd_decode (hdp, frame)
149 register struct hdcb *hdp;
150 struct 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 
213 hd_writeinternal (hdp, frametype, pf)
214 register struct hdcb *hdp;
215 register 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 
222 	MGETHDR (buf, M_DONTWAIT, MT_HEADER);
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:
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 		}
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);
293 	buf -> m_pkthdr.len = buf -> m_len;
294 	(*hdp->hd_output) (hdp, buf);
295 }
296 
297 struct mbuf *
298 hd_remove (q)
299 struct 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 
312 hd_append (q, m)
313 register struct hdtxq *q;
314 register 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 
325 hd_flush (ifp)
326 struct ifnet *ifp;
327 {
328 	register struct mbuf *m;
329 	register int s;
330 
331 	while (1) {
332 		s = splimp ();
333 		IF_DEQUEUE (&ifp->if_snd, m);
334 		splx (s);
335 		if (m == 0)
336 			break;
337 		m_freem (m);
338 	}
339 }
340 
341 hd_message (hdp, msg)
342 struct hdcb *hdp;
343 char *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
354 hd_status (hdp)
355 struct 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
364