1 /* Copyright (c) University of British Columbia, 1984 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/mbuf.h" 6 #include "../h/domain.h" 7 #include "../h/socket.h" 8 #include "../h/protosw.h" 9 #include "../h/errno.h" 10 #include "../h/time.h" 11 #include "../h/kernel.h" 12 13 #include "../net/if.h" 14 15 #include "../netccitt/hdlc.h" 16 #include "../netccitt/hd_var.h" 17 #include "../netccitt/x25.h" 18 19 hd_init () 20 { 21 22 hdintrq.ifq_maxlen = IFQ_MAXLEN; 23 } 24 25 hd_ctlinput (prc, addr) 26 caddr_t addr; 27 { 28 register struct x25config *xcp = (struct x25config *)addr; 29 register struct ifnet *ifp; 30 register struct hdcb *hdp; 31 register struct ifaddr *ifa; 32 33 if (xcp->xc_family != AF_CCITT) 34 return (EAFNOSUPPORT); 35 if (xcp->xc_lptype != HDLCPROTO_LAPB) 36 return (EPROTONOSUPPORT); 37 for (ifa = ifa_ifwithaddr ((struct sockaddr *)xcp); ifa; ifa = ifa->ifa_next) 38 if (ifa->ifa_addr.sa_family == AF_CCITT) 39 break; 40 if (ifa == 0 || (ifp = ifa->ifa_ifp) == 0) 41 panic ("hd_ctlinput"); 42 for (hdp = hdcbhead; hdp; hdp = hdp->hd_next) 43 if (hdp->hd_ifp == ifp) 44 break; 45 46 if (hdp == 0) { /* new interface */ 47 register int error; 48 register struct mbuf *m; 49 50 m = m_getclr (M_DONTWAIT, MT_PCB); 51 if (m == 0) 52 return (ENOBUFS); 53 if (error = pk_ctlinput (PRC_LINKDOWN, xcp)) { 54 m_freem (m); 55 return (error); 56 } 57 58 hdp = mtod (m, struct hdcb *); 59 hdp->hd_ifp = ifp; 60 hdp->hd_xcp = xcp; 61 hdp->hd_next = hdcbhead; 62 hdcbhead = hdp; 63 hdp->hd_state = INIT; 64 } 65 66 switch (prc) { 67 case PRC_IFUP: 68 if (xcp->xc_lwsize == 0 || 69 xcp->xc_lwsize > MAX_WINDOW_SIZE) 70 xcp->xc_lwsize = MAX_WINDOW_SIZE; 71 if (hdp->hd_state == INIT) 72 SET_TIMER (hdp); 73 break; 74 75 case PRC_IFDOWN: 76 if (hdp->hd_state == ABM) 77 hd_message (hdp, "Operator shutdown: link closed"); 78 (void) pk_ctlinput (PRC_LINKDOWN, xcp); 79 hd_writeinternal (hdp, DISC, POLLON); 80 hdp->hd_state = DISC_SENT; 81 SET_TIMER (hdp); 82 } 83 return (0); 84 } 85 86 hd_initvars (hdp) 87 register struct hdcb *hdp; 88 { 89 register struct mbuf *m; 90 register int i; 91 92 /* Clear Transmit queue. */ 93 while ((m = hd_remove (&hdp->hd_txq)) != NULL) 94 m_freem (m); 95 96 /* Clear Retransmit queue. */ 97 i = hdp->hd_lastrxnr; 98 while (i != hdp->hd_retxqi) { 99 m_freem (hdp->hd_retxq[i]); 100 i = (i + 1) % MODULUS; 101 } 102 hdp->hd_retxqi = 0; 103 104 hdp->hd_vs = hdp->hd_vr = 0; 105 hdp->hd_lasttxnr = hdp->hd_lastrxnr = 0; 106 hdp->hd_rrtimer = 0; 107 KILL_TIMER(hdp); 108 hdp->hd_retxcnt = 0; 109 hdp->hd_condition = 0; 110 } 111 112 hd_decode (hdp, frame) 113 register struct hdcb *hdp; 114 struct Hdlc_frame *frame; 115 { 116 register int frametype = ILLEGAL; 117 register struct Hdlc_iframe *iframe = (struct Hdlc_iframe *) frame; 118 register struct Hdlc_sframe *sframe = (struct Hdlc_sframe *) frame; 119 register struct Hdlc_uframe *uframe = (struct Hdlc_uframe *) frame; 120 121 if (iframe -> hdlc_0 == 0) { 122 frametype = IFRAME; 123 hdp->hd_iframes_in++; 124 } 125 126 else if (sframe -> hdlc_01 == 1) { 127 /* Supervisory format. */ 128 switch (sframe -> s2) { 129 case 0: 130 frametype = RR; 131 hdp->hd_rrs_in++; 132 break; 133 134 case 1: 135 frametype = RNR; 136 hdp->hd_rnrs_in++; 137 break; 138 139 case 2: 140 frametype = REJ; 141 hdp->hd_rejs_in++; 142 } 143 } 144 else if (uframe -> hdlc_11 == 3) { 145 /* Unnumbered format. */ 146 switch (uframe -> m3) { 147 case 0: 148 frametype = DM; 149 break; 150 151 case 1: 152 frametype = SABM; 153 break; 154 155 case 2: 156 frametype = DISC; 157 break; 158 159 case 3: 160 frametype = UA; 161 break; 162 163 case 4: 164 frametype = FRMR; 165 hdp->hd_frmrs_in++; 166 } 167 } 168 return (frametype); 169 } 170 171 /* 172 * This routine is called when the HDLC layer internally generates a 173 * command or response for the remote machine ( eg. RR, UA etc. ). 174 * Only supervisory or unnumbered frames are processed. 175 */ 176 177 hd_writeinternal (hdp, frametype, pf) 178 register struct hdcb *hdp; 179 register int frametype, pf; 180 { 181 register struct mbuf *buf; 182 struct Hdlc_frame *frame; 183 register struct Hdlc_sframe *sframe; 184 register struct Hdlc_uframe *uframe; 185 186 MGET (buf, M_DONTWAIT, MT_HEADER); 187 if (buf == 0) 188 return; 189 frame = mtod (buf, struct Hdlc_frame *); 190 sframe = mtod (buf, struct Hdlc_sframe *); 191 uframe = mtod (buf, struct Hdlc_uframe *); 192 193 /* Assume a response - address structure for DTE */ 194 frame -> address = ADDRESS_A; 195 buf -> m_len = 2; 196 buf -> m_act = buf -> m_next = NULL; 197 198 switch (frametype) { 199 case RR: 200 frame -> control = RR_CONTROL; 201 hdp->hd_rrs_out++; 202 break; 203 204 case RNR: 205 frame -> control = RNR_CONTROL; 206 hdp->hd_rnrs_out++; 207 break; 208 209 case REJ: 210 frame -> control = REJ_CONTROL; 211 hdp->hd_rejs_out++; 212 break; 213 214 case SABM: 215 frame -> control = SABM_CONTROL; 216 frame -> address = ADDRESS_B; 217 break; 218 219 case DISC: 220 frame -> control = DISC_CONTROL; 221 frame -> address = ADDRESS_B; 222 break; 223 224 case DM: 225 frame -> control = DM_CONTROL; 226 break; 227 228 case UA: 229 frame -> control = UA_CONTROL; 230 break; 231 232 case FRMR: 233 frame -> control = FRMR_CONTROL; 234 bcopy ((caddr_t)&hd_frmr, (caddr_t)frame -> info, 3); 235 buf -> m_len = 5; 236 hdp->hd_frmrs_out++; 237 238 } 239 240 if (sframe -> hdlc_01 == 1) { 241 /* Supervisory format - RR, REJ, or RNR. */ 242 sframe -> nr = hdp->hd_vr; 243 sframe -> pf = pf; 244 hdp->hd_lasttxnr = hdp->hd_vr; 245 hdp->hd_rrtimer = 0; 246 } 247 else 248 uframe -> pf = pf; 249 250 hd_trace (hdp, TX, frame); 251 (*hdp -> hd_ifp -> if_output) (hdp -> hd_ifp, buf, 252 (struct sockaddr *)hdp->hd_xcp); 253 254 } 255 256 struct mbuf * 257 hd_remove (q) 258 struct hdtxq *q; 259 { 260 register struct mbuf *m; 261 262 m = q -> head; 263 if (m) { 264 if ((q -> head = m -> m_act) == NULL) 265 q -> tail = NULL; 266 m -> m_act = 0; 267 } 268 return (m); 269 } 270 271 hd_append (q, m) 272 register struct hdtxq *q; 273 register struct mbuf *m; 274 { 275 276 m -> m_act = NULL; 277 if (q -> tail == NULL) 278 q -> head = m; 279 else 280 q -> tail -> m_act = m; 281 q -> tail = m; 282 } 283 284 hd_flush (ifp) 285 struct ifnet *ifp; 286 { 287 register struct mbuf *m; 288 register int s; 289 290 while (1) { 291 s = spl6 (); /* XXX SHOULDN'T THIS BE splimp? */ 292 IF_DEQUEUE (&ifp->if_snd, m); 293 splx (s); 294 if (m == 0) 295 break; 296 m_freem (m); 297 } 298 } 299 300 hd_message (hdp, msg) 301 struct hdcb *hdp; 302 char *msg; 303 { 304 char *format_ntn (); 305 306 if (hdcbhead -> hd_next) 307 printf ("HDLC(%s): %s\n", format_ntn (hdp->hd_xcp), msg); 308 else 309 printf ("HDLC: %s\n", msg); 310 } 311 312 #ifdef HDLCDEBUG 313 hd_status (hdp) 314 struct hdcb *hdp; 315 { 316 printf ("HDLC STATUS:\n V(S)=%d, V(R)=%d, retxqi=%d,\n", 317 hdp->hd_vs, hdp->hd_vr, hdp->hd_retxqi); 318 319 printf ("Last_rx_nr=%d, Last_tx_nr=%d,\n Condition=%d, Xx=%d\n", 320 hdp->hd_lastrxnr, hdp->hd_lasttxnr, hdp->hd_condition, hdp->hd_xx); 321 } 322 #endif 323