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