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

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

unix.superglobalmegacorp.com

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