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