Annotation of 43BSDTahoe/new/xns/morexnslib/ch/CHlookup.c.org, revision 1.1.1.1

1.1       root        1: /* $Header: CHlookup.c,v 2.4 87/03/14 06:41:56 jqj Exp $ */
                      2: 
                      3: /* contains:
                      4:  * CH_LookupAddr
                      5:  * CH_GetFirstCH
                      6:  * CH_GetOtherCH
                      7:  */
                      8: 
                      9: /* $Log:       CHlookup.c,v $
                     10:  * Revision 2.4  87/03/14  06:41:56  jqj
                     11:  * major changes to CH location algorithm.
                     12:  * changed LookupAddressDN to use new simpler semantics (can call GetOtherCH
                     13:  * many times)
                     14:  * 
                     15:  * Revision 2.3  87/01/05  11:58:47  ed
                     16:  * Webster changes
                     17:  * 
                     18:  * Revision 2.3  87/01/05  11:58:47  ed
                     19:  * Eliminate hard file name for BFS and use BFS definition instead
                     20:  * 
                     21:  * Revision 2.2  86/06/30  12:23:48  jqj
                     22:  * 1/ convert BDT read to dynamically allocate a buffer, and grow it if
                     23:  * necessary using realloc().  This should fix problems with support at
                     24:  * Xerox, where they have so many CHes that we were running out of space.
                     25:  * 2/ convert CH_GetFirstCH() to use /usr/new/xnsbfs if CH.default fails
                     26:  * to find a CH.  xnsbfs does an expanding ring, or at least a local,
                     27:  * broadcast for servers.
                     28:  * 
                     29:  * Revision 2.1  86/06/05  09:12:48  jqj
                     30:  * Split out CHdefault.c from this file.  The path to the addresses file
                     31:  * is now found in that file.
                     32:  * 
                     33:  * Revision 2.0  85/11/21  07:22:32  jqj
                     34:  * 4.3BSD standard release
                     35:  * 
                     36:  * Revision 1.3  85/11/21  07:14:19  jqj
                     37:  * first try at 4.3BSD standard release
                     38:  * 
                     39:  * Revision 1.2  85/10/21  12:41:55  jqj
                     40:  * Gould version:  work around a Gould compiler bug.  Default to /usr/new
                     41:  * for consistency.
                     42:  * 
                     43:  * Revision 1.1  85/10/18  09:14:53  jqj
                     44:  * Initial revision
                     45:  * 
                     46:  * Revision 1.1  85/03/26  06:27:00  jqj
                     47:  * Initial revision
                     48:  * 
                     49:  */
                     50: #include <stdio.h>
                     51: #include <sys/types.h>
                     52: #include <netns/ns.h>
                     53: #include <xnscourier/Clearinghouse2.h>
                     54: #include <xnscourier/CHEntries.h>
                     55: #include <xnscourier/except.h>
                     56: #include <sys/file.h>
                     57: 
                     58: #ifndef BFS
                     59: #define BFS "/usr/new/xnsbfs"
                     60: #endif
                     61: 
                     62: /* data structures for very simple (null) authentication */
                     63: static Cardinal nullpasswd = 0;
                     64: static Clearinghouse2_Authenticator nullagent = {{0,{0,0}},{1,&nullpasswd}};
                     65: 
                     66: /*
                     67:  * This is an entry in the in-core cache of known clearinghouses.
                     68:  * chl_name    Each entry has a name, which may be null for entries 
                     69:  *   obtained by expanding ring broadcast or initial table lookup.  A 
                     70:  *   particular address may appear in the list multiple times with 
                     71:  *   different or null names, but mostly the entries are unique.
                     72:  * chl_addr    The address is one of the addresses given for this 
                     73:  *   host.  For multihomed CHs, no attempt is made to make sure that 
                     74:  *   this address is optimal.
                     75:  * chl_status  The status of the entry, one of:
                     76:  *     chunknown       address invalid.
                     77:  *     chdown          did not answer when probed.
                     78:  *     chup            address valid, and responds to RetrieveAddresses.
                     79:  *     chused          has been returned to caller of GetCH routines
                     80:  *                     as a valid CH.  Hence GetOtherCH will not return it 
                     81:  *                     again.  Note that GetFirstCH resets chused->chup.
                     82:  * chl_next    Link to next clearinghouse in database.
                     83:  * chl_domains [NOT YET USED] List of domains served, for efficiency
                     84:  */
                     85: struct chlist {
                     86:        Clearinghouse2_ObjectName *chl_name;
                     87:        struct ns_addr chl_addr;
                     88:        enum {chunknown, chup, chdown, chused} chl_status;
                     89:        struct Clearinghouse2_TwoPartName *chl_domains;
                     90:        struct chlist *chl_next;
                     91: };
                     92: struct chlist *namelist = NULL;
                     93: 
                     94: /*
                     95:  * add a clearinghouse name to the ch list if it isn't already there.
                     96:  * Initial state is chunknown, since we don't know its address and can't
                     97:  * probe it.
                     98:  */
                     99: static struct chlist *
                    100: addtochlist(ch_name)
                    101:        Clearinghouse2_ObjectName *ch_name;
                    102: {
                    103:        struct chlist *chptr;
                    104:        extern char *malloc();
                    105: 
                    106:        if (ch_name != NULL) /* don't eliminate duplicate anonymous entries */
                    107:            for (chptr = namelist; chptr != NULL; chptr = chptr->chl_next) {
                    108:                if ( chptr->chl_name &&
                    109:                    (strcmp(chptr->chl_name->object,ch_name->object)==0) &&
                    110:                    (strcmp(chptr->chl_name->domain,ch_name->domain)==0) &&
                    111:                    (strcmp(chptr->chl_name->organization,
                    112:                            ch_name->organization)==0)) {
                    113:                        clear_Clearinghouse2_ObjectName(ch_name); /* dealloc */
                    114:                        return NULL;    /* already in list */
                    115:                }
                    116:            }
                    117:        chptr = (struct chlist *) malloc(sizeof(struct chlist));
                    118:        chptr->chl_name = ch_name;
                    119:        chptr->chl_status = chunknown;
                    120:        chptr->chl_next = namelist;
                    121:        namelist = chptr;
                    122:        return chptr;
                    123: }
                    124: 
                    125: static
                    126: GetData(conn)
                    127:        CourierConnection *conn;
                    128: {
                    129:        int count, i;
                    130:        int bufused, bufsize;
                    131:        Unspecified *buffer, *bp;
                    132:        Clearinghouse2_StreamOfObjectName obnames;
                    133:        
                    134:        bufsize = MAXWORDS*4;    /* end of available space */
                    135:        buffer = Allocate(bufsize);
                    136:        bufused = 0;            /* number of words used */
                    137:        while (count = BDTread(conn, (char*)(buffer+bufused), 
                    138:                                MAXWORDS*sizeof(Unspecified))
                    139:                ) {
                    140:                bufused += count/sizeof(Unspecified);
                    141:                /* leave room for one last packet */
                    142:                if (bufused+MAXWORDS > bufsize) {
                    143:                        bufsize += bufsize;     /* double our space */
                    144:                        buffer = (Unspecified *) realloc((char *) buffer,
                    145:                                                bufsize*sizeof(Unspecified));
                    146:                }
                    147:        }
                    148:        bp = buffer;
                    149:        while (bp-buffer < bufused) {
                    150:                bp += internalize_Clearinghouse2_StreamOfObjectName(&obnames,bp);
                    151:                if (0 == (int) obnames.designator) {
                    152:                   for (i = 0; i < obnames.nextSegment_case.segment.length; i++)
                    153:                        addtochlist(
                    154:                                &obnames.nextSegment_case.segment.sequence[i]);
                    155:                } else {
                    156:                   for (i = 0; i < obnames.lastSegment_case.length; i++)
                    157:                        addtochlist(
                    158:                                &obnames.lastSegment_case.sequence[i]);
                    159:                   Deallocate(buffer);
                    160:                   return;
                    161:                }
                    162:        }
                    163:        Deallocate(buffer);
                    164:        return;
                    165: }
                    166: 
                    167: static struct ns_addr*
                    168: itemtonsaddr(itemptr)
                    169:        Clearinghouse2_Item *itemptr;   /* i.e. a sequence of Unspecified */
                    170: {
                    171:        static union {
                    172:                struct ns_addr addr;
                    173:                u_short shrt[6];
                    174:        } result;
                    175:        register int i;
                    176:        register Unspecified *seq;
                    177: 
                    178:        if (itemptr->length < 7)
                    179:                return(0);
                    180: 
                    181:        seq = itemptr->sequence +1;
                    182:        /* itemptr->sequence[0] == number of addresses */
                    183:        for (i = 0; i < 6; i++, seq++)
                    184:                result.shrt[i] = ntohs(*seq);
                    185:        return(&result.addr);
                    186: }
                    187: 
                    188: /*
                    189:  * Open an SPP connection to the address given as chaddr, then
                    190:  * check whether the CHS pointed to by conn is up.  If not, close
                    191:  * conn and return 0.  If so, return the connection.
                    192:  */
                    193: static CourierConnection*
                    194: ClearinghouseOpen(chaddr)
                    195:        struct ns_addr chaddr;
                    196: {
                    197:        CourierConnection *conn;
                    198:        Clearinghouse2_RetrieveAddressesResults raresult;
                    199: 
                    200:        if ((conn = CourierOpen(&chaddr)) == NULL)
                    201:                return(conn);
                    202:        DURING
                    203:            raresult = Clearinghouse2_RetrieveAddresses(conn,NULL);
                    204:        HANDLER {
                    205:            CourierClose(conn);
                    206:            conn = NULL;
                    207:        } END_HANDLER;
                    208:        clear_Clearinghouse2_RetrieveAddressesResults(&raresult);
                    209:        return(conn);
                    210: }
                    211: 
                    212: /*
                    213:  * path to look for the addresses file on
                    214:  * (I wish I'd picked a shorter name, so we could rendezvous in /etc.
                    215:  *  But long file names in /etc are very unpopular!).
                    216:  * This path is defined n CHdefault.c, and used by CH_NameDefault()
                    217:  */
                    218: extern char *chaddrpath[];
                    219: 
                    220: CourierConnection*
                    221: CH_GetFirstCH()
                    222: {
                    223:        struct ns_addr chaddr;
                    224:        extern struct ns_addr *getXNSaddr();
                    225:        extern struct ns_addr ns_addr();
                    226:        char buf[BUFSIZ];
                    227:        CourierConnection *result;
                    228:        FILE *chfile;
                    229:        struct chlist *chptr;
                    230:        int i;
                    231: 
                    232:        result = (CourierConnection *) NULL;
                    233:        /* first, look in the process cache */
                    234:        for (chptr = namelist; chptr != NULL; chptr = chptr->chl_next) {
                    235:                switch (chptr->chl_status) {
                    236:                case chunknown:
                    237:                case chdown:
                    238:                        break;
                    239:                case chused:
                    240:                        chptr->chl_status = chup;
                    241:                case chup:
                    242:                        if (result == NULL)
                    243:                                result = ClearinghouseOpen(chptr->chl_addr);
                    244:                }
                    245:        }
                    246:        if (result) return(result);
                    247: 
                    248:        /* Now, use hard-coded CH */
                    249:        /* eventually we'll do an expanding-ring or something */
                    250:        for (i = 0; chaddrpath[i] != NULL; i++) {
                    251:                if ((chfile = fopen(chaddrpath[i],"r")) == NULL)
                    252:                        continue;
                    253:                flock(fileno(chfile),LOCK_SH);
                    254:                while (fgets(buf, BUFSIZ, chfile) != NULL)
                    255:                        if ((buf[0] != '#') &&
                    256:                            (chaddr = ns_addr(buf),
                    257:                             result = ClearinghouseOpen((chaddr)))) {
                    258:                                if ((chptr = addtochlist(NULL))) {
                    259:                                        chptr->chl_addr = chaddr;
                    260:                                        chptr->chl_status = chused;
                    261:                                }
                    262:                                flock(fileno(chfile),LOCK_UN);
                    263:                                fclose(chfile);
                    264:                                return(result);
                    265:                        }
                    266:                flock(fileno(chfile),LOCK_UN);
                    267:                fclose(chfile);
                    268:                break;  /* don't look for other files */
                    269:        }
                    270:        /* try expanding-ring here -- this could be more efficient! */
                    271:        if ((chfile = popen(BFS,"r")) != NULL) {
                    272:                while (fgets(buf, BUFSIZ, chfile) != NULL)
                    273:                        if ((buf[0] != '#') &&
                    274:                            (chaddr=ns_addr(buf),
                    275:                             result = ClearinghouseOpen(chaddr))) {
                    276:                                if ((chptr = addtochlist(NULL))) {
                    277:                                        chptr->chl_addr = chaddr;
                    278:                                        chptr->chl_status = chused;
                    279:                                }
                    280:                                pclose(chfile);
                    281:                                return(result);
                    282:                        }
                    283:                pclose(chfile);
                    284:        }
                    285:        return(result);
                    286: }
                    287: 
                    288: CourierConnection *
                    289: CH_GetOtherCH(conn,hint)
                    290:        CourierConnection *conn;
                    291:        Clearinghouse2_ObjectName hint;
                    292: {
                    293:        struct ns_addr *ch2addr;
                    294:        CourierConnection *ch2conn, *chresult;
                    295:        Clearinghouse2_RetrieveItemResults riresult;
                    296:        Clearinghouse2_RetrieveMembersResults rmresult;
                    297:        struct chlist *chptr;
                    298: 
                    299:        Clearinghouse2_Property clearinghouseNames = 3;
                    300:        Clearinghouse2_Property clearinghouseAddresses = 4;
                    301: 
                    302:        if (hint.object != NULL && *hint.object != '\0') {
                    303:            DURING
                    304:                    /* get list of possible other clearinghouses */
                    305:                    rmresult = Clearinghouse2_RetrieveMembers(conn, GetData, hint, 
                    306:                            clearinghouseNames, BulkData1_immediateSink,
                    307:                            nullagent);
                    308:            HANDLER {
                    309:                    /* some race condition */
                    310:                    return(NULL);
                    311:            } END_HANDLER;
                    312:            /* throw away the distinguished name, which we don't need */
                    313:            clear_Clearinghouse2_RetrieveMembersResults(&rmresult);
                    314:        }
                    315:        /* for each member of potentials list, probe it */
                    316:        ch2conn = chresult = NULL;
                    317:        for (chptr = namelist; chptr != NULL; chptr = chptr->chl_next) {
                    318:            switch (chptr->chl_status) {
                    319:            case chunknown:     /* a new entry, presumably */
                    320:                /* get its address */
                    321:                DURING
                    322:                        riresult = Clearinghouse2_RetrieveItem(conn, NULL, 
                    323:                                *(chptr->chl_name),
                    324:                                clearinghouseAddresses, nullagent);
                    325:                HANDLER
                    326:                        break;  /* try next in namelist */
                    327:                END_HANDLER;
                    328:                chptr->chl_addr = *itemtonsaddr(&riresult.value);
                    329:                clear_Clearinghouse2_RetrieveItemResults(&riresult);
                    330:                chptr->chl_status = chdown;
                    331:                /* fall through to: */
                    332:            case chdown:        /* check down CH to see if it has revived */
                    333:                /* make sure the second CH is really there */
                    334:                if ((ch2conn = ClearinghouseOpen(chptr->chl_addr))) {
                    335:                        chptr->chl_status = chup; /* we got it! */
                    336:                        if (chresult == NULL) {
                    337:                                chresult = ch2conn;
                    338:                                chptr->chl_status = chused;
                    339:                        }
                    340:                        else CourierClose(ch2conn);
                    341:                        ch2conn = NULL;
                    342:                }
                    343:                break;
                    344:            case chup:
                    345:            case chused:
                    346:                break;
                    347:            } /* end of switch */
                    348:        } /* inspect next in list */
                    349:        /* 
                    350:         * if no new one, return an old one
                    351:         */
                    352:        for (chptr= namelist; chptr && (chresult==NULL); chptr= chptr->chl_next) {
                    353:                if (chptr->chl_status == chup) {
                    354:                    chptr->chl_status =
                    355:                        (chresult=ClearinghouseOpen(chptr->chl_addr))
                    356:                                        ? chused : chdown;
                    357:                }
                    358:        }
                    359:        return(chresult);
                    360: }
                    361: 
                    362: /*
                    363:  * Given a Clearinghouse three part name (possibly containing wild cards)
                    364:  * and the property number on which a NetworkAddress is expected to occur,
                    365:  * returns the ns_addr structure associated with that name.
                    366:  * Note that the ns_addr structure is statically allocated!
                    367:  * Resets pattern to be the distinguished name of the object found.
                    368:  */
                    369: struct ns_addr *
                    370: CH_LookupAddr(pattern,property)
                    371:        Clearinghouse2_ObjectNamePattern pattern;
                    372:        Clearinghouse2_Property property;
                    373: {
                    374:        struct ns_addr* CH_LookupAddrDN();
                    375:        return(CH_LookupAddrDN(pattern,property,0,0));
                    376: }
                    377: 
                    378: /*
                    379:  * Lookup a clearinghouse address, returning the address and the
                    380:  * distinguished name of the object found.
                    381:  */
                    382: struct ns_addr *
                    383: CH_LookupAddrDN(pattern,property,distnamep,distnamelen)
                    384:        Clearinghouse2_ObjectNamePattern pattern;
                    385:        Clearinghouse2_Property property;
                    386:        char *distnamep;
                    387:        int distnamelen;
                    388: {
                    389:        struct ns_addr *chaddr, *resultaddr;
                    390:        CourierConnection *conn, *ch2conn;
                    391:        Clearinghouse2_ObjectName hint;         /* from WrongServer errors */
                    392:        Clearinghouse2_RetrieveItemResults riresult;
                    393:        int i;
                    394: 
                    395: 
                    396:        if ((long) property <= 0)       /* default to addressList i.e. 4 */
                    397:                property = CHEntries0_addressList;
                    398:        if (pattern.object == NULL ||
                    399:            pattern.domain == NULL ||
                    400:            pattern.organization == NULL)
                    401:                return(NULL);                   /* can't handle defaults */
                    402:        
                    403:        if ((conn = CH_GetFirstCH()) == NULL) {
                    404:                fprintf(stderr,"Can't open connection to local Clearinghouse\n");
                    405:                exit(1);
                    406:        }
                    407:        /* ask our primary clearinghouse for the address of this thing */
                    408:        for (i = 5; i > 0; i--) {
                    409:            DURING {
                    410:                riresult = Clearinghouse2_RetrieveItem(conn, NULL,
                    411:                                pattern, property, nullagent);
                    412:                i = -1;
                    413:            } HANDLER {
                    414:                if (Exception.Code == REJECT_ERROR) {
                    415:                        fprintf(stderr,"Problem with CH.addrs.  CH rejected request\n");
                    416:                        hint.object = hint.domain = hint.organization = NULL;
                    417:                }
                    418:                else if (Exception.Code != Clearinghouse2_WrongServer) {
                    419:                        /* some random error */
                    420:                        hint.object = hint.domain = hint.organization = NULL;
                    421:                }
                    422:                else hint = CourierErrArgs(Clearinghouse2_WrongServerArgs, hint);
                    423:                ch2conn = CH_GetOtherCH(conn, hint);
                    424:                CourierClose(conn);
                    425:                if (ch2conn == NULL) return(0);
                    426:                conn = ch2conn;
                    427:            } END_HANDLER;
                    428:        }
                    429:        if (i >= 0) {
                    430:            return(0);
                    431:        }
                    432:        resultaddr = itemtonsaddr(&riresult.value);
                    433:        if (distnamep != NULL &&
                    434:            distnamelen >= (2+strlen(riresult.distinguishedObject.object)+
                    435:                            strlen(riresult.distinguishedObject.domain)+
                    436:                            strlen(riresult.distinguishedObject.organization)))
                    437:                strcpy(distnamep,CH_NameToString(riresult.distinguishedObject));
                    438:        clear_Clearinghouse2_RetrieveItemResults(&riresult);
                    439:        CourierClose(conn);
                    440:        return(resultaddr);
                    441: }

unix.superglobalmegacorp.com

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