BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / netiso / if_cons.c
index f1163f2..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
 
@@ -33,10 +68,8 @@ SOFTWARE.
  *     b) COSNS below CLNP, and c) CONS below TP.
  */
 
  *     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 KERNEL
 #ifdef ARGO_DEBUG
 #define Static  
 unsigned LAST_CALL_PCB;
 #ifdef ARGO_DEBUG
 #define Static  
 unsigned LAST_CALL_PCB;
@@ -44,13 +77,9 @@ unsigned LAST_CALL_PCB;
 #define Static static
 #endif ARGO_DEBUG
 
 #define Static static
 #endif ARGO_DEBUG
 
-#include "ecn.h"
-#include "argoxtwentyfive.h"
-
-#if NARGOXTWENTYFIVE > 0
 
 
-#ifdef KERNEL
 
 
+#ifndef SOCK_STREAM
 #include "param.h"
 #include "systm.h"
 #include "mbuf.h"
 #include "param.h"
 #include "systm.h"
 #include "mbuf.h"
@@ -65,14 +94,17 @@ unsigned LAST_CALL_PCB;
 #include "../net/netisr.h"
 #include "../net/route.h"
 
 #include "../net/netisr.h"
 #include "../net/route.h"
 
-#include "../netiso/iso_errno.h"
-#include "../netiso/argo_debug.h"
-#include "../netiso/tp_trace.h"
-#include "../netiso/iso.h"
-#include "../netiso/cons.h"
-#include "../netiso/iso_pcb.h"
-#include "../netiso/cons_pcb.h"
-#include "../caif/eicon.h"
+#include "iso_errno.h"
+#include "argo_debug.h"
+#include "tp_trace.h"
+#include "iso.h"
+#include "cons.h"
+#include "iso_pcb.h"
+
+#include "../netccitt/x25.h"
+#include "../netccitt/pk.h"
+#include "../netccitt/pk_var.h"
+#endif
 
 #ifdef ARGO_DEBUG
 #define MT_XCONN       0x50
 
 #ifdef ARGO_DEBUG
 #define MT_XCONN       0x50
@@ -91,31 +123,19 @@ unsigned LAST_CALL_PCB;
 #define DONTCLEAR       -1
 
 /********************************************************************* 
 #define DONTCLEAR       -1
 
 /********************************************************************* 
- * cons.c - CONS interface to the eicon adapter
- * Includes connection manager - for (TP, CLNP)/x.25
+ * cons.c - CONS interface to the x.25 layer
  *
  * TODO: figure out what resources we might run out of besides mbufs.
  *  If we run out of any of them (including mbufs) close and recycle
  *  lru x% of the connections, for some parameter x.
  *
  *
  * TODO: figure out what resources we might run out of besides mbufs.
  *  If we run out of any of them (including mbufs) close and recycle
  *  lru x% of the connections, for some parameter x.
  *
- * There are 4 interfaces from above:
- * 0) from CLNP: 
- *    cons is an interface driver - CLNP calls
- *    cosns_output(ifp, m, dst), a device-type interface output routine
- *    that does some connection management stuff and queues a
- *    request on the eicon driver queue by calling ifp->if_output.
- *    The eicon's ifp structure contains cosns_output as its output routine
- *    rather than ifp_>if_output! Kludge, but we don't have much choice...
- *    X25 connections created in this manner may always be multiplexed
- *    but only with their own kind (not with connections servicing TP
- *    directly.)
- *             co_flags & CONSF_DGM 
+ * There are 2 interfaces from above:
  * 1) from TP0: 
  *    cons CO network service
  *    TP associates a transport connection with a network connection.
  *       cons_output( isop, m, len, isdgm==0 ) 
  *        co_flags == 0
  * 1) from TP0: 
  *    cons CO network service
  *    TP associates a transport connection with a network connection.
  *       cons_output( isop, m, len, isdgm==0 ) 
  *        co_flags == 0
- * 2) from TP 4:
+ * 2) from TP4:
  *       It's a datagram service, like clnp is. - even though it calls
  *                     cons_output( isop, m, len, isdgm==1 ) 
  *       it eventually goes through
  *       It's a datagram service, like clnp is. - even though it calls
  *                     cons_output( isop, m, len, isdgm==1 ) 
  *       it eventually goes through
@@ -123,51 +143,23 @@ unsigned LAST_CALL_PCB;
  *    TP4 permits multiplexing (reuse, possibly simultaneously) of the 
  *       network connections.
  *    This means that many sockets (many tpcbs) may be associated with
  *    TP4 permits multiplexing (reuse, possibly simultaneously) of the 
  *       network connections.
  *    This means that many sockets (many tpcbs) may be associated with
- *    this cons_pcb, hence cannot have a back ptr from cons_pcb to a tpcb.
+ *    this pklcd, hence cannot have a back ptr from pklcd to a tpcb.
  *        co_flags & CONSF_DGM 
  *        co_flags & CONSF_DGM 
- *    co_socket is null since there may be many sockets that use this copcb.
- * 3) from user: cons_usrreq(), cons_ctloutput() 
- *    cons is a standard transport service interface.
- *    There is a 1-1 correspondence between net connections and sockets.
- *       co_socket points to a socket.
+ *    co_socket is null since there may be many sockets that use this pklcd.
  *
 NOTE:
        streams would really be nice. sigh.
  *
 NOTE:
        streams would really be nice. sigh.
-NOTE:
-       eicon <--> cons interface: the first mbuf (the ecn_request structure)
-       had better NOT be a cluster.
 NOTE:
        PVCs could be handled by config-ing a cons with an address and with the
        IFF_POINTTOPOINT flag on.  This code would then have to skip the
        connection setup stuff for pt-to-pt links.  
 NOTE:
        PVCs could be handled by config-ing a cons with an address and with the
        IFF_POINTTOPOINT flag on.  This code would then have to skip the
        connection setup stuff for pt-to-pt links.  
-NOTE:
-       We keep track of the ifp for each connection.  Right now this is
-       unnecessary, but just in case someone comes up with some kind
-       of a kludge to allow > 1 eicon to be attached at a time,
-       (i.e., some meaningful netof( a type 37 address ) ),
-       we do keep track of this.
 
 
  *********************************************************************/
 
 
 
  *********************************************************************/
 
-#define touch(copcb) copcb->co_ttl = copcb->co_init_ttl
 
 #define CONS_IFQMAXLEN 5
 
 
 #define CONS_IFQMAXLEN 5
 
-#define SET_CHANMASK( isop, chan )\
-       if( (u_int)(chan) < 32 ) \
-               (isop)->isop_chanmask = (1<<((chan)-1));\
-       else \
-               (isop)->isop_negchanmask = (1<<((256-(chan))-1))
-
-#define ADD_CHANMASK( isop, chan )\
-       if( (u_int)(chan) < 32 ) \
-               (isop)->isop_chanmask |= (1<<((chan)-1));\
-       else \
-               (isop)->isop_negchanmask |= (1<<((256-(chan))-1))
-
-struct ifnet                   *consif; /* TO BE REMOVED */
-Static int                             consinit(), consioctl(), consattach();
 
 /* protosw pointers for getting to higher layer */
 Static         struct protosw  *CLNP_proto;
 
 /* protosw pointers for getting to higher layer */
 Static         struct protosw  *CLNP_proto;
@@ -184,12 +176,10 @@ extern    struct ifaddr   *ifa_ifwithaddr();
 Static  struct socket  dummysocket; /* for use by cosns */
 
 extern struct  isopcb  tp_isopcb; /* chain of all TP pcbs */
 Static  struct socket  dummysocket; /* for use by cosns */
 
 extern struct  isopcb  tp_isopcb; /* chain of all TP pcbs */
-struct isopcb                  cons_isopcb; /* chain of all cons pcbs */
 struct isopcb                  tp_incoming_pending;  /* incoming connections
                                                                                for TP, pending */
 
 struct isopcb  *Xpcblist[] =  {
 struct isopcb                  tp_incoming_pending;  /* incoming connections
                                                                                for TP, pending */
 
 struct isopcb  *Xpcblist[] =  {
-       &cons_isopcb, 
        &tp_incoming_pending,
        &tp_isopcb,
        (struct isopcb *)0
        &tp_incoming_pending,
        &tp_isopcb,
        (struct isopcb *)0
@@ -197,7 +187,7 @@ struct isopcb       *Xpcblist[] =  {
 
 Static         int parse_facil(), NSAPtoDTE(), make_partial_x25_packet();
 Static int FACILtoNSAP(), DTEtoNSAP();
 
 Static         int parse_facil(), NSAPtoDTE(), make_partial_x25_packet();
 Static int FACILtoNSAP(), DTEtoNSAP();
-Static struct cons_pcb *cons_chan_to_pcb();
+Static struct pklcd *cons_chan_to_pcb();
 
 #define HIGH_NIBBLE 1
 #define LOW_NIBBLE 0
 
 #define HIGH_NIBBLE 1
 #define LOW_NIBBLE 0
@@ -213,7 +203,7 @@ Static      struct cons_pcb *cons_chan_to_pcb();
  * RETURNS: VOID
  */
 void
  * RETURNS: VOID
  */
 void
-nibble_copy( src_octet, src_nibble, dst_octet, dst_nibble, len)
+nibble_copy(src_octet, src_nibble, dst_octet, dst_nibble, len)
        register char   *src_octet;
        register char   *dst_octet;
        register unsigned               src_nibble;
        register char   *src_octet;
        register char   *dst_octet;
        register unsigned               src_nibble;
@@ -283,7 +273,7 @@ nibble_match( src_octet, src_nibble, dst_octet, dst_nibble, len)
        for (i=0; i<len; i++) {
                nibble_b = ((*dst_octet)>>dshift) & 0xf;
                nibble_a = ( 0xf & (*src_octet >> sshift));
        for (i=0; i<len; i++) {
                nibble_b = ((*dst_octet)>>dshift) & 0xf;
                nibble_a = ( 0xf & (*src_octet >> sshift));
-               if( nibble_b != nibble_a )
+               if (nibble_b != nibble_a)
                        return 0;
 
                dshift          ^= SHIFT;
                        return 0;
 
                dshift          ^= SHIFT;
@@ -299,75 +289,9 @@ nibble_match( src_octet, src_nibble, dst_octet, dst_nibble, len)
        return 1;
 }
 
        return 1;
 }
 
-#ifdef ARGO_DEBUG
-
-Static
-dump_copcb(copcb, str)
-       char * str;
-       register struct cons_pcb *copcb;
-{
-       printf("XPCB DUMP %s\n", str);
-       if (copcb) {
-               printf("\t copcb 0x%x next 0x%x head 0x%x socket 0x%x ifp 0x%x\n",
-                       copcb, copcb->co_next, copcb->co_head, copcb->co_socket, copcb->co_ifp);
-               printf("\t channel 0x%x state 0x%x flags 0x%x proto 0x%x\n",
-                       copcb->co_channel, copcb->co_state, copcb->co_flags, copcb->co_proto);
-               printf("\t laddr :\n");
-               dump_isoaddr(&copcb->co_laddr);
-               printf("\t faddr :\n");
-               dump_isoaddr(&copcb->co_faddr);
-               printf("\tttl 0x%x init_ttl 0x%x pending: %d\n",
-                       copcb->co_ttl, copcb->co_init_ttl, copcb->co_pending.ifq_len);
-       }
-       printf("END DUMP\n");
-}
-#endif ARGO_DEBUG
-
-/*
- * FUNCTION : choose_output - chooses between the eicon and loopback.
- * This MUST be here because the ifp->if_output routine is cosns_output
- * -- due to our need to look like a device driver for CLNP. sigh.
- * ARGUMENTS & PURPOSE:  (copcb) ptr to a protocol control block for
- *                     x.25, (m) is an mbuf ptr. *m is a request destined either
- *                     for the eicon driver or for the loopback driver.
- * RETURNS : whatever error value the 2I or loopback returns.
- */
-Static int 
-choose_output( ifp, m, loop)
-       struct ifnet    *ifp;
-       struct mbuf     *m;
-       int                             loop;
-{
-       int error;
-
-       if( !m )
-               return 0;
-       ASSERT(m->m_len != 0);
-       if( loop != 0)
-               error = lpboutput( ifp, m );
-       else
-               error = ecnoutput( ifp,  m );
-
-       if (error == 0)
-               ifp->if_opackets ++;
-       else {
-               ifp->if_oerrors ++;
-               IFTRACE(D_CDATA)
-                       tptrace( TPPTmisc, 
-                       "choose_output: ifp  m error loop\n", 
-                               ifp, m, error, loop);
-               ENDTRACE
-       }
-       IFDEBUG(D_CCONS)
-               printf("choose_output returns 0x%x\n", error );
-       ENDDEBUG
-       return error;
-}
-
 /*
  **************************** NET PROTOCOL cons ***************************
  */
 /*
  **************************** NET PROTOCOL cons ***************************
  */
-
 /*
  * NAME:       cons_init()
  * CALLED FROM:
 /*
  * NAME:       cons_init()
  * CALLED FROM:
@@ -377,13 +301,8 @@ choose_output( ifp, m, loop)
  */
 cons_init()
 {
  */
 cons_init()
 {
-       init_lpb();
-       consattach(); 
+       int tp_incoming(), clnp_incoming();
 
 
-       /* protocol init stuff */
-
-       consintrq.ifq_maxlen = IFQ_MAXLEN;
-       consintrq.ifq_head = consintrq.ifq_tail =  (struct mbuf *)0;
 
        CLNP_proto = pffindproto(AF_ISO, ISOPROTO_CLNP, SOCK_DGRAM); 
        X25_proto = pffindproto(AF_ISO, ISOPROTO_X25, SOCK_STREAM);
 
        CLNP_proto = pffindproto(AF_ISO, ISOPROTO_CLNP, SOCK_DGRAM); 
        X25_proto = pffindproto(AF_ISO, ISOPROTO_X25, SOCK_STREAM);
@@ -392,3149 +311,343 @@ cons_init()
                printf("cons_init end : cnlp_proto 0x%x cons proto 0x%x tp proto 0x%x\n",
                        CLNP_proto, X25_proto, TP_proto);
        ENDDEBUG
                printf("cons_init end : cnlp_proto 0x%x cons proto 0x%x tp proto 0x%x\n",
                        CLNP_proto, X25_proto, TP_proto);
        ENDDEBUG
-
-       cons_isopcb.isop_next = cons_isopcb.isop_prev = &cons_isopcb;
-       tp_incoming_pending.isop_next = tp_incoming_pending.isop_prev =
-                       &tp_incoming_pending;
-}
-
 #ifdef notdef
 #ifdef notdef
-
-/*
- * NAME:       cons_free_lru()
- * some day CALLED FROM: 
- *     wherever we run out of mbufs (not used right yet)
- * FUNCTION:
- *     get rid of the num least recently used connections and
- *  recycle their mbufs.
- * NOTE: GROTESQUELY INEFFICIENT needs to be written nicely
- */
-
-Static
-cons_free_lru(qty)
-       int qty;
-{
-       register struct cons_pcb **copcblist = (struct cons_pcb **)Xpcblist;
-       register struct cons_pcb *copcb;
-       struct cons_pcb                         Lru; 
-       struct cons_pcb                         *lru; 
-
-       IFDEBUG(D_CCONS)
-               printf("cons_free_lru( 0x%x )\n", qty);
-       ENDDEBUG
-
-       Lru.co_ttl = X25_TTL;
-       lru = &Lru;
-
-       while (qty > 1) { /* GROT */
-               cons_free_lru( 1 );
-               qty -- ;
-       }
-
-       for( copcb = *copcblist; copcb; copcb = *(++copcblist) ) {
-               copcb = (struct cons_pcb *)copcb->co_next;
-               while (copcb !=  *copcblist) {
-                       if( copcb->co_ttl < lru->co_ttl ) 
-                               lru = copcb;
-                       copcb = (struct cons_pcb *)copcb->co_next;
-               }
-       }
-
-       if(lru->co_socket) {
-               soisdisconnected(lru->co_socket);
-               sohasoutofband(lru->co_socket); /* signal */
-       } 
-
-       cons_clear_and_detach( lru, E_CO_HLI_RESYNC, PRC_TIMXCEED_REASS);
+       pk_protolisten(0x81, 0, clnp_incoming);
+       pk_protolisten(0x82, 0, esis_incoming);
+       pk_protolisten(0x84, 0, tp8878_A_incoming);
+       pk_protolisten(0, 0, tp_incoming);
+#endif
 }
 }
-#endif notdef
 
 
-/*
- * NAME:       cons_slowtimo()
- * CALLED FROM: 
- *     the clock
- * FUNCTION:
- *     get rid of any timed-out cons connections
- *  cons connections get "touched" with every use, meaning the
- *  time-to-live gets reset to its max value w/ every use.
- *  The slowtimo() rtn decrements the time-to-live for each
- *  cons connection.  If one of them hits zero ---> zap the connection.
- *  This really only applies to those used for CLNP and TP4.
- *  TP4 keeps the connections open with keepalive.
- * TODO:
- *  Have this happen ONLY for international connections since
- *  there's no connect time charge for domestic calls.
- *  Make default 5 min; make a user option to change it.
- * TODO:
- *  Maybe if the ttl gets lower than a certain threshold, move this 
- *  copcb to the END of its queue so it doesn't slow down the others.
- */
-
-cons_slowtimo()
+tp_incoming(lcp, m)
+struct pklcd *lcp;
+register struct mbuf *m;
 {
 {
-       register struct cons_pcb **copcblist = (struct cons_pcb **)Xpcblist;
-       register struct cons_pcb *copcb;
-       int s = splnet();
-       int     qlen = 0;
-       int qdrops = 0;
-       int     nvisited = 0;
-
-#ifdef ARGO_DEBUG
-       Static int count;
-
-       count = 0;
-#endif ARGO_DEBUG
+       register struct isopcb *isop;
+       extern struct isopcb tp_isopcb;
+       int cons_tpinput();
 
 
-       IncStat(co_slowtimo);
-       for( copcb = *copcblist; copcb; copcb = *(++copcblist) ) {
-#ifdef ARGO_DEBUG
-               if( copcb == (struct cons_pcb *)0 ) {
-                       ASSERT( 0 );
-                       panic("TURNING OFF cons_slowtimo()!!! \n");
-               }
-#endif ARGO_DEBUG
-               copcb = (struct cons_pcb *)copcb->co_next;
-               while (copcb !=  *copcblist) {
-#ifdef ARGO_DEBUG
-                       if(++count >50 ) {
-                               printf("cons PANIC: slowtimo LOOP\n");
-                               splx(s);
-                               return;
-                       }
-#endif ARGO_DEBUG
-#ifdef notdef
-                       if( copcb->co_init_ttl == 0 ) {
-       ASSERT( (struct isopcb *)(*copcblist)==(struct isopcb *)&tp_isopcb );
-                               copcb = (struct cons_pcb *)copcb->co_next; 
-                               continue;
-                       }
-#endif notdef
-                       nvisited ++;
-                       ASSERT( copcb != (struct cons_pcb *)0 );
-                       qlen += copcb->co_pending.ifq_len;
-                       qdrops += copcb->co_pending.ifq_drops;
-
-                       if( copcb->co_socket) {
-                               /* don't want XTS, TP0 connections to be subject to time out */
-                               copcb = (struct cons_pcb *)copcb->co_next; 
-                               continue;
-                       }
-
-                       if( -- (copcb->co_ttl) > 0 )  {
-                               copcb = (struct cons_pcb *)copcb->co_next; 
-                               continue;
-                       }
-
-                       IncStat(co_timedout);
-
-                       IFDEBUG(D_CCONN)
-                               printf("TIMING OUT chan 0x%x copcb 0x%x flags 0x%x\n", 
-                                       copcb->co_channel, copcb, copcb->co_flags );
-                       ENDDEBUG
-
-                       { 
-                               register struct cons_pcb * next = 
-                                       (struct cons_pcb *)copcb->co_next; 
-                               cons_clear_and_detach(copcb, 
-                                               E_CO_HLI_RESYNC, PRC_TIMXCEED_REASS);
-                               copcb = next;
-                       }
-               }
-       }
-       if(nvisited) {
-               cons_stat.co_avg_qlen = qlen / nvisited;
-               cons_stat.co_avg_qdrop = qdrops / nvisited;
-               cons_stat.co_active = nvisited;
-       }
-done:
-       splx(s);
-}
-
-DUMP_PCBLIST()
-{
-       register int i=0;
-       register struct cons_pcb *copcb;
-       register struct cons_pcb **copcblist = (struct cons_pcb **)Xpcblist;
-
-       for( copcb = *copcblist; copcb; copcb = *(++copcblist) ) {
-               printf("FOR %d: 0x%x ", ++i, copcb);
-               copcb = (struct cons_pcb *)copcb->co_next;
-               printf(" next 0x%x, *copcblist 0x%x\n",  copcb, *copcblist);
-               while (copcb !=  *copcblist) {
-                       ASSERT( copcb != (struct cons_pcb *)0 );
-                       printf("\tCOPCB 0x%x\n", copcb);
-                       if( copcb )
-                               dump_buf(copcb, sizeof( *copcb));
-                       else
-                               break;
-                       copcb = (struct cons_pcb *)copcb->co_next; 
-               }
+       if (iso_pcballoc((struct socket *)0, &tp_incoming_pending)) {
+               pk_close(lcp);
+               return;
        }
        }
-}
-
-/*
- * NAME:       cons_pcballoc()
- * CALLED FROM:
- *     cons_usrreq() when doing PRU_ATTACH, 
- *  cons_incoming() when opening a new connection.  
- * FUNCTION and ARGUMENTS:
- *     Allocates a new pcb.
- *  The flags and proto arguments are stashed into the new pcb.
- * RETURN VALUE:
- *  E* if error, 0 if ok
- */
-Static int
-cons_pcballoc(so, head, flags, proto, dest)
-       struct socket   *so;
-       struct  isopcb  *head;
-       u_short                 flags;
-       struct protosw  *proto;
-       struct  cons_pcb **dest;
-{
-       int                                     error;
-       register struct cons_pcb *copcb;
-
-       IFDEBUG(D_CCONN)
-               printf("cons_pcballoc (0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", 
-                       so, head, flags, proto, dest);
-       ENDDEBUG
-       if(proto == (struct protosw *)0)
-               return EPROTONOSUPPORT;
+       isop = tp_incoming_pending.isop_next;
+       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;
+       DTEtoNSAP(isop->isop_laddr, &lcp->lcd_laddr);
+       DTEtoNSAP(isop->isop_faddr, &lcp->lcd_faddr);
+       parse_facil(isop, lcp, &(mtod(m, struct x25_packet *)->packet_data),
+               m->m_pkthdr.len - PKHEADERLN);
+}
+
+cons_tpinput(lcp, m0)
+struct mbuf *m0;
+struct pklcd *lcp;
+{
+       register struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext;
+       register struct x25_packet *xp;
+       int cmd;
 
 
-       if( ( error = iso_pcballoc(so, head) ) == EOK )  {
-               /* Have allocated a cleared mbuf */
+       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);
+               return;
 
 
-               copcb = (struct cons_pcb *)so->so_pcb;
-               copcb->co_ttl = copcb->co_init_ttl = X25_TTL;
-               copcb->co_flags = flags; 
-               copcb->co_proto = proto;
-               copcb->co_pending.ifq_maxlen = CONS_IFQMAXLEN;
-               copcb->co_myself = copcb;
+       case MT_CONTROL:
+               switch (pk_decode(mtod(m0, struct x25_packet *))) {
 
 
-               if (so == &dummysocket) 
-                       copcb->co_socket = (struct socket *)0;
+               case RR:
+                       cmd = PRC_CONS_SEND_DONE;
+                       break;
 
 
-               *dest = copcb;
-       }
-done:
-       IFDEBUG(D_CCONN)
-               printf("cons_pcballoc returns 0x%x: DUMP\n", copcb);
-               dump_buf( copcb, sizeof(*copcb));
-       ENDDEBUG
-       if( (flags & CONSF_ICRE) == 0) {
-               struct dte_addr *dtea = &(*dest)->co_peer_dte;
-               int len;
+               case CALL_ACCEPTED:
+                       if (lcp->lcd_sb.sb_mb)
+                               lcp->lcd_send(lcp); /* XXX - fix this */
+                       /*FALLTHROUGH*/
+               default:
+                       return;
 
 
-               error = iso_8208snparesolve(&(*dest)->co_faddr, dtea, &len);
-               ASSERT(error == 0);
-               ASSERT(len == sizeof(struct dte_addr));
+               dead:
+               case RESET:
+               case CLEAR:
+               case CLEAR_CONF:
+                       cmd = PRC_ROUTEDEAD;
+               }
+               tpcons_ctlinput(cmd, isop->isop_faddr, isop);
        }
        }
-
-       return error;
 }
 
 /*
  * NAME:       cons_connect()
  * CALLED FROM:
 }
 
 /*
  * NAME:       cons_connect()
  * CALLED FROM:
- *     cons_usrreq() when opening a new connection.  
+ *     tpcons_pcbconnect() when opening a new connection.  
  * FUNCTION anD ARGUMENTS:
  *  Figures out which device to use, finding a route if one doesn't
  *  already exist.
  * FUNCTION anD ARGUMENTS:
  *  Figures out which device to use, finding a route if one doesn't
  *  already exist.
- *     Builds an eicon connection request and gives it to the device.
  * RETURN VALUE:
  *  returns E*
  */
  * RETURN VALUE:
  *  returns E*
  */
-Static int 
-cons_connect( copcb )
-       register struct cons_pcb *copcb;
+cons_connect(isop)
+       register struct isopcb *isop;
 {
 {
-       register struct eicon_request *ecnrq;
+       register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
        register struct mbuf    *m;
        register struct mbuf    *m;
-       int                                     error = 0;
        struct ifaddr                   *ifa;
        struct ifaddr                   *ifa;
+       int error;
 
        IFDEBUG(D_CCONN)
 
        IFDEBUG(D_CCONN)
-               printf("cons_connect( 0x%x ) : ifp 0x%x\npeer: ", copcb, copcb->co_ifp);
-               dump_isoaddr(&copcb->co_faddr);
-               printf("\nmyaddr: ");
-               dump_isoaddr(&copcb->co_laddr);
+               printf("cons_connect(0x%x): ", isop);
+               dump_isoaddr(isop->isop_faddr);
+               printf("myaddr: ");
+               dump_isoaddr(isop->isop_laddr);
                printf("\n" );
        ENDDEBUG
                printf("\n" );
        ENDDEBUG
-
-       /* PHASE 2: this call is OK */
-       if( ifa = ifa_ifwithaddr(&copcb->co_faddr ) ) {
-               /* foreign address is me */
-               copcb->co_ifp = ifa->ifa_ifp; 
-               IFDEBUG(D_CCONN)
-                       printf("cons_connect: after if_withaddr copcb->co_ifp 0x%x\n",
-                               copcb->co_ifp);
-               ENDDEBUG
-
-               if( (ifa->ifa_ifp->if_flags&(IFF_LOOPBACK|IFF_UP)) ==
-                                                                                               (IFF_LOOPBACK|IFF_UP)) {
-                       copcb->co_flags |= CONSF_LOOPBACK;
-               }
-               bcopy((caddr_t)&ifa->ifa_addr, (caddr_t)&copcb->co_laddr, 
-                       sizeof(struct sockaddr));
-       } 
+       NSAPtoDTE(isop->isop_faddr, &lcp->lcd_faddr);
+       lcp->lcd_upper = cons_tpinput;
+       lcp->lcd_upnext = (caddr_t)isop;
        IFDEBUG(D_CCONN)
        IFDEBUG(D_CCONN)
-               printf("cons_connect: co_flags 0x%x\n", copcb->co_flags);
-               if( ifa ) {
-                       printf(" cons_connect withaddr returns %s\n", 
-                               copcb->co_ifp->if_name);
-               }
+               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
        ENDDEBUG
-       else if ( copcb->co_ifp == (struct ifnet *)0 ) {
-#ifdef PHASEONE
-               /*
-                *      We need to get the local nsap address.
-                *      First, route to the destination. This will provide us with
-                *      an ifp. Second, determine which local address linked on
-                *      that ifp is appropriate
-                */
-               struct sockaddr_iso     *first_hop;             /* filled by clnp_route */
-               struct iso_addr *localaddr, *clnp_srcaddr();
-
-               if (error = clnp_route(&copcb->co_faddr, 
-                       &((struct isopcb *)copcb)->isop_route, /* flags */0,
-                       &first_hop, &copcb->co_ifp))
-                       goto bad;
-
-               /* determine local address based upon ifp */
-               if ((localaddr = clnp_srcaddr(copcb->co_ifp, 
-                               &first_hop->siso_addr)) == NULL) {
-                       error = ENETUNREACH;
-                       goto bad;
-               }
-               copcb->co_laddr.siso_family = AF_ISO;
-               copcb->co_laddr.siso_addr = *localaddr;
-#else
-               /* Foreign addr isn't me (lpb). If still don't have an ifp or have
-                * an ifp but don't know its address, look for a route 
-                */
-               if( ifa = ifa_ifwithnet(&copcb->co_faddr) ) {
-                       copcb->co_ifp =  ifa->ifa_ifp;
-                       IFDEBUG(D_CCONN)
-                               printf(" cons_connect withnet returns %s\n",
-                                                                               copcb->co_ifp->if_name);
-                       ENDDEBUG
-               } else {
-                       printf("cons PANIC: connect: can't find SNPA \n");
-                       error = ENETUNREACH;
-                       goto bad;
-               }
-#endif PHASEONE
-       }
-#ifndef        PHASEONE
-       if( ifa == (struct ifaddr *)0 ) {
-               struct ifaddr * iso_ifwithidi();
-
-               if( ifa = iso_ifwithidi(&copcb->co_faddr) ) {
-                       copcb->co_ifp =  ifa->ifa_ifp;
-                       IFDEBUG(D_CCONN)
-                               printf(" cons_connect withnet returns %s\n",
-                                                                               copcb->co_ifp->if_name);
-                       ENDDEBUG
-               } else {
-                       printf("cons PANIC: connect: can't find SNPA \n");
-                       error = ENETUNREACH;
-                       goto bad;
-               }
-       }
-       bcopy((caddr_t)&ifa->ifa_addr, (caddr_t)&copcb->co_laddr, 
-               sizeof(struct sockaddr));
-#endif PHASEONE
-
-       copcb->co_state = CONNECTING;
+       if ((error = make_partial_x25_packet(isop, lcp, m)) == 0)
+               error = pk_connect(lcp, &lcp->lcd_faddr);
+       return error;
+}
 
 
-       ASSERT( copcb->co_ifp != (struct ifnet *) 0);
-       if ( copcb->co_ifp == (struct ifnet *)0 ) {
-               error = ENETUNREACH;
-               goto bad;
-       }
+/*
+ **************************** DEVICE cons ***************************
+ */
 
 
-       m = m_getclr(M_DONTWAIT, MT_XCONN);
-       if( !m ) {
-               copcb->co_ifp->if_oerrors ++;
-               error = ENOBUFS;
-               goto bad; 
-       }
-       m->m_len = sizeof(struct eicon_request);
 
 
-       ecnrq = mtod(m, struct eicon_request *);
+/* 
+ * NAME:       cons_ctlinput()
+ * CALLED FROM:
+ *  lower layer when ECN_CLEAR occurs : this routine is here
+ *  for consistency - cons subnet service calls its higher layer
+ *  through the protosw entry.
+ * FUNCTION & ARGUMENTS:
+ *  cmd is a PRC_* command, list found in ../sys/protosw.h
+ *  copcb is the obvious.
+ *  This serves the higher-layer cons service.
+ * NOTE: this takes 3rd arg. because cons uses it to inform itself
+ *  of things (timeouts, etc) but has a pcb instead of an address.
+ */
+cons_ctlinput(cmd, sa, copcb)
+       int cmd;
+       struct sockaddr *sa;
+       register struct pklcd *copcb;
+{
+}
 
 
-       copcb->co_myself = copcb;
-       ecnrq->e_pcb = (caddr_t)copcb;
-#ifdef ARGO_DEBUG
-       LAST_CALL_PCB = (unsigned) ecnrq->e_pcb;
-#endif ARGO_DEBUG
-       ecnrq->e_cmd = ECN_CALL;
-       ecnrq->e_vc = 0; /* mbz ? */
-       ecnrq->e_info = 0; /* mbz */
-
-       /* get data buffer */
-       {       struct mbuf *n;
-
-               MGET(n, M_DONTWAIT, MT_XCONN);
-               if( n==MNULL ) {
-                       copcb->co_ifp->if_oerrors ++;
-                       error = ENOBUFS;
-                       goto bad; 
-               }
-               e_data(ecnrq) = n; /* e_data is really dtom(ecnrq)->m_next */
-       }
 
 
-       IFDEBUG(D_CCONN)
-               printf(
-               "calling make_partial_x25_packet( 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
-                       &copcb->co_laddr, &copcb->co_faddr, 
-                       copcb->co_proto->pr_protocol, 
-                       e_data(ecnrq),
-                       copcb->co_flags & CONSF_XTS);
-       ENDDEBUG
-       if( error = make_partial_x25_packet( copcb, e_data(ecnrq)) ) {
-               copcb->co_ifp->if_oerrors ++;
-               m_freem(m);
-               goto bad;
-       }
-               
-       IncStat(co_call);
+find_error_reason( xp )
+       register struct x25_packet *xp;
+{
+       extern u_char x25_error_stats[];
+       int error, cause;
 
 
-       IFDEBUG(D_CDUMP_REQ)
-               printf("cons_connect ecnrq:\n");
-               dump_buf(ecnrq, sizeof(*ecnrq));
-       ENDDEBUG
+       if (xp) {
+               cause = 4[(char *)xp];
+               switch (cause) {
+                       case 0x00:
+                       case 0x80:
+                               /* DTE originated; look at the diagnostic */
+                               error = (CONL_ERROR_MASK | cause);
+                               goto done;
 
 
-       ASSERT( copcb->co_channel == 0);
-       if( copcb->co_channel != 0) {
-               printf("cons_connect PANIC: channel is 0x%x\n", copcb->co_channel);
-       }
+                       case 0x01: /* number busy */
+                       case 0x81:
+                       case 0x09: /* Out of order */
+                       case 0x89:
+                       case 0x11: /* Remot Procedure Error */
+                       case 0x91:
+                       case 0x19: /* reverse charging accept not subscribed */
+                       case 0x99:
+                       case 0x21: /* Incampat destination */
+                       case 0xa1:
+                       case 0x29: /* fast select accept not subscribed */
+                       case 0xa9:
+                       case 0x39: /* ship absent */
+                       case 0xb9:
+                       case 0x03: /* invalid facil request */
+                       case 0x83:
+                       case 0x0b: /* access barred */
+                       case 0x8b:
+                       case 0x13: /* local procedure error */
+                       case 0x93:
+                       case 0x05: /* network congestion */
+                       case 0x85:
+                       case 0x8d: /* not obtainable */
+                       case 0x0d:
+                       case 0x95: /* RPOA out of order */
+                       case 0x15:
+                               /* take out bit 8 
+                                * so we don't have to have so many perror entries 
+                                */
+                               error = (CONL_ERROR_MASK | 0x100 | (cause & ~0x80));
+                               goto done;
 
 
-       error = choose_output(copcb->co_ifp, m, copcb->co_flags & CONSF_LOOPBACK);
+                       case 0xc1: /* gateway-detected proc error */
+                       case 0xc3: /* gateway congestion */
 
 
-       switch( error ) {
-               case 0: /* ok */
-                       break;
-               default: /* problem */
-                       printf("cons: PANIC: if_output returns 0x%x\n", error);
-                       cons_clear_and_detach( copcb, DONTCLEAR, PRC_ROUTEDEAD);
-       }
+                               error = (CONL_ERROR_MASK | 0x100 | cause);
+                               goto done;
+               } 
+       } 
+       /* otherwise, a *hopefully* valid perror exists in the e_reason field */
+       error = xp->packet_data;
+       if (error = 0) {
+               printf("Incoming PKT TYPE 0x%x with reason 0x%x\n",
+                       pk_decode(xp),
+                       cause);
+               error = E_CO_HLI_DISCA;
+       } 
 
 
-bad:
-       IFTRACE(D_CDATA)
-               tptrace( TPPTmisc, 
-               "cons_connect: choose (copcb m) returned  error\n", 
-                       copcb, m, error, 0);
-       ENDTRACE
+done:
        return error;
 }
 
        return error;
 }
 
+
+
+#endif KERNEL
+
 /*
 /*
- * NAME:       cons_find()
- * CALLED FROM:
- *     cosns_output1() thus:
- *             cons_find( CONSF_DGM, dst, proto, 0, 0) where
- *             proto is one of { TP_proto, CLNP_proto }
+ * NAME:       make_partial_x25_packet()
+ *
  * FUNCTION and ARGUMENTS:
  * FUNCTION and ARGUMENTS:
- *  Looks through list of connections for the destination,
- *  for one marked for the use indicated by flags.
- *  If none found, opens up a new connection.
- *   These connections will be eliminated by :
- *     a) slowtimo timer, or 
- *     b) the need for a new connection, when we've run out of resources.
- *  The argument flags describes the type of pcb we want - may
- *  specify multiplexing-ok, datagram use, etc.
- *  The argument proto points the the higher layer protocol that
- *  will be using this connection.
- * RETURN VALUE:
- *  returns a ptr to a pcb whose characteristics match those
- *  described by (flags, proto)
+ *     Makes part of an X.25 call packet, for use by x25.
+ *  (src) and (dst) are the NSAP-addresses of source and destination.
+ *     (buf) is a ptr to a buffer into which to write this partial header.
+ *
+ *      0                      Facility length (in octets)
+ *      1                      Facility field, which is a set of:
+ *       m                     facil code
+ *       m+1           facil param len (for >2-byte facilities) in octets
+ *       m+2..p        facil param field
+ *  q                  user data (protocol identification octet)
+ * 
+ *
+ * RETURNS: 
+ *  0 if OK
+ *  E* if failed.
+ *
+ * SIDE EFFECTS:
+ * Stores facilites mbuf in X.25 control block, where the connect
+ * routine knows where to look for it.
  */
 
  */
 
-Static struct cons_pcb *
-cons_find(flags, dst, proto, addl_criteria, mask)
-       u_int flags, mask;
-       struct sockaddr_iso *dst;
-       struct protosw *proto;
-       int     (*addl_criteria)();
-{
-       register struct cons_pcb *copcb;
-       register struct cons_pcb **copcblist = (struct cons_pcb **)Xpcblist;
-       int s = splnet(); /* or whatever, for the device! */
-       struct dte_addr dest_dte;
-       int      dummy;
-
-       struct  copcb_descriptor {
-               int     xd_qlen;
-               struct cons_pcb *xd_pcb;
-       } next_best = {
-               0, (struct cons_pcb *)0
-       };
-
-       IFDEBUG(D_CFIND)
-               printf("cons_find( flags 0x%x proto 0x%x) ", flags, proto);
-       ENDDEBUG
+#ifdef X25_1984 
+int cons_use_facils = 1;
+#else X25_1984 
+int cons_use_facils = 0;
+#endif X25_1984 
 
 
-       if ( iso_8208snparesolve(dst, &dest_dte, &dummy)) {
-               ASSERT(0);
-               return (struct cons_pcb *)0; /* error */
-       }
-       ASSERT(dummy == sizeof(struct dte_addr));
-
-       for( copcb = *copcblist; copcb; copcb = *(++copcblist) ) {
-               copcb = (struct cons_pcb *)copcb->co_next;
-               while (copcb !=  *copcblist) {
-                       IFDEBUG(D_CFIND)
-                               printf(
-                               "cons_find: chan 0x%x flags 0x%x proto 0x%x state 0x%x \n", 
-                                       copcb->co_channel, copcb->co_flags, copcb->co_proto, 
-                                       copcb->co_state);
-                       ENDDEBUG
-                       /*
-                        * if flags is a subset of the bits in co_flags, it will suffice
-                        */
-                       if( ((copcb->co_flags & flags) == flags ) &&
-                               /* PHASE2: where do we get the mask if we use nsaps ????
-                                * If dte addresses are used, then use
-                                * nibble compare otherwise...???
-                                */
-#ifdef notdef
-                               iso_addrmatch1(&(copcb->co_faddr.siso_addr), &(dst->siso_addr)) 
-#else
-                               dest_dte.dtea_niblen == copcb->co_peer_dte.dtea_niblen &&
-                               nibble_match( (char *)&(copcb->co_peer_dte.dtea_addr), 
-                                       HIGH_NIBBLE, (char *)dest_dte.dtea_addr, 
-                                       HIGH_NIBBLE, dest_dte.dtea_niblen)
-#endif notdef
-                               &&
-                               (copcb->co_proto == proto)  &&
-                               (copcb->co_state >= MIN_USABLE_STATE)) {
-                                       IFDEBUG(D_CFIND)
-                                               printf(
-                                               "cons_find: add'l criteria...\n" );
-                                       ENDDEBUG
-                                       if((copcb->co_state != OPEN) &&
-                                               (next_best.xd_qlen > copcb->co_pending.ifq_len)) {
-                                               next_best.xd_pcb = copcb;
-                                               next_best.xd_qlen = copcb->co_pending.ifq_len;
-                                       }
-                                       if( !addl_criteria || (*addl_criteria)(copcb, mask) ) {
-                                               goto found; /* have to break out of 2 loops */
-                                       }
-                               }
-                       copcb = (struct cons_pcb *)copcb->co_next ;
-               }
-       }
-#ifdef notdef
-       /* TODO: 
-        * have a limit of the number of calls per desitination.
-        * If we didn't find one already open AND our limit for this
-        * destination hasn't been reached, return 0 'cause
-        * then the caller will open a new one.
-        * Otherwise return next_best.
-        * To do this we need some sort of per-destination info.
-        * Could go into the directory service. Oh, grotesque.
-        */
-#endif notdef
-       if( copcb == (struct cons_pcb *)0 ) {
-               copcb = next_best.xd_pcb; /* may be zero too */
-               IFDEBUG(D_CFIND)
-                       printf("NEXT_BEST! \n");
-                       dump_copcb(copcb, "find: next_best");
-               ENDDEBUG
-       }
-found:
-
-       splx(s);
-               
-       IFDEBUG(D_CFIND)
-               printf("returns 0x%x \n", copcb);
-       ENDDEBUG
-       return copcb;
-}
-
-
-/*
- * NAME:       issue_clear_req()
- * CALLED FROM:
- *     cons_clear() and wherever we get an error from x.25 that makes us
- *     want to close the vc on which it came, but don't have
- *             a copcb assoc. with that vc.
- * FUNCTION and ARGUMENTS:
- *  Creates an eicon_request for a clear request, returns it in an mbuf.
- *  (chan) is the channel on which to do the clear, (reason) is the 
- *  clear reason(diagnostic).
- * RETURN VALUE:
- *  returns E*
- */
-Static int
-issue_clear_req(chan, reason, ifp, loop)
-       u_char                  chan, reason;
-       struct  ifnet   *ifp;
-       int                             loop;
-{
-       register struct mbuf                    *m;
-       register struct mbuf                    *cdm;
-       register struct eicon_request   *ecnrq;
-       struct e_clear_data                     *ecd; 
-
-       IFDEBUG(D_CCONN)
-               printf("issue_clear_req(0x%x, 0x%x, 0x%x, 0x%x)\n", 
-                       chan, reason, ifp, loop);
-       ENDDEBUG
-       m = m_getclr(M_DONTWAIT, MT_XCLOSE);
-       if( !m ) {
-               return ENOBUFS;
-       }
-       m->m_len = sizeof(struct eicon_request);
-       ecnrq = mtod(m, struct eicon_request *);
-       ecnrq->e_cmd = ECN_CLEAR;
-       ecnrq->e_vc = chan & 0xff; 
-       /* 
-        *  see p. 149 of 8208 for reasons (diagnostic codes)
-        */
-       MGET(cdm, M_DONTWAIT, MT_XCLOSE);
-       if( !cdm ) {
-               m_freem(m);
-               return ENOBUFS;
-       }
-       cdm->m_len = sizeof(struct e_clear_data); /* cause, diagnostic */
-       e_data(ecnrq) = cdm;
-
-       ecd = mtod(cdm, struct e_clear_data *);
-       ecd->ecd_cause = 0x0; /* DTE initiated, diagnostic tells more */
-       ecd->ecd_diagnostic = (u_char)reason;
-
-       IncStat(co_clear_out);
-       return choose_output(ifp, m, loop);
-}
-
-
-/*
- * NAME:       cons_clear()
- * CALLED FROM:
- *  cons_usrreq(), PRU_DISCONNECT,
- *  cons_slowtimo(), cons_free_lru()
- * FUNCTION and ARGUMENTS:
- *     Builds a clear request for the connection represented by copcb,
- *  gives it to the device.
- * ECN_CLEAR(request) takes e_vc only, returns adr_status.
- * RETURN VALUE:
- */
-
-Static int 
-cons_clear( copcb, reason) 
-       register struct cons_pcb *copcb;
-       u_char                                  reason;
-{
-       register struct mbuf                    *m;
-       int                                                             error;
-
-       IFDEBUG(D_CCONN)
-               printf("cons_clear(0x%x, 0x%x)\n", copcb, reason);
-       ENDDEBUG
-       if( !copcb) {
-               printf("cons PANIC: clear: No copcb\n");
-               return 0;
-       }
-       while( copcb->co_pending.ifq_len > 0 ) {
-               register int s = splimp();
-
-               IF_DEQUEUE( &copcb->co_pending, m );
-               splx(s);
-               m_freem(m);
-       }
-       if( (copcb->co_state == CLOSED) || (copcb->co_state == CLOSING) )
-               return 0;
-
-#ifdef ARGO_DEBUG
-       if( copcb->co_state == CONNECTING) {
-               IFDEBUG(D_CCONN)
-                       dump_copcb(copcb, "clear");
-               ENDDEBUG
-       } else if( (copcb->co_channel == 0) || (copcb->co_channel == X_NOCHANNEL) ) {
-               IFDEBUG(D_CCONN)
-                       dump_copcb(copcb, "clear");
-               ENDDEBUG
-       }
-#endif ARGO_DEBUG
-
-       copcb->co_state = CLOSING;
-
-       IFDEBUG(D_CCONN)
-               printf("cons_clear: channel 0x%x copcb 0x%x dst: ", 
-                       copcb->co_channel,  copcb);
-               dump_isoaddr(&copcb->co_faddr);
-               dump_copcb(copcb, "clear");
-       ENDDEBUG
-
-       error = issue_clear_req(copcb->co_channel, reason, copcb->co_ifp,
-               copcb->co_flags & CONSF_LOOPBACK);
-       copcb->co_channel = X_NOCHANNEL; 
-       copcb->co_state = CLOSED;
-       return error;
-}
-
-
-/* 
- * NAME:       cons_senddata()
- * CALLED FROM:
- *  cons_output(), consoutput(), consintr()
- * FUNCTION and ARGUMENTS:
- *     issued a data (write) command - if the device isn't ready,
- *  it enqueues the command on a per-connection queue.
- * RETURN VALUE:
- *     ENOBUFS
- *  Is responsible for freeing m0!
- *
- * ECN_SEND (write) 
- */
-
-Static int 
-cons_senddata(copcb, m0)
-       register struct cons_pcb *copcb;
-       struct mbuf *m0;
-{
-       register struct mbuf *m;
-       register struct eicon_request *ecnrq;
-       int s;
-
-       IFDEBUG(D_CDATA)
-               printf("cons_senddata( 0x%x, m 0x%x ) chan 0x%x", 
-                       copcb, m0, copcb->co_channel );
-               printf(" co_lport 0x%x\n", copcb->co_lport);
-       ENDDEBUG
-       if( m0 == MNULL ) 
-               return;
-       ASSERT( m0->m_len > 0);
-       if( m0->m_len <= 0) {
-               printf("cons_senddata : BAD MLEN? 0x%x", m0->m_len);
-       }
-
-       touch(copcb);
-
-       if( (copcb->co_state == CONNECTING) || (copcb->co_state == ACKWAIT) ) {
-               IFDEBUG(D_CDATA)
-                       printf("senddata PUTTING ON PENDING Q copcb 0x%x state 0x%x\n", 
-                               copcb, copcb->co_state);
-               ENDDEBUG
-               s = splimp();
-               if (IF_QFULL(&copcb->co_pending)) {
-                       IFDEBUG(D_CDATA)
-                               printf("senddata DROPPING m0 0x%x\n",  m0);
-                       ENDDEBUG
-                       IF_DROP(&copcb->co_pending);
-                       if(copcb->co_ifp) {
-                               copcb->co_ifp->if_snd.ifq_drops ++;
-                       }
-                       IncStat(co_Xdrops);
-                       copcb->co_ifp->if_oerrors ++;
-                       splx(s);
-                       m_freem (m0);
-
-                       if( copcb->co_proto  && copcb->co_proto->pr_ctlinput ) {
-                               (*copcb->co_proto->pr_ctlinput)(PRC_QUENCH, 
-                               (struct sockaddr_iso *)&copcb->co_faddr, 
-                               (caddr_t)copcb);
-                               
-                               return 0;
-                       } else
-                               return E_CO_QFULL;
-               }
-               IFDEBUG(D_CDATA)
-                       printf("Putting 0x%x on 0x%x->pending Q\n", m0, copcb);
-               ENDDEBUG
-               IF_ENQUEUE( &copcb->co_pending, m0 );
-               splx(s);
-               return 0;
-       }
-       if(copcb->co_channel == 0 ) {
-               return E_CO_CHAN;
-       }
-       ASSERT( copcb->co_state == OPEN);
-
-       m = m_getclr(M_DONTWAIT, MT_XDATA);
-       if( !m ) {
-               copcb->co_ifp->if_oerrors ++;
-               m_freem (m0);
-               return ENOBUFS;
-       }
-       m->m_len = sizeof(struct eicon_request);
-       ecnrq = mtod(m, struct eicon_request *);
-       ecnrq->e_pcb = (caddr_t)copcb;
-       if( copcb->co_myself != copcb ) {
-               struct mbuf *mm;
-               /* TODO: REMOVE THIS DEBUGGING HACK */
-               ASSERT(0);
-               printf("BAD e_pcb from HL (0x%x,0x%x)\n", copcb, copcb->co_myself);
-               mm = dtom( copcb );
-               if(mm->m_type == MT_FREE)
-                       printf("FREED MBUF!\n");
-               return ENETDOWN;
-       }
-       ASSERT( copcb->co_channel != 0);
-       ASSERT( copcb->co_channel != X_NOCHANNEL);
-       ecnrq->e_vc = (copcb->co_channel & 0xff);
-       ecnrq->e_cmd = ECN_SEND;
-       e_data(ecnrq) = m0;
-       {
-               /* TODO: REMOVE THIS DEBUGGING HACK */
-               struct mbuf *thedata = e_data(ecnrq);
-               u_int *firstint = mtod( thedata, u_int *);
-               
-               if( (*firstint & 0xff000000) != 0x81000000 ) {
-                       /* not clnp */
-                       switch( ((*firstint) & 0x00ff0000) >> 20 ) {
-                       case 0x1:
-                       case 0x2:
-                       case 0x3:
-                       case 0x6:
-                       case 0x7:
-                       case 0x8:
-                       case 0xc:
-                       case 0xd:
-                       case 0xe:
-                       case 0xf:
-                               break;
-                       default:
-                               printf(" ECN_SEND! BAD DATA\n" );
-                               dump_buf( thedata, 20 + 12 );
-                               m_freem( m0 );
-                               return ENETDOWN;
-                       }
-               }
-       }
-
-       ecnrq->e_info = 0;
-
-       IFDEBUG(D_CDUMP_REQ)
-               printf("senddata ecnrq\n");
-       ENDDEBUG
-       IncStat(co_send);
-
-       ASSERT( copcb->co_state == OPEN );
-       copcb->co_state = ACKWAIT;
-
-       if( copcb->co_myself != copcb ) {
-               struct mbuf *mm;
-               /* TODO: REMOVE this and all mention of co_myself */
-               ASSERT(0);
-               printf("BAD e_pcb TO THE BOARD ecn (0x%x) cmd 0x%x\n", 
-                       ecnrq->e_pcb, ecnrq->e_cmd);
-               mm = dtom( copcb );
-               if(mm->m_type == MT_FREE)
-                       printf("FREED MBUF!\n");
-               dump_buf (ecnrq, sizeof (*ecnrq));
-               return ENETDOWN;
-       }
-
-       return 
-         choose_output(copcb->co_ifp, dtom(ecnrq), copcb->co_flags&CONSF_LOOPBACK);
-}
-
-/*
- * NAME:       cons_send_on_vc()
- * CALLED FROM:
- *  tp_error_emit()
- * FUNCTION and ARGUMENTS:
- *  Take a packet(m0), of length (datalen) from tp and 
- * send it on the channel (chan).
- *     
- * RETURN VALUE:
- *  whatever (E*) is returned form the net layer output routine.
- */
-int
-cons_send_on_vc(chan, m, datalen)
-       int                             chan;
-       struct mbuf     *m;
-       int                             datalen;
-{
-       struct cons_pcb *copcb = (struct cons_pcb *)0;
-
-       if(m == MNULL)
-               return;
-
-       if((copcb = 
-#ifdef ARGO_DEBUG
-               cons_chan_to_pcb( chan, __LINE__ )
-#else ARGO_DEBUG
-               cons_chan_to_pcb( chan )
-#endif ARGO_DEBUG
-                       ) == (struct cons_pcb *)0 )
-               return E_CO_CHAN; 
-       IFDEBUG(D_CCONS)
-               printf("cons_send_on_vc m 0x%x m_len 0x%x\n", m, m->m_len);
-       ENDDEBUG
-       return cons_senddata( copcb, m);
-}
-
-/*
- * NAME:       cons_output()
- * CALLED FROM:
- *  tpiso_output(), can have whatever interface we want it to...
- *  tpiso_output() decides whether to give a packet to CLNP or to 
- *  cons; if the latter, it calls this routine.
- * FUNCTION and ARGUMENTS:
- *  tp has alloc-ed a pcb - but it may not be open.
- *  some classes of tp may allow multiplexing, in which
- *  case, you may choose to send the data on ANOTHER cons connection.
- *  This decides which net connection to use, opens one if necessary.
- *  Then it sends the data.
- */
-
-cons_output(isop, m, len, isdgm)
-       struct isopcb   *isop;
-       struct mbuf     *m;
-       int                     len;
-       int                             isdgm;
-{
-       struct cons_pcb *copcb = (struct cons_pcb *)0;
-       int                             error;
-       int                     s = splnet();
-
-       IFDEBUG(D_CCONS)
-               printf("cons_output( isop 0x%x, m 0x%x, len 0x%x, dgm 0x%x )\n", 
-                       isop,m,len, isdgm);
-       ENDDEBUG
-
-       if( m == MNULL )
-               return 0;
-       ASSERT(m->m_len > 0);
-       if( isdgm ) {
-               error = cosns_output1(0, m, &isop->isop_faddr, TP_proto, isop);
-               IFDEBUG(D_CDATA)
-                       if(error)
-                       printf("cosns_output1 RETURNS ERROR 0x%x\n", error);
-               ENDDEBUG
-               return error;
-       }
-
-       if( isop->isop_chanmask  || isop->isop_negchanmask) {
-               register int    mask = isop->isop_chanmask;
-               register int    chan = 1;
-
-               if( mask == 0)
-                       mask = isop->isop_negchanmask;
-
-               for ( chan=1; (mask & 1)==0; chan++,mask>>=1 ) ;
-
-               if( isop->isop_chanmask == 0 )
-                       chan = -chan;
-
-               IFDEBUG(D_CCONS)
-                       printf(
-                       "cons_output: isop 0x%x cmask 0x%x negmask 0x%x, chan 0x%x\n",
-                       isop, isop->isop_chanmask, isop->isop_negchanmask, chan);
-               ENDDEBUG
-               ASSERT( chan != 0);
-#ifdef ARGO_DEBUG
-               copcb = cons_chan_to_pcb( chan, __LINE__ );
-#else ARGO_DEBUG
-               copcb = cons_chan_to_pcb( chan );
-#endif ARGO_DEBUG
-       }
-       if( copcb == (struct cons_pcb *)0 ) {
-               /* get a new one */
-
-               if(( error = cons_pcballoc(&dummysocket, &cons_isopcb, CONSF_OCRE, 
-                                                                                               TP_proto, &copcb)) != EOK ) {
-                       IFDEBUG(D_CCONS)
-                               printf("cosns_output: no copcb; returns 0x%x\n", error);
-                       ENDDEBUG
-                       (void) m_freem (m);
-                       splx(s);
-                       return error ;
-               }
-
-               /* abbreviated form of iso_pcbconnect(): */
-               bcopy((caddr_t)&isop->isop_faddr, (caddr_t)&copcb->co_faddr, 
-                                                                       sizeof(struct sockaddr_iso));
-
-               if ( error = cons_connect( copcb ) ) { /* if it doesn't work */
-                       /* oh, dear, throw packet away */
-                       remque((struct isopcb *)copcb);
-                       (void) m_free(dtom(copcb));
-                       (void) m_freem( m );
-                       splx(s);
-                       return error;
-               }
-
-               if( copcb->co_socket ) {
-                       while( (copcb->co_state != OPEN) && 
-                               !(error = copcb->co_socket->so_error) ) {
-                               IFDEBUG(D_CCONS)
-                                       printf(
-       "SLEEP1 copcb 0x%x isop 0x%x state 0x%x chan 0x%x mask 0x%x neg 0x%x\n",
-                                               copcb, isop, copcb->co_state, copcb->co_channel, 
-                                               ((struct isopcb *)isop)->isop_chanmask,
-                                               ((struct isopcb *)isop)->isop_negchanmask
-                                       );
-                               ENDDEBUG
-                               tsleep( (caddr_t)&copcb->co_state, PZERO+1,
-                                       SLP_ISO_CONSOUT, 0);
-                               IFDEBUG(D_CCONS)
-                                       printf("AFTER SLEEP 1 chan 0x%x chanmask 0x%x negchanmask 0x%x\n",
-                                               copcb->co_channel, isop->isop_chanmask, 
-                                               isop->isop_negchanmask);
-                               ENDDEBUG
-                       }
-                       if( !error )
-                               SET_CHANMASK( isop, copcb->co_channel);
-               }
-
-       } 
-
-       IFDEBUG(D_CDATA)
-               printf("cons_output calling senddata(0x%x 0x%x)\n", copcb, m);
-               ASSERT(m != MNULL);
-               ASSERT(m->m_len != 0);
-       ENDDEBUG
-
-       if( !error )
-               error =  cons_senddata( copcb, m);
-       splx(s);
-       return error;
-}
-
-/*
- * NAME:       cons_openvc()
- * CALLED FROM:
- *  TP when it decides to open a VC for TP 0
- * FUNCTION:
- *  opens a connection and stashes the pcb info in the socket
- *  substitute for iso_pcbconnect/ in_pcbconnect for the class 0 case
- *  only.
- */
-int
-cons_openvc(copcb, faddr, so)
-       struct cons_pcb                         *copcb;
-       struct  sockaddr_iso    *faddr;
-       struct  socket                  *so;
-{
-       int                                     error = 0;
-       int                                     s = splnet();
-       struct cons_pcb                 *cons_chan_to_pcb();
-
-
-       ASSERT( copcb->co_socket == so );
-       IFTRACE(D_CCONN)
-               tptrace(TPPTmisc, "cons_openvc( copcb so )\n", copcb, so, 0, 0);
-       ENDTRACE
-       IFDEBUG(D_CCONN)
-               printf("cons_openvc( copcb 0x%x, so 0x%x )\n", copcb,so);
-       ENDDEBUG
-       /*
-        * initialize the copcb part of the isopcb
-        */
-       copcb->co_ttl = copcb->co_init_ttl = X25_TTL;
-       copcb->co_flags = CONSF_OCRE;
-       copcb->co_proto = TP_proto;
-       copcb->co_pending.ifq_maxlen = CONS_IFQMAXLEN;
-
-       /* abbreviated form of iso_pcbconnect(): */
-       bcopy((caddr_t)faddr, (caddr_t)&copcb->co_faddr, 
-                                                               sizeof(struct sockaddr_iso));
-
-       ASSERT( copcb->co_socket == so );
-       if( error = cons_connect( copcb ) )
-               goto done;
-       while( (copcb->co_state != OPEN) && !(error = so->so_error) ) {
-               IFDEBUG(D_CCONS)
-                       printf(
-               "SLEEP2 copcb 0x%x state 0x%x chan 0x%x mask 0x%x neg 0x%x\n",
-                               copcb, copcb->co_state, copcb->co_channel, 
-                               copcb->co_chanmask,
-                               copcb->co_negchanmask
-                       );
-               ENDDEBUG
-               tsleep((caddr_t)&copcb->co_state, PZERO+2, SLP_ISO_CONSCONN, 0);
-               IFDEBUG(D_CCONS)
-                       printf("AFTER SLEEP2 chan 0x%x chanmask 0x%x negchanmask 0x%x\n",
-                               copcb->co_channel, copcb->co_chanmask, 
-                               copcb->co_negchanmask);
-               ENDDEBUG
-       }
-       if( !error )
-               SET_CHANMASK( (struct isopcb *)copcb, copcb->co_channel); 
-done:
-       ASSERT( copcb->co_socket == so );
-       splx(s);
-
-       IFDEBUG(D_CCONN)
-               printf("cons_openvc: copcb 0x%x error 0x%x\n", copcb, error );
-       ENDDEBUG
-       return error;
-}
-
-/*
- * NAME:       cons_netcmd()
- * CALLED FROM:
- *  tp_route_to() when it decides to accept or reject an incoming
- *  connection it calls this.
- * FUNCTION:
- *  either closes the cons connection named by (channel)
- *  or associates the copcb with the channel #.
- *     and removes the old copcb from the tp_incoming_pending list.
- */
-int
-cons_netcmd(cmd, isop, channel, isdgm)
-       int                                     cmd;
-       struct isopcb                   *isop; 
-       int                                             channel;
-{
-       int                                     s = splnet();
-       int                                     error = 0;
-       struct cons_pcb                 *copcb = (struct cons_pcb *)0;
-       struct cons_pcb                 *cons_chan_to_pcb();
-
-       IFTRACE(D_CCONN)
-               tptrace(TPPTmisc, "cons_netcmd( cmd isopcb channel isdgm)\n", 
-                       cmd,isop,channel, isdgm);
-       ENDTRACE
-       IFDEBUG(D_CCONN)
-               printf("cons_netcmd( cmd 0x%x, isop 0x%x, channel 0x%x, isdgm 0x%x)\n", 
-                       cmd,isop,channel, isdgm);
-               if( isop )
-                       printf("cons_netcmd: isop->socket 0x%x\n", 
-                       isop->isop_socket);
-       ENDDEBUG
-       ASSERT(cmd != CONN_OPEN);
-
-       /* Can we find a cons-level pcb based on channel? */
-       if(channel) {
-               if((copcb = 
-#ifdef ARGO_DEBUG
-                       cons_chan_to_pcb( channel, __LINE__ )
-#else ARGO_DEBUG
-                       cons_chan_to_pcb( channel)
-#endif ARGO_DEBUG
-                               ) == (struct cons_pcb *)0) {
-                       error = ECONNABORTED;
-                       splx(s);
-                       return error;
-               }
-               if( copcb == (struct cons_pcb *) isop ) {
-                       copcb = (struct cons_pcb *)0;
-                       /* avoid operating on a pcb twice */
-               } else {
-                       /* if isop is null (close/refuse):
-                        * this would remove from the TP list, which is NOT what we want 
-                        * so only remove if there is an isop (gag)
-                        */
-                       if( isop ) {
-                               remque((struct cons_pcb *)copcb); /* take it off pending list */
-                       } else {
-                               ASSERT( (cmd == CONN_CLOSE) || (cmd == CONN_REFUSE) );
-                       }
-               }
-       }
-       /* now we have one of these cases:
-        * 1) isop is non-null and copcb is null 
-        * 2) isop is non-null and copcb is non-null and they are different
-        * 3) isop is null and copcb is non-null 
-        */
-       ASSERT( (isop != (struct isopcb *)0) || (copcb != (struct cons_pcb *)0));
-
-       switch(cmd) {
-
-               case CONN_CONFIRM:
-                       if( isdgm ) {
-                               /* we want two separate pcbs */
-                               /* if we don't have a copcb, get one */
-
-                               if( copcb == (struct cons_pcb *)0 ) {
-                                       if(( error = cons_pcballoc(&dummysocket, &cons_isopcb, 
-                                               ((struct cons_pcb *)isop)->co_flags,
-                                               TP_proto, &copcb)) != EOK )
-                                                       return error;
-                                       /* copy missing info from isop */
-                                       copcb->co_laddr = isop->isop_laddr;
-                                       copcb->co_faddr = isop->isop_faddr;
-                                       /* don't care about tsuffices */
-                                       ((struct cons_pcb *)isop)->co_channel  = 0; 
-                                                                                               /* no longer used */
-
-                                       copcb->co_ifp = ((struct cons_pcb *)isop)->co_ifp ;
-                                       ASSERT( copcb->co_pending.ifq_len == 0 );
-
-                               } else {
-                                       insque((struct isopcb *)copcb, 
-                                               (struct isopcb *)&cons_isopcb); 
-                               }
-                               copcb->co_state = OPEN;
-                               copcb->co_flags |= CONSF_DGM;
-                               copcb->co_channel = channel;
-                               ASSERT(copcb->co_channel != 0);
-
-                               IFDEBUG(D_CCONN)
-                                       printf("cons_netcmd: put 0x%x on regular list \n", copcb);
-                               ENDDEBUG
-                       } else { 
-                               /* must be TP 0, since this is never called from XTS code */
-                               /* we want ONE pcb, namely isop.
-                                * If this TPE were the active side,
-                                * there ought not to be a copcb, since TP should
-                                * know that you can't send a CR with dgm and negot down
-                                * to non-dgm.
-                                * If this TPE were the passive side, we want to copy from
-                                * the copcb that was on the pending list, and delete the
-                                * pending copcb.
-                                */
-                               if( copcb ) {
-                                       IFDEBUG(D_CCONN)
-                                               printf("cons_netcmd: copied info from 0x%x to 0x%x\n", 
-                                                       copcb, isop);
-                                       ENDDEBUG
-                                       isop->isop_laddr = copcb->co_laddr;
-                                       isop->isop_faddr = copcb->co_faddr;
-                                       /* tsuffices, socket should be there already */
-                                       ((struct cons_pcb *)isop)->co_flags = 
-                                                                       copcb->co_flags & ~CONSF_DGM;
-                                       ((struct cons_pcb *)isop)->co_init_ttl = copcb->co_init_ttl;
-                                       touch(((struct cons_pcb *)isop));
-                                       ((struct cons_pcb *)isop)->co_channel = channel;
-                                       ((struct cons_pcb *)isop)->co_ifp = copcb->co_ifp;
-                                       ((struct cons_pcb *)isop)->co_proto = copcb->co_proto;
-                                       ((struct cons_pcb *)isop)->co_myself = 
-                                               (struct cons_pcb *)isop;
-                                       SET_CHANMASK( isop, ((struct cons_pcb *)isop)->co_channel );
-                                       ASSERT( copcb->co_pending.ifq_len == 0 );
-
-                                       /* get rid of the copcb that was on the pending list */
-                                       (void) m_free(dtom(copcb));
-                               } 
-                               ((struct cons_pcb *)isop)->co_state = OPEN;
-                       }
-                       break;
-
-               case CONN_CLOSE:
-               case CONN_REFUSE:
-                       /* if dgm then ignore; the connections will 
-                        * be re-used or will time out
-                        */
-                       if( isdgm ) 
-                               break;
-
-                       /* we should never come in here with both isop and copcb
-                        * unless is dgm, hence the following assertion:
-                        */
-                       ASSERT( (copcb == (struct cons_pcb *)0) || 
-                               (isop == (struct isopcb *)0) );
-
-                       /* close whichever pcb we have */
-                       if( copcb )
-                               error = cons_clear(copcb, (cmd == CONN_CLOSE)?
-                                       E_CO_HLI_DISCN:E_CO_HLI_REJT);
-                       if( isop )
-                               error = cons_clear((struct cons_pcb *)isop, (cmd == CONN_CLOSE)?
-                                       E_CO_HLI_DISCN:E_CO_HLI_REJT);
-
-                       if(copcb &&  (copcb->co_socket == (struct socket *)0) ) {
-                               ASSERT( copcb->co_flags & (CONSF_DGM | CONSF_ICRE) );
-                               (void) m_free(dtom(copcb)); /* detached */
-                       }
-                       /* isop will always be detached by the higher layer */
-                       break;
-               default:
-                       error = EOPNOTSUPP;
-                       break;
-       }
-       splx(s);
-
-       IFDEBUG(D_CCONN)
-               printf("cons_netcmd returns 0x%x: isop 0x%x\n", isop, error );
-       ENDDEBUG
-       return error;
-}
-
-
-/*
- * NAME:       addr_proto_consistency_check()
- * CALLED FROM: cons_incoming()
- * FUNCTION and ARGUMENTS:
- *  Enforces a set of rules regarding what addresses will serve
- *  what protocol stack.  This is a kludge forced upon us by the
- *  fact that there's no way to tell which NET layer you want to
- *  run when opening a socket.  Besides, no doubt, OSI directory
- *  services won't advertise any kind of a protocol stack with the
- *  NSAPs.  sigh.
- * RETURNS
- *     EAFNOSUPPORT or EOK.
- */
-Static int
-addr_proto_consistency_check(proto, addr) 
-       int                                             proto;
-       struct  sockaddr_iso    *addr;
-{
-       switch( proto ) {
-               case ISOPROTO_CLNP:
-                       break;
-
-               case ISOPROTO_INACT_NL:
-               case ISOPROTO_CLTP:
-                       return E_CO_HLI_PROTOID;
-
-               case ISOPROTO_TP:
-               case ISOPROTO_X25:
-                       /* hl is TP or X.25 */
-                       if (addr->siso_addr.isoa_afi != AFI_37)
-                               return E_CO_AIWP;
-                               /* kludge - necessary because this is the only type of
-                                * NSAP we build for an incoming NC
-                                */
-                       break;
-               default: /* unsupported */
-                       return E_CO_HLI_PROTOID;
-       }
-       return EOK;
-}
-/* 
- * NAME:       cons_incoming()
- * CALLED FROM:
- *  consintr() for incoming OPEN
- * FUNCTION and ARGUMENTS:
- *  Determines which higher layer gets this call, and 
- *  thus whether to immediately accept, reject, or to let the
- *     higher layer determine this question. 
- */
-Static 
-cons_incoming(ifp, ecnrq)
-       struct ifnet                                    *ifp;
-       register struct eicon_request   *ecnrq;
-{
-       struct sockaddr_iso     me;
-       struct sockaddr_iso     peer;
-       struct cons_pcb                 *copcb;
-       int                                     loop = 0;
-       int                                             proto =0;
-       int                                             error = 0;
-       struct  dte_addr                peer_dte;
-
-       IFDEBUG(D_INCOMING)
-               printf("consincoming enter: ifp 0x%x ecnrq 0x%x\n", ifp, ecnrq);
-       ENDDEBUG
-       bzero( &me, sizeof(me));
-       error = parse_facil( mtod(e_data(ecnrq), caddr_t), 
-                                               (e_data(ecnrq))->m_len, &me, &peer, &proto,
-                                               &peer_dte);
-       loop = is_me( &peer ); /* <-- THIS may be a problem :
-                                                       * peer may be nonsense.
-                                                       * We can only expect that WE will do it right
-                                                       * and never will we get an error return from
-                                                       * parse_facil on a facil that WE generated,
-                                                       * so if garbage comes in, peer will be garbage,
-                                                       * and loop will be false.
-                                                       */
-       if( error != EOK ) {
-               (void) issue_clear_req(ecnrq->e_vc, error, ifp, loop); 
-               IncStat(co_parse_facil_err);
-               IncStat(co_Rdrops);
-               return;
-       }
-
-       if( (error = addr_proto_consistency_check(proto, &me)) != EOK ) {
-               /* problem with consistency */
-               (void) issue_clear_req(ecnrq->e_vc, error, ifp, loop);
-               IncStat(co_addr_proto_consist_err);
-               IncStat(co_Rdrops);
-               return;
-       } else {
-               switch( proto ) {
-                       case ISOPROTO_X25:
-                               copcb = (struct cons_pcb *)
-                                               ((struct cons_pcb *)(&cons_isopcb))->co_next;
-
-                               while (copcb != (struct cons_pcb *)&cons_isopcb) {
-                                       if( copcb->co_lport == me.siso_tsuffix ) {
-                                               /* for cons "transport service",
-                                                * multiplexing is not allowed 
-                                                */
-                                               if( !copcb->co_socket ) {
-                                                       printf(
-                                                       "PANIC cons_incoming NOT TP but no sock\n");
-                                                       copcb = (struct cons_pcb *)0;
-                                                       break;
-                                               }
-                                               if( copcb->co_socket->so_options & SO_ACCEPTCONN ) {
-                                                       struct cons_pcb *newx;
-
-                                                       newx = (struct cons_pcb *)
-                                                                       sonewconn(copcb->co_socket)->so_pcb;
-                                                       newx->co_laddr = copcb->co_laddr;
-                                                       newx->co_peer_dte = peer_dte;
-                                                       newx->co_proto = copcb->co_proto;
-                                                       newx->co_myself = newx;
-                                                       touch(copcb);
-                                                       copcb = newx;
-                                                       soisconnected(copcb->co_socket); 
-                                                       break;
-                                               } /* else keep looking */ 
-                                       }
-                                       copcb = (struct cons_pcb *)copcb->co_next;
-                               }
-                               if (copcb == (struct cons_pcb *)&cons_isopcb)
-                                       copcb = (struct cons_pcb *) 0;
-                               break;
-
-                       case ISOPROTO_TP:
-                               ASSERT( me.siso_tsuffix == 0 );
-                               /*
-                                * We treat this rather like we do for CLNP.  
-                                * TP can't tell which socket
-                                * wants this until the TP header comes in, so there's no way
-                                * to associate this channel with a tpcb/isopcb.
-                                * We assume data will arrive (a CR TPDU) and be given to TP along with
-                                * the channel number.  We can then expect TP to call us with
-                                * the channel number and pcb ptr, telling us to keep this connection
-                                * or clear it.
-                                * Now, tp will have created an isopcb in the tp_isopcb list.
-                                * We will have to keep another copcb though, because there is no
-                                * 1-1 correspondence between socket and copcb when multiplexing
-                                * is allowed. 
-                                * But we want to save the peer address, ifp, and state, proto.
-                                * If the channel should clear before TP responds, we need
-                                * to know that also, so we create a tp-pending list...
-                                */
-                               if( cons_pcballoc(&dummysocket, &tp_incoming_pending, 
-                                                               CONSF_ICRE, TP_proto, &copcb) != EOK )  {
-                                       copcb = (struct cons_pcb *)0;
-                               } else {
-                                       copcb->co_peer_dte = peer_dte;
-                               }
-                               break;
-
-
-                       case ISOPROTO_CLNP:
-                               if( cons_pcballoc(&dummysocket, &cons_isopcb, 
-                                               CONSF_ICRE | CONSF_DGM, CLNP_proto, &copcb ) != EOK ) {
-                                       /* choke */
-                                       copcb = (struct cons_pcb *)0;
-                               } else {
-                                       copcb->co_peer_dte = peer_dte;
-                               }
-                               break;
-
-               default:
-                       panic("cons_incoming");
-               } /* end switch */
-
-               if(copcb) {
-                       touch(copcb);
-                       copcb->co_channel = (int)ecnrq->e_vc;
-                       ASSERT( copcb->co_channel != 0);
-                       copcb->co_state = OPEN;
-                       copcb->co_ifp = ifp;
-                       copcb->co_laddr = me;
-                       copcb->co_faddr = peer;
-                       if(loop)
-                               copcb->co_flags |= CONSF_LOOPBACK;
-                       IFDEBUG(D_CADDR)
-                               printf("cons_incoming found XPCB 0x%x, loop 0x%x\n", 
-                                               copcb, loop);
-                               printf("\nco_laddr: ");
-                               dump_buf(&copcb->co_laddr, sizeof(copcb->co_laddr));
-                               printf("\nco_faddr: ");
-                               dump_buf(&copcb->co_faddr, sizeof(copcb->co_faddr));
-                               printf("\n");
-                       ENDDEBUG
-               } else {
-                       ifp->if_ierrors ++;
-                       (void) issue_clear_req(ecnrq->e_vc, E_CO_OSI_UNSAP, ifp, loop);
-                       IncStat(co_no_copcb);
-                       IncStat(co_Rdrops);
-               }
-       } 
-       /* caller frees the mbuf so we don't have to do any such thing */
-}
-
-/*
- **************************** DEVICE cons ***************************
- */
-
-/*
- * NAME:       cosns_output()
- * CALLED FROM:
- *  clnp - this routine is given as the device-output routine
- *  for the adcom driver.
- * FUNCTION and ARGUMENTS:
- *  (ifp) is the cons/adcom, found by routing function.
- *  (m0) is the clnp datagram.
- *  (dst) is the destination address
- * This routine finds an x.25 connection for datagram use and
- * sends the packet.
- */
-int
-cosns_output(ifp, m0, dst)
-{
-       return cosns_output1(ifp, m0, dst, CLNP_proto, NULL);
-}
-
-/* DEBUGGING ONLY? */
-int    total_cosns_len = 0;
-int    total_cosns_cnt = 0;
-int    total_pkts_to_clnp = 0;
-
-/*
- *             The isop is passed here so that if we have set x25crud in the
- *             pcb, it can be passed down to cons_connect. It could be null
- *             however, in the case of tp4/x25/clnp
- */
-Static int
-cosns_output1(ifp, m0, dst, proto, isop)
-       struct ifnet *ifp;
-       register struct mbuf *m0;
-       struct sockaddr_iso *dst;
-       struct protosw *proto;
-       struct isopcb   *isop;          /* NULL if coming from clnp */
-{
-       register struct cons_pcb *copcb;
-       int                                     s = splnet();
-       int                                             error = 0;
-
-       {       register struct mbuf *n=m0;
-               register int len = 0;
-
-               for(;;) {
-                       len += n->m_len;
-                       if (n->m_next == MNULL ) {
-                               break;
-                       }
-                       n = n->m_next;
-               }
-               total_cosns_len += len;
-               total_cosns_cnt ++;
-
-       }
-
-       IFDEBUG(D_CCONS)
-               printf("cosns_output1( ifp 0x%x, m 0x%x, dst 0x%x )\n", ifp, m0, dst );
-       ENDDEBUG
-       if ( ! (copcb = cons_find( CONSF_DGM, dst, proto, 0, 0) )) {
-               struct cons_pcb *newcopcb; /* so we can pass addr of this to pcballoc */
-
-               if( (error = cons_pcballoc(&dummysocket, &cons_isopcb, 
-                               CONSF_DGM | CONSF_OCRE, proto, &newcopcb) )  != EOK ) {
-                       IFDEBUG(D_CCONS)
-                               printf("cosns_output: no copcb; returns \n");
-                       ENDDEBUG
-                       (void) m_freem(m0);
-                       goto done;
-               }
-               copcb = newcopcb;
-
-               /* abbreviated form of iso_pcbconnect(): */
-               bcopy((caddr_t)dst, (caddr_t)&copcb->co_faddr, 
-                                                                       sizeof(struct sockaddr_iso));
-               
-               /* copy x25crud into copcb if necessary */
-               if ((isop != NULL) && (isop->isop_x25crud_len > 0)) {
-                       bcopy(isop->isop_x25crud, copcb->co_x25crud, 
-                               isop->isop_x25crud_len);
-                       copcb->co_x25crud_len = isop->isop_x25crud_len;
-               }
-
-               copcb->co_ifp = ifp; /* NULL IF COMING FROM TP4! */
-
-               if ( error = cons_connect( copcb ) ) { /* if it doesn't work */
-                       /* oh, dear, throw packet away */
-                       remque((struct isopcb *)copcb);
-                       (void) m_free(dtom(copcb));
-                       (void) m_freem(m0);
-                       goto done;
-               }
-       }
-       IFDEBUG(D_CDATA)
-               printf("cosns_output1 @ senddata: state 0x%x flags 0x%x channel 0x%x\n",
-                       copcb->co_state, copcb->co_flags, copcb->co_channel);
-       ENDDEBUG
-       ASSERT(copcb->co_channel != X_NOCHANNEL);
-       error = cons_senddata(copcb, m0); 
-done:
-       splx(s);
-       return error;
-}
-
-
-/*
- **************************** TRANSPORT cons ***************************
- */
-
-
-/*
- * NAME:       cons_detach()
- * CALLED FROM:
- *  cons_usrreq() on PRU_DETACH
- *  cons_netcmd() when TP releases a net connection
- *     cons_slowtimo()  when timeout releases a net connection
- * FUNCTION and ARGUMENT:
- *  removes the copcb from the list of copcbs in use, and frees the mbufs.
- *  detaches the pcb from the socket, where a socket exists.
- * RETURN VALUE:
- *  ENOTCONN if it couldn't find the copcb in the list of connections.
- */
-
-Static int 
-cons_detach( copcb )
-       register struct cons_pcb *copcb;
-{
-       struct socket *so = copcb->co_socket;
-
-       IFDEBUG(D_CCONN)
-               printf("cons_detach( copcb 0x%x )\n", copcb);
-       ENDDEBUG
-       if(so) {
-               if (so->so_head) {
-                       if (!soqremque(so, 0) && !soqremque(so, 1))
-                               panic("sofree dq");
-                       so->so_head = 0;
-               }
-               ((struct isopcb *)copcb)->isop_options = 0; /* kludge */
-               iso_pcbdetach(copcb); /* detaches from so */
-       } else {
-               remque((struct isopcb *)copcb);
-               (void) m_free(dtom(copcb));
-       }
-}
-
-Static int
-cons_clear_and_detach(copcb, clearreason, ctlcmd)
-       register struct cons_pcb *copcb;
-       int                                     clearreason;
-       int                                             ctlcmd;
-{
-       IFDEBUG(D_CCONN)
-               printf("Clear and Detach (0x%x, 0x%x, 0x%x)\n", 
-                                               copcb, clearreason, ctlcmd);
-       ENDDEBUG
-       if( clearreason != DONTCLEAR ) {
-               (void) cons_clear( copcb ,  clearreason );
-       }
-       if( copcb->co_proto  && copcb->co_proto->pr_ctlinput )
-               (*copcb->co_proto->pr_ctlinput)(ctlcmd, 
-                       (struct sockaddr_iso *)&copcb->co_faddr, (caddr_t)copcb);
-
-       if( copcb->co_socket == (struct socket *)0 ) {
-               /* tp4, clnp users only */
-               (void) cons_detach( copcb );
-       } /* else detach will be called by the socket's closing */
-               else {
-                       ASSERT( copcb->co_socket != &dummysocket );
-                       ASSERT( (copcb->co_flags & CONSF_DGM) == 0 );
-       }
-       IFDEBUG(D_CCONN)
-               printf("END OF Clear and Detach (0x%x, 0x%x, 0x%x)\n", 
-                                               copcb, clearreason, ctlcmd);
-       ENDDEBUG
-}
-
-Static int
-cons_pcbbind( copcb, nam )
-       register struct cons_pcb *copcb;
-       struct mbuf *nam;
-{
-       int error;
-
-       if( error = iso_pcbbind( copcb, nam) )
-               return error;
-
-       /* iso_pcbbind already ensured that if port < 1024 it's superuser */
-       /* Now we check: must be in range 0 .. 23 or in range 1024 .. 99 */
-
-       if( (copcb->co_lport < X25_PORT_RESERVED)  || 
-                        ((copcb->co_lport >= ISO_PORT_RESERVED) && 
-                         (copcb->co_lport <= X25_PORT_USERMAX))) {
-               munge( copcb->co_lport, (&copcb->co_laddr)->siso_addr.t37_idi +
-                       ADDR37_IDI_LEN, 1 /* nibble */);
-               munge( copcb->co_fport, (&copcb->co_faddr)->siso_addr.t37_idi +
-                       ADDR37_IDI_LEN, 1 /* nibble */);
-                return 0;
-       } else 
-               return EADDRNOTAVAIL;
-}
-/*
- * NAME:       cons_usrreq()
- * CALLED FROM:
- *  user level via proto switch
- * FUNCTION and ARGUMENTS:
- *  so : socket
- *  req: which PRU* request
- *  m : data or mbuf ptr into which to stash data
- *     nam: mbuf ptr which is really a sockaddr_iso
- *  ifq: in PRU_CONTROL case, an ifnet structure 
- * RETURN VALUE:
- *  ENOTCONN if trying to do something which requires a connection
- *      and it's not yet connected
- *  EISCONN if trying to do something which cannot be done to a connection
- *      but it's connected
- *     ENOBUFS if ran out of mbufs
- *     EWOULDBLOCK if in nonblocking mode & can't send right away
- *     EOPNOSUPP if req isn't supported
- *     E* other passed up from lower layers or from other routines
- */
-
-cons_usrreq(so, req, m, nam, ifp)
-       struct socket *so;
-       u_int req;
-       struct mbuf *m, *nam;
-       int *ifp; 
-{      
-       struct cons_pcb *copcb =  (struct cons_pcb *)so->so_pcb;
-       int                                     s = splnet();
-       int                                     error = 0;
-
-       IFDEBUG(D_CCONS)
-               printf("cons_usrreq 0x%x so 0x%x copcb 0x%x\n", req, so, copcb);
-       ENDDEBUG
-       if (req == PRU_CONTROL) {
-               error =  iso_control(so, (int)m, (caddr_t)nam, (struct ifnet *)ifp);
-               splx(s);
-               return error;
-       }
-       if (copcb == (struct cons_pcb *)0  &&  req != PRU_ATTACH) {
-               splx(s);
-               return ENOTCONN;
-       }
-
-       switch (req) {
-
-       case PRU_ATTACH:
-               if (copcb) {
-                       error = EISCONN;
-                       break;
-               }
-               soreserve(so, X25_SBSIZE, X25_SBSIZE); /* CONS size */
-               error = cons_pcballoc(so, &cons_isopcb, CONSF_XTS, X25_proto, &copcb );
-               break;
-
-       case PRU_ABORT:         /* called from close() */
-               /* called for each incoming connect queued on the parent (accepting) 
-                * socket (SO_ACCEPTCONN); 
-                */
-                error = cons_detach ( copcb );
-                break;
-
-       case PRU_DETACH:        /* called from close() */
-               /* called after disconnect was called iff was connected at the time
-                * of the close, or directly if socket never got connected */
-               error = cons_detach ( copcb );
-               break;
-
-       case PRU_SHUTDOWN:
-               /* recv end may have been released; local credit might be zero  */
-       case PRU_DISCONNECT:
-               soisdisconnected(so);
-                       error = cons_clear(copcb, E_CO_HLI_DISCN); 
-               break;
-
-       case PRU_BIND:
-               error = cons_pcbbind( copcb, nam);
-               break;
-
-       case PRU_LISTEN:
-               if (copcb->co_lport == 0) 
-                       error = cons_pcbbind( copcb, 0 );
-               break;
-
-
-       case PRU_SOCKADDR: {
-                       struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *);
-
-                       nam->m_len = sizeof (struct sockaddr_iso);
-                       if(copcb->co_ifp) 
-                               bcopy( (caddr_t)&copcb->co_laddr,
-                                               (caddr_t)siso, sizeof(struct sockaddr_iso) );
-
-                       ((struct sockaddr_iso *)siso)->siso_tsuffix = copcb->co_lport;
-               }
-               break;
-
-       case PRU_PEERADDR:
-               if( (so->so_state & SS_ISCONNECTED) && 
-                       (so->so_state & SS_ISDISCONNECTING) == 0) {
-                               struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *);
-
-                       nam->m_len = sizeof (struct sockaddr_iso);
-                       bcopy( (caddr_t)&copcb->co_faddr, (caddr_t)siso, 
-                                                                       sizeof(struct sockaddr_iso) );
-               } else 
-                       error = ENOTCONN;
-               break;
-
-       case PRU_CONNECT:
-               /* TODO: We need to bind to the RIGHT interface. 
-                * The only way to have the right interface is to have
-                * the right route.
-                */
-               IFDEBUG(D_CCONN)
-                       printf("PRU_CONNECT 1: local tsuffix 0x%x so->so_head 0x%x nam:\n", 
-                               copcb->co_lport, so->so_head);
-                       dump_isoaddr( mtod(nam, struct sockaddr_iso *) );
-               ENDDEBUG
-               if (copcb->co_lport == 0) {
-                       if( error = cons_pcbbind( copcb, 0 ))
-                               break;
-               }
-               IFDEBUG(D_CCONN)
-                       printf("PRU_CONNECT 2: local tsuffix 0x%x so->so_head 0x%x nam:\n", 
-                               copcb->co_lport, so->so_head);
-                       dump_isoaddr( mtod(nam, struct sockaddr_iso *) );
-               ENDDEBUG
-
-               {       /* change the destination address so the last 2 digits
-                        * are the port/suffix/selector (whatever you want to call it)
-                        */
-                       register struct sockaddr_iso *siso =
-                                                       mtod(nam, struct sockaddr_iso *);
-                       if( (siso->siso_tsuffix < X25_PORT_RESERVED)  || 
-                                ((siso->siso_tsuffix >= ISO_PORT_RESERVED) && 
-                                 (siso->siso_tsuffix <= X25_PORT_USERMAX)))
-                       munge( siso->siso_tsuffix, 
-                                       siso->siso_addr.t37_idi + ADDR37_IDI_LEN, 
-                                       1 /* nibble */);
-               }
-               
-               soisconnecting(so);
-               if (error = iso_pcbconnect(copcb, nam))
-                       break;
-               error = cons_connect( copcb );
-               if ( error ) {
-                       /*
-                       remque((struct isopcb *)copcb);
-                       (void) m_free(dtom(copcb));
-                       */
-                       break;
-               }
-               while( (copcb->co_state != OPEN)&&(copcb->co_socket->so_error == 0) ) {
-                       IFDEBUG(D_CCONN)
-                               printf("PRU_CONNECT: error 0x%x sleeping on 0x%x\n", 
-                                       copcb->co_socket->so_error,
-                                       (caddr_t)&copcb->co_state );
-                       ENDDEBUG
-                       sleep((caddr_t)&copcb->co_state, PZERO+3, SLP_ISO_CONS, 0 );
-               }
-
-               ASSERT( copcb->co_channel != 0);
-
-               SET_CHANMASK ( (struct isopcb *)copcb, copcb->co_channel);
-               break;
-
-       case PRU_ACCEPT: 
-               /* so here is the NEW socket */
-               so->so_error = 0;
-               if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTED)== 0) {
-                       error = EWOULDBLOCK;
-                       break;
-               }
-               {
-                       struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *);
-
-                       /* copy the peer's address into the return argument */
-                       nam->m_len = sizeof (struct sockaddr_iso);
-                       bcopy( (caddr_t)&copcb->co_faddr, (caddr_t)siso, 
-                               sizeof(struct sockaddr_iso));
-               }
-               break;
-
-       case PRU_SEND:
-       case PRU_SENDEOT:
-               /*
-                * sosend calls this until sbspace goes negative.
-                * Sbspace may be made negative by appending this mbuf chain,
-                * possibly by a whole cluster.
-                */
-               {
-                       /* no need to actually queue this stuff and dequeue it,
-                        * just bump the pointers in so_snd so that higher
-                        * layer of socket code will cause it to sleep when
-                        * we've run out of socket space
-                        * TODO:
-                        * Unfortunately that makes sbflush vomit so we have
-                        * to allocate a single real mbuf (say size 240)
-                        * and sballoc it and sbfree it upon CONS_SEND_DONE.
-                        * Oh, my, is this sickening or what?
-                        */
-                       {
-                               struct mbuf *mx;
-                               
-                               MGET(mx, M_DONTWAIT, MT_DATA);
-                               mx->m_len = MLEN;
-                               sbappend((caddr_t)&copcb->co_socket->so_snd, mx);
-                       }
-                       if( m ) {
-                               IFDEBUG(D_CDATA)
-                                       printf("X.25 Usrreq calling cons_senddata(0x%x, 0x%x)\n",
-                                               copcb, m);
-                               ENDDEBUG
-                               error = cons_senddata(copcb, m);
-                       }
-                       IFDEBUG(D_CCONS)
-                               printf("PRU_SEND sent tsuffix 0x%x, m 0x%x error 0x%x\n", 
-                                       copcb->co_lport, m, error);
-                       ENDDEBUG
-
-                       if( req == PRU_SENDEOT ) {
-                               while(copcb->co_socket->so_snd.sb_cc > 0)
-                                       sbwait(&copcb->co_socket->so_snd);
-                       }
-               }
-               break;
-
-       case PRU_CONTROL:
-               error = cons_ioctl(so, m, (caddr_t)nam);
-               break;
-
-
-       case PRU_RCVD:
-       case PRU_RCVOOB:
-       case PRU_SENDOOB:
-               /* COULD support INTERRUPT packets as oob */
-       case PRU_PROTOSEND:
-       case PRU_PROTORCV:
-       case PRU_SENSE:
-       case PRU_SLOWTIMO:
-       case PRU_CONNECT2:
-       case PRU_FASTTIMO:
-       default:
-               error = EOPNOTSUPP;
-       }
-
-       IFDEBUG(D_CCONS)
-               printf("cons_usrreq cmd 0x%x copcb 0x%x returned error 0x%x\n", 
-                       req, copcb, error);
-       ENDDEBUG
-       splx(s);
-       return error;
-}
-
-/*
- * NAME:       cons_input()
- * CALLED FROM:
- *  consintr() through the isosw protosw for "transport" version of X25
- * FUNCTION & ARGUMENTS:
- *  process incoming data
- */
-cons_input(m, faddr, laddr, so)
-       register struct mbuf *m;
-       struct sockaddr_iso *faddr, *laddr; /* not used */
-       register struct socket *so;
-{
-       IFDEBUG(D_CCONS)
-               printf("cons_input( m 0x%x, so 0x%x)\n", m,so);
-       ENDDEBUG
-       sbappend(&so->so_rcv, m);
-       sbwakeup(&so->so_rcv);
-}
-
-#ifdef notdef
-/*  
- * NAME:       cons_ctloutput()
- * CALLED FROM:
- *  set/get sockopts()
- *     Presently the protosw has 0 in the ctloutput spot
- *      because we haven't inplemented anything yet.
- *     If there's reason to put some options in here,
- *     be sure to stick this routine name in the protosw in iso_proto.c
- */
-cons_ctloutput(cmd, so, level, optname, mp)
-       int                     cmd, level, optname;
-       struct socket   *so;
-       struct mbuf     **mp;
-{
-       int                     s = splnet();
-
-       splx(s);
-       return EOPNOTSUPP;
-}
-#endif notdef
-
-
-/* 
- * NAME:       cons_ctlinput()
- * CALLED FROM:
- *  lower layer when ECN_CLEAR occurs : this routine is here
- *  for consistency - cons subnet service calls its higher layer
- *  through the protosw entry.
- * FUNCTION & ARGUMENTS:
- *  cmd is a PRC_* command, list found in ../sys/protosw.h
- *  copcb is the obvious.
- *  This serves the higher-layer cons service.
- * NOTE: this takes 3rd arg. because cons uses it to inform itself
- *  of things (timeouts, etc) but has a pcb instead of an address.
- */
-cons_ctlinput(cmd, sa, copcb)
-       int cmd;
-       struct sockaddr *sa;
-       register struct cons_pcb *copcb;
-{
-       int                     error = 0;
-       int                     s = splnet();
-       extern u_char   inetctlerrmap[];
-       extern int              iso_rtchange();
-
-       IFDEBUG(D_CCONS)
-               printf("cons_ctlinput( cmd 0x%x, copcb 0x%x)\n", cmd, copcb);
-       ENDDEBUG
-       /* co_socket had better exist */
-       switch (cmd) {
-               case PRC_CONS_SEND_DONE:
-                       ASSERT( copcb->co_socket );
-                       ASSERT( copcb->co_flags & CONSF_XTS );
-                       sbdrop((caddr_t)&copcb->co_socket->so_snd, MLEN);
-                       sbwakeup((caddr_t)&copcb->co_socket->so_snd);
-                       break;
-
-               case PRC_ROUTEDEAD:
-                       error = ENETUNREACH;
-                       break;
-
-               case PRC_TIMXCEED_REASS:
-                       error = ETIMEDOUT;
-                       break;
-
-       /*
-               case PRC_QUENCH:
-                       iso_pcbnotify(&cons_pcb, sa,
-                                       (int)inetctlerrmap[cmd], iso_rtchange);
-                       iso_pcbnotify(&tp_incoming_pending, sa,
-                                       (int)inetctlerrmap[cmd], tpiso_quench);
-                       iso_pcbnotify(&tp_isopcb, sa,
-                                       (int)inetctlerrmap[cmd], tpiso_quench);
-       */
-
-               case PRC_IFDOWN:
-                       iso_pcbnotify(&cons_isopcb, sa,
-                                       (int)inetctlerrmap[cmd], iso_rtchange);
-                       iso_pcbnotify(&tp_incoming_pending, sa,
-                                       (int)inetctlerrmap[cmd], iso_rtchange);
-                       iso_pcbnotify(&tp_isopcb, sa,
-                                       (int)inetctlerrmap[cmd], iso_rtchange);
-                       break;
-
-
-               default:
-                       printf("cons_ctlinput: unknown cmd 0x%x\n", cmd);
-       }
-       if(error) {
-               soisdisconnected(copcb->co_socket);
-               sohasoutofband(copcb->co_socket);
-       }
-       splx(s);
-}
-
-/*
- *********************** SERVES ALL cons embodiments  *******************
- */
-
-/* 
- * NAME:       cons_chan_to_pcb()
- * CALLED FROM:
- *  cons_chan_to_tpcb() in tp_cons.c
- * and in this file: incoming requests that give only a channel number, i.e.,
- *  ECN_ACCEPT, ECN_RECEIVE, ECN_CLEAR
- * FUNCTION:
- *  identify the pcb assoc with that channel
- * RETURN:
- *  ptr to the pcb
- */
-struct cons_pcb *
-#ifdef ARGO_DEBUG
-cons_chan_to_pcb( channel, linenumber )
-       int     linenumber;
-#else ARGO_DEBUG
-cons_chan_to_pcb( channel)
-#endif ARGO_DEBUG
-       register int channel;
-{
-       register struct cons_pcb **copcblist = (struct cons_pcb **)Xpcblist;
-       register struct cons_pcb *copcb;
-
-       /* just to be sure */
-       channel = channel & 0xff;
-
-       for( copcb = *copcblist; copcb; copcb = *(++copcblist) ) {
-               copcb = (struct cons_pcb *)copcb->co_next;
-               while (copcb !=  *copcblist) {
-                       if ( copcb->co_channel == channel ) 
-                               goto found; /* want to break out of both loops */
-
-                       copcb = (struct cons_pcb *)copcb->co_next;
-               }
-       }
-found: /* or maybe not... */
-       IFDEBUG(D_CCONS)
-               printf("cons_chan_to_pcb( 0x%x, %d ) %s 0x%x\n", channel, linenumber,
-                       copcb?"FOUND":"FAILED", copcb);
-       ENDDEBUG
-
-       return copcb;
-}
-
-
-/*
- * NAME:       is_me()
- * CALLED FROM:
- *  cons_incoming().  Perhaps could just expand in line.
- * FUNCTION and ARGUMENTS:
- *     for the given remote address (remadr) if it exactly matches
- *  one of the addresses of ME, and I am up as loopback, 
- *  return TRUE, else return FALSE.
- * RETURNS:
- *  Boolean
- */
-Static int
-is_me(remaddr)
-       struct  sockaddr_iso    *remaddr;
-{
-       struct  ifnet                   *ifp = consif;
-                                                                       /* PHASE2: this is ok */
-       struct ifaddr                   *ifa = ifa_ifwithaddr(remaddr);
-
-       IFDEBUG(D_CADDR)
-               printf("is_me: withaddr returns %s\n", 
-                       ifa?ifa->ifa_ifp->if_name:"NONE");
-       ENDDEBUG
-       if( ifa ) {
-               /* remaddr matches one of my interfaces exactly */
-               if( ifa->ifa_ifp->if_flags & IFF_LOOPBACK ) {
-                       ASSERT( ifp == ifa->ifa_ifp );
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-find_error_reason( ecnrq )
-       register struct eicon_request   *ecnrq;
-{
-       extern u_char x25_error_stats[];
-       int error;
-       struct mbuf *cdm;
-       struct e_clear_data *ecd;
-
-       cdm = e_data(ecnrq);
-       if( cdm && cdm->m_len > 0 ) {
-               ecd = mtod(cdm, struct e_clear_data *);
-               switch( ecd->ecd_cause ) {
-                       case 0x00:
-                       case 0x80:
-                               /* DTE originated; look at the diagnostic */
-                               error = (CONL_ERROR_MASK | ecd->ecd_diagnostic);
-                               goto done;
-
-                       case 0x01: /* number busy */
-                       case 0x81:
-                       case 0x09: /* Out of order */
-                       case 0x89:
-                       case 0x11: /* Remot Procedure Error */
-                       case 0x91:
-                       case 0x19: /* reverse charging accept not subscribed */
-                       case 0x99:
-                       case 0x21: /* Incampat destination */
-                       case 0xa1:
-                       case 0x29: /* fast select accept not subscribed */
-                       case 0xa9:
-                       case 0x39: /* ship absent */
-                       case 0xb9:
-                       case 0x03: /* invalid facil request */
-                       case 0x83:
-                       case 0x0b: /* access barred */
-                       case 0x8b:
-                       case 0x13: /* local procedure error */
-                       case 0x93:
-                       case 0x05: /* network congestion */
-                       case 0x85:
-                       case 0x8d: /* not obtainable */
-                       case 0x0d:
-                       case 0x95: /* RPOA out of order */
-                       case 0x15:
-                               /* take out bit 8 
-                                * so we don't have to have so many perror entries 
-                                */
-                               error = (CONL_ERROR_MASK | 0x100 | (ecd->ecd_cause & ~0x80));
-                               goto done;
-
-                       case 0xc1: /* gateway-detected proc error */
-                       case 0xc3: /* gateway congestion */
-
-                               error = (CONL_ERROR_MASK | 0x100 | ecd->ecd_cause);
-                               goto done;
-               } 
-       } 
-       /* otherwise, a *hopefully* valid perror exists in the e_reason field */
-       error = ecnrq->e_reason;
-       if (error = 0) {
-               printf("Incoming PKT TYPE 0x%x with reason 0x%x\n",
-                       ecnrq->e_cmd,
-                       ecnrq->e_reason);
-               error = E_CO_HLI_DISCA;
-       } 
-
-done:
-       if(error & 0x1ff == 0) {
-               error = 0;
-       } else if( error & 0x1ff > sizeof(x25_error_stats)) {
-                       ASSERT(0);
-       } else {
-                       x25_error_stats[error& 0x1ff] ++;
-       }
-       return error;
-}
-
-/*
- * NAME:       consintr()
- * CALLED FROM:
- *  the eicon driver via software interrupt
- * FUNCTION and ARGUMENTS:
- *  processes incoming indications, passing them
- *  along to clnp, tp, or x.25-transport as appropriate.
- */
-consintr()
-{
-       struct  ifnet                                   *ifp = consif;
-       register struct eicon_request   *ecnrq;
-       register struct cons_pcb                *copcb = (struct cons_pcb *)0;
-       register struct mbuf                    *m;
-       int                                                     s, s0 = splnet();
-
-       IncStat(co_intr);
-       ifp->if_ipackets ++;
-
-       for(;;) {
-               /*
-                * Get next request off input queue 
-                */
-               s = splimp();
-               IF_DEQUEUE(&consintrq, m);
-               splx(s);
-               IFDEBUG(D_INCOMING)
-                       printf("cons intr() 0x%x m_off 0x%x m_len 0x%x dequeued\n",
-                               m, m?m->m_off:0, m?m->m_len:0);
-               ENDDEBUG
-
-               if (m == 0) {
-                       splx(s0);
-                       return;
-               }
-
-               if((m->m_off != MMINOFF)||(m->m_len != sizeof (struct eicon_request))){
-                       ifp->if_ierrors ++;
-                       IncStat(co_Rdrops);
-                       printf("Cons R DROP! BAD MBUF FROM LL 0x%x sizeof(...) 0x%x\n", 
-                                       m, sizeof(struct eicon_request));
-                       continue;
-               }
-               
-               ecnrq = mtod(m, struct eicon_request *);
-
-
-               IFDEBUG(D_INCOMING)
-                       printf("INTR: e_cmd 0x%x, e_data 0x%x\n", ecnrq->e_cmd,
-                               e_data(ecnrq));
-                       if( e_data(ecnrq) != 0 ) {
-                               /* let's just look at the first few bytes */
-                               /*
-                               dump_buf( e_data(ecnrq), (e_data(ecnrq))->m_len + 12);
-                               */
-                               dump_buf( e_data(ecnrq), 20  + 12);
-                       }
-               ENDDEBUG
-               IFTRACE(D_CDATA)
-                       tptrace( TPPTmisc, "INTR: req_type m lun\n", 
-                               ecnrq->e_cmd, m, ecnrq->e_vc, 0);
-               ENDTRACE
-
-               switch( ecnrq->e_cmd ) {
-
-                       case ECN_ACK:  /* data put on the board */
-                               IncStat(co_ack);
-                               ASSERT( ecnrq->e_vc != 0);
-                               /* from ACKWAIT to OPEN */
-                               if ( (copcb = 
-#ifdef ARGO_DEBUG
-                                       cons_chan_to_pcb( (int)ecnrq->e_vc, __LINE__ )
-#else ARGO_DEBUG
-                                       cons_chan_to_pcb( (int)ecnrq->e_vc )
-#endif ARGO_DEBUG
-                                                                               ) == (struct cons_pcb *)0 )
-                                       break;
-                               copcb->co_state = OPEN; 
-                               /*
-                                * Anything on the pending queue for this connection?
-                                */
-                               if( copcb->co_pending.ifq_len == 0 ) {
-                                       if( copcb->co_proto->pr_ctlinput )
-                                               /* for the sake of higher layer protocol (tp) */
-                                               (*copcb->co_proto->pr_ctlinput)
-                                                       (PRC_CONS_SEND_DONE, 
-                                                       (struct sockaddr_iso *)&copcb->co_faddr, 
-                                                       (caddr_t)copcb);
-                               } else {
-                                       register struct mbuf *m0;
-
-                                       s = splimp();
-                                       IF_DEQUEUE( &copcb->co_pending, m0 );
-                                       splx(s);
-                                       /* CAN ONLY DO 1 item here
-                                        * if you change this if to while, HA HA 
-                                        * it'll go right back onto
-                                        * the pending queue (which means things will
-                                        * be reordered on the queue!)
-                                        */
-                                       if( m0 ) {
-                                               IFDEBUG(D_CDATA)
-                                                       printf("ACK sending pending queue 0x%x len 0x%x\n",
-                                                               m0, m0->m_len);
-                                               ENDDEBUG
-                                               ASSERT( m0->m_len != 0);
-                                               (void) cons_senddata(copcb, m0); 
-                                       }
-                               }
-
-                               /* send more? */
-                               break;
-
-                       case ECN_ACCEPT:  /* call accepted at other end */
-                               /* adr_src, adr_dst are as given in the ECN_CALL
-                                * pcb field is copied from our ECN_CALL
-                                * request, confirm gives me a channel number
-                                */ 
-                               ASSERT( ecnrq->e_vc != 0);
-
-                               IncStat(co_accept);
-                               if(copcb = 
-#ifdef ARGO_DEBUG
-                               cons_chan_to_pcb((int)ecnrq->e_vc, __LINE__ )
-#else ARGO_DEBUG
-                               cons_chan_to_pcb((int)ecnrq->e_vc)
-#endif ARGO_DEBUG
-                                                                                               ) { 
-                                       /* error: already exists */
-                                       printf("cons PANIC: dbl confirm for channel 0x%x\n",
-                                               ecnrq->e_vc);
-                                       break;
-                               }
-                               copcb = (struct cons_pcb *)ecnrq->e_pcb;
-                               if( copcb->co_myself != copcb ) {
-                                       struct mbuf *mm;
-                                       /* TODO: REMOVE */
-                                       ASSERT(0);
-                                       printf("BAD e_pcb from ecn (0x%x) cmd 0x%x\n", 
-                                               ecnrq->e_pcb, ecnrq->e_cmd);
-                                       mm = dtom( copcb );
-                                       if(mm->m_type == MT_FREE)
-                                               printf("FREED MBUF!\n");
-                                       dump_buf (ecnrq, sizeof (*ecnrq));
-                                       panic("BAD ecnrq");
-                                       break;
-                               }
-                               touch(copcb);
-                               copcb->co_state = OPEN;
-                               copcb->co_channel = (int)ecnrq->e_vc;
-                               if(copcb->co_socket) {
-                                       /* tp0 will take care of itself */
-                                       if( copcb->co_flags & CONSF_XTS)
-                                               soisconnected(copcb->co_socket); /* wake 'em up */
-                               }
-                               wakeup( (caddr_t)&copcb->co_state );
-
-                               /*
-                                * Anything on the pending queue for this connection?
-                                */
-                               if( copcb->co_pending.ifq_len > 0 ) {
-                                       register struct mbuf *m0;
-
-                                       s = splimp();
-                                       IF_DEQUEUE( &copcb->co_pending, m0 );
-                                       splx(s);
-                                       /* CAN ONLY DO 1 item here
-                                        * if you change this if to while, HA HA 
-                                        * it'll go right back onto
-                                        * the pending queue (which means things will
-                                        * be reordered on the queue!)
-                                        */
-                                       if( m0 ) {
-                                               IFDEBUG(D_CDATA)
-                                                       printf("ACPT sending pending queue 0x%x len 0x%x\n",
-                                                               m0, m0->m_len);
-                                               ENDDEBUG
-                                               ASSERT( m0->m_len != 0);
-                                               (void) cons_senddata(copcb, m0); 
-                                       }
-                               }
-                               break;
-
-                       case ECN_REFUSE: 
-                               /* other end refused our connect request */
-                               /* src, dst are as given in the ECN_CALL */
-
-                               IncStat(co_refuse);
-                               copcb = (struct cons_pcb *)ecnrq->e_pcb;
-                               if( copcb->co_myself != copcb ) {
-                                       struct mbuf *mm;
-                                       /* TODO: REMOVE */
-                                       ASSERT(0);
-                                       printf("BAD e_pcb from ecn (0x%x) cmd 0x%x\n", 
-                                               ecnrq->e_pcb, ecnrq->e_cmd);
-                                       mm = dtom( copcb );
-                                       if(mm->m_type == MT_FREE)
-                                               printf("FREED MBUF!\n");
-                                       dump_buf (ecnrq, sizeof (*ecnrq));
-                                       dump_buf (copcb, sizeof (*copcb));
-                                       panic("BAD ecnrq");
-                                       break;
-                               }
-                               touch(copcb);
-                               copcb->co_state = CLOSED; /* do we have to do a clear?? */
-                               copcb->co_channel = X_NOCHANNEL;
-                               if(copcb->co_socket) {
-                                       copcb->co_socket->so_error = ECONNREFUSED;
-                                       /* TODO: if there's diagnostic info in the 
-                                        * packet, and it's more useful than this E*,
-                                        * get it
-                                        */
-                                       soisdisconnected(copcb->co_socket); /* wake 'em up */
-                                       IFDEBUG(D_INCOMING)
-                                               printf("ECN_REFUSE: waking up 0x%x\n", 
-                                                       (caddr_t)&copcb->co_state );
-                                       ENDDEBUG
-                                       wakeup( (caddr_t)&copcb->co_state );
-                               }
-                               /*
-                                * Anything on the pending queue for this connection?
-                                */
-                               while( copcb->co_pending.ifq_len > 0 ) {
-                                       register struct mbuf *m0;
-
-                                       s = splimp();
-                                       IF_DEQUEUE( &copcb->co_pending, m0 );
-                                       splx(s);
-                                       m_freem(m0);
-                               }
-                               if ( ecnrq->e_reason  == E_CO_NORESOURCES ) {
-                                       IncStat(co_noresources);
-                                       cons_clear_and_detach( copcb, DONTCLEAR, PRC_QUENCH );
-                               } else if(copcb->co_socket ) {
-                                       copcb->co_socket->so_error = find_error_reason( ecnrq );
-                               }
-                               break;
-
-                       case ECN_CONNECT:  /* incoming call */
-                               /*
-                                * ECN_CONNECT indication gives adc_src, adc_dst  and channel
-                                */
-                               ASSERT( ecnrq->e_vc != 0);
-
-                               IncStat(co_connect);
-                               cons_incoming(ifp, ecnrq); 
-                               break;
-
-                       case ECN_RESET:  
-                       case ECN_CLEAR:
-                               /*
-                                * ECN_CLEAR(indication) (if we can construct such a beast)
-                                * gives e_vc, 
-                                * Throw away anything queued pending on this connection
-                                * give a reset indication to the upper layer if TP
-                                * free the mbufs 
-                                */
-                               ASSERT( ecnrq->e_vc != 0);
-                               if( ecnrq->e_cmd == ECN_CLEAR )
-                                       IncStat(co_clear_in);
-                               else
-                                       IncStat(co_reset_in);
-#ifdef ARGO_DEBUG
-                               if( ! (copcb=cons_chan_to_pcb((int)ecnrq->e_vc, __LINE__)) )
-#else ARGO_DEBUG
-                               if( ! (copcb=cons_chan_to_pcb((int)ecnrq->e_vc)) )
-#endif ARGO_DEBUG
-
-                                       break;
-                               while( copcb->co_pending.ifq_len ) {
-                                       register struct mbuf *m0;
-
-                                       s = splimp();
-                                       IF_DEQUEUE( &copcb->co_pending, m0 );
-                                       splx(s);
-                                       m_freem(m0);
-                               }
-                               copcb->co_state = CLOSED; /* do we have to do a clear? */
-                               copcb->co_channel = X_NOCHANNEL;
-
-                               cons_clear_and_detach( copcb, DONTCLEAR, PRC_ROUTEDEAD );
-                               if (copcb->co_socket ) {
-                                       copcb->co_socket->so_error = find_error_reason( ecnrq ); 
-                               }
-                               break;
-                               
-                       case ECN_RECEIVE:
-                                /*
-                                 * ECN_RECEIVE (read) 
-                                 */
-                               ASSERT( ecnrq->e_vc != 0);
-                               IncStat(co_receive);
-                               {
-                                       /* TODO: REMOVE */
-                                       struct mbuf *thedata = e_data(ecnrq);
-                                       u_int *firstint = mtod( thedata, u_int *);
-                                       
-                                       if( (*firstint & 0xff000000) != 0x81000000 ) {
-                                               /* not clnp */
-                                               switch( ((*firstint) & 0x00ff0000) >> 20 ) {
-                                               case 0x1:
-                                               case 0x2:
-                                               case 0x3:
-                                               case 0x6:
-                                               case 0x7:
-                                               case 0x8:
-                                               case 0xc:
-                                               case 0xd:
-                                               case 0xe:
-                                               case 0xf:
-                                                       break;
-                                               default:
-                                                       printf(" ECN_RECEIVE! BAD DATA\n" );
-                                                       dump_buf( thedata, 20 + 12 );
-                                                       m_freem( m );
-                                                       splx(s0);
-                                               }
-                                       }
-                               }
-                               if ( (copcb = 
-#ifdef ARGO_DEBUG
-                                       cons_chan_to_pcb( (int)ecnrq->e_vc, __LINE__ )
-#else ARGO_DEBUG
-                                       cons_chan_to_pcb( (int)ecnrq->e_vc )
-#endif ARGO_DEBUG
-                                                                                       ) == (struct cons_pcb *)0 ) {
-                                       ifp->if_ierrors ++;
-                                       IFTRACE(D_CDATA)
-                                               tptrace(TPPTmisc, "ECN_RECEIVE DROPPED chan \n",
-                                                       ecnrq->e_vc, 0, 0, 0);
-                                       ENDTRACE
-                                       break;
-                               }
-
-                               touch(copcb);
-                               if( ecnrq->e_info & ECN_INFO_RCVD_INT )  {
-                                       /* interrupt packet */
-                                               printf("consintr: interrupt pkttype : DROPPED\n");
-                                       IncStat(co_intrpt_pkts_in);
-                                       IncStat(co_Rdrops);
-                                       break;
-                               }
-                               /* new way */
-                               if( copcb->co_proto == CLNP_proto ) 
-                               {
-                                       /* IP: put it on the queue and set soft interrupt */
-                                       struct ifqueue *ifq;
-                                       extern struct ifqueue clnlintrq;
-                                       register struct mbuf *ifpp; /* for ptr to ifp */
-                                       register struct mbuf *data = e_data(ecnrq);
-
-                                       total_pkts_to_clnp ++;
-
-                                       /* when acting as a subnet service, have to prepend a
-                                        * pointer to the ifnet before handing this to clnp
-                                        * GAG
-                                        */
-                                       if( ( data->m_off > MMINOFF + sizeof(struct snpa_hdr)) &&
-                                               ( data->m_off <= MMAXOFF )) {
-                                               data->m_off -= sizeof(struct snpa_hdr);
-                                               data->m_len += sizeof(struct snpa_hdr);
-                                       } else {
-                                               MGET(ifpp, M_DONTWAIT, MT_XHEADER);
-                                               if( !ifpp ) {
-                                                       ifp->if_ierrors ++;
-                                                       splx(s0);
-                                                       m_freem(m); /* frees everything */
-                                                       return; 
-                                               }
-                                               ifpp->m_len = sizeof(struct snpa_hdr);
-                                               ifpp->m_act = 0;
-                                               ifpp->m_next = data;
-                                               data = ifpp;
-                                       }
-                                       IFTRACE(D_CDATA)
-                                               tptrace(TPPTmisc, "-->CLNP copcb\n", copcb, 0, 0, 0);
-                                       ENDTRACE
-                                       {
-                                               /*
-                                                *      TODO: if we ever use esis/cons we have to
-                                                *      think of something reasonable to stick in the
-                                                *      snh_shost,snh_dhost fields. I guess
-                                                *      the x.121 address is what we want.
-                                                *
-                                                *      That would also require length fields in the
-                                                *      snpa_hdr structure.
-                                                */
-                                               struct snpa_hdr         *snh = 
-                                                       mtod(data, struct snpa_hdr *);
-                                               bzero((caddr_t)&snh, sizeof(struct snpa_hdr));
-                                               bcopy((caddr_t)&ifp, (caddr_t)&snh->snh_ifp, 
-                                                       sizeof(struct ifnet *));
-                                       }
-                                       *( mtod(data, struct ifnet **) ) = ifp; /* KLUDGE */
-
-                                       ifq = &clnlintrq;
-                                       splimp();
-                                       if (IF_QFULL(ifq)) {
-                                               IF_DROP(ifq);
-                                               m_freem(m);
-                                               IFDEBUG(D_INCOMING)
-                                                       printf("DROPPED! ecnrq 0x%x, data 0x%x\n", m,data);
-                                               ENDDEBUG
-                                               splx(s0);
-                                               ifp->if_ierrors ++;
-                                               return;
-                                       }
-                                       IF_ENQUEUE(ifq, data);
-                                       IFDEBUG(D_INCOMING) 
-                                               printf(
-                               "0x%x enqueued on ip Q: m_len 0x%x m_type 0x%x m_off 0x%x\n", 
-                                                       data, data->m_len, data->m_type, data->m_off);
-                                               dump_buf(mtod(data, caddr_t), data->m_len);
-                                       ENDDEBUG
-                                       e_data(ecnrq) = (struct mbuf *)0;
-                                       schednetisr(NETISR_CLNP);
-                               } else {
-                                       /* HL is NOT clnp */
-                                       IFTRACE(D_CDATA)
-                                               tptrace(TPPTmisc,
-                                                       "-->HL pr_input so copcb channel\n", 
-                                                       copcb->co_proto->pr_input, 
-                                                       copcb->co_socket, copcb, 
-                                                       copcb->co_channel);
-                                       ENDTRACE
-                                       IFDEBUG(D_INCOMING) 
-                                               printf( "0x%x --> HL proto 0x%x chan 0x%x\n", 
-                                                       e_data(ecnrq), copcb->co_proto, copcb->co_channel );
-                                       ENDDEBUG
-
-                                       (*copcb->co_proto->pr_input)(e_data(ecnrq), 
-                                               &copcb->co_faddr,
-                                               &copcb->co_laddr,
-                                               copcb->co_socket, /* used by cons-transport interface */
-                                               (copcb->co_flags & CONSF_DGM)?0:
-                                                       copcb->co_channel);/* used by tp-cons interface */
-
-                                       /* 
-                                        * the pr_input will free the data chain, so we must
-                                        * zero the ptr to is so that m_free doesn't panic
-                                        */
-                                       e_data(ecnrq) = (struct mbuf *)0;
-                               }
-                               break;
-
-                       default:
-                               /* error */
-                               ifp->if_ierrors ++;
-                               printf("consintr: unknown request\n");
-               }
-               IFDEBUG(D_INCOMING)
-                       printf("consintr: m_freem( 0x%x )\n", m);
-               ENDDEBUG
-               m_freem( m );
-       }
-       splx(s0);
-}
-
-/*
- * Process an ioctl request.
- * also set-time-limit, extend-time-limit
- * for ALL channels, the time-limit ioctls will be done by open-a-dummy-socket,
- * do ioctl with the channel number, close the socket (dumb!).
- */
-/* ARGSUSED */
-cons_ioctl(so, cmd, data)
-       struct socket *so;
-       int cmd;
-       caddr_t data;
-{
-       int     s = splnet();
-       int     error = 0;
-
-       IFDEBUG(D_CCONS)
-               printf("cons_ioctl( cmd 0x%x )\n", cmd);
-       ENDDEBUG
-
-#ifdef notdef
-       switch (cmd) {
-
-       default:
-#endif notdef
-               error = EOPNOTSUPP;
-#ifdef notdef
-       }
-#endif notdef
-
-       splx(s);
-       return (error);
-}
-
-
-/*
- *************************************************************
- *                                                           *
- *                                                           *
- * Interface to CO Subnetwork service from CLNP              *
- * Must be a device interface.                             *****
- *                                                          *** 
- *                                                           *
- *                                                          Poof!
- */
-
-/*
- * NAME:       consioctl()
- * CALLED FROM:
- *     called through the ifnet structure.
- * FUNCTION and ARGUMENTS:
- *     the usual ioctl stuff
- * RETURNS:
- *     E*
- * SIDE EFFECTS:
- * NOTES:
- */
-consioctl(ifp, cmd, data)
-       register struct ifnet *ifp;
-       register int cmd;
-       register caddr_t data;
-{
-       register struct ifaddr          *ifa = (struct ifaddr *)data;
-       register int                            s = splimp();
-       register struct ifreq           *ifr = (struct ifreq *)data;
-       register int                            error = 0;
-       void                                            consshutdown();
-
-       switch (cmd) {
-       case SIOCSIFADDR:
-               switch (ifa->ifa_addr.sa_family) {
-               case AF_ISO:
-                       if( (ifp->if_flags & IFF_UP ) == 0)
-                               consinit(ifp->if_unit);
-                       break;
-               default:
-                       printf("CANNOT config cons with address family %d\n",
-                               ifa->ifa_addr.sa_family);
-                       break;
-               }
-               break;
-       case SIOCSIFFLAGS:
-               IFDEBUG(D_CCONS)
-                       printf("consioctl: set flags to x%x\n", ifr->ifr_flags);
-                       printf("consioctl: ifp flags are x%x\n", ifp->if_flags);
-               ENDDEBUG
-               if( ifr->ifr_flags & IFF_LOOPBACK )
-                       ifp->if_flags |= IFF_LOOPBACK;
-               else
-                       ifp->if_flags &= ~IFF_LOOPBACK;
-
-               /* if board is down but request takes it up, init the board */
-               if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0)
-                       consinit(ifp->if_unit);
-
-               /* if board is up but request takes it down, shut the board down */
-               if (((ifr->ifr_flags & IFF_UP) == 0) && (ifp->if_flags & IFF_UP)) {
-                       consshutdown(ifp->if_unit);
-               }
-               IFDEBUG(D_CCONS)
-                       printf("consioctl: flags are x%x\n", ifp->if_flags);
-               ENDDEBUG
-               break;
-       case SIOCGSTATUS:
-               /* warning: must coerse ifp to (struct ifstatus *) in order to use */
-               IFDEBUG(D_CCONS)
-                       printf("consioctl: EICON status request\n");
-               ENDDEBUG
-#if NECN>0
-               ecnioctl(ifp, cmd, data);
-#else 
-               error = ENODEV;
-#endif NECN>0
-               break;
-       default:
-               error = EINVAL;
-       }
-       splx(s);
-       return error;
-}
-
-/*
- * NAME:       consattach()
- * CALLED FROM:
- *     cons_init() (which comes from autoconf)
- * FUNCTION and ARGUMENTS:
- *     creates an ifp and fills it in; calls ifattach() on it. 
- * RETURNS:
- *  no return value
- * SIDE EFFECTS:
- * NOTES:
- */
-consattach()
-{
-       register struct ifnet           *ifp;
-       register struct mbuf            *m;
-
-       if(sizeof(struct ifnet) > MLEN) {
-               printf("Can't attach cons!  sizeof(struct ifnet) > MLEN\n");
-               return;
-       }
-       MGET(m, M_DONTWAIT, MT_IFADDR);
-       if( !m ) {
-               printf("Can't attach cons!  NO MBUFS!\n");
-               return;
-       }
-       m->m_len = sizeof(struct ifnet);
-       ifp = consif = mtod(m, struct ifnet *); 
-       ifp->if_unit = 0;
-       ifp->if_name = "cons";
-       ifp->if_mtu = ECN_MTU;
-       ifp->if_init = consinit;
-       ifp->if_ioctl = consioctl;
-       ifp->if_output = cosns_output; /* called by clnp */
-       ifp->if_flags = IFF_LOOPBACK;  /* default */
-       if_attach(ifp); 
-       printf("cons%d: pseudo device attached \n", ifp->if_unit);
-}
-
-/*
- * NAME:       consinit()
- * CALLED FROM:
- *     consioctl()
- * FUNCTION and ARGUMENTS:
- *     Initializes apropos data structures, etc.
- *  Marks the device as up.
- *  Zaps the address list.
- *  Calls device layer restart on the device if necessary.
- */
-Static
-consinit(_unit)
-register int   _unit;  /* unit to initialize */
-{
-       struct ifnet                    *ecnifp();
-       struct ifnet                    *ifp;
-       int             s;
-
-       if ((ifp = ecnifp(_unit)) != (struct ifnet *)0 ) {
-               ecnrestart(ifp);
-               IncStat(co_restart);
-       }
-       if (consif->if_addrlist == (struct ifaddr *)0)
-               return;
-       if ((consif->if_flags & IFF_UP) == 0) {
-               s = splimp();
-               consif->if_flags |= IFF_UP;
-               splx(s);
-       }
-
-}
-
-/* 
- * NAME:       consshutdown()
- * CALLED FROM:
- *     cons_ioctl() when user takes down an interface w/ SIOCSIFFLAGS 
- * FUNCTION and ARGUMENTS:
- *  calls lower layer shutdown routine on the device.
- *  and marks the if as down if the if is the sw loopback pseudodevice.
- * RETURNS:
- *     no return value
- */
-void
-consshutdown(_unit)
-register int   _unit;  /* unit to shutdown */
-{
-       extern  struct ifnet    *ecnifp();
-       struct ifnet                    *ifp;
-       int                                     s;
-
-       if ((ifp = ecnifp(_unit)) != (struct ifnet *)0 ) {
-               ecnshutdown(ifp);
-       }
-       if ((consif->if_flags & IFF_UP) ) {
-               s = splimp();
-               consif->if_flags &= ~IFF_UP;
-               splx(s);
-       }
-}
-#endif KERNEL
-
-/*
- * NAME:       munge()
- * CALLED FROM:
- *     cons_pcbbind(), cons_usrreq()
- * FUNCTION and ARGUMENTS:
- *  Takes the argument (value) and stashes it into the last two
- *  nibbles of an X.121 address.  Does this in the two nibbles beginning
- *  at the location defined by the character pointer (dst_octet) and the 
- *  integer (dst_nibble).  Nibble 0 is the lower nibble (high
- *  order 4 bits); nibble 1 is the low order 4 bits of *(dst_octet).
- *
- * RETURNS:
- *     no return value
- */
-Static 
-munge( value, dst_octet, dst_nibble)
-       int value;
-       caddr_t dst_octet;
-       int dst_nibble;
-{
-       IFDEBUG(D_CCONN)
-               printf("MUNGE: value 0x%x dst_octet 0x%x, nibble 0x%x)\n",
-                       value, dst_octet, dst_nibble);
-       ENDDEBUG
-       if (value >= ISO_PORT_RESERVED)
-               value -= 1000;
-
-       {
-               /* convert so it  looks like a decimal number */
-               register int tens, ones;
-
-               tens = value/10;
-               ASSERT( tens <= 9 );
-               ones = value - (tens * 10);
-
-               value = tens * 16 + ones;
-       }
-
-       dst_octet --;
-       /* leave nibble same 'cause it's one after the last set nibble */
-
-       *dst_octet &= ~(0xff<<(dst_nibble << 2)); /* zero it */
-       *dst_octet |= ((value>>4) << (dst_nibble<<2));
-       dst_nibble = 1-dst_nibble;
-       dst_octet += dst_nibble;
-
-       *dst_octet &= ~(0xff<<(dst_nibble << 2)); /* zero it */
-       *dst_octet |= ((value&0xff) << (dst_nibble<<2));
-} 
-
-/*
- * NAME:       unmunge()
- * CALLED FROM:
- *  DTEtoNSAP(), FACILtoNSAP()
- * FUNCTION and ARGUMENTS:
- *  return the port/tsuffix represented by the two digits found in a
- *  bcd string beginning at the (dst_nibble)th nibble of the
- *  octet BEFORE (dst_octet).
- *  
- * dst_octet,dst_nibble  is the nibble after the one we'll look at
- * RETURNS:
- *  an integer, the port/tsuffix
- *  Note- converts to a port > 1000 if necessary.
- */
-Static int
-unmunge( dst_octet, dst_nibble )
-       caddr_t dst_octet;
-       int dst_nibble;
-{
-               register u_short last = 0;
-
-               dst_octet --;
-               /* leave nibble same 'cause it's one after the last set nibble */
-               IFDEBUG(D_CADDR)
-                       printf("unmunge: *octet 0x%x, nibble 0x%x\n", *dst_octet,
-                               dst_nibble);
-               ENDDEBUG
-
-               last = ((*dst_octet) & (0xff<<(dst_nibble<<2)));
-               dst_nibble = 1-dst_nibble;
-               dst_octet += dst_nibble;
-
-               last |= ((*dst_octet) & (0xff<<(dst_nibble << 2)));
-               {
-                       /* convert to a decimal number */
-                       register int tens, ones;
-
-                       tens = (last&0xf0)>>4;
-                       ones = last&0xf;
-
-                       last = tens * 10 + ones;
-               }
-
-               IFDEBUG(D_CADDR)
-                       printf("unmunge computes 0x%x\n", last);
-               ENDDEBUG
-               if((int)last+1000 >= ISO_PORT_RESERVED)
-                       last += 1000;
-               IFDEBUG(D_CADDR)
-                       printf("unmunge returns 0x%x\n", last);
-               ENDDEBUG
-               return last;
-} 
-
-/*
- * NAME:       make_partial_x25_packet()
- *
- * FUNCTION and ARGUMENTS:
- *     Makes part of an X.25 call packet, for use by the eicon board.
- *  (src) and (dst) are the NSAP-addresses of source and destination.
- *     (proto) is the higher-layer protocol number (in iso.h)
- *     (buf) is a ptr to a buffer into which to write this partial header.
- *
- *  The partial header looks like (choke):
- *     octet           meaning
- *  1                  calling DTE len  |  called DTE len (lengths in nibbles)
- *  2..n-1             called DTE addr  | (<-- boundary may be middle of an octet)
- *                     calling DTE addr  | zero nibble to round to octet boundary.
- *     n                       Facility length (in octets)
- *     n+1                     Facility field, which is a set of:
- *       m                     facil code
- *       m+1           facil param len (for >2-byte facilities) in octets
- *       m+2..p        facil param field
- *  q                  user data (protocol identification octet)
- * 
- *
- * RETURNS: 
- *  0 if OK
- *  E* if failed.
- */
-
-#ifdef X25_1984 
-int cons_use_facils = 1;
-#else X25_1984 
-int cons_use_facils = 0;
-#endif X25_1984 
-
-int cons_use_udata = 1; /* KLUDGE FOR DEBUGGING */
+int cons_use_udata = 1; /* KLUDGE FOR DEBUGGING */
 
 Static int
 
 Static int
-make_partial_x25_packet(copcb, m)
-       struct cons_pcb *copcb;
-       struct mbuf *m;
+make_partial_x25_packet(isop, lcp)
+       struct isopcb *isop;
+       struct pklcd *lcp;
 {
 {
-       struct sockaddr_iso     *src, *dst;
        u_int                           proto;
        int                                     flag;
        u_int                           proto;
        int                                     flag;
-       caddr_t                         buf = mtod(m, caddr_t);
-       register caddr_t        ptr     = buf + 1;  /* make room for 2 length nibbles */
+       caddr_t                         buf;
+       register caddr_t        ptr;
        register int            len     = 0;
        int                             buflen  =0;
        caddr_t                         facil_len;
        int                             oddness = 0;
        register int            len     = 0;
        int                             buflen  =0;
        caddr_t                         facil_len;
        int                             oddness = 0;
-
-       src = &copcb->co_laddr;
-       dst = &copcb->co_faddr;
-       proto = copcb->co_proto->pr_protocol, 
-       flag = copcb->co_flags & CONSF_XTS;
+       struct mbuf *m;
 
 
        IFDEBUG(D_CCONN)
                printf("make_partial_x25_packet(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
 
 
        IFDEBUG(D_CCONN)
                printf("make_partial_x25_packet(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
-                       src, dst, proto, m, flag);
+                       isop->isop_laddr, isop->isop_faddr, proto, m, flag);
        ENDDEBUG
        ENDDEBUG
-       
-       /*
-        * Note - order of addrs in x25 pkt hdr is wierd: 
-        * calling len/called len/called addr/calling addr (p.40 ISO 8202)
-        */
-       if( (len = copcb->co_peer_dte.dtea_niblen) > 0 ) {
-               nibble_copy( (char *)(copcb->co_peer_dte.dtea_addr), HIGH_NIBBLE,
-                       ptr, HIGH_NIBBLE, len);
-       } else {
-               if ((len =  NSAPtoDTE( ptr, HIGH_NIBBLE, dst)) <=0 ) {
-                       return E_CO_OSI_UNSAP;
+       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;
                }
        }
                }
        }
-       *buf = len; /* fill in called dte addr length */
-       ptr += len>>1; /* len is in nibbles */
-       oddness += len&0x1;
-
-       if ((len =  NSAPtoDTE( ptr, 1-(len&0x1), src)) <=0 ) {
-               return E_CO_OSI_UNSAP;
-       }
-       ptr += len>>1; /* len is in nibbles */
-       *buf |= len << 4; /* fill in calling dte addr length */
-       oddness += len&0x1;
 
 
-       IFDEBUG(D_CADDR)
-               printf("make_partial  2: ptr 0x%x, len 0x%x oddness 0x%x\n", 
-                       ptr, len, oddness );
-       ENDDEBUG
-       /* if either of the addresses were an odd length, the count is off by 1 */
-       if( oddness ) {
-               ptr ++;
+       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, 
 
        IFDEBUG(D_CADDR)
                printf("make_partial  calling: ptr 0x%x, len 0x%x\n", ptr, 
-                               src->siso_addr.isoa_len);
+                               isop->isop_laddr->siso_addr.isoa_len);
        ENDDEBUG
        ENDDEBUG
-       if( cons_use_facils ) {
+       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
-                               */
-               len = src->siso_addr.isoa_len;
-               bcopy( &src->siso_addr.isoa_afi, ptr, len);
-               *(ptr-2) = len+2; /* facil param len in octets */
+                                * 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);
+               *(ptr-2) = len+1; /* facil param len in octets */
                *(ptr-1) = len<<1; /* facil param len in nibbles */
                ptr += len;
 
                IFDEBUG(D_CADDR)
                        printf("make_partial  called: ptr 0x%x, len 0x%x\n", ptr, 
                *(ptr-1) = len<<1; /* facil param len in nibbles */
                ptr += len;
 
                IFDEBUG(D_CADDR)
                        printf("make_partial  called: ptr 0x%x, len 0x%x\n", ptr, 
-                                       dst->siso_addr.isoa_len);
+                                       isop->isop_faddr->siso_addr.isoa_len);
                ENDDEBUG
                *ptr = 0xc9; /* called facility code */
                ptr ++;
                ptr ++; /* leave room for facil param len (in OCTETS + 1) */
                ptr ++; /* leave room for the facil param len (in nibbles),
                ENDDEBUG
                *ptr = 0xc9; /* called 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
-                               */
-               len = dst->siso_addr.isoa_len;
-               bcopy( &dst->siso_addr.isoa_afi, ptr, len);
-               *(ptr-2) = len+2; /* facil param len = addr len + 1 for each of these
+                                * high two bits of which indicate full/partial NSAP
+                                */
+               len = isop->isop_faddr->siso_nlen;
+               bcopy(isop->isop_faddr->siso_data, ptr, len);
+               *(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;
 
        }
        *facil_len = ptr - facil_len - 1;
                                                  * two length fields, in octets */
                *(ptr-1) = len<<1; /* facil param len in nibbles */
                ptr += len;
 
        }
        *facil_len = ptr - facil_len - 1;
-       if(*facil_len > X25_FACIL_LEN_MAX )
+       if (*facil_len > MAX_FACILITIES)
                return E_CO_PNA_LONG;
 
                return E_CO_PNA_LONG;
 
-       if( cons_use_udata ) {
-               if (copcb->co_x25crud_len > 0) {
-                       /*
-                        *      The user specified something. Stick it in
-                        */
-                       bcopy(copcb->co_x25crud, ptr, copcb->co_x25crud_len);
-                       ptr += copcb->co_x25crud_len;
-               } else {
-                       /* protocol identifier */
-                       switch (proto) {
-                                       /* unfortunately all are considered 1 protocol */
-                               case ISOPROTO_TP0: 
-                               case ISOPROTO_TP1:
-                               case ISOPROTO_TP2:
-                               case ISOPROTO_TP3:
-                               case ISOPROTO_TP4:
-                               case ISOPROTO_CLTP:
-                                       /* no user data for TP */
-                                       break;
-
-                               case ISOPROTO_CLNP:
-                                       *ptr = 0x81;
-                                       ptr++; /* count the proto id byte! */
-                                       break;
-                               case ISOPROTO_INACT_NL:
-                                       *ptr = 0x0;
-                                       ptr++; /* count the proto id byte! */
-                                       break;
-                               case ISOPROTO_X25:
-                                       *ptr = 0xff; /* reserved for future extensions */
-                                                 /* we're stealing this value for local use */
-                                       ptr++; /* count the proto id byte! */
-                                       break;
-                               default:
-                                       return EPROTONOSUPPORT;
-                       }
-               }
-       }
-
        buflen = (int)(ptr - buf);
 
        IFDEBUG(D_CDUMP_REQ)
        buflen = (int)(ptr - buf);
 
        IFDEBUG(D_CDUMP_REQ)
@@ -3555,12 +668,11 @@ make_partial_x25_packet(copcb, m)
                        mtod(m, caddr_t), buflen);
        ENDDEBUG
 
                        mtod(m, caddr_t), buflen);
        ENDDEBUG
 
-       ASSERT( X25_PARTIAL_PKT_LEN_MAX < MLEN );
-
-       if(buflen > X25_PARTIAL_PKT_LEN_MAX)
+       if (buflen > MHLEN)
                return E_CO_PNA_LONG;
 
                return E_CO_PNA_LONG;
 
-       m->m_len = buflen;
+       m->m_pkthdr.len = m->m_len = buflen;
+       lcp->lcd_facilities = m;
        return  0;
 }
 
        return  0;
 }
 
@@ -3576,50 +688,64 @@ make_partial_x25_packet(copcb, m)
  *  (addr) is the NSAP-address
  *  (flag) is true if the transport suffix is to become the
  *             last two digits of the DTE address
  *  (addr) is the NSAP-address
  *  (flag) is true if the transport suffix is to become the
  *             last two digits of the DTE address
- *  A DTE address is a series of BCD digits
+ *  A DTE address is a series of ASCII digits
  *
  *     A DTE address may have leading zeros. The are significant.
  *             1 digit per nibble, may be an odd number of nibbles.
  *
  *  An NSAP-address has the DTE address in the IDI. Leading zeros are
  *             significant. Trailing hex f indicates the end of the DTE address.
  *
  *     A DTE address may have leading zeros. The are significant.
  *             1 digit per nibble, may be an odd number of nibbles.
  *
  *  An NSAP-address has the DTE address in the IDI. Leading zeros are
  *             significant. Trailing hex f indicates the end of the DTE address.
- *     Also is a series of BCD digits, one per nibble.
+ *     The IDI is a series of BCD digits, one per nibble.
  *
  * RETURNS
  *  # significant digits in the DTE address, -1 if error.
  */
 
 Static int
  *
  * RETURNS
  *  # significant digits in the DTE address, -1 if error.
  */
 
 Static int
-NSAPtoDTE( dst_octet, dst_nibble, addr)
-       caddr_t         dst_octet;
-       int                     dst_nibble;
-       register struct sockaddr_iso *addr;
+NSAPtoDTE(siso, sx25)
+       register struct sockaddr_iso *siso;
+       register struct sockaddr_x25 *sx25;
 {
 {
-       int     error;
-       u_char  x121string[7]; /* maximum is 14 digits */
-       int             x121strlen;
-       struct  dte_addr *dtea;
+       int             dtelen = -1;
 
        IFDEBUG(D_CADDR)
 
        IFDEBUG(D_CADDR)
-               printf("NSAPtoDTE: nsap: %s\n", clnp_iso_addrp(&addr->siso_addr));
+               printf("NSAPtoDTE: nsap: %s\n", clnp_iso_addrp(&siso->siso_addr));
        ENDDEBUG
 
        ENDDEBUG
 
-       error = iso_8208snparesolve(addr, x121string, &x121strlen);
-       ASSERT(error == 0);
-       if(  error != 0 ) {
-               /* no snpa - cannot send */
-               IFDEBUG(D_CADDR)
-                       printf("NSAPtoDTE: 8208resolve: %d\n", error );
-               ENDDEBUG
-               return 0;
-       }
-       ASSERT(x121strlen == sizeof(struct dte_addr));
-       dtea = (struct dte_addr *)x121string;
-       x121strlen = dtea->dtea_niblen;
+       if (siso->siso_data[0] == AFI_37) {
+               register char *out = sx25->x25_addr;
+               register char *in = siso->siso_data + 1;
+               register int nibble;
+               char *lim = siso->siso_data + siso->siso_nlen;
+               char *olim = out+15;
+               int lowNibble = 0;
 
 
-       nibble_copy((char *)x121string, HIGH_NIBBLE, 
-               dst_octet, dst_nibble, x121strlen);
-       return x121strlen;
+               while (in < lim) {
+                       nibble = ((lowNibble ? *in++ : (*in >> 4)) & 0xf) | 0x30;
+                       lowNibble ^= 1;
+                       if (nibble != 0x3f && out < olim)
+                               *out++ = nibble;
+               }
+               dtelen = out - sx25->x25_addr;
+               *out++ = 0;
+       } else {
+               register struct rtentry *rt = rtalloc1(siso, 1);
+               /* error = iso_8208snparesolve(addr, x121string, &x121strlen);*/
+
+               if (rt) {
+                       register struct sockaddr_x25 *sxx =
+                                                       (struct sockaddr_x25 *)rt->rt_gateway;
+                       register char *in = sxx->x25_addr;
+
+                       rt->rt_use--;
+                       if (sxx && sxx->x25_family == AF_CCITT) {
+                               bcopy(sx25->x25_addr, sxx->x25_addr, sizeof(sx25->x25_addr));
+                               while (*in++) {}
+                               dtelen = in - sxx->x25_addr;
+                       }
+               }
+       }
+       return dtelen;
 }
 
 /*
 }
 
 /*
@@ -3628,51 +754,58 @@ NSAPtoDTE( dst_octet, dst_nibble, addr)
  *  parse_facil()
  * FUNCTION and ARGUMENTS:
  *     Creates and NSAP in the sockaddr_iso (addr) from the
  *  parse_facil()
  * FUNCTION and ARGUMENTS:
  *     Creates and NSAP in the sockaddr_iso (addr) from the
- *  x.25 facility found at (buf), of length (buf_len).
+ *  x.25 facility found at buf - 1.
  * RETURNS:
  * RETURNS:
- *  0 if ok, non-zero if error;
+ *  length of parameter if ok, -1 if error.
  */
 
 Static int
  */
 
 Static int
-FACILtoNSAP( buf, buf_len, addr)
-       caddr_t                 buf;
-       u_char                  buf_len; /* in bytes */
+FACILtoNSAP(addr, buf)
+       u_char          *buf;
        register struct sockaddr_iso *addr;
 {
        register struct sockaddr_iso *addr;
 {
-       int len_in_nibbles;
+       int len_in_nibbles, param_len = *buf++;
+       u_char                  buf_len; /* in bytes */
 
        IFDEBUG(D_CADDR)
                printf("FACILtoNSAP( 0x%x, 0x%x, 0x%x )\n", 
                        buf, buf_len, addr );
        ENDDEBUG
 
 
        IFDEBUG(D_CADDR)
                printf("FACILtoNSAP( 0x%x, 0x%x, 0x%x )\n", 
                        buf, buf_len, addr );
        ENDDEBUG
 
-       len_in_nibbles = *buf;
+       len_in_nibbles = *buf & 0x3f;
+       buf_len = (len_in_nibbles + 1) >> 1;
        /* despite the fact that X.25 makes us put a length in nibbles
         * here, the NSAP-addrs are always in full octets
         */
        /* despite the fact that X.25 makes us put a length in nibbles
         * here, the NSAP-addrs are always in full octets
         */
-       buf ++;
+       switch (*buf++ & 0xc0) {
+       case 0:
+               /* Entire OSI NSAP address */
+               bcopy((caddr_t)buf, addr->siso_data, addr->siso_nlen = buf_len);
+               break;
 
 
-       bzero( addr, sizeof (struct sockaddr_iso) );
+       case 40:
+               /* Partial OSI NSAP address, assume trailing */
+               if (buf_len + addr->siso_nlen > sizeof(addr->siso_addr))
+                       return -1;
+               bcopy((caddr_t)buf, TSEL(addr), buf_len);
+               addr->siso_nlen += buf_len;
+               break;
 
 
-       ASSERT(buf_len <= 1+sizeof (struct iso_addr));
-       if(buf_len > 1+sizeof (struct iso_addr)) {
-               return -1; /* error */
-       }
-       ASSERT(len_in_nibbles == (buf_len - 1)<<1);
-       if(len_in_nibbles != (buf_len - 1)<<1) {
-               return -2; /* error */
+       default:
+               /* Rather than blow away the connection, just ignore and use
+                  NSAP from DTE */;
        }
        }
-       bcopy(buf, &addr->siso_addr.isoa_afi, buf_len-1);
-       addr->siso_addr.isoa_len = buf_len-1; 
-       IFDEBUG(D_CADDR)
-               printf("FACILtoNSAP: isoa_len 0x%x\n",
-                       addr->siso_addr.isoa_len);
-       ENDDEBUG
-       addr->siso_family = AF_ISO;
+       return param_len;
+}
 
 
-       addr->siso_tsuffix = 
-               unmunge( ((caddr_t)&addr->siso_addr.t37_idi) + ADDR37_IDI_LEN , 1 );
-       return 0;
+static
+init_siso(siso)
+register struct sockaddr_iso *siso;
+{
+       siso->siso_len = sizeof (*siso);
+       siso->siso_family = AF_ISO;
+       siso->siso_data[0] = AFI_37;
+       siso->siso_nlen = 8;
 }
 
 /*
 }
 
 /*
@@ -3681,67 +814,41 @@ FACILtoNSAP( buf, buf_len, addr)
  *  parse_facil()
  * FUNCTION and ARGUMENTS:
  *  Creates a type 37 NSAP in the sockaddr_iso (addr)
  *  parse_facil()
  * FUNCTION and ARGUMENTS:
  *  Creates a type 37 NSAP in the sockaddr_iso (addr)
- *     from a DTE address found at the (src_nibble)th nibble of
- *     the octet (src_octet), of length (src_nib_len).
+ *     from a DTE address found in a sockaddr_x25.
  *  
  * RETURNS:
  *  0 if ok; E* otherwise.
  */
 
 Static  int
  *  
  * RETURNS:
  *  0 if ok; E* otherwise.
  */
 
 Static  int
-DTEtoNSAP(addr, src_octet, src_nibble, src_nib_len)
+DTEtoNSAP(addr, sx)
        struct sockaddr_iso *addr;
        struct sockaddr_iso *addr;
-       caddr_t src_octet;
-       int src_nibble, src_nib_len;
+       struct sockaddr_x25 *sx;
 {
 {
-       caddr_t                         dst_octet;
-       int                                     pad_len;
-       int                                     dst_nibble;
-       char                            first_nib;
-       static                          char *z_pad = "\0\0\0\0\0\0\0";
-       static                          char *f_pad = "\021\021\021\021\021\021\021";
-
-       IFDEBUG(D_CADDR)
-               printf("DTEtoNSAP( 0x%x, 0x%x, 0x%x, 0x%x )\n", 
-                       src_octet, src_nibble, src_nib_len, addr );
-       ENDDEBUG
-
-       bzero( addr, sizeof(*addr));
-       addr->siso_family = AF_ISO;
-       /*
-        * Coming from a DTE addr it's always type 37.
-        * src_octet <-- starting place in the NSAP-address of 
-        * the embedded SNPA-address (x.121 addr or DTE addr).
-        */
-       addr->siso_addr.isoa_afi = 0x37;
-
-       /* first, figure out what pad to use and pad */
+       register char           *in, *out;
+       register int            first;
+       int                                     pad_tail = 0;
+       int                             src_len;
 
 
-       first_nib = (*src_octet) >> (SHIFT*(1-src_nibble));
-       pad_len = (ADDR37_IDI_LEN<<1 - src_nib_len);
-       nibble_copy(first_nib? z_pad : f_pad, HIGH_NIBBLE,
-               (caddr_t) addr->siso_addr.t37_idi, HIGH_NIBBLE, pad_len);
-
-       dst_octet += (pad_len>>1);
-       dst_nibble = 1-(pad_len & 0x1);
-       IFDEBUG(D_CADDR)
-               printf("DTEtoNSAP 2( 0x%x, 0x%x, 0x%x, 0x%x )\n", 
-                       dst_octet, dst_nibble, pad_len, src_nib_len );
-       ENDDEBUG
-
-       /* now copy the dte address */
-       nibble_copy( src_octet, src_nibble, dst_octet, dst_nibble, src_nib_len);
-
-       addr->siso_addr.isoa_len = ADDR37_IDI_LEN + ADDR37_DSP_LEN +1 /* for afi */;
-               /* kludge */
-
-       addr->siso_tsuffix = unmunge(
-               (caddr_t) &(addr->siso_addr.t37_idi[ADDR37_IDI_LEN]), HIGH_NIBBLE);
-
-       IFDEBUG(D_CADDR)
-               printf("DTEtoNSAP 3 returning 0 tsuffix 0x%x\n", addr->siso_tsuffix);
-       ENDDEBUG
 
 
+       init_siso(addr);
+       src_len = strlen(sx->x25_addr);
+       in = sx->x25_addr;
+       out = addr->siso_data + 1;
+       if (*in == '0' && (src_len & 1 == 0)) {
+               pad_tail = 0xf;
+               src_len++;
+       }
+       for (first = 0; src_len > 0; src_len --) {
+               first |= *in++;
+               if (src_len & 1) {
+                       *out++ = first;
+                       first = 0;
+               }
+               else first <<= 4;
+       }
+       if (pad_tail)
+               out[-1] |= 0xf;
        return 0; /* ok */
 }
 
        return 0; /* ok */
 }
 
@@ -3753,24 +860,23 @@ DTEtoNSAP(addr, src_octet, src_nibble, src_nib_len)
  *  0 if ok, E* otherwise.
  */
 
  *  0 if ok, E* otherwise.
  */
 
-Static int
-parse_facil( buf, buf_len, called, calling, proto, peer_dte)
+static int
+parse_facil(lcp, isop, buf, buf_len)
        caddr_t                 buf;
        u_char                  buf_len; /* in bytes */
        caddr_t                 buf;
        u_char                  buf_len; /* in bytes */
-       register struct sockaddr_iso *called, *calling;
-       int                             *proto;
-       struct  dte_addr        *peer_dte;
+       struct                  isopcb *isop;
+       struct                  pklcd *lcp;
 {
 {
+       register struct sockaddr_iso *called = isop->isop_laddr;
+       register struct sockaddr_iso *calling = isop->isop_faddr;
        register int    i;
        register int    i;
-       caddr_t                 ptr;
-       caddr_t                 facil_len;
-       int                     facil_param_len;
-       struct  sockaddr_iso *addr;
-       int                             addrs_not_parsed = (int)0xcb + (int)0xc9;
+       register u_char         *ptr = (u_char *)buf;
+       u_char                  *ptr_lim, *facil_lim;
+       int                     facil_param_len, facil_len;
 
        IFDEBUG(D_CADDR)
 
        IFDEBUG(D_CADDR)
-               printf("parse_facil( 0x%x, 0x%x, 0x%x, 0x%x, 0x%x )\n", 
-                       buf, buf_len, called, calling, *proto);
+               printf("parse_facil(0x%x, 0x%x, 0x%x, 0x%x)\n", 
+                       buf, buf_len, called, calling);
                dump_buf(buf, buf_len);
        ENDDEBUG
 
                dump_buf(buf, buf_len);
        ENDDEBUG
 
@@ -3780,35 +886,31 @@ parse_facil( buf, buf_len, called, calling, proto, peer_dte)
         * i += 1 so that an odd nibble gets rounded up to even  
         * before dividing by 2, then divide by two to get # octets
         */
         * i += 1 so that an odd nibble gets rounded up to even  
         * before dividing by 2, then divide by two to get # octets
         */
-       i = (int)(*buf >> 4) + (int)(*buf&0xf);
+       i = (int)(*ptr >> 4) + (int)(*ptr&0xf);
        i++;
        i++;
-       ptr = (caddr_t) (buf + (i>>1));
-       /* now i is number of octets */
-
+       ptr += i >> 1;
        ptr ++; /* plus one for the DTE lengths byte */
 
        /* ptr now is at facil_length field */
        ptr ++; /* plus one for the DTE lengths byte */
 
        /* ptr now is at facil_length field */
-       facil_len = ptr++;
+       facil_len = *ptr++;
+       facil_lim = ptr + facil_len;
        IFDEBUG(D_CADDR)
        IFDEBUG(D_CADDR)
-               printf("parse_facils: facil length is  0x%x\n", (int) *facil_len);
+               printf("parse_facils: facil length is  0x%x\n", (int) facil_len);
        ENDDEBUG
 
        ENDDEBUG
 
-       while( ptr <= (caddr_t)(facil_len + (int)*facil_len) ) {
+       while (ptr <= facil_lim) {
                /* get NSAP addresses from facilities */
                /* get NSAP addresses from facilities */
-               switch (*ptr) {
+               switch (*ptr++) {
                        case 0xcb:
                        case 0xcb:
-                               facil_param_len = 0;
-                               addr = calling;
-                               addrs_not_parsed -= 0xcb;
+                               /* calling NSAP */
+                               facil_param_len = FACILtoNSAP(isop->isop_faddr, ptr);
                                break;
                        case 0xc9:
                                break;
                        case 0xc9:
-                               facil_param_len = 0;
-                               addr = called;
-                               addrs_not_parsed -= 0xc9;
+                               /* called NSAP */
+                               facil_param_len = FACILtoNSAP(isop->isop_laddr, ptr);
                                break;
 
                                /* from here to default are legit cases that I ignore */
                                break;
 
                                /* from here to default are legit cases that I ignore */
-
                                /* variable length */
                        case 0xca:  /* end-to-end transit delay negot */
                        case 0xc6:  /* network user id */
                                /* variable length */
                        case 0xca:  /* end-to-end transit delay negot */
                        case 0xc6:  /* network user id */
@@ -3818,7 +920,6 @@ parse_facil( buf, buf_len, called, calling, proto, peer_dte)
                        case 0xc4:      /* RPOA extended format */
                        case 0xc3:      /* call redirection notification */
                                facil_param_len = 0;
                        case 0xc4:      /* RPOA extended format */
                        case 0xc3:      /* call redirection notification */
                                facil_param_len = 0;
-                               addr = (struct sockaddr_iso *)0;
                                break;
 
                                /* 1 octet */
                                break;
 
                                /* 1 octet */
@@ -3831,7 +932,6 @@ parse_facil( buf, buf_len, called, calling, proto, peer_dte)
                        case 0x04:      /* charging info : requesting service */
                        case 0x08:      /* called line addr modified notification */
                                facil_param_len = 1;
                        case 0x04:      /* charging info : requesting service */
                        case 0x08:      /* called line addr modified notification */
                                facil_param_len = 1;
-                               addr = (struct sockaddr_iso *)0;
                                break;
 
                                /* any 2 octets */
                                break;
 
                                /* any 2 octets */
@@ -3841,7 +941,6 @@ parse_facil( buf, buf_len, called, calling, proto, peer_dte)
                        case 0x41:  /* bilateral CUG shit */
                        case 0x49:      /* transit delay selection and indication */
                                facil_param_len = 2;
                        case 0x41:  /* bilateral CUG shit */
                        case 0x49:      /* transit delay selection and indication */
                                facil_param_len = 2;
-                               addr = (struct sockaddr_iso *)0;
                                break;
 
                                /* don't have any 3 octets */
                                break;
 
                                /* don't have any 3 octets */
@@ -3849,88 +948,19 @@ parse_facil( buf, buf_len, called, calling, proto, peer_dte)
                                facil_param_len = 3;
                                */
                        default:
                                facil_param_len = 3;
                                */
                        default:
-                               ASSERT(0);
                                printf(
 "BOGUS FACILITY CODE facil_len 0x%x *facil_len 0x%x, ptr 0x%x *ptr 0x%x\n",
                                printf(
 "BOGUS FACILITY CODE facil_len 0x%x *facil_len 0x%x, ptr 0x%x *ptr 0x%x\n",
-                                       facil_len, *facil_len,
-                                       ptr, *ptr);
-                               addr = (struct sockaddr_iso *)0;
+                                       ptr, facil_len, ptr - 1, ptr[-1]);
                                /* facil that we don't handle */
                                return E_CO_HLI_REJI;
                }
                                /* facil that we don't handle */
                                return E_CO_HLI_REJI;
                }
-               ptr++; /* one for facil code */
-               if(facil_param_len == 0) /* variable length */ 
+               if (facil_param_len == -1)
+                       return E_CO_REG_ICDA;
+               if (facil_param_len == 0) /* variable length */ 
                        facil_param_len = (int)*ptr; /* 1 + the real facil param */
                        facil_param_len = (int)*ptr; /* 1 + the real facil param */
-               if( addr &&  FACILtoNSAP(ptr+1, facil_param_len-1, addr) ) {
-                       return E_CO_OSI_UNSAP;
-               }
                ptr += facil_param_len;
        }
                ptr += facil_param_len;
        }
-       if( addrs_not_parsed ) {
-               /* no facilities, get NSAP addresses from DTE addresses */
-               register int ed, ing;
-
-               ed = (int)(*buf&0xf);
-               if( ed == 0 ) {
-                       panic("Called DTE address absent");
-               }
-               DTEtoNSAP(called, (buf + 1)/*octet*/, 
-                       1/*nibble*/, ed);
-
-               ing = (int)(*buf >> 4); 
-               if( ing == 0 ) {
-                       printf("cons: panic: Calling DTE address absent");
-                       return E_CO_HLI_REJI;
-               }
-               nibble_copy((buf + (ed>>1)+1)/*octet*/, 1-(ed&0x1)/*nibble*/, 
-                       peer_dte->dtea_addr, HIGH_NIBBLE, ing);
-               DTEtoNSAP(calling, (buf + (ed>>1)+1)/*octet*/, 
-                       1-(ed&0x1)/*nibble*/, ing);
-
-       }
-
-       ASSERT( ptr == (caddr_t)(facil_len + 1 + (int)*facil_len) );
-
-       /* 
-        * now look for user data to find protocol identifier
-        */
-       if( ptr == buf + buf_len ) {
-               /* no user data */
-               *proto = ISOPROTO_TP; /* to proto id --> use TP */
-               IFDEBUG(D_CADDR)
-                       printf("NO USER DATA: use TP\n");
-               ENDDEBUG
-       } else {
-               ASSERT ( ptr < buf + buf_len );
-               if ( ptr >= buf + buf_len ) {
-                       printf("ptr 0x%x buf 0x%x buf_len 0x%x buf+buf_len 0x%x\n",
-                               ptr, buf, buf_len, buf+buf_len);
-               }
-               IFDEBUG(D_CADDR)
-                       printf("proto byte 0x%x, value 0x%x\n", ptr, *ptr);
-               ENDDEBUG
-               switch(*ptr) {
-               case 0x81:
-                       *proto = ISOPROTO_CLNP;
-                       break;
-               case 0x0:
-                       *proto = ISOPROTO_INACT_NL;
-                       break;
-               case  'e': /* for EAN */
-                       *proto = ISOPROTO_TP; 
-                       /* can check for "an2" or can ignore the rest of the u data */
-                       break;
-               case 0xff: /* reserved for future extensions */
-                       *proto =  ISOPROTO_X25;
-                       break;
-               case 0x82: /* 9542 not implemented */
-               case 0x84: /* 8878/A SNDCP not implemented */
-               default:
-                       *proto =  -1; 
-                       return E_CO_HLI_PROTOID;
-               }
-       }
        return 0;
 }
 
        return 0;
 }
 
-#endif NARGOXTWENTYFIVE > 0
+#endif TPCONS