Annotation of Net2/netccitt/pk_subr.c, revision 1.1.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.