Annotation of 43BSDReno/contrib/isode-beta/ssap/ssaprovider.c, revision 1.1.1.1

1.1       root        1: /* ssaprovider.c - implement the session protocol */
                      2: 
                      3: #ifndef        lint
                      4: static char *rcsid = "$Header: /f/osi/ssap/RCS/ssaprovider.c,v 7.1 89/11/30 23:51:19 mrose Exp $";
                      5: #endif
                      6: 
                      7: /* 
                      8:  * $Header: /f/osi/ssap/RCS/ssaprovider.c,v 7.1 89/11/30 23:51:19 mrose Exp $
                      9:  *
                     10:  *
                     11:  * $Log:       ssaprovider.c,v $
                     12:  * Revision 7.1  89/11/30  23:51:19  mrose
                     13:  * touch-up
                     14:  * 
                     15:  * Revision 7.0  89/11/23  22:25:45  mrose
                     16:  * Release 6.0
                     17:  * 
                     18:  */
                     19: 
                     20: /*
                     21:  *                               NOTICE
                     22:  *
                     23:  *    Acquisition, use, and distribution of this module and related
                     24:  *    materials are subject to the restrictions of a license agreement.
                     25:  *    Consult the Preface in the User's Manual for the full terms of
                     26:  *    this agreement.
                     27:  *
                     28:  */
                     29: 
                     30: 
                     31: /* LINTLIBRARY */
                     32: 
                     33: #include <stdio.h>
                     34: #include <signal.h>
                     35: #include "spkt.h"
                     36: #include "tailor.h"
                     37: 
                     38: /*    DATA */
                     39: 
                     40: static int  once_only = 0;
                     41: static struct ssapblk ssapque;
                     42: static struct ssapblk *SHead = &ssapque;
                     43: 
                     44: 
                     45: int    TDATAser (), TDISCser ();
                     46: 
                     47: 
                     48: /*    S-DATA.REQUEST */
                     49: 
                     50: int    SDataRequest (sd, data, cc, si)
                     51: int    sd;
                     52: char   *data;
                     53: int    cc;
                     54: struct SSAPindication *si;
                     55: {
                     56:     SBV            smask;
                     57:     int     result;
                     58:     struct udvec uvs[2];
                     59:     register struct udvec *uv = uvs;
                     60:     register struct ssapblk *sb;
                     61: 
                     62:     missingP (data);
                     63:     if (cc <= 0)
                     64:        return ssaplose (si, SC_PARAMETER, NULLCP,
                     65:                    "illegal value for SSDU length (%d)", cc);
                     66:     missingP (si);
                     67: 
                     68:     smask = sigioblock ();
                     69: 
                     70:     ssapPsig (sb, sd);
                     71: 
                     72:     uv -> uv_base = data, uv -> uv_len = cc, uv++;
                     73:     uv -> uv_base = NULL;
                     74: 
                     75:     result = SDataRequestAux (sb, SPDU_DT, uvs, si);
                     76: 
                     77:     (void) sigiomask (smask);
                     78: 
                     79:     return result;
                     80: }
                     81: 
                     82: /*    S-WRITE.REQUEST (pseudo; write user data vectors) */
                     83: 
                     84: int    SWriteRequest (sd, typed, uv, si)
                     85: int    sd;
                     86: int    typed;
                     87: struct udvec *uv;
                     88: struct SSAPindication *si;
                     89: {
                     90:     SBV            smask;
                     91:     int     result;
                     92:     register struct ssapblk *sb;
                     93: 
                     94:     missingP (uv);
                     95:     missingP (si);
                     96: 
                     97:     smask = sigioblock ();
                     98: 
                     99:     ssapPsig (sb, sd);
                    100: 
                    101:     result = SDataRequestAux (sb, typed ? SPDU_TD : SPDU_DT, uv, si);
                    102: 
                    103:     (void) sigiomask (smask);
                    104: 
                    105:     return result;
                    106: }
                    107: 
                    108: /*  */
                    109: 
                    110: #define        NSPUV   12      /* really should be MSG_MAXIOVLEN - 4 */
                    111: 
                    112: 
                    113: int    SDataRequestAux (sb, code, uv, si)
                    114: register struct ssapblk *sb;
                    115: int    code;
                    116: register struct udvec *uv;
                    117: struct SSAPindication *si;
                    118: {
                    119:     int     begin,
                    120:            cc,             
                    121:             j,
                    122:            len,
                    123:            n,
                    124:             result;
                    125:     register char *bp,
                    126:                  *ep;
                    127:     register struct ssapkt *s;
                    128:     struct TSAPdisconnect   tds;
                    129:     register struct TSAPdisconnect *td = &tds;
                    130:     struct udvec vvs[NSPUV];
                    131:     register struct udvec  *vv,
                    132:                           *wv;
                    133:     struct udvec *xv;
                    134: 
                    135:     switch (code) {
                    136:        case SPDU_DT: 
                    137:            if ((sb -> sb_requirements & SR_DAT_EXISTS)
                    138:                    && !(sb -> sb_owned & ST_DAT_TOKEN))
                    139:                return ssaplose (si, SC_OPERATION, NULLCP,
                    140:                        "data token not owned by you");
                    141:            break;
                    142: 
                    143:        case SPDU_TD: 
                    144:            if (!(sb -> sb_requirements & SR_TYPEDATA))
                    145:                return ssaplose (si, SC_OPERATION, NULLCP,
                    146:                        "typed data service unavailable");
                    147:            break;
                    148:     }
                    149: 
                    150:     n = 0;
                    151:     for (vv = uv; vv -> uv_base; vv++)
                    152:        n += vv -> uv_len;
                    153:     if (n == 0)
                    154:        return ssaplose (si, SC_PARAMETER, NULLCP, "zero-length SSDU");
                    155:     
                    156:     ep = (bp = uv -> uv_base) + (cc = uv -> uv_len);
                    157:     begin = 1;
                    158:     while (uv -> uv_base) {
                    159:        len = sb -> sb_tsdu_us ? min (n, sb -> sb_tsdu_us - SSDU_MAGIC) : n;
                    160:        vv = vvs;
                    161:        vvs[0].uv_base = vvs[1].uv_base = NULL;
                    162:        vvs[1].uv_inline = 0;
                    163: 
                    164:        if (code == SPDU_DT) {
                    165:            if ((s = newspkt (SPDU_GT)) == NULL)
                    166:                return ssaplose (si, SC_CONGEST, NULLCP, "out of memory");
                    167:            s -> s_mask |= SMASK_SPDU_GT;
                    168: 
                    169:            if (spkt2tsdu (s, &vv -> uv_base, &vv -> uv_len) == NOTOK) {
                    170:                (void) ssaplose (si, s -> s_errno, NULLCP, NULLCP);
                    171:                goto out1;
                    172:            }
                    173:            freespkt (s);
                    174:            s = NULL;
                    175:            vv++;
                    176:        }
                    177: 
                    178:        xv = vv++;
                    179: 
                    180:        wv = vvs + NSPUV - 1;
                    181:        for (; len > 0 && vv < wv; len -= j) {
                    182:            j = min (cc, len);
                    183:            vv -> uv_base = bp, vv -> uv_len = j, vv -> uv_inline = 1, vv++;
                    184:            bp += j, cc -= j, n -= j;
                    185: 
                    186:            if (bp >= ep) {
                    187:                if ((bp = (++uv) -> uv_base) == NULL)
                    188:                    break;
                    189:                ep = bp + (cc = uv -> uv_len);
                    190:            }
                    191:        }
                    192:        if (!sb -> sb_tsdu_us && uv -> uv_base) {
                    193:            (void) ssaplose (si, SC_PARAMETER, NULLCP,
                    194:                             "too many vector entries in SDU");
                    195:            goto out2;
                    196:        }
                    197:        vv -> uv_base = NULL;
                    198: 
                    199:        vv = xv;
                    200:        if ((s = newspkt (code)) == NULL) {
                    201:            (void) ssaplose (si, SC_CONGEST, NULLCP, "out of memory");
                    202:            goto out2;
                    203:        }
                    204:        if (sb -> sb_tsdu_us) {
                    205:            s -> s_mask |= SMASK_ENCLOSE;
                    206:            if (begin) {
                    207:                s -> s_enclose |= ENCL_BEGIN;
                    208:                begin = 0;
                    209:            }       
                    210:            if (uv -> uv_base == NULL)
                    211:                s -> s_enclose |= ENCL_END;
                    212:        }
                    213:        if (spkt2tsdu (s, &vv -> uv_base, &vv -> uv_len) == NOTOK) {
                    214:            (void) ssaplose (si, s -> s_errno, NULLCP, NULLCP);
                    215:            goto out3;
                    216:        }
                    217:        freespkt (s);
                    218:        s = NULL;
                    219: 
                    220:        if ((result = TWriteRequest (sb -> sb_fd, vvs, td)) == NOTOK)
                    221:            (void) ts2sslose (si, "TWriteRequest", td);
                    222: 
                    223:        free (vvs[0].uv_base);
                    224:        if (code == SPDU_DT)
                    225:            free (vvs[1].uv_base);
                    226: 
                    227:        if (result == NOTOK)
                    228:            return NOTOK;
                    229:     }
                    230:     return OK;
                    231: 
                    232: out3: ;
                    233:     if (vvs[1].uv_base && !vvs[1].uv_inline)
                    234:        free (vvs[1].uv_base);
                    235: out2: ;
                    236:     if (vvs[0].uv_base)
                    237:        free (vvs[0].uv_base);
                    238: out1: ;
                    239:     freespkt (s);
                    240: 
                    241:     return NOTOK;
                    242: }
                    243: 
                    244: /*    S-READ.REQUEST (pseudo; synchronous read) */
                    245: 
                    246: int    SReadRequest (sd, sx, secs, si)
                    247: int    sd;
                    248: struct SSAPdata *sx;
                    249: int    secs;
                    250: struct SSAPindication *si;
                    251: {
                    252:     SBV            smask;
                    253:     int     result;
                    254:     register struct ssapblk *sb;
                    255: 
                    256:     missingP (sx);
                    257:     missingP (si);
                    258: 
                    259:     smask = sigioblock ();
                    260: 
                    261:     if ((sb = findsblk (sd)) == NULL) {
                    262:        (void) sigiomask (smask);
                    263:        return ssaplose (si, SC_PARAMETER, NULLCP, "invalid session descriptor");
                    264:     }
                    265:     if (!(sb -> sb_flags & SB_CONN)) {
                    266:        (void) sigiomask (smask); 
                    267:        return ssaplose (si, SC_PARAMETER, NULLCP, 
                    268:                            "session descriptor not connected"); 
                    269:     } 
                    270:     if (sb -> sb_flags & SB_FINN) { 
                    271:        (void) sigiomask (smask); 
                    272:        return ssaplose (si, SC_OPERATION, NULLCP, 
                    273:                            "session descriptor finishing"); 
                    274:     } 
                    275: 
                    276:     result = SReadRequestAux (sb, sx, secs, si, 0, NULLTX);
                    277: 
                    278:     (void) sigiomask (smask);
                    279: 
                    280:     return result;
                    281: }
                    282: 
                    283: /*  */
                    284: 
                    285: static int  SReadRequestAux (sb, sx, secs, si, async, tx)
                    286: register struct ssapblk *sb;
                    287: register struct SSAPdata *sx;
                    288: int    secs;
                    289: struct SSAPindication *si;
                    290: int    async;
                    291: struct TSAPdata *tx;
                    292: {
                    293:     int     eot;
                    294:     char    tokens;
                    295:     register struct ssapkt *s;
                    296: 
                    297:     bzero ((char *) sx, sizeof *sx);
                    298:     sx -> sx_qbuf.qb_forw = sx -> sx_qbuf.qb_back = &sx -> sx_qbuf;
                    299:     bzero ((char *) si, sizeof *si);
                    300: 
                    301:     for (; s = sb2spkt (sb, si, secs, tx); tx = NULLTX) {
                    302:        if (!(s -> s_mask & SMASK_SPDU_EXPD))
                    303:            switch (sb -> sb_pr) {
                    304:                case SPDU_PR:
                    305:                    break;
                    306: 
                    307:                case SPDU_MAA:
                    308:                    if (s -> s_code == SPDU_MAA)
                    309:                        sb -> sb_pr = SPDU_PR;
                    310:                    break;
                    311: 
                    312:                case SPDU_RS:
                    313:                    switch (s -> s_code) {
                    314:                        case SPDU_AB:
                    315: #ifdef notdef
                    316:                        case SPDU_AI:   /* aka SPDU_AB */
                    317: #endif
                    318:                            if (s -> s_mask & SMASK_SPDU_AB)
                    319:                                break;  /* else fall */
                    320:                        case SPDU_AD:
                    321:                        case SPDU_RS:
                    322:                            sb -> sb_pr = SPDU_PR;
                    323:                            break;
                    324: 
                    325:                        default:
                    326:                            goto drop_it;
                    327:                    }
                    328:                    break;
                    329: 
                    330:                case SPDU_RA:
                    331:                    switch (s -> s_code) {
                    332:                        case SPDU_AB:
                    333:                            break;
                    334: 
                    335:                        case SPDU_AA:
                    336: #ifdef notdef
                    337:                        case SPDU_AIA:  /* aka SPDU_AA */
                    338: #endif
                    339:                            if (s -> s_mask & SMASK_SPDU_AA)
                    340:                                break;  /* else fall */
                    341:                        case SPDU_ADA:
                    342:                        case SPDU_RA:
                    343:                            sb -> sb_pr = SPDU_PR;
                    344:                            break;
                    345: 
                    346:                        default:
                    347: drop_it: ;
                    348:                            SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
                    349:                                  ("discarding 0x%x SPDU", s -> s_code));
                    350:                            freespkt (s);
                    351:                            goto spin;
                    352:                    }
                    353:                    break;
                    354: 
                    355:                case SPDU_AB:
                    356:                    if (s -> s_code != SPDU_AB)
                    357:                        goto drop_it;
                    358:                    sb -> sb_pr = SPDU_PR;
                    359:                    break;
                    360: 
                    361:                default:
                    362:                    break;
                    363:            }
                    364: 
                    365:        if (sb -> sb_flags & (SB_RS | SB_AI))
                    366:            switch (s -> s_code) {
                    367:                case SPDU_PR:
                    368:                    switch (s -> s_pr_type) {
                    369:                        case PR_RS:
                    370:                        case PR_RA:
                    371:                            break;
                    372:                        default:
                    373:                            goto drop_it;
                    374:                    }
                    375:                    break;
                    376: 
                    377:                case SPDU_RS:
                    378:                    if (SDoCollideAux (sb -> sb_flags & SB_INIT ? 1 : 0,
                    379:                                sb -> sb_rs, sb -> sb_rsn,
                    380:                                (int) s -> s_rs_type, (long) s -> s_rs_serial)
                    381:                            != NOTOK)
                    382:                        goto drop_it;
                    383:                    break;
                    384: 
                    385:                case SPDU_RA:
                    386:                    break;
                    387:                  
                    388:                case SPDU_AD:
                    389:                    if (SDoCollideAux (sb -> sb_flags & SB_INIT ? 1 : 0,
                    390:                                sb -> sb_rs, sb -> sb_rsn, SYNC_DISC, 0L)
                    391:                            != NOTOK)
                    392:                        goto drop_it;
                    393:                    break;
                    394: 
                    395:                case SPDU_AB:
                    396: #ifdef notdef
                    397:                case SPDU_AI:   /* aka SPDU_AB */
                    398: #endif
                    399:                    if (s -> s_mask & SMASK_SPDU_AB)
                    400:                        break;
                    401:                    if (SDoCollideAux (sb -> sb_flags & SB_INIT ? 1 : 0,
                    402:                                sb -> sb_rs, sb -> sb_rsn, SYNC_INTR, 0L)
                    403:                            != NOTOK)
                    404:                        goto drop_it;
                    405:                    break;
                    406:            }
                    407:        
                    408:        if (sb -> sb_flags & (SB_ED | SB_ERACK))
                    409:            switch (s -> s_code) {
                    410:                case SPDU_AB:
                    411:                    break;
                    412: 
                    413:                case SPDU_MAP:
                    414:                case SPDU_MIP:
                    415:                    if (sb -> sb_flags & SB_ED)
                    416:                        break;
                    417:                    goto drop_it;
                    418: 
                    419:                case SPDU_PR:
                    420:                    if (s -> s_pr_type == PR_RS)
                    421:                        break;
                    422:                    goto drop_it;
                    423: 
                    424:                case SPDU_GT:
                    425:                    if ((s -> s_mask & SMASK_SPDU_GT)
                    426:                            && (s -> s_mask & SMASK_GT_TOKEN)
                    427:                            && (s -> s_gt_token & ST_DAT_TOKEN))
                    428:                        break;  /* else fall */
                    429: 
                    430:                default:
                    431:                    goto drop_it;
                    432:            }
                    433: 
                    434:        if (sb -> sb_len > 0)
                    435:            switch (s -> s_code) {
                    436:                case SPDU_PT:
                    437:                case SPDU_EX:
                    438:                    break;
                    439: 
                    440:                case SPDU_PR:
                    441:                    if (s -> s_pr_type != PR_RS)
                    442:                        break;
                    443:                case SPDU_RS:
                    444:                case SPDU_ER:
                    445:                case SPDU_ED:
                    446:                case SPDU_AD:
                    447: #ifdef notdef
                    448:                case SPDU_AI:   /* aka SPDU_AB */
                    449: #endif
                    450:                case SPDU_AB:
                    451:                    SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
                    452:                          ("flush partially assembled (T))SSDU"));
                    453:                    QBFREE (&sb -> sb_qbuf);
                    454:                    sb -> sb_len = 0;
                    455:                    break;
                    456: 
                    457:                case SPDU_GT:
                    458:                    if (s -> s_mask & SMASK_SPDU_GT)
                    459:                        break;  /* else SPDU_DT */
                    460:                default:
                    461:                    if (sb -> sb_code == s -> s_code)
                    462:                        break;
                    463:                    (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
                    464:                            "session protocol mangled: expecting 0x%x, got 0x%x during segmentation",
                    465:                            sb -> sb_code, s -> s_code);
                    466:                    goto out;
                    467:            }
                    468: 
                    469: /* allows AB SPDUs to have 512, not 9, octets (which is fine by me) */
                    470:        if (s -> s_ulen > CN_SIZE && sb -> sb_version < SB_VRSN2) {
                    471:            (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
                    472:                             "too much user data (%d) in SPDU 0x%x",
                    473:                             s -> s_ulen, s -> s_code);
                    474:            goto out;
                    475:        }
                    476: 
                    477:        if ((s -> s_mask & SMASK_ENCLOSE)
                    478:                && (s -> s_code != SPDU_DT || (s -> s_mask & SMASK_SPDU_GT))
                    479:                && s -> s_code != SPDU_TD) {
                    480:            if (sb -> sb_version < SB_VRSN2) {
                    481:                (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
                    482:                                 "unexpected segmentation for SPDU 0x%x",
                    483:                                 s -> s_code);
                    484:                goto out;
                    485:            }
                    486: 
                    487: /* XXX: in practice, I don't think this is unreasonable.  It is
                    488:        however not too restrictive */
                    489: 
                    490:            if (s -> s_enclose != ENCL_MASK) {
                    491:                (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
                    492:                                 "non-trivial segmentation (0x%x) for SPDU 0x%x",
                    493:                                 s -> s_enclose, s -> s_code);
                    494:                goto out;
                    495:            }
                    496:        }
                    497: 
                    498:        switch (s -> s_code) {
                    499:            case SPDU_PT: 
                    500:                if (sb -> sb_flags & SB_GTC) {
                    501:                    freespkt (s);
                    502:                    goto spin;
                    503:                }
                    504:                tokens = 0;
                    505:                if (s -> s_mask & SMASK_PT_TOKEN) {
                    506: #define        dotoken(requires,shift,bit,type) \
                    507: { \
                    508:                    if ((sb -> sb_requirements & requires) \
                    509:                            && (s -> s_pt_token & bit)) \
                    510:                        tokens |= bit; \
                    511: }
                    512:                        dotokens ();
                    513: #undef dotoken
                    514:                }
                    515:                si -> si_type = SI_TOKEN;
                    516:                {
                    517:                    register struct SSAPtoken *st = &si -> si_token;
                    518: 
                    519:                    st -> st_type = ST_PLEASE;
                    520:                    st -> st_tokens = tokens;
                    521:                    st -> st_owned = sb -> sb_owned;
                    522:                    copySPKTdata (s, st);
                    523:                }
                    524:                freespkt (s);
                    525:                return DONE;
                    526: 
                    527:            case SPDU_GT: 
                    528:                if (s -> s_mask & SMASK_SPDU_GT) {
                    529:                    if (sb -> sb_flags & SB_GTC) {
                    530:                        freespkt (s);
                    531:                        goto spin;
                    532:                    }
                    533:                    tokens = 0;
                    534:                    if (s -> s_mask & SMASK_GT_TOKEN) {
                    535: #define        dotoken(requires,shift,bit,type) \
                    536: { \
                    537:                        if ((sb -> sb_requirements & requires) \
                    538:                            && (s -> s_gt_token & bit)) \
                    539:                                sb -> sb_owned |= bit, tokens |= bit; \
                    540: }
                    541:                        dotokens ();
                    542: #undef dotoken
                    543:                    }
                    544:                    freespkt (s);
                    545:                    if (tokens & ST_DAT_TOKEN)
                    546:                        sb -> sb_flags &= ~(SB_ED | SB_ERACK);
                    547:                    si -> si_type = SI_TOKEN;
                    548:                    {
                    549:                        register struct SSAPtoken  *st = &si -> si_token;
                    550: 
                    551:                        st -> st_type = ST_GIVE;
                    552:                        st -> st_tokens = tokens;
                    553:                        st -> st_owned = sb -> sb_owned;
                    554:                    }
                    555:                    return DONE;
                    556:                }               /* else fall for case SPDU_DT: */
                    557: #ifdef notdef
                    558:            case SPDU_DT:
                    559: #endif
                    560:            case SPDU_TD:
                    561:                sb -> sb_code = s -> s_code;
                    562:                if (sb -> sb_tsdu_them) {
                    563:                    if (!(s -> s_mask & SMASK_ENCLOSE)) {
                    564:                        (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
                    565:                                "no segmentation information");
                    566:                        break;
                    567:                    }
                    568:                    if ((s -> s_enclose & ENCL_BEGIN)
                    569:                            ? sb -> sb_len > 0 : sb -> sb_len == 0) {
                    570:                        (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
                    571:                                "segmentation mismatch");
                    572:                        break;
                    573:                    }
                    574:                    eot = s -> s_enclose & ENCL_END;
                    575:                }
                    576:                else
                    577:                    eot = 1;
                    578:                if (s -> s_qbuf.qb_forw != &s -> s_qbuf) {
                    579:                    sb -> sb_qbuf.qb_back -> qb_forw = s -> s_qbuf.qb_forw;
                    580:                    s -> s_qbuf.qb_forw -> qb_back = sb -> sb_qbuf.qb_back;
                    581:                    s -> s_qbuf.qb_back -> qb_forw = &sb -> sb_qbuf;
                    582:                    sb -> sb_qbuf.qb_back = s -> s_qbuf.qb_back;
                    583:                    sb -> sb_len += s -> s_qlen;
                    584:                    s -> s_qbuf.qb_forw =
                    585:                            s -> s_qbuf.qb_back = &s -> s_qbuf;
                    586:                    s -> s_qlen = 0;
                    587:                }
                    588:                if (!eot && (s -> s_code == SPDU_DT) && sb -> sb_spdu) {
                    589:                    freespkt (sb -> sb_spdu);
                    590:                    sb -> sb_spdu = NULL;
                    591:                }
                    592:                freespkt (s);
                    593:                if (!eot)
                    594:                    goto spin;
                    595:                sx -> sx_type = sb -> sb_code == SPDU_DT ? SX_NORMAL
                    596:                                    : SX_TYPED;
                    597:                if (sb -> sb_qbuf.qb_forw != &sb -> sb_qbuf) {
                    598:                    sx -> sx_qbuf = sb -> sb_qbuf;/* struct copy */
                    599:                    sx -> sx_qbuf.qb_forw -> qb_back =
                    600:                            sx -> sx_qbuf.qb_back -> qb_forw = &sx -> sx_qbuf;
                    601:                    sx -> sx_cc = sb -> sb_len;
                    602:                    sb -> sb_qbuf.qb_forw =
                    603:                            sb -> sb_qbuf.qb_back = &sb -> sb_qbuf;
                    604:                    sb -> sb_len = 0;
                    605:                }
                    606:                return OK;
                    607: 
                    608:            case SPDU_EX: 
                    609:                if (sb -> sb_pr != SPDU_PR) {
                    610:                    SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
                    611:                          ("buffering XSDU during preparation"));
                    612:                    if (sb -> sb_xspdu) {
                    613:                        (void) spktlose (sb -> sb_fd, si, SC_CONGEST, NULLCP,
                    614:                                "unable to buffer second XSDU");
                    615:                        break;
                    616:                    }
                    617:                    sb -> sb_xspdu = s;
                    618:                    goto spin;
                    619:                }
                    620:                sx -> sx_type = SX_EXPEDITED;
                    621:                if (s -> s_qbuf.qb_forw != &s -> s_qbuf) {
                    622:                    sx -> sx_qbuf = s -> s_qbuf;/* struct copy */
                    623:                    sx -> sx_qbuf.qb_forw -> qb_back =
                    624:                            sx -> sx_qbuf.qb_back -> qb_forw = &sx -> sx_qbuf;
                    625:                    sx -> sx_cc = s -> s_qlen;
                    626:                    s -> s_qbuf.qb_forw =
                    627:                            s -> s_qbuf.qb_back = &s -> s_qbuf;
                    628:                    s -> s_qlen = 0;
                    629:                }
                    630:                freespkt (s);
                    631:                return OK;
                    632: 
                    633:            case SPDU_CD:
                    634:            case SPDU_CDA:
                    635:                if (s -> s_code == SPDU_CD) {
                    636:                    sb -> sb_flags |= SB_CDA;
                    637:                    sx -> sx_type = SX_CAPDIND;
                    638:                }
                    639:                else {
                    640:                    sb -> sb_flags &= ~SB_CD;
                    641:                    sx -> sx_type = SX_CAPDCNF;
                    642:                }
                    643:                if (s -> s_udata) {
                    644:                    register struct qbuf *qb;
                    645: 
                    646:                    qb = (struct qbuf *)
                    647:                            malloc (sizeof *qb + (unsigned) s -> s_ulen);
                    648:                    if (qb == NULL) {
                    649:                        (void) spktlose (sb -> sb_fd, si, SC_CONGEST, NULLCP,
                    650:                                    "out of memory");
                    651:                        break;
                    652:                    }
                    653:                    bcopy (s -> s_udata, qb -> qb_data = qb -> qb_base,
                    654:                            qb -> qb_len = s -> s_ulen);
                    655:                    insque (qb, &sx -> sx_qbuf);
                    656:                    sx -> sx_cc = s -> s_ulen;
                    657:                }
                    658:                freespkt (s);
                    659:                return OK;
                    660: 
                    661:            case SPDU_GTC:
                    662:                if (sb -> sb_flags & SB_Vact) {
                    663:                    freespkt (s);
                    664:                    goto spin;
                    665:                }
                    666: #define        dotoken(requires,shift,bit,type) \
                    667: { \
                    668:                if (sb -> sb_requirements & requires) \
                    669:                    sb -> sb_owned |= bit; \
                    670: }
                    671:                dotokens ();
                    672: #undef dotoken
                    673:                freespkt (s);
                    674:                if ((s = newspkt (SPDU_GTA)) == NULL) {
                    675:                    (void) spktlose (sb -> sb_fd, si, SC_CONGEST, NULLCP,
                    676:                            "out of memory");
                    677:                    break;
                    678:                }
                    679:                if (spkt2sd (s, sb -> sb_fd, 0, si) == NOTOK)
                    680:                    break;
                    681:                freespkt (s);
                    682:                si -> si_type = SI_TOKEN;
                    683:                {
                    684:                    register struct SSAPtoken  *st = &si -> si_token;
                    685: 
                    686:                    st -> st_type = ST_CONTROL;
                    687:                    st -> st_tokens = st -> st_owned = sb -> sb_owned;
                    688:                }
                    689:                return DONE;
                    690: 
                    691:            case SPDU_GTA:
                    692:                if (!(sb -> sb_flags & SB_GTC)) {
                    693:                    freespkt (s);
                    694:                    goto spin;
                    695:                }
                    696:                sb -> sb_flags &= ~SB_GTC;
                    697: spin: ;
                    698:                if (!async || sb -> sb_spdu)
                    699:                    continue;
                    700:                si -> si_type = SI_DATA;
                    701:                {
                    702:                    register struct SSAPdata *sk = &si -> si_data;
                    703: 
                    704:                    bzero ((char *) sk, sizeof *sk);
                    705:                    sk -> sx_qbuf.qb_forw = sk -> sx_qbuf.qb_back =
                    706:                        &sk -> sx_qbuf;
                    707:                }
                    708:                return DONE;
                    709: 
                    710:            case SPDU_MAP:
                    711: #ifdef notdef
                    712:            case SPDU_AE:       /* aka SPDU_MAP */
                    713: #endif
                    714:                if (sb -> sb_V_M != s -> s_map_serial) {
                    715:                    freespkt (s);
                    716:                    goto spin;
                    717:                }
                    718:                if (!(s -> s_mask & SMASK_MAP_SYNC)
                    719:                        || !(s -> s_map_sync & MAP_SYNC_NOEND))
                    720:                    goto spdu_ae;
                    721:                if (!(sb -> sb_flags & SB_Vsc))
                    722:                    sb -> sb_V_A = sb -> sb_V_M;
                    723:                sb -> sb_V_M++;
                    724:                if (sb -> sb_flags & (SB_ED | SB_ERACK)) {
                    725:                    freespkt (s);
                    726:                    goto spin;
                    727:                }
                    728:                if (sb -> sb_requirements & SR_ACTIVITY)
                    729:                    sb -> sb_flags |= SB_Vnextact;
                    730:                sb -> sb_flags |= SB_MAA;
                    731:                si -> si_type = SI_SYNC;
                    732:                {
                    733:                    register struct SSAPsync *sn = &si -> si_sync;
                    734: 
                    735:                    sn -> sn_type = SN_MAJORIND;
                    736:                    sn -> sn_ssn = s -> s_map_serial;
                    737:                    copySPKTdata (s, sn);
                    738:                }
                    739:                freespkt (s);
                    740:                return DONE;
                    741: 
                    742:            case SPDU_MAA:
                    743: #ifdef notdef
                    744:            case SPDU_AEA:      /* aka SPDU_MAA */
                    745: #endif
                    746:                if (sb -> sb_V_M != s -> s_maa_serial + 1) {
                    747:                    freespkt (s);
                    748:                    goto spin;
                    749:                }
                    750:                sb -> sb_V_A = sb -> sb_V_R = sb -> sb_V_M;
                    751:                if (sb -> sb_requirements & SR_ACTIVITY)
                    752:                    if (sb -> sb_flags & SB_Vnextact)
                    753:                        sb -> sb_flags |= SB_Vact;
                    754:                    else
                    755:                        sb -> sb_flags &= ~SB_Vact;
                    756:                sb -> sb_flags &= ~SB_MAP;
                    757:                if (sb -> sb_flags & SB_AE) {
                    758:                    sb -> sb_flags &= ~SB_AE;
                    759:                    si -> si_type = SI_ACTIVITY;
                    760:                    {
                    761:                        register struct SSAPactivity *sv = &si -> si_activity;
                    762: 
                    763:                        sv -> sv_type = SV_ENDCNF;
                    764:                        sv -> sv_ssn = s -> s_maa_serial;
                    765:                        copySPKTdata (s, sv);
                    766:                    }
                    767:                }
                    768:                else {
                    769:                    si -> si_type = SI_SYNC;
                    770:                    {
                    771:                        register struct SSAPsync *sn = &si -> si_sync;
                    772: 
                    773:                        sn -> sn_type = SN_MAJORCNF;
                    774:                        sn -> sn_ssn = s -> s_maa_serial;
                    775:                        copySPKTdata (s, sn);
                    776:                    }
                    777:                }
                    778:                freespkt (s);
                    779:                return DONE;
                    780: 
                    781:            case SPDU_MIP:
                    782:                if (!(sb -> sb_flags & SB_Vsc)) {
                    783:                    sb -> sb_V_A = sb -> sb_V_M;
                    784:                    sb -> sb_flags |= SB_Vsc;
                    785:                }
                    786:                sb -> sb_V_M++;
                    787:                if (sb -> sb_flags & (SB_ED | SB_ERACK)) {
                    788:                    freespkt (s);
                    789:                    goto spin;
                    790:                }
                    791:                si -> si_type = SI_SYNC;
                    792:                {
                    793:                    register struct SSAPsync *sn = &si -> si_sync;
                    794: 
                    795:                    sn -> sn_type = SN_MINORIND;
                    796:                    sn -> sn_options = (s -> s_mask & SMASK_MIP_SYNC)
                    797:                            && (s -> s_mip_sync & MIP_SYNC_NOEXPL)
                    798:                            ? SYNC_NOCONFIRM : SYNC_CONFIRM;
                    799:                    sn -> sn_ssn = s -> s_mip_serial;
                    800:                    copySPKTdata (s, sn);
                    801:                }
                    802:                freespkt (s);
                    803:                return DONE;
                    804: 
                    805:            case SPDU_MIA:
                    806:                if ((sb -> sb_flags & SB_Vsc)
                    807:                        || sb -> sb_V_A > s -> s_mia_serial
                    808:                        || s -> s_mia_serial >= sb -> sb_V_M) {
                    809:                    freespkt (s);
                    810:                    goto spin;
                    811:                }
                    812:                sb -> sb_V_A = s -> s_mia_serial;
                    813:                si -> si_type = SI_SYNC;
                    814:                {
                    815:                    register struct SSAPsync *sn = &si -> si_sync;
                    816: 
                    817:                    sn -> sn_type = SN_MINORCNF;
                    818:                    sn -> sn_ssn = s -> s_mia_serial;
                    819:                    copySPKTdata (s, sn);
                    820:                }
                    821:                freespkt (s);
                    822:                return DONE;
                    823: 
                    824:            case SPDU_RS:
                    825:                if (s -> s_rs_type == SYNC_RESTART
                    826:                        && sb -> sb_V_R > s -> s_rs_serial) {
                    827:                    freespkt (s);
                    828:                    goto spin;
                    829:                }
                    830:                sb -> sb_flags &= ~SB_RS, sb -> sb_flags |= SB_RA;
                    831:                sb -> sb_rs = s -> s_rs_type;
                    832:                sb -> sb_rsn = s -> s_rs_serial;
                    833:                if (s -> s_mask & SMASK_RS_SET)
                    834:                    sb -> sb_rsettings = s -> s_rs_settings;
                    835:                else {
                    836:                    sb -> sb_rsettings = 0;
                    837: #define        dotoken(requires,shift,bit,type) \
                    838: { \
                    839:                    if (sb -> sb_requirements & requires) \
                    840:                        if ((sb -> sb_owned & bit) \
                    841:                                && (sb -> sb_flags & SB_INIT)) \
                    842:                            sb -> sb_rsettings = ST_INIT_VALUE << shift; \
                    843:                        else \
                    844:                            sb -> sb_rsettings = ST_RESP_VALUE << shift; \
                    845: }
                    846:                    dotokens ();
                    847: #undef dotoken
                    848:                }
                    849:                si -> si_type = SI_SYNC;
                    850:                {
                    851:                    register struct SSAPsync *sn = &si -> si_sync;
                    852: 
                    853:                    sn -> sn_type = SN_RESETIND;
                    854:                    sn -> sn_options = sb -> sb_rs;
                    855:                    sn -> sn_ssn = sb -> sb_rsn;
                    856:                    sn -> sn_settings = sb -> sb_rsettings;
                    857:                    copySPKTdata (s, sn);
                    858:                }
                    859:                freespkt (s);
                    860:                return DONE;
                    861: 
                    862:            case SPDU_RA:
                    863:                sb -> sb_flags &= ~SB_RS;
                    864:                sb -> sb_V_A = sb -> sb_V_M = s -> s_ra_serial;
                    865:                if (sb -> sb_rs != SYNC_RESTART)
                    866:                    sb -> sb_V_R = 0;
                    867:                if (s -> s_mask & SMASK_RA_SET)
                    868:                    sb -> sb_rsettings = s -> s_ra_settings;
                    869: #define        dotoken(requires,shift,bit,type) \
                    870: { \
                    871:                if (sb -> sb_requirements & requires) \
                    872:                    switch (sb -> sb_rsettings & (ST_MASK << shift)) { \
                    873:                        dotoken1 (requires,shift,bit,type); \
                    874:  \
                    875:                        dotoken2 (requires,shift,bit,type); \
                    876:                    } \
                    877: }
                    878: #define        dotoken1(requires,shift,bit,type) \
                    879:                        case ST_CALL_VALUE << shift: \
                    880:                            switch (s -> s_ra_settings & (ST_MASK << shift)) { \
                    881:                                case ST_INIT_VALUE: \
                    882:                                    if (sb -> sb_flags & SB_INIT) \
                    883:                                        sb -> sb_owned |= bit; \
                    884:                                    else \
                    885:                                        sb -> sb_owned &= ~bit; \
                    886:                                    break; \
                    887:  \
                    888:                                case ST_RESP_VALUE: \
                    889:                                    if (!(sb -> sb_flags & SB_INIT)) \
                    890:                                        sb -> sb_owned |= bit; \
                    891:                                    else \
                    892:                                        sb -> sb_owned &= ~bit; \
                    893:                                    break; \
                    894:                            } \
                    895:                            break;
                    896: #define        dotoken2(requires,shift,bit,type) \
                    897:                        case ST_INIT_VALUE << shift: \
                    898:                            if (sb -> sb_flags & SB_INIT) \
                    899:                                sb -> sb_owned |= bit; \
                    900:                            else \
                    901:                                sb -> sb_owned &= ~bit; \
                    902:                            break; \
                    903:  \
                    904:                        case ST_RESP_VALUE << shift: \
                    905:                            if (!(sb -> sb_flags & SB_INIT)) \
                    906:                                sb -> sb_owned |= bit; \
                    907:                            else \
                    908:                                sb -> sb_owned &= ~bit; \
                    909:                            break;
                    910:                dotokens ();
                    911: #undef dotoken
                    912: #undef dotoken1
                    913: #undef dotoken2
                    914:                si -> si_type = SI_SYNC;
                    915:                {
                    916:                    register struct SSAPsync *sn = &si -> si_sync;
                    917: 
                    918:                    sn -> sn_type = SN_RESETCNF;
                    919:                    sn -> sn_ssn = sb -> sb_V_M;
                    920:                    sn -> sn_settings = sb -> sb_rsettings;
                    921:                    copySPKTdata (s, sn);
                    922:                }
                    923:                freespkt (s);
                    924:                return DONE;
                    925: 
                    926:            case SPDU_PR: 
                    927:                switch (s -> s_pr_type) {
                    928:                    case PR_MAA: 
                    929:                        sb -> sb_pr = SPDU_MAA;
                    930:                        break;
                    931:                    case PR_RS: 
                    932:                        sb -> sb_flags &= ~(SB_ED | SB_ERACK);
                    933:                        sb -> sb_pr = SPDU_RS;
                    934:                        break;
                    935:                    case PR_RA: 
                    936:                        sb -> sb_pr = SPDU_RA;
                    937:                        break;
                    938:                    case PR_AB: 
                    939:                        sb -> sb_pr = SPDU_AB;
                    940:                        break;
                    941:                }
                    942:                freespkt (s);
                    943:                goto spin;
                    944: 
                    945:            case SPDU_ER:       /* this implementation never generates these */
                    946:                sb -> sb_flags |= SB_ERACK;
                    947:                si -> si_type = SI_REPORT;
                    948:                {
                    949:                    register struct SSAPreport *sp = &si -> si_report;
                    950: 
                    951:                    sp -> sp_peer = 0;
                    952:                    sp -> sp_reason = SP_PROTOCOL;
                    953:                }
                    954:                freespkt (s);
                    955:                return DONE;
                    956: 
                    957:            case SPDU_ED:
                    958:                if (sb -> sb_owned & ST_DAT_TOKEN)
                    959:                    sb -> sb_flags |= SB_EDACK;
                    960:                si -> si_type = SI_REPORT;
                    961:                {
                    962:                    register struct SSAPreport *sp = &si -> si_report;
                    963: 
                    964:                    sp -> sp_peer = 1;
                    965:                    sp -> sp_reason = s -> s_ed_reason;
                    966:                    copySPKTdata (s, sp);
                    967:                }
                    968:                freespkt (s);
                    969:                return DONE;
                    970: 
                    971:            case SPDU_AS:
                    972:                if (sb -> sb_flags & SB_Vact) {
                    973:                    freespkt (s);
                    974:                    goto spin;
                    975:                }
                    976:                sb -> sb_V_A = sb -> sb_V_M = sb -> sb_V_R = 1;
                    977:                sb -> sb_flags |= SB_Vact;
                    978:                si -> si_type = SI_ACTIVITY;
                    979:                {
                    980:                    register struct SSAPactivity *sv = &si -> si_activity;
                    981: 
                    982:                    sv -> sv_type = SV_START;
                    983:                    sv -> sv_id = s -> s_as_id; /* struct copy */
                    984:                    copySPKTdata (s, sv);
                    985:                }
                    986:                freespkt (s);
                    987:                return DONE;
                    988: 
                    989:            case SPDU_AR:
                    990:                if (sb -> sb_flags & SB_Vact) {
                    991:                    freespkt (s);
                    992:                    goto spin;
                    993:                }
                    994:                sb -> sb_V_A = sb -> sb_V_M = s -> s_ar_serial + 1;
                    995:                sb -> sb_V_R = 1;
                    996:                sb -> sb_flags |= SB_Vact;
                    997:                si -> si_type = SI_ACTIVITY;
                    998:                {
                    999:                    register struct SSAPactivity *sv = &si -> si_activity;
                   1000: 
                   1001:                    sv -> sv_type = SV_RESUME;
                   1002:                    sv -> sv_id = s -> s_ar_id; /* struct copy */
                   1003:                    sv -> sv_oid = s -> s_ar_oid;       /* struct copy */
                   1004:                    if (s -> s_mask & SMASK_AR_REF)     /* struct copy */
                   1005:                        sv -> sv_connect = s -> s_ar_reference;
                   1006:                    sv -> sv_ssn = s -> s_ar_serial;
                   1007:                    copySPKTdata (s, sv);
                   1008:                }
                   1009:                freespkt (s);
                   1010:                return DONE;
                   1011: 
                   1012:            case SPDU_AD:
                   1013: spdu_ai: ;
                   1014:                if (!(sb -> sb_flags & SB_Vact)) {
                   1015:                    freespkt (s);
                   1016:                    goto spin;
                   1017:                }
                   1018:                sb -> sb_flags &= ~(SB_RS | SB_RA), sb -> sb_flags |= SB_AIA;
                   1019:                sb -> sb_rs = SYNC_INTR;
                   1020:                si -> si_type = SI_ACTIVITY;
                   1021:                {
                   1022:                    register struct SSAPactivity *sv = &si -> si_activity;
                   1023: 
                   1024:                    sv -> sv_type = s -> s_code == SPDU_AI ? SV_INTRIND
                   1025:                            : SV_DISCIND;
                   1026:                    sv -> sv_reason = s -> s_ai_reason;
                   1027:                }
                   1028:                freespkt (s);
                   1029:                return DONE;
                   1030: 
                   1031:            case SPDU_AA:
                   1032: #ifdef notdef
                   1033:            case SPDU_AIA:      /* aka SPDU_AA */
                   1034: #endif
                   1035:                if (s -> s_mask & SMASK_SPDU_AA) {
                   1036:                    freespkt (s);
                   1037:                    goto spin;
                   1038:                }               /* else fall */
                   1039:            case SPDU_ADA:
                   1040:                if (!(sb -> sb_flags & SB_Vact)) {
                   1041:                    freespkt (s);
                   1042:                    goto spin;
                   1043:                }
                   1044:                sb -> sb_flags &= ~(SB_AI | SB_Vact);
                   1045: #define        dotoken(requires,shift,bit,type) \
                   1046: { \
                   1047:                if (sb -> sb_requirements & requires) \
                   1048:                    sb -> sb_owned |= bit; \
                   1049: }
                   1050:                dotokens ();
                   1051: #undef dotoken
                   1052:                si -> si_type = SI_ACTIVITY;
                   1053:                {
                   1054:                    register struct SSAPactivity *sv = &si -> si_activity;
                   1055: 
                   1056:                    sv -> sv_type = s -> s_code == SPDU_AIA ? SV_INTRCNF
                   1057:                                        : SV_DISCCNF;
                   1058:                }
                   1059:                freespkt (s);
                   1060:                return DONE;            
                   1061: 
                   1062: spdu_ae: ;
                   1063:                if (!(sb -> sb_flags & SB_Vsc))
                   1064:                    sb -> sb_V_A = sb -> sb_V_M;
                   1065:                sb -> sb_V_M++;
                   1066:                sb -> sb_flags &= ~SB_Vnextact;
                   1067:                sb -> sb_flags |= SB_MAA | SB_AE;
                   1068:                si -> si_type = SI_ACTIVITY;
                   1069:                {
                   1070:                    register struct SSAPactivity *sv = &si -> si_activity;
                   1071: 
                   1072:                    sv -> sv_type = SV_ENDIND;
                   1073:                    sv -> sv_ssn = s -> s_map_serial;
                   1074:                    copySPKTdata (s, sv);
                   1075:                }
                   1076:                freespkt (s);
                   1077:                return DONE;
                   1078: 
                   1079:            case SPDU_FN: 
                   1080:                sb -> sb_flags |= SB_FINN;
                   1081:                si -> si_type = SI_FINISH;
                   1082:                {
                   1083:                    register struct SSAPfinish *sf = &si -> si_finish;
                   1084: 
                   1085:                    copySPKTdata (s, sf);
                   1086:                }
                   1087:                freespkt (s);
                   1088:                return DONE;
                   1089: 
                   1090:            case SPDU_AB: 
                   1091:                if (!(s -> s_mask & SMASK_SPDU_AB))
                   1092:                    goto spdu_ai;
                   1093:                sb -> sb_flags &= ~(SB_ED | SB_EDACK | SB_ERACK);
                   1094:                si -> si_type = SI_ABORT;
                   1095:                {
                   1096:                    register struct SSAPabort  *sa = &si -> si_abort;
                   1097: 
                   1098:                    if (!(sa -> sa_peer = (s -> s_ab_disconnect & AB_DISC_USER)
                   1099:                                ? 1 : 0))
                   1100:                        sa -> sa_reason = SC_ABORT;
                   1101:                    sa -> sa_info = s -> s_udata, sa -> sa_cc = s -> s_ulen;
                   1102:                    sa -> sa_realinfo = s -> s_udata, s -> s_udata = NULL;
                   1103:                }
                   1104: #ifdef notdef          /* only if transport connection is to be re-used */
                   1105:                freespkt (s);
                   1106:                if (s = newspkt (SPDU_AA)) {
                   1107:                    s -> s_mask |= SMASK_SPDU_AA;
                   1108:                    (void) spkt2sd (s, sb -> sb_fd, sb -> sb_flags & SB_EXPD
                   1109:                                ? 1 : 0, (struct SSAPindication *) 0);
                   1110:                }
                   1111: #endif
                   1112:                break;
                   1113: 
                   1114:            default: 
                   1115:                (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
                   1116:                        "session protocol mangled: not expecting 0x%x",
                   1117:                        s -> s_code);
                   1118:                break;
                   1119:        }
                   1120:        break;
                   1121:     }
                   1122: 
                   1123:     if (si -> si_abort.sa_reason == SC_TIMER)
                   1124:        return NOTOK;
                   1125: 
                   1126: out: ;
                   1127:     freespkt (s);
                   1128:     freesblk (sb);
                   1129: 
                   1130:     return NOTOK;
                   1131: }
                   1132: 
                   1133: /*  */
                   1134: 
                   1135: /* a decision tree (ugh!) */
                   1136: 
                   1137: int    SDoCollideAux (init, localop, localssn, remoteop, remotessn)
                   1138: int     init,
                   1139:        localop,
                   1140:         remoteop;
                   1141: long    localssn,
                   1142:         remotessn;
                   1143: {
                   1144:     SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
                   1145:          ("collide: local<%d,%ld,%s> remote<%d,%ld,%s>",
                   1146:           localop, localssn, init ? "initiator" : "responder",
                   1147:           remoteop, remotessn, init ? "responder" : "initiator"));
                   1148: 
                   1149:     if (localop == SYNC_DISC)
                   1150:        return OK;
                   1151: 
                   1152:     if (remoteop == SYNC_DISC)
                   1153:        return NOTOK;
                   1154: 
                   1155:     if (localop == SYNC_INTR)
                   1156:        return OK;
                   1157: 
                   1158:     if (remoteop == SYNC_DISC)
                   1159:        return NOTOK;
                   1160: 
                   1161:     if (localop == SYNC_ABANDON) {
                   1162:        if (remoteop != SYNC_ABANDON)
                   1163:            return OK;
                   1164: 
                   1165:        return (init ? OK : NOTOK);
                   1166:     }
                   1167:     else
                   1168:        if (remoteop == SYNC_ABANDON)
                   1169:            return NOTOK;
                   1170: 
                   1171:     if (localop == SYNC_SET) {
                   1172:        if (remoteop != SYNC_SET)
                   1173:            return OK;
                   1174: 
                   1175:        return (init ? OK : NOTOK);
                   1176:     }
                   1177:     else
                   1178:        if (remoteop == SYNC_SET)
                   1179:            return NOTOK;
                   1180: 
                   1181:     if (localssn == remotessn)
                   1182:        return (init ? OK : NOTOK);
                   1183: 
                   1184:     return (localssn < remotessn ? OK : NOTOK);
                   1185: }
                   1186: 
                   1187: /*    define vectors for INDICATION events */
                   1188: 
                   1189: int    SSetIndications (sd, data, tokens, sync, activity, report, finish,
                   1190:                abort, si)
                   1191: int    sd;
                   1192: IFP    data,   
                   1193:        tokens,
                   1194:        sync,
                   1195:        activity,
                   1196:        report,
                   1197:        finish,
                   1198:        abort;
                   1199: struct SSAPindication *si;
                   1200: {
                   1201:     SBV     smask;
                   1202:     register struct ssapblk *sb;
                   1203:     struct TSAPdisconnect   tds;
                   1204:     register struct TSAPdisconnect *td = &tds;
                   1205: 
                   1206:     if (data || tokens || sync || activity || report || finish || abort) {
                   1207:        missingP (data);
                   1208:        missingP (tokens);
                   1209:        missingP (sync);
                   1210:        missingP (activity);
                   1211:        missingP (report);
                   1212:        missingP (finish);
                   1213:        missingP (abort);
                   1214:     }
                   1215: 
                   1216:     smask = sigioblock ();
                   1217: 
                   1218:     ssapPsig (sb, sd);
                   1219: 
                   1220:     if (TSetIndications (sb -> sb_fd, TDATAser, TDISCser, td) == NOTOK)
                   1221:        if (td -> td_reason == DR_WAITING)
                   1222:            return ssaplose (si, SC_WAITING, NULLCP, NULLCP);
                   1223:        else
                   1224:            return ts2sslose (si, "TSetIndications", td);
                   1225: 
                   1226:     if (sb -> sb_DataIndication = data)
                   1227:        sb -> sb_flags |= SB_ASYN;
                   1228:     else
                   1229:        sb -> sb_flags &= ~SB_ASYN;
                   1230:     sb -> sb_TokenIndication = tokens;
                   1231:     sb -> sb_SyncIndication = sync;
                   1232:     sb -> sb_ActivityIndication = activity;
                   1233:     sb -> sb_ReportIndication = report;
                   1234:     sb -> sb_ReleaseIndication = finish;
                   1235:     sb -> sb_AbortIndication = abort;
                   1236: 
                   1237:     (void) sigiomask (smask);
                   1238: 
                   1239:     return OK;
                   1240: }
                   1241: 
                   1242: /*    TSAP interface */
                   1243: 
                   1244: int    spkt2sd (s, sd, expedited, si)
                   1245: register struct ssapkt *s;
                   1246: int     sd,
                   1247:         expedited;
                   1248: register struct SSAPindication *si;
                   1249: {
                   1250:     int     i,
                   1251:             len,
                   1252:             result;
                   1253:     char   *base,
                   1254:            *dp;
                   1255:     struct TSAPdisconnect   tds;
                   1256:     register struct TSAPdisconnect *td = &tds;
                   1257: 
                   1258:     if (expedited)
                   1259:        s -> s_mask |= SMASK_SPDU_EXPD;
                   1260:     if (spkt2tsdu (s, &base, &len) == NOTOK) {
                   1261:        (void) ssaplose (si, s -> s_errno, NULLCP, NULLCP);
                   1262:        return NOTOK;
                   1263:     }
                   1264:     if (s -> s_code == SPDU_EX) {/* only SX_EXSIZE octets, so no big deal... */
                   1265:        if (s -> s_udata) {
                   1266:            if ((dp = realloc (base, (unsigned) (i = len + s -> s_ulen)))
                   1267:                    == NULL) {
                   1268:                free (base);
                   1269:                (void) ssaplose (si, SC_CONGEST, NULLCP, NULLCP);
                   1270:                return NOTOK;
                   1271:            }
                   1272:            bcopy (s -> s_udata, (base = dp) + len, s -> s_ulen);
                   1273:            len = i;
                   1274:        }
                   1275:     }
                   1276: 
                   1277:     if (len > TX_SIZE)
                   1278:        expedited = 0;
                   1279:     if ((result = expedited ? TExpdRequest (sd, base, len, td)
                   1280:                : TDataRequest (sd, base, len, td)) == NOTOK)
                   1281:        (void) ts2sslose (si, expedited ? "TExpdRequest" : "TDataRequest", td);
                   1282: 
                   1283:     if (base)
                   1284:        free (base);
                   1285: 
                   1286:     return result;
                   1287: }
                   1288: 
                   1289: /*  */
                   1290: 
                   1291: struct ssapkt   *sb2spkt (sb, si, secs, ty)
                   1292: register struct ssapblk *sb;
                   1293: register struct SSAPindication *si;
                   1294: int     secs;
                   1295: register struct TSAPdata   *ty;
                   1296: {
                   1297:     int     cc;
                   1298:     register struct ssapkt   *s,
                   1299:                             *p;
                   1300:     struct TSAPdata txs;
                   1301:     register struct TSAPdata   *tx = &txs;
                   1302:     struct TSAPdisconnect   tds;
                   1303:     register struct TSAPdisconnect *td = &tds;
                   1304: 
                   1305:     if (sb -> sb_pr == SPDU_PR && sb -> sb_xspdu) {
                   1306:        SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
                   1307:              ("returning XSDU buffered during preparation"));
                   1308:        s = sb -> sb_xspdu;
                   1309:        sb -> sb_xspdu = NULL;
                   1310: 
                   1311:        return s;
                   1312:     }
                   1313: 
                   1314:     if (sb -> sb_spdu) {       /* get previous category 0 SPDU */
                   1315:        SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
                   1316:              ("returning category 0 SPDU previously buffered"));
                   1317:        s = sb -> sb_spdu;
                   1318:        sb -> sb_spdu = NULL;
                   1319: 
                   1320:        return s;
                   1321:     }
                   1322: 
                   1323:     if (ty) {
                   1324:        *tx = *ty;              /* struct copy */
                   1325:        tx -> tx_qbuf.qb_forw -> qb_back =
                   1326:                tx -> tx_qbuf.qb_back -> qb_forw = &tx -> tx_qbuf;
                   1327:        bzero ((char *) ty, sizeof *ty);
                   1328:        ty -> tx_qbuf.qb_forw = ty -> tx_qbuf.qb_back = &ty -> tx_qbuf;
                   1329:     }
                   1330:     else
                   1331:        if (TReadRequest (sb -> sb_fd, tx, secs, td) == NOTOK) {
                   1332:            if (td -> td_reason != DR_TIMER)
                   1333:                (void) ts2sslose (si, "TReadRequest", td);
                   1334:            else
                   1335:                (void) ssaplose (si, SC_TIMER, NULLCP, NULLCP);
                   1336: 
                   1337:            return NULL;
                   1338:        }
                   1339: 
                   1340:     DLOG (ssap_log, LLOG_DEBUG, ("read TSDU, size %d", tx -> tx_cc));
                   1341: 
                   1342:     if ((s = tsdu2spkt (&tx -> tx_qbuf, tx -> tx_cc, (cc = 1, &cc))) == NULL
                   1343:            || s -> s_errno != SC_ACCEPT) {
                   1344:        (void) ssaplose (si, s ? s -> s_errno : SC_CONGEST, NULLCP, NULLCP);
                   1345: bad1: ;
                   1346:        freespkt (s);
                   1347:        TXFREE (tx);
                   1348:        return NULL;
                   1349:     }
                   1350: 
                   1351:     if (tx -> tx_expedited)
                   1352:        s -> s_mask |= SMASK_SPDU_EXPD;
                   1353:     tx -> tx_cc -= cc;
                   1354: 
                   1355:     switch (s -> s_code) {
                   1356:        case SPDU_GT:           /* category 0 SPDUs */
                   1357:        case SPDU_PT: 
                   1358:            if (tx -> tx_cc <= 0)
                   1359:                goto simple;
                   1360:            break;
                   1361: 
                   1362:        case SPDU_EX:           /* category 1 SPDUs with user data */
                   1363:        case SPDU_TD: 
                   1364:            if (tx -> tx_qbuf.qb_forw != &tx -> tx_qbuf) {
                   1365:                s -> s_qbuf = tx -> tx_qbuf;/* struct copy */
                   1366:                s -> s_qbuf.qb_forw -> qb_back =
                   1367:                        s -> s_qbuf.qb_back -> qb_forw = &s -> s_qbuf;
                   1368:                s -> s_qlen = tx -> tx_cc;
                   1369:            }
                   1370:            return s;
                   1371: 
                   1372:        case SPDU_CN:           /* category 1 SPDUs */
                   1373:        case SPDU_AC: 
                   1374:        case SPDU_RF: 
                   1375:        case SPDU_FN: 
                   1376:        case SPDU_DN: 
                   1377:        case SPDU_NF: 
                   1378:        case SPDU_AB: 
                   1379:        case SPDU_AA: 
                   1380:        case SPDU_GTC: 
                   1381:        case SPDU_GTA: 
                   1382:        case SPDU_PR: 
                   1383:            if (tx -> tx_cc <= 0) {
                   1384:        simple: ;
                   1385:                TXFREE (tx);
                   1386:                return s;
                   1387:            }
                   1388:            (void) ssaplose (si, SC_PROTOCOL, NULLCP,
                   1389:                    "session protocol mangled: not expecting user information after 0x%x (%d bytes)",
                   1390:                    s -> s_code, tx -> tx_cc);
                   1391:            goto bad1;
                   1392: 
                   1393:        default:
                   1394:            (void) ssaplose (si, SC_PROTOCOL, NULLCP,
                   1395:                    "session protocol mangled: not expecting 0x%x",
                   1396:                    s -> s_code);
                   1397:            goto bad1;
                   1398:     }
                   1399: 
                   1400:     sb -> sb_spdu = p = s;             /* save category 0 SPDU */
                   1401: 
                   1402:     if ((s = tsdu2spkt (&tx -> tx_qbuf, tx -> tx_cc, (cc = 0, &cc))) == NULL
                   1403:            || s -> s_errno != SC_ACCEPT) {
                   1404:        (void) ssaplose (si, s ? s -> s_errno : SC_CONGEST, NULLCP, NULLCP);
                   1405: bad2:  ;
                   1406:        freespkt (s);
                   1407:        freespkt (p);
                   1408:        sb -> sb_spdu = NULL;
                   1409:        TXFREE (tx);
                   1410:        return NULL;
                   1411:     }
                   1412: 
                   1413:     if (tx -> tx_expedited)
                   1414:        s -> s_mask |= SMASK_SPDU_EXPD;
                   1415:     tx -> tx_cc -= cc;
                   1416: 
                   1417:     switch ((p -> s_code) << 8 | s -> s_code) {
                   1418:        case (SPDU_GT << 8) | SPDU_DT:  /* category 2 SPDUs with user data */
                   1419:            if (tx -> tx_qbuf.qb_forw != &tx -> tx_qbuf) {
                   1420:                s -> s_qbuf = tx -> tx_qbuf;/* struct copy */
                   1421:                s -> s_qbuf.qb_forw -> qb_back =
                   1422:                        s -> s_qbuf.qb_back -> qb_forw = &s -> s_qbuf;
                   1423:                s -> s_qlen = tx -> tx_cc;
                   1424:            }
                   1425:            break;
                   1426: 
                   1427:        case (SPDU_GT << 8) | SPDU_MIP: /* category 2 SPDUs */
                   1428:        case (SPDU_PT << 8) | SPDU_MIA: 
                   1429:        case (SPDU_GT << 8) | SPDU_MAP: 
                   1430:        case (SPDU_PT << 8) | SPDU_MAA: 
                   1431:        case (SPDU_GT << 8) | SPDU_RS: 
                   1432:        case (SPDU_PT << 8) | SPDU_RA: 
                   1433:        case (SPDU_GT << 8) | SPDU_AS: 
                   1434:        case (SPDU_GT << 8) | SPDU_AR: 
                   1435:        case (SPDU_GT << 8) | SPDU_AD: 
                   1436:        case (SPDU_PT << 8) | SPDU_ADA: 
                   1437:        case (SPDU_GT << 8) | SPDU_AI:
                   1438:        case (SPDU_PT << 8) | SPDU_AIA: 
                   1439: #ifdef notdef
                   1440:        case (SPDU_GT << 8) | SPDU_AE:  /* aka SPDU_MAP */
                   1441:        case (SPDU_PT << 8) | SPDU_AEA: /* aka SPDU_MAA */
                   1442: #endif
                   1443:        case (SPDU_GT << 8) | SPDU_CD: 
                   1444:        case (SPDU_PT << 8) | SPDU_CDA: 
                   1445:        case (SPDU_PT << 8) | SPDU_ER: 
                   1446:        case (SPDU_PT << 8) | SPDU_ED: 
                   1447:            if (tx -> tx_cc <= 0) {
                   1448:                TXFREE (tx);
                   1449:                break;
                   1450:            }
                   1451:            (void) ssaplose (si, SC_PROTOCOL, NULLCP,
                   1452:                    "session protocol mangled: not expecting user information after 0x%x (%d bytes)",
                   1453:                    s -> s_code, tx -> tx_cc);
                   1454:                goto bad2;
                   1455: 
                   1456:        default: 
                   1457:            (void) ssaplose (si, SC_PROTOCOL, NULLCP,
                   1458:                    "session protocol mangled: not expecting 0x%x to be concatenated after 0x%x",
                   1459:                    s -> s_code, p -> s_code);
                   1460:            goto bad2;
                   1461:     }
                   1462: 
                   1463:     switch (s -> s_code) {
                   1464:        default:
                   1465:            if (p -> s_code == SPDU_GT) {
                   1466:                if ((p -> s_mask & SMASK_GT_TOKEN) && p -> s_gt_token)
                   1467:                    break;
                   1468:            }
                   1469:            else {
                   1470:                if (((p -> s_mask & SMASK_PT_TOKEN) && p -> s_pt_token)
                   1471:                        || p -> s_ulen)
                   1472:                    break;
                   1473:            }                   /* fall... */
                   1474: 
                   1475:        case SPDU_RS: 
                   1476:        case SPDU_AD: 
                   1477:        case SPDU_AI: 
                   1478:        case SPDU_CD: 
                   1479:            freespkt (p);
                   1480:            sb -> sb_spdu = NULL;
                   1481:            break;
                   1482:     }
                   1483: 
                   1484:     return s;
                   1485: }
                   1486: 
                   1487: /*  */
                   1488: 
                   1489: static int  TDATAser (sd, tx)
                   1490: int     sd;
                   1491: register struct TSAPdata   *tx;
                   1492: {
                   1493:     IFP            abort;
                   1494:     register struct ssapblk *sb;
                   1495:     struct SSAPdata sxs;
                   1496:     register struct SSAPdata   *sx = &sxs;
                   1497:     struct SSAPindication   sis;
                   1498:     register struct SSAPindication *si = &sis;
                   1499:     register struct SSAPabort  *sa = &si -> si_abort;
                   1500: 
                   1501:     if ((sb = findsblk (sd)) == NULL)
                   1502:        return;
                   1503: 
                   1504:     abort = sb -> sb_AbortIndication;
                   1505: 
                   1506:     for (;; tx = NULLTX) {
                   1507:        switch (SReadRequestAux (sb, sx, OK, si, 1, tx)) {
                   1508:            case NOTOK: 
                   1509:                (*abort) (sd, sa);
                   1510:                return;
                   1511: 
                   1512:            case OK: 
                   1513:                (*sb -> sb_DataIndication) (sd, sx);
                   1514:                break;
                   1515: 
                   1516:            case DONE: 
                   1517:                switch (si -> si_type) {
                   1518:                    case SI_TOKEN: 
                   1519:                        (*sb -> sb_TokenIndication) (sd, &si -> si_token);
                   1520:                        break;
                   1521: 
                   1522:                    case SI_SYNC: 
                   1523:                        (*sb -> sb_SyncIndication) (sd, &si -> si_sync);
                   1524:                        break;
                   1525: 
                   1526:                    case SI_ACTIVITY: 
                   1527:                        (*sb -> sb_ActivityIndication) (sd, &si -> si_activity);
                   1528:                        break;
                   1529: 
                   1530:                    case SI_REPORT: 
                   1531:                        (*sb -> sb_ReportIndication) (sd, &si -> si_report);
                   1532:                        break;
                   1533: 
                   1534:                    case SI_FINISH: 
                   1535:                        (*sb -> sb_ReleaseIndication) (sd, &si -> si_finish);
                   1536:                        break;
                   1537: 
                   1538:                    case SI_DATA: /* partially assembled (T)SSDU */
                   1539:                        break;
                   1540:                }
                   1541:                break;
                   1542:        }
                   1543: 
                   1544:        if (sb -> sb_spdu == NULL)
                   1545:            break;
                   1546:     }
                   1547: }
                   1548: 
                   1549: /*  */
                   1550: 
                   1551: static int TDISCser (sd, td)
                   1552: int    sd;
                   1553: register struct TSAPdisconnect *td;
                   1554: {
                   1555:     IFP            abort;
                   1556:     register struct ssapblk *sb;
                   1557:     struct SSAPindication sis;
                   1558:     register struct SSAPindication *si = &sis;
                   1559: 
                   1560:     if ((sb = findsblk (sd)) == NULL)
                   1561:        return;
                   1562: 
                   1563:     (void) ts2sslose (si, NULLCP, td);
                   1564: 
                   1565:     abort = sb -> sb_AbortIndication;
                   1566: 
                   1567:     sb -> sb_fd = NOTOK;
                   1568:     (void) freesblk (sb);
                   1569: 
                   1570:     (*abort) (sd, &si -> si_abort);
                   1571: }
                   1572: 
                   1573: /*  */
                   1574: 
                   1575: int    ts2sslose (si, event, td)
                   1576: register struct SSAPindication *si;
                   1577: char   *event;
                   1578: register struct TSAPdisconnect *td;
                   1579: {
                   1580:     int     reason;
                   1581:     char   *cp,
                   1582:             buffer[BUFSIZ];
                   1583: 
                   1584:     if (event)
                   1585:        SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
                   1586:              (td -> td_cc > 0 ? "%s: %s [%*.*s]": "%s: %s", event,
                   1587:               TErrString (td -> td_reason), td -> td_cc, td -> td_cc,
                   1588:               td -> td_data));
                   1589: 
                   1590:     cp = "";
                   1591:     switch (td -> td_reason) {
                   1592:        case DR_REMOTE: 
                   1593:        case DR_CONGEST: 
                   1594:            reason = SC_CONGEST;
                   1595:            break;
                   1596: 
                   1597:        case DR_SESSION: 
                   1598:        case DR_ADDRESS: 
                   1599:            reason = SC_ADDRESS;
                   1600:            break;
                   1601: 
                   1602:        case DR_REFUSED:
                   1603:            reason = SC_REFUSED;
                   1604:            break;
                   1605: 
                   1606:        default: 
                   1607:            (void) sprintf (cp = buffer, " (%s at transport)",
                   1608:                    TErrString (td -> td_reason));
                   1609:        case DR_NETWORK:
                   1610:            reason = SC_TRANSPORT;
                   1611:            break;
                   1612:     }
                   1613: 
                   1614:     if (td -> td_cc > 0)
                   1615:        return ssaplose (si, reason, NULLCP, "%*.*s%s",
                   1616:                td -> td_cc, td -> td_cc, td -> td_data, cp);
                   1617:     else
                   1618:        return ssaplose (si, reason, NULLCP, "%s", *cp ? cp + 1 : cp);
                   1619: }
                   1620: 
                   1621: /*    INTERNAL */
                   1622: 
                   1623: struct ssapblk  *newsblk () {
                   1624:     register struct ssapblk *sb;
                   1625: 
                   1626:     sb = (struct ssapblk   *) calloc (1, sizeof *sb);
                   1627:     if (sb == NULL)
                   1628:        return NULL;
                   1629: 
                   1630:     sb -> sb_fd = NOTOK;
                   1631:     sb -> sb_qbuf.qb_forw = sb -> sb_qbuf.qb_back = &sb -> sb_qbuf;
                   1632:     sb -> sb_pr = SPDU_PR;
                   1633: 
                   1634:     if (once_only == 0) {
                   1635:        SHead -> sb_forw = SHead -> sb_back = SHead;
                   1636:        once_only++;
                   1637:     }
                   1638: 
                   1639:     insque (sb, SHead -> sb_back);
                   1640: 
                   1641:     return sb;
                   1642: }
                   1643: 
                   1644: 
                   1645: int    freesblk (sb)
                   1646: register struct ssapblk *sb;
                   1647: {
                   1648:     if (sb == NULL)
                   1649:        return;
                   1650: 
                   1651:     if (sb -> sb_fd != NOTOK) {
                   1652:        struct TSAPdata         txs;
                   1653:        struct TSAPdisconnect   tds;
                   1654: 
                   1655:                                /* SunLink says this is proper behavior...
                   1656:                                   using NOTOK, I've changed it to 10 secs */
                   1657:        if (sb -> sb_flags & SB_FINN)
                   1658:            while (TReadRequest (sb -> sb_fd, &txs, 10, &tds) != NOTOK) {
                   1659:                TXFREE (&txs);
                   1660:            }
                   1661: 
                   1662:        (void) TDiscRequest (sb -> sb_fd, NULLCP, 0, &tds);
                   1663:     }
                   1664: 
                   1665:     if (sb -> sb_retry) {
                   1666:        sb -> sb_retry -> s_mask &= ~SMASK_UDATA_PGI;
                   1667:        sb -> sb_retry -> s_udata = NULL, sb -> sb_retry -> s_ulen = 0;
                   1668:        freespkt (sb -> sb_retry);
                   1669:     }
                   1670: 
                   1671:     if (sb -> sb_xspdu)
                   1672:        freespkt (sb -> sb_xspdu);
                   1673:     if (sb -> sb_spdu)
                   1674:        freespkt (sb -> sb_spdu);
                   1675: 
                   1676:     QBFREE (&sb -> sb_qbuf);
                   1677: 
                   1678:     remque (sb);
                   1679: 
                   1680:     free ((char *) sb);
                   1681: }
                   1682: 
                   1683: /*  */
                   1684: 
                   1685: struct ssapblk   *findsblk (sd)
                   1686: register int sd;
                   1687: {
                   1688:     register struct ssapblk *sb;
                   1689: 
                   1690:     if (once_only == 0)
                   1691:        return NULL;
                   1692: 
                   1693:     for (sb = SHead -> sb_forw; sb != SHead; sb = sb -> sb_forw)
                   1694:        if (sb -> sb_fd == sd)
                   1695:            return sb;
                   1696: 
                   1697:     return NULL;
                   1698: }

unix.superglobalmegacorp.com

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