|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.