Annotation of XNU/bsd/netiso/if_cons.c, revision 1.1.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.