Annotation of XNU/bsd/netiso/if_cons.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*-
        !            23:  * Copyright (c) 1991, 1993
        !            24:  *     The Regents of the University of California.  All rights reserved.
        !            25:  *
        !            26:  * Redistribution and use in source and binary forms, with or without
        !            27:  * modification, are permitted provided that the following conditions
        !            28:  * are met:
        !            29:  * 1. Redistributions of source code must retain the above copyright
        !            30:  *    notice, this list of conditions and the following disclaimer.
        !            31:  * 2. Redistributions in binary form must reproduce the above copyright
        !            32:  *    notice, this list of conditions and the following disclaimer in the
        !            33:  *    documentation and/or other materials provided with the distribution.
        !            34:  * 3. All advertising materials mentioning features or use of this software
        !            35:  *    must display the following acknowledgement:
        !            36:  *     This product includes software developed by the University of
        !            37:  *     California, Berkeley and its contributors.
        !            38:  * 4. Neither the name of the University nor the names of its contributors
        !            39:  *    may be used to endorse or promote products derived from this software
        !            40:  *    without specific prior written permission.
        !            41:  *
        !            42:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            43:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            44:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            45:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            46:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            47:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            48:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            49:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            50:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            51:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            52:  * SUCH DAMAGE.
        !            53:  *
        !            54:  *     @(#)if_cons.c   8.1 (Berkeley) 6/10/93
        !            55:  */
        !            56: 
        !            57: /***********************************************************
        !            58:                Copyright IBM Corporation 1987
        !            59: 
        !            60:                       All Rights Reserved
        !            61: 
        !            62: Permission to use, copy, modify, and distribute this software and its 
        !            63: documentation for any purpose and without fee is hereby granted, 
        !            64: provided that the above copyright notice appear in all copies and that
        !            65: both that copyright notice and this permission notice appear in 
        !            66: supporting documentation, and that the name of IBM not be
        !            67: used in advertising or publicity pertaining to distribution of the
        !            68: software without specific, written prior permission.  
        !            69: 
        !            70: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
        !            71: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
        !            72: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
        !            73: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
        !            74: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
        !            75: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
        !            76: SOFTWARE.
        !            77: 
        !            78: ******************************************************************/
        !            79: 
        !            80: /*
        !            81:  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
        !            82:  */
        !            83: /*
        !            84:  * cons.c - Connection Oriented Network Service:
        !            85:  * including support for a) user transport-level service, 
        !            86:  *     b) COSNS below CLNP, and c) CONS below TP.
        !            87:  */
        !            88: 
        !            89: #if TPCONS
        !            90: #ifdef KERNEL
        !            91: #ifdef ARGO_DEBUG
        !            92: #define Static  
        !            93: unsigned LAST_CALL_PCB;
        !            94: #else /* ARGO_DEBUG */
        !            95: #define Static static
        !            96: #endif /* ARGO_DEBUG */
        !            97: 
        !            98: #ifndef SOCK_STREAM
        !            99: #include <sys/param.h>
        !           100: #include <sys/systm.h>
        !           101: #include <sys/mbuf.h>
        !           102: #include <sys/protosw.h>
        !           103: #include <sys/socket.h>
        !           104: #include <sys/socketvar.h>
        !           105: #include <sys/errno.h>
        !           106: #include <sys/ioctl.h>
        !           107: #include <sys/tsleep.h>
        !           108: 
        !           109: #include <net/if.h>
        !           110: #include <net/netisr.h>
        !           111: #include <net/route.h>
        !           112: 
        !           113: #include <netiso/iso_errno.h>
        !           114: #include <netiso/argo_debug.h>
        !           115: #include <netiso/tp_trace.h>
        !           116: #include <netiso/iso.h>
        !           117: #include <netiso/cons.h>
        !           118: #include <netiso/iso_pcb.h>
        !           119: 
        !           120: #include <netccitt/x25.h>
        !           121: #include <netccitt/pk.h>
        !           122: #include <netccitt/pk_var.h>
        !           123: #endif
        !           124: 
        !           125: #ifdef ARGO_DEBUG
        !           126: #define MT_XCONN       0x50
        !           127: #define MT_XCLOSE      0x51
        !           128: #define MT_XCONFIRM    0x52
        !           129: #define MT_XDATA       0x53
        !           130: #define MT_XHEADER     0x54
        !           131: #else
        !           132: #define MT_XCONN       MT_DATA
        !           133: #define MT_XCLOSE      MT_DATA
        !           134: #define MT_XCONFIRM    MT_DATA
        !           135: #define MT_XDATA       MT_DATA
        !           136: #define MT_XHEADER     MT_HEADER
        !           137: #endif /* ARGO_DEBUG */
        !           138: 
        !           139: #define DONTCLEAR       -1
        !           140: 
        !           141: /********************************************************************* 
        !           142:  * cons.c - CONS interface to the x.25 layer
        !           143:  *
        !           144:  * TODO: figure out what resources we might run out of besides mbufs.
        !           145:  *  If we run out of any of them (including mbufs) close and recycle
        !           146:  *  lru x% of the connections, for some parameter x.
        !           147:  *
        !           148:  * There are 2 interfaces from above:
        !           149:  * 1) from TP0: 
        !           150:  *    cons CO network service
        !           151:  *    TP associates a transport connection with a network connection.
        !           152:  *       cons_output( isop, m, len, isdgm==0 ) 
        !           153:  *        co_flags == 0
        !           154:  * 2) from TP4:
        !           155:  *       It's a datagram service, like clnp is. - even though it calls
        !           156:  *                     cons_output( isop, m, len, isdgm==1 ) 
        !           157:  *       it eventually goes through
        !           158:  *                     cosns_output(ifp, m, dst).
        !           159:  *    TP4 permits multiplexing (reuse, possibly simultaneously) of the 
        !           160:  *       network connections.
        !           161:  *    This means that many sockets (many tpcbs) may be associated with
        !           162:  *    this pklcd, hence cannot have a back ptr from pklcd to a tpcb.
        !           163:  *        co_flags & CONSF_DGM 
        !           164:  *    co_socket is null since there may be many sockets that use this pklcd.
        !           165:  *
        !           166: NOTE:
        !           167:        streams would really be nice. sigh.
        !           168: NOTE:
        !           169:        PVCs could be handled by config-ing a cons with an address and with the
        !           170:        IFF_POINTTOPOINT flag on.  This code would then have to skip the
        !           171:        connection setup stuff for pt-to-pt links.  
        !           172: 
        !           173: 
        !           174:  *********************************************************************/
        !           175: 
        !           176: 
        !           177: #define CONS_IFQMAXLEN 5
        !           178: 
        !           179: 
        !           180: /* protosw pointers for getting to higher layer */
        !           181: Static         struct protosw  *CLNP_proto;
        !           182: Static         struct protosw  *TP_proto;
        !           183: Static         struct protosw  *X25_proto;
        !           184: Static         int                             issue_clear_req();
        !           185: 
        !           186: #ifndef        PHASEONE
        !           187: extern struct ifaddr   *ifa_ifwithnet();
        !           188: #endif /* PHASEONE */
        !           189: 
        !           190: extern struct ifaddr   *ifa_ifwithaddr();
        !           191: 
        !           192: extern struct  isopcb  tp_isopcb; /* chain of all TP pcbs */
        !           193: 
        !           194: 
        !           195: Static         int parse_facil(), NSAPtoDTE(), make_partial_x25_packet();
        !           196: Static int FACILtoNSAP(), DTEtoNSAP();
        !           197: Static struct pklcd *cons_chan_to_pcb();
        !           198: 
        !           199: #define HIGH_NIBBLE 1
        !           200: #define LOW_NIBBLE 0
        !           201: 
        !           202: /*
        !           203:  * NAME:       nibble_copy()
        !           204:  * FUNCTION and ARGUMENTS:
        !           205:  *     copies (len) nibbles from (src_octet), high or low nibble
        !           206:  *  to (dst_octet), high or low nibble,
        !           207:  * src_nibble & dst_nibble should be:
        !           208:  *     HIGH_NIBBLE (1) if leftmost 4 bits/ most significant nibble
        !           209:  *     LOW_NIBBLE (0) if rightmost 4 bits/ least significant nibble
        !           210:  * RETURNS: VOID
        !           211:  */
        !           212: void
        !           213: nibble_copy(src_octet, src_nibble, dst_octet, dst_nibble, len)
        !           214:        register char   *src_octet;
        !           215:        register char   *dst_octet;
        !           216:        register unsigned               src_nibble;
        !           217:        register unsigned               dst_nibble;
        !           218:        int             len;
        !           219: {
        !           220: 
        !           221:        register        i;
        !           222:        register        unsigned dshift, sshift;
        !           223: 
        !           224:        IFDEBUG(D_CADDR)
        !           225:                printf("nibble_copy ( 0x%x, 0x%x, 0x%x, 0x%x 0x%x)\n", 
        !           226:                 src_octet, src_nibble, dst_octet, dst_nibble, len);
        !           227:        ENDDEBUG
        !           228: #define SHIFT 0x4
        !           229: 
        !           230:        dshift = dst_nibble << 2;
        !           231:        sshift = src_nibble << 2;
        !           232: 
        !           233:        for (i=0; i<len; i++) {
        !           234:                /* clear dst_nibble  */
        !           235:                *dst_octet      &= ~(0xf<< dshift);
        !           236: 
        !           237:                /* set dst nibble */
        !           238:                *dst_octet      |= ( 0xf & (*src_octet >> sshift))<< dshift;
        !           239: 
        !           240:                dshift          ^= SHIFT;
        !           241:                sshift          ^= SHIFT;
        !           242:                src_nibble      = 1-src_nibble;
        !           243:                dst_nibble      = 1-dst_nibble;
        !           244:                src_octet       += src_nibble;
        !           245:                dst_octet       += dst_nibble;
        !           246:        }
        !           247:        IFDEBUG(D_CADDR)
        !           248:                printf("nibble_copy DONE\n");
        !           249:        ENDDEBUG
        !           250: }
        !           251: 
        !           252: /*
        !           253:  * NAME:       nibble_match()
        !           254:  * FUNCTION and ARGUMENTS:
        !           255:  *     compares src_octet/src_nibble and dst_octet/dst_nibble  for len nibbles.
        !           256:  * RETURNS: 0 if they differ, 1 if they are the same.
        !           257:  */
        !           258: int
        !           259: nibble_match( src_octet, src_nibble, dst_octet, dst_nibble, len)
        !           260:        register char   *src_octet;
        !           261:        register char   *dst_octet;
        !           262:        register unsigned               src_nibble;
        !           263:        register unsigned               dst_nibble;
        !           264:        int             len;
        !           265: {
        !           266: 
        !           267:        register        i;
        !           268:        register        unsigned dshift, sshift;
        !           269:        u_char          nibble_a, nibble_b;
        !           270: 
        !           271:        IFDEBUG(D_CADDR)
        !           272:                printf("nibble_match ( 0x%x, 0x%x, 0x%x, 0x%x 0x%x)\n", 
        !           273:                 src_octet, src_nibble, dst_octet, dst_nibble, len);
        !           274:        ENDDEBUG
        !           275: #define SHIFT 0x4
        !           276: 
        !           277:        dshift = dst_nibble << 2;
        !           278:        sshift = src_nibble << 2;
        !           279: 
        !           280:        for (i=0; i<len; i++) {
        !           281:                nibble_b = ((*dst_octet)>>dshift) & 0xf;
        !           282:                nibble_a = ( 0xf & (*src_octet >> sshift));
        !           283:                if (nibble_b != nibble_a)
        !           284:                        return 0;
        !           285: 
        !           286:                dshift          ^= SHIFT;
        !           287:                sshift          ^= SHIFT;
        !           288:                src_nibble      = 1-src_nibble;
        !           289:                dst_nibble      = 1-dst_nibble;
        !           290:                src_octet       += src_nibble;
        !           291:                dst_octet       += dst_nibble;
        !           292:        }
        !           293:        IFDEBUG(D_CADDR)
        !           294:                printf("nibble_match DONE\n");
        !           295:        ENDDEBUG
        !           296:        return 1;
        !           297: }
        !           298: 
        !           299: /*
        !           300:  **************************** NET PROTOCOL cons ***************************
        !           301:  */
        !           302: /*
        !           303:  * NAME:       cons_init()
        !           304:  * CALLED FROM:
        !           305:  *     autoconf
        !           306:  * FUNCTION:
        !           307:  *     initialize the protocol
        !           308:  */
        !           309: cons_init()
        !           310: {
        !           311:        int tp_incoming(), clnp_incoming();
        !           312: 
        !           313: 
        !           314:        CLNP_proto = pffindproto(AF_ISO, ISOPROTO_CLNP, SOCK_DGRAM); 
        !           315:        X25_proto = pffindproto(AF_ISO, ISOPROTO_X25, SOCK_STREAM);
        !           316:        TP_proto = pffindproto(AF_ISO, ISOPROTO_TP0, SOCK_SEQPACKET);
        !           317:        IFDEBUG(D_CCONS)
        !           318:                printf("cons_init end : cnlp_proto 0x%x cons proto 0x%x tp proto 0x%x\n",
        !           319:                        CLNP_proto, X25_proto, TP_proto);
        !           320:        ENDDEBUG
        !           321: #ifdef notdef
        !           322:        pk_protolisten(0x81, 0, clnp_incoming);
        !           323:        pk_protolisten(0x82, 0, esis_incoming);
        !           324:        pk_protolisten(0x84, 0, tp8878_A_incoming);
        !           325:        pk_protolisten(0, 0, tp_incoming);
        !           326: #endif
        !           327: }
        !           328: 
        !           329: tp_incoming(lcp, m)
        !           330: struct pklcd *lcp;
        !           331: register struct mbuf *m;
        !           332: {
        !           333:        register struct isopcb *isop;
        !           334:        int cons_tpinput();
        !           335: 
        !           336:        if (iso_pcballoc((struct socket *)0, &tp_isopcb)) {
        !           337:                pk_close(lcp);
        !           338:                return;
        !           339:        }
        !           340:        isop = tp_isopcb.isop_next;
        !           341:        lcp->lcd_upper = cons_tpinput;
        !           342:        lcp->lcd_upnext = (caddr_t)isop;
        !           343:        lcp->lcd_send(lcp); /* Confirms call */
        !           344:        isop->isop_chan = (caddr_t)lcp;
        !           345:        isop->isop_laddr = &isop->isop_sladdr;
        !           346:        isop->isop_faddr = &isop->isop_sfaddr;
        !           347:        DTEtoNSAP(isop->isop_laddr, &lcp->lcd_laddr);
        !           348:        DTEtoNSAP(isop->isop_faddr, &lcp->lcd_faddr);
        !           349:        parse_facil(lcp, isop, &(mtod(m, struct x25_packet *)->packet_data),
        !           350:                m->m_pkthdr.len - PKHEADERLN);
        !           351: }
        !           352: 
        !           353: cons_tpinput(lcp, m0)
        !           354: struct mbuf *m0;
        !           355: struct pklcd *lcp;
        !           356: {
        !           357:        register struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext;
        !           358:        register struct x25_packet *xp;
        !           359:        int cmd, ptype = CLEAR;
        !           360: 
        !           361:        if (isop == 0)
        !           362:                return;
        !           363:        if (m0 == 0)
        !           364:                goto dead;
        !           365:        switch(m0->m_type) {
        !           366:        case MT_DATA:
        !           367:        case MT_OOBDATA:
        !           368:                tpcons_input(m0, isop->isop_faddr, isop->isop_laddr, (caddr_t)lcp);
        !           369:                return;
        !           370: 
        !           371:        case MT_CONTROL:
        !           372:                switch (ptype = pk_decode(mtod(m0, struct x25_packet *))) {
        !           373: 
        !           374:                case RR:
        !           375:                        cmd = PRC_CONS_SEND_DONE;
        !           376:                        break;
        !           377: 
        !           378:                case CALL_ACCEPTED:
        !           379:                        if (lcp->lcd_sb.sb_mb)
        !           380:                                lcp->lcd_send(lcp); /* XXX - fix this */
        !           381:                        /*FALLTHROUGH*/
        !           382:                default:
        !           383:                        return;
        !           384: 
        !           385:                dead:
        !           386:                case CLEAR:
        !           387:                case CLEAR_CONF:
        !           388:                        lcp->lcd_upper = 0;
        !           389:                        lcp->lcd_upnext = 0;
        !           390:                        isop->isop_chan = 0;
        !           391:                case RESET:
        !           392:                        cmd = PRC_ROUTEDEAD;
        !           393:                }
        !           394:                tpcons_ctlinput(cmd, isop->isop_faddr, isop);
        !           395:                if (cmd = PRC_ROUTEDEAD && isop->isop_refcnt == 0) 
        !           396:                        iso_pcbdetach(isop);
        !           397:        }
        !           398: }
        !           399: 
        !           400: /*
        !           401:  * NAME:       cons_connect()
        !           402:  * CALLED FROM:
        !           403:  *     tpcons_pcbconnect() when opening a new connection.  
        !           404:  * FUNCTION anD ARGUMENTS:
        !           405:  *  Figures out which device to use, finding a route if one doesn't
        !           406:  *  already exist.
        !           407:  * RETURN VALUE:
        !           408:  *  returns E*
        !           409:  */
        !           410: cons_connect(isop)
        !           411:        register struct isopcb *isop;
        !           412: {
        !           413:        register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
        !           414:        register struct mbuf    *m;
        !           415:        struct ifaddr                   *ifa;
        !           416:        int error;
        !           417: 
        !           418:        IFDEBUG(D_CCONN)
        !           419:                printf("cons_connect(0x%x): ", isop);
        !           420:                dump_isoaddr(isop->isop_faddr);
        !           421:                printf("myaddr: ");
        !           422:                dump_isoaddr(isop->isop_laddr);
        !           423:                printf("\n" );
        !           424:        ENDDEBUG
        !           425:        NSAPtoDTE(isop->isop_faddr, &lcp->lcd_faddr);
        !           426:        lcp->lcd_upper = cons_tpinput;
        !           427:        lcp->lcd_upnext = (caddr_t)isop;
        !           428:        IFDEBUG(D_CCONN)
        !           429:                printf(
        !           430:                "calling make_partial_x25_packet( 0x%x, 0x%x, 0x%x)\n",
        !           431:                        &lcp->lcd_faddr, &lcp->lcd_laddr, 
        !           432:                        isop->isop_socket->so_proto->pr_protocol); 
        !           433:        ENDDEBUG
        !           434:        if ((error = make_partial_x25_packet(isop, lcp, m)) == 0)
        !           435:                error = pk_connect(lcp, &lcp->lcd_faddr);
        !           436:        return error;
        !           437: }
        !           438: 
        !           439: /*
        !           440:  **************************** DEVICE cons ***************************
        !           441:  */
        !           442: 
        !           443: 
        !           444: /* 
        !           445:  * NAME:       cons_ctlinput()
        !           446:  * CALLED FROM:
        !           447:  *  lower layer when ECN_CLEAR occurs : this routine is here
        !           448:  *  for consistency - cons subnet service calls its higher layer
        !           449:  *  through the protosw entry.
        !           450:  * FUNCTION & ARGUMENTS:
        !           451:  *  cmd is a PRC_* command, list found in ../sys/protosw.h
        !           452:  *  copcb is the obvious.
        !           453:  *  This serves the higher-layer cons service.
        !           454:  * NOTE: this takes 3rd arg. because cons uses it to inform itself
        !           455:  *  of things (timeouts, etc) but has a pcb instead of an address.
        !           456:  */
        !           457: cons_ctlinput(cmd, sa, copcb)
        !           458:        int cmd;
        !           459:        struct sockaddr *sa;
        !           460:        register struct pklcd *copcb;
        !           461: {
        !           462: }
        !           463: 
        !           464: 
        !           465: find_error_reason( xp )
        !           466:        register struct x25_packet *xp;
        !           467: {
        !           468:        extern u_char x25_error_stats[];
        !           469:        int error, cause;
        !           470: 
        !           471:        if (xp) {
        !           472:                cause = 4[(char *)xp];
        !           473:                switch (cause) {
        !           474:                        case 0x00:
        !           475:                        case 0x80:
        !           476:                                /* DTE originated; look at the diagnostic */
        !           477:                                error = (CONL_ERROR_MASK | cause);
        !           478:                                goto done;
        !           479: 
        !           480:                        case 0x01: /* number busy */
        !           481:                        case 0x81:
        !           482:                        case 0x09: /* Out of order */
        !           483:                        case 0x89:
        !           484:                        case 0x11: /* Remot Procedure Error */
        !           485:                        case 0x91:
        !           486:                        case 0x19: /* reverse charging accept not subscribed */
        !           487:                        case 0x99:
        !           488:                        case 0x21: /* Incampat destination */
        !           489:                        case 0xa1:
        !           490:                        case 0x29: /* fast select accept not subscribed */
        !           491:                        case 0xa9:
        !           492:                        case 0x39: /* ship absent */
        !           493:                        case 0xb9:
        !           494:                        case 0x03: /* invalid facil request */
        !           495:                        case 0x83:
        !           496:                        case 0x0b: /* access barred */
        !           497:                        case 0x8b:
        !           498:                        case 0x13: /* local procedure error */
        !           499:                        case 0x93:
        !           500:                        case 0x05: /* network congestion */
        !           501:                        case 0x85:
        !           502:                        case 0x8d: /* not obtainable */
        !           503:                        case 0x0d:
        !           504:                        case 0x95: /* RPOA out of order */
        !           505:                        case 0x15:
        !           506:                                /* take out bit 8 
        !           507:                                 * so we don't have to have so many perror entries 
        !           508:                                 */
        !           509:                                error = (CONL_ERROR_MASK | 0x100 | (cause & ~0x80));
        !           510:                                goto done;
        !           511: 
        !           512:                        case 0xc1: /* gateway-detected proc error */
        !           513:                        case 0xc3: /* gateway congestion */
        !           514: 
        !           515:                                error = (CONL_ERROR_MASK | 0x100 | cause);
        !           516:                                goto done;
        !           517:                } 
        !           518:        } 
        !           519:        /* otherwise, a *hopefully* valid perror exists in the e_reason field */
        !           520:        error = xp->packet_data;
        !           521:        if (error = 0) {
        !           522:                printf("Incoming PKT TYPE 0x%x with reason 0x%x\n",
        !           523:                        pk_decode(xp),
        !           524:                        cause);
        !           525:                error = E_CO_HLI_DISCA;
        !           526:        } 
        !           527: 
        !           528: done:
        !           529:        return error;
        !           530: }
        !           531: 
        !           532: 
        !           533: 
        !           534: #endif /* KERNEL */
        !           535: 
        !           536: /*
        !           537:  * NAME:       make_partial_x25_packet()
        !           538:  *
        !           539:  * FUNCTION and ARGUMENTS:
        !           540:  *     Makes part of an X.25 call packet, for use by x25.
        !           541:  *  (src) and (dst) are the NSAP-addresses of source and destination.
        !           542:  *     (buf) is a ptr to a buffer into which to write this partial header.
        !           543:  *
        !           544:  *      0                      Facility length (in octets)
        !           545:  *      1                      Facility field, which is a set of:
        !           546:  *       m                     facil code
        !           547:  *       m+1           facil param len (for >2-byte facilities) in octets
        !           548:  *       m+2..p        facil param field
        !           549:  *  q                  user data (protocol identification octet)
        !           550:  * 
        !           551:  *
        !           552:  * RETURNS: 
        !           553:  *  0 if OK
        !           554:  *  E* if failed.
        !           555:  *
        !           556:  * SIDE EFFECTS:
        !           557:  * Stores facilites mbuf in X.25 control block, where the connect
        !           558:  * routine knows where to look for it.
        !           559:  */
        !           560: 
        !           561: #ifdef X25_1984 
        !           562: int cons_use_facils = 1;
        !           563: #else /* X25_1984  */
        !           564: int cons_use_facils = 0;
        !           565: #endif /* X25_1984  */
        !           566: 
        !           567: int cons_use_udata = 1; /* KLUDGE FOR DEBUGGING */
        !           568: 
        !           569: Static int
        !           570: make_partial_x25_packet(isop, lcp)
        !           571:        struct isopcb *isop;
        !           572:        struct pklcd *lcp;
        !           573: {
        !           574:        u_int                           proto;
        !           575:        int                                     flag;
        !           576:        caddr_t                         buf;
        !           577:        register caddr_t        ptr;
        !           578:        register int            len     = 0;
        !           579:        int                             buflen  =0;
        !           580:        caddr_t                         facil_len;
        !           581:        int                             oddness = 0;
        !           582:        struct mbuf *m;
        !           583: 
        !           584: 
        !           585:        IFDEBUG(D_CCONN)
        !           586:                printf("make_partial_x25_packet(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
        !           587:                        isop->isop_laddr, isop->isop_faddr, proto, m, flag);
        !           588:        ENDDEBUG
        !           589:        if (cons_use_udata) {
        !           590:                if (isop->isop_x25crud_len > 0) {
        !           591:                        /*
        !           592:                         *      The user specified something. Stick it in
        !           593:                         */
        !           594:                        bcopy(isop->isop_x25crud, lcp->lcd_faddr.x25_udata,
        !           595:                                        isop->isop_x25crud_len);
        !           596:                        lcp->lcd_faddr.x25_udlen = isop->isop_x25crud_len;
        !           597:                }
        !           598:        }
        !           599: 
        !           600:        if (cons_use_facils == 0) {
        !           601:                lcp->lcd_facilities = 0;
        !           602:                return 0;
        !           603:        }
        !           604:        MGETHDR(m, MT_DATA, M_WAITOK);
        !           605:        if (m == 0)
        !           606:                return ENOBUFS;
        !           607:        buf = mtod(m, caddr_t);
        !           608:        ptr = buf;
        !           609:        
        !           610:        /* ptr now points to facil length (len of whole facil field in OCTETS */
        !           611:        facil_len = ptr ++;
        !           612:        m->m_len = 0;
        !           613:        pk_build_facilities(m, &lcp->lcd_faddr, 0);
        !           614: 
        !           615:        IFDEBUG(D_CADDR)
        !           616:                printf("make_partial  calling: ptr 0x%x, len 0x%x\n", ptr, 
        !           617:                                isop->isop_laddr->siso_addr.isoa_len);
        !           618:        ENDDEBUG
        !           619:        if (cons_use_facils) {
        !           620:                *ptr++ = 0;      /* Marker to separate X.25 facitilies from CCITT ones */
        !           621:                *ptr++ = 0x0f;
        !           622:                *ptr = 0xcb; /* calling facility code */
        !           623:                ptr ++;
        !           624:                ptr ++; /* leave room for facil param len (in OCTETS + 1) */
        !           625:                ptr ++; /* leave room for the facil param len (in nibbles),
        !           626:                                 * high two bits of which indicate full/partial NSAP
        !           627:                                 */
        !           628:                len = isop->isop_laddr->siso_addr.isoa_len;
        !           629:                bcopy( isop->isop_laddr->siso_data, ptr, len);
        !           630:                *(ptr-2) = len+1; /* facil param len in octets */
        !           631:                *(ptr-1) = len<<1; /* facil param len in nibbles */
        !           632:                ptr += len;
        !           633: 
        !           634:                IFDEBUG(D_CADDR)
        !           635:                        printf("make_partial  called: ptr 0x%x, len 0x%x\n", ptr, 
        !           636:                                        isop->isop_faddr->siso_addr.isoa_len);
        !           637:                ENDDEBUG
        !           638:                *ptr = 0xc9; /* called facility code */
        !           639:                ptr ++;
        !           640:                ptr ++; /* leave room for facil param len (in OCTETS + 1) */
        !           641:                ptr ++; /* leave room for the facil param len (in nibbles),
        !           642:                                 * high two bits of which indicate full/partial NSAP
        !           643:                                 */
        !           644:                len = isop->isop_faddr->siso_nlen;
        !           645:                bcopy(isop->isop_faddr->siso_data, ptr, len);
        !           646:                *(ptr-2) = len+1; /* facil param len = addr len + 1 for each of these
        !           647:                                                  * two length fields, in octets */
        !           648:                *(ptr-1) = len<<1; /* facil param len in nibbles */
        !           649:                ptr += len;
        !           650: 
        !           651:        }
        !           652:        *facil_len = ptr - facil_len - 1;
        !           653:        if (*facil_len > MAX_FACILITIES)
        !           654:                return E_CO_PNA_LONG;
        !           655: 
        !           656:        buflen = (int)(ptr - buf);
        !           657: 
        !           658:        IFDEBUG(D_CDUMP_REQ)
        !           659:                register int i;
        !           660: 
        !           661:                printf("ECN_CONNECT DATA buf 0x%x len %d (0x%x)\n", 
        !           662:                        buf, buflen, buflen);
        !           663:                for( i=0; i < buflen; ) {
        !           664:                        printf("+%d: %x %x %x %x    %x %x %x %x\n",
        !           665:                                i,
        !           666:                                *(buf+i), *(buf+i+1), *(buf+i+2), *(buf+i+3),
        !           667:                                *(buf+i+4), *(buf+i+5), *(buf+i+6), *(buf+i+7));
        !           668:                        i+=8;
        !           669:                }
        !           670:        ENDDEBUG
        !           671:        IFDEBUG(D_CADDR)
        !           672:                printf("make_partial returns buf 0x%x size 0x%x bytes\n", 
        !           673:                        mtod(m, caddr_t), buflen);
        !           674:        ENDDEBUG
        !           675: 
        !           676:        if (buflen > MHLEN)
        !           677:                return E_CO_PNA_LONG;
        !           678: 
        !           679:        m->m_pkthdr.len = m->m_len = buflen;
        !           680:        lcp->lcd_facilities = m;
        !           681:        return  0;
        !           682: }
        !           683: 
        !           684: /*
        !           685:  * NAME:       NSAPtoDTE()
        !           686:  * CALLED FROM:
        !           687:  *  make_partial_x25_packet()
        !           688:  * FUNCTION and ARGUMENTS: 
        !           689:  *  get a DTE address from an NSAP-address (struct sockaddr_iso)
        !           690:  *  (dst_octet) is the octet into which to begin stashing the DTE addr
        !           691:  *  (dst_nibble) takes 0 or 1.  1 means begin filling in the DTE addr
        !           692:  *             in the high-order nibble of dst_octet.  0 means low-order nibble.
        !           693:  *  (addr) is the NSAP-address
        !           694:  *  (flag) is true if the transport suffix is to become the
        !           695:  *             last two digits of the DTE address
        !           696:  *  A DTE address is a series of ASCII digits
        !           697:  *
        !           698:  *     A DTE address may have leading zeros. The are significant.
        !           699:  *             1 digit per nibble, may be an odd number of nibbles.
        !           700:  *
        !           701:  *  An NSAP-address has the DTE address in the IDI. Leading zeros are
        !           702:  *             significant. Trailing hex f indicates the end of the DTE address.
        !           703:  *     The IDI is a series of BCD digits, one per nibble.
        !           704:  *
        !           705:  * RETURNS
        !           706:  *  # significant digits in the DTE address, -1 if error.
        !           707:  */
        !           708: 
        !           709: Static int
        !           710: NSAPtoDTE(siso, sx25)
        !           711:        register struct sockaddr_iso *siso;
        !           712:        register struct sockaddr_x25 *sx25;
        !           713: {
        !           714:        int             dtelen = -1;
        !           715: 
        !           716:        IFDEBUG(D_CADDR)
        !           717:                printf("NSAPtoDTE: nsap: %s\n", clnp_iso_addrp(&siso->siso_addr));
        !           718:        ENDDEBUG
        !           719: 
        !           720:        if (siso->siso_data[0] == AFI_37) {
        !           721:                register char *out = sx25->x25_addr;
        !           722:                register char *in = siso->siso_data + 1;
        !           723:                register int nibble;
        !           724:                char *lim = siso->siso_data + siso->siso_nlen;
        !           725:                char *olim = out+15;
        !           726:                int lowNibble = 0;
        !           727: 
        !           728:                while (in < lim) {
        !           729:                        nibble = ((lowNibble ? *in++ : (*in >> 4)) & 0xf) | 0x30;
        !           730:                        lowNibble ^= 1;
        !           731:                        if (nibble != 0x3f && out < olim)
        !           732:                                *out++ = nibble;
        !           733:                }
        !           734:                dtelen = out - sx25->x25_addr;
        !           735:                *out++ = 0;
        !           736:        } else {
        !           737:                /* error = iso_8208snparesolve(addr, x121string, &x121strlen);*/
        !           738:                register struct rtentry *rt;
        !           739:                extern struct sockaddr_iso blank_siso;
        !           740:                struct sockaddr_iso nsiso;
        !           741: 
        !           742:                nsiso = blank_siso;
        !           743:                bcopy(nsiso.siso_data, siso->siso_data,
        !           744:                                nsiso.siso_nlen = siso->siso_nlen);
        !           745:                if (rt = rtalloc1(&nsiso, 1)) {
        !           746:                        register struct sockaddr_x25 *sxx =
        !           747:                                                        (struct sockaddr_x25 *)rt->rt_gateway;
        !           748:                        register char *in = sxx->x25_addr;
        !           749: 
        !           750:                        rt->rt_use--;
        !           751:                        if (sxx && sxx->x25_family == AF_CCITT) {
        !           752:                                bcopy(sx25->x25_addr, sxx->x25_addr, sizeof(sx25->x25_addr));
        !           753:                                while (*in++) {}
        !           754:                                dtelen = in - sxx->x25_addr;
        !           755:                        }
        !           756:                }
        !           757:        }
        !           758:        return dtelen;
        !           759: }
        !           760: 
        !           761: /*
        !           762:  * NAME:       FACILtoNSAP()
        !           763:  * CALLED FROM:
        !           764:  *  parse_facil()
        !           765:  * FUNCTION and ARGUMENTS:
        !           766:  *     Creates and NSAP in the sockaddr_iso (addr) from the
        !           767:  *  x.25 facility found at buf - 1.
        !           768:  * RETURNS:
        !           769:  *  0 if ok, -1 if error.
        !           770:  */
        !           771: 
        !           772: Static int
        !           773: FACILtoNSAP(addr, buf)
        !           774:        register u_char                 *buf;
        !           775:        register struct sockaddr_iso *addr;
        !           776: {
        !           777:        int                     len_in_nibbles = *++buf & 0x3f;
        !           778:        u_char          buf_len = (len_in_nibbles + 1) >> 1;; /* in bytes */
        !           779: 
        !           780:        IFDEBUG(D_CADDR)
        !           781:                printf("FACILtoNSAP( 0x%x, 0x%x, 0x%x )\n", 
        !           782:                        buf, buf_len, addr );
        !           783:        ENDDEBUG
        !           784: 
        !           785:        len_in_nibbles = *buf & 0x3f;
        !           786:        /* despite the fact that X.25 makes us put a length in nibbles
        !           787:         * here, the NSAP-addrs are always in full octets
        !           788:         */
        !           789:        switch (*buf++ & 0xc0) {
        !           790:        case 0:
        !           791:                /* Entire OSI NSAP address */
        !           792:                bcopy((caddr_t)buf, addr->siso_data, addr->siso_nlen = buf_len);
        !           793:                break;
        !           794: 
        !           795:        case 40:
        !           796:                /* Partial OSI NSAP address, assume trailing */
        !           797:                if (buf_len + addr->siso_nlen > sizeof(addr->siso_addr))
        !           798:                        return -1;
        !           799:                bcopy((caddr_t)buf, TSEL(addr), buf_len);
        !           800:                addr->siso_nlen += buf_len;
        !           801:                break;
        !           802: 
        !           803:        default:
        !           804:                /* Rather than blow away the connection, just ignore and use
        !           805:                   NSAP from DTE */;
        !           806:        }
        !           807:        return 0;
        !           808: }
        !           809: 
        !           810: Static
        !           811: init_siso(siso)
        !           812: register struct sockaddr_iso *siso;
        !           813: {
        !           814:        siso->siso_len = sizeof (*siso);
        !           815:        siso->siso_family = AF_ISO;
        !           816:        siso->siso_data[0] = AFI_37;
        !           817:        siso->siso_nlen = 8;
        !           818: }
        !           819: 
        !           820: /*
        !           821:  * NAME:       DTEtoNSAP()
        !           822:  * CALLED FROM:
        !           823:  *  parse_facil()
        !           824:  * FUNCTION and ARGUMENTS:
        !           825:  *  Creates a type 37 NSAP in the sockaddr_iso (addr)
        !           826:  *     from a DTE address found in a sockaddr_x25.
        !           827:  *  
        !           828:  * RETURNS:
        !           829:  *  0 if ok; E* otherwise.
        !           830:  */
        !           831: 
        !           832: Static  int
        !           833: DTEtoNSAP(addr, sx)
        !           834:        struct sockaddr_iso *addr;
        !           835:        struct sockaddr_x25 *sx;
        !           836: {
        !           837:        register char           *in, *out;
        !           838:        register int            first;
        !           839:        int                                     pad_tail = 0;
        !           840:        int                             src_len;
        !           841: 
        !           842: 
        !           843:        init_siso(addr);
        !           844:        in = sx->x25_addr;
        !           845:        src_len = strlen(in);
        !           846:        addr->siso_nlen = (src_len + 3) / 2;
        !           847:        out = addr->siso_data;
        !           848:        *out++ = 0x37;
        !           849:        if (src_len & 1) {
        !           850:                pad_tail = 0xf;
        !           851:                src_len++;
        !           852:        }
        !           853:        for (first = 0; src_len > 0; src_len--) {
        !           854:                first |= 0xf & *in++;
        !           855:                if (src_len & 1) {
        !           856:                        *out++ = first;
        !           857:                        first = 0;
        !           858:                }
        !           859:                else first <<= 4;
        !           860:        }
        !           861:        if (pad_tail)
        !           862:                out[-1] |= 0xf;
        !           863:        return 0; /* ok */
        !           864: }
        !           865: 
        !           866: /*
        !           867:  * FUNCTION and ARGUMENTS:
        !           868:  *     parses (buf_len) bytes beginning at (buf) and finds
        !           869:  *  a called nsap, a calling nsap, and protocol identifier.
        !           870:  * RETURNS:
        !           871:  *  0 if ok, E* otherwise.
        !           872:  */
        !           873: 
        !           874: Static int
        !           875: parse_facil(lcp, isop, buf, buf_len)
        !           876:        caddr_t                 buf;
        !           877:        u_char                  buf_len; /* in bytes */
        !           878:        struct                  isopcb *isop;
        !           879:        struct                  pklcd *lcp;
        !           880: {
        !           881:        register int    i;
        !           882:        register u_char         *ptr = (u_char *)buf;
        !           883:        u_char                  *ptr_lim, *facil_lim;
        !           884:        int                     facil_param_len, facil_len;
        !           885: 
        !           886:        IFDEBUG(D_CADDR)
        !           887:                printf("parse_facil(0x%x, 0x%x, 0x%x, 0x%x)\n", 
        !           888:                        lcp, isop, buf, buf_len);
        !           889:                dump_buf(buf, buf_len);
        !           890:        ENDDEBUG
        !           891: 
        !           892:        /* find the beginnings of the facility fields in buf 
        !           893:         * by skipping over the called & calling DTE addresses
        !           894:         * i <- # nibbles in called + # nibbles in calling
        !           895:         * i += 1 so that an odd nibble gets rounded up to even  
        !           896:         * before dividing by 2, then divide by two to get # octets
        !           897:         */
        !           898:        i = (int)(*ptr >> 4) + (int)(*ptr&0xf);
        !           899:        i++;
        !           900:        ptr += i >> 1;
        !           901:        ptr ++; /* plus one for the DTE lengths byte */
        !           902: 
        !           903:        /* ptr now is at facil_length field */
        !           904:        facil_len = *ptr++;
        !           905:        facil_lim = ptr + facil_len;
        !           906:        IFDEBUG(D_CADDR)
        !           907:                printf("parse_facils: facil length is  0x%x\n", (int) facil_len);
        !           908:        ENDDEBUG
        !           909: 
        !           910:        while (ptr < facil_lim) {
        !           911:                /* get NSAP addresses from facilities */
        !           912:                switch (*ptr++) {
        !           913:                        case 0xcb:
        !           914:                                /* calling NSAP */
        !           915:                                facil_param_len = FACILtoNSAP(isop->isop_faddr, ptr);
        !           916:                                break;
        !           917:                        case 0xc9:
        !           918:                                /* called NSAP */
        !           919:                                facil_param_len = FACILtoNSAP(isop->isop_laddr, ptr);
        !           920:                                break;
        !           921: 
        !           922:                                /* from here to default are legit cases that I ignore */
        !           923:                                /* variable length */
        !           924:                        case 0xca:  /* end-to-end transit delay negot */
        !           925:                        case 0xc6:  /* network user id */
        !           926:                        case 0xc5:      /* charging info : indicating monetary unit */
        !           927:                        case 0xc2:      /* charging info : indicating segment count */
        !           928:                        case 0xc1:      /* charging info : indicating call duration */
        !           929:                        case 0xc4:      /* RPOA extended format */
        !           930:                        case 0xc3:      /* call redirection notification */
        !           931:                                facil_param_len = 0;
        !           932:                                break;
        !           933: 
        !           934:                                /* 1 octet */
        !           935:                        case 0x0a:  /* min. throughput class negot */
        !           936:                        case 0x02:  /* throughput class */
        !           937:                        case 0x03:  case 0x47:  /* CUG stuff */
        !           938:                        case 0x0b:  /* expedited data negot */
        !           939:                        case 0x01:  /* Fast select or reverse charging 
        !           940:                                                (example of intelligent protocol design) */
        !           941:                        case 0x04:      /* charging info : requesting service */
        !           942:                        case 0x08:      /* called line addr modified notification */
        !           943:                        case 0x00:  /* marker to indicate beginning of CCITT facils */
        !           944:                                facil_param_len = 1;
        !           945:                                break;
        !           946: 
        !           947:                                /* any 2 octets */
        !           948:                        case 0x42:  /* pkt size */
        !           949:                        case 0x43:  /* win size */
        !           950:                        case 0x44:  /* RPOA basic format */
        !           951:                        case 0x41:  /* bilateral CUG stuff */
        !           952:                        case 0x49:      /* transit delay selection and indication */
        !           953:                                facil_param_len = 2;
        !           954:                                break;
        !           955: 
        !           956:                        default:
        !           957:                                printf(
        !           958: "BOGUS FACILITY CODE facil_lim 0x%x facil_len %d, ptr 0x%x *ptr 0x%x\n",
        !           959:                                        facil_lim, facil_len, ptr - 1, ptr[-1]);
        !           960:                                /* facil that we don't handle
        !           961:                                return E_CO_HLI_REJI; */
        !           962:                                switch (ptr[-1] & 0xc0) {
        !           963:                                case 0x00:      facil_param_len = 1; break;
        !           964:                                case 0x40:      facil_param_len = 2; break;
        !           965:                                case 0x80:      facil_param_len = 3; break;
        !           966:                                case 0xc0:      facil_param_len = 0; break;
        !           967:                                }
        !           968:                }
        !           969:                if (facil_param_len == -1)
        !           970:                        return E_CO_REG_ICDA;
        !           971:                if (facil_param_len == 0) /* variable length */ 
        !           972:                        facil_param_len = (int)*ptr++; /* 1 + the real facil param */
        !           973:                ptr += facil_param_len;
        !           974:        }
        !           975:        return 0;
        !           976: }
        !           977: 
        !           978: #endif /* TPCONS */

unix.superglobalmegacorp.com

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