Annotation of kernel/bsd/netiso/if_cons.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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