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