BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / netiso / if_cons.c
index e04cd66..d9101d2 100644 (file)
@@ -1,3 +1,38 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)if_cons.c   7.10 (Berkeley) 5/29/91
+ */
+
 /***********************************************************
                Copyright IBM Corporation 1987
 
 /***********************************************************
                Copyright IBM Corporation 1987
 
@@ -31,10 +66,6 @@ SOFTWARE.
  * cons.c - Connection Oriented Network Service:
  * including support for a) user transport-level service, 
  *     b) COSNS below CLNP, and c) CONS below TP.
  * cons.c - Connection Oriented Network Service:
  * including support for a) user transport-level service, 
  *     b) COSNS below CLNP, and c) CONS below TP.
-
-#ifndef lint
-static char *rcsid = "$Header: if_cons.c,v 4.7 88/08/11 15:52:55 nhall Exp $";
-#endif lint
  */
 
 #ifdef TPCONS
  */
 
 #ifdef TPCONS
@@ -284,28 +315,26 @@ cons_init()
        pk_protolisten(0x81, 0, clnp_incoming);
        pk_protolisten(0x82, 0, esis_incoming);
        pk_protolisten(0x84, 0, tp8878_A_incoming);
        pk_protolisten(0x81, 0, clnp_incoming);
        pk_protolisten(0x82, 0, esis_incoming);
        pk_protolisten(0x84, 0, tp8878_A_incoming);
-#endif
        pk_protolisten(0, 0, tp_incoming);
        pk_protolisten(0, 0, tp_incoming);
+#endif
 }
 
 }
 
-tp_incoming(lcp, m0)
+tp_incoming(lcp, m)
 struct pklcd *lcp;
 struct pklcd *lcp;
-struct mbuf *m0;
+register struct mbuf *m;
 {
 {
-       register struct mbuf *m = m0->m_next; /* m0 has calling sockaddr_x25 */
        register struct isopcb *isop;
        extern struct isopcb tp_isopcb;
        int cons_tpinput();
 
        if (iso_pcballoc((struct socket *)0, &tp_incoming_pending)) {
        register struct isopcb *isop;
        extern struct isopcb tp_isopcb;
        int cons_tpinput();
 
        if (iso_pcballoc((struct socket *)0, &tp_incoming_pending)) {
-               m_freem(m);
-               pk_clear(lcp);
+               pk_close(lcp);
                return;
        }
        isop = tp_incoming_pending.isop_next;
                return;
        }
        isop = tp_incoming_pending.isop_next;
-       pk_output(lcp); /* Confirms call */
        lcp->lcd_upper = cons_tpinput;
        lcp->lcd_upnext = (caddr_t)isop;
        lcp->lcd_upper = cons_tpinput;
        lcp->lcd_upnext = (caddr_t)isop;
+       lcp->lcd_send(lcp); /* Confirms call */
        isop->isop_chan = (caddr_t)lcp;
        isop->isop_laddr = &isop->isop_sladdr;
        isop->isop_faddr = &isop->isop_sfaddr;
        isop->isop_chan = (caddr_t)lcp;
        isop->isop_laddr = &isop->isop_sladdr;
        isop->isop_faddr = &isop->isop_sfaddr;
@@ -313,7 +342,6 @@ struct mbuf *m0;
        DTEtoNSAP(isop->isop_faddr, &lcp->lcd_faddr);
        parse_facil(isop, lcp, &(mtod(m, struct x25_packet *)->packet_data),
                m->m_pkthdr.len - PKHEADERLN);
        DTEtoNSAP(isop->isop_faddr, &lcp->lcd_faddr);
        parse_facil(isop, lcp, &(mtod(m, struct x25_packet *)->packet_data),
                m->m_pkthdr.len - PKHEADERLN);
-       m_freem(m);
 }
 
 cons_tpinput(lcp, m0)
 }
 
 cons_tpinput(lcp, m0)
@@ -324,22 +352,40 @@ struct pklcd *lcp;
        register struct x25_packet *xp;
        int cmd;
 
        register struct x25_packet *xp;
        int cmd;
 
+       if (isop == 0)
+               return;
+       if (m0 == 0) {
+               isop->isop_chan = 0;
+               isop->isop_refcnt = 0;
+               lcp->lcd_upnext = 0;
+               lcp->lcd_upper = 0;
+               goto dead;
+       }
        switch(m0->m_type) {
        case MT_DATA:
        case MT_OOBDATA:
                tpcons_input(m0, isop->isop_faddr, isop->isop_laddr,
                        (struct socket *)0, (caddr_t)lcp);
        switch(m0->m_type) {
        case MT_DATA:
        case MT_OOBDATA:
                tpcons_input(m0, isop->isop_faddr, isop->isop_laddr,
                        (struct socket *)0, (caddr_t)lcp);
+               return;
 
        case MT_CONTROL:
                switch (pk_decode(mtod(m0, struct x25_packet *))) {
 
        case MT_CONTROL:
                switch (pk_decode(mtod(m0, struct x25_packet *))) {
-               default:
-                       return;
 
                case RR:
                        cmd = PRC_CONS_SEND_DONE;
                        break;
 
 
                case RR:
                        cmd = PRC_CONS_SEND_DONE;
                        break;
 
+               case CALL_ACCEPTED:
+                       if (lcp->lcd_sb.sb_mb)
+                               lcp->lcd_send(lcp); /* XXX - fix this */
+                       /*FALLTHROUGH*/
+               default:
+                       return;
+
+               dead:
                case RESET:
                case RESET:
+               case CLEAR:
+               case CLEAR_CONF:
                        cmd = PRC_ROUTEDEAD;
                }
                tpcons_ctlinput(cmd, isop->isop_faddr, isop);
                        cmd = PRC_ROUTEDEAD;
                }
                tpcons_ctlinput(cmd, isop->isop_faddr, isop);
@@ -362,6 +408,7 @@ cons_connect(isop)
        register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
        register struct mbuf    *m;
        struct ifaddr                   *ifa;
        register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
        register struct mbuf    *m;
        struct ifaddr                   *ifa;
+       int error;
 
        IFDEBUG(D_CCONN)
                printf("cons_connect(0x%x): ", isop);
 
        IFDEBUG(D_CCONN)
                printf("cons_connect(0x%x): ", isop);
@@ -371,14 +418,17 @@ cons_connect(isop)
                printf("\n" );
        ENDDEBUG
        NSAPtoDTE(isop->isop_faddr, &lcp->lcd_faddr);
                printf("\n" );
        ENDDEBUG
        NSAPtoDTE(isop->isop_faddr, &lcp->lcd_faddr);
+       lcp->lcd_upper = cons_tpinput;
+       lcp->lcd_upnext = (caddr_t)isop;
        IFDEBUG(D_CCONN)
                printf(
                "calling make_partial_x25_packet( 0x%x, 0x%x, 0x%x)\n",
                        &lcp->lcd_faddr, &lcp->lcd_laddr, 
                        isop->isop_socket->so_proto->pr_protocol); 
        ENDDEBUG
        IFDEBUG(D_CCONN)
                printf(
                "calling make_partial_x25_packet( 0x%x, 0x%x, 0x%x)\n",
                        &lcp->lcd_faddr, &lcp->lcd_laddr, 
                        isop->isop_socket->so_proto->pr_protocol); 
        ENDDEBUG
-       return (make_partial_x25_packet(isop, lcp, m) ||
-                pk_connect(lcp, &lcp->lcd_faddr));
+       if ((error = make_partial_x25_packet(isop, lcp, m)) == 0)
+               error = pk_connect(lcp, &lcp->lcd_faddr);
+       return error;
 }
 
 /*
 }
 
 /*
@@ -519,7 +569,7 @@ make_partial_x25_packet(isop, lcp)
        u_int                           proto;
        int                                     flag;
        caddr_t                         buf;
        u_int                           proto;
        int                                     flag;
        caddr_t                         buf;
-       register caddr_t        ptr     = buf;
+       register caddr_t        ptr;
        register int            len     = 0;
        int                             buflen  =0;
        caddr_t                         facil_len;
        register int            len     = 0;
        int                             buflen  =0;
        caddr_t                         facil_len;
@@ -527,32 +577,52 @@ make_partial_x25_packet(isop, lcp)
        struct mbuf *m;
 
 
        struct mbuf *m;
 
 
-       MGET(m, MT_DATA, M_WAITOK);
-       if (m == 0)
-               return ENOBUFS;
-       buf = mtod(m, caddr_t);
        IFDEBUG(D_CCONN)
                printf("make_partial_x25_packet(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
                        isop->isop_laddr, isop->isop_faddr, proto, m, flag);
        ENDDEBUG
        IFDEBUG(D_CCONN)
                printf("make_partial_x25_packet(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
                        isop->isop_laddr, isop->isop_faddr, proto, m, flag);
        ENDDEBUG
+       if (cons_use_udata) {
+               if (isop->isop_x25crud_len > 0) {
+                       /*
+                        *      The user specified something. Stick it in
+                        */
+                       bcopy(isop->isop_x25crud, lcp->lcd_faddr.x25_udata,
+                                       isop->isop_x25crud_len);
+                       lcp->lcd_faddr.x25_udlen = isop->isop_x25crud_len;
+               }
+       }
+
+       if (cons_use_facils == 0) {
+               lcp->lcd_facilities = 0;
+               return 0;
+       }
+       MGETHDR(m, MT_DATA, M_WAITOK);
+       if (m == 0)
+               return ENOBUFS;
+       buf = mtod(m, caddr_t);
+       ptr = buf;
        
        /* ptr now points to facil length (len of whole facil field in OCTETS */
        facil_len = ptr ++;
        
        /* ptr now points to facil length (len of whole facil field in OCTETS */
        facil_len = ptr ++;
+       m->m_len = 0;
+       pk_build_facilities(m, &lcp->lcd_faddr, 0);
 
        IFDEBUG(D_CADDR)
                printf("make_partial  calling: ptr 0x%x, len 0x%x\n", ptr, 
                                isop->isop_laddr->siso_addr.isoa_len);
        ENDDEBUG
        if (cons_use_facils) {
 
        IFDEBUG(D_CADDR)
                printf("make_partial  calling: ptr 0x%x, len 0x%x\n", ptr, 
                                isop->isop_laddr->siso_addr.isoa_len);
        ENDDEBUG
        if (cons_use_facils) {
+               *ptr++ = 0;      /* Marker to separate X.25 facitilies from CCITT ones */
+               *ptr++ = 0x0f;
                *ptr = 0xcb; /* calling facility code */
                ptr ++;
                ptr ++; /* leave room for facil param len (in OCTETS + 1) */
                ptr ++; /* leave room for the facil param len (in nibbles),
                *ptr = 0xcb; /* calling facility code */
                ptr ++;
                ptr ++; /* leave room for facil param len (in OCTETS + 1) */
                ptr ++; /* leave room for the facil param len (in nibbles),
-                               * high two bits of which indicate full/partial NSAP
-                               */
+                                * high two bits of which indicate full/partial NSAP
+                                */
                len = isop->isop_laddr->siso_addr.isoa_len;
                bcopy( isop->isop_laddr->siso_data, ptr, len);
                len = isop->isop_laddr->siso_addr.isoa_len;
                bcopy( isop->isop_laddr->siso_data, ptr, len);
-               *(ptr-2) = len+2; /* facil param len in octets */
+               *(ptr-2) = len+1; /* facil param len in octets */
                *(ptr-1) = len<<1; /* facil param len in nibbles */
                ptr += len;
 
                *(ptr-1) = len<<1; /* facil param len in nibbles */
                ptr += len;
 
@@ -564,11 +634,11 @@ make_partial_x25_packet(isop, lcp)
                ptr ++;
                ptr ++; /* leave room for facil param len (in OCTETS + 1) */
                ptr ++; /* leave room for the facil param len (in nibbles),
                ptr ++;
                ptr ++; /* leave room for facil param len (in OCTETS + 1) */
                ptr ++; /* leave room for the facil param len (in nibbles),
-                               * high two bits of which indicate full/partial NSAP
-                               */
+                                * high two bits of which indicate full/partial NSAP
+                                */
                len = isop->isop_faddr->siso_nlen;
                bcopy(isop->isop_faddr->siso_data, ptr, len);
                len = isop->isop_faddr->siso_nlen;
                bcopy(isop->isop_faddr->siso_data, ptr, len);
-               *(ptr-2) = len+2; /* facil param len = addr len + 1 for each of these
+               *(ptr-2) = len+1; /* facil param len = addr len + 1 for each of these
                                                  * two length fields, in octets */
                *(ptr-1) = len<<1; /* facil param len in nibbles */
                ptr += len;
                                                  * two length fields, in octets */
                *(ptr-1) = len<<1; /* facil param len in nibbles */
                ptr += len;
@@ -578,17 +648,6 @@ make_partial_x25_packet(isop, lcp)
        if (*facil_len > MAX_FACILITIES)
                return E_CO_PNA_LONG;
 
        if (*facil_len > MAX_FACILITIES)
                return E_CO_PNA_LONG;
 
-       if (cons_use_udata) {
-               if (isop->isop_x25crud_len > 0) {
-                       /*
-                        *      The user specified something. Stick it in
-                        */
-                       bcopy(isop->isop_x25crud, lcp->lcd_faddr.x25_udata,
-                                       isop->isop_x25crud_len);
-                       lcp->lcd_faddr.x25_udlen = isop->isop_x25crud_len;
-               }
-       }
-
        buflen = (int)(ptr - buf);
 
        IFDEBUG(D_CDUMP_REQ)
        buflen = (int)(ptr - buf);
 
        IFDEBUG(D_CDUMP_REQ)
@@ -612,7 +671,7 @@ make_partial_x25_packet(isop, lcp)
        if (buflen > MHLEN)
                return E_CO_PNA_LONG;
 
        if (buflen > MHLEN)
                return E_CO_PNA_LONG;
 
-       m->m_len = buflen;
+       m->m_pkthdr.len = m->m_len = buflen;
        lcp->lcd_facilities = m;
        return  0;
 }
        lcp->lcd_facilities = m;
        return  0;
 }
@@ -657,13 +716,14 @@ NSAPtoDTE(siso, sx25)
                register char *out = sx25->x25_addr;
                register char *in = siso->siso_data + 1;
                register int nibble;
                register char *out = sx25->x25_addr;
                register char *in = siso->siso_data + 1;
                register int nibble;
-               char *lim = in + 15;
+               char *lim = siso->siso_data + siso->siso_nlen;
+               char *olim = out+15;
                int lowNibble = 0;
 
                while (in < lim) {
                        nibble = ((lowNibble ? *in++ : (*in >> 4)) & 0xf) | 0x30;
                        lowNibble ^= 1;
                int lowNibble = 0;
 
                while (in < lim) {
                        nibble = ((lowNibble ? *in++ : (*in >> 4)) & 0xf) | 0x30;
                        lowNibble ^= 1;
-                       if (nibble != 0x3f)
+                       if (nibble != 0x3f && out < olim)
                                *out++ = nibble;
                }
                dtelen = out - sx25->x25_addr;
                                *out++ = nibble;
                }
                dtelen = out - sx25->x25_addr;