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
hd_init()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
hd_initvars(hdp)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
hd_decode(hdp,frame)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
hd_writeinternal(hdp,frametype,pf)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 *
hd_remove(q)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
hd_append(q,m)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