Annotation of 43BSDReno/contrib/isode-beta/quipu/dsa_chain.c, revision 1.1

1.1     ! root        1: /* dsa_chain.c - take referral and chain if allowed */
        !             2: 
        !             3: #ifndef lint
        !             4: static char *rcsid = "$Header: /f/osi/quipu/RCS/dsa_chain.c,v 7.3 90/07/09 14:45:58 mrose Exp $";
        !             5: #endif
        !             6: 
        !             7: /*
        !             8:  * $Header: /f/osi/quipu/RCS/dsa_chain.c,v 7.3 90/07/09 14:45:58 mrose Exp $
        !             9:  *
        !            10:  *
        !            11:  * $Log:       dsa_chain.c,v $
        !            12:  * Revision 7.3  90/07/09  14:45:58  mrose
        !            13:  * sync
        !            14:  * 
        !            15:  * Revision 7.2  89/12/19  16:20:26  mrose
        !            16:  * sync
        !            17:  * 
        !            18:  * Revision 7.1  89/11/27  10:30:12  mrose
        !            19:  * sync
        !            20:  * 
        !            21:  * Revision 7.0  89/11/23  22:17:21  mrose
        !            22:  * Release 6.0
        !            23:  * 
        !            24:  */
        !            25: 
        !            26: /*
        !            27:  *                                NOTICE
        !            28:  *
        !            29:  *    Acquisition, use, and distribution of this module and related
        !            30:  *    materials are subject to the restrictions of a license agreement.
        !            31:  *    Consult the Preface in the User's Manual for the full terms of
        !            32:  *    this agreement.
        !            33:  *
        !            34:  */
        !            35: 
        !            36: 
        !            37: #include "acsap.h"
        !            38: #include "quipu/util.h"
        !            39: #include "quipu/connection.h"
        !            40: 
        !            41: extern LLog * log_dsap;
        !            42: 
        !            43: extern int dn_print ();
        !            44: extern char    * mydsaname;
        !            45: extern DN        mydsadn;
        !            46: extern int       no_dsp_chain;
        !            47: 
        !            48: struct oper_act        * task2oper();
        !            49: struct di_block        * di_alloc();
        !            50: struct di_block        * select_refer_dsa();
        !            51: struct connection      * conn_alloc();
        !            52: struct oper_act * oper_alloc();
        !            53: struct PSAPaddr        * psap_cpy();
        !            54: struct access_point *ap_cpy ();
        !            55: 
        !            56: struct connection      * make_conn_block(name, addr, conn_ctx)
        !            57: DN                       name;
        !            58: struct PSAPaddr                * addr;
        !            59: char                     conn_ctx;
        !            60: {
        !            61:     struct connection  * cn;
        !            62: 
        !            63:     struct TSAPaddr *tb;
        !            64:     struct TSAPaddr *ta;
        !            65:     struct NSAPaddr *na;
        !            66:     struct NSAPaddr *nb;
        !            67:     extern struct PSAPaddr * mydsaaddr;
        !            68:     int x,y;
        !            69:     char onnet = FALSE;
        !            70: 
        !            71:     /*
        !            72:     * Set up a new connection block and add it to the list.
        !            73:     */
        !            74: 
        !            75:     if(dn_cmp(name, mydsadn) == 0)
        !            76:     {
        !            77:        LLOG(log_dsap, LLOG_FATAL, ("Trying to connect to self :-)"));
        !            78:        return(NULLCONN);
        !            79:     }
        !            80: 
        !            81:     /* see if on the appropriate net */
        !            82:     ta = & (addr->pa_addr.sa_addr);
        !            83:     tb = & (mydsaaddr->pa_addr.sa_addr);
        !            84: 
        !            85:     /* compare ta and tb to see if they have a network in common */
        !            86:     for (na=ta->ta_addrs , x = ta->ta_naddr - 1 ;
        !            87:                x >= 0;
        !            88:                na++, x-- ) {
        !            89:        for (nb=tb->ta_addrs , y = tb->ta_naddr - 1 ;
        !            90:                        y >= 0;
        !            91:                        nb++, y-- ) {
        !            92:                if (na->na_community == nb->na_community) {
        !            93:                        onnet = TRUE;
        !            94:                        break;
        !            95:                }
        !            96:        }
        !            97:     }
        !            98: 
        !            99:     if (! onnet) {
        !           100:        LLOG(log_dsap, LLOG_NOTICE, ("make_conn_block - no network in common"));
        !           101:        return(NULLCONN);
        !           102:     }
        !           103:     
        !           104:     if((cn = conn_alloc()) == NULLCONN)
        !           105:     {
        !           106:        LLOG(log_dsap, LLOG_EXCEPTIONS, ("make_conn_block - conn_alloc() out of memory"));
        !           107:        return(NULLCONN);
        !           108:     }
        !           109:     cn->cn_state = CN_WAITING;
        !           110:     cn->cn_ctx = conn_ctx;
        !           111:     cn->cn_initiator = TRUE;
        !           112:     make_dsa_bind_arg(&(cn->cn_connect.cc_req));
        !           113: 
        !           114:     cn->cn_dn = dn_cpy(name);
        !           115:     DLOG (log_dsap,LLOG_TRACE,( "Before psap_dup: %s", paddr2str(addr,NULLNA)));
        !           116:     psap_dup(&(cn->cn_addr), addr);
        !           117:     DLOG (log_dsap,LLOG_TRACE,( "After psap_dup:  %s", paddr2str(&(cn->cn_addr),NULLNA)));
        !           118: 
        !           119:     return(cn);
        !           120: }
        !           121: 
        !           122: int      link_op_to_conn(on)
        !           123: struct oper_act        * on;
        !           124: {
        !           125:     char                 conn_ctx = DS_CTX_X500_DSP;
        !           126:     struct di_block    * di;
        !           127:     struct di_block    **next_di;
        !           128:     struct connection  * cn;
        !           129:     int                          do_conn;
        !           130:     struct access_point * loop_ap;
        !           131:     int                res;
        !           132: 
        !           133:     sort_dsa_list (&on->on_dsas);
        !           134: 
        !           135:     /*
        !           136:     *  Use an open connection if one is available.
        !           137:     */
        !           138: 
        !           139:     next_di = &(on->on_dsas);
        !           140:     for(di=on->on_dsas; di!=NULL_DI_BLOCK; di=di->di_next)
        !           141:     {
        !           142:        for(cn=connlist; cn!=NULLCONN; cn=cn->cn_next)
        !           143:        {
        !           144:            /* Must be a suitable context */
        !           145:            if(cn->cn_ctx == DS_CTX_X500_DAP)
        !           146:            {
        !           147:                LLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn - open conn has DAP context"));
        !           148:                continue;
        !           149:            }
        !           150: 
        !           151:            if((cn->cn_ctx == DS_CTX_X500_DSP)
        !           152:                && ((on->on_type == ON_TYPE_GET_EDB)
        !           153:                    || (on->on_type == ON_TYPE_GET_DSA_INFO)
        !           154:                    || (!cn->cn_initiator)))
        !           155:            {
        !           156:                if (!cn->cn_initiator)
        !           157:                        LLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn - open conn has DSP context - we must initiate it"));
        !           158:                else
        !           159:                        LLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn - open conn has DSP context - QUIPU context needed"));
        !           160:                continue;
        !           161:            }
        !           162: 
        !           163:            if((cn->cn_dn != NULLDN)
        !           164:              && (dn_cmp(cn->cn_dn, di->di_dn) == 0))
        !           165:                break;
        !           166: 
        !           167:        }
        !           168:        if(cn != NULLCONN)
        !           169:            break;
        !           170: 
        !           171:        next_di = &(di->di_next);
        !           172:     }
        !           173:     if(di != NULL_DI_BLOCK)
        !           174:     {
        !           175:        /* Got one - remove successful di_block and link op to conn */
        !           176:        DLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn - Found suitable open connection"));
        !           177:        (*next_di) = di->di_next;
        !           178:        if (di->di_state == DI_DEFERRED) {
        !           179:                /* We have an open connection, but not a cache entry */
        !           180:                /*              (must have used an access point in the past) */
        !           181:                /* Need to be careful about freeing - do it later ! */
        !           182:                di->di_oper = NULLOPER;
        !           183:        } else
        !           184:                di_extract(di);
        !           185:        on->on_conn = cn;
        !           186:        on->on_next_conn = cn->cn_operlist;
        !           187:        cn->cn_operlist = on;
        !           188:        on->on_relay = FALSE;   /* No need we have an open connection */
        !           189:        return(OK);
        !           190:     }
        !           191: 
        !           192:     /*
        !           193:     *  Use a waiting connection if one is available.
        !           194:     */
        !           195:     next_di = &(on->on_dsas);
        !           196:     for(di=on->on_dsas; di!=NULL_DI_BLOCK; di=di->di_next)
        !           197:     {
        !           198:        for(cn=connwaitlist; cn!=NULLCONN; cn=cn->cn_next)
        !           199:        {
        !           200:        /*
        !           201:        *  Could do some clever stuff here and convert a waiting 
        !           202:        *  connection to QUIPU from X500 if possible and useful.
        !           203:        *  Left as an exercise for the reader.
        !           204:        */
        !           205:            /* Must be a suitable context */
        !           206:            if(cn->cn_ctx == DS_CTX_X500_DAP)
        !           207:                continue;
        !           208: 
        !           209:            if((cn->cn_ctx == DS_CTX_X500_DSP)
        !           210:                && ((on->on_type == ON_TYPE_GET_EDB)
        !           211:                    || (on->on_type == ON_TYPE_GET_DSA_INFO)))
        !           212:                continue;
        !           213: 
        !           214:            if((cn->cn_dn != NULLDN)
        !           215:              && (dn_cmp(cn->cn_dn, di->di_dn) == 0))
        !           216:                break;
        !           217:        }
        !           218:        if(cn != NULLCONN)
        !           219:            break;
        !           220: 
        !           221:        next_di = &(di->di_next);
        !           222:     }
        !           223:     if(di != NULL_DI_BLOCK)
        !           224:     {
        !           225:        /* Got one - remove successful di_block and link op to conn */
        !           226:        LLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn - Found suitable waiting connection"));
        !           227:        (*next_di) = di->di_next;
        !           228:        di_extract(di);
        !           229:        on->on_conn = cn;
        !           230:        on->on_next_conn = cn->cn_operlist;
        !           231:        cn->cn_operlist = on;
        !           232:        on->on_relay = FALSE;   /* No need we will chain sooner or later */
        !           233:        return(OK);
        !           234:     }
        !           235: 
        !           236:     DLOG(log_dsap, LLOG_DEBUG, ("Neither an open nor a waiting conn suitable"));
        !           237: 
        !           238:     next_di = &(on->on_dsas);
        !           239:     for(di=on->on_dsas; di!=NULL_DI_BLOCK; di=(*next_di))
        !           240:     {
        !           241:        if(di->di_state == DI_DEFERRED)
        !           242:        {
        !           243:            DLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn - deferred di_block"));
        !           244:            next_di = &(di->di_next);
        !           245:            continue;
        !           246:        }
        !           247: 
        !           248:        if(di->di_state == DI_ACCESSPOINT)
        !           249:        {
        !           250:            /* context problem:
        !           251:                if we have not got the entry, we don't know which context it
        !           252:                will accept.
        !           253:                If the operation is a getedb, or getdsainfo 
        !           254:                        ASSUME Quipu context is OK
        !           255:            */
        !           256:                
        !           257:            if((on->on_type == ON_TYPE_GET_EDB)
        !           258:                  || (on->on_type == ON_TYPE_GET_DSA_INFO)) 
        !           259:                conn_ctx = DS_CTX_QUIPU_DSP;
        !           260:            else {
        !           261:                conn_ctx = DS_CTX_X500_DSP;
        !           262:            }
        !           263: 
        !           264:            DLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn - make conn block from access point"));
        !           265: 
        !           266:            /* There *should* only be one access point - 
        !           267:             * but QUIPU may give a choice try find one that will work...
        !           268:              * This is *wrong* if it is a non specific subordinate reference.
        !           269:              */
        !           270:            if (di->di_reftype == RT_NONSPECIFICSUBORDINATE)
        !           271:                    LLOG(log_dsap,LLOG_EXCEPTIONS,("Should try each access point - not just one !!!"));
        !           272: 
        !           273:            for (loop_ap=di->di_accesspoints; loop_ap != NULLACCESSPOINT; loop_ap=loop_ap->ap_next)
        !           274:                    if((cn = make_conn_block(loop_ap->ap_name, loop_ap->ap_address, conn_ctx)) != NULLCONN) {
        !           275:                        on->on_relay = FALSE;   /* Made a connection block */
        !           276:                        break;
        !           277:                    }
        !           278: 
        !           279:            if (loop_ap == NULLACCESSPOINT) {
        !           280:                DLOG(log_dsap, LLOG_DEBUG, ("link_op_to_conn - make_conn_block failed 1"));
        !           281:                (*next_di) = di->di_next;
        !           282:                di_extract(di);
        !           283:                continue;
        !           284:            }
        !           285:        }
        !           286: 
        !           287:        if(di->di_state == DI_COMPLETE)
        !           288:        {
        !           289:            /*
        !           290:            *  Open a quipu context connection if possible: this is so if
        !           291:            *  the entry for the dsa in question has object class quipuDSA.
        !           292:            */
        !           293:            if((res = quipu_ctx_supported(di->di_entry)) != 2)
        !           294:            {
        !           295:                if((on->on_type == ON_TYPE_GET_EDB)
        !           296:                  || (on->on_type == ON_TYPE_GET_DSA_INFO)
        !           297:                  || (res == -1)) /* DAP only !!! */
        !           298:                {
        !           299:                    /* Ditch this di_block and carry on looking */
        !           300:                    LLOG(log_dsap, LLOG_EXCEPTIONS, ("link_op_to_conn - avoiding non-quipu context for GetEDB"));
        !           301:                    (*next_di) = di->di_next;
        !           302:                    di_extract(di);
        !           303:                    continue;
        !           304:                }
        !           305:                else
        !           306:                {
        !           307:                    DLOG(log_dsap, LLOG_DEBUG, ("link_op_to_conn - linking to a connection without a quipu context"));
        !           308:                    conn_ctx = DS_CTX_X500_DSP;
        !           309:                }
        !           310:            }
        !           311:            else
        !           312:            {
        !           313:                DLOG(log_dsap, LLOG_DEBUG, ("link_op_to_conn - linking to a connection with a quipu context"));
        !           314:                conn_ctx = DS_CTX_QUIPU_DSP;
        !           315:            }
        !           316: 
        !           317: 
        !           318:            DLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn - make conn block from entry"));
        !           319: 
        !           320:             if((cn = make_conn_block(di->di_dn, di->di_entry->e_dsainfo->dsa_addr, conn_ctx)) == NULLCONN)
        !           321:            {
        !           322:                DLOG(log_dsap, LLOG_DEBUG, ("link_op_to_conn - make_conn_block failed 2"));
        !           323:                (*next_di) = di->di_next;
        !           324:                di_extract(di);
        !           325:                continue;
        !           326:            } else
        !           327:                on->on_relay = FALSE;   /* Made a connection block */
        !           328: 
        !           329:        }
        !           330: 
        !           331:        /*
        !           332:        *  Decide whether to request connection or place it
        !           333:        *  on the list of waiting connections.
        !           334:        */
        !           335:        switch(on->on_type)
        !           336:        {
        !           337:        case ON_TYPE_GET_DSA_INFO:
        !           338:            do_conn = (conns_used < MAX_CONNS);
        !           339:            break;
        !           340:        case ON_TYPE_GET_EDB:
        !           341:            do_conn = (conns_used < (MAX_CONNS - CONNS_RESERVED_DI - CONNS_RESERVED_X500));
        !           342:            break;
        !           343:        default:
        !           344:            do_conn = (conns_used < (MAX_CONNS - CONNS_RESERVED_DI));
        !           345:            break;
        !           346:        }
        !           347: 
        !           348:        if(do_conn)
        !           349:        {
        !           350:            DLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn - about to request connection"));
        !           351:            if(conn_request(cn) != OK)
        !           352:            {
        !           353:                DLOG(log_dsap, LLOG_DEBUG, ("link_op_to_conn - conn_request failed"));
        !           354:                (*next_di) = di->di_next;
        !           355:                di_extract(di);
        !           356:                continue;
        !           357:            }
        !           358:            DLOG(log_dsap, LLOG_DEBUG, ("link_op_to_conn - conn_request OK"));
        !           359: 
        !           360:            cn->cn_next = connlist;
        !           361:            connlist = cn;
        !           362:            conns_used++;
        !           363:        }
        !           364:        else
        !           365:        {
        !           366:            DLOG(log_dsap, LLOG_NOTICE, ("Waiting for a free connection slot"));
        !           367:            cn->cn_next = connwaitlist;
        !           368:            connwaitlist = cn;
        !           369:        }
        !           370: 
        !           371:        (*next_di) = di->di_next;
        !           372:        di_extract(di);
        !           373:        on->on_conn = cn;
        !           374:        on->on_next_conn = cn->cn_operlist;
        !           375:        cn->cn_operlist = on;
        !           376:        return(OK);
        !           377:     }
        !           378: 
        !           379:     /*
        !           380:     *  If we get this far it means that we are waiting for a dsa info
        !           381:     *  operation to complete, or there are no di_blocks left to try.
        !           382:     *  Callers of link_op_to_conn must check on_dsas to discover which it is.
        !           383:     */
        !           384:     DLOG(log_dsap, LLOG_NOTICE, ("link_op_to_conn: returning NOTOK"));
        !           385:     return(NOTOK);
        !           386: }
        !           387: 
        !           388: int      oper_chain(on)
        !           389: struct oper_act                * on;
        !           390: {
        !           391:     if(link_op_to_conn(on) == OK)
        !           392:     {
        !           393:        if(on->on_conn == NULLCONN)
        !           394:        {
        !           395:            DLOG(log_dsap, LLOG_DEBUG, ("oper_chain - link_op_to_conn: OK but no conn"));
        !           396:        }
        !           397:        else
        !           398:        {
        !           399:            DLOG(log_dsap, LLOG_DEBUG, ("oper_chain - link_op_to_conn: OK got conn"));
        !           400: 
        !           401:            if(on->on_conn->cn_state == CN_OPEN)
        !           402:            {
        !           403:                DLOG(log_dsap, LLOG_DEBUG, ("oper_chain - link_op_to_conn: OK got open conn"));
        !           404:                if(oper_send_invoke(on) != OK)
        !           405:                {
        !           406:                    LLOG(log_dsap, LLOG_EXCEPTIONS, ("oper_chain - oper_send failed"));
        !           407:                    /* Have another go? */
        !           408:                    return(oper_chain(on));
        !           409:                }
        !           410:                else
        !           411:                { 
        !           412:                    DLOG(log_dsap, LLOG_DEBUG, ("oper_chain - oper_send succeeded"));
        !           413:                }
        !           414:            }
        !           415:        }
        !           416: 
        !           417:        on->on_state = ON_CHAINED;
        !           418:     }
        !           419:     else
        !           420:     {
        !           421:        /*
        !           422:        *  If on->on_dsas is empty then chaining has failed
        !           423:        *  otherwise the op is deferred.
        !           424:        */
        !           425:        if(on->on_dsas == NULL_DI_BLOCK)
        !           426:        {
        !           427:            if (relay_dsa (on) == NOTOK)
        !           428:                return NOTOK;
        !           429: 
        !           430:            LLOG(log_dsap, LLOG_NOTICE, ("Trying to relay..."));
        !           431:            return(oper_chain(on));
        !           432:        }
        !           433:        
        !           434:        on->on_state = ON_DEFERRED;
        !           435:     }
        !           436: 
        !           437:     return(OK);
        !           438: }
        !           439: 
        !           440: int      task_chain(tk, di)
        !           441: register       struct task_act     * tk;
        !           442: struct di_block        * di;
        !           443: {
        !           444:     struct oper_act    * on;
        !           445:     struct DSError     * err = &(tk->tk_resp.di_error.de_err);
        !           446:     struct di_block    * di_tmp;
        !           447:     char               refer_ok = TRUE;
        !           448: 
        !           449: #ifdef DEBUG
        !           450:     DLOG(log_dsap, LLOG_DEBUG, ("task_chain called with:"));
        !           451:     di_list_log(di);
        !           452: #endif
        !           453: 
        !           454: /* NB At some point this routine must assign the di_block list to
        !           455: * either the task (if it is intended to geneate a referral) or to
        !           456: * an operation hanging off that task if it is intended to chain the
        !           457: * task. This is fine when there are no deferred di_blocks, but when
        !           458: * there are then the information they will eventually contain is
        !           459: * needed to make a full decision on whether to chain or refer.
        !           460: * This needs a lot of thought to get right, for now the chain/refer
        !           461: * decision is made once and for all on the basis of the information
        !           462: * available now. Any information not available is assumed to force a
        !           463: * referral (the safe option  -  until network connectivity is considered)!
        !           464: * THis may introduce the unwelcome effect that a first request to a
        !           465: * DSA may produce a referral where subsequent requests do not - so much
        !           466: * for consistency but it won't happen that often if DSA info is cached
        !           467: * sensibly.
        !           468: */
        !           469: 
        !           470:     /*
        !           471:     *  Generate the referral which the DSA will pass back if
        !           472:     *  chaining is disallowed or oper_chain fails for all
        !           473:     *  DSAs listed.
        !           474:     */
        !           475: 
        !           476:     sort_dsa_list (&di);
        !           477: 
        !           478:     if ((di_tmp = select_refer_dsa (di,tk)) == NULL_DI_BLOCK) {
        !           479:        /* The remote END is probably unable to follow the referral - chain if allowed */
        !           480:        refer_ok = FALSE;
        !           481:        for(di_tmp=di; di_tmp!=NULL_DI_BLOCK; di_tmp=di_tmp->di_next)
        !           482:        {
        !           483:                if(di_tmp->di_state == DI_DEFERRED)
        !           484:                        continue;
        !           485: 
        !           486: #ifdef DEBUG
        !           487:                DLOG(log_dsap, LLOG_DEBUG, ("About to call di2cref with:"));
        !           488:                di_log(di_tmp);
        !           489: #endif
        !           490:                if(di2cref(di_tmp, err, tk->tk_conn->cn_ctx) == OK)
        !           491:                    break;
        !           492:        }
        !           493:     } else if (di2cref(di_tmp, err, tk->tk_conn->cn_ctx) != OK)
        !           494:                di_tmp = NULL_DI_BLOCK; /* waiting... */
        !           495: 
        !           496:     if(di_tmp == NULL_DI_BLOCK)
        !           497:     {
        !           498:        /*
        !           499:        *  Want to generate a referral - but all di_blocks (if any)
        !           500:        *  are deferred. Would we be lying too much if we said the
        !           501:        *  DSA was "busy" at this point???
        !           502:        */
        !           503:        ds_error_free (err);
        !           504:        err->dse_type = DSE_SERVICEERROR;
        !           505:        err->ERR_SERVICE.DSE_sv_problem = DSE_SV_BUSY;
        !           506:        di_desist(di);
        !           507:        return(NOTOK);
        !           508:     }
        !           509: 
        !           510:     /*
        !           511:     *  If it would be inappropriate to chain this operation, then
        !           512:     *  generate a referral from the di_block list.
        !           513:     */
        !           514: 
        !           515:     if(chain_ok(tk,refer_ok,di_tmp->di_dn) == FALSE)
        !           516:     {
        !           517:        DLOG(log_dsap, LLOG_DEBUG, ("Referring!"));
        !           518:        di_desist(di);
        !           519:        return(NOTOK);
        !           520:     }
        !           521: 
        !           522:     DLOG(log_dsap, LLOG_DEBUG, ("Chaining!"));
        !           523:     /* Chain. Generate the new operation to send */
        !           524:     if((on = task2oper(tk)) == NULLOPER)
        !           525:     {
        !           526:        DLOG(log_dsap, LLOG_DEBUG, ("Why did task2oper fail??"));
        !           527:        ds_error_free (err);
        !           528:        err->dse_type = DSE_SERVICEERROR;
        !           529:        err->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNAVAILABLE;
        !           530:        di_desist(di);
        !           531:        return(NOTOK);
        !           532:     }
        !           533: 
        !           534:     if(ti_is_elem(tk->tk_dx.dx_arg.dca_charg.cha_trace,
        !           535:                  tk->tk_dx.dx_arg.dca_charg.cha_trace->ti_next))
        !           536:        {
        !           537:            DLOG (log_dsap,LLOG_NOTICE,("Loop found in oper_chain()"));
        !           538:            ds_error_free (&on->on_resp.di_error.de_err);
        !           539:            on->on_resp.di_error.de_err.dse_type = DSE_SERVICEERROR;
        !           540:            on->on_resp.di_error.de_err.ERR_SERVICE.DSE_sv_problem = DSE_SV_LOOPDETECT;
        !           541:            return(NOTOK);
        !           542:        }
        !           543: 
        !           544:     on->on_next_task = tk->tk_operlist;
        !           545:     tk->tk_operlist = on;
        !           546:     on->on_task = tk;
        !           547: 
        !           548:     /* Hand control of di_blocks to the operation */
        !           549:     on->on_dsas = di;
        !           550:     for(di_tmp = di; di_tmp != NULL_DI_BLOCK; di_tmp=di_tmp->di_next)
        !           551:     {
        !           552:        di_tmp->di_type = DI_OPERATION;
        !           553:        di_tmp->di_oper = on;
        !           554:     }
        !           555: 
        !           556:     if(oper_chain(on) != OK)
        !           557:     {
        !           558:        oper_task_extract(on);
        !           559:        oper_free(on);
        !           560:        return(NOTOK);
        !           561:     }
        !           562: 
        !           563:     return(OK);
        !           564: }
        !           565: 
        !           566: oper_rechain(on)
        !           567: struct oper_act * on;
        !           568: {
        !           569:     struct DSE_referral         * ref = &(on->on_resp.di_error.de_err.ERR_REFERRAL);
        !           570:     struct continuation_ref     * cref;
        !           571:     register struct chain_arg  * cha = &(on->on_req.dca_charg);
        !           572:     struct trace_info          * ti;
        !           573:     struct di_block * ap2di();
        !           574: 
        !           575:     DLOG(log_dsap, LLOG_TRACE, ("Rechain an operation ..."));
        !           576:     cref = ref->DSE_ref_candidates;
        !           577:     
        !           578:     if(cref == NULLCONTINUATIONREF)
        !           579:     {
        !           580:        LLOG(log_dsap, LLOG_FATAL, ("No continuation reference to rechain"));
        !           581:        return(NOTOK);
        !           582:     }
        !           583: 
        !           584:     cha->cha_target = dn_cpy(cref->cr_name);
        !           585:     cha->cha_progress = cref->cr_progress;
        !           586:     cha->cha_aliasderef = ((cha->cha_aliasedrdns = cref->cr_aliasedRDNs) != CR_NOALIASEDRDNS);
        !           587: 
        !           588:     if (cha->cha_aliasderef) {
        !           589:        if ((on->on_arg->dca_dsarg.arg_type == OP_SEARCH) 
        !           590:                && (on->on_arg->dca_dsarg.arg_sr.sra_subset == SRA_ONELEVEL))
        !           591: #ifdef COMPAT_6_0
        !           592:        {
        !           593:                on->on_arg->dca_dsarg.arg_sr.sra_subset = SRA_BASEOBJECT;
        !           594:                cha->cha_entryonly = FALSE;
        !           595:        }
        !           596: #else
        !           597:                cha->cha_entryonly = TRUE;
        !           598: #endif
        !           599:        else
        !           600:                cha->cha_entryonly = FALSE;
        !           601:     }
        !           602: 
        !           603:     cha->cha_returnrefs = FALSE;
        !           604:     cha->cha_domaininfo = NULLPE;
        !           605:     if((cha->cha_reftype = cref->cr_reftype) == RT_UNDEFINED)
        !           606:        cha->cha_reftype = RT_SUPERIOR;
        !           607: 
        !           608:     DLOG(log_dsap, LLOG_DEBUG, ("oper_rechain - Setting trace info"));
        !           609:     ti = (struct trace_info *) malloc(sizeof(struct trace_info));
        !           610:     ti->ti_dsa = dn_cpy(on->on_conn->cn_dn); 
        !           611:     ti->ti_target = dn_cpy(cref->cr_name);
        !           612:     ti->ti_progress = cref->cr_progress;
        !           613:     ti->ti_next = cha->cha_trace;
        !           614:     cha->cha_trace = ti;
        !           615: 
        !           616:     if(ti_is_elem(ti,ti->ti_next))
        !           617:        {
        !           618:            DLOG (log_dsap,LLOG_NOTICE,("Loop found in oper_rechain()"));
        !           619:            ds_error_free (&on->on_resp.di_error.de_err);
        !           620:            on->on_resp.di_error.de_err.dse_type = DSE_SERVICEERROR;
        !           621:            on->on_resp.di_error.de_err.ERR_SERVICE.DSE_sv_problem = DSE_SV_LOOPDETECT;
        !           622:            return(NOTOK);
        !           623:        }
        !           624: 
        !           625:     oper_conn_extract(on);
        !           626: 
        !           627:     /*
        !           628:     *  Problem - having converted to di_blocks it is harder to handle referrals
        !           629:     *  Set up a single di_block with the address in the parent field ??
        !           630:     */
        !           631:     di_desist(on->on_dsas);
        !           632:     if (cref->cr_reftype != RT_NONSPECIFICSUBORDINATE)
        !           633:            on->on_dsas = ap2di (cref->cr_accesspoints,cref->cr_name,FALSE,DI_OPERATION,on,cref->cr_reftype);
        !           634:     else {
        !           635:            on->on_dsas = di_alloc();
        !           636:            on->on_dsas->di_target = dn_cpy(cref->cr_name);
        !           637:            on->on_dsas->di_dn = dn_cpy(cref->cr_accesspoints->ap_name);
        !           638:            DLOG(log_dsap, LLOG_DEBUG, ("oper_rechain allocates di_block with dn[%x]", on->on_dsas->di_dn));
        !           639:            on->on_dsas->di_type = DI_OPERATION;
        !           640:            on->on_dsas->di_reftype = RT_NONSPECIFICSUBORDINATE;
        !           641:            on->on_dsas->di_oper = on;
        !           642:            on->on_dsas->di_state = DI_ACCESSPOINT;
        !           643:            on->on_dsas->di_accesspoints = ap_cpy(cref->cr_accesspoints);
        !           644:            on->on_dsas->di_next = NULL_DI_BLOCK;
        !           645:     }
        !           646: 
        !           647:     sort_dsa_list (&on->on_dsas);      /* might be able to turn DI_ACCESS into DI_COMPLETE */
        !           648:     return(oper_chain(on));
        !           649: }
        !           650: 
        !           651: struct oper_act        * task2oper(tk)
        !           652: struct task_act * tk;
        !           653: {
        !           654:     register struct chain_arg  * cha = &(tk->tk_dx.dx_arg.dca_charg);
        !           655:     struct continuation_ref    * cref = tk->tk_resp.di_error.de_err.ERR_REFERRAL.DSE_ref_candidates;
        !           656:     struct trace_info          * ti;
        !           657:     struct oper_act            * on;
        !           658: 
        !           659:     DLOG(log_dsap, LLOG_TRACE, ("Chain a task ..."));
        !           660:     
        !           661:     if((on = oper_alloc()) == NULLOPER)
        !           662:        return(NULLOPER);
        !           663: 
        !           664:     on->on_type = ON_TYPE_X500;
        !           665: 
        !           666:     cha->cha_target = NULLDN;
        !           667:     if(cref->cr_name != NULLDN)
        !           668:     {
        !           669:            cha->cha_target = dn_cpy(cref->cr_name);
        !           670:     }
        !           671:     cha->cha_progress = cref->cr_progress;
        !           672:     cha->cha_aliasderef = ((cha->cha_aliasedrdns = cref->cr_aliasedRDNs) != CR_NOALIASEDRDNS);
        !           673: 
        !           674:     if (cha->cha_aliasderef) {
        !           675:        if ((on->on_arg->dca_dsarg.arg_type == OP_SEARCH) 
        !           676:                && (on->on_arg->dca_dsarg.arg_sr.sra_subset == SRA_ONELEVEL)) {
        !           677: #ifdef COMPAT_6_0
        !           678:        {
        !           679:                on->on_arg->dca_dsarg.arg_sr.sra_subset = SRA_BASEOBJECT;
        !           680:                cha->cha_entryonly = FALSE;
        !           681:        }
        !           682: #else
        !           683:                cha->cha_entryonly = TRUE;
        !           684: #endif
        !           685:        } else
        !           686:                cha->cha_entryonly = FALSE;
        !           687:     }
        !           688: 
        !           689:     cha->cha_returnrefs = FALSE;
        !           690:     cha->cha_domaininfo = NULLPE;
        !           691:     if((cha->cha_reftype = cref->cr_reftype) == RT_UNDEFINED)
        !           692:        cha->cha_reftype = RT_SUPERIOR;
        !           693: 
        !           694:     DLOG(log_dsap, LLOG_DEBUG, ("Checking history of op"));
        !           695:     if(tk->tk_conn->cn_ctx == DS_CTX_X500_DAP)
        !           696:     {
        !           697:        DLOG(log_dsap, LLOG_DEBUG, ("... user originated ..."));
        !           698:        cha->cha_originator = dn_cpy(tk->tk_conn->cn_dn);
        !           699:        cha->cha_trace = NULLTRACEINFO;
        !           700:     }
        !           701: 
        !           702:     if(tk->tk_timed == FALSE)
        !           703:     {
        !           704:        cha->cha_timelimit = NULLCP;
        !           705:     }
        !           706:     else
        !           707:     {
        !           708: #ifdef CHAIN_ARGS_TIMEOUT
        !           709:        struct UTCtime  ut;
        !           710:        tm2ut(gmtime(&(tk->tk_timeout)), &(ut));
        !           711:        cha->cha_timelimit = strdup(utct2str(&ut));
        !           712: #else
        !           713:        cha->cha_timelimit = NULLCP;
        !           714: #endif
        !           715:     }
        !           716: 
        !           717:     DLOG(log_dsap, LLOG_DEBUG, ("Setting trace info"));
        !           718:     ti = (struct trace_info *) malloc(sizeof(struct trace_info));
        !           719:     ti->ti_dsa = dn_cpy(mydsadn);
        !           720:     ti->ti_target = dn_cpy(cref->cr_name);
        !           721:     ti->ti_progress = cref->cr_progress;
        !           722:     ti->ti_next = cha->cha_trace;
        !           723:     cha->cha_trace = ti;
        !           724: 
        !           725:     on->on_arg = &(tk->tk_dx.dx_arg);
        !           726: 
        !           727:     return(on);
        !           728: }
        !           729: 
        !           730: int     chain_ok(tk,refer_ok,dsadn)
        !           731: struct task_act        * tk;
        !           732: char refer_ok;
        !           733: DN dsadn;
        !           734: {
        !           735:     struct common_args * ca;
        !           736: struct common_args     * get_ca_ref();
        !           737: 
        !           738:     ca = get_ca_ref(&(tk->tk_dx.dx_arg));
        !           739: 
        !           740:     /* if refer_ok is FALSE - we MUST chain unless prevented, otherwise operation will fail */
        !           741: 
        !           742:     DLOG (log_dsap,LLOG_TRACE,( "chain_ok: Checking if chaining is ok"));
        !           743: 
        !           744:     if ( ! refer_ok) {
        !           745:        DLOG (log_dsap,LLOG_DEBUG,( "We MUST chain"));  
        !           746:        
        !           747:        if ((tk->tk_conn->cn_ctx != DS_CTX_X500_DAP) && no_dsp_chain)
        !           748:        {
        !           749:                DLOG (log_dsap,LLOG_DEBUG,( "Not chaining because of NO_DSP_CHAIN"));
        !           750:                return(FALSE);
        !           751:        }
        !           752:        if(ca->ca_servicecontrol.svc_options & SVC_OPT_CHAININGPROHIBIT)
        !           753:        {
        !           754:                DLOG (log_dsap,LLOG_DEBUG,( "But prohibited"));
        !           755:                return(FALSE);
        !           756:        }
        !           757: 
        !           758:        if(ca->ca_servicecontrol.svc_options & SVC_OPT_LOCALSCOPE)
        !           759:        {
        !           760:                DLOG (log_dsap,LLOG_DEBUG,( "But out of scope"));
        !           761:                return(FALSE); 
        !           762:        }
        !           763:        
        !           764:        DLOG (log_dsap,LLOG_DEBUG,( "Forced chain OK!"));
        !           765:        return TRUE;
        !           766:     }
        !           767: 
        !           768:     if (tk->tk_conn->cn_ctx != DS_CTX_X500_DAP) {
        !           769:        if (no_dsp_chain)
        !           770:        {
        !           771:                DLOG (log_dsap,LLOG_DEBUG,( "Not chaining because of NO_DSP_CHAIN (2)"));
        !           772:                return(FALSE);
        !           773:        }
        !           774: 
        !           775:        if(! (ca->ca_servicecontrol.svc_options & SVC_OPT_PREFERCHAIN))
        !           776:        {
        !           777:                /* Don't send a self reference back to a remote DSA - chain if possible */
        !           778:                /* Should not need it, when self reference bug is fixed ! */
        !           779:                if ((tk->tk_conn->cn_initiator)
        !           780:                        || (dn_cmp (dsadn, tk->tk_conn->cn_dn) == NOTOK)) {
        !           781:                                DLOG (log_dsap,LLOG_DEBUG,( "Not chaining because of preference"));
        !           782:                                return(FALSE);
        !           783:                        }
        !           784:        }
        !           785:     }
        !           786: 
        !           787:     if(ca->ca_servicecontrol.svc_options & SVC_OPT_CHAININGPROHIBIT)
        !           788:     {
        !           789:        DLOG (log_dsap,LLOG_DEBUG,( "Not chaining because of prohibition"));
        !           790:        return(FALSE);
        !           791:     }
        !           792: 
        !           793:     if(ca->ca_servicecontrol.svc_options & SVC_OPT_LOCALSCOPE)
        !           794:     {
        !           795:        DLOG (log_dsap,LLOG_DEBUG,( "Not chaining because of scope"));
        !           796:        return(FALSE); 
        !           797:     }
        !           798: 
        !           799:     switch (tk->tk_dx.dx_arg.dca_dsarg.arg_type) {
        !           800:        case OP_ADDENTRY:
        !           801:        case OP_REMOVEENTRY:
        !           802:        case OP_MODIFYRDN:
        !           803:        case OP_MODIFYENTRY:
        !           804:                /* QUIPU DSAs will only allow modification over DAP */
        !           805:                if (!(ca->ca_servicecontrol.svc_options & SVC_OPT_PREFERCHAIN)) {
        !           806:                        DLOG (log_dsap,LLOG_DEBUG,( "Not chaining because of authentication"));
        !           807:                        return(FALSE); 
        !           808:                }
        !           809:        default:
        !           810:                break;
        !           811:     }
        !           812: 
        !           813:     DLOG (log_dsap,LLOG_DEBUG,( "Chain OK!"));
        !           814:     return(TRUE);
        !           815: }
        !           816: 
        !           817: task_result_wakeup(on)
        !           818: struct oper_act        * on;
        !           819: {
        !           820:     struct task_act    * tk;
        !           821: 
        !           822:     DLOG(log_dsap, LLOG_TRACE, ("task_result_wakeup"));
        !           823: 
        !           824:     if((tk = on->on_task) == NULLTASK)
        !           825:     {
        !           826:        LLOG(log_dsap, LLOG_EXCEPTIONS, ("Oper can't wake up (result)extracted task"));
        !           827:        oper_extract(on);
        !           828:     }
        !           829:     else
        !           830:     {
        !           831:        /*
        !           832:        *  Were waiting for a remote result and here it is.
        !           833:        *  Attempt to tidy up and send result.
        !           834:        */
        !           835:        tk->tk_result = &(on->on_resp.di_result.dr_res);
        !           836:        
        !           837:        dsp_cache (&(tk->tk_dx.dx_arg.dca_dsarg),&(tk->tk_result->dcr_dsres),tk->tk_conn->cn_ctx, tk->tk_conn->cn_dn);
        !           838: 
        !           839:        task_conn_extract(tk);
        !           840:        task_result(tk);
        !           841:        oper_extract(on);
        !           842:        task_extract(tk);
        !           843:     }
        !           844: }
        !           845: 
        !           846: task_error_wakeup(on)
        !           847: struct oper_act        * on;
        !           848: {
        !           849:     struct task_act    * tk;
        !           850: 
        !           851:     DLOG(log_dsap, LLOG_TRACE, ("task_error_wakeup"));
        !           852: 
        !           853:     if((tk = on->on_task) == NULLTASK)
        !           854:     {
        !           855:        LLOG(log_dsap, LLOG_EXCEPTIONS, ("Oper can't wake up (error) extracted task"));
        !           856:        oper_extract(on);
        !           857:     }
        !           858:     else
        !           859:     {
        !           860:        /*
        !           861:        *  Were waiting for a remote result and got a remote error.
        !           862:        *  If it is a referral, then rechain the operation if appropriate
        !           863:        *  otherwise return the error.
        !           864:        */
        !           865:        if ( !  ((on->on_resp.di_error.de_err.dse_type == DSE_SECURITYERROR)
        !           866:                && (on->on_resp.di_error.de_err.ERR_SECURITY.DSE_sc_problem == DSE_SC_AUTHENTICATION))) {
        !           867:                /* If is not an authenticaton error, swap errors */
        !           868:                ds_error_free(&(tk->tk_resp.di_error.de_err));
        !           869:                tk->tk_error = &(on->on_resp.di_error.de_err);
        !           870:        }
        !           871: 
        !           872:        if((on->on_resp.di_error.de_err.dse_type == DSE_DSAREFERRAL)
        !           873:        || (on->on_resp.di_error.de_err.dse_type == DSE_REFERRAL))
        !           874:        {
        !           875:            DLOG(log_dsap, LLOG_DEBUG, ("Try rechaining"));
        !           876:            if(oper_rechain(on) == OK)
        !           877:            {
        !           878:                DLOG(log_dsap, LLOG_DEBUG, ("Succeeded rechaining"));
        !           879:                return;
        !           880:            }
        !           881:            DLOG(log_dsap, LLOG_DEBUG, ("Failed rechaining"));
        !           882:        }
        !           883: 
        !           884:        task_conn_extract(tk);
        !           885:        task_error(tk);
        !           886:        oper_extract(on);
        !           887:        task_extract(tk);
        !           888:     }
        !           889: }
        !           890: 
        !           891: task_fail_wakeup(on)
        !           892: struct oper_act        * on;
        !           893: {
        !           894:     struct task_act    * tk;
        !           895:     struct DSError     * err;
        !           896: 
        !           897:     DLOG(log_dsap, LLOG_TRACE, ("task_fail_wakeup"));
        !           898: 
        !           899:     if((tk = on->on_task) == NULLTASK)
        !           900:     {
        !           901:        if (on->on_state != ON_ABANDONED)
        !           902:                LLOG(log_dsap, LLOG_EXCEPTIONS, ("task_fail_wakeup: no task"));
        !           903:        oper_extract(on);
        !           904:        return;
        !           905:     }
        !           906: 
        !           907:     /*
        !           908:     *  Were waiting for a remote result and got a remote failure.
        !           909:     *  If it is a referral, then rechain the operation if appropriate
        !           910:     *  otherwise return the error.
        !           911:     */
        !           912:     /*
        !           913:     *  If the task does not have a suitable referral error set up
        !           914:     *  then return serviceError invalid reference.
        !           915:     */
        !           916:     err = &(tk->tk_resp.di_error.de_err);
        !           917:     if((err->dse_type != DSE_REFERRAL) && (err->dse_type != DSE_DSAREFERRAL))
        !           918:     {
        !           919:        err->dse_type = DSE_SERVICEERROR;
        !           920:        err->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNAVAILABLE;
        !           921:     }
        !           922:     task_conn_extract(tk);
        !           923:     task_error(tk);
        !           924:     oper_conn_extract(on);
        !           925:     oper_task_extract(on);
        !           926:     oper_extract(on);
        !           927:     task_extract(tk);
        !           928: }
        !           929: 
        !           930: task_dsa_info_wakeup(di)
        !           931: struct di_block        * di;
        !           932: {
        !           933:     struct task_act    * tk = di->di_task;
        !           934: 
        !           935: 
        !           936:     DLOG(log_dsap, LLOG_TRACE, ("task_dsa_info_wakeup"));
        !           937: 
        !           938:     /*
        !           939:     * Were waiting for a reference to return.
        !           940:     * Check if the reference now returned is acceptable.
        !           941:     * If it is return a referral and unwrap everything,
        !           942:     * otherwise try another di_block for the reference.
        !           943:     */
        !           944:     sort_dsa_list (&di);
        !           945: 
        !           946:     if(di2cref(di, &(tk->tk_resp.di_error.de_err), tk->tk_conn->cn_ctx) != OK)
        !           947:     {
        !           948:        LLOG(log_dsap, LLOG_EXCEPTIONS, ("task_dsa_info_wakeup - reference not acceptable"));
        !           949:        /* Remove di_block which generated unwanted referral wait */
        !           950:        if(tk->tk_dsas == NULL_DI_BLOCK)
        !           951:        {
        !           952:            /* No more dsas from which to request info to form referral */
        !           953:            tk->tk_resp.di_error.de_err.dse_type = DSE_SERVICEERROR;
        !           954:            tk->tk_resp.di_error.de_err.ERR_SERVICE.DSE_sv_problem = DSE_SV_INVALIDREFERENCE;
        !           955:            task_conn_extract(tk);
        !           956:            task_error(tk);
        !           957:            task_extract(tk);
        !           958:            return;
        !           959:        }
        !           960:        return;
        !           961:     }
        !           962: 
        !           963:     task_conn_extract(tk);
        !           964:     task_error(tk);
        !           965:     task_extract(tk);
        !           966: }
        !           967: 
        !           968: static struct access_point * di2ap (di)
        !           969: struct di_block * di;
        !           970: {
        !           971: struct access_point *ap;
        !           972: 
        !           973:     switch(di->di_state)
        !           974:     {
        !           975:     case DI_ACCESSPOINT:
        !           976:        return (ap_cpy(di->di_accesspoints));
        !           977:     case DI_COMPLETE:
        !           978:        if(di->di_entry == NULLENTRY)
        !           979:        {
        !           980:            LLOG(log_dsap, LLOG_EXCEPTIONS, ("di2ap - di_entry NULL"));
        !           981:            return NULLACCESSPOINT;
        !           982:        }
        !           983:        if(di->di_entry->e_dsainfo == NULL)
        !           984:        {
        !           985:            LLOG(log_dsap, LLOG_EXCEPTIONS, ("di2ap - e_dsainfo NULL"));
        !           986:            return NULLACCESSPOINT;
        !           987:        }
        !           988:        if(di->di_entry->e_dsainfo->dsa_addr == NULLPA)
        !           989:        {
        !           990:            LLOG(log_dsap, LLOG_EXCEPTIONS, ("di2ap - dsa_addr NULL"));
        !           991:            return NULLACCESSPOINT;
        !           992:        }
        !           993:        ap = (struct access_point *) calloc(1, sizeof(struct access_point));
        !           994:        ap->ap_name = dn_cpy(di->di_dn);
        !           995:        ap->ap_address = psap_cpy(di->di_entry->e_dsainfo->dsa_addr);
        !           996:        return (ap);
        !           997:     default:
        !           998:        return NULLACCESSPOINT;
        !           999:     }
        !          1000:        
        !          1001: }
        !          1002: 
        !          1003: int    di2cref(di, err, ctx)
        !          1004: struct di_block        * di;
        !          1005: struct DSError * err;
        !          1006: char ctx;
        !          1007: {
        !          1008:     struct continuation_ref     * cref;
        !          1009:     struct di_block * loop;
        !          1010:     struct access_point *ap_append(), *ap;
        !          1011: 
        !          1012: #ifdef DEBUG
        !          1013:     DLOG(log_dsap, LLOG_TRACE, ("di2cref"));
        !          1014:     di_log(di);
        !          1015: #endif
        !          1016: 
        !          1017:     switch(di->di_state)
        !          1018:     {
        !          1019:     case DI_ACCESSPOINT:
        !          1020:         DLOG(log_dsap, LLOG_TRACE, ("di2cref - generating referrral from di_accesspoints"));
        !          1021: 
        !          1022:        /* Should check context */
        !          1023:        err->dse_type = DSE_REFERRAL;
        !          1024:        err->ERR_REFERRAL.DSE_ref_prefix = NULLDN;
        !          1025: 
        !          1026:         cref = err->ERR_REFERRAL.DSE_ref_candidates = (struct continuation_ref *) calloc(1, sizeof(struct continuation_ref));
        !          1027:        cref->cr_accesspoints = ap_cpy(di->di_accesspoints);
        !          1028:        cref->cr_name = dn_cpy(di->di_target);
        !          1029:        if((cref->cr_rdn_resolved = di->di_rdn_resolved) <= 0)
        !          1030:        {
        !          1031:            cref->cr_progress.op_resolution_phase = OP_PHASE_NOTSTARTED;
        !          1032:            cref->cr_progress.op_nextrdntoberesolved = 0;
        !          1033:        }
        !          1034:        else
        !          1035:        {
        !          1036:            cref->cr_progress.op_resolution_phase = OP_PHASE_PROCEEDING;
        !          1037:            cref->cr_progress.op_nextrdntoberesolved = di->di_rdn_resolved;
        !          1038:        }
        !          1039:        cref->cr_aliasedRDNs = di->di_aliasedRDNs;
        !          1040:        cref->cr_reftype = di->di_reftype;
        !          1041:        break;
        !          1042:     case DI_COMPLETE:
        !          1043:         DLOG(log_dsap, LLOG_TRACE, ("di2cref - generating referrral from di_entry"));
        !          1044: 
        !          1045:        /* Should check context */
        !          1046:        err->dse_type = DSE_REFERRAL;
        !          1047:        err->ERR_REFERRAL.DSE_ref_prefix = NULLDN;
        !          1048: 
        !          1049:         cref = err->ERR_REFERRAL.DSE_ref_candidates = (struct continuation_ref *) calloc(1, sizeof(struct continuation_ref));
        !          1050:        if ((cref->cr_accesspoints = di2ap (di)) == NULLACCESSPOINT)
        !          1051:                return NOTOK;
        !          1052:        cref->cr_name = dn_cpy(di->di_target);
        !          1053:        if((cref->cr_rdn_resolved = di->di_rdn_resolved) <= 0)
        !          1054:        {
        !          1055:            cref->cr_progress.op_resolution_phase = OP_PHASE_NOTSTARTED;
        !          1056:            cref->cr_progress.op_nextrdntoberesolved = 0;
        !          1057:        }
        !          1058:        else
        !          1059:        {
        !          1060:            cref->cr_progress.op_resolution_phase = OP_PHASE_PROCEEDING;
        !          1061:            cref->cr_progress.op_nextrdntoberesolved = di->di_rdn_resolved;
        !          1062:        }
        !          1063:        cref->cr_aliasedRDNs = di->di_aliasedRDNs;
        !          1064:        cref->cr_reftype = di->di_reftype;
        !          1065:        break;
        !          1066:     case DI_DEFERRED:
        !          1067:        LLOG(log_dsap, LLOG_NOTICE, ("di2cref - Trying to turn deferred di_block into continuation reference!"));
        !          1068:        return(NOTOK);
        !          1069:     default:
        !          1070:         LLOG(log_dsap, LLOG_EXCEPTIONS, ("di2cref - invalid di_state %d",di->di_state));
        !          1071:         return(NOTOK);
        !          1072:     }
        !          1073: 
        !          1074:     if (ctx == DS_CTX_QUIPU_DSP) {
        !          1075:        /* Make QSSR */
        !          1076:        /* append AP's from remaining di_blocks */
        !          1077:        LLOG (log_dsap, LLOG_TRACE, ("Making a QSSR"));
        !          1078:        for (loop=di->di_next; loop!=NULL_DI_BLOCK; loop=loop->di_next) {
        !          1079:                if (( ap = di2ap(loop)) == NULLACCESSPOINT)
        !          1080:                        return OK;      /* Have finished - return OK */
        !          1081:                cref->cr_accesspoints = ap_append (cref->cr_accesspoints,ap);
        !          1082:        }
        !          1083:     }
        !          1084: 
        !          1085:     return OK;
        !          1086: }
        !          1087: 
        !          1088: oper_fail_wakeup(on)
        !          1089: struct oper_act        * on;
        !          1090: {
        !          1091:     DLOG(log_dsap, LLOG_TRACE, ("oper_fail_wakeup()"));
        !          1092:     /*
        !          1093:     *  Attempt to perform operation remotely has failed.
        !          1094:     *  Check the type of operation and take appropriate action.
        !          1095:     */
        !          1096: 
        !          1097:     switch(on->on_type)
        !          1098:     {
        !          1099:     case ON_TYPE_X500:
        !          1100:        task_fail_wakeup(on);
        !          1101:        break;
        !          1102:     case ON_TYPE_SUBTASK:
        !          1103:        subtask_fail_wakeup(on);
        !          1104:        break;
        !          1105:     case ON_TYPE_BIND_COMPARE:
        !          1106:        bind_compare_fail_wakeup(on);
        !          1107:        break;
        !          1108:     case ON_TYPE_GET_DSA_INFO:
        !          1109:        dsa_info_fail_wakeup(on);
        !          1110:        break;
        !          1111:     case ON_TYPE_GET_EDB:
        !          1112:        get_edb_fail_wakeup(on);
        !          1113:        break;
        !          1114:     default:
        !          1115:        LLOG(log_dsap, LLOG_EXCEPTIONS, ("oper_fail_wakeup - op has invalid type"));
        !          1116:        break;
        !          1117:     }
        !          1118: }
        !          1119: 
        !          1120: 
        !          1121: subtask_chain(tk)
        !          1122: struct task_act * tk;
        !          1123: {
        !          1124:     struct ds_search_task      *refer;
        !          1125:     struct ds_search_task      *nref;
        !          1126:     struct ds_search_task      * trail = NULL_ST;
        !          1127:     struct ds_search_task      * st_done();
        !          1128:     struct oper_act            * on;
        !          1129:     struct di_block            * di;
        !          1130:     struct di_block            * di_tmp;
        !          1131:     register struct chain_arg  * tkcha = &(tk->tk_dx.dx_arg.dca_charg);
        !          1132:     register struct chain_arg  * oncha;
        !          1133:     struct trace_info          * ti;
        !          1134:     struct DSError             err;
        !          1135:     struct common_args         * ca;
        !          1136: struct common_args             * get_ca_ref();
        !          1137: 
        !          1138:     ca = get_ca_ref(&(tk->tk_dx.dx_arg));
        !          1139: 
        !          1140: 
        !          1141:     if(tk->refer_st == NULL_ST)
        !          1142:        return;
        !          1143: 
        !          1144:     DLOG(log_dsap, LLOG_TRACE, ("Chain search subtasks ..."));
        !          1145: 
        !          1146:     for(refer = tk->refer_st; refer != NULL_ST; refer = nref)
        !          1147:     {
        !          1148:        nref = refer->st_next;
        !          1149:        if((di = refer->st_di) == NULL_DI_BLOCK)
        !          1150:        {
        !          1151:            LLOG(log_dsap, LLOG_EXCEPTIONS, ("search referred without di_block list"));
        !          1152:            continue;
        !          1153:        }
        !          1154: 
        !          1155:        sort_dsa_list (&di);
        !          1156: 
        !          1157:        err.ERR_REFERRAL.DSE_ref_candidates = NULLCONTINUATIONREF;
        !          1158:        if ((di_tmp = select_refer_dsa (di,tk)) == NULL_DI_BLOCK) {
        !          1159:                /* The remote END is probably unable to follow the referral - chain if allowed */
        !          1160:                for(di_tmp=di; di_tmp!=NULL_DI_BLOCK; di_tmp=di_tmp->di_next)
        !          1161:                {
        !          1162:                        if(di_tmp->di_state == DI_DEFERRED)
        !          1163:                                continue;
        !          1164: 
        !          1165: #ifdef DEBUG
        !          1166:                        DLOG(log_dsap, LLOG_DEBUG, ("About to call di2cref with:"));
        !          1167:                        di_log(di_tmp);
        !          1168: #endif
        !          1169:                        if(di2cref(di_tmp, &err, tk->tk_conn->cn_ctx) == OK)
        !          1170:                            break;
        !          1171:                }
        !          1172:        } else 
        !          1173:                (void) di2cref(di_tmp, &err, tk->tk_conn->cn_ctx);
        !          1174: 
        !          1175:        on = oper_alloc();
        !          1176:        on->on_type = ON_TYPE_SUBTASK;
        !          1177:        on->on_dsas = di;
        !          1178:        for(di_tmp=di; di_tmp!=NULL_DI_BLOCK; di_tmp=di_tmp->di_next)
        !          1179:        {
        !          1180:            di_tmp->di_type = DI_OPERATION;
        !          1181:            di_tmp->di_oper = on;
        !          1182:        }
        !          1183:        on->on_subtask = refer;
        !          1184:        on->on_task = tk;
        !          1185:        on->on_next_task = tk->tk_operlist;
        !          1186:        tk->tk_operlist = on;
        !          1187: 
        !          1188:        oncha = &(on->on_req.dca_charg);
        !          1189: 
        !          1190:        if(refer->st_alias == NULLDN)
        !          1191:        {
        !          1192:            if (err.ERR_REFERRAL.DSE_ref_candidates)
        !          1193:                    oncha->cha_target = dn_cpy(err.ERR_REFERRAL.DSE_ref_candidates->cr_name);
        !          1194:            else 
        !          1195:                    oncha->cha_target = dn_cpy (di->di_target);
        !          1196:        }
        !          1197:        else
        !          1198:        {
        !          1199:            oncha->cha_target = dn_cpy(refer->st_alias);
        !          1200:        }
        !          1201: 
        !          1202:        if(di->di_rdn_resolved <= 0)
        !          1203:        {
        !          1204:            oncha->cha_progress.op_resolution_phase = OP_PHASE_NOTSTARTED;
        !          1205:            oncha->cha_progress.op_nextrdntoberesolved = 0;
        !          1206:        }
        !          1207:        else
        !          1208:        {
        !          1209:            oncha->cha_progress.op_resolution_phase = OP_PHASE_PROCEEDING;
        !          1210:            oncha->cha_progress.op_nextrdntoberesolved = di->di_rdn_resolved;
        !          1211:        }
        !          1212: 
        !          1213:        oncha->cha_aliasderef = ((oncha->cha_aliasedrdns = di->di_aliasedRDNs) != CR_NOALIASEDRDNS);
        !          1214:        if((oncha->cha_reftype = di->di_reftype) == RT_UNDEFINED)
        !          1215:            oncha->cha_reftype = RT_SUPERIOR;
        !          1216: 
        !          1217: #ifdef COMPAT_6_0
        !          1218:         oncha->cha_entryonly = FALSE;
        !          1219: #else
        !          1220:         oncha->cha_entryonly = refer->st_entryonly;
        !          1221: #endif
        !          1222: 
        !          1223:        oncha->cha_returnrefs = FALSE;
        !          1224:        oncha->cha_domaininfo = NULLPE;
        !          1225: 
        !          1226:        if(tk->tk_timed == FALSE)
        !          1227:        {
        !          1228:            oncha->cha_timelimit = NULLCP;
        !          1229:        }
        !          1230:        else
        !          1231:        {
        !          1232: #ifdef CHAIN_ARGS_TIMEOUT
        !          1233:            struct UTCtime      ut;
        !          1234:            tm2ut(gmtime(&(tk->tk_timeout)), &(ut));
        !          1235:            oncha->cha_timelimit = strdup(utct2str(&ut));
        !          1236: #else
        !          1237:            oncha->cha_timelimit = NULLCP;
        !          1238: #endif
        !          1239:        }
        !          1240: 
        !          1241:        DLOG(log_dsap, LLOG_DEBUG, ("Checking history of op"));
        !          1242:        if(tk->tk_conn->cn_ctx == DS_CTX_X500_DAP)
        !          1243:        {
        !          1244:            DLOG(log_dsap, LLOG_DEBUG, ("... user originated ..."));
        !          1245:            oncha->cha_originator = dn_cpy(tk->tk_conn->cn_dn);
        !          1246:            oncha->cha_trace = NULLTRACEINFO;
        !          1247:        }
        !          1248:        else
        !          1249:        {
        !          1250:            oncha->cha_originator = dn_cpy(tk->tk_dx.dx_arg.dca_charg.cha_originator);
        !          1251:            oncha->cha_trace = ti_cpy(tkcha->cha_trace);
        !          1252:        }
        !          1253: 
        !          1254:        DLOG(log_dsap, LLOG_DEBUG, ("Setting trace info"));
        !          1255:        ti = (struct trace_info *) malloc(sizeof(struct trace_info));
        !          1256:        ti->ti_dsa = dn_cpy(mydsadn);
        !          1257:        ti->ti_target = dn_cpy(di->di_target);
        !          1258: 
        !          1259:        if(di->di_rdn_resolved <= 0)
        !          1260:        {
        !          1261:            ti->ti_progress.op_resolution_phase = OP_PHASE_NOTSTARTED;
        !          1262:            ti->ti_progress.op_nextrdntoberesolved = 0;
        !          1263:        }
        !          1264:        else
        !          1265:        {
        !          1266:            ti->ti_progress.op_resolution_phase = OP_PHASE_PROCEEDING;
        !          1267:            ti->ti_progress.op_nextrdntoberesolved = di->di_rdn_resolved;
        !          1268:        }
        !          1269: 
        !          1270:        ti->ti_next = oncha->cha_trace;
        !          1271:        oncha->cha_trace = ti;
        !          1272: 
        !          1273:        on->on_req.dca_dsarg = tk->tk_dx.dx_arg.dca_dsarg;      /* struct copy */
        !          1274: 
        !          1275: #ifdef COMPAT_6_0
        !          1276:        on->on_req.dca_dsarg.arg_sr.sra_subset = refer->st_subset;
        !          1277: #endif
        !          1278: 
        !          1279:        on->on_arg = &(on->on_req);
        !          1280: 
        !          1281:        DLOG(log_dsap, LLOG_DEBUG, ("Generating search subtask OP"));
        !          1282:        if( (ca->ca_servicecontrol.svc_options & SVC_OPT_CHAININGPROHIBIT) 
        !          1283:                || (oper_chain(on) != OK))
        !          1284:        {
        !          1285:           add_cref2poq (&tk->tk_resp.di_result.dr_res.dcr_dsres.res_sr, err.ERR_REFERRAL.DSE_ref_candidates);
        !          1286:           oper_task_extract(on);
        !          1287:           oper_free(on);
        !          1288:                
        !          1289:           if (trail == NULL_ST)
        !          1290:                tk->refer_st = st_done(&refer);
        !          1291:           else
        !          1292:                trail->st_next = st_done (&refer);
        !          1293:        } else {
        !          1294:                refer->st_cr = err.ERR_REFERRAL.DSE_ref_candidates;
        !          1295:                trail = refer;
        !          1296:        }
        !          1297:     }
        !          1298:     if (trail != NULL_ST)
        !          1299:        trail->st_next = tk->referred_st;
        !          1300:     tk->referred_st = tk->refer_st;
        !          1301:     tk->refer_st = NULL_ST;
        !          1302: 
        !          1303:     if((tk->referred_st == NULL_ST) && (tk->tk_state == TK_PASSIVE) && (tk->tk_operlist == NULLOPER))
        !          1304:        {
        !          1305:            task_conn_extract(tk);
        !          1306:            task_result(tk);
        !          1307:            task_extract(tk);
        !          1308:        }
        !          1309: 
        !          1310: }
        !          1311: 
        !          1312: subtask_result_wakeup(on)
        !          1313: struct oper_act        * on;
        !          1314: {
        !          1315:     struct task_act    * tk;
        !          1316:     struct ds_search_task      **next_st;
        !          1317:     struct ds_search_task      * st;
        !          1318: 
        !          1319:     DLOG(log_dsap, LLOG_TRACE, ("subtask_result_wakeup"));
        !          1320: 
        !          1321:     if((tk = on->on_task) == NULLTASK)
        !          1322:     {
        !          1323:        LLOG(log_dsap, LLOG_EXCEPTIONS, ("Oper can't wake up (result)extracted task"));
        !          1324:        oper_extract(on);
        !          1325:     }
        !          1326:     else
        !          1327:     {
        !          1328:        /*
        !          1329:        *  Were waiting for a remote subtask result and here it is.
        !          1330:        */
        !          1331:        next_st = &(tk->referred_st);
        !          1332:        for(st=tk->referred_st; st!=NULL_ST; st=(*next_st))
        !          1333:        {
        !          1334:            if(st == on->on_subtask)
        !          1335:                break;
        !          1336: 
        !          1337:            next_st = &(st->st_next);
        !          1338:        }
        !          1339:        if(st == NULL_ST)
        !          1340:        {
        !          1341:            LLOG(log_dsap, LLOG_EXCEPTIONS, ("subtask_result_wakeup - subtask lost from referred list"));
        !          1342:        }
        !          1343:        else
        !          1344:        {
        !          1345:            /*
        !          1346:            *  Correlate uncorrelated search results from oper,
        !          1347:            *  then merge with correlated search results of task.
        !          1348:            */
        !          1349: 
        !          1350:            struct ds_search_result * tk_sr = &(tk->tk_resp.di_result.dr_res.dcr_dsres.res_sr);
        !          1351:            struct ds_search_result * op_sr = &(on->on_resp.di_result.dr_res.dcr_dsres.res_sr);
        !          1352: 
        !          1353:            DLOG(log_dsap, LLOG_DEBUG, ("Collating a search result"));
        !          1354: 
        !          1355:            st_comp_free (st);
        !          1356:            (*next_st) = st->st_next;
        !          1357: 
        !          1358:            correlate_search_results(op_sr);
        !          1359:            if(tk_sr->srr_next == NULLSRR)
        !          1360:            {
        !          1361:                DLOG(log_dsap, LLOG_DEBUG, ("Search result unallocated!"));
        !          1362:                tk_sr->srr_next = (struct ds_search_result *) calloc(1, sizeof(struct ds_search_result));
        !          1363:                tk_sr->srr_next->srr_correlated = TRUE;
        !          1364:                tk_sr->srr_next->srr_un.srr_unit = (struct ds_search_unit *) calloc(1, sizeof(struct ds_search_unit));
        !          1365:                tk_sr->srr_next->CSR_limitproblem = LSR_NOLIMITPROBLEM;
        !          1366:            }
        !          1367: 
        !          1368:            merge_search_results(tk_sr->srr_next, op_sr);
        !          1369:        }
        !          1370:        
        !          1371:        oper_extract(on);
        !          1372: 
        !          1373:        if((tk->referred_st == NULL_ST) && (tk->tk_state == TK_PASSIVE) && (tk->tk_operlist == NULLOPER))
        !          1374:        {
        !          1375:            task_conn_extract(tk);
        !          1376:            task_result(tk);
        !          1377:            task_extract(tk);
        !          1378:        }
        !          1379:     }
        !          1380: }
        !          1381: 
        !          1382: subtask_error_wakeup(on)
        !          1383: struct oper_act        * on;
        !          1384: {
        !          1385:     struct task_act    * tk;
        !          1386:     struct ds_search_task      **next_st;
        !          1387:     struct ds_search_task      * st;
        !          1388: 
        !          1389:     DLOG(log_dsap, LLOG_TRACE, ("subtask_error_wakeup"));
        !          1390: 
        !          1391:     if((tk = on->on_task) == NULLTASK)
        !          1392:     {
        !          1393:        LLOG(log_dsap, LLOG_EXCEPTIONS, ("Oper can't wake up (error) extracted task"));
        !          1394:        oper_extract(on);
        !          1395:     }
        !          1396:     else
        !          1397:     {
        !          1398:        /*
        !          1399:        *  Were waiting for a remote subtask result and got a remote error.
        !          1400:        *  If it is a referral, then rechain the operation if appropriate
        !          1401:        *  otherwise dump the subtask and check the task for completion.
        !          1402:        */
        !          1403: /* Too many struct copies...
        !          1404:        ds_error_free(&(tk->tk_resp.di_error.de_err));
        !          1405: */
        !          1406:        tk->tk_error = &(on->on_resp.di_error.de_err);
        !          1407: 
        !          1408:        if((on->on_resp.di_error.de_err.dse_type == DSE_DSAREFERRAL)
        !          1409:        || (on->on_resp.di_error.de_err.dse_type == DSE_REFERRAL))
        !          1410:        {
        !          1411:            DLOG(log_dsap, LLOG_DEBUG, ("Try rechaining st"));
        !          1412:            if(oper_rechain(on) == OK)
        !          1413:            {
        !          1414:                DLOG(log_dsap, LLOG_DEBUG, ("Succeeded rechaining st"));
        !          1415:                return;
        !          1416:            }
        !          1417:            DLOG(log_dsap, LLOG_DEBUG, ("Failed rechaining st"));
        !          1418:            add_cref2poq (&tk->tk_resp.di_result.dr_res.dcr_dsres.res_sr, on->on_resp.di_error.de_err.ERR_REFERRAL.DSE_ref_candidates);
        !          1419:            on->on_resp.di_error.de_err.ERR_REFERRAL.DSE_ref_candidates = NULLCONTINUATIONREF;
        !          1420:        }
        !          1421: 
        !          1422:        next_st = &(tk->referred_st);
        !          1423:        for(st=tk->referred_st; st!=NULL_ST; st=(*next_st))
        !          1424:        {
        !          1425:            if(st == on->on_subtask)
        !          1426:                break;
        !          1427: 
        !          1428:            next_st = &(st->st_next);
        !          1429:        }
        !          1430:        if(st == NULL_ST)
        !          1431:        {
        !          1432:            LLOG(log_dsap, LLOG_EXCEPTIONS, ("subtask_result_wakeup - subtask lost from referred list"));
        !          1433:        }
        !          1434:        else
        !          1435:        {
        !          1436:            st_comp_free (st);
        !          1437:            (*next_st) = st->st_next;
        !          1438:        }
        !          1439: 
        !          1440:        oper_extract(on);
        !          1441: 
        !          1442:        if((tk->referred_st == NULL_ST) && (tk->tk_state == TK_PASSIVE) && (tk->tk_operlist == NULLOPER))
        !          1443:        {
        !          1444:            task_conn_extract(tk);
        !          1445:            task_result(tk);
        !          1446:            task_extract(tk);
        !          1447:        }
        !          1448:     }
        !          1449: }
        !          1450: 
        !          1451: subtask_fail_wakeup(on)
        !          1452: struct oper_act        * on;
        !          1453: {
        !          1454:     struct task_act    * tk;
        !          1455:     struct DSError     * err;
        !          1456:     struct ds_search_task      **next_st;
        !          1457:     struct ds_search_task      * st;
        !          1458: 
        !          1459:     DLOG(log_dsap, LLOG_TRACE, ("subtask_fail_wakeup"));
        !          1460: 
        !          1461:     if((tk = on->on_task) == NULLTASK)
        !          1462:     {
        !          1463:        LLOG(log_dsap, LLOG_FATAL, ("subtask_fail_wakeup: no task"));
        !          1464:        oper_extract(on);
        !          1465:        return;
        !          1466:     }
        !          1467:     else
        !          1468:     {
        !          1469:        next_st = &(tk->referred_st);
        !          1470:        for(st=tk->referred_st; st!=NULL_ST; st=(*next_st))
        !          1471:        {
        !          1472:            if(st == on->on_subtask)
        !          1473:                break;
        !          1474: 
        !          1475:            next_st = &(st->st_next);
        !          1476:        }
        !          1477:        if(st == NULL_ST)
        !          1478:        {
        !          1479:            LLOG(log_dsap, LLOG_EXCEPTIONS, ("subtask_result_wakeup - subtask lost from referred list"));
        !          1480:        }
        !          1481:        else
        !          1482:        {
        !          1483:            add_cref2poq (&tk->tk_resp.di_result.dr_res.dcr_dsres.res_sr, st->st_cr);
        !          1484:            st_comp_free (st);
        !          1485:            (*next_st) = st->st_next;
        !          1486:        }
        !          1487: 
        !          1488:        oper_extract(on);
        !          1489: 
        !          1490:        if((tk->referred_st == NULL_ST) && (tk->tk_state == TK_PASSIVE) && (tk->tk_operlist == NULLOPER))
        !          1491:        {
        !          1492:            task_conn_extract(tk);
        !          1493:            task_result(tk);
        !          1494:            task_extract(tk);
        !          1495:        }
        !          1496:     }
        !          1497:     err = &(tk->tk_resp.di_error.de_err);
        !          1498:     if((err->dse_type != DSE_REFERRAL) && (err->dse_type != DSE_DSAREFERRAL))
        !          1499:     {
        !          1500:        err->dse_type = DSE_SERVICEERROR;
        !          1501:        err->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNAVAILABLE;
        !          1502:     }
        !          1503: }
        !          1504: 
        !          1505: subtask_dsa_info_wakeup(di)
        !          1506: struct di_block        * di;
        !          1507: {
        !          1508:     struct task_act    * tk = di->di_task;
        !          1509: 
        !          1510: 
        !          1511:     DLOG(log_dsap, LLOG_TRACE, ("subtask_dsa_info_wakeup"));
        !          1512: 
        !          1513:     /*
        !          1514:     * Were waiting for a reference to return.
        !          1515:     * Check if the reference now returned is acceptable.
        !          1516:     * If it is return a referral and unwrap everything,
        !          1517:     * otherwise try another di_block for the reference.
        !          1518:     */
        !          1519: 
        !          1520:     if(di2cref(di, &(tk->tk_resp.di_error.de_err), tk->tk_conn->cn_ctx) != OK)
        !          1521:     {
        !          1522:        LLOG(log_dsap, LLOG_EXCEPTIONS, ("subtask_dsa_info_wakeup - reference not acceptable"));
        !          1523:        /* Remove di_block which generated unwanted referral wait */
        !          1524:        if(tk->tk_dsas == NULL_DI_BLOCK)
        !          1525:        {
        !          1526:            /* No more dsas from which to request info to form referral */
        !          1527:            tk->tk_resp.di_error.de_err.dse_type = DSE_SERVICEERROR;
        !          1528:            tk->tk_resp.di_error.de_err.ERR_SERVICE.DSE_sv_problem = DSE_SV_INVALIDREFERENCE;
        !          1529:            task_conn_extract(tk);
        !          1530:            task_error(tk);
        !          1531:            task_extract(tk);
        !          1532:            return;
        !          1533:        }
        !          1534:        return;
        !          1535:     }
        !          1536: 
        !          1537:     task_conn_extract(tk);
        !          1538:     task_error(tk);
        !          1539:     task_extract(tk);
        !          1540: }
        !          1541: 
        !          1542: 
        !          1543: add_cref2poq (res,cref)
        !          1544: struct ds_search_result *res;
        !          1545: ContinuationRef cref;  
        !          1546: {
        !          1547: ContinuationRef cr;    
        !          1548: 
        !          1549:        if (res->CSR_cr == NULLCONTINUATIONREF) {
        !          1550:                res->CSR_cr = cref;
        !          1551:                return;
        !          1552:        }
        !          1553:        for (cr = res->CSR_cr; cr->cr_next != NULLCONTINUATIONREF; cr=cr->cr_next)
        !          1554:                ;
        !          1555: 
        !          1556:        cr->cr_next = cref;
        !          1557: }
        !          1558: 
        !          1559: relay_dsa (on)
        !          1560: struct oper_act * on;
        !          1561: {
        !          1562: struct DSError  err;
        !          1563: struct di_block *di = NULL_DI_BLOCK;
        !          1564: 
        !          1565:        if (  (on == NULLOPER)
        !          1566:           || (on->on_relay == FALSE)
        !          1567:           || (on->on_task == NULLTASK)
        !          1568:           || (on->on_task->tk_conn == NULLCONN)
        !          1569:           || (on->on_task->tk_conn->cn_ctx != DS_CTX_X500_DAP))
        !          1570:                return NOTOK;
        !          1571: 
        !          1572:        if (dsa_info_parent (NULLDN,&err,&di,TRUE) != DS_CONTINUE)
        !          1573:                return NOTOK;
        !          1574: 
        !          1575:        on->on_relay = FALSE;   /* Don't relay twice to same DSA ! */
        !          1576: 
        !          1577:        on->on_dsas = di;
        !          1578: 
        !          1579:        return (on->on_dsas == NULL_DI_BLOCK ? NOTOK : OK);
        !          1580: 
        !          1581: }

unix.superglobalmegacorp.com

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