Annotation of 43BSDReno/sys/netiso/if_cons.c, revision 1.1.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.