Commit | Line | Data |
---|---|---|
15637ed4 RG |
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 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | |
18 | * 3. All advertising materials mentioning features or use of this software | |
19 | * must display the following acknowledgement: | |
20 | * This product includes software developed by the University of | |
21 | * California, Berkeley and its contributors. | |
22 | * 4. Neither the name of the University nor the names of its contributors | |
23 | * may be used to endorse or promote products derived from this software | |
24 | * without specific prior written permission. | |
25 | * | |
26 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
27 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
28 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
29 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
30 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
31 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
32 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
33 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
34 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
35 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
36 | * SUCH DAMAGE. | |
37 | * | |
1cdffd64 | 38 | * from: @(#)hd_subr.c 7.6 (Berkeley) 5/29/91 |
4c45483e | 39 | * $Id: hd_subr.c,v 1.2 1993/10/16 19:46:37 rgrimes Exp $ |
15637ed4 RG |
40 | */ |
41 | ||
42 | #include "param.h" | |
43 | #include "systm.h" | |
44 | #include "mbuf.h" | |
45 | #include "domain.h" | |
46 | #include "socket.h" | |
47 | #include "protosw.h" | |
48 | #include "errno.h" | |
49 | #include "time.h" | |
50 | #include "kernel.h" | |
51 | ||
52 | #include "../net/if.h" | |
53 | ||
54 | #include "hdlc.h" | |
55 | #include "hd_var.h" | |
56 | #include "x25.h" | |
57 | ||
4c45483e | 58 | void |
15637ed4 RG |
59 | hd_init () |
60 | { | |
61 | ||
62 | hdintrq.ifq_maxlen = IFQ_MAXLEN; | |
63 | } | |
64 | ||
4c45483e | 65 | int |
15637ed4 | 66 | hd_ctlinput (prc, addr) |
4c45483e GW |
67 | int prc; |
68 | struct sockaddr *addr; | |
15637ed4 RG |
69 | { |
70 | register struct x25config *xcp = (struct x25config *)addr; | |
71 | register struct hdcb *hdp; | |
72 | register struct ifaddr *ifa; | |
73 | struct ifnet *ifp; | |
74 | caddr_t pk_newlink(); | |
75 | ||
76 | if (addr->sa_family != AF_CCITT) | |
77 | return (EAFNOSUPPORT); | |
78 | if (xcp->xc_lptype != HDLCPROTO_LAPB) | |
79 | return (EPROTONOSUPPORT); | |
80 | ifa = ifa_ifwithaddr(addr); | |
81 | if (ifa == 0 || ifa->ifa_addr->sa_family != AF_CCITT || | |
82 | (ifp = ifa->ifa_ifp) == 0) | |
83 | panic ("hd_ctlinput"); | |
84 | for (hdp = hdcbhead; hdp; hdp = hdp->hd_next) | |
85 | if (hdp->hd_ifp == ifp) | |
86 | break; | |
87 | ||
88 | if (hdp == 0) { /* new interface */ | |
89 | int error, hd_ifoutput(), hd_output(); | |
90 | ||
91 | /* an hdcb is now too big to fit in an mbuf */ | |
92 | MALLOC(hdp, struct hdcb *, sizeof (*hdp), M_PCB, M_DONTWAIT); | |
93 | if (hdp == 0) | |
94 | return (ENOBUFS); | |
95 | bzero((caddr_t)hdp, sizeof(*hdp)); | |
96 | hdp->hd_pkp = | |
97 | pk_newlink ((struct x25_ifaddr *)ifa, (caddr_t)hdp); | |
98 | if (hdp -> hd_pkp == 0) { | |
99 | free(hdp, M_PCB); | |
100 | return (ENOBUFS); | |
101 | } | |
102 | hdp->hd_ifp = ifp; | |
103 | hdp->hd_ifa = ifa; | |
104 | hdp->hd_xcp = xcp; | |
105 | hdp->hd_state = INIT; | |
106 | hdp->hd_output = hd_ifoutput; | |
107 | hdp->hd_next = hdcbhead; | |
108 | hdcbhead = hdp; | |
109 | } | |
110 | ||
111 | switch (prc) { | |
112 | case PRC_IFUP: | |
113 | if (xcp->xc_lwsize == 0 || | |
114 | xcp->xc_lwsize > MAX_WINDOW_SIZE) | |
115 | xcp->xc_lwsize = MAX_WINDOW_SIZE; | |
116 | if (hdp->hd_state == INIT) | |
117 | SET_TIMER (hdp); | |
118 | break; | |
119 | ||
120 | case PRC_IFDOWN: | |
121 | if (hdp->hd_state == ABM) | |
122 | hd_message (hdp, "Operator shutdown: link closed"); | |
123 | (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp); | |
124 | hd_writeinternal (hdp, DISC, POLLON); | |
125 | hdp->hd_state = DISC_SENT; | |
126 | SET_TIMER (hdp); | |
127 | } | |
128 | return (0); | |
129 | } | |
130 | ||
4c45483e | 131 | void |
15637ed4 | 132 | hd_initvars (hdp) |
4c45483e | 133 | register struct hdcb *hdp; |
15637ed4 RG |
134 | { |
135 | register struct mbuf *m; | |
136 | register int i; | |
137 | ||
138 | /* Clear Transmit queue. */ | |
139 | while ((m = hd_remove (&hdp->hd_txq)) != NULL) | |
140 | m_freem (m); | |
141 | ||
142 | /* Clear Retransmit queue. */ | |
143 | i = hdp->hd_lastrxnr; | |
144 | while (i != hdp->hd_retxqi) { | |
145 | m_freem (hdp->hd_retxq[i]); | |
146 | i = (i + 1) % MODULUS; | |
147 | } | |
148 | hdp->hd_retxqi = 0; | |
149 | ||
150 | hdp->hd_vs = hdp->hd_vr = 0; | |
151 | hdp->hd_lasttxnr = hdp->hd_lastrxnr = 0; | |
152 | hdp->hd_rrtimer = 0; | |
153 | KILL_TIMER(hdp); | |
154 | hdp->hd_retxcnt = 0; | |
155 | hdp->hd_condition = 0; | |
156 | } | |
157 | ||
4c45483e | 158 | int |
15637ed4 | 159 | hd_decode (hdp, frame) |
4c45483e GW |
160 | register struct hdcb *hdp; |
161 | struct Hdlc_frame *frame; | |
15637ed4 RG |
162 | { |
163 | register int frametype = ILLEGAL; | |
164 | register struct Hdlc_iframe *iframe = (struct Hdlc_iframe *) frame; | |
165 | register struct Hdlc_sframe *sframe = (struct Hdlc_sframe *) frame; | |
166 | register struct Hdlc_uframe *uframe = (struct Hdlc_uframe *) frame; | |
167 | ||
168 | if (iframe -> hdlc_0 == 0) { | |
169 | frametype = IFRAME; | |
170 | hdp->hd_iframes_in++; | |
171 | } | |
172 | ||
173 | else if (sframe -> hdlc_01 == 1) { | |
174 | /* Supervisory format. */ | |
175 | switch (sframe -> s2) { | |
176 | case 0: | |
177 | frametype = RR; | |
178 | hdp->hd_rrs_in++; | |
179 | break; | |
180 | ||
181 | case 1: | |
182 | frametype = RNR; | |
183 | hdp->hd_rnrs_in++; | |
184 | break; | |
185 | ||
186 | case 2: | |
187 | frametype = REJ; | |
188 | hdp->hd_rejs_in++; | |
189 | } | |
190 | } | |
191 | else if (uframe -> hdlc_11 == 3) { | |
192 | /* Unnumbered format. */ | |
193 | switch (uframe -> m3) { | |
194 | case 0: | |
195 | frametype = DM; | |
196 | break; | |
197 | ||
198 | case 1: | |
199 | frametype = SABM; | |
200 | break; | |
201 | ||
202 | case 2: | |
203 | frametype = DISC; | |
204 | break; | |
205 | ||
206 | case 3: | |
207 | frametype = UA; | |
208 | break; | |
209 | ||
210 | case 4: | |
211 | frametype = FRMR; | |
212 | hdp->hd_frmrs_in++; | |
213 | } | |
214 | } | |
215 | return (frametype); | |
216 | } | |
217 | ||
218 | /* | |
219 | * This routine is called when the HDLC layer internally generates a | |
220 | * command or response for the remote machine ( eg. RR, UA etc. ). | |
221 | * Only supervisory or unnumbered frames are processed. | |
222 | */ | |
223 | ||
4c45483e | 224 | void |
15637ed4 | 225 | hd_writeinternal (hdp, frametype, pf) |
4c45483e GW |
226 | register struct hdcb *hdp; |
227 | register int frametype, pf; | |
15637ed4 RG |
228 | { |
229 | register struct mbuf *buf; | |
230 | struct Hdlc_frame *frame; | |
231 | register struct Hdlc_sframe *sframe; | |
232 | register struct Hdlc_uframe *uframe; | |
233 | ||
234 | MGETHDR (buf, M_DONTWAIT, MT_HEADER); | |
235 | if (buf == 0) | |
236 | return; | |
237 | frame = mtod (buf, struct Hdlc_frame *); | |
238 | sframe = mtod (buf, struct Hdlc_sframe *); | |
239 | uframe = mtod (buf, struct Hdlc_uframe *); | |
240 | ||
241 | /* Assume a response - address structure for DTE */ | |
242 | frame -> address = ADDRESS_A; | |
243 | buf -> m_len = 2; | |
244 | buf -> m_act = buf -> m_next = NULL; | |
245 | ||
246 | switch (frametype) { | |
247 | case RR: | |
248 | frame -> control = RR_CONTROL; | |
249 | hdp->hd_rrs_out++; | |
250 | break; | |
251 | ||
252 | case RNR: | |
253 | frame -> control = RNR_CONTROL; | |
254 | hdp->hd_rnrs_out++; | |
255 | break; | |
256 | ||
257 | case REJ: | |
258 | frame -> control = REJ_CONTROL; | |
259 | hdp->hd_rejs_out++; | |
260 | break; | |
261 | ||
262 | case SABM: | |
263 | frame -> control = SABM_CONTROL; | |
264 | frame -> address = ADDRESS_B; | |
265 | break; | |
266 | ||
267 | case DISC: | |
268 | if ((hdp->hd_ifp->if_flags & IFF_UP) == 0) { | |
269 | hdp->hd_state = DISCONNECTED; | |
270 | (void) m_freem (buf); | |
271 | hd_flush (hdp->hd_ifp); | |
272 | return; | |
273 | } | |
274 | frame -> control = DISC_CONTROL; | |
275 | frame -> address = ADDRESS_B; | |
276 | break; | |
277 | ||
278 | case DM: | |
279 | frame -> control = DM_CONTROL; | |
280 | break; | |
281 | ||
282 | case UA: | |
283 | frame -> control = UA_CONTROL; | |
284 | break; | |
285 | ||
286 | case FRMR: | |
287 | frame -> control = FRMR_CONTROL; | |
288 | bcopy ((caddr_t)&hd_frmr, (caddr_t)frame -> info, 3); | |
289 | buf -> m_len = 5; | |
290 | hdp->hd_frmrs_out++; | |
291 | ||
292 | } | |
293 | ||
294 | if (sframe -> hdlc_01 == 1) { | |
295 | /* Supervisory format - RR, REJ, or RNR. */ | |
296 | sframe -> nr = hdp->hd_vr; | |
297 | sframe -> pf = pf; | |
298 | hdp->hd_lasttxnr = hdp->hd_vr; | |
299 | hdp->hd_rrtimer = 0; | |
300 | } | |
301 | else | |
302 | uframe -> pf = pf; | |
303 | ||
304 | hd_trace (hdp, TX, frame); | |
305 | buf -> m_pkthdr.len = buf -> m_len; | |
306 | (*hdp->hd_output) (hdp, buf); | |
307 | } | |
308 | ||
309 | struct mbuf * | |
310 | hd_remove (q) | |
311 | struct hdtxq *q; | |
312 | { | |
313 | register struct mbuf *m; | |
314 | ||
315 | m = q -> head; | |
316 | if (m) { | |
317 | if ((q -> head = m -> m_act) == NULL) | |
318 | q -> tail = NULL; | |
319 | m -> m_act = 0; | |
320 | } | |
321 | return (m); | |
322 | } | |
323 | ||
4c45483e | 324 | void |
15637ed4 | 325 | hd_append (q, m) |
4c45483e GW |
326 | register struct hdtxq *q; |
327 | register struct mbuf *m; | |
15637ed4 RG |
328 | { |
329 | ||
330 | m -> m_act = NULL; | |
331 | if (q -> tail == NULL) | |
332 | q -> head = m; | |
333 | else | |
334 | q -> tail -> m_act = m; | |
335 | q -> tail = m; | |
336 | } | |
337 | ||
4c45483e | 338 | void |
15637ed4 | 339 | hd_flush (ifp) |
4c45483e | 340 | struct ifnet *ifp; |
15637ed4 RG |
341 | { |
342 | register struct mbuf *m; | |
343 | register int s; | |
344 | ||
345 | while (1) { | |
346 | s = splimp (); | |
347 | IF_DEQUEUE (&ifp->if_snd, m); | |
348 | splx (s); | |
349 | if (m == 0) | |
350 | break; | |
351 | m_freem (m); | |
352 | } | |
353 | } | |
354 | ||
4c45483e | 355 | void |
15637ed4 | 356 | hd_message (hdp, msg) |
4c45483e GW |
357 | struct hdcb *hdp; |
358 | const char *msg; | |
15637ed4 RG |
359 | { |
360 | char *format_ntn (); | |
361 | ||
362 | if (hdcbhead -> hd_next) | |
363 | printf ("HDLC(%s): %s\n", format_ntn (hdp->hd_xcp), msg); | |
364 | else | |
365 | printf ("HDLC: %s\n", msg); | |
366 | } | |
367 | ||
368 | #ifdef HDLCDEBUG | |
369 | hd_status (hdp) | |
370 | struct hdcb *hdp; | |
371 | { | |
372 | printf ("HDLC STATUS:\n V(S)=%d, V(R)=%d, retxqi=%d,\n", | |
373 | hdp->hd_vs, hdp->hd_vr, hdp->hd_retxqi); | |
374 | ||
375 | printf ("Last_rx_nr=%d, Last_tx_nr=%d,\n Condition=%d, Xx=%d\n", | |
376 | hdp->hd_lastrxnr, hdp->hd_lasttxnr, hdp->hd_condition, hdp->hd_xx); | |
377 | } | |
378 | #endif |