Annotation of 43BSDReno/contrib/isode-beta/tsap/ts2sunlink.c, revision 1.1.1.1

1.1       root        1: /* ts2sunlink.c - TPM: SunLink OSI TP4 interface */
                      2: 
                      3: #ifndef        lint
                      4: static char *rcsid = "$Header: /f/osi/tsap/RCS/ts2sunlink.c,v 7.8 90/07/09 14:51:17 mrose Exp $";
                      5: #endif
                      6: 
                      7: /* 
                      8:  * $Header: /f/osi/tsap/RCS/ts2sunlink.c,v 7.8 90/07/09 14:51:17 mrose Exp $
                      9:  *
                     10:  * Contributed by John A. Scott, The MITRE Corporation
                     11:  *
                     12:  *
                     13:  * $Log:       ts2sunlink.c,v $
                     14:  * Revision 7.8  90/07/09  14:51:17  mrose
                     15:  * sync
                     16:  * 
                     17:  * Revision 7.7  90/03/23  17:31:22  mrose
                     18:  * 8
                     19:  * 
                     20:  * Revision 7.6  90/03/22  08:38:08  mrose
                     21:  * touch-up
                     22:  * 
                     23:  * Revision 7.5  90/01/27  10:27:39  mrose
                     24:  * touch-up
                     25:  * 
                     26:  * Revision 7.4  89/12/19  10:18:38  mrose
                     27:  * DLOG
                     28:  * 
                     29:  * Revision 7.3  89/12/13  07:05:45  mrose
                     30:  * touch-up
                     31:  * 
                     32:  * Revision 7.2  89/12/08  09:41:35  mrose
                     33:  * touch-up
                     34:  * 
                     35:  * Revision 7.1  89/12/07  22:15:30  mrose
                     36:  * queued writes
                     37:  * 
                     38:  * Revision 7.0  89/11/23  22:30:38  mrose
                     39:  * Release 6.0
                     40:  * 
                     41:  */
                     42: 
                     43: /*
                     44:  *                               NOTICE
                     45:  *
                     46:  *    Acquisition, use, and distribution of this module and related
                     47:  *    materials are subject to the restrictions of a license agreement.
                     48:  *    Consult the Preface in the User's Manual for the full terms of
                     49:  *    this agreement.
                     50:  *
                     51:  */
                     52: 
                     53: 
                     54: /* LINTLIBRARY */
                     55: 
                     56: #include <stdio.h>
                     57: #include "tpkt.h"
                     58: #include "mpkt.h"
                     59: 
                     60: #ifdef TP4
                     61: #include "tp4.h"
                     62: #endif
                     63: 
                     64: #ifdef SUN_TP4
                     65: #include <errno.h>
                     66: #include <sys/ioctl.h>
                     67: #include <sys/uio.h>
                     68: #include "tailor.h"
                     69: 
                     70: 
                     71: #define MAXTP4 (1 << SIZE_8K)
                     72: 
                     73: #ifndef        SUNLINK_6_0
                     74: #define        OSI_AF_GENERIC  AF_GENERIC
                     75: #endif
                     76: #ifndef        MSG_OSI_OOB
                     77: #define        MSG_OSI_OOB     MSG_OOB
                     78: #endif
                     79: 
                     80: 
                     81: /* A driver for SunLink OSI's TP4!
                     82:  *
                     83:  *     SunLink OSI TP4 user interface is very much like a ``datagram''
                     84:  *     interface.  Some of the hair in this port involves converting
                     85:  *     ISODE TP packets into SUN TP4 packets.  My gut feeling is that the
                     86:  *     port should be redone to make better use of existing ISODE
                     87:  *     structures (but this works and I hesitate to change something works).
                     88:  *                     -- John
                     89:  *
                     90:  *     Actually, I think is fairly close to optimal now.
                     91:  *                     -- /mtr
                     92:  *
                     93:  * TODO:
                     94:  *
                     95:  * 1. Figure out how to implement tsaplisten.c$tp4unique()
                     96:  *
                     97:  * 2. On failure of sendto, sendmsg, or recvfrom, try to figure out if a
                     98:  *    disconnect happened and return the right DR_ reason.
                     99:  *
                    100:  * 3. SunLink OSI should support TSELs of length greater than two.  In fact,
                    101:  *    a transport address really should be:
                    102:  *     nsap - 64 octets, tsel - 44 octets (would prefer 64, but mbufs limit)
                    103:  *
                    104:  * 4. Should do QOS mappings for error recovery (not class 0 or 2) and cost
                    105:  *    (class 0).
                    106:  *
                    107:  */
                    108: 
                    109: /*    DATA */
                    110: 
                    111: extern int  errno;
                    112: 
                    113: /*    UPPER HALF */
                    114: 
                    115: static int  TConnect (tb, expedited, data, cc, td)
                    116: register struct tsapblk *tb;
                    117: char    *data;
                    118: int    expedited,
                    119:        cc;
                    120: struct TSAPdisconnect *td;
                    121: {
                    122:     int            result;
                    123:     register struct tp4pkt *t;
                    124: 
                    125:     if ((t = newtp4pkt (TP_CONNECT_REQ)) == NULL)
                    126:        return tsaplose (td, DR_CONGEST, NULLCP, NULLCP);
                    127: 
                    128:     if (gen2tp4X (&tb -> tb_responding, &t -> tp4_called,
                    129:                  tb -> tb_initiating.ta_present
                    130:                      ? &tb -> tb_initiating.ta_addr : NULLNA) == NOTOK) {
                    131:        result = tsaplose (td, DR_ADDRESS, NULLCP,
                    132:                           "unable to parse remote address");
                    133:        goto out;
                    134:     }
                    135: 
                    136:     if (gen2tp4X (&tb -> tb_initiating, &t -> tp4_calling,
                    137:                  tb -> tb_responding.ta_present
                    138:                      ? &tb -> tb_responding.ta_addr : NULLNA) == NOTOK) {
                    139:        result = tsaplose (td, DR_ADDRESS, NULLCP,
                    140:                           "unable to parse local address");
                    141:        goto out;
                    142:     }
                    143: 
                    144:     if (expedited) {
                    145:        tb -> tb_flags |= TB_EXPD;
                    146:        t -> tp4_expedited = 1;
                    147:     }
                    148: 
                    149:     if (sendto (tb -> tb_fd, data, cc, 0, (struct sockaddr *) t,
                    150:                sizeof (TP_MSG_CONNECT)) == NOTOK)
                    151:        result = tsaplose (td, DR_CONGEST, "failed", "sendto");
                    152:     else
                    153:        result = CONNECTING_2;
                    154: 
                    155: out: ;
                    156:     freetp4pkt (t);
                    157: 
                    158:     return result;
                    159: }
                    160: 
                    161: /*  */
                    162: 
                    163: static int  TRetry (tb, async, tc, td)
                    164: register struct tsapblk *tb;
                    165: int    async;
                    166: struct TSAPconnect *tc;
                    167: struct TSAPdisconnect *td;
                    168: {
                    169:     int            cc,
                    170:            header_len,
                    171:            onoff;
                    172:     char    data[TS_SIZE];
                    173:     register struct tp4pkt *t;
                    174: 
                    175:     t = NULL;
                    176:     if (async)
                    177:        switch ((*tb -> tb_retryfnx) (tb, td)) {
                    178:            case NOTOK:
                    179:                goto out;
                    180: 
                    181:            case OK:
                    182:                return CONNECTING_2;
                    183: 
                    184:            case DONE:
                    185:                break;              
                    186:        }
                    187: 
                    188:     if ((t = newtp4pkt ((TP_EVENT) 0)) == NULL) {
                    189:        (void) tsaplose (td, DR_CONGEST, NULLCP, NULLCP);
                    190:        goto out;
                    191:     }
                    192: 
                    193:     header_len = sizeof (TP_MSG_CONNECT);
                    194:     if ((cc = recvfrom (tb -> tb_fd, data, sizeof data, 0,
                    195:                        (struct sockaddr *) t, &header_len)) == NOTOK) {
                    196:        if (errno == EWOULDBLOCK) {
                    197:            freetp4pkt (t);
                    198:            return CONNECTING_2;
                    199:        }
                    200: 
                    201:        (void) tsaplose (td, DR_CONGEST, "failed", "recvfrom");
                    202:        goto out;
                    203:     }
                    204: 
                    205:     if (async)
                    206:        (void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 0, (char *) &onoff));
                    207: 
                    208:     switch (t -> tp4_event) {
                    209:        case TP_CONNECT_CONF:
                    210:            tc -> tc_sd = tb -> tb_fd;
                    211:            tc -> tc_tsdusize = tb -> tb_tsdusize = MAXTP4;
                    212:            (void) tp42genX (&tb -> tb_responding, &t -> tp4_calling);
                    213:            copyTSAPaddrX (&tb -> tb_responding, &tc -> tc_responding);
                    214:            if ((tb -> tb_flags & TB_EXPD) && !t -> tp4_expedited)
                    215:                tb -> tb_flags &= ~TB_EXPD;
                    216:            tc -> tc_expedited = (tb -> tb_flags & TB_EXPD) ? 1 : 0;
                    217:            if ((tc -> tc_cc = cc) > 0)
                    218:                bcopy (data, tc -> tc_data, cc);
                    219: 
                    220:            freetp4pkt (t);
                    221:            tb -> tb_flags |= TB_CONN;
                    222: #ifdef  MGMT
                    223:            if (tb -> tb_manfnx)
                    224:                (*tb -> tb_manfnx) (OPREQOUT, tb);
                    225: #endif
                    226:            if (tb -> tb_calling)
                    227:                free ((char *) tb -> tb_calling), tb -> tb_calling = NULL;
                    228:            if (tb -> tb_called)
                    229:                free ((char *) tb -> tb_called), tb -> tb_called = NULL;
                    230: 
                    231:            return DONE;
                    232: 
                    233:        case TP_DISCONNECT_IND:
                    234:            if ((td -> td_reason = (int) t -> tp4_reason) == DR_UNKNOWN)
                    235:                td -> td_reason = DR_NETWORK;
                    236:            if ((td -> td_cc = cc) > 0)
                    237:                bcopy (data, td -> td_data, cc);
                    238:            break;
                    239: 
                    240:        default:
                    241:            (void) tsaplose (td, DR_NETWORK, NULLCP,
                    242:                             "expecting 0x%x, got 0x%x",
                    243:                             TP_CONNECT_CONF, t -> tp4_event);
                    244:            break;
                    245:     }
                    246: 
                    247: out: ;
                    248:     if (t)
                    249:        freetp4pkt (t);
                    250:     freetblk (tb);
                    251: 
                    252:     return NOTOK;
                    253: }
                    254: 
                    255: /*  */
                    256: 
                    257: static int  TStart (tb, cp, ts, td)
                    258: register struct tsapblk *tb;
                    259: char   *cp;
                    260: struct TSAPstart *ts;
                    261: struct TSAPdisconnect *td;
                    262: {
                    263:     int            cc,
                    264:            i,
                    265:            result;
                    266:     register struct tp4pkt *tp;
                    267: 
                    268:     if ((i = strlen (cp)) < (cc = 2 * sizeof (TP_MSG_CONNECT)))
                    269:        return tsaplose (td, DR_PARAMETER, NULLCP,
                    270:                         "bad initialization vector");
                    271: 
                    272:     if ((tp = newtp4pkt ((TP_EVENT) 0)) == NULL) {
                    273:        result = tsaplose (td, DR_CONGEST, NULLCP, NULLCP);
                    274:        goto out;
                    275:     }
                    276: 
                    277:     cc = 2 * implode ((u_char *) tp, cp, cc);
                    278:     cp += cc, i -= cc;
                    279: 
                    280:     if (tp -> tp4_expedited)
                    281:        tb -> tb_flags |= TB_EXPD;
                    282: 
                    283:     (void) tp42genX (&tb -> tb_initiating, &tp -> tp4_calling);
                    284:     (void) tp42genX (&tb -> tb_responding, &tp -> tp4_called);
                    285: 
                    286:     ts -> ts_sd = tb -> tb_fd;
                    287:     copyTSAPaddrX (&tb -> tb_initiating, &ts -> ts_calling);
                    288:     copyTSAPaddrX (&tb -> tb_responding, &ts -> ts_called);
                    289:     ts -> ts_expedited = (tb -> tb_flags & TB_EXPD) ? 1 : 0;
                    290:     ts -> ts_tsdusize = tb -> tb_tsdusize;
                    291: 
                    292:     if (i > 0) {
                    293:        if (i > 2 * TS_SIZE) {
                    294:            result = tsaplose (td, DR_CONNECT, NULLCP,
                    295:                             "too much initial user data");
                    296:            goto out;
                    297:        }
                    298: 
                    299:        ts -> ts_cc = implode ((u_char *) ts -> ts_data, cp, i);
                    300:     }
                    301:     else
                    302:        ts -> ts_cc = 0;
                    303: 
                    304:     result = OK;
                    305: 
                    306: out: ;
                    307:     if (tp)
                    308:        freetp4pkt (tp);
                    309: 
                    310:     return result;
                    311: }
                    312: 
                    313: /*  */
                    314: 
                    315: /* ARGSUSED */
                    316: 
                    317: static int  TAccept (tb, responding, data, cc, qos, td)
                    318: register struct tsapblk *tb;
                    319: char   *data;
                    320: int    responding,
                    321:        cc;
                    322: struct QOStype *qos;
                    323: struct TSAPdisconnect *td;
                    324: {
                    325:     int            result;
                    326:     register struct tp4pkt *tp;
                    327: 
                    328:     if ((tp = newtp4pkt (TP_CONNECT_RESP)) == NULL)
                    329:        return tsaplose (td, DR_CONGEST, NULLCP, NULLCP);
                    330: 
                    331:     if (responding)
                    332:        (void) gen2tp4X (&tb -> tb_responding, &tp -> tp4_called,
                    333:                        tb -> tb_initiating.ta_present
                    334:                            ? &tb -> tb_initiating.ta_addr : NULLNA);
                    335: 
                    336:     if (tb -> tb_flags & TB_EXPD)
                    337:        tp -> tp4_expedited = 1;
                    338: 
                    339:     if (sendto (tb -> tb_fd, data, cc, 0, (struct sockaddr *) tp,
                    340:                sizeof (TP_MSG_CONNECT)) == NOTOK)
                    341:        result = tsaplose (td, DR_CONGEST, "failed", "sendto");
                    342:     else {
                    343:        result = OK;
                    344: 
                    345:        tb -> tb_flags |= TB_CONN;
                    346: #ifdef  MGMT
                    347:        if (tb -> tb_manfnx)
                    348:            (*tb -> tb_manfnx) (OPREQIN, tb);
                    349: #endif
                    350:     }
                    351: 
                    352:     freetp4pkt (tp);
                    353: 
                    354:     return result;
                    355: }
                    356: 
                    357: /*  */
                    358: 
                    359: /* life would be nice if we didn't have to worry about the maximum number of
                    360:    bytes that can be written in a single syscall() */
                    361: 
                    362: #ifndef        MSG_MAXIOVLEN
                    363: #define        MSG_MAXIOVLEN   NTPUV
                    364: #endif
                    365: 
                    366: 
                    367: static int  TWrite (tb, uv, expedited, td)
                    368: register struct tsapblk *tb;
                    369: register struct udvec *uv;
                    370: int    expedited;
                    371: struct TSAPdisconnect *td;
                    372: {
                    373:     int            cc,
                    374:            flags,
                    375:            j,
                    376:            len,
                    377:            size;
                    378: #ifdef MGMT
                    379:     int            dlen;
                    380: #endif
                    381:     register char *bp,
                    382:                  *ep;
                    383: #ifndef        SUNLINK_6_0
                    384:     register char *dp;
                    385:     char    data[MAXTP4];
                    386: #endif
                    387:     struct msghdr msgs;
                    388:     register struct msghdr *msg = &msgs;
                    389:     register struct tp4pkt *tp;
                    390:     struct iovec iovs[MSG_MAXIOVLEN];
                    391:     register struct iovec *vv,
                    392:                          *wv;
                    393: 
                    394:     if ((tp = newtp4pkt (expedited ? TP_X_DATA_REQ : TP_DATA_REQ)) == NULL) {
                    395:        (void) tsaplose (td, DR_CONGEST, NULLCP, NULLCP);
                    396:        goto out;
                    397:     }
                    398: 
                    399:     if (expedited)
                    400:        size = sizeof (TP_MSG_X_DATA), flags = MSG_OOB;
                    401:     else
                    402:        size = sizeof (TP_MSG_DATA), flags = 0;
                    403:     
                    404: #ifdef MGMT
                    405:     dlen = 0;
                    406: #endif
                    407: 
                    408:     if (!expedited && (tb -> tb_flags & TB_QWRITES)) {
                    409:        int     onoff,
                    410:                nc;
                    411:        register struct qbuf *qb;
                    412:        struct udvec *xv;
                    413: 
                    414:        cc = 0;
                    415:        for (xv = uv; xv -> uv_base; xv++)
                    416:            cc += xv -> uv_len;
                    417: #ifdef MGMT
                    418:        dlen = cc;
                    419: #endif
                    420: 
                    421:        if ((qb = (struct qbuf *) malloc (sizeof *qb + (unsigned) cc))
                    422:                == NULL) {
                    423:            (void) tsaplose (td, DR_CONGEST, NULLCP,
                    424:                             "unable to malloc %d octets for pseudo-writev, failing...",
                    425:                             cc);
                    426:            freetp4pkt (tp);
                    427:            freetblk (tb);
                    428: 
                    429:            return NOTOK;
                    430:        }
                    431:        qb -> qb_forw = qb -> qb_back = qb;
                    432:        qb -> qb_data = qb -> qb_base, qb -> qb_len = cc;
                    433: 
                    434:        bp = qb -> qb_data;
                    435:        for (xv = uv; xv -> uv_base; xv++) {
                    436:            bcopy (xv -> uv_base, bp, xv -> uv_len);
                    437:            bp += xv -> uv_len;
                    438:        }
                    439: 
                    440:        if (tb -> tb_qwrites.qb_forw != &tb -> tb_qwrites) {
                    441:            nc = 0;
                    442:            goto insert;
                    443:        }
                    444: 
                    445:        tp -> tp4_eot = 1;
                    446: 
                    447:        vv = iovs;
                    448:        vv -> iov_base = qb -> qb_data, vv -> iov_len = qb -> qb_len;
                    449:        vv++;
                    450: 
                    451:        msg -> msg_name = (caddr_t) tp;
                    452:        msg -> msg_namelen = size;
                    453:        msg -> msg_iov = iovs;
                    454:        msg -> msg_iovlen = vv - iovs;
                    455:        msg -> msg_accrights = (caddr_t) NULL;
                    456:        msg -> msg_accrightslen = 0;
                    457: 
                    458:        (void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 1, (char *) &onoff));
                    459: 
                    460:        nc = sendmsg (tb -> tb_fd, msg, flags);
                    461: 
                    462:        (void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 0, (char *) &onoff));
                    463: 
                    464:        if (nc != cc) {
                    465:            if (nc == NOTOK) {
                    466:                if (errno != EWOULDBLOCK) {
                    467:                    (void) tsaplose (td, DR_CONGEST, "failed", "sendmsg");
                    468:                    goto losing;
                    469:                }
                    470: 
                    471:                nc = 0;
                    472:            }
                    473:            if ((*tb -> tb_queuePfnx) (tb, 1, td) == NOTOK)
                    474:                goto losing;
                    475: 
                    476:            qb -> qb_data += nc, qb -> qb_len -= nc;
                    477: insert: ;
                    478:            insque (qb, tb -> tb_qwrites.qb_back);
                    479:            DLOG (tsap_log, LLOG_TRACE,
                    480:                  ("queueing blocked write of %d of %d octets", nc, cc));
                    481:        }
                    482:        else
                    483:            free ((char *) qb);
                    484:        goto done;
                    485: 
                    486: losing: ;
                    487:        free ((char *) qb);
                    488:        freetp4pkt (tp);
                    489:        freetblk (tb);
                    490: 
                    491:        return NOTOK;
                    492:     }
                    493: 
                    494:     ep = (bp = uv -> uv_base) + (cc = uv -> uv_len);
                    495:     while (uv -> uv_base) {
                    496:        wv = (vv = iovs) + MSG_MAXIOVLEN;
                    497:        for (len = tb -> tb_tsdusize; len > 0 && vv < wv; len -= j) {
                    498:            j = min (cc, len);
                    499: #ifdef MGMT
                    500:            dlen += j;
                    501: #endif
                    502:            vv -> iov_base = bp, vv -> iov_len = j, vv++;
                    503:            bp += j, cc -= j;
                    504: 
                    505:            if (bp >= ep) {
                    506:                if ((bp = (++uv) -> uv_base) == NULL)
                    507:                    break;
                    508:                ep = bp + (cc = uv -> uv_len);
                    509:            }
                    510:        }
                    511: 
                    512:        if (!expedited)
                    513:            tp -> tp4_eot = uv -> uv_base == NULL;
                    514: 
                    515: #ifndef        SUNLINK_6_0
                    516:        dp = data, len = 0;
                    517:        for (wv = iovs; wv < vv; wv++) {
                    518:            bcopy (wv -> iov_base, dp, wv -> iov_len);
                    519:            dp += wv -> iov_len, len += wv -> iov_len;
                    520:        }
                    521:        vv = iovs;
                    522:        vv -> iov_base = data, vv -> iov_len = len, vv++;
                    523: #endif
                    524: 
                    525:        msg -> msg_name = (caddr_t) tp;
                    526:        msg -> msg_namelen = size;
                    527:        msg -> msg_iov = iovs;
                    528:        msg -> msg_iovlen = vv - iovs;
                    529:        msg -> msg_accrights = (caddr_t) NULL;
                    530:        msg -> msg_accrightslen = 0;
                    531: 
                    532:        if (sendmsg (tb -> tb_fd, msg, flags) == NOTOK) {
                    533:            (void) tsaplose (td, DR_CONGEST, "failed", "sendmsg");
                    534:            goto out;
                    535:        }
                    536:     }
                    537: 
                    538: done: ;
                    539:     freetp4pkt (tp);
                    540: 
                    541: #ifdef  MGMT
                    542:     if (tb -> tb_manfnx)
                    543:        (*tb -> tb_manfnx) (USERDT, tb, dlen);
                    544: #endif
                    545: 
                    546:     return OK;
                    547: 
                    548: out: ;
                    549:     if (tp)
                    550:        freetp4pkt (tp);
                    551:     freetblk (tb);
                    552: 
                    553:     return NOTOK;
                    554: }
                    555: 
                    556: /*  */
                    557: 
                    558: static int  TDrain (tb, td)
                    559: register struct tsapblk *tb;
                    560: struct TSAPdisconnect *td;
                    561: {
                    562:     int            nc,
                    563:            onoff,
                    564:            result;
                    565:     register struct qbuf *qb;
                    566:     struct msghdr msgs;
                    567:     register struct msghdr *msg = &msgs;
                    568:     register struct tp4pkt *tp;
                    569:     struct iovec vvs;
                    570:     register struct iovec *vv = &vvs;
                    571: 
                    572:     if ((tp = newtp4pkt (TP_DATA_REQ)) == NULL)
                    573:        return tsaplose (td, DR_CONGEST, NULLCP, NULLCP);
                    574:     tp -> tp4_eot = 1;
                    575: 
                    576:     msg -> msg_name = (caddr_t) tp;
                    577:     msg -> msg_namelen = sizeof (TP_MSG_DATA);
                    578:     msg -> msg_iov = vv, msg -> msg_iovlen = 1;
                    579:     msg -> msg_accrights = (caddr_t) NULL;
                    580:     msg -> msg_accrightslen = 0;
                    581: 
                    582:     (void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 1, (char *) &onoff));
                    583: 
                    584:     while ((qb = tb -> tb_qwrites.qb_forw) != &tb -> tb_qwrites) {
                    585:        vv -> iov_base = qb -> qb_data, vv -> iov_len = qb -> qb_len;
                    586: 
                    587:        if (nc = sendmsg (tb -> tb_fd, msg, 0) != qb -> qb_len) {
                    588:            if (nc == NOTOK) {
                    589:                if (errno != EWOULDBLOCK) {
                    590:                    result = tsaplose (td, DR_NETWORK, "failed",
                    591:                                      "write to network");
                    592:                    goto out;
                    593:                }
                    594: 
                    595:                nc = 0;
                    596:            }
                    597: 
                    598:            DLOG (tsap_log, LLOG_TRACE,
                    599:                  ("wrote %d of %d octets from blocked write", nc,
                    600:                   qb -> qb_len));
                    601:            qb -> qb_data += nc, qb -> qb_len -= nc;
                    602: 
                    603:            result = OK;
                    604:            goto out;
                    605:        }
                    606: 
                    607:        DLOG (tsap_log, LLOG_TRACE,
                    608:              ("finished blocked write of %d octets", qb -> qb_len));
                    609:        remque (qb);
                    610:        free ((char *) qb);
                    611:     }
                    612:     result = DONE;
                    613: 
                    614: out: ;
                    615:     (void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 0, (char *) &onoff));
                    616: 
                    617:     freetp4pkt (tp);
                    618:     return result;
                    619: }
                    620: 
                    621: /*  */
                    622: 
                    623: static int  TRead (tb, tx, td, async, oob)
                    624: register struct tsapblk *tb;
                    625: register struct TSAPdata *tx;
                    626: struct TSAPdisconnect *td;
                    627: int    async,
                    628:        oob;
                    629: {
                    630:     int            cc,
                    631:            header_len;
                    632:     register struct qbuf *qb;
                    633:     register struct tp4pkt *tp;
                    634: 
                    635:     bzero ((char *) tx, sizeof *tx);
                    636:     tx -> tx_qbuf.qb_forw = tx -> tx_qbuf.qb_back = &tx -> tx_qbuf;
                    637: 
                    638:     for (;;) {
                    639:        if ((qb = (struct qbuf *) malloc ((unsigned) (sizeof *qb + sizeof *tp
                    640:                                                     + tb -> tb_tsdusize)))
                    641:                == NULL) {
                    642:            (void) tsaplose (td, DR_CONGEST, NULLCP, NULLCP);
                    643:            break;
                    644:        }
                    645:        tp = (struct tp4pkt *) qb -> qb_base;
                    646:        qb -> qb_data = qb -> qb_base + sizeof *tp;
                    647: 
                    648:        header_len = sizeof (struct tp4pkt);    
                    649:        if ((cc = recvfrom (tb -> tb_fd, qb -> qb_data, tb -> tb_tsdusize,
                    650:                            oob ? MSG_OSI_OOB : 0,
                    651:                            (struct sockaddr *) tp, &header_len)) == NOTOK) {
                    652:            (void) tsaplose (td, DR_CONGEST, "failed", "recvfrom");
                    653:            break;
                    654:        }
                    655: 
                    656:        switch (tp -> tp4_event) {
                    657:            case TP_DATA_IND:
                    658:                if (cc > 0) {
                    659:                    insque (qb, tb -> tb_qbuf.qb_back);
                    660:                    tb -> tb_len += (qb -> qb_len = cc);
                    661:                }
                    662:                else
                    663:                    free ((char *) qb);
                    664: #ifdef MGMT
                    665:                if (tb -> tb_manfnx)
                    666:                    (*tb -> tb_manfnx) (USERDR, tb, tb -> tb_len);
                    667: #endif
                    668:                if (!tp -> tp4_eot) {
                    669:                    if (async)
                    670:                        return DONE;
                    671: 
                    672:                    continue;
                    673:                }
                    674:                tx -> tx_expedited = 0;
                    675:                if (tb -> tb_qbuf.qb_forw != &tb -> tb_qbuf) {
                    676:                    tx -> tx_qbuf = tb -> tb_qbuf;      /* struct copy */
                    677:                    tx -> tx_qbuf.qb_forw -> qb_back =
                    678:                            tx -> tx_qbuf.qb_back -> qb_forw = &tx -> tx_qbuf;
                    679:                    tx -> tx_cc = tb -> tb_len;
                    680:                    tb -> tb_qbuf.qb_forw =
                    681:                            tb -> tb_qbuf.qb_back = &tb -> tb_qbuf;
                    682:                    tb -> tb_len = 0;
                    683:                }
                    684: 
                    685:                return OK;
                    686: 
                    687:            case TP_X_DATA_IND:
                    688:                if (cc > 0) {
                    689:                    insque (qb, tx -> tx_qbuf.qb_back);
                    690:                    tx -> tx_cc = (qb -> qb_len = cc);
                    691:                }
                    692:                else
                    693:                    free ((char *) qb);
                    694:                tx -> tx_expedited = 1;
                    695: 
                    696:                return OK;
                    697: 
                    698:            case TP_DISCONNECT_IND:
                    699:                td -> td_reason = (int) tp -> tp4_reason;
                    700:                if ((td -> td_cc = cc) > 0)
                    701:                    bcopy (qb -> qb_data, td -> td_data, cc);
                    702:                break;
                    703: 
                    704:            default:
                    705:                (void) tsaplose (td, DR_NETWORK, NULLCP,
                    706:                                 "unexpected response 0x%x",
                    707:                                 (int) (tp -> tp4_event));
                    708:                break;
                    709:        }
                    710: 
                    711:        break;
                    712:     }
                    713:     if (qb)
                    714:        free ((char *) qb);
                    715: 
                    716:     freetblk (tb);
                    717: 
                    718:     return NOTOK;
                    719: }
                    720: 
                    721: /*  */
                    722: 
                    723: static int  TDisconnect (tb, data, cc, td)
                    724: register struct tsapblk *tb;
                    725: char   *data;
                    726: int    cc;
                    727: struct TSAPdisconnect *td;
                    728: {
                    729:     int            result;
                    730:     register struct tp4pkt *tp;
                    731: 
                    732:     if (tp = newtp4pkt (TP_DISCONNECT_REQ)) {
                    733:        tp -> tp4_reason = (TP_DR_REASON) DR_NORMAL;
                    734: 
                    735: 
                    736:        if (sendto (tb -> tb_fd, data, cc, 0, (struct sockaddr *) tp,
                    737:                    sizeof (TP_MSG_DISCONNECT)) == NOTOK)
                    738:            result = tsaplose (td, DR_CONGEST, "failed", "sendto");
                    739:        else
                    740:            result = OK;
                    741: 
                    742:        freetp4pkt (tp);
                    743:     }
                    744:     else
                    745:        result = tsaplose (td, DR_CONGEST, NULLCP, NULLCP);
                    746: 
                    747:     freetblk (tb);
                    748: 
                    749:     return result;
                    750: }
                    751: 
                    752: /*  */
                    753: 
                    754: /* ARGSUSED */
                    755: 
                    756: static int  TLose (tb, reason, td)
                    757: register struct tsapblk *tb;
                    758: int    reason;
                    759: struct TSAPdisconnect *td;
                    760: {
                    761:     register struct tp4pkt *tp;
                    762: 
                    763:     SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ("TPM error %d", reason));
                    764: 
                    765:     if (tp = newtp4pkt (TP_DISCONNECT_REQ)) {
                    766:        tp -> tp4_reason = (TP_DR_REASON) reason;
                    767: 
                    768:        (void) sendto (tb -> tb_fd, NULLCP, 0, 0, (struct sockaddr *) tp,
                    769:                       sizeof (TP_MSG_DISCONNECT));
                    770: 
                    771:        freetp4pkt (tp);
                    772:     }
                    773: }
                    774: 
                    775: /*    LOWER HALF */
                    776: 
                    777: /* ARGSUSED */
                    778: 
                    779: int    tp4open (tb, local_ta, local_na, remote_ta, remote_na, td, async)
                    780: register struct tsapblk *tb;
                    781: struct TSAPaddr *local_ta,
                    782:                *remote_ta;
                    783: struct NSAPaddr *local_na,
                    784:                *remote_na;
                    785: struct TSAPdisconnect *td;
                    786: int    async;
                    787: {
                    788:     int            fd,
                    789:            onoff;
                    790:     struct TSAPaddr tzs;
                    791:     register struct TSAPaddr *tz = &tzs;
                    792:     register struct NSAPaddr *nz = tz -> ta_addrs;
                    793:     OSI_ADDR   ifaddr;
                    794: 
                    795:     bzero ((char *) tz, sizeof *tz);
                    796:     if (local_ta)
                    797:        *tz = *local_ta;        /* struct copy */
                    798:     if (local_na) {
                    799:        *nz = *local_na;        /* struct copy */
                    800:        tz -> ta_naddr = 1;
                    801:     }
                    802: 
                    803:     (void) gen2tp4 (tz, &ifaddr, remote_na);
                    804: 
                    805:     if ((fd = socket (AF_OSI, SOCK_EVENT, OSIPROTO_TP_EVENT)) == NOTOK)
                    806:        return tsaplose (td, DR_CONGEST, "socket", "unable to start");
                    807: 
                    808:     if (bind (fd, (struct sockaddr *) &ifaddr, sizeof ifaddr) == NOTOK) {
                    809:        (void) tsaplose (td, DR_ADDRESS, "socket", "unable to bind");
                    810:        (void) close (fd);
                    811:        return NOTOK;
                    812:     }
                    813: 
                    814:     tb -> tb_fd = fd;
                    815:     (void) tp4init (tb);
                    816: 
                    817:     if (async)
                    818:        (void) ioctl (fd, FIONBIO, (onoff = 1, (char *) &onoff));
                    819: 
                    820:     return (async ? OK : DONE);
                    821: }
                    822: 
                    823: /*  */
                    824: 
                    825: /* ARGSUSED */
                    826: 
                    827: static int  retry_tp4_socket (tb, td)
                    828: register struct tsapblk *tb;
                    829: struct TSAPdisconnect *td;
                    830: {
                    831:     fd_set  mask;
                    832: 
                    833:     FD_ZERO (&mask);
                    834:     FD_SET (tb -> tb_fd, &mask);
                    835:     if (xselect (tb -> tb_fd + 1, &mask, NULLFD, NULLFD, 0) < 1)
                    836:        return OK;
                    837: 
                    838:     return DONE;
                    839: }
                    840: 
                    841: /*  */
                    842: 
                    843: /* ARGSUSED */
                    844: 
                    845: char   *tp4save (fd, td)
                    846: int fd;
                    847: struct TSAPdisconnect *td;
                    848: {
                    849:     static char buffer[BUFSIZ];
                    850: 
                    851:     (void) sprintf (buffer, "%c%d", NT_SUN, fd);
                    852:     return buffer;
                    853: }
                    854: 
                    855: /*  */
                    856: 
                    857: int    tp4restore (tb, buffer, td)
                    858: register struct tsapblk *tb;
                    859: char   *buffer;
                    860: struct TSAPdisconnect *td;
                    861: {
                    862:     int            fd;
                    863: 
                    864:     if (sscanf (buffer, "%d", &fd) != 1 || fd < 0)
                    865:        return tsaplose (td, DR_PARAMETER, NULLCP,
                    866:                        "bad initialization vector \"%s\"", buffer);
                    867: 
                    868:     tb -> tb_fd = fd;
                    869:     (void) tp4init (tb);
                    870: 
                    871:     return OK;
                    872: }
                    873: 
                    874: /*  */
                    875: 
                    876: int    tp4init (tb)
                    877: register struct tsapblk *tb;
                    878: {
                    879:     tb -> tb_connPfnx = TConnect;
                    880:     tb -> tb_retryPfnx = TRetry;
                    881: 
                    882:     tb -> tb_startPfnx = TStart;
                    883:     tb -> tb_acceptPfnx = TAccept;
                    884: 
                    885:     tb -> tb_writePfnx = TWrite;
                    886:     tb -> tb_readPfnx = TRead;
                    887:     tb -> tb_discPfnx = TDisconnect;
                    888:     tb -> tb_losePfnx = TLose;
                    889: 
                    890:     tb -> tb_drainPfnx = TDrain;
                    891: 
                    892: #ifdef  MGMT
                    893:     tb -> tb_manfnx = TManGen;
                    894: #endif
                    895: 
                    896:     tb -> tb_flags |= TB_TP4;
                    897: 
                    898:     tb -> tb_tsdusize = MAXTP4 - (tb -> tb_tpduslop = 0);
                    899: 
                    900:     tb -> tb_retryfnx = retry_tp4_socket;
                    901: 
                    902:     tb -> tb_closefnx = close_tp4_socket;
                    903:     tb -> tb_selectfnx = select_tp4_socket;
                    904: }
                    905: 
                    906: /*  */
                    907: 
                    908: /* ARGSUSED */
                    909: 
                    910: int    start_tp4_server (sock, backlog, opt1, opt2, td)
                    911: struct TSAPaddr *sock;
                    912: int    backlog,
                    913:        opt1,
                    914:        opt2;
                    915: struct TSAPdisconnect *td;
                    916: {
                    917:     int            sd;
                    918:     OSI_ADDR   ifaddr;
                    919: 
                    920:     (void) gen2tp4 (sock, &ifaddr, NULLNA);
                    921: 
                    922:     if ((sd = socket (AF_OSI, SOCK_EVENT, OSIPROTO_TP_EVENT)) == NOTOK)
                    923:        return tsaplose (td, DR_CONGEST, "socket", "unable to start");
                    924: 
                    925:     if (bind (sd, (struct sockaddr *) &ifaddr, sizeof ifaddr) == NOTOK) {
                    926:        (void) tsaplose (td, DR_ADDRESS, "socket", "unable to bind");
                    927:        (void) close (sd);
                    928:        return NOTOK;
                    929:     }
                    930: 
                    931:     (void) listen (sd, backlog);
                    932: 
                    933:     return sd;
                    934: }
                    935: 
                    936: /*  */
                    937: 
                    938: #ifndef        notdef
                    939: /* ARGSUSED */
                    940: #endif
                    941: 
                    942: int    join_tp4_client (fd, sock, td)
                    943: int    fd;
                    944: struct TSAPaddr *sock;
                    945: struct TSAPdisconnect *td;
                    946: {
                    947:     int            len,
                    948:            sd;
                    949:     OSI_ADDR   ifaddr;
                    950: 
                    951:     len = sizeof (OSI_ADDR);
                    952:     if ((sd = accept (fd, (struct sockaddr *) &ifaddr, &len)) == NOTOK)
                    953:        return tsaplose (td, DR_NETWORK, "socket", "unable to accept");
                    954:        
                    955: #ifdef notdef
                    956:     /* Ouch!!  Trying to get the remote address off the socket
                    957:      * only works for local connections.  Non-local connections
                    958:      * causes a core dump when I try to convert.
                    959:      */
                    960:     (void) tp42gen (sock, &ifaddr);
                    961: #endif
                    962:     
                    963:     return sd;
                    964: }
                    965: 
                    966: /*  */
                    967: 
                    968: /* SunLink OSI address encoding/decoding */
                    969: 
                    970: #ifdef SUNLINK_5_2
                    971: /* ARGSUSED */
                    972: #endif
                    973: 
                    974: static int  gen2tp4 (generic, specific, template)
                    975: struct TSAPaddr *generic;
                    976: OSI_ADDR       *specific;
                    977: struct NSAPaddr        *template;
                    978: {
                    979: #ifndef        SUNLINK_6_0
                    980:     int            len,
                    981:            paddr_type;
                    982: #endif
                    983: #ifndef        SUNLINK_5_2
                    984:     char    buffer[BUFSIZ];
                    985: #endif
                    986:     struct NSAPaddr *na;
                    987: 
                    988:     OSI_ADDR_INIT (specific);
                    989: 
                    990:     if (generic -> ta_naddr > 0) {
                    991:        na = generic -> ta_addrs;
                    992: #ifndef        SUNLINK_6_0
                    993:        paddr_type = AF_OSI, len = 0;
                    994:        if (na -> na_addrlen > 0)
                    995:            switch (na -> na_address[0]) {
                    996:                case 0x49:
                    997:                    paddr_type = AF_NBS;
                    998:                    len = 1;
                    999:                    break;
                   1000: 
                   1001:                case 0x47:
                   1002:                    if (na -> na_addrlen < 3
                   1003:                            || na -> na_address[1] != 0x00
                   1004:                            || na -> na_address[2] != 0x04)
                   1005:                        break;
                   1006:                    paddr_type = AF_OSINET;
                   1007:                    len = 3;
                   1008:                    break;
                   1009:            }
                   1010: 
                   1011:        osi_set_sap (na -> na_address + len, na -> na_addrlen - len, specific,
                   1012:                     OSI_NSAP, paddr_type);
                   1013: #else
                   1014:        osi_set_sap (na -> na_address, na -> na_addrlen, specific,
                   1015:                     OSI_NSAP, AF_USER_DEFINED);
                   1016: #endif
                   1017:     }
                   1018:     else {
                   1019: #ifndef        SUNLINK_5_2
                   1020:        /* The SunLink OSI I'm using seems to require something
                   1021:         * although the ``manual'' says I don't.  Hmmmm, I wonder
                   1022:          * if I still need the OSI_ADDR_INIT? BTW, osi_set_sap is one
                   1023:         * of the two functions I link from the -losi library.  When I
                   1024:         * get the source for SunLink (maybe before I retire) I'll
                   1025:         * write my own set/get sap function and punt libosi.a
                   1026:         */
                   1027: 
                   1028:        paddr_type = AF_OSI;
                   1029:        if (template != NULLNA && template -> na_addrlen > 0)
                   1030:            switch (template -> na_address[0]) {
                   1031:                case 0x49:
                   1032:                    paddr_type = AF_NBS;
                   1033:                    break;
                   1034: 
                   1035:                case 0x47:
                   1036:                    if (template -> na_addrlen < 3
                   1037:                            || template -> na_address[1] != 0x00
                   1038:                            || template -> na_address[2] != 0x04)
                   1039:                        break;
                   1040:                    paddr_type = AF_OSINET;
                   1041:                    break;
                   1042:            }
                   1043: 
                   1044:        buffer[0] = 0x00, len = 1;
                   1045:        osi_set_sap (buffer, len, specific, OSI_NSAP, paddr_type);
                   1046: #else
                   1047:        mds_lookup ("localhost", "CLIENT", specific);;
                   1048: #endif
                   1049:     }
                   1050: 
                   1051:     osi_set_sap (generic -> ta_selector, generic -> ta_selectlen, specific,
                   1052:                 OSI_TSAP, OSI_AF_GENERIC);
                   1053: 
                   1054:     return OK;
                   1055: }
                   1056: 
                   1057: 
                   1058: static int  gen2tp4X (generic, specific, template)
                   1059: struct tsapADDR *generic;
                   1060: OSI_ADDR       *specific;
                   1061: struct NSAPaddr        *template;
                   1062: {
                   1063:     struct TSAPaddr tas;
                   1064: 
                   1065:     copyTSAPaddrX (generic, &tas);
                   1066:     return gen2tp4 (&tas, specific, template);
                   1067: }
                   1068: 
                   1069: /*  */
                   1070: 
                   1071: int    tp42gen (generic, specific)
                   1072: struct TSAPaddr *generic;
                   1073: OSI_ADDR       *specific;
                   1074: {
                   1075:     int            len,
                   1076:            paddr_type;
                   1077:     char    buffer[NASIZE];
                   1078:     struct NSAPaddr *na;
                   1079: 
                   1080:     paddr_type = 0;
                   1081:     if ((len = osi_get_sap (specific, buffer, sizeof buffer, OSI_NSAP,
                   1082:                            &paddr_type)) <= 0)
                   1083:        return NOTOK;
                   1084: 
                   1085:     na = generic -> ta_addrs;
                   1086:     na -> na_stack = NA_NSAP;
                   1087:     na -> na_community = ts_comm_nsap_default;
                   1088:     switch (paddr_type) {
                   1089:        case AF_NBS:
                   1090:            na -> na_address[0] = 0x49;
                   1091:            na -> na_addrlen = 1;
                   1092:            break;
                   1093: 
                   1094:        case AF_OSINET:
                   1095:            na -> na_address[0] = 0x47;
                   1096:            na -> na_address[1] = 0x00;
                   1097:            na -> na_address[2] = 0x04;
                   1098:            na -> na_addrlen = 3;
                   1099:            break;
                   1100: 
                   1101:        default:
                   1102:            na -> na_addrlen = 0;
                   1103:            break;
                   1104:     }
                   1105:     bcopy (buffer, na -> na_address + na -> na_addrlen, len);
                   1106:     na -> na_addrlen += len;
                   1107: 
                   1108:     generic -> ta_naddr = 1;
                   1109:     generic -> ta_selectlen = osi_get_sap (specific, generic -> ta_selector,
                   1110:                                           TSSIZE, OSI_TSAP, &paddr_type);
                   1111: 
                   1112:     return OK;
                   1113: }
                   1114: 
                   1115: 
                   1116: int    tp42genX (generic, specific)
                   1117: struct tsapADDR *generic;
                   1118: OSI_ADDR       *specific;
                   1119: {
                   1120:     int            result;
                   1121:     struct TSAPaddr tas;
                   1122: 
                   1123:     if ((result = tp42gen (&tas, specific)) == OK)
                   1124:        copyTSAPaddrY (&tas, generic);
                   1125: 
                   1126:     return result;
                   1127: }
                   1128: 
                   1129: /*  */
                   1130: 
                   1131: struct tp4pkt *newtp4pkt (code)
                   1132: TP_EVENT code;
                   1133: {
                   1134:     struct tp4pkt *tp;
                   1135: 
                   1136:     tp = (struct tp4pkt *) calloc (1, sizeof *tp);
                   1137:     if (tp != NULL)
                   1138:        tp -> tp4_event = code;
                   1139:     
                   1140:     return tp;
                   1141: }
                   1142: #endif

unix.superglobalmegacorp.com

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