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

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

unix.superglobalmegacorp.com

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