|
|
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.