1*41705Ssklower /* 2*41705Ssklower * Copyright (c) University of British Columbia, 1984 3*41705Ssklower * Copyright (c) 1990 The Regents of the University of California. 4*41705Ssklower * All rights reserved. 5*41705Ssklower * 6*41705Ssklower * This code is derived from software contributed to Berkeley by 7*41705Ssklower * the Laboratory for Computation Vision and the Computer Science Department 8*41705Ssklower * of the University of British Columbia. 9*41705Ssklower * 10*41705Ssklower * %sccs.include.redist.c% 11*41705Ssklower * 12*41705Ssklower * @(#)hd_subr.c 7.2 (Berkeley) 05/11/90 13*41705Ssklower */ 1441587Ssklower 1541587Ssklower #include "../h/param.h" 1641587Ssklower #include "../h/systm.h" 1741587Ssklower #include "../h/mbuf.h" 1841587Ssklower #include "../h/domain.h" 1941587Ssklower #include "../h/socket.h" 2041587Ssklower #include "../h/protosw.h" 2141587Ssklower #include "../h/errno.h" 2241587Ssklower #include "../h/time.h" 2341587Ssklower #include "../h/kernel.h" 2441587Ssklower 2541587Ssklower #include "../net/if.h" 2641587Ssklower 2741587Ssklower #include "../netccitt/hdlc.h" 2841587Ssklower #include "../netccitt/hd_var.h" 2941587Ssklower #include "../netccitt/x25.h" 3041587Ssklower 3141587Ssklower hd_init () 3241587Ssklower { 3341587Ssklower 3441587Ssklower hdintrq.ifq_maxlen = IFQ_MAXLEN; 3541587Ssklower } 3641587Ssklower 3741587Ssklower hd_ctlinput (prc, addr) 3841587Ssklower caddr_t addr; 3941587Ssklower { 4041587Ssklower register struct x25config *xcp = (struct x25config *)addr; 4141587Ssklower register struct ifnet *ifp; 4241587Ssklower register struct hdcb *hdp; 4341587Ssklower register struct ifaddr *ifa; 4441587Ssklower 4541587Ssklower if (xcp->xc_family != AF_CCITT) 4641587Ssklower return (EAFNOSUPPORT); 4741587Ssklower if (xcp->xc_lptype != HDLCPROTO_LAPB) 4841587Ssklower return (EPROTONOSUPPORT); 4941587Ssklower for (ifa = ifa_ifwithaddr ((struct sockaddr *)xcp); ifa; ifa = ifa->ifa_next) 5041587Ssklower if (ifa->ifa_addr.sa_family == AF_CCITT) 5141587Ssklower break; 5241587Ssklower if (ifa == 0 || (ifp = ifa->ifa_ifp) == 0) 5341587Ssklower panic ("hd_ctlinput"); 5441587Ssklower for (hdp = hdcbhead; hdp; hdp = hdp->hd_next) 5541587Ssklower if (hdp->hd_ifp == ifp) 5641587Ssklower break; 5741587Ssklower 5841587Ssklower if (hdp == 0) { /* new interface */ 5941587Ssklower register int error; 6041587Ssklower register struct mbuf *m; 6141587Ssklower 6241587Ssklower m = m_getclr (M_DONTWAIT, MT_PCB); 6341587Ssklower if (m == 0) 6441587Ssklower return (ENOBUFS); 6541587Ssklower if (error = pk_ctlinput (PRC_LINKDOWN, xcp)) { 6641587Ssklower m_freem (m); 6741587Ssklower return (error); 6841587Ssklower } 6941587Ssklower 7041587Ssklower hdp = mtod (m, struct hdcb *); 7141587Ssklower hdp->hd_ifp = ifp; 7241587Ssklower hdp->hd_xcp = xcp; 7341587Ssklower hdp->hd_next = hdcbhead; 7441587Ssklower hdcbhead = hdp; 7541587Ssklower hdp->hd_state = INIT; 7641587Ssklower } 7741587Ssklower 7841587Ssklower switch (prc) { 7941587Ssklower case PRC_IFUP: 8041587Ssklower if (xcp->xc_lwsize == 0 || 8141587Ssklower xcp->xc_lwsize > MAX_WINDOW_SIZE) 8241587Ssklower xcp->xc_lwsize = MAX_WINDOW_SIZE; 8341587Ssklower if (hdp->hd_state == INIT) 8441587Ssklower SET_TIMER (hdp); 8541587Ssklower break; 8641587Ssklower 8741587Ssklower case PRC_IFDOWN: 8841587Ssklower if (hdp->hd_state == ABM) 8941587Ssklower hd_message (hdp, "Operator shutdown: link closed"); 9041587Ssklower (void) pk_ctlinput (PRC_LINKDOWN, xcp); 9141587Ssklower hd_writeinternal (hdp, DISC, POLLON); 9241587Ssklower hdp->hd_state = DISC_SENT; 9341587Ssklower SET_TIMER (hdp); 9441587Ssklower } 9541587Ssklower return (0); 9641587Ssklower } 9741587Ssklower 9841587Ssklower hd_initvars (hdp) 9941587Ssklower register struct hdcb *hdp; 10041587Ssklower { 10141587Ssklower register struct mbuf *m; 10241587Ssklower register int i; 10341587Ssklower 10441587Ssklower /* Clear Transmit queue. */ 10541587Ssklower while ((m = hd_remove (&hdp->hd_txq)) != NULL) 10641587Ssklower m_freem (m); 10741587Ssklower 10841587Ssklower /* Clear Retransmit queue. */ 10941587Ssklower i = hdp->hd_lastrxnr; 11041587Ssklower while (i != hdp->hd_retxqi) { 11141587Ssklower m_freem (hdp->hd_retxq[i]); 11241587Ssklower i = (i + 1) % MODULUS; 11341587Ssklower } 11441587Ssklower hdp->hd_retxqi = 0; 11541587Ssklower 11641587Ssklower hdp->hd_vs = hdp->hd_vr = 0; 11741587Ssklower hdp->hd_lasttxnr = hdp->hd_lastrxnr = 0; 11841587Ssklower hdp->hd_rrtimer = 0; 11941587Ssklower KILL_TIMER(hdp); 12041587Ssklower hdp->hd_retxcnt = 0; 12141587Ssklower hdp->hd_condition = 0; 12241587Ssklower } 12341587Ssklower 12441587Ssklower hd_decode (hdp, frame) 12541587Ssklower register struct hdcb *hdp; 12641587Ssklower struct Hdlc_frame *frame; 12741587Ssklower { 12841587Ssklower register int frametype = ILLEGAL; 12941587Ssklower register struct Hdlc_iframe *iframe = (struct Hdlc_iframe *) frame; 13041587Ssklower register struct Hdlc_sframe *sframe = (struct Hdlc_sframe *) frame; 13141587Ssklower register struct Hdlc_uframe *uframe = (struct Hdlc_uframe *) frame; 13241587Ssklower 13341587Ssklower if (iframe -> hdlc_0 == 0) { 13441587Ssklower frametype = IFRAME; 13541587Ssklower hdp->hd_iframes_in++; 13641587Ssklower } 13741587Ssklower 13841587Ssklower else if (sframe -> hdlc_01 == 1) { 13941587Ssklower /* Supervisory format. */ 14041587Ssklower switch (sframe -> s2) { 14141587Ssklower case 0: 14241587Ssklower frametype = RR; 14341587Ssklower hdp->hd_rrs_in++; 14441587Ssklower break; 14541587Ssklower 14641587Ssklower case 1: 14741587Ssklower frametype = RNR; 14841587Ssklower hdp->hd_rnrs_in++; 14941587Ssklower break; 15041587Ssklower 15141587Ssklower case 2: 15241587Ssklower frametype = REJ; 15341587Ssklower hdp->hd_rejs_in++; 15441587Ssklower } 15541587Ssklower } 15641587Ssklower else if (uframe -> hdlc_11 == 3) { 15741587Ssklower /* Unnumbered format. */ 15841587Ssklower switch (uframe -> m3) { 15941587Ssklower case 0: 16041587Ssklower frametype = DM; 16141587Ssklower break; 16241587Ssklower 16341587Ssklower case 1: 16441587Ssklower frametype = SABM; 16541587Ssklower break; 16641587Ssklower 16741587Ssklower case 2: 16841587Ssklower frametype = DISC; 16941587Ssklower break; 17041587Ssklower 17141587Ssklower case 3: 17241587Ssklower frametype = UA; 17341587Ssklower break; 17441587Ssklower 17541587Ssklower case 4: 17641587Ssklower frametype = FRMR; 17741587Ssklower hdp->hd_frmrs_in++; 17841587Ssklower } 17941587Ssklower } 18041587Ssklower return (frametype); 18141587Ssklower } 18241587Ssklower 18341587Ssklower /* 18441587Ssklower * This routine is called when the HDLC layer internally generates a 18541587Ssklower * command or response for the remote machine ( eg. RR, UA etc. ). 18641587Ssklower * Only supervisory or unnumbered frames are processed. 18741587Ssklower */ 18841587Ssklower 18941587Ssklower hd_writeinternal (hdp, frametype, pf) 19041587Ssklower register struct hdcb *hdp; 19141587Ssklower register int frametype, pf; 19241587Ssklower { 19341587Ssklower register struct mbuf *buf; 19441587Ssklower struct Hdlc_frame *frame; 19541587Ssklower register struct Hdlc_sframe *sframe; 19641587Ssklower register struct Hdlc_uframe *uframe; 19741587Ssklower 19841587Ssklower MGET (buf, M_DONTWAIT, MT_HEADER); 19941587Ssklower if (buf == 0) 20041587Ssklower return; 20141587Ssklower frame = mtod (buf, struct Hdlc_frame *); 20241587Ssklower sframe = mtod (buf, struct Hdlc_sframe *); 20341587Ssklower uframe = mtod (buf, struct Hdlc_uframe *); 20441587Ssklower 20541587Ssklower /* Assume a response - address structure for DTE */ 20641587Ssklower frame -> address = ADDRESS_A; 20741587Ssklower buf -> m_len = 2; 20841587Ssklower buf -> m_act = buf -> m_next = NULL; 20941587Ssklower 21041587Ssklower switch (frametype) { 21141587Ssklower case RR: 21241587Ssklower frame -> control = RR_CONTROL; 21341587Ssklower hdp->hd_rrs_out++; 21441587Ssklower break; 21541587Ssklower 21641587Ssklower case RNR: 21741587Ssklower frame -> control = RNR_CONTROL; 21841587Ssklower hdp->hd_rnrs_out++; 21941587Ssklower break; 22041587Ssklower 22141587Ssklower case REJ: 22241587Ssklower frame -> control = REJ_CONTROL; 22341587Ssklower hdp->hd_rejs_out++; 22441587Ssklower break; 22541587Ssklower 22641587Ssklower case SABM: 22741587Ssklower frame -> control = SABM_CONTROL; 22841587Ssklower frame -> address = ADDRESS_B; 22941587Ssklower break; 23041587Ssklower 23141587Ssklower case DISC: 23241587Ssklower frame -> control = DISC_CONTROL; 23341587Ssklower frame -> address = ADDRESS_B; 23441587Ssklower break; 23541587Ssklower 23641587Ssklower case DM: 23741587Ssklower frame -> control = DM_CONTROL; 23841587Ssklower break; 23941587Ssklower 24041587Ssklower case UA: 24141587Ssklower frame -> control = UA_CONTROL; 24241587Ssklower break; 24341587Ssklower 24441587Ssklower case FRMR: 24541587Ssklower frame -> control = FRMR_CONTROL; 24641587Ssklower bcopy ((caddr_t)&hd_frmr, (caddr_t)frame -> info, 3); 24741587Ssklower buf -> m_len = 5; 24841587Ssklower hdp->hd_frmrs_out++; 24941587Ssklower 25041587Ssklower } 25141587Ssklower 25241587Ssklower if (sframe -> hdlc_01 == 1) { 25341587Ssklower /* Supervisory format - RR, REJ, or RNR. */ 25441587Ssklower sframe -> nr = hdp->hd_vr; 25541587Ssklower sframe -> pf = pf; 25641587Ssklower hdp->hd_lasttxnr = hdp->hd_vr; 25741587Ssklower hdp->hd_rrtimer = 0; 25841587Ssklower } 25941587Ssklower else 26041587Ssklower uframe -> pf = pf; 26141587Ssklower 26241587Ssklower hd_trace (hdp, TX, frame); 26341587Ssklower (*hdp -> hd_ifp -> if_output) (hdp -> hd_ifp, buf, 26441587Ssklower (struct sockaddr *)hdp->hd_xcp); 26541587Ssklower 26641587Ssklower } 26741587Ssklower 26841587Ssklower struct mbuf * 26941587Ssklower hd_remove (q) 27041587Ssklower struct hdtxq *q; 27141587Ssklower { 27241587Ssklower register struct mbuf *m; 27341587Ssklower 27441587Ssklower m = q -> head; 27541587Ssklower if (m) { 27641587Ssklower if ((q -> head = m -> m_act) == NULL) 27741587Ssklower q -> tail = NULL; 27841587Ssklower m -> m_act = 0; 27941587Ssklower } 28041587Ssklower return (m); 28141587Ssklower } 28241587Ssklower 28341587Ssklower hd_append (q, m) 28441587Ssklower register struct hdtxq *q; 28541587Ssklower register struct mbuf *m; 28641587Ssklower { 28741587Ssklower 28841587Ssklower m -> m_act = NULL; 28941587Ssklower if (q -> tail == NULL) 29041587Ssklower q -> head = m; 29141587Ssklower else 29241587Ssklower q -> tail -> m_act = m; 29341587Ssklower q -> tail = m; 29441587Ssklower } 29541587Ssklower 29641587Ssklower hd_flush (ifp) 29741587Ssklower struct ifnet *ifp; 29841587Ssklower { 29941587Ssklower register struct mbuf *m; 30041587Ssklower register int s; 30141587Ssklower 30241587Ssklower while (1) { 30341587Ssklower s = spl6 (); /* XXX SHOULDN'T THIS BE splimp? */ 30441587Ssklower IF_DEQUEUE (&ifp->if_snd, m); 30541587Ssklower splx (s); 30641587Ssklower if (m == 0) 30741587Ssklower break; 30841587Ssklower m_freem (m); 30941587Ssklower } 31041587Ssklower } 31141587Ssklower 31241587Ssklower hd_message (hdp, msg) 31341587Ssklower struct hdcb *hdp; 31441587Ssklower char *msg; 31541587Ssklower { 31641587Ssklower char *format_ntn (); 31741587Ssklower 31841587Ssklower if (hdcbhead -> hd_next) 31941587Ssklower printf ("HDLC(%s): %s\n", format_ntn (hdp->hd_xcp), msg); 32041587Ssklower else 32141587Ssklower printf ("HDLC: %s\n", msg); 32241587Ssklower } 32341587Ssklower 32441587Ssklower #ifdef HDLCDEBUG 32541587Ssklower hd_status (hdp) 32641587Ssklower struct hdcb *hdp; 32741587Ssklower { 32841587Ssklower printf ("HDLC STATUS:\n V(S)=%d, V(R)=%d, retxqi=%d,\n", 32941587Ssklower hdp->hd_vs, hdp->hd_vr, hdp->hd_retxqi); 33041587Ssklower 33141587Ssklower printf ("Last_rx_nr=%d, Last_tx_nr=%d,\n Condition=%d, Xx=%d\n", 33241587Ssklower hdp->hd_lastrxnr, hdp->hd_lasttxnr, hdp->hd_condition, hdp->hd_xx); 33341587Ssklower } 33441587Ssklower #endif 335