Annotation of 43BSDReno/contrib/isode-beta/quipu/di_block.c, revision 1.1.1.1

1.1       root        1: /* di_block.c - routines to handle operation activity blocks */
                      2: 
                      3: #ifndef lint
                      4: static char *rcsid = "$Header: /f/osi/quipu/RCS/di_block.c,v 7.2 90/07/09 14:45:34 mrose Exp $";
                      5: #endif
                      6: 
                      7: /*
                      8:  * $Header: /f/osi/quipu/RCS/di_block.c,v 7.2 90/07/09 14:45:34 mrose Exp $
                      9:  *
                     10:  *
                     11:  * $Log:       di_block.c,v $
                     12:  * Revision 7.2  90/07/09  14:45:34  mrose
                     13:  * sync
                     14:  * 
                     15:  * Revision 7.1  89/12/19  16:20:09  mrose
                     16:  * sync
                     17:  * 
                     18:  * Revision 7.0  89/11/23  22:17:00  mrose
                     19:  * Release 6.0
                     20:  * 
                     21:  */
                     22: 
                     23: /*
                     24:  *                                NOTICE
                     25:  *
                     26:  *    Acquisition, use, and distribution of this module and related
                     27:  *    materials are subject to the restrictions of a license agreement.
                     28:  *    Consult the Preface in the User's Manual for the full terms of
                     29:  *    this agreement.
                     30:  *
                     31:  */
                     32: 
                     33: 
                     34: #include "quipu/util.h"
                     35: #include "quipu/connection.h"
                     36: #include "tsap.h"
                     37: #include "tailor.h"
                     38: 
                     39: extern LLog * log_dsap;
                     40: 
                     41: extern time_t timenow;
                     42: 
                     43: struct di_block *di_alloc()
                     44: {
                     45:     struct di_block    * di_ret;
                     46: 
                     47:     di_ret = (struct di_block *) calloc(1,sizeof(struct di_block));
                     48: 
                     49:     return(di_ret);
                     50: }
                     51: 
                     52: di_free(di)
                     53: struct di_block *di;
                     54: {
                     55:        DLOG(log_dsap, LLOG_TRACE, ("di_free()"));
                     56: 
                     57:        switch (di->di_state) {
                     58:          case DI_GLOBAL:       break;
                     59:          case DI_TASK:         break;
                     60:          case DI_OPERATION:    break;
                     61:          default:
                     62:                DLOG(log_dsap, LLOG_TRACE, ("di_free() of unknown type %d",di->di_state));
                     63:                return;
                     64:        }
                     65: 
                     66:        dn_free(di->di_dn);
                     67: 
                     68:        dn_free(di->di_target);
                     69: 
                     70:        if(di->di_accesspoints != NULLACCESSPOINT)
                     71:            aps_free(di->di_accesspoints);
                     72: 
                     73:        di->di_state = -1;
                     74: 
                     75:        free((char *)di);
                     76: }
                     77: 
                     78: di_extract(old_di)
                     79: struct di_block        * old_di;
                     80: {
                     81:     struct di_block    * di;
                     82:     struct di_block    **next_di;
                     83: 
                     84:     LLOG(log_dsap, LLOG_TRACE, ("di_extract"));
                     85: #ifdef DEBUG
                     86:     di_log(old_di);
                     87: #endif
                     88: 
                     89:     switch(old_di->di_type)
                     90:     {
                     91:     case DI_GLOBAL:
                     92:         next_di = &(deferred_dis);
                     93:        for(di=deferred_dis; di!=NULL_DI_BLOCK; di=di->di_next)
                     94:        {
                     95:            if(di == old_di)
                     96:                break;
                     97: 
                     98:            next_di = &(di->di_next);
                     99:        }
                    100:        if(di == NULL_DI_BLOCK)
                    101:        {
                    102:            LLOG(log_dsap, LLOG_EXCEPTIONS, ("di_block has escaped from global list"));
                    103:        }
                    104:        else
                    105:        {
                    106:            (*next_di) = di->di_next;
                    107:        }
                    108:        break;
                    109:     case DI_OPERATION:
                    110:        break;
                    111:     case DI_TASK:
                    112:        break;
                    113:     default:
                    114:        break;
                    115:     }
                    116: 
                    117:     di_free(old_di);
                    118: }
                    119: 
                    120: di_desist(di)
                    121: struct di_block        * di;
                    122: {
                    123:     struct di_block    * di_tmp1;
                    124:     struct di_block    * di_tmp1_next;
                    125:     struct di_block    * di_tmp2;
                    126:     struct di_block    **di_p2;
                    127: 
                    128:        DLOG(log_dsap, LLOG_TRACE, ("di_desist()"));
                    129: 
                    130:     for(di_tmp1=di; di_tmp1 != NULL_DI_BLOCK; di_tmp1 = di_tmp1_next)
                    131:     {
                    132:        di_tmp1_next = di_tmp1->di_next;
                    133: 
                    134:        switch(di->di_state)
                    135:        {
                    136:        case DI_ACCESSPOINT:
                    137:        case DI_COMPLETE:
                    138:                break;
                    139:        case DI_DEFERRED:
                    140:            di_p2 = &(di_tmp1->di_perform->on_wake_list);
                    141:            for(di_tmp2=di_tmp1->di_perform->on_wake_list; di_tmp2!=NULL_DI_BLOCK; di_tmp2=di_tmp2->di_wake_next)
                    142:            {
                    143:                if(di_tmp2 == di_tmp1)
                    144:                    break;
                    145: 
                    146:                di_p2 = &(di_tmp2->di_wake_next);
                    147:            }
                    148:            if(di_tmp2 == NULL_DI_BLOCK)
                    149:            {
                    150:                LLOG(log_dsap, LLOG_EXCEPTIONS, ("di_desist - di_block lost from performing operations wake up list"));
                    151:            }
                    152:            else
                    153:            {
                    154:                (*di_p2) = di_tmp2->di_wake_next;
                    155:            }
                    156:            break;
                    157:        }
                    158:        di_free(di_tmp1);
                    159:     }
                    160: }
                    161: 
                    162: di_log(di)
                    163: struct di_block        * di;
                    164: {
                    165:     DLOG (log_dsap,LLOG_DEBUG, ("di_block [%x] , state = %d, type = %d",
                    166:        di, di->di_state, di->di_type));
                    167: }
                    168: 
                    169: di_list_log(di)
                    170: struct di_block *di;
                    171: {
                    172:     struct di_block    * di_tmp;
                    173: 
                    174:     DLOG(log_dsap, LLOG_DEBUG, ("di_list:"));
                    175: #ifdef DEBUG
                    176:     for(di_tmp = di; di_tmp!=NULL_DI_BLOCK; di_tmp=di_tmp->di_next)
                    177:     {
                    178:        di_log(di_tmp);
                    179:     }
                    180: #endif
                    181:     DLOG(log_dsap, LLOG_DEBUG, ("di_list ends."));
                    182: }
                    183: 
                    184: 
                    185: 
                    186: static struct dn_seq * prefer_dsa_list = NULLDNSEQ;
                    187: 
                    188: prefer_dsa (str)
                    189: char * str;
                    190: {
                    191: struct dn_seq * dsa, *loop;
                    192: 
                    193:        if (( dsa=str2dnseq(str)) == NULLDNSEQ) {
                    194:                LLOG (log_dsap,LLOG_EXCEPTIONS,("Invalid prefered DSA name %s",str));   
                    195:                return;
                    196:        }
                    197:        
                    198:        if (prefer_dsa_list == NULLDNSEQ) 
                    199:                prefer_dsa_list = dsa;
                    200:        else {
                    201:                for (loop = prefer_dsa_list; loop->dns_next != NULLDNSEQ; loop=loop->dns_next)
                    202:                        ;
                    203:                loop->dns_next = dsa;
                    204:        }
                    205: }
                    206: 
                    207: static di_prefer_dsa (a,b)
                    208: DN a,b;
                    209: {
                    210: int x,y;
                    211: 
                    212:        if (prefer_dsa_list == NULLDNSEQ) {
                    213:                DLOG (log_dsap,LLOG_TRACE,("NO DSAs to chose from"));
                    214:                return 0;       /* not fussy !!! */
                    215:        }
                    216: 
                    217:        if ((b == NULLDN) || (a == NULLDN)) {
                    218:                DLOG (log_dsap,LLOG_NOTICE,("di_pref DNs NULL"));
                    219:                return 0;       /* safty catch - don't think it can happen */
                    220:        }
                    221: 
                    222:        if ((x = dn_in_dnseq (a,prefer_dsa_list)) == 0)
                    223:                if ((y = dn_in_dnseq (b,prefer_dsa_list)) == 0)
                    224:                        return 0;
                    225:                else {
                    226:                        DLOG (log_dsap,LLOG_TRACE,("DSA selected on preference"));
                    227:                        return -1;
                    228:                }
                    229: 
                    230:        if ((y = dn_in_dnseq (b,prefer_dsa_list)) == 0) {
                    231:                DLOG (log_dsap,LLOG_TRACE,("DSA selected on preference"));
                    232:                return 1;
                    233:        }
                    234: 
                    235:        if ( x != y ) {
                    236:                DLOG (log_dsap,LLOG_TRACE,("DSA selected on preference"));
                    237:                return ( x > y ? -1 : 1 );
                    238:        }
                    239: 
                    240:        return 0;
                    241:        
                    242: }
                    243: 
                    244: static di_ap2comp (di)
                    245: struct di_block        **di;
                    246: {
                    247: struct di_block *loop;
                    248: Entry eptr;
                    249: 
                    250:        /* replace DI_ACCESSPOINT with DI_COMPLETE if possible... */
                    251:        /*      (data may have been cached since creating DI_ACCESSPOINT) */
                    252: 
                    253:        for (loop= *di; loop!=NULL_DI_BLOCK; loop=loop->di_next) {
                    254:                if (loop->di_state != DI_ACCESSPOINT)
                    255:                        continue;
                    256: 
                    257:                if (loop->di_reftype == RT_NONSPECIFICSUBORDINATE) 
                    258:                        continue;       /* can't split these - all must be followed... */
                    259: 
                    260:                if (loop->di_accesspoints->ap_next == NULLACCESSPOINT) {
                    261:                        if ((eptr=local_find_entry (loop->di_accesspoints->ap_name,FALSE)) != NULLENTRY)
                    262:                                if (eptr->e_dsainfo != NULLDSA) {
                    263:                                        loop->di_entry = eptr;
                    264:                                        loop->di_state = DI_COMPLETE;   
                    265:                                        aps_free (loop->di_accesspoints);
                    266:                                        loop->di_accesspoints = NULLACCESSPOINT;
                    267:                                }
                    268:                } else 
                    269:                        LLOG (log_dsap,LLOG_EXCEPTIONS,("Many access points, but not a RT_NONSPECIFICSUBORDINATE"));
                    270:        }
                    271: 
                    272: }
                    273: 
                    274: dsa_reliable (cn,good,when)
                    275: struct connection * cn;
                    276: char good;
                    277: time_t when;
                    278: {
                    279: Entry ptr;
                    280: 
                    281:        if ( (ptr=local_find_entry(cn->cn_dn,FALSE)) == NULLENTRY)
                    282:                return;
                    283: 
                    284:        if (ptr->e_dsainfo == NULLDSA)
                    285:                return;
                    286: 
                    287:        ptr->e_dsainfo->dsa_last_attempt = when;
                    288:        if (good) {
                    289:                ptr->e_dsainfo->dsa_last_success = when;
                    290:                ptr->e_dsainfo->dsa_failures = 0;
                    291:        } else 
                    292:                ptr->e_dsainfo->dsa_failures++;
                    293: }
                    294: 
                    295: static di_cmp_reliability (a,b)
                    296: struct di_block *a, *b;
                    297: {
                    298: extern time_t retry_timeout;
                    299: struct dsa_info *da, *db;
                    300: 
                    301:        /* If we have used a DSA recently, with no failures - use it again */
                    302: 
                    303:        if ((da = a->di_entry->e_dsainfo) == NULLDSA)
                    304:                return 0;
                    305:        if ((db = b->di_entry->e_dsainfo) == NULLDSA)
                    306:                return 0;
                    307: 
                    308:        if (da->dsa_last_attempt == (time_t)0) {
                    309:                if (db->dsa_failures == 0) {
                    310:                        if ((db->dsa_last_success != (time_t)0)
                    311:                                && (timenow - db->dsa_last_attempt < retry_timeout))
                    312:                                return -1;      /* b worked recently */
                    313:                } else if (timenow - db->dsa_last_attempt < retry_timeout)
                    314:                        return 1;               /* b failed recently */
                    315:                return 0;       /* have not tried either recently  */
                    316: 
                    317:        } else if (db->dsa_last_attempt == (time_t)0) {
                    318:                if (da->dsa_failures == 0) {
                    319:                        if ((da->dsa_last_success != (time_t)0)
                    320:                                && (timenow - da->dsa_last_attempt < retry_timeout))
                    321:                                return 1;       /* a worked recentdlry */
                    322:                } else if (timenow - da->dsa_last_attempt < retry_timeout)
                    323:                        return -1;              /* a failed recently */
                    324:                return 0;       /* have not tried either recently  */
                    325:        }
                    326: 
                    327:        if (da->dsa_failures == 0) {
                    328:                if (db->dsa_failures == 0)
                    329:                        return 0;       /* both OK */
                    330:                return 1;       /* a worked last time, b failed - use a */
                    331:        }
                    332: 
                    333:        if (db->dsa_failures == 0)
                    334:                return -1;      /* b worked last time, a failed - use b */
                    335: 
                    336:        /* both failed last time - see if either have suceeded recently */
                    337: 
                    338:        if ((timenow - da->dsa_last_success) > retry_timeout ) {
                    339:                if ((timenow - db->dsa_last_success) > retry_timeout)
                    340:                        return 0;       /* too long ago to tell */
                    341:                return -1;      /* use b it worked not that long ago... */
                    342:        }
                    343:        if ((timenow - db->dsa_last_success) > retry_timeout)
                    344:                return 1;       /* use a it worked not that long ago... */
                    345: 
                    346:        /* neither has worked recently chose some other way */
                    347:        return 0;
                    348: }
                    349: 
                    350: static di_cmp_address (a,b)
                    351: struct di_block *a, *b;
                    352: {
                    353: struct NSAPaddr *na;
                    354: struct NSAPaddr *nb;
                    355: struct NSAPaddr nas;
                    356: struct TSAPaddr *ta2norm();
                    357: struct TSAPaddr *ta;
                    358: struct TSAPaddr *tb;
                    359: int *ip;
                    360: extern DN mydsadn;
                    361: DN dnptr, mydnptr, dna,dnb;
                    362: int ma,mb;
                    363: 
                    364:        /* select DSA with best looking address !!! */
                    365: 
                    366:        if (a->di_state == DI_COMPLETE) {
                    367:                ta = &(a->di_entry->e_dsainfo->dsa_addr->pa_addr.sa_addr);
                    368:                tb = &(b->di_entry->e_dsainfo->dsa_addr->pa_addr.sa_addr);
                    369:                dna = a->di_dn;
                    370:                dnb = b->di_dn;
                    371:        } else {
                    372:                /* Use 1 access point only */
                    373:                ta = &(a->di_accesspoints->ap_address->pa_addr.sa_addr);
                    374:                tb = &(b->di_accesspoints->ap_address->pa_addr.sa_addr);
                    375:        }
                    376: 
                    377:        /* ta2norm return a static buffer */
                    378:        ta = ta2norm (ta);
                    379:        nas = *(ta->ta_addrs);  /* struct copy */
                    380:        na = &nas;
                    381:        tb = ta2norm (tb);
                    382:        nb = tb->ta_addrs;
                    383: 
                    384:        /* normalised, so look for first "na" match with ts_communities */
                    385:        for (ip = ts_communities; *ip; ip++) {
                    386:                if (*ip == na->na_community) {
                    387:                        if (*ip == nb->na_community)
                    388:                                break;          /* same primary community */
                    389:                        return 1;               /* 'a' preferred */
                    390:                }
                    391:                if (*ip == nb->na_community)
                    392:                        return -1;              /* 'b' preferred */
                    393:        }
                    394: 
                    395:        /* Look at the DSA name to detect locality */
                    396:        ma=0;
                    397:        for (dnptr=dna, mydnptr=mydsadn ;
                    398:                (dnptr!=NULLDN) && (mydnptr!=NULLDN) ;
                    399:                dnptr=dnptr->dn_parent, mydnptr=mydnptr->dn_parent) {
                    400:                if (rdn_cmp(dnptr->dn_rdn,mydnptr->dn_rdn) == 0)
                    401:                        ma++;
                    402:        }
                    403: 
                    404:        mb=0;
                    405:        for (dnptr=dnb, mydnptr=mydsadn ;
                    406:                (dnptr!=NULLDN) && (mydnptr!=NULLDN) ;
                    407:                dnptr=dnptr->dn_parent, mydnptr=mydnptr->dn_parent) {
                    408:                if (rdn_cmp(dnptr->dn_rdn,mydnptr->dn_rdn) == 0)
                    409:                        mb++;
                    410:        }
                    411: 
                    412:        if (ma != mb)
                    413:                return (ma > mb ? 1 : -1);
                    414: 
                    415:        /* check the DMD - NYI */
                    416:        return 0;       
                    417: }
                    418: 
                    419: static di_cmp (a,b)
                    420: struct di_block *a, *b;
                    421:     /*
                    422:     *  Select best di_block
                    423:     *    rule 1: deferred dsa infos have lowest preference, 
                    424:     *           complete have highest.
                    425:     *
                    426:     *  If two block have same state, select using
                    427:     *    preference 1: quipu DSAs with quipu context
                    428:     *    preference 2: quipu DSAs
                    429:     *    preference 3: reliable DSAs
                    430:     *    preference 4: local DSAs
                    431:     */
                    432: {
                    433: int x,y;
                    434: 
                    435:        if (a->di_state != b->di_state)
                    436:                return (a->di_state > b->di_state ? -1 : 1);    /* rule 1 */
                    437: 
                    438:        switch (a->di_state) {
                    439:        case DI_DEFERRED:
                    440:                break;  
                    441:        case DI_ACCESSPOINT:
                    442:                if ((x = di_cmp_address(a,b)) != 0) {
                    443:                        DLOG (log_dsap,LLOG_TRACE,("AP selected on address"));
                    444:                        return x;       /* preference 4 - no info to asses 1,2 or 3 */
                    445:                }
                    446:                break;
                    447:        case DI_COMPLETE:
                    448:                x = quipu_ctx_supported (a->di_entry);
                    449:                y = quipu_ctx_supported (b->di_entry);
                    450:                if ( x != y ) {
                    451:                        DLOG (log_dsap,LLOG_TRACE,("DSA selected on context"));
                    452:                        return ( x > y ? 1 : -1);       /* preference 1 or 2 */
                    453:                }
                    454: 
                    455:                if ((x=di_cmp_reliability (a,b)) != 0) {
                    456:                        DLOG (log_dsap,LLOG_TRACE,("DSA selected on relibility"));
                    457:                        return x;                       /* preference 3 */
                    458:                }
                    459: 
                    460:                if ((x=di_cmp_address(a,b)) != 0) {
                    461:                        DLOG (log_dsap,LLOG_TRACE,("DSA selected on address"));
                    462:                        return x;               /* preference 4 */
                    463:                }
                    464: 
                    465:                break;
                    466:        }
                    467: 
                    468:        return (di_prefer_dsa(a->di_dn, b->di_dn));
                    469: }
                    470: 
                    471: 
                    472: sort_dsa_list (dsas)
                    473: struct di_block        **dsas;
                    474: {
                    475: struct di_block        *trail;
                    476: struct di_block        *old_di, *new_di;
                    477: struct di_block *result;
                    478: char changed = FALSE;
                    479: 
                    480:        /* turn access point into complete references if possible */
                    481:        di_ap2comp (dsas);
                    482: 
                    483:        result = *dsas;
                    484:        if ((old_di = result->di_next) == NULL_DI_BLOCK)
                    485:                return;         /* only 1 - must be sorted !!! */
                    486: 
                    487:        result->di_next = NULL_DI_BLOCK;
                    488: 
                    489:        for(; old_di != NULL_DI_BLOCK; ) {
                    490:                trail = NULL_DI_BLOCK;
                    491:                for(new_di = result; new_di != NULL_DI_BLOCK; new_di= new_di->di_next) {
                    492:                        if ( di_cmp (old_di,new_di) > 0 ) {
                    493:                                if (trail == NULL_DI_BLOCK) {
                    494:                                        result = old_di;
                    495:                                        old_di = old_di->di_next;
                    496:                                        result->di_next = new_di;
                    497:                                } else {
                    498:                                        trail->di_next = old_di;
                    499:                                        old_di = old_di->di_next;
                    500:                                        trail->di_next->di_next = new_di;
                    501:                                }
                    502:                                changed = TRUE;
                    503:                                break;
                    504:                        }
                    505:                        trail = new_di;
                    506:                } 
                    507:                if (new_di == NULL_DI_BLOCK) {
                    508:                        trail->di_next = old_di;
                    509:                        old_di = old_di->di_next;
                    510:                        trail->di_next->di_next = NULL_DI_BLOCK;
                    511:                } 
                    512:        }
                    513:        *dsas = result;
                    514: 
                    515:        if (changed) {
                    516:                LLOG (log_dsap,LLOG_TRACE,("DSA order changed"));
                    517: #ifdef DEBUG
                    518:                di_list_log (result);
                    519: #endif
                    520:        } else
                    521:                DLOG (log_dsap,LLOG_TRACE,("DSA order not changed"));
                    522: 
                    523: }
                    524: 
                    525: static int       common_address (a,tb)
                    526: struct di_block *a;
                    527: struct TSAPaddr *tb;
                    528: {
                    529: struct TSAPaddr *ta;
                    530: struct NSAPaddr *na;
                    531: struct NSAPaddr *nb;
                    532: int x,y;
                    533: 
                    534:        /* select DSA with best looking address !!! */
                    535: 
                    536:        if (a->di_state == DI_DEFERRED)
                    537:                return FALSE;
                    538: 
                    539:        if (a->di_state == DI_COMPLETE)
                    540:                ta = &(a->di_entry->e_dsainfo->dsa_addr->pa_addr.sa_addr);
                    541:        else
                    542:                /* Use 1 access point only */
                    543:                ta = &(a->di_accesspoints->ap_address->pa_addr.sa_addr);
                    544: 
                    545:        /* compare ta and tb to see if they have a network in common */
                    546:        for (na=ta->ta_addrs , x = ta->ta_naddr - 1 ;
                    547:                        x >= 0;
                    548:                        na++, x-- ) {
                    549:                for (nb=tb->ta_addrs , y = tb->ta_naddr - 1 ;
                    550:                                y >= 0;
                    551:                                nb++, y-- ) {
                    552:                        if (na->na_community == nb->na_community)
                    553:                                return TRUE;
                    554:                                }
                    555:                        }
                    556:        return FALSE;
                    557: }
                    558: 
                    559: 
                    560: struct di_block * select_refer_dsa(di,tk)
                    561: struct di_block *di;
                    562: struct task_act *tk;
                    563: {
                    564: struct di_block *best;
                    565: struct di_block *loop;
                    566: Entry eptr;
                    567: struct TSAPaddr *ta;
                    568: DN rdsa;
                    569: 
                    570:        /* return the di block of the best DSA the other end should be
                    571:           to contact...
                    572:           If it can't contact any - return NULL
                    573:         */
                    574: 
                    575:        if (di != NULL_DI_BLOCK)
                    576:                best = di;
                    577:        else
                    578:                best = NULL_DI_BLOCK;
                    579: 
                    580:        /* First set - find out who the remote end is... */
                    581:        if (tk->tk_conn->cn_ctx == DS_CTX_X500_DAP)
                    582:                return best;    /* we will chain anyway - unless prevented by service control... */
                    583: 
                    584:        rdsa = tk->tk_conn->cn_dn;
                    585:        if ((eptr=local_find_entry (rdsa,FALSE)) == NULLENTRY)
                    586:                return best;    /* no way of knowing */
                    587: 
                    588:        if (eptr->e_dsainfo == NULLDSA) 
                    589:                return best;    /* no way of knowing */
                    590: 
                    591:        ta = &(eptr->e_dsainfo->dsa_addr->pa_addr.sa_addr);
                    592:        ta = ta2norm (ta);      /* calculate subnets... */
                    593: 
                    594:        for (loop=di; loop!=NULL_DI_BLOCK; loop=loop->di_next)
                    595:                if (common_address (loop,ta))
                    596:                        return loop;
                    597: 
                    598:        /* nothing on the same network - chain if possible !!! */
                    599:        return NULL_DI_BLOCK;   
                    600: }
                    601: 

unix.superglobalmegacorp.com

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