Annotation of Net2/netccitt/pk_subr.c, revision 1.1

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

unix.superglobalmegacorp.com

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