1: /* $Header: CHlookup.c,v 2.0 85/11/21 07:22:32 jqj Exp $ */ 2: 3: /* contains: 4: * CH_LookupAddr 5: * CH_GetFirstCH 6: * CH_GetOtherCH 7: * CH_NameDefault 8: */ 9: 10: /* $Log: CHlookup.c,v $ 11: * Revision 2.0 85/11/21 07:22:32 jqj 12: * 4.3BSD standard release 13: * 14: * Revision 1.3 85/11/21 07:14:19 jqj 15: * 4.3BSD standard release 16: * 17: * Revision 1.2 85/10/21 12:41:55 jqj 18: * Gould version: work around a Gould compiler bug. Default to /usr/new 19: * for consistency. 20: * 21: * Revision 1.1 85/10/18 09:14:53 jqj 22: * Initial revision 23: * 24: * Revision 1.1 85/03/26 06:27:00 jqj 25: * Initial revision 26: * 27: */ 28: #include <stdio.h> 29: #include <sys/types.h> 30: #include <netns/ns.h> 31: #include <xnscourier/Clearinghouse2.h> 32: #include <xnscourier/CHEntries.h> 33: #include <xnscourier/except.h> 34: #define MAXPACKS 5 35: #define NLSIZE 50 36: 37: static Clearinghouse2_ObjectName *namelist[NLSIZE]; 38: static int nlcount = 0; 39: 40: static Cardinal nullpasswd = 0; 41: static Clearinghouse2_Authenticator nullagent = {{0,{0,0}},{1,&nullpasswd}}; 42: 43: static 44: GetData(conn) 45: CourierConnection *conn; 46: { 47: int count, i; 48: Unspecified buffer[MAXWORDS*MAXPACKS], *bp, *bufend; 49: Clearinghouse2_StreamOfObjectName obnames; 50: 51: bufend = buffer; 52: bp = buffer+((MAXWORDS-1)*MAXPACKS); /* end of available space */ 53: while (count = BDTread(conn, (char*)bufend, 54: MAXWORDS*sizeof(Unspecified)) 55: ) { 56: bufend += count/sizeof(Unspecified); 57: if (bufend > bp) { 58: fprintf(stderr,"BDT read too big to fit\n"); 59: BDTabort(conn); 60: /* should clear out stuff here if we knew how much */ 61: } 62: } 63: bp = buffer; 64: while (bp < bufend) { 65: bp += internalize_Clearinghouse2_StreamOfObjectName(&obnames,bp); 66: if (0 == (int) obnames.designator) { 67: for (i = 0; i < obnames.nextSegment_case.segment.length; i++) 68: if (nlcount < NLSIZE) namelist[nlcount++] = 69: &obnames.nextSegment_case.segment.sequence[i]; 70: } else { 71: for (i = 0; i < obnames.lastSegment_case.length; i++) 72: if (nlcount < NLSIZE) namelist[nlcount++] = 73: &obnames.lastSegment_case.sequence[i]; 74: return; 75: } 76: } 77: } 78: 79: static struct ns_addr* 80: itemtonsaddr(itemptr) 81: Clearinghouse2_Item *itemptr; /* i.e. a sequence of Unspecified */ 82: { 83: static union { 84: struct ns_addr addr; 85: u_short shrt[6]; 86: } result; 87: register int i; 88: register Unspecified *seq; 89: 90: if (itemptr->length < 7) 91: return(0); 92: 93: seq = itemptr->sequence +1; 94: /* itemptr->sequence[0] == number of addresses */ 95: for (i = 0; i < 6; i++, seq++) 96: result.shrt[i] = ntohs(*seq); 97: return(&result.addr); 98: } 99: 100: /* 101: * path to look for the addresses file on 102: * (I wish I'd picked a shorter name, so we could rendezvous in /etc. 103: * But long file names in /etc are very unpopular!). 104: */ 105: static char *chaddrpath[] = { 106: #ifdef CHADDRS 107: CHADDRS, 108: #endif 109: "/usr/new/lib/xnscourier/clearinghouse.addresses", 110: "/etc/clearinghouse.addresses", 111: "/usr/local/lib/xnscourier/clearinghouse.addresses", 112: 0 }; 113: 114: 115: /* 116: * Set defaults for organization and domain, based on the file 117: * /usr/local/lib/xnscourier/clearinghouse.addresses 118: * (should get the local clearinghouse and set defaults based on 119: * ListDomainsServed 120: */ 121: CH_NameDefault(defaultobjnamep) 122: Clearinghouse2_ObjectName *defaultobjnamep; 123: { 124: FILE *chfile; 125: int i, nmatch; 126: static char orgbuf[21], domainbuf[21]; 127: 128: defaultobjnamep->object = ""; 129: for (i=0; chaddrpath[i] != NULL; i++) { 130: chfile = fopen(chaddrpath[i],"r"); 131: if (chfile != (FILE*)0) { 132: nmatch = fscanf(chfile,"%*[^ \t\n] \":%[^:]:%[^\"]", 133: domainbuf, orgbuf); 134: fclose(chfile); 135: if (nmatch == 2) { 136: defaultobjnamep->domain = domainbuf; 137: defaultobjnamep->organization = orgbuf; 138: return; /* done */ 139: } 140: } 141: } 142: defaultobjnamep->organization = ""; 143: defaultobjnamep->domain = ""; 144: } 145: 146: 147: CourierConnection* 148: CH_GetFirstCH() 149: { 150: struct ns_addr *chaddr; 151: extern struct ns_addr *getXNSaddr(); 152: char buf[BUFSIZ]; 153: CourierConnection *result; 154: FILE *chfile; 155: int i; 156: 157: /* for now, use hard-coded CH */ 158: /* eventually we'll do an expanding-ring or something */ 159: result = (CourierConnection *) NULL; 160: for (i = 0; chaddrpath[i] != NULL; i++) { 161: if ((chfile = fopen(chaddrpath[i],"r")) != NULL) { 162: while (fgets(buf, BUFSIZ, chfile)) 163: if ((chaddr = getXNSaddr(buf)) && 164: (result = CourierOpen(chaddr))) { 165: fclose(chfile); 166: return(result); 167: } 168: fclose(chfile); 169: break; /* don't look for other files */ 170: } 171: } 172: /* try expanding-ring here */ 173: return(result); 174: } 175: 176: CourierConnection * 177: CH_GetOtherCH(conn,hint) 178: CourierConnection *conn; 179: Clearinghouse2_ObjectName hint; 180: { 181: struct ns_addr *ch2addr; 182: CourierConnection *ch2conn; 183: Clearinghouse2_RetrieveItemResults riresult; 184: Clearinghouse2_RetrieveMembersResults rmresult; 185: int i; 186: 187: Clearinghouse2_Property clearinghouseNames = 3; 188: Clearinghouse2_Property clearinghouseAddresses = 4; 189: Clearinghouse2_ObjectName hint1; 190: 191: DURING 192: /* get list of possible other clearinghouses */ 193: rmresult = Clearinghouse2_RetrieveMembers(conn, GetData, hint, 194: clearinghouseNames, BulkData1_immediateSink, 195: nullagent); 196: HANDLER { 197: /* some race condition */ 198: return(NULL); 199: } END_HANDLER; 200: /* throw away the distinguished name, which we don't need */ 201: clear_Clearinghouse2_RetrieveMembersResults(&rmresult); 202: /* for each member of potentials list, probe it */ 203: ch2conn = NULL; 204: for (i = 0; i < nlcount; i++) { 205: Clearinghouse2_ObjectName thisname; 206: thisname = *namelist[i]; 207: /* get its address */ 208: DURING 209: riresult = Clearinghouse2_RetrieveItem(conn, NULL, 210: thisname, 211: clearinghouseAddresses, nullagent); 212: HANDLER 213: continue; /* try next in namelist */ 214: END_HANDLER; 215: ch2addr = itemtonsaddr(&riresult.value); 216: clear_Clearinghouse2_RetrieveItemResults(&riresult); 217: ch2conn = CourierOpen(ch2addr); 218: if (ch2conn == NULL) continue; 219: /* make sure the second CH is really there */ 220: DURING 221: (void) Clearinghouse2_RetrieveAddresses(ch2conn, NULL); 222: HANDLER { 223: CourierClose(ch2conn); 224: ch2conn = NULL; 225: continue; 226: } END_HANDLER; 227: /* we got it! */ 228: break; 229: } 230: for (i = 0; i < nlcount; i++) { 231: /* free namelist[i] components */ 232: clear_Clearinghouse2_ObjectName(namelist[i]); 233: /* free the top level thing too */ 234: Deallocate((Unspecified*) namelist[i]); 235: } 236: return(ch2conn); 237: } 238: 239: /* 240: * Given a Clearinghouse three part name (possibly containing wild cards) 241: * and the property number on which a NetworkAddress is expected to occur, 242: * returns the ns_addr structure associated with that name. 243: * Note that the ns_addr structure is statically allocated! 244: * Resets pattern to be the distinguished name of the object found. 245: */ 246: struct ns_addr * 247: CH_LookupAddr(pattern,property) 248: Clearinghouse2_ObjectNamePattern pattern; 249: Clearinghouse2_Property property; 250: { 251: struct ns_addr* CH_LookupAddrDN(); 252: return(CH_LookupAddrDN(pattern,property,0,0)); 253: } 254: 255: /* 256: * Lookup a clearinghouse address, returning the address and the 257: * distinguished name of the object found. 258: */ 259: struct ns_addr * 260: CH_LookupAddrDN(pattern,property,distnamep,distnamelen) 261: Clearinghouse2_ObjectNamePattern pattern; 262: Clearinghouse2_Property property; 263: char *distnamep; 264: int distnamelen; 265: { 266: struct ns_addr *chaddr, *resultaddr; 267: CourierConnection *conn, *ch2conn; 268: Clearinghouse2_ObjectName hint; /* from WrongServer errors */ 269: Clearinghouse2_RetrieveItemResults riresult; 270: 271: 272: if ((long) property <= 0) /* default to addressList i.e. 4 */ 273: property = CHEntries0_addressList; 274: if (pattern.object == NULL || 275: pattern.domain == NULL || 276: pattern.organization == NULL) 277: return(NULL); /* can't handle defaults */ 278: 279: if ((conn = CH_GetFirstCH()) == NULL) { 280: fprintf(stderr,"Can't open connection to local Clearinghouse\n"); 281: exit(1); 282: } 283: /* ask our primary clearinghouse for the address of this thing */ 284: DURING { 285: riresult = Clearinghouse2_RetrieveItem(conn, NULL, 286: pattern, property, nullagent); 287: } HANDLER { 288: if (Exception.Code != Clearinghouse2_WrongServer) { 289: CourierClose(conn); 290: return(0); /* some random error */ 291: } 292: hint = CourierErrArgs(Clearinghouse2_WrongServerArgs, hint); 293: ch2conn = CH_GetOtherCH(conn, hint); 294: CourierClose(conn); 295: if (ch2conn == NULL) return(0); 296: conn = ch2conn; 297: /* probe the second clearinghouse */ 298: DURING 299: riresult = Clearinghouse2_RetrieveItem(conn, NULL, 300: pattern, property, nullagent); 301: HANDLER { 302: /* should be smarter if WrongServer here */ 303: CourierClose(conn); 304: return(0); 305: } END_HANDLER; 306: /* we got it */ 307: } END_HANDLER; 308: resultaddr = itemtonsaddr(&riresult.value); 309: if (distnamep != NULL && 310: distnamelen >= (2+strlen(riresult.distinguishedObject.object)+ 311: strlen(riresult.distinguishedObject.domain)+ 312: strlen(riresult.distinguishedObject.organization))) 313: sprintf(distnamep,"%s:%s:%s", 314: riresult.distinguishedObject.object, 315: riresult.distinguishedObject.domain, 316: riresult.distinguishedObject.organization); 317: clear_Clearinghouse2_RetrieveItemResults(&riresult); 318: CourierClose(conn); 319: return(resultaddr); 320: }