Annotation of 43BSDReno/sys/netiso/if_cons.c, revision 1.1

1.1     ! root        1: /***********************************************************
        !             2:                Copyright IBM Corporation 1987
        !             3: 
        !             4:                       All Rights Reserved
        !             5: 
        !             6: Permission to use, copy, modify, and distribute this software and its 
        !             7: documentation for any purpose and without fee is hereby granted, 
        !             8: provided that the above copyright notice appear in all copies and that
        !             9: both that copyright notice and this permission notice appear in 
        !            10: supporting documentation, and that the name of IBM not be
        !            11: used in advertising or publicity pertaining to distribution of the
        !            12: software without specific, written prior permission.  
        !            13: 
        !            14: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
        !            15: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
        !            16: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
        !            17: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
        !            18: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
        !            19: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
        !            20: SOFTWARE.
        !            21: 
        !            22: ******************************************************************/
        !            23: 
        !            24: /*
        !            25:  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
        !            26:  */
        !            27: /*
        !            28:  * $Header: if_cons.c,v 4.7 88/08/11 15:52:55 nhall Exp $
        !            29:  * $Source: /usr/argo/sys/netiso/RCS/if_cons.c,v $
        !            30:  *
        !            31:  * cons.c - Connection Oriented Network Service:
        !            32:  * including support for a) user transport-level service, 
        !            33:  *     b) COSNS below CLNP, and c) CONS below TP.
        !            34:  */
        !            35: 
        !            36: #ifndef lint
        !            37: static char *rcsid = "$Header: if_cons.c,v 4.7 88/08/11 15:52:55 nhall Exp $";
        !            38: #endif lint
        !            39: 
        !            40: #ifdef ARGO_DEBUG
        !            41: #define Static  
        !            42: unsigned LAST_CALL_PCB;
        !            43: #else ARGO_DEBUG
        !            44: #define Static static
        !            45: #endif ARGO_DEBUG
        !            46: 
        !            47: #include "ecn.h"
        !            48: #include "argoxtwentyfive.h"
        !            49: 
        !            50: #if NARGOXTWENTYFIVE > 0
        !            51: 
        !            52: #ifdef KERNEL
        !            53: 
        !            54: #include "param.h"
        !            55: #include "systm.h"
        !            56: #include "mbuf.h"
        !            57: #include "protosw.h"
        !            58: #include "socket.h"
        !            59: #include "socketvar.h"
        !            60: #include "errno.h"
        !            61: #include "ioctl.h"
        !            62: #include "tsleep.h"
        !            63: 
        !            64: #include "../net/if.h"
        !            65: #include "../net/netisr.h"
        !            66: #include "../net/route.h"
        !            67: 
        !            68: #include "../netiso/iso_errno.h"
        !            69: #include "../netiso/argo_debug.h"
        !            70: #include "../netiso/tp_trace.h"
        !            71: #include "../netiso/iso.h"
        !            72: #include "../netiso/cons.h"
        !            73: #include "../netiso/iso_pcb.h"
        !            74: #include "../netiso/cons_pcb.h"
        !            75: #include "../caif/eicon.h"
        !            76: 
        !            77: #ifdef ARGO_DEBUG
        !            78: #define MT_XCONN       0x50
        !            79: #define MT_XCLOSE      0x51
        !            80: #define MT_XCONFIRM    0x52
        !            81: #define MT_XDATA       0x53
        !            82: #define MT_XHEADER     0x54
        !            83: #else
        !            84: #define MT_XCONN       MT_DATA
        !            85: #define MT_XCLOSE      MT_DATA
        !            86: #define MT_XCONFIRM    MT_DATA
        !            87: #define MT_XDATA       MT_DATA
        !            88: #define MT_XHEADER     MT_HEADER
        !            89: #endif ARGO_DEBUG
        !            90: 
        !            91: #define DONTCLEAR       -1
        !            92: 
        !            93: /********************************************************************* 
        !            94:  * cons.c - CONS interface to the eicon adapter
        !            95:  * Includes connection manager - for (TP, CLNP)/x.25
        !            96:  *
        !            97:  * TODO: figure out what resources we might run out of besides mbufs.
        !            98:  *  If we run out of any of them (including mbufs) close and recycle
        !            99:  *  lru x% of the connections, for some parameter x.
        !           100:  *
        !           101:  * There are 4 interfaces from above:
        !           102:  * 0) from CLNP: 
        !           103:  *    cons is an interface driver - CLNP calls
        !           104:  *    cosns_output(ifp, m, dst), a device-type interface output routine
        !           105:  *    that does some connection management stuff and queues a
        !           106:  *    request on the eicon driver queue by calling ifp->if_output.
        !           107:  *    The eicon's ifp structure contains cosns_output as its output routine
        !           108:  *    rather than ifp_>if_output! Kludge, but we don't have much choice...
        !           109:  *    X25 connections created in this manner may always be multiplexed
        !           110:  *    but only with their own kind (not with connections servicing TP
        !           111:  *    directly.)
        !           112:  *             co_flags & CONSF_DGM 
        !           113:  * 1) from TP0: 
        !           114:  *    cons CO network service
        !           115:  *    TP associates a transport connection with a network connection.
        !           116:  *       cons_output( isop, m, len, isdgm==0 ) 
        !           117:  *        co_flags == 0
        !           118:  * 2) from TP 4:
        !           119:  *       It's a datagram service, like clnp is. - even though it calls
        !           120:  *                     cons_output( isop, m, len, isdgm==1 ) 
        !           121:  *       it eventually goes through
        !           122:  *                     cosns_output(ifp, m, dst).
        !           123:  *    TP4 permits multiplexing (reuse, possibly simultaneously) of the 
        !           124:  *       network connections.
        !           125:  *    This means that many sockets (many tpcbs) may be associated with
        !           126:  *    this cons_pcb, hence cannot have a back ptr from cons_pcb to a tpcb.
        !           127:  *        co_flags & CONSF_DGM 
        !           128:  *    co_socket is null since there may be many sockets that use this copcb.
        !           129:  * 3) from user: cons_usrreq(), cons_ctloutput() 
        !           130:  *    cons is a standard transport service interface.
        !           131:  *    There is a 1-1 correspondence between net connections and sockets.
        !           132:  *       co_socket points to a socket.
        !           133:  *
        !           134: NOTE:
        !           135:        streams would really be nice. sigh.
        !           136: NOTE:
        !           137:        eicon <--> cons interface: the first mbuf (the ecn_request structure)
        !           138:        had better NOT be a cluster.
        !           139: NOTE:
        !           140:        PVCs could be handled by config-ing a cons with an address and with the
        !           141:        IFF_POINTTOPOINT flag on.  This code would then have to skip the
        !           142:        connection setup stuff for pt-to-pt links.  
        !           143: NOTE:
        !           144:        We keep track of the ifp for each connection.  Right now this is
        !           145:        unnecessary, but just in case someone comes up with some kind
        !           146:        of a kludge to allow > 1 eicon to be attached at a time,
        !           147:        (i.e., some meaningful netof( a type 37 address ) ),
        !           148:        we do keep track of this.
        !           149: 
        !           150: 
        !           151:  *********************************************************************/
        !           152: 
        !           153: #define touch(copcb) copcb->co_ttl = copcb->co_init_ttl
        !           154: 
        !           155: #define CONS_IFQMAXLEN 5
        !           156: 
        !           157: #define SET_CHANMASK( isop, chan )\
        !           158:        if( (u_int)(chan) < 32 ) \
        !           159:                (isop)->isop_chanmask = (1<<((chan)-1));\
        !           160:        else \
        !           161:                (isop)->isop_negchanmask = (1<<((256-(chan))-1))
        !           162: 
        !           163: #define ADD_CHANMASK( isop, chan )\
        !           164:        if( (u_int)(chan) < 32 ) \
        !           165:                (isop)->isop_chanmask |= (1<<((chan)-1));\
        !           166:        else \
        !           167:                (isop)->isop_negchanmask |= (1<<((256-(chan))-1))
        !           168: 
        !           169: struct ifnet                   *consif; /* TO BE REMOVED */
        !           170: Static int                             consinit(), consioctl(), consattach();
        !           171: 
        !           172: /* protosw pointers for getting to higher layer */
        !           173: Static         struct protosw  *CLNP_proto;
        !           174: Static         struct protosw  *TP_proto;
        !           175: Static         struct protosw  *X25_proto;
        !           176: Static         int                             issue_clear_req();
        !           177: 
        !           178: #ifndef        PHASEONE
        !           179: extern struct ifaddr   *ifa_ifwithnet();
        !           180: #endif PHASEONE
        !           181: 
        !           182: extern struct ifaddr   *ifa_ifwithaddr();
        !           183: 
        !           184: Static  struct socket  dummysocket; /* for use by cosns */
        !           185: 
        !           186: extern struct  isopcb  tp_isopcb; /* chain of all TP pcbs */
        !           187: struct isopcb                  cons_isopcb; /* chain of all cons pcbs */
        !           188: struct isopcb                  tp_incoming_pending;  /* incoming connections
        !           189:                                                                                for TP, pending */
        !           190: 
        !           191: struct isopcb  *Xpcblist[] =  {
        !           192:        &cons_isopcb, 
        !           193:        &tp_incoming_pending,
        !           194:        &tp_isopcb,
        !           195:        (struct isopcb *)0
        !           196: };
        !           197: 
        !           198: Static         int parse_facil(), NSAPtoDTE(), make_partial_x25_packet();
        !           199: Static int FACILtoNSAP(), DTEtoNSAP();
        !           200: Static struct cons_pcb *cons_chan_to_pcb();
        !           201: 
        !           202: #define HIGH_NIBBLE 1
        !           203: #define LOW_NIBBLE 0
        !           204: 
        !           205: /*
        !           206:  * NAME:       nibble_copy()
        !           207:  * FUNCTION and ARGUMENTS:
        !           208:  *     copies (len) nibbles from (src_octet), high or low nibble
        !           209:  *  to (dst_octet), high or low nibble,
        !           210:  * src_nibble & dst_nibble should be:
        !           211:  *     HIGH_NIBBLE (1) if leftmost 4 bits/ most significant nibble
        !           212:  *     LOW_NIBBLE (0) if rightmost 4 bits/ least significant nibble
        !           213:  * RETURNS: VOID
        !           214:  */
        !           215: void
        !           216: nibble_copy( src_octet, src_nibble, dst_octet, dst_nibble, len)
        !           217:        register char   *src_octet;
        !           218:        register char   *dst_octet;
        !           219:        register unsigned               src_nibble;
        !           220:        register unsigned               dst_nibble;
        !           221:        int             len;
        !           222: {
        !           223: 
        !           224:        register        i;
        !           225:        register        unsigned dshift, sshift;
        !           226: 
        !           227:        IFDEBUG(D_CADDR)
        !           228:                printf("nibble_copy ( 0x%x, 0x%x, 0x%x, 0x%x 0x%x)\n", 
        !           229:                 src_octet, src_nibble, dst_octet, dst_nibble, len);
        !           230:        ENDDEBUG
        !           231: #define SHIFT 0x4
        !           232: 
        !           233:        dshift = dst_nibble << 2;
        !           234:        sshift = src_nibble << 2;
        !           235: 
        !           236:        for (i=0; i<len; i++) {
        !           237:                /* clear dst_nibble  */
        !           238:                *dst_octet      &= ~(0xf<< dshift);
        !           239: 
        !           240:                /* set dst nibble */
        !           241:                *dst_octet      |= ( 0xf & (*src_octet >> sshift))<< dshift;
        !           242: 
        !           243:                dshift          ^= SHIFT;
        !           244:                sshift          ^= SHIFT;
        !           245:                src_nibble      = 1-src_nibble;
        !           246:                dst_nibble      = 1-dst_nibble;
        !           247:                src_octet       += src_nibble;
        !           248:                dst_octet       += dst_nibble;
        !           249:        }
        !           250:        IFDEBUG(D_CADDR)
        !           251:                printf("nibble_copy DONE\n");
        !           252:        ENDDEBUG
        !           253: }
        !           254: 
        !           255: /*
        !           256:  * NAME:       nibble_match()
        !           257:  * FUNCTION and ARGUMENTS:
        !           258:  *     compares src_octet/src_nibble and dst_octet/dst_nibble  for len nibbles.
        !           259:  * RETURNS: 0 if they differ, 1 if they are the same.
        !           260:  */
        !           261: int
        !           262: nibble_match( src_octet, src_nibble, dst_octet, dst_nibble, len)
        !           263:        register char   *src_octet;
        !           264:        register char   *dst_octet;
        !           265:        register unsigned               src_nibble;
        !           266:        register unsigned               dst_nibble;
        !           267:        int             len;
        !           268: {
        !           269: 
        !           270:        register        i;
        !           271:        register        unsigned dshift, sshift;
        !           272:        u_char          nibble_a, nibble_b;
        !           273: 
        !           274:        IFDEBUG(D_CADDR)
        !           275:                printf("nibble_match ( 0x%x, 0x%x, 0x%x, 0x%x 0x%x)\n", 
        !           276:                 src_octet, src_nibble, dst_octet, dst_nibble, len);
        !           277:        ENDDEBUG
        !           278: #define SHIFT 0x4
        !           279: 
        !           280:        dshift = dst_nibble << 2;
        !           281:        sshift = src_nibble << 2;
        !           282: 
        !           283:        for (i=0; i<len; i++) {
        !           284:                nibble_b = ((*dst_octet)>>dshift) & 0xf;
        !           285:                nibble_a = ( 0xf & (*src_octet >> sshift));
        !           286:                if( nibble_b != nibble_a )
        !           287:                        return 0;
        !           288: 
        !           289:                dshift          ^= SHIFT;
        !           290:                sshift          ^= SHIFT;
        !           291:                src_nibble      = 1-src_nibble;
        !           292:                dst_nibble      = 1-dst_nibble;
        !           293:                src_octet       += src_nibble;
        !           294:                dst_octet       += dst_nibble;
        !           295:        }
        !           296:        IFDEBUG(D_CADDR)
        !           297:                printf("nibble_match DONE\n");
        !           298:        ENDDEBUG
        !           299:        return 1;
        !           300: }
        !           301: 
        !           302: #ifdef ARGO_DEBUG
        !           303: 
        !           304: Static
        !           305: dump_copcb(copcb, str)
        !           306:        char * str;
        !           307:        register struct cons_pcb *copcb;
        !           308: {
        !           309:        printf("XPCB DUMP %s\n", str);
        !           310:        if (copcb) {
        !           311:                printf("\t copcb 0x%x next 0x%x head 0x%x socket 0x%x ifp 0x%x\n",
        !           312:                        copcb, copcb->co_next, copcb->co_head, copcb->co_socket, copcb->co_ifp);
        !           313:                printf("\t channel 0x%x state 0x%x flags 0x%x proto 0x%x\n",
        !           314:                        copcb->co_channel, copcb->co_state, copcb->co_flags, copcb->co_proto);
        !           315:                printf("\t laddr :\n");
        !           316:                dump_isoaddr(&copcb->co_laddr);
        !           317:                printf("\t faddr :\n");
        !           318:                dump_isoaddr(&copcb->co_faddr);
        !           319:                printf("\tttl 0x%x init_ttl 0x%x pending: %d\n",
        !           320:                        copcb->co_ttl, copcb->co_init_ttl, copcb->co_pending.ifq_len);
        !           321:        }
        !           322:        printf("END DUMP\n");
        !           323: }
        !           324: #endif ARGO_DEBUG
        !           325: 
        !           326: /*
        !           327:  * FUNCTION : choose_output - chooses between the eicon and loopback.
        !           328:  * This MUST be here because the ifp->if_output routine is cosns_output
        !           329:  * -- due to our need to look like a device driver for CLNP. sigh.
        !           330:  * ARGUMENTS & PURPOSE:  (copcb) ptr to a protocol control block for
        !           331:  *                     x.25, (m) is an mbuf ptr. *m is a request destined either
        !           332:  *                     for the eicon driver or for the loopback driver.
        !           333:  * RETURNS : whatever error value the 2I or loopback returns.
        !           334:  */
        !           335: Static int 
        !           336: choose_output( ifp, m, loop)
        !           337:        struct ifnet    *ifp;
        !           338:        struct mbuf     *m;
        !           339:        int                             loop;
        !           340: {
        !           341:        int error;
        !           342: 
        !           343:        if( !m )
        !           344:                return 0;
        !           345:        ASSERT(m->m_len != 0);
        !           346:        if( loop != 0)
        !           347:                error = lpboutput( ifp, m );
        !           348:        else
        !           349:                error = ecnoutput( ifp,  m );
        !           350: 
        !           351:        if (error == 0)
        !           352:                ifp->if_opackets ++;
        !           353:        else {
        !           354:                ifp->if_oerrors ++;
        !           355:                IFTRACE(D_CDATA)
        !           356:                        tptrace( TPPTmisc, 
        !           357:                        "choose_output: ifp  m error loop\n", 
        !           358:                                ifp, m, error, loop);
        !           359:                ENDTRACE
        !           360:        }
        !           361:        IFDEBUG(D_CCONS)
        !           362:                printf("choose_output returns 0x%x\n", error );
        !           363:        ENDDEBUG
        !           364:        return error;
        !           365: }
        !           366: 
        !           367: /*
        !           368:  **************************** NET PROTOCOL cons ***************************
        !           369:  */
        !           370: 
        !           371: /*
        !           372:  * NAME:       cons_init()
        !           373:  * CALLED FROM:
        !           374:  *     autoconf
        !           375:  * FUNCTION:
        !           376:  *     initialize the protocol
        !           377:  */
        !           378: cons_init()
        !           379: {
        !           380:        init_lpb();
        !           381:        consattach(); 
        !           382: 
        !           383:        /* protocol init stuff */
        !           384: 
        !           385:        consintrq.ifq_maxlen = IFQ_MAXLEN;
        !           386:        consintrq.ifq_head = consintrq.ifq_tail =  (struct mbuf *)0;
        !           387: 
        !           388:        CLNP_proto = pffindproto(AF_ISO, ISOPROTO_CLNP, SOCK_DGRAM); 
        !           389:        X25_proto = pffindproto(AF_ISO, ISOPROTO_X25, SOCK_STREAM);
        !           390:        TP_proto = pffindproto(AF_ISO, ISOPROTO_TP0, SOCK_SEQPACKET);
        !           391:        IFDEBUG(D_CCONS)
        !           392:                printf("cons_init end : cnlp_proto 0x%x cons proto 0x%x tp proto 0x%x\n",
        !           393:                        CLNP_proto, X25_proto, TP_proto);
        !           394:        ENDDEBUG
        !           395: 
        !           396:        cons_isopcb.isop_next = cons_isopcb.isop_prev = &cons_isopcb;
        !           397:        tp_incoming_pending.isop_next = tp_incoming_pending.isop_prev =
        !           398:                        &tp_incoming_pending;
        !           399: }
        !           400: 
        !           401: #ifdef notdef
        !           402: 
        !           403: /*
        !           404:  * NAME:       cons_free_lru()
        !           405:  * some day CALLED FROM: 
        !           406:  *     wherever we run out of mbufs (not used right yet)
        !           407:  * FUNCTION:
        !           408:  *     get rid of the num least recently used connections and
        !           409:  *  recycle their mbufs.
        !           410:  * NOTE: GROTESQUELY INEFFICIENT needs to be written nicely
        !           411:  */
        !           412: 
        !           413: Static
        !           414: cons_free_lru(qty)
        !           415:        int qty;
        !           416: {
        !           417:        register struct cons_pcb **copcblist = (struct cons_pcb **)Xpcblist;
        !           418:        register struct cons_pcb *copcb;
        !           419:        struct cons_pcb                         Lru; 
        !           420:        struct cons_pcb                         *lru; 
        !           421: 
        !           422:        IFDEBUG(D_CCONS)
        !           423:                printf("cons_free_lru( 0x%x )\n", qty);
        !           424:        ENDDEBUG
        !           425: 
        !           426:        Lru.co_ttl = X25_TTL;
        !           427:        lru = &Lru;
        !           428: 
        !           429:        while (qty > 1) { /* GROT */
        !           430:                cons_free_lru( 1 );
        !           431:                qty -- ;
        !           432:        }
        !           433: 
        !           434:        for( copcb = *copcblist; copcb; copcb = *(++copcblist) ) {
        !           435:                copcb = (struct cons_pcb *)copcb->co_next;
        !           436:                while (copcb !=  *copcblist) {
        !           437:                        if( copcb->co_ttl < lru->co_ttl ) 
        !           438:                                lru = copcb;
        !           439:                        copcb = (struct cons_pcb *)copcb->co_next;
        !           440:                }
        !           441:        }
        !           442: 
        !           443:        if(lru->co_socket) {
        !           444:                soisdisconnected(lru->co_socket);
        !           445:                sohasoutofband(lru->co_socket); /* signal */
        !           446:        } 
        !           447: 
        !           448:        cons_clear_and_detach( lru, E_CO_HLI_RESYNC, PRC_TIMXCEED_REASS);
        !           449: }
        !           450: #endif notdef
        !           451: 
        !           452: /*
        !           453:  * NAME:       cons_slowtimo()
        !           454:  * CALLED FROM: 
        !           455:  *     the clock
        !           456:  * FUNCTION:
        !           457:  *     get rid of any timed-out cons connections
        !           458:  *  cons connections get "touched" with every use, meaning the
        !           459:  *  time-to-live gets reset to its max value w/ every use.
        !           460:  *  The slowtimo() rtn decrements the time-to-live for each
        !           461:  *  cons connection.  If one of them hits zero ---> zap the connection.
        !           462:  *  This really only applies to those used for CLNP and TP4.
        !           463:  *  TP4 keeps the connections open with keepalive.
        !           464:  * TODO:
        !           465:  *  Have this happen ONLY for international connections since
        !           466:  *  there's no connect time charge for domestic calls.
        !           467:  *  Make default 5 min; make a user option to change it.
        !           468:  * TODO:
        !           469:  *  Maybe if the ttl gets lower than a certain threshold, move this 
        !           470:  *  copcb to the END of its queue so it doesn't slow down the others.
        !           471:  */
        !           472: 
        !           473: cons_slowtimo()
        !           474: {
        !           475:        register struct cons_pcb **copcblist = (struct cons_pcb **)Xpcblist;
        !           476:        register struct cons_pcb *copcb;
        !           477:        int s = splnet();
        !           478:        int     qlen = 0;
        !           479:        int qdrops = 0;
        !           480:        int     nvisited = 0;
        !           481: 
        !           482: #ifdef ARGO_DEBUG
        !           483:        Static int count;
        !           484: 
        !           485:        count = 0;
        !           486: #endif ARGO_DEBUG
        !           487: 
        !           488:        IncStat(co_slowtimo);
        !           489:        for( copcb = *copcblist; copcb; copcb = *(++copcblist) ) {
        !           490: #ifdef ARGO_DEBUG
        !           491:                if( copcb == (struct cons_pcb *)0 ) {
        !           492:                        ASSERT( 0 );
        !           493:                        panic("TURNING OFF cons_slowtimo()!!! \n");
        !           494:                }
        !           495: #endif ARGO_DEBUG
        !           496:                copcb = (struct cons_pcb *)copcb->co_next;
        !           497:                while (copcb !=  *copcblist) {
        !           498: #ifdef ARGO_DEBUG
        !           499:                        if(++count >50 ) {
        !           500:                                printf("cons PANIC: slowtimo LOOP\n");
        !           501:                                splx(s);
        !           502:                                return;
        !           503:                        }
        !           504: #endif ARGO_DEBUG
        !           505: #ifdef notdef
        !           506:                        if( copcb->co_init_ttl == 0 ) {
        !           507:        ASSERT( (struct isopcb *)(*copcblist)==(struct isopcb *)&tp_isopcb );
        !           508:                                copcb = (struct cons_pcb *)copcb->co_next; 
        !           509:                                continue;
        !           510:                        }
        !           511: #endif notdef
        !           512:                        nvisited ++;
        !           513:                        ASSERT( copcb != (struct cons_pcb *)0 );
        !           514:                        qlen += copcb->co_pending.ifq_len;
        !           515:                        qdrops += copcb->co_pending.ifq_drops;
        !           516: 
        !           517:                        if( copcb->co_socket) {
        !           518:                                /* don't want XTS, TP0 connections to be subject to time out */
        !           519:                                copcb = (struct cons_pcb *)copcb->co_next; 
        !           520:                                continue;
        !           521:                        }
        !           522: 
        !           523:                        if( -- (copcb->co_ttl) > 0 )  {
        !           524:                                copcb = (struct cons_pcb *)copcb->co_next; 
        !           525:                                continue;
        !           526:                        }
        !           527: 
        !           528:                        IncStat(co_timedout);
        !           529: 
        !           530:                        IFDEBUG(D_CCONN)
        !           531:                                printf("TIMING OUT chan 0x%x copcb 0x%x flags 0x%x\n", 
        !           532:                                        copcb->co_channel, copcb, copcb->co_flags );
        !           533:                        ENDDEBUG
        !           534: 
        !           535:                        { 
        !           536:                                register struct cons_pcb * next = 
        !           537:                                        (struct cons_pcb *)copcb->co_next; 
        !           538:                                cons_clear_and_detach(copcb, 
        !           539:                                                E_CO_HLI_RESYNC, PRC_TIMXCEED_REASS);
        !           540:                                copcb = next;
        !           541:                        }
        !           542:                }
        !           543:        }
        !           544:        if(nvisited) {
        !           545:                cons_stat.co_avg_qlen = qlen / nvisited;
        !           546:                cons_stat.co_avg_qdrop = qdrops / nvisited;
        !           547:                cons_stat.co_active = nvisited;
        !           548:        }
        !           549: done:
        !           550:        splx(s);
        !           551: }
        !           552: 
        !           553: DUMP_PCBLIST()
        !           554: {
        !           555:        register int i=0;
        !           556:        register struct cons_pcb *copcb;
        !           557:        register struct cons_pcb **copcblist = (struct cons_pcb **)Xpcblist;
        !           558: 
        !           559:        for( copcb = *copcblist; copcb; copcb = *(++copcblist) ) {
        !           560:                printf("FOR %d: 0x%x ", ++i, copcb);
        !           561:                copcb = (struct cons_pcb *)copcb->co_next;
        !           562:                printf(" next 0x%x, *copcblist 0x%x\n",  copcb, *copcblist);
        !           563:                while (copcb !=  *copcblist) {
        !           564:                        ASSERT( copcb != (struct cons_pcb *)0 );
        !           565:                        printf("\tCOPCB 0x%x\n", copcb);
        !           566:                        if( copcb )
        !           567:                                dump_buf(copcb, sizeof( *copcb));
        !           568:                        else
        !           569:                                break;
        !           570:                        copcb = (struct cons_pcb *)copcb->co_next; 
        !           571:                }
        !           572:        }
        !           573: }
        !           574: 
        !           575: /*
        !           576:  * NAME:       cons_pcballoc()
        !           577:  * CALLED FROM:
        !           578:  *     cons_usrreq() when doing PRU_ATTACH, 
        !           579:  *  cons_incoming() when opening a new connection.  
        !           580:  * FUNCTION and ARGUMENTS:
        !           581:  *     Allocates a new pcb.
        !           582:  *  The flags and proto arguments are stashed into the new pcb.
        !           583:  * RETURN VALUE:
        !           584:  *  E* if error, 0 if ok
        !           585:  */
        !           586: Static int
        !           587: cons_pcballoc(so, head, flags, proto, dest)
        !           588:        struct socket   *so;
        !           589:        struct  isopcb  *head;
        !           590:        u_short                 flags;
        !           591:        struct protosw  *proto;
        !           592:        struct  cons_pcb **dest;
        !           593: {
        !           594:        int                                     error;
        !           595:        register struct cons_pcb *copcb;
        !           596: 
        !           597:        IFDEBUG(D_CCONN)
        !           598:                printf("cons_pcballoc (0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", 
        !           599:                        so, head, flags, proto, dest);
        !           600:        ENDDEBUG
        !           601:        if(proto == (struct protosw *)0)
        !           602:                return EPROTONOSUPPORT;
        !           603: 
        !           604:        if( ( error = iso_pcballoc(so, head) ) == EOK )  {
        !           605:                /* Have allocated a cleared mbuf */
        !           606: 
        !           607:                copcb = (struct cons_pcb *)so->so_pcb;
        !           608:                copcb->co_ttl = copcb->co_init_ttl = X25_TTL;
        !           609:                copcb->co_flags = flags; 
        !           610:                copcb->co_proto = proto;
        !           611:                copcb->co_pending.ifq_maxlen = CONS_IFQMAXLEN;
        !           612:                copcb->co_myself = copcb;
        !           613: 
        !           614:                if (so == &dummysocket) 
        !           615:                        copcb->co_socket = (struct socket *)0;
        !           616: 
        !           617:                *dest = copcb;
        !           618:        }
        !           619: done:
        !           620:        IFDEBUG(D_CCONN)
        !           621:                printf("cons_pcballoc returns 0x%x: DUMP\n", copcb);
        !           622:                dump_buf( copcb, sizeof(*copcb));
        !           623:        ENDDEBUG
        !           624:        if( (flags & CONSF_ICRE) == 0) {
        !           625:                struct dte_addr *dtea = &(*dest)->co_peer_dte;
        !           626:                int len;
        !           627: 
        !           628:                error = iso_8208snparesolve(&(*dest)->co_faddr, dtea, &len);
        !           629:                ASSERT(error == 0);
        !           630:                ASSERT(len == sizeof(struct dte_addr));
        !           631:        }
        !           632: 
        !           633:        return error;
        !           634: }
        !           635: 
        !           636: /*
        !           637:  * NAME:       cons_connect()
        !           638:  * CALLED FROM:
        !           639:  *     cons_usrreq() when opening a new connection.  
        !           640:  * FUNCTION anD ARGUMENTS:
        !           641:  *  Figures out which device to use, finding a route if one doesn't
        !           642:  *  already exist.
        !           643:  *     Builds an eicon connection request and gives it to the device.
        !           644:  * RETURN VALUE:
        !           645:  *  returns E*
        !           646:  */
        !           647: Static int 
        !           648: cons_connect( copcb )
        !           649:        register struct cons_pcb *copcb;
        !           650: {
        !           651:        register struct eicon_request *ecnrq;
        !           652:        register struct mbuf    *m;
        !           653:        int                                     error = 0;
        !           654:        struct ifaddr                   *ifa;
        !           655: 
        !           656:        IFDEBUG(D_CCONN)
        !           657:                printf("cons_connect( 0x%x ) : ifp 0x%x\npeer: ", copcb, copcb->co_ifp);
        !           658:                dump_isoaddr(&copcb->co_faddr);
        !           659:                printf("\nmyaddr: ");
        !           660:                dump_isoaddr(&copcb->co_laddr);
        !           661:                printf("\n" );
        !           662:        ENDDEBUG
        !           663: 
        !           664:        /* PHASE 2: this call is OK */
        !           665:        if( ifa = ifa_ifwithaddr(&copcb->co_faddr ) ) {
        !           666:                /* foreign address is me */
        !           667:                copcb->co_ifp = ifa->ifa_ifp; 
        !           668:                IFDEBUG(D_CCONN)
        !           669:                        printf("cons_connect: after if_withaddr copcb->co_ifp 0x%x\n",
        !           670:                                copcb->co_ifp);
        !           671:                ENDDEBUG
        !           672: 
        !           673:                if( (ifa->ifa_ifp->if_flags&(IFF_LOOPBACK|IFF_UP)) ==
        !           674:                                                                                                (IFF_LOOPBACK|IFF_UP)) {
        !           675:                        copcb->co_flags |= CONSF_LOOPBACK;
        !           676:                }
        !           677:                bcopy((caddr_t)&ifa->ifa_addr, (caddr_t)&copcb->co_laddr, 
        !           678:                        sizeof(struct sockaddr));
        !           679:        } 
        !           680:        IFDEBUG(D_CCONN)
        !           681:                printf("cons_connect: co_flags 0x%x\n", copcb->co_flags);
        !           682:                if( ifa ) {
        !           683:                        printf(" cons_connect withaddr returns %s\n", 
        !           684:                                copcb->co_ifp->if_name);
        !           685:                }
        !           686:        ENDDEBUG
        !           687:        else if ( copcb->co_ifp == (struct ifnet *)0 ) {
        !           688: #ifdef PHASEONE
        !           689:                /*
        !           690:                 *      We need to get the local nsap address.
        !           691:                 *      First, route to the destination. This will provide us with
        !           692:                 *      an ifp. Second, determine which local address linked on
        !           693:                 *      that ifp is appropriate
        !           694:                 */
        !           695:                struct sockaddr_iso     *first_hop;             /* filled by clnp_route */
        !           696:                struct iso_addr *localaddr, *clnp_srcaddr();
        !           697: 
        !           698:                if (error = clnp_route(&copcb->co_faddr, 
        !           699:                        &((struct isopcb *)copcb)->isop_route, /* flags */0,
        !           700:                        &first_hop, &copcb->co_ifp))
        !           701:                        goto bad;
        !           702: 
        !           703:                /* determine local address based upon ifp */
        !           704:                if ((localaddr = clnp_srcaddr(copcb->co_ifp, 
        !           705:                                &first_hop->siso_addr)) == NULL) {
        !           706:                        error = ENETUNREACH;
        !           707:                        goto bad;
        !           708:                }
        !           709:                copcb->co_laddr.siso_family = AF_ISO;
        !           710:                copcb->co_laddr.siso_addr = *localaddr;
        !           711: #else
        !           712:                /* Foreign addr isn't me (lpb). If still don't have an ifp or have
        !           713:                 * an ifp but don't know its address, look for a route 
        !           714:                 */
        !           715:                if( ifa = ifa_ifwithnet(&copcb->co_faddr) ) {
        !           716:                        copcb->co_ifp =  ifa->ifa_ifp;
        !           717:                        IFDEBUG(D_CCONN)
        !           718:                                printf(" cons_connect withnet returns %s\n",
        !           719:                                                                                copcb->co_ifp->if_name);
        !           720:                        ENDDEBUG
        !           721:                } else {
        !           722:                        printf("cons PANIC: connect: can't find SNPA \n");
        !           723:                        error = ENETUNREACH;
        !           724:                        goto bad;
        !           725:                }
        !           726: #endif PHASEONE
        !           727:        }
        !           728: #ifndef        PHASEONE
        !           729:        if( ifa == (struct ifaddr *)0 ) {
        !           730:                struct ifaddr * iso_ifwithidi();
        !           731: 
        !           732:                if( ifa = iso_ifwithidi(&copcb->co_faddr) ) {
        !           733:                        copcb->co_ifp =  ifa->ifa_ifp;
        !           734:                        IFDEBUG(D_CCONN)
        !           735:                                printf(" cons_connect withnet returns %s\n",
        !           736:                                                                                copcb->co_ifp->if_name);
        !           737:                        ENDDEBUG
        !           738:                } else {
        !           739:                        printf("cons PANIC: connect: can't find SNPA \n");
        !           740:                        error = ENETUNREACH;
        !           741:                        goto bad;
        !           742:                }
        !           743:        }
        !           744:        bcopy((caddr_t)&ifa->ifa_addr, (caddr_t)&copcb->co_laddr, 
        !           745:                sizeof(struct sockaddr));
        !           746: #endif PHASEONE
        !           747: 
        !           748:        copcb->co_state = CONNECTING;
        !           749: 
        !           750:        ASSERT( copcb->co_ifp != (struct ifnet *) 0);
        !           751:        if ( copcb->co_ifp == (struct ifnet *)0 ) {
        !           752:                error = ENETUNREACH;
        !           753:                goto bad;
        !           754:        }
        !           755: 
        !           756:        m = m_getclr(M_DONTWAIT, MT_XCONN);
        !           757:        if( !m ) {
        !           758:                copcb->co_ifp->if_oerrors ++;
        !           759:                error = ENOBUFS;
        !           760:                goto bad; 
        !           761:        }
        !           762:        m->m_len = sizeof(struct eicon_request);
        !           763: 
        !           764:        ecnrq = mtod(m, struct eicon_request *);
        !           765: 
        !           766:        copcb->co_myself = copcb;
        !           767:        ecnrq->e_pcb = (caddr_t)copcb;
        !           768: #ifdef ARGO_DEBUG
        !           769:        LAST_CALL_PCB = (unsigned) ecnrq->e_pcb;
        !           770: #endif ARGO_DEBUG
        !           771:        ecnrq->e_cmd = ECN_CALL;
        !           772:        ecnrq->e_vc = 0; /* mbz ? */
        !           773:        ecnrq->e_info = 0; /* mbz */
        !           774: 
        !           775:        /* get data buffer */
        !           776:        {       struct mbuf *n;
        !           777: 
        !           778:                MGET(n, M_DONTWAIT, MT_XCONN);
        !           779:                if( n==MNULL ) {
        !           780:                        copcb->co_ifp->if_oerrors ++;
        !           781:                        error = ENOBUFS;
        !           782:                        goto bad; 
        !           783:                }
        !           784:                e_data(ecnrq) = n; /* e_data is really dtom(ecnrq)->m_next */
        !           785:        }
        !           786: 
        !           787:        IFDEBUG(D_CCONN)
        !           788:                printf(
        !           789:                "calling make_partial_x25_packet( 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
        !           790:                        &copcb->co_laddr, &copcb->co_faddr, 
        !           791:                        copcb->co_proto->pr_protocol, 
        !           792:                        e_data(ecnrq),
        !           793:                        copcb->co_flags & CONSF_XTS);
        !           794:        ENDDEBUG
        !           795:        if( error = make_partial_x25_packet( copcb, e_data(ecnrq)) ) {
        !           796:                copcb->co_ifp->if_oerrors ++;
        !           797:                m_freem(m);
        !           798:                goto bad;
        !           799:        }
        !           800:                
        !           801:        IncStat(co_call);
        !           802: 
        !           803:        IFDEBUG(D_CDUMP_REQ)
        !           804:                printf("cons_connect ecnrq:\n");
        !           805:                dump_buf(ecnrq, sizeof(*ecnrq));
        !           806:        ENDDEBUG
        !           807: 
        !           808:        ASSERT( copcb->co_channel == 0);
        !           809:        if( copcb->co_channel != 0) {
        !           810:                printf("cons_connect PANIC: channel is 0x%x\n", copcb->co_channel);
        !           811:        }
        !           812: 
        !           813:        error = choose_output(copcb->co_ifp, m, copcb->co_flags & CONSF_LOOPBACK);
        !           814: 
        !           815:        switch( error ) {
        !           816:                case 0: /* ok */
        !           817:                        break;
        !           818:                default: /* problem */
        !           819:                        printf("cons: PANIC: if_output returns 0x%x\n", error);
        !           820:                        cons_clear_and_detach( copcb, DONTCLEAR, PRC_ROUTEDEAD);
        !           821:        }
        !           822: 
        !           823: bad:
        !           824:        IFTRACE(D_CDATA)
        !           825:                tptrace( TPPTmisc, 
        !           826:                "cons_connect: choose (copcb m) returned  error\n", 
        !           827:                        copcb, m, error, 0);
        !           828:        ENDTRACE
        !           829:        return error;
        !           830: }
        !           831: 
        !           832: /*
        !           833:  * NAME:       cons_find()
        !           834:  * CALLED FROM:
        !           835:  *     cosns_output1() thus:
        !           836:  *             cons_find( CONSF_DGM, dst, proto, 0, 0) where
        !           837:  *             proto is one of { TP_proto, CLNP_proto }
        !           838:  * FUNCTION and ARGUMENTS:
        !           839:  *  Looks through list of connections for the destination,
        !           840:  *  for one marked for the use indicated by flags.
        !           841:  *  If none found, opens up a new connection.
        !           842:  *   These connections will be eliminated by :
        !           843:  *     a) slowtimo timer, or 
        !           844:  *     b) the need for a new connection, when we've run out of resources.
        !           845:  *  The argument flags describes the type of pcb we want - may
        !           846:  *  specify multiplexing-ok, datagram use, etc.
        !           847:  *  The argument proto points the the higher layer protocol that
        !           848:  *  will be using this connection.
        !           849:  * RETURN VALUE:
        !           850:  *  returns a ptr to a pcb whose characteristics match those
        !           851:  *  described by (flags, proto)
        !           852:  */
        !           853: 
        !           854: Static struct cons_pcb *
        !           855: cons_find(flags, dst, proto, addl_criteria, mask)
        !           856:        u_int flags, mask;
        !           857:        struct sockaddr_iso *dst;
        !           858:        struct protosw *proto;
        !           859:        int     (*addl_criteria)();
        !           860: {
        !           861:        register struct cons_pcb *copcb;
        !           862:        register struct cons_pcb **copcblist = (struct cons_pcb **)Xpcblist;
        !           863:        int s = splnet(); /* or whatever, for the device! */
        !           864:        struct dte_addr dest_dte;
        !           865:        int      dummy;
        !           866: 
        !           867:        struct  copcb_descriptor {
        !           868:                int     xd_qlen;
        !           869:                struct cons_pcb *xd_pcb;
        !           870:        } next_best = {
        !           871:                0, (struct cons_pcb *)0
        !           872:        };
        !           873: 
        !           874:        IFDEBUG(D_CFIND)
        !           875:                printf("cons_find( flags 0x%x proto 0x%x) ", flags, proto);
        !           876:        ENDDEBUG
        !           877: 
        !           878:        if ( iso_8208snparesolve(dst, &dest_dte, &dummy)) {
        !           879:                ASSERT(0);
        !           880:                return (struct cons_pcb *)0; /* error */
        !           881:        }
        !           882:        ASSERT(dummy == sizeof(struct dte_addr));
        !           883: 
        !           884:        for( copcb = *copcblist; copcb; copcb = *(++copcblist) ) {
        !           885:                copcb = (struct cons_pcb *)copcb->co_next;
        !           886:                while (copcb !=  *copcblist) {
        !           887:                        IFDEBUG(D_CFIND)
        !           888:                                printf(
        !           889:                                "cons_find: chan 0x%x flags 0x%x proto 0x%x state 0x%x \n", 
        !           890:                                        copcb->co_channel, copcb->co_flags, copcb->co_proto, 
        !           891:                                        copcb->co_state);
        !           892:                        ENDDEBUG
        !           893:                        /*
        !           894:                         * if flags is a subset of the bits in co_flags, it will suffice
        !           895:                         */
        !           896:                        if( ((copcb->co_flags & flags) == flags ) &&
        !           897:                                /* PHASE2: where do we get the mask if we use nsaps ????
        !           898:                                 * If dte addresses are used, then use
        !           899:                                 * nibble compare otherwise...???
        !           900:                                 */
        !           901: #ifdef notdef
        !           902:                                iso_addrmatch1(&(copcb->co_faddr.siso_addr), &(dst->siso_addr)) 
        !           903: #else
        !           904:                                dest_dte.dtea_niblen == copcb->co_peer_dte.dtea_niblen &&
        !           905:                                nibble_match( (char *)&(copcb->co_peer_dte.dtea_addr), 
        !           906:                                        HIGH_NIBBLE, (char *)dest_dte.dtea_addr, 
        !           907:                                        HIGH_NIBBLE, dest_dte.dtea_niblen)
        !           908: #endif notdef
        !           909:                                &&
        !           910:                                (copcb->co_proto == proto)  &&
        !           911:                                (copcb->co_state >= MIN_USABLE_STATE)) {
        !           912:                                        IFDEBUG(D_CFIND)
        !           913:                                                printf(
        !           914:                                                "cons_find: add'l criteria...\n" );
        !           915:                                        ENDDEBUG
        !           916:                                        if((copcb->co_state != OPEN) &&
        !           917:                                                (next_best.xd_qlen > copcb->co_pending.ifq_len)) {
        !           918:                                                next_best.xd_pcb = copcb;
        !           919:                                                next_best.xd_qlen = copcb->co_pending.ifq_len;
        !           920:                                        }
        !           921:                                        if( !addl_criteria || (*addl_criteria)(copcb, mask) ) {
        !           922:                                                goto found; /* have to break out of 2 loops */
        !           923:                                        }
        !           924:                                }
        !           925:                        copcb = (struct cons_pcb *)copcb->co_next ;
        !           926:                }
        !           927:        }
        !           928: #ifdef notdef
        !           929:        /* TODO: 
        !           930:         * have a limit of the number of calls per desitination.
        !           931:         * If we didn't find one already open AND our limit for this
        !           932:         * destination hasn't been reached, return 0 'cause
        !           933:         * then the caller will open a new one.
        !           934:         * Otherwise return next_best.
        !           935:         * To do this we need some sort of per-destination info.
        !           936:         * Could go into the directory service. Oh, grotesque.
        !           937:         */
        !           938: #endif notdef
        !           939:        if( copcb == (struct cons_pcb *)0 ) {
        !           940:                copcb = next_best.xd_pcb; /* may be zero too */
        !           941:                IFDEBUG(D_CFIND)
        !           942:                        printf("NEXT_BEST! \n");
        !           943:                        dump_copcb(copcb, "find: next_best");
        !           944:                ENDDEBUG
        !           945:        }
        !           946: found:
        !           947: 
        !           948:        splx(s);
        !           949:                
        !           950:        IFDEBUG(D_CFIND)
        !           951:                printf("returns 0x%x \n", copcb);
        !           952:        ENDDEBUG
        !           953:        return copcb;
        !           954: }
        !           955: 
        !           956: 
        !           957: /*
        !           958:  * NAME:       issue_clear_req()
        !           959:  * CALLED FROM:
        !           960:  *     cons_clear() and wherever we get an error from x.25 that makes us
        !           961:  *     want to close the vc on which it came, but don't have
        !           962:  *             a copcb assoc. with that vc.
        !           963:  * FUNCTION and ARGUMENTS:
        !           964:  *  Creates an eicon_request for a clear request, returns it in an mbuf.
        !           965:  *  (chan) is the channel on which to do the clear, (reason) is the 
        !           966:  *  clear reason(diagnostic).
        !           967:  * RETURN VALUE:
        !           968:  *  returns E*
        !           969:  */
        !           970: Static int
        !           971: issue_clear_req(chan, reason, ifp, loop)
        !           972:        u_char                  chan, reason;
        !           973:        struct  ifnet   *ifp;
        !           974:        int                             loop;
        !           975: {
        !           976:        register struct mbuf                    *m;
        !           977:        register struct mbuf                    *cdm;
        !           978:        register struct eicon_request   *ecnrq;
        !           979:        struct e_clear_data                     *ecd; 
        !           980: 
        !           981:        IFDEBUG(D_CCONN)
        !           982:                printf("issue_clear_req(0x%x, 0x%x, 0x%x, 0x%x)\n", 
        !           983:                        chan, reason, ifp, loop);
        !           984:        ENDDEBUG
        !           985:        m = m_getclr(M_DONTWAIT, MT_XCLOSE);
        !           986:        if( !m ) {
        !           987:                return ENOBUFS;
        !           988:        }
        !           989:        m->m_len = sizeof(struct eicon_request);
        !           990:        ecnrq = mtod(m, struct eicon_request *);
        !           991:        ecnrq->e_cmd = ECN_CLEAR;
        !           992:        ecnrq->e_vc = chan & 0xff; 
        !           993:        /* 
        !           994:         *  see p. 149 of 8208 for reasons (diagnostic codes)
        !           995:         */
        !           996:        MGET(cdm, M_DONTWAIT, MT_XCLOSE);
        !           997:        if( !cdm ) {
        !           998:                m_freem(m);
        !           999:                return ENOBUFS;
        !          1000:        }
        !          1001:        cdm->m_len = sizeof(struct e_clear_data); /* cause, diagnostic */
        !          1002:        e_data(ecnrq) = cdm;
        !          1003: 
        !          1004:        ecd = mtod(cdm, struct e_clear_data *);
        !          1005:        ecd->ecd_cause = 0x0; /* DTE initiated, diagnostic tells more */
        !          1006:        ecd->ecd_diagnostic = (u_char)reason;
        !          1007: 
        !          1008:        IncStat(co_clear_out);
        !          1009:        return choose_output(ifp, m, loop);
        !          1010: }
        !          1011: 
        !          1012: 
        !          1013: /*
        !          1014:  * NAME:       cons_clear()
        !          1015:  * CALLED FROM:
        !          1016:  *  cons_usrreq(), PRU_DISCONNECT,
        !          1017:  *  cons_slowtimo(), cons_free_lru()
        !          1018:  * FUNCTION and ARGUMENTS:
        !          1019:  *     Builds a clear request for the connection represented by copcb,
        !          1020:  *  gives it to the device.
        !          1021:  * ECN_CLEAR(request) takes e_vc only, returns adr_status.
        !          1022:  * RETURN VALUE:
        !          1023:  */
        !          1024: 
        !          1025: Static int 
        !          1026: cons_clear( copcb, reason) 
        !          1027:        register struct cons_pcb *copcb;
        !          1028:        u_char                                  reason;
        !          1029: {
        !          1030:        register struct mbuf                    *m;
        !          1031:        int                                                             error;
        !          1032: 
        !          1033:        IFDEBUG(D_CCONN)
        !          1034:                printf("cons_clear(0x%x, 0x%x)\n", copcb, reason);
        !          1035:        ENDDEBUG
        !          1036:        if( !copcb) {
        !          1037:                printf("cons PANIC: clear: No copcb\n");
        !          1038:                return 0;
        !          1039:        }
        !          1040:        while( copcb->co_pending.ifq_len > 0 ) {
        !          1041:                register int s = splimp();
        !          1042: 
        !          1043:                IF_DEQUEUE( &copcb->co_pending, m );
        !          1044:                splx(s);
        !          1045:                m_freem(m);
        !          1046:        }
        !          1047:        if( (copcb->co_state == CLOSED) || (copcb->co_state == CLOSING) )
        !          1048:                return 0;
        !          1049: 
        !          1050: #ifdef ARGO_DEBUG
        !          1051:        if( copcb->co_state == CONNECTING) {
        !          1052:                IFDEBUG(D_CCONN)
        !          1053:                        dump_copcb(copcb, "clear");
        !          1054:                ENDDEBUG
        !          1055:        } else if( (copcb->co_channel == 0) || (copcb->co_channel == X_NOCHANNEL) ) {
        !          1056:                IFDEBUG(D_CCONN)
        !          1057:                        dump_copcb(copcb, "clear");
        !          1058:                ENDDEBUG
        !          1059:        }
        !          1060: #endif ARGO_DEBUG
        !          1061: 
        !          1062:        copcb->co_state = CLOSING;
        !          1063: 
        !          1064:        IFDEBUG(D_CCONN)
        !          1065:                printf("cons_clear: channel 0x%x copcb 0x%x dst: ", 
        !          1066:                        copcb->co_channel,  copcb);
        !          1067:                dump_isoaddr(&copcb->co_faddr);
        !          1068:                dump_copcb(copcb, "clear");
        !          1069:        ENDDEBUG
        !          1070: 
        !          1071:        error = issue_clear_req(copcb->co_channel, reason, copcb->co_ifp,
        !          1072:                copcb->co_flags & CONSF_LOOPBACK);
        !          1073:        copcb->co_channel = X_NOCHANNEL; 
        !          1074:        copcb->co_state = CLOSED;
        !          1075:        return error;
        !          1076: }
        !          1077: 
        !          1078: 
        !          1079: /* 
        !          1080:  * NAME:       cons_senddata()
        !          1081:  * CALLED FROM:
        !          1082:  *  cons_output(), consoutput(), consintr()
        !          1083:  * FUNCTION and ARGUMENTS:
        !          1084:  *     issued a data (write) command - if the device isn't ready,
        !          1085:  *  it enqueues the command on a per-connection queue.
        !          1086:  * RETURN VALUE:
        !          1087:  *     ENOBUFS
        !          1088:  *  Is responsible for freeing m0!
        !          1089:  *
        !          1090:  * ECN_SEND (write) 
        !          1091:  */
        !          1092: 
        !          1093: Static int 
        !          1094: cons_senddata(copcb, m0)
        !          1095:        register struct cons_pcb *copcb;
        !          1096:        struct mbuf *m0;
        !          1097: {
        !          1098:        register struct mbuf *m;
        !          1099:        register struct eicon_request *ecnrq;
        !          1100:        int s;
        !          1101: 
        !          1102:        IFDEBUG(D_CDATA)
        !          1103:                printf("cons_senddata( 0x%x, m 0x%x ) chan 0x%x", 
        !          1104:                        copcb, m0, copcb->co_channel );
        !          1105:                printf(" co_lport 0x%x\n", copcb->co_lport);
        !          1106:        ENDDEBUG
        !          1107:        if( m0 == MNULL ) 
        !          1108:                return;
        !          1109:        ASSERT( m0->m_len > 0);
        !          1110:        if( m0->m_len <= 0) {
        !          1111:                printf("cons_senddata : BAD MLEN? 0x%x", m0->m_len);
        !          1112:        }
        !          1113: 
        !          1114:        touch(copcb);
        !          1115: 
        !          1116:        if( (copcb->co_state == CONNECTING) || (copcb->co_state == ACKWAIT) ) {
        !          1117:                IFDEBUG(D_CDATA)
        !          1118:                        printf("senddata PUTTING ON PENDING Q copcb 0x%x state 0x%x\n", 
        !          1119:                                copcb, copcb->co_state);
        !          1120:                ENDDEBUG
        !          1121:                s = splimp();
        !          1122:                if (IF_QFULL(&copcb->co_pending)) {
        !          1123:                        IFDEBUG(D_CDATA)
        !          1124:                                printf("senddata DROPPING m0 0x%x\n",  m0);
        !          1125:                        ENDDEBUG
        !          1126:                        IF_DROP(&copcb->co_pending);
        !          1127:                        if(copcb->co_ifp) {
        !          1128:                                copcb->co_ifp->if_snd.ifq_drops ++;
        !          1129:                        }
        !          1130:                        IncStat(co_Xdrops);
        !          1131:                        copcb->co_ifp->if_oerrors ++;
        !          1132:                        splx(s);
        !          1133:                        m_freem (m0);
        !          1134: 
        !          1135:                        if( copcb->co_proto  && copcb->co_proto->pr_ctlinput ) {
        !          1136:                                (*copcb->co_proto->pr_ctlinput)(PRC_QUENCH, 
        !          1137:                                (struct sockaddr_iso *)&copcb->co_faddr, 
        !          1138:                                (caddr_t)copcb);
        !          1139:                                
        !          1140:                                return 0;
        !          1141:                        } else
        !          1142:                                return E_CO_QFULL;
        !          1143:                }
        !          1144:                IFDEBUG(D_CDATA)
        !          1145:                        printf("Putting 0x%x on 0x%x->pending Q\n", m0, copcb);
        !          1146:                ENDDEBUG
        !          1147:                IF_ENQUEUE( &copcb->co_pending, m0 );
        !          1148:                splx(s);
        !          1149:                return 0;
        !          1150:        }
        !          1151:        if(copcb->co_channel == 0 ) {
        !          1152:                return E_CO_CHAN;
        !          1153:        }
        !          1154:        ASSERT( copcb->co_state == OPEN);
        !          1155: 
        !          1156:        m = m_getclr(M_DONTWAIT, MT_XDATA);
        !          1157:        if( !m ) {
        !          1158:                copcb->co_ifp->if_oerrors ++;
        !          1159:                m_freem (m0);
        !          1160:                return ENOBUFS;
        !          1161:        }
        !          1162:        m->m_len = sizeof(struct eicon_request);
        !          1163:        ecnrq = mtod(m, struct eicon_request *);
        !          1164:        ecnrq->e_pcb = (caddr_t)copcb;
        !          1165:        if( copcb->co_myself != copcb ) {
        !          1166:                struct mbuf *mm;
        !          1167:                /* TODO: REMOVE THIS DEBUGGING HACK */
        !          1168:                ASSERT(0);
        !          1169:                printf("BAD e_pcb from HL (0x%x,0x%x)\n", copcb, copcb->co_myself);
        !          1170:                mm = dtom( copcb );
        !          1171:                if(mm->m_type == MT_FREE)
        !          1172:                        printf("FREED MBUF!\n");
        !          1173:                return ENETDOWN;
        !          1174:        }
        !          1175:        ASSERT( copcb->co_channel != 0);
        !          1176:        ASSERT( copcb->co_channel != X_NOCHANNEL);
        !          1177:        ecnrq->e_vc = (copcb->co_channel & 0xff);
        !          1178:        ecnrq->e_cmd = ECN_SEND;
        !          1179:        e_data(ecnrq) = m0;
        !          1180:        {
        !          1181:                /* TODO: REMOVE THIS DEBUGGING HACK */
        !          1182:                struct mbuf *thedata = e_data(ecnrq);
        !          1183:                u_int *firstint = mtod( thedata, u_int *);
        !          1184:                
        !          1185:                if( (*firstint & 0xff000000) != 0x81000000 ) {
        !          1186:                        /* not clnp */
        !          1187:                        switch( ((*firstint) & 0x00ff0000) >> 20 ) {
        !          1188:                        case 0x1:
        !          1189:                        case 0x2:
        !          1190:                        case 0x3:
        !          1191:                        case 0x6:
        !          1192:                        case 0x7:
        !          1193:                        case 0x8:
        !          1194:                        case 0xc:
        !          1195:                        case 0xd:
        !          1196:                        case 0xe:
        !          1197:                        case 0xf:
        !          1198:                                break;
        !          1199:                        default:
        !          1200:                                printf(" ECN_SEND! BAD DATA\n" );
        !          1201:                                dump_buf( thedata, 20 + 12 );
        !          1202:                                m_freem( m0 );
        !          1203:                                return ENETDOWN;
        !          1204:                        }
        !          1205:                }
        !          1206:        }
        !          1207: 
        !          1208:        ecnrq->e_info = 0;
        !          1209: 
        !          1210:        IFDEBUG(D_CDUMP_REQ)
        !          1211:                printf("senddata ecnrq\n");
        !          1212:        ENDDEBUG
        !          1213:        IncStat(co_send);
        !          1214: 
        !          1215:        ASSERT( copcb->co_state == OPEN );
        !          1216:        copcb->co_state = ACKWAIT;
        !          1217: 
        !          1218:        if( copcb->co_myself != copcb ) {
        !          1219:                struct mbuf *mm;
        !          1220:                /* TODO: REMOVE this and all mention of co_myself */
        !          1221:                ASSERT(0);
        !          1222:                printf("BAD e_pcb TO THE BOARD ecn (0x%x) cmd 0x%x\n", 
        !          1223:                        ecnrq->e_pcb, ecnrq->e_cmd);
        !          1224:                mm = dtom( copcb );
        !          1225:                if(mm->m_type == MT_FREE)
        !          1226:                        printf("FREED MBUF!\n");
        !          1227:                dump_buf (ecnrq, sizeof (*ecnrq));
        !          1228:                return ENETDOWN;
        !          1229:        }
        !          1230: 
        !          1231:        return 
        !          1232:          choose_output(copcb->co_ifp, dtom(ecnrq), copcb->co_flags&CONSF_LOOPBACK);
        !          1233: }
        !          1234: 
        !          1235: /*
        !          1236:  * NAME:       cons_send_on_vc()
        !          1237:  * CALLED FROM:
        !          1238:  *  tp_error_emit()
        !          1239:  * FUNCTION and ARGUMENTS:
        !          1240:  *  Take a packet(m0), of length (datalen) from tp and 
        !          1241:  * send it on the channel (chan).
        !          1242:  *     
        !          1243:  * RETURN VALUE:
        !          1244:  *  whatever (E*) is returned form the net layer output routine.
        !          1245:  */
        !          1246: int
        !          1247: cons_send_on_vc(chan, m, datalen)
        !          1248:        int                             chan;
        !          1249:        struct mbuf     *m;
        !          1250:        int                             datalen;
        !          1251: {
        !          1252:        struct cons_pcb *copcb = (struct cons_pcb *)0;
        !          1253: 
        !          1254:        if(m == MNULL)
        !          1255:                return;
        !          1256: 
        !          1257:        if((copcb = 
        !          1258: #ifdef ARGO_DEBUG
        !          1259:                cons_chan_to_pcb( chan, __LINE__ )
        !          1260: #else ARGO_DEBUG
        !          1261:                cons_chan_to_pcb( chan )
        !          1262: #endif ARGO_DEBUG
        !          1263:                        ) == (struct cons_pcb *)0 )
        !          1264:                return E_CO_CHAN; 
        !          1265:        IFDEBUG(D_CCONS)
        !          1266:                printf("cons_send_on_vc m 0x%x m_len 0x%x\n", m, m->m_len);
        !          1267:        ENDDEBUG
        !          1268:        return cons_senddata( copcb, m);
        !          1269: }
        !          1270: 
        !          1271: /*
        !          1272:  * NAME:       cons_output()
        !          1273:  * CALLED FROM:
        !          1274:  *  tpiso_output(), can have whatever interface we want it to...
        !          1275:  *  tpiso_output() decides whether to give a packet to CLNP or to 
        !          1276:  *  cons; if the latter, it calls this routine.
        !          1277:  * FUNCTION and ARGUMENTS:
        !          1278:  *  tp has alloc-ed a pcb - but it may not be open.
        !          1279:  *  some classes of tp may allow multiplexing, in which
        !          1280:  *  case, you may choose to send the data on ANOTHER cons connection.
        !          1281:  *  This decides which net connection to use, opens one if necessary.
        !          1282:  *  Then it sends the data.
        !          1283:  */
        !          1284: 
        !          1285: cons_output(isop, m, len, isdgm)
        !          1286:        struct isopcb   *isop;
        !          1287:        struct mbuf     *m;
        !          1288:        int                     len;
        !          1289:        int                             isdgm;
        !          1290: {
        !          1291:        struct cons_pcb *copcb = (struct cons_pcb *)0;
        !          1292:        int                             error;
        !          1293:        int                     s = splnet();
        !          1294: 
        !          1295:        IFDEBUG(D_CCONS)
        !          1296:                printf("cons_output( isop 0x%x, m 0x%x, len 0x%x, dgm 0x%x )\n", 
        !          1297:                        isop,m,len, isdgm);
        !          1298:        ENDDEBUG
        !          1299: 
        !          1300:        if( m == MNULL )
        !          1301:                return 0;
        !          1302:        ASSERT(m->m_len > 0);
        !          1303:        if( isdgm ) {
        !          1304:                error = cosns_output1(0, m, &isop->isop_faddr, TP_proto, isop);
        !          1305:                IFDEBUG(D_CDATA)
        !          1306:                        if(error)
        !          1307:                        printf("cosns_output1 RETURNS ERROR 0x%x\n", error);
        !          1308:                ENDDEBUG
        !          1309:                return error;
        !          1310:        }
        !          1311: 
        !          1312:        if( isop->isop_chanmask  || isop->isop_negchanmask) {
        !          1313:                register int    mask = isop->isop_chanmask;
        !          1314:                register int    chan = 1;
        !          1315: 
        !          1316:                if( mask == 0)
        !          1317:                        mask = isop->isop_negchanmask;
        !          1318: 
        !          1319:                for ( chan=1; (mask & 1)==0; chan++,mask>>=1 ) ;
        !          1320: 
        !          1321:                if( isop->isop_chanmask == 0 )
        !          1322:                        chan = -chan;
        !          1323: 
        !          1324:                IFDEBUG(D_CCONS)
        !          1325:                        printf(
        !          1326:                        "cons_output: isop 0x%x cmask 0x%x negmask 0x%x, chan 0x%x\n",
        !          1327:                        isop, isop->isop_chanmask, isop->isop_negchanmask, chan);
        !          1328:                ENDDEBUG
        !          1329:                ASSERT( chan != 0);
        !          1330: #ifdef ARGO_DEBUG
        !          1331:                copcb = cons_chan_to_pcb( chan, __LINE__ );
        !          1332: #else ARGO_DEBUG
        !          1333:                copcb = cons_chan_to_pcb( chan );
        !          1334: #endif ARGO_DEBUG
        !          1335:        }
        !          1336:        if( copcb == (struct cons_pcb *)0 ) {
        !          1337:                /* get a new one */
        !          1338: 
        !          1339:                if(( error = cons_pcballoc(&dummysocket, &cons_isopcb, CONSF_OCRE, 
        !          1340:                                                                                                TP_proto, &copcb)) != EOK ) {
        !          1341:                        IFDEBUG(D_CCONS)
        !          1342:                                printf("cosns_output: no copcb; returns 0x%x\n", error);
        !          1343:                        ENDDEBUG
        !          1344:                        (void) m_freem (m);
        !          1345:                        splx(s);
        !          1346:                        return error ;
        !          1347:                }
        !          1348: 
        !          1349:                /* abbreviated form of iso_pcbconnect(): */
        !          1350:                bcopy((caddr_t)&isop->isop_faddr, (caddr_t)&copcb->co_faddr, 
        !          1351:                                                                        sizeof(struct sockaddr_iso));
        !          1352: 
        !          1353:                if ( error = cons_connect( copcb ) ) { /* if it doesn't work */
        !          1354:                        /* oh, dear, throw packet away */
        !          1355:                        remque((struct isopcb *)copcb);
        !          1356:                        (void) m_free(dtom(copcb));
        !          1357:                        (void) m_freem( m );
        !          1358:                        splx(s);
        !          1359:                        return error;
        !          1360:                }
        !          1361: 
        !          1362:                if( copcb->co_socket ) {
        !          1363:                        while( (copcb->co_state != OPEN) && 
        !          1364:                                !(error = copcb->co_socket->so_error) ) {
        !          1365:                                IFDEBUG(D_CCONS)
        !          1366:                                        printf(
        !          1367:        "SLEEP1 copcb 0x%x isop 0x%x state 0x%x chan 0x%x mask 0x%x neg 0x%x\n",
        !          1368:                                                copcb, isop, copcb->co_state, copcb->co_channel, 
        !          1369:                                                ((struct isopcb *)isop)->isop_chanmask,
        !          1370:                                                ((struct isopcb *)isop)->isop_negchanmask
        !          1371:                                        );
        !          1372:                                ENDDEBUG
        !          1373:                                tsleep( (caddr_t)&copcb->co_state, PZERO+1,
        !          1374:                                        SLP_ISO_CONSOUT, 0);
        !          1375:                                IFDEBUG(D_CCONS)
        !          1376:                                        printf("AFTER SLEEP 1 chan 0x%x chanmask 0x%x negchanmask 0x%x\n",
        !          1377:                                                copcb->co_channel, isop->isop_chanmask, 
        !          1378:                                                isop->isop_negchanmask);
        !          1379:                                ENDDEBUG
        !          1380:                        }
        !          1381:                        if( !error )
        !          1382:                                SET_CHANMASK( isop, copcb->co_channel);
        !          1383:                }
        !          1384: 
        !          1385:        } 
        !          1386: 
        !          1387:        IFDEBUG(D_CDATA)
        !          1388:                printf("cons_output calling senddata(0x%x 0x%x)\n", copcb, m);
        !          1389:                ASSERT(m != MNULL);
        !          1390:                ASSERT(m->m_len != 0);
        !          1391:        ENDDEBUG
        !          1392: 
        !          1393:        if( !error )
        !          1394:                error =  cons_senddata( copcb, m);
        !          1395:        splx(s);
        !          1396:        return error;
        !          1397: }
        !          1398: 
        !          1399: /*
        !          1400:  * NAME:       cons_openvc()
        !          1401:  * CALLED FROM:
        !          1402:  *  TP when it decides to open a VC for TP 0
        !          1403:  * FUNCTION:
        !          1404:  *  opens a connection and stashes the pcb info in the socket
        !          1405:  *  substitute for iso_pcbconnect/ in_pcbconnect for the class 0 case
        !          1406:  *  only.
        !          1407:  */
        !          1408: int
        !          1409: cons_openvc(copcb, faddr, so)
        !          1410:        struct cons_pcb                         *copcb;
        !          1411:        struct  sockaddr_iso    *faddr;
        !          1412:        struct  socket                  *so;
        !          1413: {
        !          1414:        int                                     error = 0;
        !          1415:        int                                     s = splnet();
        !          1416:        struct cons_pcb                 *cons_chan_to_pcb();
        !          1417: 
        !          1418: 
        !          1419:        ASSERT( copcb->co_socket == so );
        !          1420:        IFTRACE(D_CCONN)
        !          1421:                tptrace(TPPTmisc, "cons_openvc( copcb so )\n", copcb, so, 0, 0);
        !          1422:        ENDTRACE
        !          1423:        IFDEBUG(D_CCONN)
        !          1424:                printf("cons_openvc( copcb 0x%x, so 0x%x )\n", copcb,so);
        !          1425:        ENDDEBUG
        !          1426:        /*
        !          1427:         * initialize the copcb part of the isopcb
        !          1428:         */
        !          1429:        copcb->co_ttl = copcb->co_init_ttl = X25_TTL;
        !          1430:        copcb->co_flags = CONSF_OCRE;
        !          1431:        copcb->co_proto = TP_proto;
        !          1432:        copcb->co_pending.ifq_maxlen = CONS_IFQMAXLEN;
        !          1433: 
        !          1434:        /* abbreviated form of iso_pcbconnect(): */
        !          1435:        bcopy((caddr_t)faddr, (caddr_t)&copcb->co_faddr, 
        !          1436:                                                                sizeof(struct sockaddr_iso));
        !          1437: 
        !          1438:        ASSERT( copcb->co_socket == so );
        !          1439:        if( error = cons_connect( copcb ) )
        !          1440:                goto done;
        !          1441:        while( (copcb->co_state != OPEN) && !(error = so->so_error) ) {
        !          1442:                IFDEBUG(D_CCONS)
        !          1443:                        printf(
        !          1444:                "SLEEP2 copcb 0x%x state 0x%x chan 0x%x mask 0x%x neg 0x%x\n",
        !          1445:                                copcb, copcb->co_state, copcb->co_channel, 
        !          1446:                                copcb->co_chanmask,
        !          1447:                                copcb->co_negchanmask
        !          1448:                        );
        !          1449:                ENDDEBUG
        !          1450:                tsleep((caddr_t)&copcb->co_state, PZERO+2, SLP_ISO_CONSCONN, 0);
        !          1451:                IFDEBUG(D_CCONS)
        !          1452:                        printf("AFTER SLEEP2 chan 0x%x chanmask 0x%x negchanmask 0x%x\n",
        !          1453:                                copcb->co_channel, copcb->co_chanmask, 
        !          1454:                                copcb->co_negchanmask);
        !          1455:                ENDDEBUG
        !          1456:        }
        !          1457:        if( !error )
        !          1458:                SET_CHANMASK( (struct isopcb *)copcb, copcb->co_channel); 
        !          1459: done:
        !          1460:        ASSERT( copcb->co_socket == so );
        !          1461:        splx(s);
        !          1462: 
        !          1463:        IFDEBUG(D_CCONN)
        !          1464:                printf("cons_openvc: copcb 0x%x error 0x%x\n", copcb, error );
        !          1465:        ENDDEBUG
        !          1466:        return error;
        !          1467: }
        !          1468: 
        !          1469: /*
        !          1470:  * NAME:       cons_netcmd()
        !          1471:  * CALLED FROM:
        !          1472:  *  tp_route_to() when it decides to accept or reject an incoming
        !          1473:  *  connection it calls this.
        !          1474:  * FUNCTION:
        !          1475:  *  either closes the cons connection named by (channel)
        !          1476:  *  or associates the copcb with the channel #.
        !          1477:  *     and removes the old copcb from the tp_incoming_pending list.
        !          1478:  */
        !          1479: int
        !          1480: cons_netcmd(cmd, isop, channel, isdgm)
        !          1481:        int                                     cmd;
        !          1482:        struct isopcb                   *isop; 
        !          1483:        int                                             channel;
        !          1484: {
        !          1485:        int                                     s = splnet();
        !          1486:        int                                     error = 0;
        !          1487:        struct cons_pcb                 *copcb = (struct cons_pcb *)0;
        !          1488:        struct cons_pcb                 *cons_chan_to_pcb();
        !          1489: 
        !          1490:        IFTRACE(D_CCONN)
        !          1491:                tptrace(TPPTmisc, "cons_netcmd( cmd isopcb channel isdgm)\n", 
        !          1492:                        cmd,isop,channel, isdgm);
        !          1493:        ENDTRACE
        !          1494:        IFDEBUG(D_CCONN)
        !          1495:                printf("cons_netcmd( cmd 0x%x, isop 0x%x, channel 0x%x, isdgm 0x%x)\n", 
        !          1496:                        cmd,isop,channel, isdgm);
        !          1497:                if( isop )
        !          1498:                        printf("cons_netcmd: isop->socket 0x%x\n", 
        !          1499:                        isop->isop_socket);
        !          1500:        ENDDEBUG
        !          1501:        ASSERT(cmd != CONN_OPEN);
        !          1502: 
        !          1503:        /* Can we find a cons-level pcb based on channel? */
        !          1504:        if(channel) {
        !          1505:                if((copcb = 
        !          1506: #ifdef ARGO_DEBUG
        !          1507:                        cons_chan_to_pcb( channel, __LINE__ )
        !          1508: #else ARGO_DEBUG
        !          1509:                        cons_chan_to_pcb( channel)
        !          1510: #endif ARGO_DEBUG
        !          1511:                                ) == (struct cons_pcb *)0) {
        !          1512:                        error = ECONNABORTED;
        !          1513:                        splx(s);
        !          1514:                        return error;
        !          1515:                }
        !          1516:                if( copcb == (struct cons_pcb *) isop ) {
        !          1517:                        copcb = (struct cons_pcb *)0;
        !          1518:                        /* avoid operating on a pcb twice */
        !          1519:                } else {
        !          1520:                        /* if isop is null (close/refuse):
        !          1521:                         * this would remove from the TP list, which is NOT what we want 
        !          1522:                         * so only remove if there is an isop (gag)
        !          1523:                         */
        !          1524:                        if( isop ) {
        !          1525:                                remque((struct cons_pcb *)copcb); /* take it off pending list */
        !          1526:                        } else {
        !          1527:                                ASSERT( (cmd == CONN_CLOSE) || (cmd == CONN_REFUSE) );
        !          1528:                        }
        !          1529:                }
        !          1530:        }
        !          1531:        /* now we have one of these cases:
        !          1532:         * 1) isop is non-null and copcb is null 
        !          1533:         * 2) isop is non-null and copcb is non-null and they are different
        !          1534:         * 3) isop is null and copcb is non-null 
        !          1535:         */
        !          1536:        ASSERT( (isop != (struct isopcb *)0) || (copcb != (struct cons_pcb *)0));
        !          1537: 
        !          1538:        switch(cmd) {
        !          1539: 
        !          1540:                case CONN_CONFIRM:
        !          1541:                        if( isdgm ) {
        !          1542:                                /* we want two separate pcbs */
        !          1543:                                /* if we don't have a copcb, get one */
        !          1544: 
        !          1545:                                if( copcb == (struct cons_pcb *)0 ) {
        !          1546:                                        if(( error = cons_pcballoc(&dummysocket, &cons_isopcb, 
        !          1547:                                                ((struct cons_pcb *)isop)->co_flags,
        !          1548:                                                TP_proto, &copcb)) != EOK )
        !          1549:                                                        return error;
        !          1550:                                        /* copy missing info from isop */
        !          1551:                                        copcb->co_laddr = isop->isop_laddr;
        !          1552:                                        copcb->co_faddr = isop->isop_faddr;
        !          1553:                                        /* don't care about tsuffices */
        !          1554:                                        ((struct cons_pcb *)isop)->co_channel  = 0; 
        !          1555:                                                                                                /* no longer used */
        !          1556: 
        !          1557:                                        copcb->co_ifp = ((struct cons_pcb *)isop)->co_ifp ;
        !          1558:                                        ASSERT( copcb->co_pending.ifq_len == 0 );
        !          1559: 
        !          1560:                                } else {
        !          1561:                                        insque((struct isopcb *)copcb, 
        !          1562:                                                (struct isopcb *)&cons_isopcb); 
        !          1563:                                }
        !          1564:                                copcb->co_state = OPEN;
        !          1565:                                copcb->co_flags |= CONSF_DGM;
        !          1566:                                copcb->co_channel = channel;
        !          1567:                                ASSERT(copcb->co_channel != 0);
        !          1568: 
        !          1569:                                IFDEBUG(D_CCONN)
        !          1570:                                        printf("cons_netcmd: put 0x%x on regular list \n", copcb);
        !          1571:                                ENDDEBUG
        !          1572:                        } else { 
        !          1573:                                /* must be TP 0, since this is never called from XTS code */
        !          1574:                                /* we want ONE pcb, namely isop.
        !          1575:                                 * If this TPE were the active side,
        !          1576:                                 * there ought not to be a copcb, since TP should
        !          1577:                                 * know that you can't send a CR with dgm and negot down
        !          1578:                                 * to non-dgm.
        !          1579:                                 * If this TPE were the passive side, we want to copy from
        !          1580:                                 * the copcb that was on the pending list, and delete the
        !          1581:                                 * pending copcb.
        !          1582:                                 */
        !          1583:                                if( copcb ) {
        !          1584:                                        IFDEBUG(D_CCONN)
        !          1585:                                                printf("cons_netcmd: copied info from 0x%x to 0x%x\n", 
        !          1586:                                                        copcb, isop);
        !          1587:                                        ENDDEBUG
        !          1588:                                        isop->isop_laddr = copcb->co_laddr;
        !          1589:                                        isop->isop_faddr = copcb->co_faddr;
        !          1590:                                        /* tsuffices, socket should be there already */
        !          1591:                                        ((struct cons_pcb *)isop)->co_flags = 
        !          1592:                                                                        copcb->co_flags & ~CONSF_DGM;
        !          1593:                                        ((struct cons_pcb *)isop)->co_init_ttl = copcb->co_init_ttl;
        !          1594:                                        touch(((struct cons_pcb *)isop));
        !          1595:                                        ((struct cons_pcb *)isop)->co_channel = channel;
        !          1596:                                        ((struct cons_pcb *)isop)->co_ifp = copcb->co_ifp;
        !          1597:                                        ((struct cons_pcb *)isop)->co_proto = copcb->co_proto;
        !          1598:                                        ((struct cons_pcb *)isop)->co_myself = 
        !          1599:                                                (struct cons_pcb *)isop;
        !          1600:                                        SET_CHANMASK( isop, ((struct cons_pcb *)isop)->co_channel );
        !          1601:                                        ASSERT( copcb->co_pending.ifq_len == 0 );
        !          1602: 
        !          1603:                                        /* get rid of the copcb that was on the pending list */
        !          1604:                                        (void) m_free(dtom(copcb));
        !          1605:                                } 
        !          1606:                                ((struct cons_pcb *)isop)->co_state = OPEN;
        !          1607:                        }
        !          1608:                        break;
        !          1609: 
        !          1610:                case CONN_CLOSE:
        !          1611:                case CONN_REFUSE:
        !          1612:                        /* if dgm then ignore; the connections will 
        !          1613:                         * be re-used or will time out
        !          1614:                         */
        !          1615:                        if( isdgm ) 
        !          1616:                                break;
        !          1617: 
        !          1618:                        /* we should never come in here with both isop and copcb
        !          1619:                         * unless is dgm, hence the following assertion:
        !          1620:                         */
        !          1621:                        ASSERT( (copcb == (struct cons_pcb *)0) || 
        !          1622:                                (isop == (struct isopcb *)0) );
        !          1623: 
        !          1624:                        /* close whichever pcb we have */
        !          1625:                        if( copcb )
        !          1626:                                error = cons_clear(copcb, (cmd == CONN_CLOSE)?
        !          1627:                                        E_CO_HLI_DISCN:E_CO_HLI_REJT);
        !          1628:                        if( isop )
        !          1629:                                error = cons_clear((struct cons_pcb *)isop, (cmd == CONN_CLOSE)?
        !          1630:                                        E_CO_HLI_DISCN:E_CO_HLI_REJT);
        !          1631: 
        !          1632:                        if(copcb &&  (copcb->co_socket == (struct socket *)0) ) {
        !          1633:                                ASSERT( copcb->co_flags & (CONSF_DGM | CONSF_ICRE) );
        !          1634:                                (void) m_free(dtom(copcb)); /* detached */
        !          1635:                        }
        !          1636:                        /* isop will always be detached by the higher layer */
        !          1637:                        break;
        !          1638:                default:
        !          1639:                        error = EOPNOTSUPP;
        !          1640:                        break;
        !          1641:        }
        !          1642:        splx(s);
        !          1643: 
        !          1644:        IFDEBUG(D_CCONN)
        !          1645:                printf("cons_netcmd returns 0x%x: isop 0x%x\n", isop, error );
        !          1646:        ENDDEBUG
        !          1647:        return error;
        !          1648: }
        !          1649: 
        !          1650: 
        !          1651: /*
        !          1652:  * NAME:       addr_proto_consistency_check()
        !          1653:  * CALLED FROM: cons_incoming()
        !          1654:  * FUNCTION and ARGUMENTS:
        !          1655:  *  Enforces a set of rules regarding what addresses will serve
        !          1656:  *  what protocol stack.  This is a kludge forced upon us by the
        !          1657:  *  fact that there's no way to tell which NET layer you want to
        !          1658:  *  run when opening a socket.  Besides, no doubt, OSI directory
        !          1659:  *  services won't advertise any kind of a protocol stack with the
        !          1660:  *  NSAPs.  sigh.
        !          1661:  * RETURNS
        !          1662:  *     EAFNOSUPPORT or EOK.
        !          1663:  */
        !          1664: Static int
        !          1665: addr_proto_consistency_check(proto, addr) 
        !          1666:        int                                             proto;
        !          1667:        struct  sockaddr_iso    *addr;
        !          1668: {
        !          1669:        switch( proto ) {
        !          1670:                case ISOPROTO_CLNP:
        !          1671:                        break;
        !          1672: 
        !          1673:                case ISOPROTO_INACT_NL:
        !          1674:                case ISOPROTO_CLTP:
        !          1675:                        return E_CO_HLI_PROTOID;
        !          1676: 
        !          1677:                case ISOPROTO_TP:
        !          1678:                case ISOPROTO_X25:
        !          1679:                        /* hl is TP or X.25 */
        !          1680:                        if (addr->siso_addr.isoa_afi != AFI_37)
        !          1681:                                return E_CO_AIWP;
        !          1682:                                /* kludge - necessary because this is the only type of
        !          1683:                                 * NSAP we build for an incoming NC
        !          1684:                                 */
        !          1685:                        break;
        !          1686:                default: /* unsupported */
        !          1687:                        return E_CO_HLI_PROTOID;
        !          1688:        }
        !          1689:        return EOK;
        !          1690: }
        !          1691: /* 
        !          1692:  * NAME:       cons_incoming()
        !          1693:  * CALLED FROM:
        !          1694:  *  consintr() for incoming OPEN
        !          1695:  * FUNCTION and ARGUMENTS:
        !          1696:  *  Determines which higher layer gets this call, and 
        !          1697:  *  thus whether to immediately accept, reject, or to let the
        !          1698:  *     higher layer determine this question. 
        !          1699:  */
        !          1700: Static 
        !          1701: cons_incoming(ifp, ecnrq)
        !          1702:        struct ifnet                                    *ifp;
        !          1703:        register struct eicon_request   *ecnrq;
        !          1704: {
        !          1705:        struct sockaddr_iso     me;
        !          1706:        struct sockaddr_iso     peer;
        !          1707:        struct cons_pcb                 *copcb;
        !          1708:        int                                     loop = 0;
        !          1709:        int                                             proto =0;
        !          1710:        int                                             error = 0;
        !          1711:        struct  dte_addr                peer_dte;
        !          1712: 
        !          1713:        IFDEBUG(D_INCOMING)
        !          1714:                printf("consincoming enter: ifp 0x%x ecnrq 0x%x\n", ifp, ecnrq);
        !          1715:        ENDDEBUG
        !          1716:        bzero( &me, sizeof(me));
        !          1717:        error = parse_facil( mtod(e_data(ecnrq), caddr_t), 
        !          1718:                                                (e_data(ecnrq))->m_len, &me, &peer, &proto,
        !          1719:                                                &peer_dte);
        !          1720:        loop = is_me( &peer ); /* <-- THIS may be a problem :
        !          1721:                                                        * peer may be nonsense.
        !          1722:                                                        * We can only expect that WE will do it right
        !          1723:                                                        * and never will we get an error return from
        !          1724:                                                        * parse_facil on a facil that WE generated,
        !          1725:                                                        * so if garbage comes in, peer will be garbage,
        !          1726:                                                        * and loop will be false.
        !          1727:                                                        */
        !          1728:        if( error != EOK ) {
        !          1729:                (void) issue_clear_req(ecnrq->e_vc, error, ifp, loop); 
        !          1730:                IncStat(co_parse_facil_err);
        !          1731:                IncStat(co_Rdrops);
        !          1732:                return;
        !          1733:        }
        !          1734: 
        !          1735:        if( (error = addr_proto_consistency_check(proto, &me)) != EOK ) {
        !          1736:                /* problem with consistency */
        !          1737:                (void) issue_clear_req(ecnrq->e_vc, error, ifp, loop);
        !          1738:                IncStat(co_addr_proto_consist_err);
        !          1739:                IncStat(co_Rdrops);
        !          1740:                return;
        !          1741:        } else {
        !          1742:                switch( proto ) {
        !          1743:                        case ISOPROTO_X25:
        !          1744:                                copcb = (struct cons_pcb *)
        !          1745:                                                ((struct cons_pcb *)(&cons_isopcb))->co_next;
        !          1746: 
        !          1747:                                while (copcb != (struct cons_pcb *)&cons_isopcb) {
        !          1748:                                        if( copcb->co_lport == me.siso_tsuffix ) {
        !          1749:                                                /* for cons "transport service",
        !          1750:                                                 * multiplexing is not allowed 
        !          1751:                                                 */
        !          1752:                                                if( !copcb->co_socket ) {
        !          1753:                                                        printf(
        !          1754:                                                        "PANIC cons_incoming NOT TP but no sock\n");
        !          1755:                                                        copcb = (struct cons_pcb *)0;
        !          1756:                                                        break;
        !          1757:                                                }
        !          1758:                                                if( copcb->co_socket->so_options & SO_ACCEPTCONN ) {
        !          1759:                                                        struct cons_pcb *newx;
        !          1760: 
        !          1761:                                                        newx = (struct cons_pcb *)
        !          1762:                                                                        sonewconn(copcb->co_socket)->so_pcb;
        !          1763:                                                        newx->co_laddr = copcb->co_laddr;
        !          1764:                                                        newx->co_peer_dte = peer_dte;
        !          1765:                                                        newx->co_proto = copcb->co_proto;
        !          1766:                                                        newx->co_myself = newx;
        !          1767:                                                        touch(copcb);
        !          1768:                                                        copcb = newx;
        !          1769:                                                        soisconnected(copcb->co_socket); 
        !          1770:                                                        break;
        !          1771:                                                } /* else keep looking */ 
        !          1772:                                        }
        !          1773:                                        copcb = (struct cons_pcb *)copcb->co_next;
        !          1774:                                }
        !          1775:                                if (copcb == (struct cons_pcb *)&cons_isopcb)
        !          1776:                                        copcb = (struct cons_pcb *) 0;
        !          1777:                                break;
        !          1778: 
        !          1779:                        case ISOPROTO_TP:
        !          1780:                                ASSERT( me.siso_tsuffix == 0 );
        !          1781:                                /*
        !          1782:                                 * We treat this rather like we do for CLNP.  
        !          1783:                                 * TP can't tell which socket
        !          1784:                                 * wants this until the TP header comes in, so there's no way
        !          1785:                                 * to associate this channel with a tpcb/isopcb.
        !          1786:                                 * We assume data will arrive (a CR TPDU) and be given to TP along with
        !          1787:                                 * the channel number.  We can then expect TP to call us with
        !          1788:                                 * the channel number and pcb ptr, telling us to keep this connection
        !          1789:                                 * or clear it.
        !          1790:                                 * Now, tp will have created an isopcb in the tp_isopcb list.
        !          1791:                                 * We will have to keep another copcb though, because there is no
        !          1792:                                 * 1-1 correspondence between socket and copcb when multiplexing
        !          1793:                                 * is allowed. 
        !          1794:                                 * But we want to save the peer address, ifp, and state, proto.
        !          1795:                                 * If the channel should clear before TP responds, we need
        !          1796:                                 * to know that also, so we create a tp-pending list...
        !          1797:                                 */
        !          1798:                                if( cons_pcballoc(&dummysocket, &tp_incoming_pending, 
        !          1799:                                                                CONSF_ICRE, TP_proto, &copcb) != EOK )  {
        !          1800:                                        copcb = (struct cons_pcb *)0;
        !          1801:                                } else {
        !          1802:                                        copcb->co_peer_dte = peer_dte;
        !          1803:                                }
        !          1804:                                break;
        !          1805: 
        !          1806: 
        !          1807:                        case ISOPROTO_CLNP:
        !          1808:                                if( cons_pcballoc(&dummysocket, &cons_isopcb, 
        !          1809:                                                CONSF_ICRE | CONSF_DGM, CLNP_proto, &copcb ) != EOK ) {
        !          1810:                                        /* choke */
        !          1811:                                        copcb = (struct cons_pcb *)0;
        !          1812:                                } else {
        !          1813:                                        copcb->co_peer_dte = peer_dte;
        !          1814:                                }
        !          1815:                                break;
        !          1816: 
        !          1817:                default:
        !          1818:                        panic("cons_incoming");
        !          1819:                } /* end switch */
        !          1820: 
        !          1821:                if(copcb) {
        !          1822:                        touch(copcb);
        !          1823:                        copcb->co_channel = (int)ecnrq->e_vc;
        !          1824:                        ASSERT( copcb->co_channel != 0);
        !          1825:                        copcb->co_state = OPEN;
        !          1826:                        copcb->co_ifp = ifp;
        !          1827:                        copcb->co_laddr = me;
        !          1828:                        copcb->co_faddr = peer;
        !          1829:                        if(loop)
        !          1830:                                copcb->co_flags |= CONSF_LOOPBACK;
        !          1831:                        IFDEBUG(D_CADDR)
        !          1832:                                printf("cons_incoming found XPCB 0x%x, loop 0x%x\n", 
        !          1833:                                                copcb, loop);
        !          1834:                                printf("\nco_laddr: ");
        !          1835:                                dump_buf(&copcb->co_laddr, sizeof(copcb->co_laddr));
        !          1836:                                printf("\nco_faddr: ");
        !          1837:                                dump_buf(&copcb->co_faddr, sizeof(copcb->co_faddr));
        !          1838:                                printf("\n");
        !          1839:                        ENDDEBUG
        !          1840:                } else {
        !          1841:                        ifp->if_ierrors ++;
        !          1842:                        (void) issue_clear_req(ecnrq->e_vc, E_CO_OSI_UNSAP, ifp, loop);
        !          1843:                        IncStat(co_no_copcb);
        !          1844:                        IncStat(co_Rdrops);
        !          1845:                }
        !          1846:        } 
        !          1847:        /* caller frees the mbuf so we don't have to do any such thing */
        !          1848: }
        !          1849: 
        !          1850: /*
        !          1851:  **************************** DEVICE cons ***************************
        !          1852:  */
        !          1853: 
        !          1854: /*
        !          1855:  * NAME:       cosns_output()
        !          1856:  * CALLED FROM:
        !          1857:  *  clnp - this routine is given as the device-output routine
        !          1858:  *  for the adcom driver.
        !          1859:  * FUNCTION and ARGUMENTS:
        !          1860:  *  (ifp) is the cons/adcom, found by routing function.
        !          1861:  *  (m0) is the clnp datagram.
        !          1862:  *  (dst) is the destination address
        !          1863:  * This routine finds an x.25 connection for datagram use and
        !          1864:  * sends the packet.
        !          1865:  */
        !          1866: int
        !          1867: cosns_output(ifp, m0, dst)
        !          1868: {
        !          1869:        return cosns_output1(ifp, m0, dst, CLNP_proto, NULL);
        !          1870: }
        !          1871: 
        !          1872: /* DEBUGGING ONLY? */
        !          1873: int    total_cosns_len = 0;
        !          1874: int    total_cosns_cnt = 0;
        !          1875: int    total_pkts_to_clnp = 0;
        !          1876: 
        !          1877: /*
        !          1878:  *             The isop is passed here so that if we have set x25crud in the
        !          1879:  *             pcb, it can be passed down to cons_connect. It could be null
        !          1880:  *             however, in the case of tp4/x25/clnp
        !          1881:  */
        !          1882: Static int
        !          1883: cosns_output1(ifp, m0, dst, proto, isop)
        !          1884:        struct ifnet *ifp;
        !          1885:        register struct mbuf *m0;
        !          1886:        struct sockaddr_iso *dst;
        !          1887:        struct protosw *proto;
        !          1888:        struct isopcb   *isop;          /* NULL if coming from clnp */
        !          1889: {
        !          1890:        register struct cons_pcb *copcb;
        !          1891:        int                                     s = splnet();
        !          1892:        int                                             error = 0;
        !          1893: 
        !          1894:        {       register struct mbuf *n=m0;
        !          1895:                register int len = 0;
        !          1896: 
        !          1897:                for(;;) {
        !          1898:                        len += n->m_len;
        !          1899:                        if (n->m_next == MNULL ) {
        !          1900:                                break;
        !          1901:                        }
        !          1902:                        n = n->m_next;
        !          1903:                }
        !          1904:                total_cosns_len += len;
        !          1905:                total_cosns_cnt ++;
        !          1906: 
        !          1907:        }
        !          1908: 
        !          1909:        IFDEBUG(D_CCONS)
        !          1910:                printf("cosns_output1( ifp 0x%x, m 0x%x, dst 0x%x )\n", ifp, m0, dst );
        !          1911:        ENDDEBUG
        !          1912:        if ( ! (copcb = cons_find( CONSF_DGM, dst, proto, 0, 0) )) {
        !          1913:                struct cons_pcb *newcopcb; /* so we can pass addr of this to pcballoc */
        !          1914: 
        !          1915:                if( (error = cons_pcballoc(&dummysocket, &cons_isopcb, 
        !          1916:                                CONSF_DGM | CONSF_OCRE, proto, &newcopcb) )  != EOK ) {
        !          1917:                        IFDEBUG(D_CCONS)
        !          1918:                                printf("cosns_output: no copcb; returns \n");
        !          1919:                        ENDDEBUG
        !          1920:                        (void) m_freem(m0);
        !          1921:                        goto done;
        !          1922:                }
        !          1923:                copcb = newcopcb;
        !          1924: 
        !          1925:                /* abbreviated form of iso_pcbconnect(): */
        !          1926:                bcopy((caddr_t)dst, (caddr_t)&copcb->co_faddr, 
        !          1927:                                                                        sizeof(struct sockaddr_iso));
        !          1928:                
        !          1929:                /* copy x25crud into copcb if necessary */
        !          1930:                if ((isop != NULL) && (isop->isop_x25crud_len > 0)) {
        !          1931:                        bcopy(isop->isop_x25crud, copcb->co_x25crud, 
        !          1932:                                isop->isop_x25crud_len);
        !          1933:                        copcb->co_x25crud_len = isop->isop_x25crud_len;
        !          1934:                }
        !          1935: 
        !          1936:                copcb->co_ifp = ifp; /* NULL IF COMING FROM TP4! */
        !          1937: 
        !          1938:                if ( error = cons_connect( copcb ) ) { /* if it doesn't work */
        !          1939:                        /* oh, dear, throw packet away */
        !          1940:                        remque((struct isopcb *)copcb);
        !          1941:                        (void) m_free(dtom(copcb));
        !          1942:                        (void) m_freem(m0);
        !          1943:                        goto done;
        !          1944:                }
        !          1945:        }
        !          1946:        IFDEBUG(D_CDATA)
        !          1947:                printf("cosns_output1 @ senddata: state 0x%x flags 0x%x channel 0x%x\n",
        !          1948:                        copcb->co_state, copcb->co_flags, copcb->co_channel);
        !          1949:        ENDDEBUG
        !          1950:        ASSERT(copcb->co_channel != X_NOCHANNEL);
        !          1951:        error = cons_senddata(copcb, m0); 
        !          1952: done:
        !          1953:        splx(s);
        !          1954:        return error;
        !          1955: }
        !          1956: 
        !          1957: 
        !          1958: /*
        !          1959:  **************************** TRANSPORT cons ***************************
        !          1960:  */
        !          1961: 
        !          1962: 
        !          1963: /*
        !          1964:  * NAME:       cons_detach()
        !          1965:  * CALLED FROM:
        !          1966:  *  cons_usrreq() on PRU_DETACH
        !          1967:  *  cons_netcmd() when TP releases a net connection
        !          1968:  *     cons_slowtimo()  when timeout releases a net connection
        !          1969:  * FUNCTION and ARGUMENT:
        !          1970:  *  removes the copcb from the list of copcbs in use, and frees the mbufs.
        !          1971:  *  detaches the pcb from the socket, where a socket exists.
        !          1972:  * RETURN VALUE:
        !          1973:  *  ENOTCONN if it couldn't find the copcb in the list of connections.
        !          1974:  */
        !          1975: 
        !          1976: Static int 
        !          1977: cons_detach( copcb )
        !          1978:        register struct cons_pcb *copcb;
        !          1979: {
        !          1980:        struct socket *so = copcb->co_socket;
        !          1981: 
        !          1982:        IFDEBUG(D_CCONN)
        !          1983:                printf("cons_detach( copcb 0x%x )\n", copcb);
        !          1984:        ENDDEBUG
        !          1985:        if(so) {
        !          1986:                if (so->so_head) {
        !          1987:                        if (!soqremque(so, 0) && !soqremque(so, 1))
        !          1988:                                panic("sofree dq");
        !          1989:                        so->so_head = 0;
        !          1990:                }
        !          1991:                ((struct isopcb *)copcb)->isop_options = 0; /* kludge */
        !          1992:                iso_pcbdetach(copcb); /* detaches from so */
        !          1993:        } else {
        !          1994:                remque((struct isopcb *)copcb);
        !          1995:                (void) m_free(dtom(copcb));
        !          1996:        }
        !          1997: }
        !          1998: 
        !          1999: Static int
        !          2000: cons_clear_and_detach(copcb, clearreason, ctlcmd)
        !          2001:        register struct cons_pcb *copcb;
        !          2002:        int                                     clearreason;
        !          2003:        int                                             ctlcmd;
        !          2004: {
        !          2005:        IFDEBUG(D_CCONN)
        !          2006:                printf("Clear and Detach (0x%x, 0x%x, 0x%x)\n", 
        !          2007:                                                copcb, clearreason, ctlcmd);
        !          2008:        ENDDEBUG
        !          2009:        if( clearreason != DONTCLEAR ) {
        !          2010:                (void) cons_clear( copcb ,  clearreason );
        !          2011:        }
        !          2012:        if( copcb->co_proto  && copcb->co_proto->pr_ctlinput )
        !          2013:                (*copcb->co_proto->pr_ctlinput)(ctlcmd, 
        !          2014:                        (struct sockaddr_iso *)&copcb->co_faddr, (caddr_t)copcb);
        !          2015: 
        !          2016:        if( copcb->co_socket == (struct socket *)0 ) {
        !          2017:                /* tp4, clnp users only */
        !          2018:                (void) cons_detach( copcb );
        !          2019:        } /* else detach will be called by the socket's closing */
        !          2020:                else {
        !          2021:                        ASSERT( copcb->co_socket != &dummysocket );
        !          2022:                        ASSERT( (copcb->co_flags & CONSF_DGM) == 0 );
        !          2023:        }
        !          2024:        IFDEBUG(D_CCONN)
        !          2025:                printf("END OF Clear and Detach (0x%x, 0x%x, 0x%x)\n", 
        !          2026:                                                copcb, clearreason, ctlcmd);
        !          2027:        ENDDEBUG
        !          2028: }
        !          2029: 
        !          2030: Static int
        !          2031: cons_pcbbind( copcb, nam )
        !          2032:        register struct cons_pcb *copcb;
        !          2033:        struct mbuf *nam;
        !          2034: {
        !          2035:        int error;
        !          2036: 
        !          2037:        if( error = iso_pcbbind( copcb, nam) )
        !          2038:                return error;
        !          2039: 
        !          2040:        /* iso_pcbbind already ensured that if port < 1024 it's superuser */
        !          2041:        /* Now we check: must be in range 0 .. 23 or in range 1024 .. 99 */
        !          2042: 
        !          2043:        if( (copcb->co_lport < X25_PORT_RESERVED)  || 
        !          2044:                         ((copcb->co_lport >= ISO_PORT_RESERVED) && 
        !          2045:                          (copcb->co_lport <= X25_PORT_USERMAX))) {
        !          2046:                munge( copcb->co_lport, (&copcb->co_laddr)->siso_addr.t37_idi +
        !          2047:                        ADDR37_IDI_LEN, 1 /* nibble */);
        !          2048:                munge( copcb->co_fport, (&copcb->co_faddr)->siso_addr.t37_idi +
        !          2049:                        ADDR37_IDI_LEN, 1 /* nibble */);
        !          2050:                 return 0;
        !          2051:        } else 
        !          2052:                return EADDRNOTAVAIL;
        !          2053: }
        !          2054: /*
        !          2055:  * NAME:       cons_usrreq()
        !          2056:  * CALLED FROM:
        !          2057:  *  user level via proto switch
        !          2058:  * FUNCTION and ARGUMENTS:
        !          2059:  *  so : socket
        !          2060:  *  req: which PRU* request
        !          2061:  *  m : data or mbuf ptr into which to stash data
        !          2062:  *     nam: mbuf ptr which is really a sockaddr_iso
        !          2063:  *  ifq: in PRU_CONTROL case, an ifnet structure 
        !          2064:  * RETURN VALUE:
        !          2065:  *  ENOTCONN if trying to do something which requires a connection
        !          2066:  *      and it's not yet connected
        !          2067:  *  EISCONN if trying to do something which cannot be done to a connection
        !          2068:  *      but it's connected
        !          2069:  *     ENOBUFS if ran out of mbufs
        !          2070:  *     EWOULDBLOCK if in nonblocking mode & can't send right away
        !          2071:  *     EOPNOSUPP if req isn't supported
        !          2072:  *     E* other passed up from lower layers or from other routines
        !          2073:  */
        !          2074: 
        !          2075: cons_usrreq(so, req, m, nam, ifp)
        !          2076:        struct socket *so;
        !          2077:        u_int req;
        !          2078:        struct mbuf *m, *nam;
        !          2079:        int *ifp; 
        !          2080: {      
        !          2081:        struct cons_pcb *copcb =  (struct cons_pcb *)so->so_pcb;
        !          2082:        int                                     s = splnet();
        !          2083:        int                                     error = 0;
        !          2084: 
        !          2085:        IFDEBUG(D_CCONS)
        !          2086:                printf("cons_usrreq 0x%x so 0x%x copcb 0x%x\n", req, so, copcb);
        !          2087:        ENDDEBUG
        !          2088:        if (req == PRU_CONTROL) {
        !          2089:                error =  iso_control(so, (int)m, (caddr_t)nam, (struct ifnet *)ifp);
        !          2090:                splx(s);
        !          2091:                return error;
        !          2092:        }
        !          2093:        if (copcb == (struct cons_pcb *)0  &&  req != PRU_ATTACH) {
        !          2094:                splx(s);
        !          2095:                return ENOTCONN;
        !          2096:        }
        !          2097: 
        !          2098:        switch (req) {
        !          2099: 
        !          2100:        case PRU_ATTACH:
        !          2101:                if (copcb) {
        !          2102:                        error = EISCONN;
        !          2103:                        break;
        !          2104:                }
        !          2105:                soreserve(so, X25_SBSIZE, X25_SBSIZE); /* CONS size */
        !          2106:                error = cons_pcballoc(so, &cons_isopcb, CONSF_XTS, X25_proto, &copcb );
        !          2107:                break;
        !          2108: 
        !          2109:        case PRU_ABORT:         /* called from close() */
        !          2110:                /* called for each incoming connect queued on the parent (accepting) 
        !          2111:                 * socket (SO_ACCEPTCONN); 
        !          2112:                 */
        !          2113:                 error = cons_detach ( copcb );
        !          2114:                 break;
        !          2115: 
        !          2116:        case PRU_DETACH:        /* called from close() */
        !          2117:                /* called after disconnect was called iff was connected at the time
        !          2118:                 * of the close, or directly if socket never got connected */
        !          2119:                error = cons_detach ( copcb );
        !          2120:                break;
        !          2121: 
        !          2122:        case PRU_SHUTDOWN:
        !          2123:                /* recv end may have been released; local credit might be zero  */
        !          2124:        case PRU_DISCONNECT:
        !          2125:                soisdisconnected(so);
        !          2126:                        error = cons_clear(copcb, E_CO_HLI_DISCN); 
        !          2127:                break;
        !          2128: 
        !          2129:        case PRU_BIND:
        !          2130:                error = cons_pcbbind( copcb, nam);
        !          2131:                break;
        !          2132: 
        !          2133:        case PRU_LISTEN:
        !          2134:                if (copcb->co_lport == 0) 
        !          2135:                        error = cons_pcbbind( copcb, 0 );
        !          2136:                break;
        !          2137: 
        !          2138: 
        !          2139:        case PRU_SOCKADDR: {
        !          2140:                        struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *);
        !          2141: 
        !          2142:                        nam->m_len = sizeof (struct sockaddr_iso);
        !          2143:                        if(copcb->co_ifp) 
        !          2144:                                bcopy( (caddr_t)&copcb->co_laddr,
        !          2145:                                                (caddr_t)siso, sizeof(struct sockaddr_iso) );
        !          2146: 
        !          2147:                        ((struct sockaddr_iso *)siso)->siso_tsuffix = copcb->co_lport;
        !          2148:                }
        !          2149:                break;
        !          2150: 
        !          2151:        case PRU_PEERADDR:
        !          2152:                if( (so->so_state & SS_ISCONNECTED) && 
        !          2153:                        (so->so_state & SS_ISDISCONNECTING) == 0) {
        !          2154:                                struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *);
        !          2155: 
        !          2156:                        nam->m_len = sizeof (struct sockaddr_iso);
        !          2157:                        bcopy( (caddr_t)&copcb->co_faddr, (caddr_t)siso, 
        !          2158:                                                                        sizeof(struct sockaddr_iso) );
        !          2159:                } else 
        !          2160:                        error = ENOTCONN;
        !          2161:                break;
        !          2162: 
        !          2163:        case PRU_CONNECT:
        !          2164:                /* TODO: We need to bind to the RIGHT interface. 
        !          2165:                 * The only way to have the right interface is to have
        !          2166:                 * the right route.
        !          2167:                 */
        !          2168:                IFDEBUG(D_CCONN)
        !          2169:                        printf("PRU_CONNECT 1: local tsuffix 0x%x so->so_head 0x%x nam:\n", 
        !          2170:                                copcb->co_lport, so->so_head);
        !          2171:                        dump_isoaddr( mtod(nam, struct sockaddr_iso *) );
        !          2172:                ENDDEBUG
        !          2173:                if (copcb->co_lport == 0) {
        !          2174:                        if( error = cons_pcbbind( copcb, 0 ))
        !          2175:                                break;
        !          2176:                }
        !          2177:                IFDEBUG(D_CCONN)
        !          2178:                        printf("PRU_CONNECT 2: local tsuffix 0x%x so->so_head 0x%x nam:\n", 
        !          2179:                                copcb->co_lport, so->so_head);
        !          2180:                        dump_isoaddr( mtod(nam, struct sockaddr_iso *) );
        !          2181:                ENDDEBUG
        !          2182: 
        !          2183:                {       /* change the destination address so the last 2 digits
        !          2184:                         * are the port/suffix/selector (whatever you want to call it)
        !          2185:                         */
        !          2186:                        register struct sockaddr_iso *siso =
        !          2187:                                                        mtod(nam, struct sockaddr_iso *);
        !          2188:                        if( (siso->siso_tsuffix < X25_PORT_RESERVED)  || 
        !          2189:                                 ((siso->siso_tsuffix >= ISO_PORT_RESERVED) && 
        !          2190:                                  (siso->siso_tsuffix <= X25_PORT_USERMAX)))
        !          2191:                        munge( siso->siso_tsuffix, 
        !          2192:                                        siso->siso_addr.t37_idi + ADDR37_IDI_LEN, 
        !          2193:                                        1 /* nibble */);
        !          2194:                }
        !          2195:                
        !          2196:                soisconnecting(so);
        !          2197:                if (error = iso_pcbconnect(copcb, nam))
        !          2198:                        break;
        !          2199:                error = cons_connect( copcb );
        !          2200:                if ( error ) {
        !          2201:                        /*
        !          2202:                        remque((struct isopcb *)copcb);
        !          2203:                        (void) m_free(dtom(copcb));
        !          2204:                        */
        !          2205:                        break;
        !          2206:                }
        !          2207:                while( (copcb->co_state != OPEN)&&(copcb->co_socket->so_error == 0) ) {
        !          2208:                        IFDEBUG(D_CCONN)
        !          2209:                                printf("PRU_CONNECT: error 0x%x sleeping on 0x%x\n", 
        !          2210:                                        copcb->co_socket->so_error,
        !          2211:                                        (caddr_t)&copcb->co_state );
        !          2212:                        ENDDEBUG
        !          2213:                        sleep((caddr_t)&copcb->co_state, PZERO+3, SLP_ISO_CONS, 0 );
        !          2214:                }
        !          2215: 
        !          2216:                ASSERT( copcb->co_channel != 0);
        !          2217: 
        !          2218:                SET_CHANMASK ( (struct isopcb *)copcb, copcb->co_channel);
        !          2219:                break;
        !          2220: 
        !          2221:        case PRU_ACCEPT: 
        !          2222:                /* so here is the NEW socket */
        !          2223:                so->so_error = 0;
        !          2224:                if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTED)== 0) {
        !          2225:                        error = EWOULDBLOCK;
        !          2226:                        break;
        !          2227:                }
        !          2228:                {
        !          2229:                        struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *);
        !          2230: 
        !          2231:                        /* copy the peer's address into the return argument */
        !          2232:                        nam->m_len = sizeof (struct sockaddr_iso);
        !          2233:                        bcopy( (caddr_t)&copcb->co_faddr, (caddr_t)siso, 
        !          2234:                                sizeof(struct sockaddr_iso));
        !          2235:                }
        !          2236:                break;
        !          2237: 
        !          2238:        case PRU_SEND:
        !          2239:        case PRU_SENDEOT:
        !          2240:                /*
        !          2241:                 * sosend calls this until sbspace goes negative.
        !          2242:                 * Sbspace may be made negative by appending this mbuf chain,
        !          2243:                 * possibly by a whole cluster.
        !          2244:                 */
        !          2245:                {
        !          2246:                        /* no need to actually queue this stuff and dequeue it,
        !          2247:                         * just bump the pointers in so_snd so that higher
        !          2248:                         * layer of socket code will cause it to sleep when
        !          2249:                         * we've run out of socket space
        !          2250:                         * TODO:
        !          2251:                         * Unfortunately that makes sbflush vomit so we have
        !          2252:                         * to allocate a single real mbuf (say size 240)
        !          2253:                         * and sballoc it and sbfree it upon CONS_SEND_DONE.
        !          2254:                         * Oh, my, is this sickening or what?
        !          2255:                         */
        !          2256:                        {
        !          2257:                                struct mbuf *mx;
        !          2258:                                
        !          2259:                                MGET(mx, M_DONTWAIT, MT_DATA);
        !          2260:                                mx->m_len = MLEN;
        !          2261:                                sbappend((caddr_t)&copcb->co_socket->so_snd, mx);
        !          2262:                        }
        !          2263:                        if( m ) {
        !          2264:                                IFDEBUG(D_CDATA)
        !          2265:                                        printf("X.25 Usrreq calling cons_senddata(0x%x, 0x%x)\n",
        !          2266:                                                copcb, m);
        !          2267:                                ENDDEBUG
        !          2268:                                error = cons_senddata(copcb, m);
        !          2269:                        }
        !          2270:                        IFDEBUG(D_CCONS)
        !          2271:                                printf("PRU_SEND sent tsuffix 0x%x, m 0x%x error 0x%x\n", 
        !          2272:                                        copcb->co_lport, m, error);
        !          2273:                        ENDDEBUG
        !          2274: 
        !          2275:                        if( req == PRU_SENDEOT ) {
        !          2276:                                while(copcb->co_socket->so_snd.sb_cc > 0)
        !          2277:                                        sbwait(&copcb->co_socket->so_snd);
        !          2278:                        }
        !          2279:                }
        !          2280:                break;
        !          2281: 
        !          2282:        case PRU_CONTROL:
        !          2283:                error = cons_ioctl(so, m, (caddr_t)nam);
        !          2284:                break;
        !          2285: 
        !          2286: 
        !          2287:        case PRU_RCVD:
        !          2288:        case PRU_RCVOOB:
        !          2289:        case PRU_SENDOOB:
        !          2290:                /* COULD support INTERRUPT packets as oob */
        !          2291:        case PRU_PROTOSEND:
        !          2292:        case PRU_PROTORCV:
        !          2293:        case PRU_SENSE:
        !          2294:        case PRU_SLOWTIMO:
        !          2295:        case PRU_CONNECT2:
        !          2296:        case PRU_FASTTIMO:
        !          2297:        default:
        !          2298:                error = EOPNOTSUPP;
        !          2299:        }
        !          2300: 
        !          2301:        IFDEBUG(D_CCONS)
        !          2302:                printf("cons_usrreq cmd 0x%x copcb 0x%x returned error 0x%x\n", 
        !          2303:                        req, copcb, error);
        !          2304:        ENDDEBUG
        !          2305:        splx(s);
        !          2306:        return error;
        !          2307: }
        !          2308: 
        !          2309: /*
        !          2310:  * NAME:       cons_input()
        !          2311:  * CALLED FROM:
        !          2312:  *  consintr() through the isosw protosw for "transport" version of X25
        !          2313:  * FUNCTION & ARGUMENTS:
        !          2314:  *  process incoming data
        !          2315:  */
        !          2316: cons_input(m, faddr, laddr, so)
        !          2317:        register struct mbuf *m;
        !          2318:        struct sockaddr_iso *faddr, *laddr; /* not used */
        !          2319:        register struct socket *so;
        !          2320: {
        !          2321:        IFDEBUG(D_CCONS)
        !          2322:                printf("cons_input( m 0x%x, so 0x%x)\n", m,so);
        !          2323:        ENDDEBUG
        !          2324:        sbappend(&so->so_rcv, m);
        !          2325:        sbwakeup(&so->so_rcv);
        !          2326: }
        !          2327: 
        !          2328: #ifdef notdef
        !          2329: /*  
        !          2330:  * NAME:       cons_ctloutput()
        !          2331:  * CALLED FROM:
        !          2332:  *  set/get sockopts()
        !          2333:  *     Presently the protosw has 0 in the ctloutput spot
        !          2334:  *      because we haven't inplemented anything yet.
        !          2335:  *     If there's reason to put some options in here,
        !          2336:  *     be sure to stick this routine name in the protosw in iso_proto.c
        !          2337:  */
        !          2338: cons_ctloutput(cmd, so, level, optname, mp)
        !          2339:        int                     cmd, level, optname;
        !          2340:        struct socket   *so;
        !          2341:        struct mbuf     **mp;
        !          2342: {
        !          2343:        int                     s = splnet();
        !          2344: 
        !          2345:        splx(s);
        !          2346:        return EOPNOTSUPP;
        !          2347: }
        !          2348: #endif notdef
        !          2349: 
        !          2350: 
        !          2351: /* 
        !          2352:  * NAME:       cons_ctlinput()
        !          2353:  * CALLED FROM:
        !          2354:  *  lower layer when ECN_CLEAR occurs : this routine is here
        !          2355:  *  for consistency - cons subnet service calls its higher layer
        !          2356:  *  through the protosw entry.
        !          2357:  * FUNCTION & ARGUMENTS:
        !          2358:  *  cmd is a PRC_* command, list found in ../sys/protosw.h
        !          2359:  *  copcb is the obvious.
        !          2360:  *  This serves the higher-layer cons service.
        !          2361:  * NOTE: this takes 3rd arg. because cons uses it to inform itself
        !          2362:  *  of things (timeouts, etc) but has a pcb instead of an address.
        !          2363:  */
        !          2364: cons_ctlinput(cmd, sa, copcb)
        !          2365:        int cmd;
        !          2366:        struct sockaddr *sa;
        !          2367:        register struct cons_pcb *copcb;
        !          2368: {
        !          2369:        int                     error = 0;
        !          2370:        int                     s = splnet();
        !          2371:        extern u_char   inetctlerrmap[];
        !          2372:        extern int              iso_rtchange();
        !          2373: 
        !          2374:        IFDEBUG(D_CCONS)
        !          2375:                printf("cons_ctlinput( cmd 0x%x, copcb 0x%x)\n", cmd, copcb);
        !          2376:        ENDDEBUG
        !          2377:        /* co_socket had better exist */
        !          2378:        switch (cmd) {
        !          2379:                case PRC_CONS_SEND_DONE:
        !          2380:                        ASSERT( copcb->co_socket );
        !          2381:                        ASSERT( copcb->co_flags & CONSF_XTS );
        !          2382:                        sbdrop((caddr_t)&copcb->co_socket->so_snd, MLEN);
        !          2383:                        sbwakeup((caddr_t)&copcb->co_socket->so_snd);
        !          2384:                        break;
        !          2385: 
        !          2386:                case PRC_ROUTEDEAD:
        !          2387:                        error = ENETUNREACH;
        !          2388:                        break;
        !          2389: 
        !          2390:                case PRC_TIMXCEED_REASS:
        !          2391:                        error = ETIMEDOUT;
        !          2392:                        break;
        !          2393: 
        !          2394:        /*
        !          2395:                case PRC_QUENCH:
        !          2396:                        iso_pcbnotify(&cons_pcb, sa,
        !          2397:                                        (int)inetctlerrmap[cmd], iso_rtchange);
        !          2398:                        iso_pcbnotify(&tp_incoming_pending, sa,
        !          2399:                                        (int)inetctlerrmap[cmd], tpiso_quench);
        !          2400:                        iso_pcbnotify(&tp_isopcb, sa,
        !          2401:                                        (int)inetctlerrmap[cmd], tpiso_quench);
        !          2402:        */
        !          2403: 
        !          2404:                case PRC_IFDOWN:
        !          2405:                        iso_pcbnotify(&cons_isopcb, sa,
        !          2406:                                        (int)inetctlerrmap[cmd], iso_rtchange);
        !          2407:                        iso_pcbnotify(&tp_incoming_pending, sa,
        !          2408:                                        (int)inetctlerrmap[cmd], iso_rtchange);
        !          2409:                        iso_pcbnotify(&tp_isopcb, sa,
        !          2410:                                        (int)inetctlerrmap[cmd], iso_rtchange);
        !          2411:                        break;
        !          2412: 
        !          2413: 
        !          2414:                default:
        !          2415:                        printf("cons_ctlinput: unknown cmd 0x%x\n", cmd);
        !          2416:        }
        !          2417:        if(error) {
        !          2418:                soisdisconnected(copcb->co_socket);
        !          2419:                sohasoutofband(copcb->co_socket);
        !          2420:        }
        !          2421:        splx(s);
        !          2422: }
        !          2423: 
        !          2424: /*
        !          2425:  *********************** SERVES ALL cons embodiments  *******************
        !          2426:  */
        !          2427: 
        !          2428: /* 
        !          2429:  * NAME:       cons_chan_to_pcb()
        !          2430:  * CALLED FROM:
        !          2431:  *  cons_chan_to_tpcb() in tp_cons.c
        !          2432:  * and in this file: incoming requests that give only a channel number, i.e.,
        !          2433:  *  ECN_ACCEPT, ECN_RECEIVE, ECN_CLEAR
        !          2434:  * FUNCTION:
        !          2435:  *  identify the pcb assoc with that channel
        !          2436:  * RETURN:
        !          2437:  *  ptr to the pcb
        !          2438:  */
        !          2439: struct cons_pcb *
        !          2440: #ifdef ARGO_DEBUG
        !          2441: cons_chan_to_pcb( channel, linenumber )
        !          2442:        int     linenumber;
        !          2443: #else ARGO_DEBUG
        !          2444: cons_chan_to_pcb( channel)
        !          2445: #endif ARGO_DEBUG
        !          2446:        register int channel;
        !          2447: {
        !          2448:        register struct cons_pcb **copcblist = (struct cons_pcb **)Xpcblist;
        !          2449:        register struct cons_pcb *copcb;
        !          2450: 
        !          2451:        /* just to be sure */
        !          2452:        channel = channel & 0xff;
        !          2453: 
        !          2454:        for( copcb = *copcblist; copcb; copcb = *(++copcblist) ) {
        !          2455:                copcb = (struct cons_pcb *)copcb->co_next;
        !          2456:                while (copcb !=  *copcblist) {
        !          2457:                        if ( copcb->co_channel == channel ) 
        !          2458:                                goto found; /* want to break out of both loops */
        !          2459: 
        !          2460:                        copcb = (struct cons_pcb *)copcb->co_next;
        !          2461:                }
        !          2462:        }
        !          2463: found: /* or maybe not... */
        !          2464:        IFDEBUG(D_CCONS)
        !          2465:                printf("cons_chan_to_pcb( 0x%x, %d ) %s 0x%x\n", channel, linenumber,
        !          2466:                        copcb?"FOUND":"FAILED", copcb);
        !          2467:        ENDDEBUG
        !          2468: 
        !          2469:        return copcb;
        !          2470: }
        !          2471: 
        !          2472: 
        !          2473: /*
        !          2474:  * NAME:       is_me()
        !          2475:  * CALLED FROM:
        !          2476:  *  cons_incoming().  Perhaps could just expand in line.
        !          2477:  * FUNCTION and ARGUMENTS:
        !          2478:  *     for the given remote address (remadr) if it exactly matches
        !          2479:  *  one of the addresses of ME, and I am up as loopback, 
        !          2480:  *  return TRUE, else return FALSE.
        !          2481:  * RETURNS:
        !          2482:  *  Boolean
        !          2483:  */
        !          2484: Static int
        !          2485: is_me(remaddr)
        !          2486:        struct  sockaddr_iso    *remaddr;
        !          2487: {
        !          2488:        struct  ifnet                   *ifp = consif;
        !          2489:                                                                        /* PHASE2: this is ok */
        !          2490:        struct ifaddr                   *ifa = ifa_ifwithaddr(remaddr);
        !          2491: 
        !          2492:        IFDEBUG(D_CADDR)
        !          2493:                printf("is_me: withaddr returns %s\n", 
        !          2494:                        ifa?ifa->ifa_ifp->if_name:"NONE");
        !          2495:        ENDDEBUG
        !          2496:        if( ifa ) {
        !          2497:                /* remaddr matches one of my interfaces exactly */
        !          2498:                if( ifa->ifa_ifp->if_flags & IFF_LOOPBACK ) {
        !          2499:                        ASSERT( ifp == ifa->ifa_ifp );
        !          2500:                        return 1;
        !          2501:                }
        !          2502:        }
        !          2503:        return 0;
        !          2504: }
        !          2505: 
        !          2506: find_error_reason( ecnrq )
        !          2507:        register struct eicon_request   *ecnrq;
        !          2508: {
        !          2509:        extern u_char x25_error_stats[];
        !          2510:        int error;
        !          2511:        struct mbuf *cdm;
        !          2512:        struct e_clear_data *ecd;
        !          2513: 
        !          2514:        cdm = e_data(ecnrq);
        !          2515:        if( cdm && cdm->m_len > 0 ) {
        !          2516:                ecd = mtod(cdm, struct e_clear_data *);
        !          2517:                switch( ecd->ecd_cause ) {
        !          2518:                        case 0x00:
        !          2519:                        case 0x80:
        !          2520:                                /* DTE originated; look at the diagnostic */
        !          2521:                                error = (CONL_ERROR_MASK | ecd->ecd_diagnostic);
        !          2522:                                goto done;
        !          2523: 
        !          2524:                        case 0x01: /* number busy */
        !          2525:                        case 0x81:
        !          2526:                        case 0x09: /* Out of order */
        !          2527:                        case 0x89:
        !          2528:                        case 0x11: /* Remot Procedure Error */
        !          2529:                        case 0x91:
        !          2530:                        case 0x19: /* reverse charging accept not subscribed */
        !          2531:                        case 0x99:
        !          2532:                        case 0x21: /* Incampat destination */
        !          2533:                        case 0xa1:
        !          2534:                        case 0x29: /* fast select accept not subscribed */
        !          2535:                        case 0xa9:
        !          2536:                        case 0x39: /* ship absent */
        !          2537:                        case 0xb9:
        !          2538:                        case 0x03: /* invalid facil request */
        !          2539:                        case 0x83:
        !          2540:                        case 0x0b: /* access barred */
        !          2541:                        case 0x8b:
        !          2542:                        case 0x13: /* local procedure error */
        !          2543:                        case 0x93:
        !          2544:                        case 0x05: /* network congestion */
        !          2545:                        case 0x85:
        !          2546:                        case 0x8d: /* not obtainable */
        !          2547:                        case 0x0d:
        !          2548:                        case 0x95: /* RPOA out of order */
        !          2549:                        case 0x15:
        !          2550:                                /* take out bit 8 
        !          2551:                                 * so we don't have to have so many perror entries 
        !          2552:                                 */
        !          2553:                                error = (CONL_ERROR_MASK | 0x100 | (ecd->ecd_cause & ~0x80));
        !          2554:                                goto done;
        !          2555: 
        !          2556:                        case 0xc1: /* gateway-detected proc error */
        !          2557:                        case 0xc3: /* gateway congestion */
        !          2558: 
        !          2559:                                error = (CONL_ERROR_MASK | 0x100 | ecd->ecd_cause);
        !          2560:                                goto done;
        !          2561:                } 
        !          2562:        } 
        !          2563:        /* otherwise, a *hopefully* valid perror exists in the e_reason field */
        !          2564:        error = ecnrq->e_reason;
        !          2565:        if (error = 0) {
        !          2566:                printf("Incoming PKT TYPE 0x%x with reason 0x%x\n",
        !          2567:                        ecnrq->e_cmd,
        !          2568:                        ecnrq->e_reason);
        !          2569:                error = E_CO_HLI_DISCA;
        !          2570:        } 
        !          2571: 
        !          2572: done:
        !          2573:        if(error & 0x1ff == 0) {
        !          2574:                error = 0;
        !          2575:        } else if( error & 0x1ff > sizeof(x25_error_stats)) {
        !          2576:                        ASSERT(0);
        !          2577:        } else {
        !          2578:                        x25_error_stats[error& 0x1ff] ++;
        !          2579:        }
        !          2580:        return error;
        !          2581: }
        !          2582: 
        !          2583: /*
        !          2584:  * NAME:       consintr()
        !          2585:  * CALLED FROM:
        !          2586:  *  the eicon driver via software interrupt
        !          2587:  * FUNCTION and ARGUMENTS:
        !          2588:  *  processes incoming indications, passing them
        !          2589:  *  along to clnp, tp, or x.25-transport as appropriate.
        !          2590:  */
        !          2591: consintr()
        !          2592: {
        !          2593:        struct  ifnet                                   *ifp = consif;
        !          2594:        register struct eicon_request   *ecnrq;
        !          2595:        register struct cons_pcb                *copcb = (struct cons_pcb *)0;
        !          2596:        register struct mbuf                    *m;
        !          2597:        int                                                     s, s0 = splnet();
        !          2598: 
        !          2599:        IncStat(co_intr);
        !          2600:        ifp->if_ipackets ++;
        !          2601: 
        !          2602:        for(;;) {
        !          2603:                /*
        !          2604:                 * Get next request off input queue 
        !          2605:                 */
        !          2606:                s = splimp();
        !          2607:                IF_DEQUEUE(&consintrq, m);
        !          2608:                splx(s);
        !          2609:                IFDEBUG(D_INCOMING)
        !          2610:                        printf("cons intr() 0x%x m_off 0x%x m_len 0x%x dequeued\n",
        !          2611:                                m, m?m->m_off:0, m?m->m_len:0);
        !          2612:                ENDDEBUG
        !          2613: 
        !          2614:                if (m == 0) {
        !          2615:                        splx(s0);
        !          2616:                        return;
        !          2617:                }
        !          2618: 
        !          2619:                if((m->m_off != MMINOFF)||(m->m_len != sizeof (struct eicon_request))){
        !          2620:                        ifp->if_ierrors ++;
        !          2621:                        IncStat(co_Rdrops);
        !          2622:                        printf("Cons R DROP! BAD MBUF FROM LL 0x%x sizeof(...) 0x%x\n", 
        !          2623:                                        m, sizeof(struct eicon_request));
        !          2624:                        continue;
        !          2625:                }
        !          2626:                
        !          2627:                ecnrq = mtod(m, struct eicon_request *);
        !          2628: 
        !          2629: 
        !          2630:                IFDEBUG(D_INCOMING)
        !          2631:                        printf("INTR: e_cmd 0x%x, e_data 0x%x\n", ecnrq->e_cmd,
        !          2632:                                e_data(ecnrq));
        !          2633:                        if( e_data(ecnrq) != 0 ) {
        !          2634:                                /* let's just look at the first few bytes */
        !          2635:                                /*
        !          2636:                                dump_buf( e_data(ecnrq), (e_data(ecnrq))->m_len + 12);
        !          2637:                                */
        !          2638:                                dump_buf( e_data(ecnrq), 20  + 12);
        !          2639:                        }
        !          2640:                ENDDEBUG
        !          2641:                IFTRACE(D_CDATA)
        !          2642:                        tptrace( TPPTmisc, "INTR: req_type m lun\n", 
        !          2643:                                ecnrq->e_cmd, m, ecnrq->e_vc, 0);
        !          2644:                ENDTRACE
        !          2645: 
        !          2646:                switch( ecnrq->e_cmd ) {
        !          2647: 
        !          2648:                        case ECN_ACK:  /* data put on the board */
        !          2649:                                IncStat(co_ack);
        !          2650:                                ASSERT( ecnrq->e_vc != 0);
        !          2651:                                /* from ACKWAIT to OPEN */
        !          2652:                                if ( (copcb = 
        !          2653: #ifdef ARGO_DEBUG
        !          2654:                                        cons_chan_to_pcb( (int)ecnrq->e_vc, __LINE__ )
        !          2655: #else ARGO_DEBUG
        !          2656:                                        cons_chan_to_pcb( (int)ecnrq->e_vc )
        !          2657: #endif ARGO_DEBUG
        !          2658:                                                                                ) == (struct cons_pcb *)0 )
        !          2659:                                        break;
        !          2660:                                copcb->co_state = OPEN; 
        !          2661:                                /*
        !          2662:                                 * Anything on the pending queue for this connection?
        !          2663:                                 */
        !          2664:                                if( copcb->co_pending.ifq_len == 0 ) {
        !          2665:                                        if( copcb->co_proto->pr_ctlinput )
        !          2666:                                                /* for the sake of higher layer protocol (tp) */
        !          2667:                                                (*copcb->co_proto->pr_ctlinput)
        !          2668:                                                        (PRC_CONS_SEND_DONE, 
        !          2669:                                                        (struct sockaddr_iso *)&copcb->co_faddr, 
        !          2670:                                                        (caddr_t)copcb);
        !          2671:                                } else {
        !          2672:                                        register struct mbuf *m0;
        !          2673: 
        !          2674:                                        s = splimp();
        !          2675:                                        IF_DEQUEUE( &copcb->co_pending, m0 );
        !          2676:                                        splx(s);
        !          2677:                                        /* CAN ONLY DO 1 item here
        !          2678:                                         * if you change this if to while, HA HA 
        !          2679:                                         * it'll go right back onto
        !          2680:                                         * the pending queue (which means things will
        !          2681:                                         * be reordered on the queue!)
        !          2682:                                         */
        !          2683:                                        if( m0 ) {
        !          2684:                                                IFDEBUG(D_CDATA)
        !          2685:                                                        printf("ACK sending pending queue 0x%x len 0x%x\n",
        !          2686:                                                                m0, m0->m_len);
        !          2687:                                                ENDDEBUG
        !          2688:                                                ASSERT( m0->m_len != 0);
        !          2689:                                                (void) cons_senddata(copcb, m0); 
        !          2690:                                        }
        !          2691:                                }
        !          2692: 
        !          2693:                                /* send more? */
        !          2694:                                break;
        !          2695: 
        !          2696:                        case ECN_ACCEPT:  /* call accepted at other end */
        !          2697:                                /* adr_src, adr_dst are as given in the ECN_CALL
        !          2698:                                 * pcb field is copied from our ECN_CALL
        !          2699:                                 * request, confirm gives me a channel number
        !          2700:                                 */ 
        !          2701:                                ASSERT( ecnrq->e_vc != 0);
        !          2702: 
        !          2703:                                IncStat(co_accept);
        !          2704:                                if(copcb = 
        !          2705: #ifdef ARGO_DEBUG
        !          2706:                                cons_chan_to_pcb((int)ecnrq->e_vc, __LINE__ )
        !          2707: #else ARGO_DEBUG
        !          2708:                                cons_chan_to_pcb((int)ecnrq->e_vc)
        !          2709: #endif ARGO_DEBUG
        !          2710:                                                                                                ) { 
        !          2711:                                        /* error: already exists */
        !          2712:                                        printf("cons PANIC: dbl confirm for channel 0x%x\n",
        !          2713:                                                ecnrq->e_vc);
        !          2714:                                        break;
        !          2715:                                }
        !          2716:                                copcb = (struct cons_pcb *)ecnrq->e_pcb;
        !          2717:                                if( copcb->co_myself != copcb ) {
        !          2718:                                        struct mbuf *mm;
        !          2719:                                        /* TODO: REMOVE */
        !          2720:                                        ASSERT(0);
        !          2721:                                        printf("BAD e_pcb from ecn (0x%x) cmd 0x%x\n", 
        !          2722:                                                ecnrq->e_pcb, ecnrq->e_cmd);
        !          2723:                                        mm = dtom( copcb );
        !          2724:                                        if(mm->m_type == MT_FREE)
        !          2725:                                                printf("FREED MBUF!\n");
        !          2726:                                        dump_buf (ecnrq, sizeof (*ecnrq));
        !          2727:                                        panic("BAD ecnrq");
        !          2728:                                        break;
        !          2729:                                }
        !          2730:                                touch(copcb);
        !          2731:                                copcb->co_state = OPEN;
        !          2732:                                copcb->co_channel = (int)ecnrq->e_vc;
        !          2733:                                if(copcb->co_socket) {
        !          2734:                                        /* tp0 will take care of itself */
        !          2735:                                        if( copcb->co_flags & CONSF_XTS)
        !          2736:                                                soisconnected(copcb->co_socket); /* wake 'em up */
        !          2737:                                }
        !          2738:                                wakeup( (caddr_t)&copcb->co_state );
        !          2739: 
        !          2740:                                /*
        !          2741:                                 * Anything on the pending queue for this connection?
        !          2742:                                 */
        !          2743:                                if( copcb->co_pending.ifq_len > 0 ) {
        !          2744:                                        register struct mbuf *m0;
        !          2745: 
        !          2746:                                        s = splimp();
        !          2747:                                        IF_DEQUEUE( &copcb->co_pending, m0 );
        !          2748:                                        splx(s);
        !          2749:                                        /* CAN ONLY DO 1 item here
        !          2750:                                         * if you change this if to while, HA HA 
        !          2751:                                         * it'll go right back onto
        !          2752:                                         * the pending queue (which means things will
        !          2753:                                         * be reordered on the queue!)
        !          2754:                                         */
        !          2755:                                        if( m0 ) {
        !          2756:                                                IFDEBUG(D_CDATA)
        !          2757:                                                        printf("ACPT sending pending queue 0x%x len 0x%x\n",
        !          2758:                                                                m0, m0->m_len);
        !          2759:                                                ENDDEBUG
        !          2760:                                                ASSERT( m0->m_len != 0);
        !          2761:                                                (void) cons_senddata(copcb, m0); 
        !          2762:                                        }
        !          2763:                                }
        !          2764:                                break;
        !          2765: 
        !          2766:                        case ECN_REFUSE: 
        !          2767:                                /* other end refused our connect request */
        !          2768:                                /* src, dst are as given in the ECN_CALL */
        !          2769: 
        !          2770:                                IncStat(co_refuse);
        !          2771:                                copcb = (struct cons_pcb *)ecnrq->e_pcb;
        !          2772:                                if( copcb->co_myself != copcb ) {
        !          2773:                                        struct mbuf *mm;
        !          2774:                                        /* TODO: REMOVE */
        !          2775:                                        ASSERT(0);
        !          2776:                                        printf("BAD e_pcb from ecn (0x%x) cmd 0x%x\n", 
        !          2777:                                                ecnrq->e_pcb, ecnrq->e_cmd);
        !          2778:                                        mm = dtom( copcb );
        !          2779:                                        if(mm->m_type == MT_FREE)
        !          2780:                                                printf("FREED MBUF!\n");
        !          2781:                                        dump_buf (ecnrq, sizeof (*ecnrq));
        !          2782:                                        dump_buf (copcb, sizeof (*copcb));
        !          2783:                                        panic("BAD ecnrq");
        !          2784:                                        break;
        !          2785:                                }
        !          2786:                                touch(copcb);
        !          2787:                                copcb->co_state = CLOSED; /* do we have to do a clear?? */
        !          2788:                                copcb->co_channel = X_NOCHANNEL;
        !          2789:                                if(copcb->co_socket) {
        !          2790:                                        copcb->co_socket->so_error = ECONNREFUSED;
        !          2791:                                        /* TODO: if there's diagnostic info in the 
        !          2792:                                         * packet, and it's more useful than this E*,
        !          2793:                                         * get it
        !          2794:                                         */
        !          2795:                                        soisdisconnected(copcb->co_socket); /* wake 'em up */
        !          2796:                                        IFDEBUG(D_INCOMING)
        !          2797:                                                printf("ECN_REFUSE: waking up 0x%x\n", 
        !          2798:                                                        (caddr_t)&copcb->co_state );
        !          2799:                                        ENDDEBUG
        !          2800:                                        wakeup( (caddr_t)&copcb->co_state );
        !          2801:                                }
        !          2802:                                /*
        !          2803:                                 * Anything on the pending queue for this connection?
        !          2804:                                 */
        !          2805:                                while( copcb->co_pending.ifq_len > 0 ) {
        !          2806:                                        register struct mbuf *m0;
        !          2807: 
        !          2808:                                        s = splimp();
        !          2809:                                        IF_DEQUEUE( &copcb->co_pending, m0 );
        !          2810:                                        splx(s);
        !          2811:                                        m_freem(m0);
        !          2812:                                }
        !          2813:                                if ( ecnrq->e_reason  == E_CO_NORESOURCES ) {
        !          2814:                                        IncStat(co_noresources);
        !          2815:                                        cons_clear_and_detach( copcb, DONTCLEAR, PRC_QUENCH );
        !          2816:                                } else if(copcb->co_socket ) {
        !          2817:                                        copcb->co_socket->so_error = find_error_reason( ecnrq );
        !          2818:                                }
        !          2819:                                break;
        !          2820: 
        !          2821:                        case ECN_CONNECT:  /* incoming call */
        !          2822:                                /*
        !          2823:                                 * ECN_CONNECT indication gives adc_src, adc_dst  and channel
        !          2824:                                 */
        !          2825:                                ASSERT( ecnrq->e_vc != 0);
        !          2826: 
        !          2827:                                IncStat(co_connect);
        !          2828:                                cons_incoming(ifp, ecnrq); 
        !          2829:                                break;
        !          2830: 
        !          2831:                        case ECN_RESET:  
        !          2832:                        case ECN_CLEAR:
        !          2833:                                /*
        !          2834:                                 * ECN_CLEAR(indication) (if we can construct such a beast)
        !          2835:                                 * gives e_vc, 
        !          2836:                                 * Throw away anything queued pending on this connection
        !          2837:                                 * give a reset indication to the upper layer if TP
        !          2838:                                 * free the mbufs 
        !          2839:                                 */
        !          2840:                                ASSERT( ecnrq->e_vc != 0);
        !          2841:                                if( ecnrq->e_cmd == ECN_CLEAR )
        !          2842:                                        IncStat(co_clear_in);
        !          2843:                                else
        !          2844:                                        IncStat(co_reset_in);
        !          2845: #ifdef ARGO_DEBUG
        !          2846:                                if( ! (copcb=cons_chan_to_pcb((int)ecnrq->e_vc, __LINE__)) )
        !          2847: #else ARGO_DEBUG
        !          2848:                                if( ! (copcb=cons_chan_to_pcb((int)ecnrq->e_vc)) )
        !          2849: #endif ARGO_DEBUG
        !          2850: 
        !          2851:                                        break;
        !          2852:                                while( copcb->co_pending.ifq_len ) {
        !          2853:                                        register struct mbuf *m0;
        !          2854: 
        !          2855:                                        s = splimp();
        !          2856:                                        IF_DEQUEUE( &copcb->co_pending, m0 );
        !          2857:                                        splx(s);
        !          2858:                                        m_freem(m0);
        !          2859:                                }
        !          2860:                                copcb->co_state = CLOSED; /* do we have to do a clear? */
        !          2861:                                copcb->co_channel = X_NOCHANNEL;
        !          2862: 
        !          2863:                                cons_clear_and_detach( copcb, DONTCLEAR, PRC_ROUTEDEAD );
        !          2864:                                if (copcb->co_socket ) {
        !          2865:                                        copcb->co_socket->so_error = find_error_reason( ecnrq ); 
        !          2866:                                }
        !          2867:                                break;
        !          2868:                                
        !          2869:                        case ECN_RECEIVE:
        !          2870:                                 /*
        !          2871:                                  * ECN_RECEIVE (read) 
        !          2872:                                  */
        !          2873:                                ASSERT( ecnrq->e_vc != 0);
        !          2874:                                IncStat(co_receive);
        !          2875:                                {
        !          2876:                                        /* TODO: REMOVE */
        !          2877:                                        struct mbuf *thedata = e_data(ecnrq);
        !          2878:                                        u_int *firstint = mtod( thedata, u_int *);
        !          2879:                                        
        !          2880:                                        if( (*firstint & 0xff000000) != 0x81000000 ) {
        !          2881:                                                /* not clnp */
        !          2882:                                                switch( ((*firstint) & 0x00ff0000) >> 20 ) {
        !          2883:                                                case 0x1:
        !          2884:                                                case 0x2:
        !          2885:                                                case 0x3:
        !          2886:                                                case 0x6:
        !          2887:                                                case 0x7:
        !          2888:                                                case 0x8:
        !          2889:                                                case 0xc:
        !          2890:                                                case 0xd:
        !          2891:                                                case 0xe:
        !          2892:                                                case 0xf:
        !          2893:                                                        break;
        !          2894:                                                default:
        !          2895:                                                        printf(" ECN_RECEIVE! BAD DATA\n" );
        !          2896:                                                        dump_buf( thedata, 20 + 12 );
        !          2897:                                                        m_freem( m );
        !          2898:                                                        splx(s0);
        !          2899:                                                }
        !          2900:                                        }
        !          2901:                                }
        !          2902:                                if ( (copcb = 
        !          2903: #ifdef ARGO_DEBUG
        !          2904:                                        cons_chan_to_pcb( (int)ecnrq->e_vc, __LINE__ )
        !          2905: #else ARGO_DEBUG
        !          2906:                                        cons_chan_to_pcb( (int)ecnrq->e_vc )
        !          2907: #endif ARGO_DEBUG
        !          2908:                                                                                        ) == (struct cons_pcb *)0 ) {
        !          2909:                                        ifp->if_ierrors ++;
        !          2910:                                        IFTRACE(D_CDATA)
        !          2911:                                                tptrace(TPPTmisc, "ECN_RECEIVE DROPPED chan \n",
        !          2912:                                                        ecnrq->e_vc, 0, 0, 0);
        !          2913:                                        ENDTRACE
        !          2914:                                        break;
        !          2915:                                }
        !          2916: 
        !          2917:                                touch(copcb);
        !          2918:                                if( ecnrq->e_info & ECN_INFO_RCVD_INT )  {
        !          2919:                                        /* interrupt packet */
        !          2920:                                                printf("consintr: interrupt pkttype : DROPPED\n");
        !          2921:                                        IncStat(co_intrpt_pkts_in);
        !          2922:                                        IncStat(co_Rdrops);
        !          2923:                                        break;
        !          2924:                                }
        !          2925:                                /* new way */
        !          2926:                                if( copcb->co_proto == CLNP_proto ) 
        !          2927:                                {
        !          2928:                                        /* IP: put it on the queue and set soft interrupt */
        !          2929:                                        struct ifqueue *ifq;
        !          2930:                                        extern struct ifqueue clnlintrq;
        !          2931:                                        register struct mbuf *ifpp; /* for ptr to ifp */
        !          2932:                                        register struct mbuf *data = e_data(ecnrq);
        !          2933: 
        !          2934:                                        total_pkts_to_clnp ++;
        !          2935: 
        !          2936:                                        /* when acting as a subnet service, have to prepend a
        !          2937:                                         * pointer to the ifnet before handing this to clnp
        !          2938:                                         * GAG
        !          2939:                                         */
        !          2940:                                        if( ( data->m_off > MMINOFF + sizeof(struct snpa_hdr)) &&
        !          2941:                                                ( data->m_off <= MMAXOFF )) {
        !          2942:                                                data->m_off -= sizeof(struct snpa_hdr);
        !          2943:                                                data->m_len += sizeof(struct snpa_hdr);
        !          2944:                                        } else {
        !          2945:                                                MGET(ifpp, M_DONTWAIT, MT_XHEADER);
        !          2946:                                                if( !ifpp ) {
        !          2947:                                                        ifp->if_ierrors ++;
        !          2948:                                                        splx(s0);
        !          2949:                                                        m_freem(m); /* frees everything */
        !          2950:                                                        return; 
        !          2951:                                                }
        !          2952:                                                ifpp->m_len = sizeof(struct snpa_hdr);
        !          2953:                                                ifpp->m_act = 0;
        !          2954:                                                ifpp->m_next = data;
        !          2955:                                                data = ifpp;
        !          2956:                                        }
        !          2957:                                        IFTRACE(D_CDATA)
        !          2958:                                                tptrace(TPPTmisc, "-->CLNP copcb\n", copcb, 0, 0, 0);
        !          2959:                                        ENDTRACE
        !          2960:                                        {
        !          2961:                                                /*
        !          2962:                                                 *      TODO: if we ever use esis/cons we have to
        !          2963:                                                 *      think of something reasonable to stick in the
        !          2964:                                                 *      snh_shost,snh_dhost fields. I guess
        !          2965:                                                 *      the x.121 address is what we want.
        !          2966:                                                 *
        !          2967:                                                 *      That would also require length fields in the
        !          2968:                                                 *      snpa_hdr structure.
        !          2969:                                                 */
        !          2970:                                                struct snpa_hdr         *snh = 
        !          2971:                                                        mtod(data, struct snpa_hdr *);
        !          2972:                                                bzero((caddr_t)&snh, sizeof(struct snpa_hdr));
        !          2973:                                                bcopy((caddr_t)&ifp, (caddr_t)&snh->snh_ifp, 
        !          2974:                                                        sizeof(struct ifnet *));
        !          2975:                                        }
        !          2976:                                        *( mtod(data, struct ifnet **) ) = ifp; /* KLUDGE */
        !          2977: 
        !          2978:                                        ifq = &clnlintrq;
        !          2979:                                        splimp();
        !          2980:                                        if (IF_QFULL(ifq)) {
        !          2981:                                                IF_DROP(ifq);
        !          2982:                                                m_freem(m);
        !          2983:                                                IFDEBUG(D_INCOMING)
        !          2984:                                                        printf("DROPPED! ecnrq 0x%x, data 0x%x\n", m,data);
        !          2985:                                                ENDDEBUG
        !          2986:                                                splx(s0);
        !          2987:                                                ifp->if_ierrors ++;
        !          2988:                                                return;
        !          2989:                                        }
        !          2990:                                        IF_ENQUEUE(ifq, data);
        !          2991:                                        IFDEBUG(D_INCOMING) 
        !          2992:                                                printf(
        !          2993:                                "0x%x enqueued on ip Q: m_len 0x%x m_type 0x%x m_off 0x%x\n", 
        !          2994:                                                        data, data->m_len, data->m_type, data->m_off);
        !          2995:                                                dump_buf(mtod(data, caddr_t), data->m_len);
        !          2996:                                        ENDDEBUG
        !          2997:                                        e_data(ecnrq) = (struct mbuf *)0;
        !          2998:                                        schednetisr(NETISR_CLNP);
        !          2999:                                } else {
        !          3000:                                        /* HL is NOT clnp */
        !          3001:                                        IFTRACE(D_CDATA)
        !          3002:                                                tptrace(TPPTmisc,
        !          3003:                                                        "-->HL pr_input so copcb channel\n", 
        !          3004:                                                        copcb->co_proto->pr_input, 
        !          3005:                                                        copcb->co_socket, copcb, 
        !          3006:                                                        copcb->co_channel);
        !          3007:                                        ENDTRACE
        !          3008:                                        IFDEBUG(D_INCOMING) 
        !          3009:                                                printf( "0x%x --> HL proto 0x%x chan 0x%x\n", 
        !          3010:                                                        e_data(ecnrq), copcb->co_proto, copcb->co_channel );
        !          3011:                                        ENDDEBUG
        !          3012: 
        !          3013:                                        (*copcb->co_proto->pr_input)(e_data(ecnrq), 
        !          3014:                                                &copcb->co_faddr,
        !          3015:                                                &copcb->co_laddr,
        !          3016:                                                copcb->co_socket, /* used by cons-transport interface */
        !          3017:                                                (copcb->co_flags & CONSF_DGM)?0:
        !          3018:                                                        copcb->co_channel);/* used by tp-cons interface */
        !          3019: 
        !          3020:                                        /* 
        !          3021:                                         * the pr_input will free the data chain, so we must
        !          3022:                                         * zero the ptr to is so that m_free doesn't panic
        !          3023:                                         */
        !          3024:                                        e_data(ecnrq) = (struct mbuf *)0;
        !          3025:                                }
        !          3026:                                break;
        !          3027: 
        !          3028:                        default:
        !          3029:                                /* error */
        !          3030:                                ifp->if_ierrors ++;
        !          3031:                                printf("consintr: unknown request\n");
        !          3032:                }
        !          3033:                IFDEBUG(D_INCOMING)
        !          3034:                        printf("consintr: m_freem( 0x%x )\n", m);
        !          3035:                ENDDEBUG
        !          3036:                m_freem( m );
        !          3037:        }
        !          3038:        splx(s0);
        !          3039: }
        !          3040: 
        !          3041: /*
        !          3042:  * Process an ioctl request.
        !          3043:  * also set-time-limit, extend-time-limit
        !          3044:  * for ALL channels, the time-limit ioctls will be done by open-a-dummy-socket,
        !          3045:  * do ioctl with the channel number, close the socket (dumb!).
        !          3046:  */
        !          3047: /* ARGSUSED */
        !          3048: cons_ioctl(so, cmd, data)
        !          3049:        struct socket *so;
        !          3050:        int cmd;
        !          3051:        caddr_t data;
        !          3052: {
        !          3053:        int     s = splnet();
        !          3054:        int     error = 0;
        !          3055: 
        !          3056:        IFDEBUG(D_CCONS)
        !          3057:                printf("cons_ioctl( cmd 0x%x )\n", cmd);
        !          3058:        ENDDEBUG
        !          3059: 
        !          3060: #ifdef notdef
        !          3061:        switch (cmd) {
        !          3062: 
        !          3063:        default:
        !          3064: #endif notdef
        !          3065:                error = EOPNOTSUPP;
        !          3066: #ifdef notdef
        !          3067:        }
        !          3068: #endif notdef
        !          3069: 
        !          3070:        splx(s);
        !          3071:        return (error);
        !          3072: }
        !          3073: 
        !          3074: 
        !          3075: /*
        !          3076:  *************************************************************
        !          3077:  *                                                           *
        !          3078:  *                                                           *
        !          3079:  * Interface to CO Subnetwork service from CLNP              *
        !          3080:  * Must be a device interface.                             *****
        !          3081:  *                                                          *** 
        !          3082:  *                                                           *
        !          3083:  *                                                          Poof!
        !          3084:  */
        !          3085: 
        !          3086: /*
        !          3087:  * NAME:       consioctl()
        !          3088:  * CALLED FROM:
        !          3089:  *     called through the ifnet structure.
        !          3090:  * FUNCTION and ARGUMENTS:
        !          3091:  *     the usual ioctl stuff
        !          3092:  * RETURNS:
        !          3093:  *     E*
        !          3094:  * SIDE EFFECTS:
        !          3095:  * NOTES:
        !          3096:  */
        !          3097: consioctl(ifp, cmd, data)
        !          3098:        register struct ifnet *ifp;
        !          3099:        register int cmd;
        !          3100:        register caddr_t data;
        !          3101: {
        !          3102:        register struct ifaddr          *ifa = (struct ifaddr *)data;
        !          3103:        register int                            s = splimp();
        !          3104:        register struct ifreq           *ifr = (struct ifreq *)data;
        !          3105:        register int                            error = 0;
        !          3106:        void                                            consshutdown();
        !          3107: 
        !          3108:        switch (cmd) {
        !          3109:        case SIOCSIFADDR:
        !          3110:                switch (ifa->ifa_addr.sa_family) {
        !          3111:                case AF_ISO:
        !          3112:                        if( (ifp->if_flags & IFF_UP ) == 0)
        !          3113:                                consinit(ifp->if_unit);
        !          3114:                        break;
        !          3115:                default:
        !          3116:                        printf("CANNOT config cons with address family %d\n",
        !          3117:                                ifa->ifa_addr.sa_family);
        !          3118:                        break;
        !          3119:                }
        !          3120:                break;
        !          3121:        case SIOCSIFFLAGS:
        !          3122:                IFDEBUG(D_CCONS)
        !          3123:                        printf("consioctl: set flags to x%x\n", ifr->ifr_flags);
        !          3124:                        printf("consioctl: ifp flags are x%x\n", ifp->if_flags);
        !          3125:                ENDDEBUG
        !          3126:                if( ifr->ifr_flags & IFF_LOOPBACK )
        !          3127:                        ifp->if_flags |= IFF_LOOPBACK;
        !          3128:                else
        !          3129:                        ifp->if_flags &= ~IFF_LOOPBACK;
        !          3130: 
        !          3131:                /* if board is down but request takes it up, init the board */
        !          3132:                if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0)
        !          3133:                        consinit(ifp->if_unit);
        !          3134: 
        !          3135:                /* if board is up but request takes it down, shut the board down */
        !          3136:                if (((ifr->ifr_flags & IFF_UP) == 0) && (ifp->if_flags & IFF_UP)) {
        !          3137:                        consshutdown(ifp->if_unit);
        !          3138:                }
        !          3139:                IFDEBUG(D_CCONS)
        !          3140:                        printf("consioctl: flags are x%x\n", ifp->if_flags);
        !          3141:                ENDDEBUG
        !          3142:                break;
        !          3143:        case SIOCGSTATUS:
        !          3144:                /* warning: must coerse ifp to (struct ifstatus *) in order to use */
        !          3145:                IFDEBUG(D_CCONS)
        !          3146:                        printf("consioctl: EICON status request\n");
        !          3147:                ENDDEBUG
        !          3148: #if NECN>0
        !          3149:                ecnioctl(ifp, cmd, data);
        !          3150: #else 
        !          3151:                error = ENODEV;
        !          3152: #endif NECN>0
        !          3153:                break;
        !          3154:        default:
        !          3155:                error = EINVAL;
        !          3156:        }
        !          3157:        splx(s);
        !          3158:        return error;
        !          3159: }
        !          3160: 
        !          3161: /*
        !          3162:  * NAME:       consattach()
        !          3163:  * CALLED FROM:
        !          3164:  *     cons_init() (which comes from autoconf)
        !          3165:  * FUNCTION and ARGUMENTS:
        !          3166:  *     creates an ifp and fills it in; calls ifattach() on it. 
        !          3167:  * RETURNS:
        !          3168:  *  no return value
        !          3169:  * SIDE EFFECTS:
        !          3170:  * NOTES:
        !          3171:  */
        !          3172: consattach()
        !          3173: {
        !          3174:        register struct ifnet           *ifp;
        !          3175:        register struct mbuf            *m;
        !          3176: 
        !          3177:        if(sizeof(struct ifnet) > MLEN) {
        !          3178:                printf("Can't attach cons!  sizeof(struct ifnet) > MLEN\n");
        !          3179:                return;
        !          3180:        }
        !          3181:        MGET(m, M_DONTWAIT, MT_IFADDR);
        !          3182:        if( !m ) {
        !          3183:                printf("Can't attach cons!  NO MBUFS!\n");
        !          3184:                return;
        !          3185:        }
        !          3186:        m->m_len = sizeof(struct ifnet);
        !          3187:        ifp = consif = mtod(m, struct ifnet *); 
        !          3188:        ifp->if_unit = 0;
        !          3189:        ifp->if_name = "cons";
        !          3190:        ifp->if_mtu = ECN_MTU;
        !          3191:        ifp->if_init = consinit;
        !          3192:        ifp->if_ioctl = consioctl;
        !          3193:        ifp->if_output = cosns_output; /* called by clnp */
        !          3194:        ifp->if_flags = IFF_LOOPBACK;  /* default */
        !          3195:        if_attach(ifp); 
        !          3196:        printf("cons%d: pseudo device attached \n", ifp->if_unit);
        !          3197: }
        !          3198: 
        !          3199: /*
        !          3200:  * NAME:       consinit()
        !          3201:  * CALLED FROM:
        !          3202:  *     consioctl()
        !          3203:  * FUNCTION and ARGUMENTS:
        !          3204:  *     Initializes apropos data structures, etc.
        !          3205:  *  Marks the device as up.
        !          3206:  *  Zaps the address list.
        !          3207:  *  Calls device layer restart on the device if necessary.
        !          3208:  */
        !          3209: Static
        !          3210: consinit(_unit)
        !          3211: register int   _unit;  /* unit to initialize */
        !          3212: {
        !          3213:        struct ifnet                    *ecnifp();
        !          3214:        struct ifnet                    *ifp;
        !          3215:        int             s;
        !          3216: 
        !          3217:        if ((ifp = ecnifp(_unit)) != (struct ifnet *)0 ) {
        !          3218:                ecnrestart(ifp);
        !          3219:                IncStat(co_restart);
        !          3220:        }
        !          3221:        if (consif->if_addrlist == (struct ifaddr *)0)
        !          3222:                return;
        !          3223:        if ((consif->if_flags & IFF_UP) == 0) {
        !          3224:                s = splimp();
        !          3225:                consif->if_flags |= IFF_UP;
        !          3226:                splx(s);
        !          3227:        }
        !          3228: 
        !          3229: }
        !          3230: 
        !          3231: /* 
        !          3232:  * NAME:       consshutdown()
        !          3233:  * CALLED FROM:
        !          3234:  *     cons_ioctl() when user takes down an interface w/ SIOCSIFFLAGS 
        !          3235:  * FUNCTION and ARGUMENTS:
        !          3236:  *  calls lower layer shutdown routine on the device.
        !          3237:  *  and marks the if as down if the if is the sw loopback pseudodevice.
        !          3238:  * RETURNS:
        !          3239:  *     no return value
        !          3240:  */
        !          3241: void
        !          3242: consshutdown(_unit)
        !          3243: register int   _unit;  /* unit to shutdown */
        !          3244: {
        !          3245:        extern  struct ifnet    *ecnifp();
        !          3246:        struct ifnet                    *ifp;
        !          3247:        int                                     s;
        !          3248: 
        !          3249:        if ((ifp = ecnifp(_unit)) != (struct ifnet *)0 ) {
        !          3250:                ecnshutdown(ifp);
        !          3251:        }
        !          3252:        if ((consif->if_flags & IFF_UP) ) {
        !          3253:                s = splimp();
        !          3254:                consif->if_flags &= ~IFF_UP;
        !          3255:                splx(s);
        !          3256:        }
        !          3257: }
        !          3258: #endif KERNEL
        !          3259: 
        !          3260: /*
        !          3261:  * NAME:       munge()
        !          3262:  * CALLED FROM:
        !          3263:  *     cons_pcbbind(), cons_usrreq()
        !          3264:  * FUNCTION and ARGUMENTS:
        !          3265:  *  Takes the argument (value) and stashes it into the last two
        !          3266:  *  nibbles of an X.121 address.  Does this in the two nibbles beginning
        !          3267:  *  at the location defined by the character pointer (dst_octet) and the 
        !          3268:  *  integer (dst_nibble).  Nibble 0 is the lower nibble (high
        !          3269:  *  order 4 bits); nibble 1 is the low order 4 bits of *(dst_octet).
        !          3270:  *
        !          3271:  * RETURNS:
        !          3272:  *     no return value
        !          3273:  */
        !          3274: Static 
        !          3275: munge( value, dst_octet, dst_nibble)
        !          3276:        int value;
        !          3277:        caddr_t dst_octet;
        !          3278:        int dst_nibble;
        !          3279: {
        !          3280:        IFDEBUG(D_CCONN)
        !          3281:                printf("MUNGE: value 0x%x dst_octet 0x%x, nibble 0x%x)\n",
        !          3282:                        value, dst_octet, dst_nibble);
        !          3283:        ENDDEBUG
        !          3284:        if (value >= ISO_PORT_RESERVED)
        !          3285:                value -= 1000;
        !          3286: 
        !          3287:        {
        !          3288:                /* convert so it  looks like a decimal number */
        !          3289:                register int tens, ones;
        !          3290: 
        !          3291:                tens = value/10;
        !          3292:                ASSERT( tens <= 9 );
        !          3293:                ones = value - (tens * 10);
        !          3294: 
        !          3295:                value = tens * 16 + ones;
        !          3296:        }
        !          3297: 
        !          3298:        dst_octet --;
        !          3299:        /* leave nibble same 'cause it's one after the last set nibble */
        !          3300: 
        !          3301:        *dst_octet &= ~(0xff<<(dst_nibble << 2)); /* zero it */
        !          3302:        *dst_octet |= ((value>>4) << (dst_nibble<<2));
        !          3303:        dst_nibble = 1-dst_nibble;
        !          3304:        dst_octet += dst_nibble;
        !          3305: 
        !          3306:        *dst_octet &= ~(0xff<<(dst_nibble << 2)); /* zero it */
        !          3307:        *dst_octet |= ((value&0xff) << (dst_nibble<<2));
        !          3308: } 
        !          3309: 
        !          3310: /*
        !          3311:  * NAME:       unmunge()
        !          3312:  * CALLED FROM:
        !          3313:  *  DTEtoNSAP(), FACILtoNSAP()
        !          3314:  * FUNCTION and ARGUMENTS:
        !          3315:  *  return the port/tsuffix represented by the two digits found in a
        !          3316:  *  bcd string beginning at the (dst_nibble)th nibble of the
        !          3317:  *  octet BEFORE (dst_octet).
        !          3318:  *  
        !          3319:  * dst_octet,dst_nibble  is the nibble after the one we'll look at
        !          3320:  * RETURNS:
        !          3321:  *  an integer, the port/tsuffix
        !          3322:  *  Note- converts to a port > 1000 if necessary.
        !          3323:  */
        !          3324: Static int
        !          3325: unmunge( dst_octet, dst_nibble )
        !          3326:        caddr_t dst_octet;
        !          3327:        int dst_nibble;
        !          3328: {
        !          3329:                register u_short last = 0;
        !          3330: 
        !          3331:                dst_octet --;
        !          3332:                /* leave nibble same 'cause it's one after the last set nibble */
        !          3333:                IFDEBUG(D_CADDR)
        !          3334:                        printf("unmunge: *octet 0x%x, nibble 0x%x\n", *dst_octet,
        !          3335:                                dst_nibble);
        !          3336:                ENDDEBUG
        !          3337: 
        !          3338:                last = ((*dst_octet) & (0xff<<(dst_nibble<<2)));
        !          3339:                dst_nibble = 1-dst_nibble;
        !          3340:                dst_octet += dst_nibble;
        !          3341: 
        !          3342:                last |= ((*dst_octet) & (0xff<<(dst_nibble << 2)));
        !          3343:                {
        !          3344:                        /* convert to a decimal number */
        !          3345:                        register int tens, ones;
        !          3346: 
        !          3347:                        tens = (last&0xf0)>>4;
        !          3348:                        ones = last&0xf;
        !          3349: 
        !          3350:                        last = tens * 10 + ones;
        !          3351:                }
        !          3352: 
        !          3353:                IFDEBUG(D_CADDR)
        !          3354:                        printf("unmunge computes 0x%x\n", last);
        !          3355:                ENDDEBUG
        !          3356:                if((int)last+1000 >= ISO_PORT_RESERVED)
        !          3357:                        last += 1000;
        !          3358:                IFDEBUG(D_CADDR)
        !          3359:                        printf("unmunge returns 0x%x\n", last);
        !          3360:                ENDDEBUG
        !          3361:                return last;
        !          3362: } 
        !          3363: 
        !          3364: /*
        !          3365:  * NAME:       make_partial_x25_packet()
        !          3366:  *
        !          3367:  * FUNCTION and ARGUMENTS:
        !          3368:  *     Makes part of an X.25 call packet, for use by the eicon board.
        !          3369:  *  (src) and (dst) are the NSAP-addresses of source and destination.
        !          3370:  *     (proto) is the higher-layer protocol number (in iso.h)
        !          3371:  *     (buf) is a ptr to a buffer into which to write this partial header.
        !          3372:  *
        !          3373:  *  The partial header looks like (choke):
        !          3374:  *     octet           meaning
        !          3375:  *  1                  calling DTE len  |  called DTE len (lengths in nibbles)
        !          3376:  *  2..n-1             called DTE addr  | (<-- boundary may be middle of an octet)
        !          3377:  *                     calling DTE addr  | zero nibble to round to octet boundary.
        !          3378:  *     n                       Facility length (in octets)
        !          3379:  *     n+1                     Facility field, which is a set of:
        !          3380:  *       m                     facil code
        !          3381:  *       m+1           facil param len (for >2-byte facilities) in octets
        !          3382:  *       m+2..p        facil param field
        !          3383:  *  q                  user data (protocol identification octet)
        !          3384:  * 
        !          3385:  *
        !          3386:  * RETURNS: 
        !          3387:  *  0 if OK
        !          3388:  *  E* if failed.
        !          3389:  */
        !          3390: 
        !          3391: #ifdef X25_1984 
        !          3392: int cons_use_facils = 1;
        !          3393: #else X25_1984 
        !          3394: int cons_use_facils = 0;
        !          3395: #endif X25_1984 
        !          3396: 
        !          3397: int cons_use_udata = 1; /* KLUDGE FOR DEBUGGING */
        !          3398: 
        !          3399: Static int
        !          3400: make_partial_x25_packet(copcb, m)
        !          3401:        struct cons_pcb *copcb;
        !          3402:        struct mbuf *m;
        !          3403: {
        !          3404:        struct sockaddr_iso     *src, *dst;
        !          3405:        u_int                           proto;
        !          3406:        int                                     flag;
        !          3407:        caddr_t                         buf = mtod(m, caddr_t);
        !          3408:        register caddr_t        ptr     = buf + 1;  /* make room for 2 length nibbles */
        !          3409:        register int            len     = 0;
        !          3410:        int                             buflen  =0;
        !          3411:        caddr_t                         facil_len;
        !          3412:        int                             oddness = 0;
        !          3413: 
        !          3414:        src = &copcb->co_laddr;
        !          3415:        dst = &copcb->co_faddr;
        !          3416:        proto = copcb->co_proto->pr_protocol, 
        !          3417:        flag = copcb->co_flags & CONSF_XTS;
        !          3418: 
        !          3419: 
        !          3420:        IFDEBUG(D_CCONN)
        !          3421:                printf("make_partial_x25_packet(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
        !          3422:                        src, dst, proto, m, flag);
        !          3423:        ENDDEBUG
        !          3424:        
        !          3425:        /*
        !          3426:         * Note - order of addrs in x25 pkt hdr is wierd: 
        !          3427:         * calling len/called len/called addr/calling addr (p.40 ISO 8202)
        !          3428:         */
        !          3429:        if( (len = copcb->co_peer_dte.dtea_niblen) > 0 ) {
        !          3430:                nibble_copy( (char *)(copcb->co_peer_dte.dtea_addr), HIGH_NIBBLE,
        !          3431:                        ptr, HIGH_NIBBLE, len);
        !          3432:        } else {
        !          3433:                if ((len =  NSAPtoDTE( ptr, HIGH_NIBBLE, dst)) <=0 ) {
        !          3434:                        return E_CO_OSI_UNSAP;
        !          3435:                }
        !          3436:        }
        !          3437:        *buf = len; /* fill in called dte addr length */
        !          3438:        ptr += len>>1; /* len is in nibbles */
        !          3439:        oddness += len&0x1;
        !          3440: 
        !          3441:        if ((len =  NSAPtoDTE( ptr, 1-(len&0x1), src)) <=0 ) {
        !          3442:                return E_CO_OSI_UNSAP;
        !          3443:        }
        !          3444:        ptr += len>>1; /* len is in nibbles */
        !          3445:        *buf |= len << 4; /* fill in calling dte addr length */
        !          3446:        oddness += len&0x1;
        !          3447: 
        !          3448:        IFDEBUG(D_CADDR)
        !          3449:                printf("make_partial  2: ptr 0x%x, len 0x%x oddness 0x%x\n", 
        !          3450:                        ptr, len, oddness );
        !          3451:        ENDDEBUG
        !          3452:        /* if either of the addresses were an odd length, the count is off by 1 */
        !          3453:        if( oddness ) {
        !          3454:                ptr ++;
        !          3455:        }
        !          3456: 
        !          3457:        /* ptr now points to facil length (len of whole facil field in OCTETS */
        !          3458:        facil_len = ptr ++;
        !          3459: 
        !          3460:        IFDEBUG(D_CADDR)
        !          3461:                printf("make_partial  calling: ptr 0x%x, len 0x%x\n", ptr, 
        !          3462:                                src->siso_addr.isoa_len);
        !          3463:        ENDDEBUG
        !          3464:        if( cons_use_facils ) {
        !          3465:                *ptr = 0xcb; /* calling facility code */
        !          3466:                ptr ++;
        !          3467:                ptr ++; /* leave room for facil param len (in OCTETS + 1) */
        !          3468:                ptr ++; /* leave room for the facil param len (in nibbles),
        !          3469:                                * high two bits of which indicate full/partial NSAP
        !          3470:                                */
        !          3471:                len = src->siso_addr.isoa_len;
        !          3472:                bcopy( &src->siso_addr.isoa_afi, ptr, len);
        !          3473:                *(ptr-2) = len+2; /* facil param len in octets */
        !          3474:                *(ptr-1) = len<<1; /* facil param len in nibbles */
        !          3475:                ptr += len;
        !          3476: 
        !          3477:                IFDEBUG(D_CADDR)
        !          3478:                        printf("make_partial  called: ptr 0x%x, len 0x%x\n", ptr, 
        !          3479:                                        dst->siso_addr.isoa_len);
        !          3480:                ENDDEBUG
        !          3481:                *ptr = 0xc9; /* called facility code */
        !          3482:                ptr ++;
        !          3483:                ptr ++; /* leave room for facil param len (in OCTETS + 1) */
        !          3484:                ptr ++; /* leave room for the facil param len (in nibbles),
        !          3485:                                * high two bits of which indicate full/partial NSAP
        !          3486:                                */
        !          3487:                len = dst->siso_addr.isoa_len;
        !          3488:                bcopy( &dst->siso_addr.isoa_afi, ptr, len);
        !          3489:                *(ptr-2) = len+2; /* facil param len = addr len + 1 for each of these
        !          3490:                                                  * two length fields, in octets */
        !          3491:                *(ptr-1) = len<<1; /* facil param len in nibbles */
        !          3492:                ptr += len;
        !          3493: 
        !          3494:        }
        !          3495:        *facil_len = ptr - facil_len - 1;
        !          3496:        if(*facil_len > X25_FACIL_LEN_MAX )
        !          3497:                return E_CO_PNA_LONG;
        !          3498: 
        !          3499:        if( cons_use_udata ) {
        !          3500:                if (copcb->co_x25crud_len > 0) {
        !          3501:                        /*
        !          3502:                         *      The user specified something. Stick it in
        !          3503:                         */
        !          3504:                        bcopy(copcb->co_x25crud, ptr, copcb->co_x25crud_len);
        !          3505:                        ptr += copcb->co_x25crud_len;
        !          3506:                } else {
        !          3507:                        /* protocol identifier */
        !          3508:                        switch (proto) {
        !          3509:                                        /* unfortunately all are considered 1 protocol */
        !          3510:                                case ISOPROTO_TP0: 
        !          3511:                                case ISOPROTO_TP1:
        !          3512:                                case ISOPROTO_TP2:
        !          3513:                                case ISOPROTO_TP3:
        !          3514:                                case ISOPROTO_TP4:
        !          3515:                                case ISOPROTO_CLTP:
        !          3516:                                        /* no user data for TP */
        !          3517:                                        break;
        !          3518: 
        !          3519:                                case ISOPROTO_CLNP:
        !          3520:                                        *ptr = 0x81;
        !          3521:                                        ptr++; /* count the proto id byte! */
        !          3522:                                        break;
        !          3523:                                case ISOPROTO_INACT_NL:
        !          3524:                                        *ptr = 0x0;
        !          3525:                                        ptr++; /* count the proto id byte! */
        !          3526:                                        break;
        !          3527:                                case ISOPROTO_X25:
        !          3528:                                        *ptr = 0xff; /* reserved for future extensions */
        !          3529:                                                  /* we're stealing this value for local use */
        !          3530:                                        ptr++; /* count the proto id byte! */
        !          3531:                                        break;
        !          3532:                                default:
        !          3533:                                        return EPROTONOSUPPORT;
        !          3534:                        }
        !          3535:                }
        !          3536:        }
        !          3537: 
        !          3538:        buflen = (int)(ptr - buf);
        !          3539: 
        !          3540:        IFDEBUG(D_CDUMP_REQ)
        !          3541:                register int i;
        !          3542: 
        !          3543:                printf("ECN_CONNECT DATA buf 0x%x len %d (0x%x)\n", 
        !          3544:                        buf, buflen, buflen);
        !          3545:                for( i=0; i < buflen; ) {
        !          3546:                        printf("+%d: %x %x %x %x    %x %x %x %x\n",
        !          3547:                                i,
        !          3548:                                *(buf+i), *(buf+i+1), *(buf+i+2), *(buf+i+3),
        !          3549:                                *(buf+i+4), *(buf+i+5), *(buf+i+6), *(buf+i+7));
        !          3550:                        i+=8;
        !          3551:                }
        !          3552:        ENDDEBUG
        !          3553:        IFDEBUG(D_CADDR)
        !          3554:                printf("make_partial returns buf 0x%x size 0x%x bytes\n", 
        !          3555:                        mtod(m, caddr_t), buflen);
        !          3556:        ENDDEBUG
        !          3557: 
        !          3558:        ASSERT( X25_PARTIAL_PKT_LEN_MAX < MLEN );
        !          3559: 
        !          3560:        if(buflen > X25_PARTIAL_PKT_LEN_MAX)
        !          3561:                return E_CO_PNA_LONG;
        !          3562: 
        !          3563:        m->m_len = buflen;
        !          3564:        return  0;
        !          3565: }
        !          3566: 
        !          3567: /*
        !          3568:  * NAME:       NSAPtoDTE()
        !          3569:  * CALLED FROM:
        !          3570:  *  make_partial_x25_packet()
        !          3571:  * FUNCTION and ARGUMENTS: 
        !          3572:  *  get a DTE address from an NSAP-address (struct sockaddr_iso)
        !          3573:  *  (dst_octet) is the octet into which to begin stashing the DTE addr
        !          3574:  *  (dst_nibble) takes 0 or 1.  1 means begin filling in the DTE addr
        !          3575:  *             in the high-order nibble of dst_octet.  0 means low-order nibble.
        !          3576:  *  (addr) is the NSAP-address
        !          3577:  *  (flag) is true if the transport suffix is to become the
        !          3578:  *             last two digits of the DTE address
        !          3579:  *  A DTE address is a series of BCD digits
        !          3580:  *
        !          3581:  *     A DTE address may have leading zeros. The are significant.
        !          3582:  *             1 digit per nibble, may be an odd number of nibbles.
        !          3583:  *
        !          3584:  *  An NSAP-address has the DTE address in the IDI. Leading zeros are
        !          3585:  *             significant. Trailing hex f indicates the end of the DTE address.
        !          3586:  *     Also is a series of BCD digits, one per nibble.
        !          3587:  *
        !          3588:  * RETURNS
        !          3589:  *  # significant digits in the DTE address, -1 if error.
        !          3590:  */
        !          3591: 
        !          3592: Static int
        !          3593: NSAPtoDTE( dst_octet, dst_nibble, addr)
        !          3594:        caddr_t         dst_octet;
        !          3595:        int                     dst_nibble;
        !          3596:        register struct sockaddr_iso *addr;
        !          3597: {
        !          3598:        int     error;
        !          3599:        u_char  x121string[7]; /* maximum is 14 digits */
        !          3600:        int             x121strlen;
        !          3601:        struct  dte_addr *dtea;
        !          3602: 
        !          3603:        IFDEBUG(D_CADDR)
        !          3604:                printf("NSAPtoDTE: nsap: %s\n", clnp_iso_addrp(&addr->siso_addr));
        !          3605:        ENDDEBUG
        !          3606: 
        !          3607:        error = iso_8208snparesolve(addr, x121string, &x121strlen);
        !          3608:        ASSERT(error == 0);
        !          3609:        if(  error != 0 ) {
        !          3610:                /* no snpa - cannot send */
        !          3611:                IFDEBUG(D_CADDR)
        !          3612:                        printf("NSAPtoDTE: 8208resolve: %d\n", error );
        !          3613:                ENDDEBUG
        !          3614:                return 0;
        !          3615:        }
        !          3616:        ASSERT(x121strlen == sizeof(struct dte_addr));
        !          3617:        dtea = (struct dte_addr *)x121string;
        !          3618:        x121strlen = dtea->dtea_niblen;
        !          3619: 
        !          3620:        nibble_copy((char *)x121string, HIGH_NIBBLE, 
        !          3621:                dst_octet, dst_nibble, x121strlen);
        !          3622:        return x121strlen;
        !          3623: }
        !          3624: 
        !          3625: /*
        !          3626:  * NAME:       FACILtoNSAP()
        !          3627:  * CALLED FROM:
        !          3628:  *  parse_facil()
        !          3629:  * FUNCTION and ARGUMENTS:
        !          3630:  *     Creates and NSAP in the sockaddr_iso (addr) from the
        !          3631:  *  x.25 facility found at (buf), of length (buf_len).
        !          3632:  * RETURNS:
        !          3633:  *  0 if ok, non-zero if error;
        !          3634:  */
        !          3635: 
        !          3636: Static int
        !          3637: FACILtoNSAP( buf, buf_len, addr)
        !          3638:        caddr_t                 buf;
        !          3639:        u_char                  buf_len; /* in bytes */
        !          3640:        register struct sockaddr_iso *addr;
        !          3641: {
        !          3642:        int len_in_nibbles;
        !          3643: 
        !          3644:        IFDEBUG(D_CADDR)
        !          3645:                printf("FACILtoNSAP( 0x%x, 0x%x, 0x%x )\n", 
        !          3646:                        buf, buf_len, addr );
        !          3647:        ENDDEBUG
        !          3648: 
        !          3649:        len_in_nibbles = *buf;
        !          3650:        /* despite the fact that X.25 makes us put a length in nibbles
        !          3651:         * here, the NSAP-addrs are always in full octets
        !          3652:         */
        !          3653:        buf ++;
        !          3654: 
        !          3655:        bzero( addr, sizeof (struct sockaddr_iso) );
        !          3656: 
        !          3657:        ASSERT(buf_len <= 1+sizeof (struct iso_addr));
        !          3658:        if(buf_len > 1+sizeof (struct iso_addr)) {
        !          3659:                return -1; /* error */
        !          3660:        }
        !          3661:        ASSERT(len_in_nibbles == (buf_len - 1)<<1);
        !          3662:        if(len_in_nibbles != (buf_len - 1)<<1) {
        !          3663:                return -2; /* error */
        !          3664:        }
        !          3665:        bcopy(buf, &addr->siso_addr.isoa_afi, buf_len-1);
        !          3666:        addr->siso_addr.isoa_len = buf_len-1; 
        !          3667:        IFDEBUG(D_CADDR)
        !          3668:                printf("FACILtoNSAP: isoa_len 0x%x\n",
        !          3669:                        addr->siso_addr.isoa_len);
        !          3670:        ENDDEBUG
        !          3671:        addr->siso_family = AF_ISO;
        !          3672: 
        !          3673:        addr->siso_tsuffix = 
        !          3674:                unmunge( ((caddr_t)&addr->siso_addr.t37_idi) + ADDR37_IDI_LEN , 1 );
        !          3675:        return 0;
        !          3676: }
        !          3677: 
        !          3678: /*
        !          3679:  * NAME:       DTEtoNSAP()
        !          3680:  * CALLED FROM:
        !          3681:  *  parse_facil()
        !          3682:  * FUNCTION and ARGUMENTS:
        !          3683:  *  Creates a type 37 NSAP in the sockaddr_iso (addr)
        !          3684:  *     from a DTE address found at the (src_nibble)th nibble of
        !          3685:  *     the octet (src_octet), of length (src_nib_len).
        !          3686:  *  
        !          3687:  * RETURNS:
        !          3688:  *  0 if ok; E* otherwise.
        !          3689:  */
        !          3690: 
        !          3691: Static  int
        !          3692: DTEtoNSAP(addr, src_octet, src_nibble, src_nib_len)
        !          3693:        struct sockaddr_iso *addr;
        !          3694:        caddr_t src_octet;
        !          3695:        int src_nibble, src_nib_len;
        !          3696: {
        !          3697:        caddr_t                         dst_octet;
        !          3698:        int                                     pad_len;
        !          3699:        int                                     dst_nibble;
        !          3700:        char                            first_nib;
        !          3701:        static                          char *z_pad = "\0\0\0\0\0\0\0";
        !          3702:        static                          char *f_pad = "\021\021\021\021\021\021\021";
        !          3703: 
        !          3704:        IFDEBUG(D_CADDR)
        !          3705:                printf("DTEtoNSAP( 0x%x, 0x%x, 0x%x, 0x%x )\n", 
        !          3706:                        src_octet, src_nibble, src_nib_len, addr );
        !          3707:        ENDDEBUG
        !          3708: 
        !          3709:        bzero( addr, sizeof(*addr));
        !          3710:        addr->siso_family = AF_ISO;
        !          3711:        /*
        !          3712:         * Coming from a DTE addr it's always type 37.
        !          3713:         * src_octet <-- starting place in the NSAP-address of 
        !          3714:         * the embedded SNPA-address (x.121 addr or DTE addr).
        !          3715:         */
        !          3716:        addr->siso_addr.isoa_afi = 0x37;
        !          3717: 
        !          3718:        /* first, figure out what pad to use and pad */
        !          3719: 
        !          3720:        first_nib = (*src_octet) >> (SHIFT*(1-src_nibble));
        !          3721:        pad_len = (ADDR37_IDI_LEN<<1 - src_nib_len);
        !          3722:        nibble_copy(first_nib? z_pad : f_pad, HIGH_NIBBLE,
        !          3723:                (caddr_t) addr->siso_addr.t37_idi, HIGH_NIBBLE, pad_len);
        !          3724: 
        !          3725:        dst_octet += (pad_len>>1);
        !          3726:        dst_nibble = 1-(pad_len & 0x1);
        !          3727:        IFDEBUG(D_CADDR)
        !          3728:                printf("DTEtoNSAP 2( 0x%x, 0x%x, 0x%x, 0x%x )\n", 
        !          3729:                        dst_octet, dst_nibble, pad_len, src_nib_len );
        !          3730:        ENDDEBUG
        !          3731: 
        !          3732:        /* now copy the dte address */
        !          3733:        nibble_copy( src_octet, src_nibble, dst_octet, dst_nibble, src_nib_len);
        !          3734: 
        !          3735:        addr->siso_addr.isoa_len = ADDR37_IDI_LEN + ADDR37_DSP_LEN +1 /* for afi */;
        !          3736:                /* kludge */
        !          3737: 
        !          3738:        addr->siso_tsuffix = unmunge(
        !          3739:                (caddr_t) &(addr->siso_addr.t37_idi[ADDR37_IDI_LEN]), HIGH_NIBBLE);
        !          3740: 
        !          3741:        IFDEBUG(D_CADDR)
        !          3742:                printf("DTEtoNSAP 3 returning 0 tsuffix 0x%x\n", addr->siso_tsuffix);
        !          3743:        ENDDEBUG
        !          3744: 
        !          3745:        return 0; /* ok */
        !          3746: }
        !          3747: 
        !          3748: /*
        !          3749:  * FUNCTION and ARGUMENTS:
        !          3750:  *     parses (buf_len) bytes beginning at (buf) and finds
        !          3751:  *  a called nsap, a calling nsap, and protocol identifier.
        !          3752:  * RETURNS:
        !          3753:  *  0 if ok, E* otherwise.
        !          3754:  */
        !          3755: 
        !          3756: Static int
        !          3757: parse_facil( buf, buf_len, called, calling, proto, peer_dte)
        !          3758:        caddr_t                 buf;
        !          3759:        u_char                  buf_len; /* in bytes */
        !          3760:        register struct sockaddr_iso *called, *calling;
        !          3761:        int                             *proto;
        !          3762:        struct  dte_addr        *peer_dte;
        !          3763: {
        !          3764:        register int    i;
        !          3765:        caddr_t                 ptr;
        !          3766:        caddr_t                 facil_len;
        !          3767:        int                     facil_param_len;
        !          3768:        struct  sockaddr_iso *addr;
        !          3769:        int                             addrs_not_parsed = (int)0xcb + (int)0xc9;
        !          3770: 
        !          3771:        IFDEBUG(D_CADDR)
        !          3772:                printf("parse_facil( 0x%x, 0x%x, 0x%x, 0x%x, 0x%x )\n", 
        !          3773:                        buf, buf_len, called, calling, *proto);
        !          3774:                dump_buf(buf, buf_len);
        !          3775:        ENDDEBUG
        !          3776: 
        !          3777:        /* find the beginnings of the facility fields in buf 
        !          3778:         * by skipping over the called & calling DTE addresses
        !          3779:         * i <- # nibbles in called + # nibbles in calling
        !          3780:         * i += 1 so that an odd nibble gets rounded up to even  
        !          3781:         * before dividing by 2, then divide by two to get # octets
        !          3782:         */
        !          3783:        i = (int)(*buf >> 4) + (int)(*buf&0xf);
        !          3784:        i++;
        !          3785:        ptr = (caddr_t) (buf + (i>>1));
        !          3786:        /* now i is number of octets */
        !          3787: 
        !          3788:        ptr ++; /* plus one for the DTE lengths byte */
        !          3789: 
        !          3790:        /* ptr now is at facil_length field */
        !          3791:        facil_len = ptr++;
        !          3792:        IFDEBUG(D_CADDR)
        !          3793:                printf("parse_facils: facil length is  0x%x\n", (int) *facil_len);
        !          3794:        ENDDEBUG
        !          3795: 
        !          3796:        while( ptr <= (caddr_t)(facil_len + (int)*facil_len) ) {
        !          3797:                /* get NSAP addresses from facilities */
        !          3798:                switch (*ptr) {
        !          3799:                        case 0xcb:
        !          3800:                                facil_param_len = 0;
        !          3801:                                addr = calling;
        !          3802:                                addrs_not_parsed -= 0xcb;
        !          3803:                                break;
        !          3804:                        case 0xc9:
        !          3805:                                facil_param_len = 0;
        !          3806:                                addr = called;
        !          3807:                                addrs_not_parsed -= 0xc9;
        !          3808:                                break;
        !          3809: 
        !          3810:                                /* from here to default are legit cases that I ignore */
        !          3811: 
        !          3812:                                /* variable length */
        !          3813:                        case 0xca:  /* end-to-end transit delay negot */
        !          3814:                        case 0xc6:  /* network user id */
        !          3815:                        case 0xc5:      /* charging info : indicating monetary unit */
        !          3816:                        case 0xc2:      /* charging info : indicating segment count */
        !          3817:                        case 0xc1:      /* charging info : indicating call duration */
        !          3818:                        case 0xc4:      /* RPOA extended format */
        !          3819:                        case 0xc3:      /* call redirection notification */
        !          3820:                                facil_param_len = 0;
        !          3821:                                addr = (struct sockaddr_iso *)0;
        !          3822:                                break;
        !          3823: 
        !          3824:                                /* 1 octet */
        !          3825:                        case 0x0a:  /* min. throughput class negot */
        !          3826:                        case 0x02:  /* throughput class */
        !          3827:                        case 0x03:  case 0x47:  /* CUG shit */
        !          3828:                        case 0x0b:  /* expedited data negot */
        !          3829:                        case 0x01:  /* Fast select or reverse charging 
        !          3830:                                                (example of intelligent protocol design) */
        !          3831:                        case 0x04:      /* charging info : requesting service */
        !          3832:                        case 0x08:      /* called line addr modified notification */
        !          3833:                                facil_param_len = 1;
        !          3834:                                addr = (struct sockaddr_iso *)0;
        !          3835:                                break;
        !          3836: 
        !          3837:                                /* any 2 octets */
        !          3838:                        case 0x42:  /* pkt size */
        !          3839:                        case 0x43:  /* win size */
        !          3840:                        case 0x44:  /* RPOA basic format */
        !          3841:                        case 0x41:  /* bilateral CUG shit */
        !          3842:                        case 0x49:      /* transit delay selection and indication */
        !          3843:                                facil_param_len = 2;
        !          3844:                                addr = (struct sockaddr_iso *)0;
        !          3845:                                break;
        !          3846: 
        !          3847:                                /* don't have any 3 octets */
        !          3848:                                /*
        !          3849:                                facil_param_len = 3;
        !          3850:                                */
        !          3851:                        default:
        !          3852:                                ASSERT(0);
        !          3853:                                printf(
        !          3854: "BOGUS FACILITY CODE facil_len 0x%x *facil_len 0x%x, ptr 0x%x *ptr 0x%x\n",
        !          3855:                                        facil_len, *facil_len,
        !          3856:                                        ptr, *ptr);
        !          3857:                                addr = (struct sockaddr_iso *)0;
        !          3858:                                /* facil that we don't handle */
        !          3859:                                return E_CO_HLI_REJI;
        !          3860:                }
        !          3861:                ptr++; /* one for facil code */
        !          3862:                if(facil_param_len == 0) /* variable length */ 
        !          3863:                        facil_param_len = (int)*ptr; /* 1 + the real facil param */
        !          3864:                if( addr &&  FACILtoNSAP(ptr+1, facil_param_len-1, addr) ) {
        !          3865:                        return E_CO_OSI_UNSAP;
        !          3866:                }
        !          3867:                ptr += facil_param_len;
        !          3868:        }
        !          3869:        if( addrs_not_parsed ) {
        !          3870:                /* no facilities, get NSAP addresses from DTE addresses */
        !          3871:                register int ed, ing;
        !          3872: 
        !          3873:                ed = (int)(*buf&0xf);
        !          3874:                if( ed == 0 ) {
        !          3875:                        panic("Called DTE address absent");
        !          3876:                }
        !          3877:                DTEtoNSAP(called, (buf + 1)/*octet*/, 
        !          3878:                        1/*nibble*/, ed);
        !          3879: 
        !          3880:                ing = (int)(*buf >> 4); 
        !          3881:                if( ing == 0 ) {
        !          3882:                        printf("cons: panic: Calling DTE address absent");
        !          3883:                        return E_CO_HLI_REJI;
        !          3884:                }
        !          3885:                nibble_copy((buf + (ed>>1)+1)/*octet*/, 1-(ed&0x1)/*nibble*/, 
        !          3886:                        peer_dte->dtea_addr, HIGH_NIBBLE, ing);
        !          3887:                DTEtoNSAP(calling, (buf + (ed>>1)+1)/*octet*/, 
        !          3888:                        1-(ed&0x1)/*nibble*/, ing);
        !          3889: 
        !          3890:        }
        !          3891: 
        !          3892:        ASSERT( ptr == (caddr_t)(facil_len + 1 + (int)*facil_len) );
        !          3893: 
        !          3894:        /* 
        !          3895:         * now look for user data to find protocol identifier
        !          3896:         */
        !          3897:        if( ptr == buf + buf_len ) {
        !          3898:                /* no user data */
        !          3899:                *proto = ISOPROTO_TP; /* to proto id --> use TP */
        !          3900:                IFDEBUG(D_CADDR)
        !          3901:                        printf("NO USER DATA: use TP\n");
        !          3902:                ENDDEBUG
        !          3903:        } else {
        !          3904:                ASSERT ( ptr < buf + buf_len );
        !          3905:                if ( ptr >= buf + buf_len ) {
        !          3906:                        printf("ptr 0x%x buf 0x%x buf_len 0x%x buf+buf_len 0x%x\n",
        !          3907:                                ptr, buf, buf_len, buf+buf_len);
        !          3908:                }
        !          3909:                IFDEBUG(D_CADDR)
        !          3910:                        printf("proto byte 0x%x, value 0x%x\n", ptr, *ptr);
        !          3911:                ENDDEBUG
        !          3912:                switch(*ptr) {
        !          3913:                case 0x81:
        !          3914:                        *proto = ISOPROTO_CLNP;
        !          3915:                        break;
        !          3916:                case 0x0:
        !          3917:                        *proto = ISOPROTO_INACT_NL;
        !          3918:                        break;
        !          3919:                case  'e': /* for EAN */
        !          3920:                        *proto = ISOPROTO_TP; 
        !          3921:                        /* can check for "an2" or can ignore the rest of the u data */
        !          3922:                        break;
        !          3923:                case 0xff: /* reserved for future extensions */
        !          3924:                        *proto =  ISOPROTO_X25;
        !          3925:                        break;
        !          3926:                case 0x82: /* 9542 not implemented */
        !          3927:                case 0x84: /* 8878/A SNDCP not implemented */
        !          3928:                default:
        !          3929:                        *proto =  -1; 
        !          3930:                        return E_CO_HLI_PROTOID;
        !          3931:                }
        !          3932:        }
        !          3933:        return 0;
        !          3934: }
        !          3935: 
        !          3936: #endif NARGOXTWENTYFIVE > 0

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.