141705Ssklower /* 241705Ssklower * Copyright (c) University of British Columbia, 1984 341705Ssklower * Copyright (c) 1990 The Regents of the University of California. 441705Ssklower * All rights reserved. 541705Ssklower * 641705Ssklower * This code is derived from software contributed to Berkeley by 741705Ssklower * the Laboratory for Computation Vision and the Computer Science Department 841705Ssklower * of the University of British Columbia. 941705Ssklower * 1041705Ssklower * %sccs.include.redist.c% 1141705Ssklower * 12*57020Ssklower * @(#)hd_subr.c 7.8 (Berkeley) 12/08/92 1341705Ssklower */ 1441587Ssklower 1556530Sbostic #include <sys/param.h> 1656530Sbostic #include <sys/systm.h> 1756530Sbostic #include <sys/mbuf.h> 1856530Sbostic #include <sys/domain.h> 1956530Sbostic #include <sys/socket.h> 2056530Sbostic #include <sys/protosw.h> 2156530Sbostic #include <sys/errno.h> 2256530Sbostic #include <sys/time.h> 2356530Sbostic #include <sys/kernel.h> 2441587Ssklower 2556530Sbostic #include <net/if.h> 2641587Ssklower 2756530Sbostic #include <netccitt/hdlc.h> 2856530Sbostic #include <netccitt/hd_var.h> 2956530Sbostic #include <netccitt/x25.h> 3041587Ssklower 3141587Ssklower hd_init () 3241587Ssklower { 3341587Ssklower 3441587Ssklower hdintrq.ifq_maxlen = IFQ_MAXLEN; 3541587Ssklower } 3641587Ssklower 3741587Ssklower hd_ctlinput (prc, addr) 3845296Ssklower struct sockaddr *addr; 3941587Ssklower { 4041587Ssklower register struct x25config *xcp = (struct x25config *)addr; 4141587Ssklower register struct hdcb *hdp; 4241587Ssklower register struct ifaddr *ifa; 4345296Ssklower struct ifnet *ifp; 4449927Ssklower caddr_t pk_newlink(); 4541587Ssklower 4645296Ssklower if (addr->sa_family != AF_CCITT) 4741587Ssklower return (EAFNOSUPPORT); 4841587Ssklower if (xcp->xc_lptype != HDLCPROTO_LAPB) 4941587Ssklower return (EPROTONOSUPPORT); 5045296Ssklower ifa = ifa_ifwithaddr(addr); 5145296Ssklower if (ifa == 0 || ifa->ifa_addr->sa_family != AF_CCITT || 5245296Ssklower (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 */ 5945296Ssklower int error, hd_ifoutput(), hd_output(); 6041587Ssklower 6145296Ssklower /* an hdcb is now too big to fit in an mbuf */ 6245296Ssklower MALLOC(hdp, struct hdcb *, sizeof (*hdp), M_PCB, M_DONTWAIT); 6345296Ssklower if (hdp == 0) 6441587Ssklower return (ENOBUFS); 6545296Ssklower bzero((caddr_t)hdp, sizeof(*hdp)); 6649927Ssklower hdp->hd_pkp = 67*57020Ssklower (caddr_t) pk_newlink ((struct x25_ifaddr *) ifa, 68*57020Ssklower (caddr_t) hdp); 69*57020Ssklower ((struct x25_ifaddr *)ifa)->ia_pkcb = 70*57020Ssklower (struct pkcb *) hdp->hd_pkp; 7149927Ssklower if (hdp -> hd_pkp == 0) { 7249927Ssklower free(hdp, M_PCB); 7349927Ssklower return (ENOBUFS); 7441587Ssklower } 7541587Ssklower hdp->hd_ifp = ifp; 7645296Ssklower hdp->hd_ifa = ifa; 7741587Ssklower hdp->hd_xcp = xcp; 7841587Ssklower hdp->hd_state = INIT; 7945296Ssklower hdp->hd_output = hd_ifoutput; 8049927Ssklower hdp->hd_next = hdcbhead; 8149927Ssklower hdcbhead = hdp; 82*57020Ssklower } else if (hdp->hd_pkp == 0) { /* interface got reconfigured */ 83*57020Ssklower hdp->hd_pkp = 84*57020Ssklower (caddr_t) pk_newlink ((struct x25_ifaddr *) ifa, 85*57020Ssklower (caddr_t) hdp); 86*57020Ssklower ((struct x25_ifaddr *)ifa)->ia_pkcb = 87*57020Ssklower (struct pkcb *) hdp->hd_pkp; 88*57020Ssklower if (hdp -> hd_pkp == 0) { 89*57020Ssklower free(hdp, M_PCB); 90*57020Ssklower return (ENOBUFS); 91*57020Ssklower } 9241587Ssklower } 9341587Ssklower 9441587Ssklower switch (prc) { 9541587Ssklower case PRC_IFUP: 9641587Ssklower if (xcp->xc_lwsize == 0 || 9741587Ssklower xcp->xc_lwsize > MAX_WINDOW_SIZE) 9841587Ssklower xcp->xc_lwsize = MAX_WINDOW_SIZE; 9941587Ssklower if (hdp->hd_state == INIT) 10041587Ssklower SET_TIMER (hdp); 10141587Ssklower break; 10241587Ssklower 10341587Ssklower case PRC_IFDOWN: 10441587Ssklower if (hdp->hd_state == ABM) 10541587Ssklower hd_message (hdp, "Operator shutdown: link closed"); 10649927Ssklower (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp); 107*57020Ssklower 108*57020Ssklower /* fall thru to ... */ 109*57020Ssklower 110*57020Ssklower case PRC_DISCONNECT_REQUEST: 111*57020Ssklower /* drop reference to pkcb --- it's dead meat */ 112*57020Ssklower hdp->hd_pkp = (caddr_t) 0; 113*57020Ssklower ((struct x25_ifaddr *)ifa)->ia_pkcb = (struct pkcb *) 0; 114*57020Ssklower 11541587Ssklower hd_writeinternal (hdp, DISC, POLLON); 11641587Ssklower hdp->hd_state = DISC_SENT; 11741587Ssklower SET_TIMER (hdp); 11841587Ssklower } 11941587Ssklower return (0); 12041587Ssklower } 12141587Ssklower 12241587Ssklower hd_initvars (hdp) 12341587Ssklower register struct hdcb *hdp; 12441587Ssklower { 12541587Ssklower register struct mbuf *m; 12641587Ssklower register int i; 12741587Ssklower 12841587Ssklower /* Clear Transmit queue. */ 12941587Ssklower while ((m = hd_remove (&hdp->hd_txq)) != NULL) 13041587Ssklower m_freem (m); 13141587Ssklower 13241587Ssklower /* Clear Retransmit queue. */ 13341587Ssklower i = hdp->hd_lastrxnr; 13441587Ssklower while (i != hdp->hd_retxqi) { 13541587Ssklower m_freem (hdp->hd_retxq[i]); 13641587Ssklower i = (i + 1) % MODULUS; 13741587Ssklower } 13841587Ssklower hdp->hd_retxqi = 0; 13941587Ssklower 14041587Ssklower hdp->hd_vs = hdp->hd_vr = 0; 14141587Ssklower hdp->hd_lasttxnr = hdp->hd_lastrxnr = 0; 14241587Ssklower hdp->hd_rrtimer = 0; 14341587Ssklower KILL_TIMER(hdp); 14441587Ssklower hdp->hd_retxcnt = 0; 14541587Ssklower hdp->hd_condition = 0; 14641587Ssklower } 14741587Ssklower 14841587Ssklower hd_decode (hdp, frame) 14941587Ssklower register struct hdcb *hdp; 15041587Ssklower struct Hdlc_frame *frame; 15141587Ssklower { 15241587Ssklower register int frametype = ILLEGAL; 15341587Ssklower register struct Hdlc_iframe *iframe = (struct Hdlc_iframe *) frame; 15441587Ssklower register struct Hdlc_sframe *sframe = (struct Hdlc_sframe *) frame; 15541587Ssklower register struct Hdlc_uframe *uframe = (struct Hdlc_uframe *) frame; 15641587Ssklower 15741587Ssklower if (iframe -> hdlc_0 == 0) { 15841587Ssklower frametype = IFRAME; 15941587Ssklower hdp->hd_iframes_in++; 16041587Ssklower } 16141587Ssklower 16241587Ssklower else if (sframe -> hdlc_01 == 1) { 16341587Ssklower /* Supervisory format. */ 16441587Ssklower switch (sframe -> s2) { 16541587Ssklower case 0: 16641587Ssklower frametype = RR; 16741587Ssklower hdp->hd_rrs_in++; 16841587Ssklower break; 16941587Ssklower 17041587Ssklower case 1: 17141587Ssklower frametype = RNR; 17241587Ssklower hdp->hd_rnrs_in++; 17341587Ssklower break; 17441587Ssklower 17541587Ssklower case 2: 17641587Ssklower frametype = REJ; 17741587Ssklower hdp->hd_rejs_in++; 17841587Ssklower } 17941587Ssklower } 18041587Ssklower else if (uframe -> hdlc_11 == 3) { 18141587Ssklower /* Unnumbered format. */ 18241587Ssklower switch (uframe -> m3) { 18341587Ssklower case 0: 18441587Ssklower frametype = DM; 18541587Ssklower break; 18641587Ssklower 18741587Ssklower case 1: 18841587Ssklower frametype = SABM; 18941587Ssklower break; 19041587Ssklower 19141587Ssklower case 2: 19241587Ssklower frametype = DISC; 19341587Ssklower break; 19441587Ssklower 19541587Ssklower case 3: 19641587Ssklower frametype = UA; 19741587Ssklower break; 19841587Ssklower 19941587Ssklower case 4: 20041587Ssklower frametype = FRMR; 20141587Ssklower hdp->hd_frmrs_in++; 20241587Ssklower } 20341587Ssklower } 20441587Ssklower return (frametype); 20541587Ssklower } 20641587Ssklower 20741587Ssklower /* 20841587Ssklower * This routine is called when the HDLC layer internally generates a 20941587Ssklower * command or response for the remote machine ( eg. RR, UA etc. ). 21041587Ssklower * Only supervisory or unnumbered frames are processed. 21141587Ssklower */ 21241587Ssklower 21341587Ssklower hd_writeinternal (hdp, frametype, pf) 21441587Ssklower register struct hdcb *hdp; 21541587Ssklower register int frametype, pf; 21641587Ssklower { 21741587Ssklower register struct mbuf *buf; 21841587Ssklower struct Hdlc_frame *frame; 21941587Ssklower register struct Hdlc_sframe *sframe; 22041587Ssklower register struct Hdlc_uframe *uframe; 22141587Ssklower 22245296Ssklower MGETHDR (buf, M_DONTWAIT, MT_HEADER); 22341587Ssklower if (buf == 0) 22441587Ssklower return; 22541587Ssklower frame = mtod (buf, struct Hdlc_frame *); 22641587Ssklower sframe = mtod (buf, struct Hdlc_sframe *); 22741587Ssklower uframe = mtod (buf, struct Hdlc_uframe *); 22841587Ssklower 22941587Ssklower /* Assume a response - address structure for DTE */ 23041587Ssklower frame -> address = ADDRESS_A; 23141587Ssklower buf -> m_len = 2; 23241587Ssklower buf -> m_act = buf -> m_next = NULL; 23341587Ssklower 23441587Ssklower switch (frametype) { 23541587Ssklower case RR: 23641587Ssklower frame -> control = RR_CONTROL; 23741587Ssklower hdp->hd_rrs_out++; 23841587Ssklower break; 23941587Ssklower 24041587Ssklower case RNR: 24141587Ssklower frame -> control = RNR_CONTROL; 24241587Ssklower hdp->hd_rnrs_out++; 24341587Ssklower break; 24441587Ssklower 24541587Ssklower case REJ: 24641587Ssklower frame -> control = REJ_CONTROL; 24741587Ssklower hdp->hd_rejs_out++; 24841587Ssklower break; 24941587Ssklower 25041587Ssklower case SABM: 25141587Ssklower frame -> control = SABM_CONTROL; 25241587Ssklower frame -> address = ADDRESS_B; 25341587Ssklower break; 25441587Ssklower 25541587Ssklower case DISC: 25645296Ssklower if ((hdp->hd_ifp->if_flags & IFF_UP) == 0) { 25745296Ssklower hdp->hd_state = DISCONNECTED; 25845296Ssklower (void) m_freem (buf); 25945296Ssklower hd_flush (hdp->hd_ifp); 26045296Ssklower return; 26145296Ssklower } 26241587Ssklower frame -> control = DISC_CONTROL; 26341587Ssklower frame -> address = ADDRESS_B; 26441587Ssklower break; 26541587Ssklower 26641587Ssklower case DM: 26741587Ssklower frame -> control = DM_CONTROL; 26841587Ssklower break; 26941587Ssklower 27041587Ssklower case UA: 27141587Ssklower frame -> control = UA_CONTROL; 27241587Ssklower break; 27341587Ssklower 27441587Ssklower case FRMR: 27541587Ssklower frame -> control = FRMR_CONTROL; 27641587Ssklower bcopy ((caddr_t)&hd_frmr, (caddr_t)frame -> info, 3); 27741587Ssklower buf -> m_len = 5; 27841587Ssklower hdp->hd_frmrs_out++; 27941587Ssklower 28041587Ssklower } 28141587Ssklower 28241587Ssklower if (sframe -> hdlc_01 == 1) { 28341587Ssklower /* Supervisory format - RR, REJ, or RNR. */ 28441587Ssklower sframe -> nr = hdp->hd_vr; 28541587Ssklower sframe -> pf = pf; 28641587Ssklower hdp->hd_lasttxnr = hdp->hd_vr; 28741587Ssklower hdp->hd_rrtimer = 0; 28841587Ssklower } 28941587Ssklower else 29041587Ssklower uframe -> pf = pf; 29141587Ssklower 29241587Ssklower hd_trace (hdp, TX, frame); 29345296Ssklower buf -> m_pkthdr.len = buf -> m_len; 29445296Ssklower (*hdp->hd_output) (hdp, buf); 29541587Ssklower } 29641587Ssklower 29741587Ssklower struct mbuf * 29841587Ssklower hd_remove (q) 29941587Ssklower struct hdtxq *q; 30041587Ssklower { 30141587Ssklower register struct mbuf *m; 30241587Ssklower 30341587Ssklower m = q -> head; 30441587Ssklower if (m) { 30541587Ssklower if ((q -> head = m -> m_act) == NULL) 30641587Ssklower q -> tail = NULL; 30741587Ssklower m -> m_act = 0; 30841587Ssklower } 30941587Ssklower return (m); 31041587Ssklower } 31141587Ssklower 31241587Ssklower hd_append (q, m) 31341587Ssklower register struct hdtxq *q; 31441587Ssklower register struct mbuf *m; 31541587Ssklower { 31641587Ssklower 31741587Ssklower m -> m_act = NULL; 31841587Ssklower if (q -> tail == NULL) 31941587Ssklower q -> head = m; 32041587Ssklower else 32141587Ssklower q -> tail -> m_act = m; 32241587Ssklower q -> tail = m; 32341587Ssklower } 32441587Ssklower 32541587Ssklower hd_flush (ifp) 32641587Ssklower struct ifnet *ifp; 32741587Ssklower { 32841587Ssklower register struct mbuf *m; 32941587Ssklower register int s; 33041587Ssklower 33141587Ssklower while (1) { 33245296Ssklower s = splimp (); 33341587Ssklower IF_DEQUEUE (&ifp->if_snd, m); 33441587Ssklower splx (s); 33541587Ssklower if (m == 0) 33641587Ssklower break; 33741587Ssklower m_freem (m); 33841587Ssklower } 33941587Ssklower } 34041587Ssklower 34141587Ssklower hd_message (hdp, msg) 34241587Ssklower struct hdcb *hdp; 34341587Ssklower char *msg; 34441587Ssklower { 34541587Ssklower char *format_ntn (); 34641587Ssklower 34741587Ssklower if (hdcbhead -> hd_next) 34841587Ssklower printf ("HDLC(%s): %s\n", format_ntn (hdp->hd_xcp), msg); 34941587Ssklower else 35041587Ssklower printf ("HDLC: %s\n", msg); 35141587Ssklower } 35241587Ssklower 35341587Ssklower #ifdef HDLCDEBUG 35441587Ssklower hd_status (hdp) 35541587Ssklower struct hdcb *hdp; 35641587Ssklower { 35741587Ssklower printf ("HDLC STATUS:\n V(S)=%d, V(R)=%d, retxqi=%d,\n", 35841587Ssklower hdp->hd_vs, hdp->hd_vr, hdp->hd_retxqi); 35941587Ssklower 36041587Ssklower printf ("Last_rx_nr=%d, Last_tx_nr=%d,\n Condition=%d, Xx=%d\n", 36141587Ssklower hdp->hd_lastrxnr, hdp->hd_lasttxnr, hdp->hd_condition, hdp->hd_xx); 36241587Ssklower } 36341587Ssklower #endif 364