Annotation of 43BSDReno/contrib/isode-beta/tsap/ts2sunlink.c, revision 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.