Annotation of kernel/bsd/netccitt/pk_subr.c, revision 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) University of British Columbia, 1984
        !            27:  * Copyright (C) Computer Science Department IV, 
        !            28:  *              University of Erlangen-Nuremberg, Germany, 1992
        !            29:  * Copyright (c) 1991, 1992, 1993
        !            30:  *     The Regents of the University of California.  All rights reserved.
        !            31:  *
        !            32:  * This code is derived from software contributed to Berkeley by the
        !            33:  * Laboratory for Computation Vision and the Computer Science Department
        !            34:  * of the the University of British Columbia and the Computer Science
        !            35:  * Department (IV) of the University of Erlangen-Nuremberg, Germany.
        !            36:  *
        !            37:  * Redistribution and use in source and binary forms, with or without
        !            38:  * modification, are permitted provided that the following conditions
        !            39:  * are met:
        !            40:  * 1. Redistributions of source code must retain the above copyright
        !            41:  *    notice, this list of conditions and the following disclaimer.
        !            42:  * 2. Redistributions in binary form must reproduce the above copyright
        !            43:  *    notice, this list of conditions and the following disclaimer in the
        !            44:  *    documentation and/or other materials provided with the distribution.
        !            45:  * 3. All advertising materials mentioning features or use of this software
        !            46:  *    must display the following acknowledgement:
        !            47:  *     This product includes software developed by the University of
        !            48:  *     California, Berkeley and its contributors.
        !            49:  * 4. Neither the name of the University nor the names of its contributors
        !            50:  *    may be used to endorse or promote products derived from this software
        !            51:  *    without specific prior written permission.
        !            52:  *
        !            53:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            54:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            55:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            56:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            57:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            58:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            59:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            60:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            61:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            62:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            63:  * SUCH DAMAGE.
        !            64:  *
        !            65:  *     @(#)pk_subr.c   8.1 (Berkeley) 6/10/93
        !            66:  */
        !            67: 
        !            68: #include <sys/param.h>
        !            69: #include <sys/systm.h>
        !            70: #include <sys/mbuf.h>
        !            71: #include <sys/socket.h>
        !            72: #include <sys/protosw.h>
        !            73: #include <sys/socketvar.h>
        !            74: #include <sys/errno.h>
        !            75: #include <sys/time.h>
        !            76: #include <sys/kernel.h>
        !            77: #include <sys/malloc.h>
        !            78: 
        !            79: #include <net/if.h>
        !            80: #include <net/route.h>
        !            81: 
        !            82: #include <netccitt/dll.h>
        !            83: #include <netccitt/x25.h>
        !            84: #include <netccitt/x25err.h>
        !            85: #include <netccitt/pk.h>
        !            86: #include <netccitt/pk_var.h>
        !            87: 
        !            88: int     pk_sendspace = 1024 * 2 + 8;
        !            89: int     pk_recvspace = 1024 * 2 + 8;
        !            90: 
        !            91: struct pklcd_q pklcd_q = {&pklcd_q, &pklcd_q};
        !            92: 
        !            93: struct x25bitslice x25_bitslice[] = {
        !            94: /*       mask, shift value */
        !            95:        { 0xf0, 0x4 },
        !            96:        { 0xf,  0x0 },
        !            97:        { 0x80, 0x7 },
        !            98:        { 0x40, 0x6 },
        !            99:        { 0x30, 0x4 },
        !           100:        { 0xe0, 0x5 },
        !           101:        { 0x10, 0x4 },
        !           102:        { 0xe,  0x1 },
        !           103:        { 0x1,  0x0 }
        !           104: };
        !           105: 
        !           106: 
        !           107: /* 
        !           108:  *  Attach X.25 protocol to socket, allocate logical channel descripter
        !           109:  *  and buffer space, and enter LISTEN state if we are to accept
        !           110:  *  IN-COMMING CALL packets.  
        !           111:  *
        !           112:  */
        !           113: 
        !           114: struct pklcd *
        !           115: pk_attach (so)
        !           116: struct socket *so;
        !           117: {
        !           118:        register struct pklcd *lcp;
        !           119:        register int error = ENOBUFS;
        !           120:        int pk_output ();
        !           121: 
        !           122:        MALLOC(lcp, struct pklcd *, sizeof (*lcp), M_PCB, M_NOWAIT);
        !           123:        if (lcp) {
        !           124:                bzero ((caddr_t)lcp, sizeof (*lcp));
        !           125:                insque (&lcp -> lcd_q, &pklcd_q);
        !           126:                lcp -> lcd_state = READY;
        !           127:                lcp -> lcd_send = pk_output;
        !           128:                if (so) {
        !           129:                        error = soreserve (so, pk_sendspace, pk_recvspace);
        !           130:                        lcp -> lcd_so = so;
        !           131:                        if (so -> so_options & SO_ACCEPTCONN)
        !           132:                                lcp -> lcd_state = LISTEN;
        !           133:                } else
        !           134:                        sbreserve (&lcp -> lcd_sb, pk_sendspace);
        !           135:        }
        !           136:        if (so) {
        !           137:                so -> so_pcb = (caddr_t) lcp;
        !           138:                so -> so_error = error;
        !           139:        }
        !           140:        return (lcp);
        !           141: }
        !           142: 
        !           143: /* 
        !           144:  *  Disconnect X.25 protocol from socket.
        !           145:  */
        !           146: 
        !           147: pk_disconnect (lcp)
        !           148: register struct pklcd *lcp;
        !           149: {
        !           150:        register struct socket *so = lcp -> lcd_so;
        !           151:        register struct pklcd *l, *p;
        !           152: 
        !           153:        switch (lcp -> lcd_state) {
        !           154:        case LISTEN: 
        !           155:                for (p = 0, l = pk_listenhead; l && l != lcp; p = l, l = l -> lcd_listen);
        !           156:                if (p == 0) {
        !           157:                        if (l != 0)
        !           158:                                pk_listenhead = l -> lcd_listen;
        !           159:                }
        !           160:                else
        !           161:                if (l != 0)
        !           162:                        p -> lcd_listen = l -> lcd_listen;
        !           163:                pk_close (lcp);
        !           164:                break;
        !           165: 
        !           166:        case READY: 
        !           167:                pk_acct (lcp);
        !           168:                pk_close (lcp);
        !           169:                break;
        !           170: 
        !           171:        case SENT_CLEAR: 
        !           172:        case RECEIVED_CLEAR: 
        !           173:                break;
        !           174: 
        !           175:        default: 
        !           176:                pk_acct (lcp);
        !           177:                if (so) {
        !           178:                        soisdisconnecting (so);
        !           179:                        sbflush (&so -> so_rcv);
        !           180:                }
        !           181:                pk_clear (lcp, 241, 0); /* Normal Disconnect */
        !           182: 
        !           183:        }
        !           184: }
        !           185: 
        !           186: /* 
        !           187:  *  Close an X.25 Logical Channel. Discard all space held by the
        !           188:  *  connection and internal descriptors. Wake up any sleepers.
        !           189:  */
        !           190: 
        !           191: pk_close (lcp)
        !           192: struct pklcd *lcp;
        !           193: {
        !           194:        register struct socket *so = lcp -> lcd_so;
        !           195: 
        !           196:        /*
        !           197:         * If the X.25 connection is torn down due to link
        !           198:         * level failure (e.g. LLC2 FRMR) and at the same the user
        !           199:         * level is still filling up the socket send buffer that
        !           200:         * send buffer is locked. An attempt to sbflush () that send
        !           201:         * buffer will lead us into - no, not temptation but - panic!
        !           202:         * So - we'll just check wether the send buffer is locked
        !           203:         * and if that's the case we'll mark the lcp as zombie and 
        !           204:         * have the pk_timer () do the cleaning ...
        !           205:         */
        !           206:        
        !           207:        if (so && so -> so_snd.sb_flags & SB_LOCK)
        !           208:                lcp -> lcd_state = LCN_ZOMBIE;
        !           209:        else
        !           210:                pk_freelcd (lcp);
        !           211: 
        !           212:        if (so == NULL)
        !           213:                return;
        !           214: 
        !           215:        so -> so_pcb = 0;
        !           216:        soisdisconnected (so);
        !           217:        /* sofree (so); /* gak!!! you can't do that here */
        !           218: }
        !           219: 
        !           220: /* 
        !           221:  *  Create a template to be used to send X.25 packets on a logical
        !           222:  *  channel. It allocates an mbuf and fills in a skeletal packet
        !           223:  *  depending on its type. This packet is passed to pk_output where
        !           224:  *  the remainer of the packet is filled in.
        !           225: */
        !           226: 
        !           227: struct mbuf *
        !           228: pk_template (lcn, type)
        !           229: int lcn, type;
        !           230: {
        !           231:        register struct mbuf *m;
        !           232:        register struct x25_packet *xp;
        !           233: 
        !           234:        MGETHDR (m, M_DONTWAIT, MT_HEADER);
        !           235:        if (m == 0)
        !           236:                panic ("pk_template");
        !           237:        m -> m_act = 0;
        !           238: 
        !           239:        /*
        !           240:         * Efficiency hack: leave a four byte gap at the beginning
        !           241:         * of the packet level header with the hope that this will
        !           242:         * be enough room for the link level to insert its header.
        !           243:         */
        !           244:        m -> m_data += max_linkhdr;
        !           245:        m -> m_pkthdr.len = m -> m_len = PKHEADERLN;
        !           246: 
        !           247:        xp = mtod (m, struct x25_packet *);
        !           248:        *(long *)xp = 0;                /* ugly, but fast */
        !           249: /*     xp -> q_bit = 0;*/
        !           250:        X25SBITS(xp -> bits, fmt_identifier, 1);
        !           251: /*     xp -> lc_group_number = 0;*/
        !           252: 
        !           253:        SET_LCN(xp, lcn);
        !           254:        xp -> packet_type = type;
        !           255: 
        !           256:        return (m);
        !           257: }
        !           258: 
        !           259: /* 
        !           260:  *  This routine restarts all the virtual circuits. Actually,
        !           261:  *  the virtual circuits are not "restarted" as such. Instead,
        !           262:  *  any active switched circuit is simply returned to READY
        !           263:  *  state.
        !           264:  */
        !           265: 
        !           266: pk_restart (pkp, restart_cause)
        !           267: register struct pkcb *pkp;
        !           268: int restart_cause;
        !           269: {
        !           270:        register struct mbuf *m;
        !           271:        register struct pklcd *lcp;
        !           272:        register int i;
        !           273: 
        !           274:        /* Restart all logical channels. */
        !           275:        if (pkp -> pk_chan == 0)
        !           276:                return;
        !           277: 
        !           278:        /*
        !           279:         * Don't do this if we're doing a restart issued from
        !           280:         * inside pk_connect () --- which is only done if and
        !           281:         * only if the X.25 link is down, i.e. a RESTART needs
        !           282:         * to be done to get it up.
        !           283:         */
        !           284:        if (!(pkp -> pk_dxerole & DTE_CONNECTPENDING)) {
        !           285:                for (i = 1; i <= pkp -> pk_maxlcn; ++i)
        !           286:                        if ((lcp = pkp -> pk_chan[i]) != NULL) {
        !           287:                                if (lcp -> lcd_so) {
        !           288:                                        lcp -> lcd_so -> so_error = ENETRESET;
        !           289:                                        pk_close (lcp);
        !           290:                                } else {
        !           291:                                        pk_flush (lcp);
        !           292:                                        lcp -> lcd_state = READY;
        !           293:                                        if (lcp -> lcd_upper)
        !           294:                                                lcp -> lcd_upper (lcp, 0);
        !           295:                                }
        !           296:                        }
        !           297:        }
        !           298: 
        !           299:        if (restart_cause < 0)
        !           300:                return;
        !           301: 
        !           302:        pkp -> pk_state = DTE_SENT_RESTART;
        !           303:        pkp -> pk_dxerole &= ~(DTE_PLAYDCE | DTE_PLAYDTE);
        !           304:        lcp = pkp -> pk_chan[0];
        !           305:        m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESTART);
        !           306:        m -> m_pkthdr.len = m -> m_len += 2;
        !           307:        mtod (m, struct x25_packet *) -> packet_data = 0;       /* DTE only */
        !           308:        mtod (m, octet *)[4]  = restart_cause;
        !           309:        pk_output (lcp);
        !           310: }
        !           311: 
        !           312: 
        !           313: /* 
        !           314:  *  This procedure frees up the Logical Channel Descripter.
        !           315:  */
        !           316: 
        !           317: pk_freelcd (lcp)
        !           318: register struct pklcd *lcp;
        !           319: {
        !           320:        if (lcp == NULL)
        !           321:                return;
        !           322: 
        !           323:        if (lcp -> lcd_lcn > 0)
        !           324:                lcp -> lcd_pkp -> pk_chan[lcp -> lcd_lcn] = NULL;
        !           325: 
        !           326:        pk_flush (lcp);
        !           327:        remque (&lcp -> lcd_q);
        !           328:        free ((caddr_t)lcp, M_PCB);
        !           329: }
        !           330: 
        !           331: static struct x25_ifaddr *
        !           332: pk_ifwithaddr (sx)
        !           333:        struct sockaddr_x25 *sx;
        !           334: {
        !           335:        struct ifnet *ifp;
        !           336:        struct ifaddr *ifa;
        !           337:        register struct x25_ifaddr *ia;
        !           338:        char *addr = sx -> x25_addr;
        !           339: 
        !           340:        for (ifp = ifnet; ifp; ifp = ifp -> if_next)
        !           341:                for (ifa = ifp -> if_addrlist; ifa; ifa = ifa -> ifa_next)
        !           342:                        if (ifa -> ifa_addr -> sa_family == AF_CCITT) {
        !           343:                                ia = (struct x25_ifaddr *)ifa;
        !           344:                                if (bcmp (addr, ia -> ia_xc.xc_addr.x25_addr,
        !           345:                                         16) == 0)
        !           346:                                        return (ia);
        !           347:                                
        !           348:                        }
        !           349:        return ((struct x25_ifaddr *)0);
        !           350: }
        !           351: 
        !           352: 
        !           353: /* 
        !           354:  *  Bind a address and protocol value to a socket.  The important
        !           355:  *  part is the protocol value - the first four characters of the 
        !           356:  *  Call User Data field.
        !           357:  */
        !           358: 
        !           359: #define XTRACTPKP(rt)  ((rt) -> rt_flags & RTF_GATEWAY ? \
        !           360:                         ((rt) -> rt_llinfo ? \
        !           361:                          (struct pkcb *) ((struct rtentry *)((rt) -> rt_llinfo)) -> rt_llinfo : \
        !           362:                          (struct pkcb *) NULL) : \
        !           363:                         (struct pkcb *)((rt) -> rt_llinfo))
        !           364: 
        !           365: pk_bind (lcp, nam)
        !           366: struct pklcd *lcp;
        !           367: struct mbuf *nam;
        !           368: {
        !           369:        register struct pklcd *pp;
        !           370:        register struct sockaddr_x25 *sa;
        !           371: 
        !           372:        if (nam == NULL)
        !           373:                return (EADDRNOTAVAIL);
        !           374:        if (lcp -> lcd_ceaddr)                          /* XXX */
        !           375:                return (EADDRINUSE);
        !           376:        if (pk_checksockaddr (nam))
        !           377:                return (EINVAL);
        !           378:        sa = mtod (nam, struct sockaddr_x25 *);
        !           379: 
        !           380:        /*
        !           381:         * If the user wishes to accept calls only from a particular
        !           382:         * net (net != 0), make sure the net is known
        !           383:         */
        !           384: 
        !           385:        if (sa -> x25_addr[0]) {
        !           386:                if (!pk_ifwithaddr (sa))
        !           387:                        return (ENETUNREACH);
        !           388:        } else if (sa -> x25_net) {
        !           389:                if (!ifa_ifwithnet ((struct sockaddr *)sa))
        !           390:                        return (ENETUNREACH);
        !           391:        }
        !           392: 
        !           393:        /*
        !           394:         * For ISO's sake permit default listeners, but only one such . . .
        !           395:         */
        !           396:        for (pp = pk_listenhead; pp; pp = pp -> lcd_listen) {
        !           397:                register struct sockaddr_x25 *sa2 = pp -> lcd_ceaddr;
        !           398:                if ((sa2 -> x25_udlen == sa -> x25_udlen) &&
        !           399:                    (sa2 -> x25_udlen == 0 ||
        !           400:                     (bcmp (sa2 -> x25_udata, sa -> x25_udata,
        !           401:                            min (sa2 -> x25_udlen, sa -> x25_udlen)) == 0)))
        !           402:                                return (EADDRINUSE);
        !           403:        }
        !           404:        lcp -> lcd_laddr = *sa;
        !           405:        lcp -> lcd_ceaddr = &lcp -> lcd_laddr;
        !           406:        return (0);
        !           407: }
        !           408: 
        !           409: /*
        !           410:  * Include a bound control block in the list of listeners.
        !           411:  */
        !           412: pk_listen (lcp)
        !           413: register struct pklcd *lcp;
        !           414: {
        !           415:        register struct pklcd **pp;
        !           416: 
        !           417:        if (lcp -> lcd_ceaddr == 0)
        !           418:                return (EDESTADDRREQ);
        !           419: 
        !           420:        lcp -> lcd_state = LISTEN;
        !           421:        /*
        !           422:         * Add default listener at end, any others at start.
        !           423:         */
        !           424:        if (lcp -> lcd_ceaddr -> x25_udlen == 0) {
        !           425:                for (pp = &pk_listenhead; *pp; )
        !           426:                        pp = &((*pp) -> lcd_listen);
        !           427:                *pp = lcp;
        !           428:        } else {
        !           429:                lcp -> lcd_listen = pk_listenhead;
        !           430:                pk_listenhead = lcp;
        !           431:        }
        !           432:        return (0);
        !           433: }
        !           434: /*
        !           435:  * Include a listening control block for the benefit of other protocols.
        !           436:  */
        !           437: pk_protolisten (spi, spilen, callee)
        !           438: int (*callee) ();
        !           439: {
        !           440:        register struct pklcd *lcp = pk_attach ((struct socket *)0);
        !           441:        register struct mbuf *nam;
        !           442:        register struct sockaddr_x25 *sa;
        !           443:        int error = ENOBUFS;
        !           444: 
        !           445:        if (lcp) {
        !           446:                if (nam = m_getclr (MT_SONAME, M_DONTWAIT)) {
        !           447:                        sa = mtod (nam, struct sockaddr_x25 *);
        !           448:                        sa -> x25_family = AF_CCITT;
        !           449:                        sa -> x25_len = nam -> m_len = sizeof (*sa);
        !           450:                        sa -> x25_udlen = spilen;
        !           451:                        sa -> x25_udata[0] = spi;
        !           452:                        lcp -> lcd_upper = callee;
        !           453:                        lcp -> lcd_flags = X25_MBS_HOLD;
        !           454:                        if ((error = pk_bind (lcp, nam)) == 0)
        !           455:                                error = pk_listen (lcp);
        !           456:                        (void) m_free (nam);
        !           457:                }
        !           458:                if (error)
        !           459:                        pk_freelcd (lcp);
        !           460:        }
        !           461:        return error; /* Hopefully Zero !*/
        !           462: }
        !           463: 
        !           464: /*
        !           465:  * Associate a logical channel descriptor with a network.
        !           466:  * Fill in the default network specific parameters and then
        !           467:  * set any parameters explicitly specified by the user or
        !           468:  * by the remote DTE.
        !           469:  */
        !           470: 
        !           471: pk_assoc (pkp, lcp, sa)
        !           472: register struct pkcb *pkp;
        !           473: register struct pklcd *lcp;
        !           474: register struct sockaddr_x25 *sa;
        !           475: {
        !           476: 
        !           477:        lcp -> lcd_pkp = pkp;
        !           478:        lcp -> lcd_packetsize = pkp -> pk_xcp -> xc_psize;
        !           479:        lcp -> lcd_windowsize = pkp -> pk_xcp -> xc_pwsize;
        !           480:        lcp -> lcd_rsn = MODULUS - 1;
        !           481:        pkp -> pk_chan[lcp -> lcd_lcn] = lcp;
        !           482: 
        !           483:        if (sa -> x25_opts.op_psize)
        !           484:                lcp -> lcd_packetsize = sa -> x25_opts.op_psize;
        !           485:        else
        !           486:                sa -> x25_opts.op_psize = lcp -> lcd_packetsize;
        !           487:        if (sa -> x25_opts.op_wsize)
        !           488:                lcp -> lcd_windowsize = sa -> x25_opts.op_wsize;
        !           489:        else
        !           490:                sa -> x25_opts.op_wsize = lcp -> lcd_windowsize;
        !           491:        sa -> x25_net = pkp -> pk_xcp -> xc_addr.x25_net;
        !           492:        lcp -> lcd_flags |= sa -> x25_opts.op_flags;
        !           493:        lcp -> lcd_stime = time.tv_sec;
        !           494: }
        !           495: 
        !           496: pk_connect (lcp, sa)
        !           497: register struct pklcd *lcp;
        !           498: register struct sockaddr_x25 *sa;
        !           499: {
        !           500:        register struct pkcb *pkp;
        !           501:        register struct rtentry *rt;
        !           502:        register struct rtentry *nrt;
        !           503: 
        !           504:        struct rtentry *npaidb_enter ();
        !           505:        struct pkcb *pk_newlink ();
        !           506: 
        !           507:        if (sa -> x25_addr[0] == '\0')
        !           508:                return (EDESTADDRREQ);
        !           509: 
        !           510:        /*
        !           511:         * Is the destination address known?
        !           512:         */
        !           513:        if (!(rt = rtalloc1 ((struct sockaddr *)sa, 1)))
        !           514:                return (ENETUNREACH);
        !           515: 
        !           516:        if (!(pkp = XTRACTPKP(rt)))
        !           517:                pkp = pk_newlink ((struct x25_ifaddr *) (rt -> rt_ifa), 
        !           518:                                 (caddr_t) 0);
        !           519: 
        !           520:        /*
        !           521:         * Have we entered the LLC address?
        !           522:         */
        !           523:        if (nrt = npaidb_enter (rt -> rt_gateway, rt_key (rt), rt, 0))
        !           524:                pkp -> pk_llrt = nrt;
        !           525: 
        !           526:        /*
        !           527:         * Have we allocated an LLC2 link yet?
        !           528:         */
        !           529:        if (pkp -> pk_llnext == (caddr_t)0 && pkp -> pk_llctlinput) {
        !           530:                struct dll_ctlinfo ctlinfo;
        !           531: 
        !           532:                ctlinfo.dlcti_rt = rt;
        !           533:                ctlinfo.dlcti_pcb = (caddr_t) pkp;
        !           534:                ctlinfo.dlcti_conf = 
        !           535:                        (struct dllconfig *) (&((struct x25_ifaddr *)(rt -> rt_ifa)) -> ia_xc);
        !           536:                pkp -> pk_llnext = 
        !           537:                        (pkp -> pk_llctlinput) (PRC_CONNECT_REQUEST, 0, &ctlinfo);
        !           538:        }
        !           539: 
        !           540:        if (pkp -> pk_state != DTE_READY && pkp -> pk_state != DTE_WAITING)
        !           541:                        return (ENETDOWN);
        !           542:        if ((lcp -> lcd_lcn = pk_getlcn (pkp)) == 0)
        !           543:                return (EMFILE);
        !           544: 
        !           545:        lcp -> lcd_faddr = *sa;
        !           546:        lcp -> lcd_ceaddr = & lcp -> lcd_faddr;
        !           547:        pk_assoc (pkp, lcp, lcp -> lcd_ceaddr);
        !           548: 
        !           549:        /*
        !           550:         * If the link is not up yet, initiate an X.25 RESTART
        !           551:         */
        !           552:        if (pkp -> pk_state == DTE_WAITING) {
        !           553:                pkp -> pk_dxerole |= DTE_CONNECTPENDING;
        !           554:                pk_ctlinput (PRC_LINKUP, (struct sockaddr *)0, pkp);
        !           555:                if (lcp -> lcd_so)
        !           556:                        soisconnecting (lcp -> lcd_so);
        !           557:                return 0;
        !           558:        }
        !           559: 
        !           560:        if (lcp -> lcd_so)
        !           561:                soisconnecting (lcp -> lcd_so);
        !           562:        lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL);
        !           563:        pk_callrequest (lcp, lcp -> lcd_ceaddr, pkp -> pk_xcp);
        !           564:        return (*pkp -> pk_ia -> ia_start) (lcp);
        !           565: }
        !           566: 
        !           567: /*
        !           568:  * Complete all pending X.25 call requests --- this gets called after
        !           569:  * the X.25 link has been restarted.
        !           570:  */
        !           571: #define RESHUFFLELCN(maxlcn, lcn) ((maxlcn) - (lcn) + 1)
        !           572: 
        !           573: pk_callcomplete (pkp)
        !           574:        register struct pkcb *pkp;
        !           575: {
        !           576:        register struct pklcd *lcp;
        !           577:        register int i;
        !           578:        register int ni;
        !           579:        
        !           580: 
        !           581:        if (pkp -> pk_dxerole & DTE_CONNECTPENDING) 
        !           582:                pkp -> pk_dxerole &= ~DTE_CONNECTPENDING;
        !           583:        else return;
        !           584: 
        !           585:        if (pkp -> pk_chan == 0)
        !           586:                return;
        !           587:        
        !           588:        /*
        !           589:         * We pretended to be a DTE for allocating lcns, if
        !           590:         * it turns out that we are in reality performing as a
        !           591:         * DCE we need to reshuffle the lcps.
        !           592:         *                                                    
        !           593:          *             /+---------------+--------     -              
        !           594:         *            / | a  (maxlcn-1) |              \      
        !           595:         *           /  +---------------+               \     
        !           596:         *     +--- *   | b  (maxlcn-2) |                \    
        !           597:         *     |     \  +---------------+                 \   
        !           598:         *   r |      \ | c  (maxlcn-3) |                  \  
        !           599:         *   e |       \+---------------+                   | 
        !           600:         *   s |        |        .                          |  
        !           601:         *   h |        |        .                          | m
        !           602:         *   u |        |        .                          | a
        !           603:         *   f |        |        .                          | x
        !           604:         *   f |        |        .                          | l
        !           605:         *   l |       /+---------------+                   | c
        !           606:         *   e |      / | c' (   3    ) |                   | n
        !           607:         *     |     /  +---------------+                   | 
        !           608:         *     +--> *   | b' (   2    ) |                  /
        !           609:         *           \  +---------------+                 / 
        !           610:         *            \ | a' (   1    ) |                /  
        !           611:         *             \+---------------+               /   
        !           612:          *              | 0             |              /    
        !           613:         *              +---------------+--------     -     
        !           614:         *          
        !           615:         */         
        !           616:        if (pkp -> pk_dxerole & DTE_PLAYDCE) {
        !           617:                /* Sigh, reshuffle it */
        !           618:                for (i = pkp -> pk_maxlcn; i > 0; --i)
        !           619:                        if (pkp -> pk_chan[i]) {
        !           620:                                ni = RESHUFFLELCN(pkp -> pk_maxlcn, i);
        !           621:                                pkp -> pk_chan[ni] = pkp -> pk_chan[i];
        !           622:                                pkp -> pk_chan[i] = NULL;
        !           623:                                pkp -> pk_chan[ni] -> lcd_lcn = ni;
        !           624:                        }
        !           625:        }
        !           626: 
        !           627:        for (i = 1; i <= pkp -> pk_maxlcn; ++i)
        !           628:                if ((lcp = pkp -> pk_chan[i]) != NULL) {
        !           629:                        /* if (lcp -> lcd_so)
        !           630:                                soisconnecting (lcp -> lcd_so); */
        !           631:                        lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL);
        !           632:                        pk_callrequest (lcp, lcp -> lcd_ceaddr, pkp -> pk_xcp);
        !           633:                        (*pkp -> pk_ia -> ia_start) (lcp);
        !           634:                }
        !           635: }
        !           636: 
        !           637: struct bcdinfo {
        !           638:        octet *cp;
        !           639:        unsigned posn;
        !           640: };
        !           641: /* 
        !           642:  *  Build the rest of the CALL REQUEST packet. Fill in calling
        !           643:  *  address, facilities fields and the user data field.
        !           644:  */
        !           645: 
        !           646: pk_callrequest (lcp, sa, xcp)
        !           647: struct pklcd *lcp;
        !           648: register struct sockaddr_x25 *sa;
        !           649: register struct x25config *xcp;
        !           650: {
        !           651:        register struct x25_calladdr *a;
        !           652:        register struct mbuf *m = lcp -> lcd_template;
        !           653:        register struct x25_packet *xp = mtod (m, struct x25_packet *);
        !           654:        struct bcdinfo b;
        !           655: 
        !           656:        if (lcp -> lcd_flags & X25_DBIT)
        !           657:                X25SBITS(xp -> bits, d_bit, 1);
        !           658:        a = (struct x25_calladdr *) &xp -> packet_data;
        !           659:        b.cp = (octet *) a -> address_field;
        !           660:        b.posn = 0;
        !           661:        X25SBITS(a -> addrlens, called_addrlen, to_bcd (&b, sa, xcp));
        !           662:        X25SBITS(a -> addrlens, calling_addrlen, to_bcd (&b, &xcp -> xc_addr, xcp));
        !           663:        if (b.posn & 0x01)
        !           664:                *b.cp++ &= 0xf0;
        !           665:        m -> m_pkthdr.len = m -> m_len += b.cp - (octet *) a;
        !           666: 
        !           667:        if (lcp -> lcd_facilities) {
        !           668:                m -> m_pkthdr.len += 
        !           669:                        (m -> m_next = lcp -> lcd_facilities) -> m_pkthdr.len;
        !           670:                lcp -> lcd_facilities = 0;
        !           671:        } else
        !           672:                pk_build_facilities (m, sa, (int)xcp -> xc_type);
        !           673: 
        !           674:        m_copyback (m, m -> m_pkthdr.len, sa -> x25_udlen, sa -> x25_udata);
        !           675: }
        !           676: 
        !           677: pk_build_facilities (m, sa, type)
        !           678: register struct mbuf *m;
        !           679: struct sockaddr_x25 *sa;
        !           680: {
        !           681:        register octet *cp;
        !           682:        register octet *fcp;
        !           683:        register int revcharge;
        !           684: 
        !           685:        cp = mtod (m, octet *) + m -> m_len;
        !           686:        fcp = cp + 1;
        !           687:        revcharge = sa -> x25_opts.op_flags & X25_REVERSE_CHARGE ? 1 : 0;
        !           688:        /*
        !           689:         * This is specific to Datapac X.25(1976) DTEs.  International
        !           690:         * calls must have the "hi priority" bit on.
        !           691:         */
        !           692:        if (type == X25_1976 && sa -> x25_opts.op_psize == X25_PS128)
        !           693:                revcharge |= 02;
        !           694:        if (revcharge) {
        !           695:                *fcp++ = FACILITIES_REVERSE_CHARGE;
        !           696:                *fcp++ = revcharge;
        !           697:        }
        !           698:        switch (type) {
        !           699:        case X25_1980:
        !           700:        case X25_1984:
        !           701:                *fcp++ = FACILITIES_PACKETSIZE;
        !           702:                *fcp++ = sa -> x25_opts.op_psize;
        !           703:                *fcp++ = sa -> x25_opts.op_psize;
        !           704: 
        !           705:                *fcp++ = FACILITIES_WINDOWSIZE;
        !           706:                *fcp++ = sa -> x25_opts.op_wsize;
        !           707:                *fcp++ = sa -> x25_opts.op_wsize;
        !           708:        }
        !           709:        *cp = fcp - cp - 1;
        !           710:        m -> m_pkthdr.len = (m -> m_len += *cp + 1);
        !           711: }
        !           712: 
        !           713: to_bcd (b, sa, xcp)
        !           714: register struct bcdinfo *b;
        !           715: struct sockaddr_x25 *sa;
        !           716: register struct x25config *xcp;
        !           717: {
        !           718:        register char *x = sa -> x25_addr;
        !           719:        unsigned start = b -> posn;
        !           720:        /*
        !           721:         * The nodnic and prepnd0 stuff looks tedious,
        !           722:         * but it does allow full X.121 addresses to be used,
        !           723:         * which is handy for routing info (& OSI type 37 addresses).
        !           724:         */
        !           725:        if (xcp -> xc_addr.x25_net && (xcp -> xc_nodnic || xcp -> xc_prepnd0)) {
        !           726:                char dnicname[sizeof (long) * NBBY/3 + 2];
        !           727:                register char *p = dnicname;
        !           728: 
        !           729:                sprintf (p, "%d", xcp -> xc_addr.x25_net & 0x7fff);
        !           730:                for (; *p; p++) /* *p == 0 means dnic matched */
        !           731:                        if ((*p ^ *x++) & 0x0f)
        !           732:                                break;
        !           733:                if (*p || xcp -> xc_nodnic == 0)
        !           734:                        x = sa -> x25_addr;
        !           735:                if (*p && xcp -> xc_prepnd0) {
        !           736:                        if ((b -> posn)++ & 0x01)
        !           737:                                *(b -> cp)++;
        !           738:                        else
        !           739:                                *(b -> cp) = 0;
        !           740:                }
        !           741:        }
        !           742:        while (*x)
        !           743:                if ((b -> posn)++ & 0x01)
        !           744:                        *(b -> cp)++ |= *x++ & 0x0F;
        !           745:                else
        !           746:                        *(b -> cp) = *x++ << 4;
        !           747:        return ((b -> posn) - start);
        !           748: }
        !           749: 
        !           750: /* 
        !           751:  *  This routine gets the  first available logical channel number.  The
        !           752:  *  search is 
        !           753:  *             - from the highest number to lowest number if playing DTE, and
        !           754:  *             - from lowest to highest number if playing DCE.
        !           755:  */
        !           756: 
        !           757: pk_getlcn (pkp)
        !           758: register struct pkcb *pkp;
        !           759: {
        !           760:        register int i;
        !           761: 
        !           762:        if (pkp -> pk_chan == 0)
        !           763:                return (0);
        !           764:        if ( pkp -> pk_dxerole & DTE_PLAYDCE ) {
        !           765:                for (i = 1; i <= pkp -> pk_maxlcn; ++i)
        !           766:                        if (pkp -> pk_chan[i] == NULL)
        !           767:                                break;
        !           768:        } else { 
        !           769:                for (i = pkp -> pk_maxlcn; i > 0; --i)
        !           770:                        if (pkp -> pk_chan[i] == NULL)
        !           771:                                break;
        !           772:        }
        !           773:        i = ( i > pkp -> pk_maxlcn ? 0 : i );
        !           774:        return (i);
        !           775: }
        !           776: 
        !           777: /* 
        !           778:  *  This procedure sends a CLEAR request packet. The lc state is
        !           779:  *  set to "SENT_CLEAR". 
        !           780:  */
        !           781: 
        !           782: pk_clear (lcp, diagnostic, abortive)
        !           783: register struct pklcd *lcp;
        !           784: {
        !           785:        register struct mbuf *m = pk_template (lcp -> lcd_lcn, X25_CLEAR);
        !           786: 
        !           787:        m -> m_len += 2;
        !           788:        m -> m_pkthdr.len += 2;
        !           789:        mtod (m, struct x25_packet *) -> packet_data = 0;
        !           790:        mtod (m, octet *)[4] = diagnostic;
        !           791:        if (lcp -> lcd_facilities) {
        !           792:                m -> m_next = lcp -> lcd_facilities;
        !           793:                m -> m_pkthdr.len += m -> m_next -> m_len;
        !           794:                lcp -> lcd_facilities = 0;
        !           795:        }
        !           796:        if (abortive)
        !           797:                lcp -> lcd_template = m;
        !           798:        else {
        !           799:                struct socket *so = lcp -> lcd_so;
        !           800:                struct sockbuf *sb = so ? & so -> so_snd : & lcp -> lcd_sb;
        !           801:                sbappendrecord (sb, m);
        !           802:        }
        !           803:        pk_output (lcp);
        !           804: 
        !           805: }
        !           806: 
        !           807: /*
        !           808:  * This procedure generates RNR's or RR's to inhibit or enable
        !           809:  * inward data flow, if the current state changes (blocked ==> open or
        !           810:  * vice versa), or if forced to generate one.  One forces RNR's to ack data.  
        !           811:  */
        !           812: pk_flowcontrol (lcp, inhibit, forced)
        !           813: register struct pklcd *lcp;
        !           814: {
        !           815:        inhibit = (inhibit != 0);
        !           816:        if (lcp == 0 || lcp -> lcd_state != DATA_TRANSFER ||
        !           817:            (forced == 0 && lcp -> lcd_rxrnr_condition == inhibit))
        !           818:                return;
        !           819:        lcp -> lcd_rxrnr_condition = inhibit;
        !           820:        lcp -> lcd_template =
        !           821:                pk_template (lcp -> lcd_lcn, inhibit ? X25_RNR : X25_RR);
        !           822:        pk_output (lcp);
        !           823: }
        !           824: 
        !           825: /* 
        !           826:  *  This procedure sends a RESET request packet. It re-intializes
        !           827:  *  virtual circuit.
        !           828:  */
        !           829: 
        !           830: static
        !           831: pk_reset (lcp, diagnostic)
        !           832: register struct pklcd *lcp;
        !           833: {
        !           834:        register struct mbuf *m;
        !           835:        register struct socket *so = lcp -> lcd_so;
        !           836: 
        !           837:        if (lcp -> lcd_state != DATA_TRANSFER)
        !           838:                return;
        !           839: 
        !           840:        if (so)
        !           841:                so -> so_error = ECONNRESET;
        !           842:        lcp -> lcd_reset_condition = TRUE;
        !           843: 
        !           844:        /* Reset all the control variables for the channel. */
        !           845:        pk_flush (lcp);
        !           846:        lcp -> lcd_window_condition = lcp -> lcd_rnr_condition =
        !           847:                lcp -> lcd_intrconf_pending = FALSE;
        !           848:        lcp -> lcd_rsn = MODULUS - 1;
        !           849:        lcp -> lcd_ssn = 0;
        !           850:        lcp -> lcd_output_window = lcp -> lcd_input_window =
        !           851:                lcp -> lcd_last_transmitted_pr = 0;
        !           852:        m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET);
        !           853:        m -> m_pkthdr.len = m -> m_len += 2;
        !           854:        mtod (m, struct x25_packet *) -> packet_data = 0;
        !           855:        mtod (m, octet *)[4] = diagnostic;
        !           856:        pk_output (lcp);
        !           857: 
        !           858: }
        !           859: 
        !           860: /*
        !           861:  * This procedure frees all data queued for output or delivery on a
        !           862:  *  virtual circuit.
        !           863:  */
        !           864: 
        !           865: pk_flush (lcp)
        !           866: register struct pklcd *lcp;
        !           867: {
        !           868:        register struct socket *so;
        !           869: 
        !           870:        if (lcp -> lcd_template)
        !           871:                m_freem (lcp -> lcd_template);
        !           872: 
        !           873:        if (lcp -> lcd_cps) {
        !           874:                m_freem (lcp -> lcd_cps);
        !           875:                lcp -> lcd_cps = 0;
        !           876:        }
        !           877:        if (lcp -> lcd_facilities) {
        !           878:                m_freem (lcp -> lcd_facilities);
        !           879:                lcp -> lcd_facilities = 0;
        !           880:        }
        !           881:        if (so = lcp -> lcd_so) 
        !           882:                sbflush (&so -> so_snd);
        !           883:        else 
        !           884:                sbflush (&lcp -> lcd_sb);
        !           885: }
        !           886: 
        !           887: /* 
        !           888:  *  This procedure handles all local protocol procedure errors.
        !           889:  */
        !           890: 
        !           891: pk_procerror (error, lcp, errstr, diagnostic)
        !           892: register struct pklcd *lcp;
        !           893: char *errstr;
        !           894: {
        !           895: 
        !           896:        pk_message (lcp -> lcd_lcn, lcp -> lcd_pkp -> pk_xcp, errstr);
        !           897: 
        !           898:        switch (error) {
        !           899:        case CLEAR: 
        !           900:                if (lcp -> lcd_so) {
        !           901:                        lcp -> lcd_so -> so_error = ECONNABORTED;
        !           902:                        soisdisconnecting (lcp -> lcd_so);
        !           903:                }
        !           904:                pk_clear (lcp, diagnostic, 1);
        !           905:                break;
        !           906: 
        !           907:        case RESET: 
        !           908:                pk_reset (lcp, diagnostic);
        !           909:        }
        !           910: }
        !           911: 
        !           912: /* 
        !           913:  *  This procedure is called during the DATA TRANSFER state to check 
        !           914:  *  and  process  the P(R) values  received  in the DATA,  RR OR RNR
        !           915:  *  packets.
        !           916:  */
        !           917: 
        !           918: pk_ack (lcp, pr)
        !           919: struct pklcd *lcp;
        !           920: unsigned pr;
        !           921: {
        !           922:        register struct socket *so = lcp -> lcd_so;
        !           923: 
        !           924:        if (lcp -> lcd_output_window == pr)
        !           925:                return (PACKET_OK);
        !           926:        if (lcp -> lcd_output_window < lcp -> lcd_ssn) {
        !           927:                if (pr < lcp -> lcd_output_window || pr > lcp -> lcd_ssn) {
        !           928:                        pk_procerror (RESET, lcp,
        !           929:                                "p(r) flow control error", 2);
        !           930:                        return (ERROR_PACKET);
        !           931:                }
        !           932:        }
        !           933:        else {
        !           934:                if (pr < lcp -> lcd_output_window && pr > lcp -> lcd_ssn) {
        !           935:                        pk_procerror (RESET, lcp,
        !           936:                                "p(r) flow control error #2", 2);
        !           937:                        return (ERROR_PACKET);
        !           938:                }
        !           939:        }
        !           940: 
        !           941:        lcp -> lcd_output_window = pr;          /* Rotate window. */
        !           942:        if (lcp -> lcd_window_condition == TRUE)
        !           943:                lcp -> lcd_window_condition = FALSE;
        !           944: 
        !           945:        if (so && ((so -> so_snd.sb_flags & SB_WAIT) || 
        !           946:                   (so -> so_snd.sb_flags & SB_NOTIFY)))
        !           947:                sowwakeup (so);
        !           948: 
        !           949:        return (PACKET_OK);
        !           950: }
        !           951: 
        !           952: /* 
        !           953:  *  This procedure decodes the X.25 level 3 packet returning a 
        !           954:  *  code to be used in switchs or arrays.
        !           955:  */
        !           956: 
        !           957: pk_decode (xp)
        !           958: register struct x25_packet *xp;
        !           959: {
        !           960:        register int type;
        !           961: 
        !           962:        if (X25GBITS(xp -> bits, fmt_identifier) != 1)
        !           963:                return (INVALID_PACKET);
        !           964: #ifdef ancient_history
        !           965:        /* 
        !           966:         *  Make sure that the logical channel group number is 0.
        !           967:         *  This restriction may be removed at some later date.
        !           968:         */
        !           969:        if (xp -> lc_group_number != 0)
        !           970:                return (INVALID_PACKET);
        !           971: #endif
        !           972:        /* 
        !           973:         *  Test for data packet first.
        !           974:         */
        !           975:        if (!(xp -> packet_type & DATA_PACKET_DESIGNATOR))
        !           976:                return (DATA);
        !           977: 
        !           978:        /* 
        !           979:         *  Test if flow control packet (RR or RNR).
        !           980:         */
        !           981:        if (!(xp -> packet_type & RR_OR_RNR_PACKET_DESIGNATOR))
        !           982:                switch (xp -> packet_type & 0x1f) {
        !           983:                case X25_RR:
        !           984:                        return (RR);
        !           985:                case X25_RNR:
        !           986:                        return (RNR);
        !           987:                case X25_REJECT:
        !           988:                        return (REJECT);
        !           989:                }
        !           990: 
        !           991:        /* 
        !           992:         *  Determine the rest of the packet types.
        !           993:         */
        !           994:        switch (xp -> packet_type) {
        !           995:        case X25_CALL: 
        !           996:                type = CALL;
        !           997:                break;
        !           998: 
        !           999:        case X25_CALL_ACCEPTED: 
        !          1000:                type = CALL_ACCEPTED;
        !          1001:                break;
        !          1002: 
        !          1003:        case X25_CLEAR: 
        !          1004:                type = CLEAR;
        !          1005:                break;
        !          1006: 
        !          1007:        case X25_CLEAR_CONFIRM: 
        !          1008:                type = CLEAR_CONF;
        !          1009:                break;
        !          1010: 
        !          1011:        case X25_INTERRUPT: 
        !          1012:                type = INTERRUPT;
        !          1013:                break;
        !          1014: 
        !          1015:        case X25_INTERRUPT_CONFIRM: 
        !          1016:                type = INTERRUPT_CONF;
        !          1017:                break;
        !          1018: 
        !          1019:        case X25_RESET: 
        !          1020:                type = RESET;
        !          1021:                break;
        !          1022: 
        !          1023:        case X25_RESET_CONFIRM: 
        !          1024:                type = RESET_CONF;
        !          1025:                break;
        !          1026: 
        !          1027:        case X25_RESTART: 
        !          1028:                type = RESTART;
        !          1029:                break;
        !          1030: 
        !          1031:        case X25_RESTART_CONFIRM: 
        !          1032:                type = RESTART_CONF;
        !          1033:                break;
        !          1034: 
        !          1035:        case X25_DIAGNOSTIC:
        !          1036:                type = DIAG_TYPE;
        !          1037:                break;
        !          1038: 
        !          1039:        default: 
        !          1040:                type = INVALID_PACKET;
        !          1041:        }
        !          1042:        return (type);
        !          1043: }
        !          1044: 
        !          1045: /* 
        !          1046:  *  A restart packet has been received. Print out the reason
        !          1047:  *  for the restart.
        !          1048:  */
        !          1049: 
        !          1050: pk_restartcause (pkp, xp)
        !          1051: struct pkcb *pkp;
        !          1052: register struct x25_packet *xp;
        !          1053: {
        !          1054:        register struct x25config *xcp = pkp -> pk_xcp;
        !          1055:        register int lcn = LCN(xp);
        !          1056: 
        !          1057:        switch (xp -> packet_data) {
        !          1058:        case X25_RESTART_LOCAL_PROCEDURE_ERROR: 
        !          1059:                pk_message (lcn, xcp, "restart: local procedure error");
        !          1060:                break;
        !          1061: 
        !          1062:        case X25_RESTART_NETWORK_CONGESTION: 
        !          1063:                pk_message (lcn, xcp, "restart: network congestion");
        !          1064:                break;
        !          1065: 
        !          1066:        case X25_RESTART_NETWORK_OPERATIONAL: 
        !          1067:                pk_message (lcn, xcp, "restart: network operational");
        !          1068:                break;
        !          1069: 
        !          1070:        default: 
        !          1071:                pk_message (lcn, xcp, "restart: unknown cause");
        !          1072:        }
        !          1073: }
        !          1074: 
        !          1075: #define MAXRESETCAUSE  7
        !          1076: 
        !          1077: int     Reset_cause[] = {
        !          1078:        EXRESET, EXROUT, 0, EXRRPE, 0, EXRLPE, 0, EXRNCG
        !          1079: };
        !          1080: 
        !          1081: /* 
        !          1082:  *  A reset packet has arrived. Return the cause to the user.
        !          1083:  */
        !          1084: 
        !          1085: pk_resetcause (pkp, xp)
        !          1086: struct pkcb *pkp;
        !          1087: register struct x25_packet *xp;
        !          1088: {
        !          1089:        register struct pklcd *lcp =
        !          1090:                                pkp -> pk_chan[LCN(xp)];
        !          1091:        register int code = xp -> packet_data;
        !          1092: 
        !          1093:        if (code > MAXRESETCAUSE)
        !          1094:                code = 7;       /* EXRNCG */
        !          1095: 
        !          1096:        pk_message (LCN(xp), lcp -> lcd_pkp, "reset code 0x%x, diagnostic 0x%x",
        !          1097:                        xp -> packet_data, 4[(u_char *)xp]);
        !          1098:                        
        !          1099:        if (lcp -> lcd_so)
        !          1100:                lcp -> lcd_so -> so_error = Reset_cause[code];
        !          1101: }
        !          1102: 
        !          1103: #define MAXCLEARCAUSE  25
        !          1104: 
        !          1105: int     Clear_cause[] = {
        !          1106:        EXCLEAR, EXCBUSY, 0, EXCINV, 0, EXCNCG, 0,
        !          1107:        0, 0, EXCOUT, 0, EXCAB, 0, EXCNOB, 0, 0, 0, EXCRPE,
        !          1108:        0, EXCLPE, 0, 0, 0, 0, 0, EXCRRC
        !          1109: };
        !          1110: 
        !          1111: /* 
        !          1112:  *  A clear packet has arrived. Return the cause to the user.
        !          1113:  */
        !          1114: 
        !          1115: pk_clearcause (pkp, xp)
        !          1116: struct pkcb *pkp;
        !          1117: register struct x25_packet *xp;
        !          1118: {
        !          1119:        register struct pklcd *lcp =
        !          1120:                pkp -> pk_chan[LCN(xp)];
        !          1121:        register int code = xp -> packet_data;
        !          1122: 
        !          1123:        if (code > MAXCLEARCAUSE)
        !          1124:                code = 5;       /* EXRNCG */
        !          1125:        if (lcp -> lcd_so)
        !          1126:                lcp -> lcd_so -> so_error = Clear_cause[code];
        !          1127: }
        !          1128: 
        !          1129: char *
        !          1130: format_ntn (xcp)
        !          1131: register struct x25config *xcp;
        !          1132: {
        !          1133: 
        !          1134:        return (xcp -> xc_addr.x25_addr);
        !          1135: }
        !          1136: 
        !          1137: /* VARARGS1 */
        !          1138: pk_message (lcn, xcp, fmt, a1, a2, a3, a4, a5, a6)
        !          1139: struct x25config *xcp;
        !          1140: char *fmt;
        !          1141: {
        !          1142: 
        !          1143:        if (lcn)
        !          1144:                if (!PQEMPTY)
        !          1145:                        printf ("X.25(%s): lcn %d: ", format_ntn (xcp), lcn);
        !          1146:                else
        !          1147:                        printf ("X.25: lcn %d: ", lcn);
        !          1148:        else
        !          1149:                if (!PQEMPTY)
        !          1150:                        printf ("X.25(%s): ", format_ntn (xcp));
        !          1151:                else
        !          1152:                        printf ("X.25: ");
        !          1153: 
        !          1154:        printf (fmt, a1, a2, a3, a4, a5, a6);
        !          1155:        printf ("\n");
        !          1156: }
        !          1157: 
        !          1158: pk_fragment (lcp, m0, qbit, mbit, wait)
        !          1159: struct mbuf *m0;
        !          1160: register struct pklcd *lcp;
        !          1161: {
        !          1162:        register struct mbuf *m = m0;
        !          1163:        register struct x25_packet *xp;
        !          1164:        register struct sockbuf *sb;
        !          1165:        struct mbuf *head = 0, *next, **mp = &head, *m_split ();
        !          1166:        int totlen, psize = 1 << (lcp -> lcd_packetsize);
        !          1167: 
        !          1168:        if (m == 0)
        !          1169:                return 0;
        !          1170:        if (m -> m_flags & M_PKTHDR == 0)
        !          1171:                panic ("pk_fragment");
        !          1172:        totlen = m -> m_pkthdr.len;
        !          1173:        m -> m_act = 0;
        !          1174:        sb = lcp -> lcd_so ? &lcp -> lcd_so -> so_snd : & lcp -> lcd_sb;
        !          1175:        do {
        !          1176:                if (totlen > psize) {
        !          1177:                        if ((next = m_split (m, psize, wait)) == 0)
        !          1178:                                goto abort;
        !          1179:                        totlen -= psize;
        !          1180:                } else
        !          1181:                        next = 0;
        !          1182:                M_PREPEND(m, PKHEADERLN, wait);
        !          1183:                if (m == 0)
        !          1184:                        goto abort;
        !          1185:                *mp = m;
        !          1186:                mp = & m -> m_act;
        !          1187:                *mp = 0;
        !          1188:                xp = mtod (m, struct x25_packet *);
        !          1189:                0[(char *)xp] = 0;
        !          1190:                if (qbit)
        !          1191:                        X25SBITS(xp -> bits, q_bit, 1);
        !          1192:                if (lcp -> lcd_flags & X25_DBIT)
        !          1193:                        X25SBITS(xp -> bits, d_bit, 1);
        !          1194:                X25SBITS(xp -> bits, fmt_identifier, 1);
        !          1195:                xp -> packet_type = X25_DATA;
        !          1196:                SET_LCN(xp, lcp -> lcd_lcn);
        !          1197:                if (next || (mbit && (totlen == psize ||
        !          1198:                                      (lcp -> lcd_flags & X25_DBIT))))
        !          1199:                        SMBIT(xp, 1);
        !          1200:        } while (m = next);
        !          1201:        for (m = head; m; m = next) {
        !          1202:                next = m -> m_act;
        !          1203:                m -> m_act = 0;
        !          1204:                sbappendrecord (sb, m);
        !          1205:        }
        !          1206:        return 0;
        !          1207: abort:
        !          1208:        if (wait)
        !          1209:                panic ("pk_fragment null mbuf after wait");
        !          1210:        if (next)
        !          1211:                m_freem (next);
        !          1212:        for (m = head; m; m = next) {
        !          1213:                next = m -> m_act;
        !          1214:                m_freem (m);
        !          1215:        }
        !          1216:        return ENOBUFS;
        !          1217: }

unix.superglobalmegacorp.com

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