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