|
|
BSD 4.3tahoe
/* $Header: /var/lib/cvsd/repos/CSRG/43BSDTahoe/new/xns/morexnslib/ch/CHlookup.c.org,v 1.1.1.1 2018/04/24 16:12:58 root Exp $ */
/* contains:
* CH_LookupAddr
* CH_GetFirstCH
* CH_GetOtherCH
*/
/* $Log: CHlookup.c.org,v $
/* Revision 1.1.1.1 2018/04/24 16:12:58 root
/* BSD 4.3tahoe
/*
* Revision 2.4 87/03/14 06:41:56 jqj
* major changes to CH location algorithm.
* changed LookupAddressDN to use new simpler semantics (can call GetOtherCH
* many times)
*
* Revision 2.3 87/01/05 11:58:47 ed
* Webster changes
*
* Revision 2.3 87/01/05 11:58:47 ed
* Eliminate hard file name for BFS and use BFS definition instead
*
* Revision 2.2 86/06/30 12:23:48 jqj
* 1/ convert BDT read to dynamically allocate a buffer, and grow it if
* necessary using realloc(). This should fix problems with support at
* Xerox, where they have so many CHes that we were running out of space.
* 2/ convert CH_GetFirstCH() to use /usr/new/xnsbfs if CH.default fails
* to find a CH. xnsbfs does an expanding ring, or at least a local,
* broadcast for servers.
*
* Revision 2.1 86/06/05 09:12:48 jqj
* Split out CHdefault.c from this file. The path to the addresses file
* is now found in that file.
*
* Revision 2.0 85/11/21 07:22:32 jqj
* 4.3BSD standard release
*
* Revision 1.3 85/11/21 07:14:19 jqj
* first try at 4.3BSD standard release
*
* Revision 1.2 85/10/21 12:41:55 jqj
* Gould version: work around a Gould compiler bug. Default to /usr/new
* for consistency.
*
* Revision 1.1 85/10/18 09:14:53 jqj
* Initial revision
*
* Revision 1.1 85/03/26 06:27:00 jqj
* Initial revision
*
*/
#include <stdio.h>
#include <sys/types.h>
#include <netns/ns.h>
#include <xnscourier/Clearinghouse2.h>
#include <xnscourier/CHEntries.h>
#include <xnscourier/except.h>
#include <sys/file.h>
#ifndef BFS
#define BFS "/usr/new/xnsbfs"
#endif
/* data structures for very simple (null) authentication */
static Cardinal nullpasswd = 0;
static Clearinghouse2_Authenticator nullagent = {{0,{0,0}},{1,&nullpasswd}};
/*
* This is an entry in the in-core cache of known clearinghouses.
* chl_name Each entry has a name, which may be null for entries
* obtained by expanding ring broadcast or initial table lookup. A
* particular address may appear in the list multiple times with
* different or null names, but mostly the entries are unique.
* chl_addr The address is one of the addresses given for this
* host. For multihomed CHs, no attempt is made to make sure that
* this address is optimal.
* chl_status The status of the entry, one of:
* chunknown address invalid.
* chdown did not answer when probed.
* chup address valid, and responds to RetrieveAddresses.
* chused has been returned to caller of GetCH routines
* as a valid CH. Hence GetOtherCH will not return it
* again. Note that GetFirstCH resets chused->chup.
* chl_next Link to next clearinghouse in database.
* chl_domains [NOT YET USED] List of domains served, for efficiency
*/
struct chlist {
Clearinghouse2_ObjectName *chl_name;
struct ns_addr chl_addr;
enum {chunknown, chup, chdown, chused} chl_status;
struct Clearinghouse2_TwoPartName *chl_domains;
struct chlist *chl_next;
};
struct chlist *namelist = NULL;
/*
* add a clearinghouse name to the ch list if it isn't already there.
* Initial state is chunknown, since we don't know its address and can't
* probe it.
*/
static struct chlist *
addtochlist(ch_name)
Clearinghouse2_ObjectName *ch_name;
{
struct chlist *chptr;
extern char *malloc();
if (ch_name != NULL) /* don't eliminate duplicate anonymous entries */
for (chptr = namelist; chptr != NULL; chptr = chptr->chl_next) {
if ( chptr->chl_name &&
(strcmp(chptr->chl_name->object,ch_name->object)==0) &&
(strcmp(chptr->chl_name->domain,ch_name->domain)==0) &&
(strcmp(chptr->chl_name->organization,
ch_name->organization)==0)) {
clear_Clearinghouse2_ObjectName(ch_name); /* dealloc */
return NULL; /* already in list */
}
}
chptr = (struct chlist *) malloc(sizeof(struct chlist));
chptr->chl_name = ch_name;
chptr->chl_status = chunknown;
chptr->chl_next = namelist;
namelist = chptr;
return chptr;
}
static
GetData(conn)
CourierConnection *conn;
{
int count, i;
int bufused, bufsize;
Unspecified *buffer, *bp;
Clearinghouse2_StreamOfObjectName obnames;
bufsize = MAXWORDS*4; /* end of available space */
buffer = Allocate(bufsize);
bufused = 0; /* number of words used */
while (count = BDTread(conn, (char*)(buffer+bufused),
MAXWORDS*sizeof(Unspecified))
) {
bufused += count/sizeof(Unspecified);
/* leave room for one last packet */
if (bufused+MAXWORDS > bufsize) {
bufsize += bufsize; /* double our space */
buffer = (Unspecified *) realloc((char *) buffer,
bufsize*sizeof(Unspecified));
}
}
bp = buffer;
while (bp-buffer < bufused) {
bp += internalize_Clearinghouse2_StreamOfObjectName(&obnames,bp);
if (0 == (int) obnames.designator) {
for (i = 0; i < obnames.nextSegment_case.segment.length; i++)
addtochlist(
&obnames.nextSegment_case.segment.sequence[i]);
} else {
for (i = 0; i < obnames.lastSegment_case.length; i++)
addtochlist(
&obnames.lastSegment_case.sequence[i]);
Deallocate(buffer);
return;
}
}
Deallocate(buffer);
return;
}
static struct ns_addr*
itemtonsaddr(itemptr)
Clearinghouse2_Item *itemptr; /* i.e. a sequence of Unspecified */
{
static union {
struct ns_addr addr;
u_short shrt[6];
} result;
register int i;
register Unspecified *seq;
if (itemptr->length < 7)
return(0);
seq = itemptr->sequence +1;
/* itemptr->sequence[0] == number of addresses */
for (i = 0; i < 6; i++, seq++)
result.shrt[i] = ntohs(*seq);
return(&result.addr);
}
/*
* Open an SPP connection to the address given as chaddr, then
* check whether the CHS pointed to by conn is up. If not, close
* conn and return 0. If so, return the connection.
*/
static CourierConnection*
ClearinghouseOpen(chaddr)
struct ns_addr chaddr;
{
CourierConnection *conn;
Clearinghouse2_RetrieveAddressesResults raresult;
if ((conn = CourierOpen(&chaddr)) == NULL)
return(conn);
DURING
raresult = Clearinghouse2_RetrieveAddresses(conn,NULL);
HANDLER {
CourierClose(conn);
conn = NULL;
} END_HANDLER;
clear_Clearinghouse2_RetrieveAddressesResults(&raresult);
return(conn);
}
/*
* path to look for the addresses file on
* (I wish I'd picked a shorter name, so we could rendezvous in /etc.
* But long file names in /etc are very unpopular!).
* This path is defined n CHdefault.c, and used by CH_NameDefault()
*/
extern char *chaddrpath[];
CourierConnection*
CH_GetFirstCH()
{
struct ns_addr chaddr;
extern struct ns_addr *getXNSaddr();
extern struct ns_addr ns_addr();
char buf[BUFSIZ];
CourierConnection *result;
FILE *chfile;
struct chlist *chptr;
int i;
result = (CourierConnection *) NULL;
/* first, look in the process cache */
for (chptr = namelist; chptr != NULL; chptr = chptr->chl_next) {
switch (chptr->chl_status) {
case chunknown:
case chdown:
break;
case chused:
chptr->chl_status = chup;
case chup:
if (result == NULL)
result = ClearinghouseOpen(chptr->chl_addr);
}
}
if (result) return(result);
/* Now, use hard-coded CH */
/* eventually we'll do an expanding-ring or something */
for (i = 0; chaddrpath[i] != NULL; i++) {
if ((chfile = fopen(chaddrpath[i],"r")) == NULL)
continue;
flock(fileno(chfile),LOCK_SH);
while (fgets(buf, BUFSIZ, chfile) != NULL)
if ((buf[0] != '#') &&
(chaddr = ns_addr(buf),
result = ClearinghouseOpen((chaddr)))) {
if ((chptr = addtochlist(NULL))) {
chptr->chl_addr = chaddr;
chptr->chl_status = chused;
}
flock(fileno(chfile),LOCK_UN);
fclose(chfile);
return(result);
}
flock(fileno(chfile),LOCK_UN);
fclose(chfile);
break; /* don't look for other files */
}
/* try expanding-ring here -- this could be more efficient! */
if ((chfile = popen(BFS,"r")) != NULL) {
while (fgets(buf, BUFSIZ, chfile) != NULL)
if ((buf[0] != '#') &&
(chaddr=ns_addr(buf),
result = ClearinghouseOpen(chaddr))) {
if ((chptr = addtochlist(NULL))) {
chptr->chl_addr = chaddr;
chptr->chl_status = chused;
}
pclose(chfile);
return(result);
}
pclose(chfile);
}
return(result);
}
CourierConnection *
CH_GetOtherCH(conn,hint)
CourierConnection *conn;
Clearinghouse2_ObjectName hint;
{
struct ns_addr *ch2addr;
CourierConnection *ch2conn, *chresult;
Clearinghouse2_RetrieveItemResults riresult;
Clearinghouse2_RetrieveMembersResults rmresult;
struct chlist *chptr;
Clearinghouse2_Property clearinghouseNames = 3;
Clearinghouse2_Property clearinghouseAddresses = 4;
if (hint.object != NULL && *hint.object != '\0') {
DURING
/* get list of possible other clearinghouses */
rmresult = Clearinghouse2_RetrieveMembers(conn, GetData, hint,
clearinghouseNames, BulkData1_immediateSink,
nullagent);
HANDLER {
/* some race condition */
return(NULL);
} END_HANDLER;
/* throw away the distinguished name, which we don't need */
clear_Clearinghouse2_RetrieveMembersResults(&rmresult);
}
/* for each member of potentials list, probe it */
ch2conn = chresult = NULL;
for (chptr = namelist; chptr != NULL; chptr = chptr->chl_next) {
switch (chptr->chl_status) {
case chunknown: /* a new entry, presumably */
/* get its address */
DURING
riresult = Clearinghouse2_RetrieveItem(conn, NULL,
*(chptr->chl_name),
clearinghouseAddresses, nullagent);
HANDLER
break; /* try next in namelist */
END_HANDLER;
chptr->chl_addr = *itemtonsaddr(&riresult.value);
clear_Clearinghouse2_RetrieveItemResults(&riresult);
chptr->chl_status = chdown;
/* fall through to: */
case chdown: /* check down CH to see if it has revived */
/* make sure the second CH is really there */
if ((ch2conn = ClearinghouseOpen(chptr->chl_addr))) {
chptr->chl_status = chup; /* we got it! */
if (chresult == NULL) {
chresult = ch2conn;
chptr->chl_status = chused;
}
else CourierClose(ch2conn);
ch2conn = NULL;
}
break;
case chup:
case chused:
break;
} /* end of switch */
} /* inspect next in list */
/*
* if no new one, return an old one
*/
for (chptr= namelist; chptr && (chresult==NULL); chptr= chptr->chl_next) {
if (chptr->chl_status == chup) {
chptr->chl_status =
(chresult=ClearinghouseOpen(chptr->chl_addr))
? chused : chdown;
}
}
return(chresult);
}
/*
* Given a Clearinghouse three part name (possibly containing wild cards)
* and the property number on which a NetworkAddress is expected to occur,
* returns the ns_addr structure associated with that name.
* Note that the ns_addr structure is statically allocated!
* Resets pattern to be the distinguished name of the object found.
*/
struct ns_addr *
CH_LookupAddr(pattern,property)
Clearinghouse2_ObjectNamePattern pattern;
Clearinghouse2_Property property;
{
struct ns_addr* CH_LookupAddrDN();
return(CH_LookupAddrDN(pattern,property,0,0));
}
/*
* Lookup a clearinghouse address, returning the address and the
* distinguished name of the object found.
*/
struct ns_addr *
CH_LookupAddrDN(pattern,property,distnamep,distnamelen)
Clearinghouse2_ObjectNamePattern pattern;
Clearinghouse2_Property property;
char *distnamep;
int distnamelen;
{
struct ns_addr *chaddr, *resultaddr;
CourierConnection *conn, *ch2conn;
Clearinghouse2_ObjectName hint; /* from WrongServer errors */
Clearinghouse2_RetrieveItemResults riresult;
int i;
if ((long) property <= 0) /* default to addressList i.e. 4 */
property = CHEntries0_addressList;
if (pattern.object == NULL ||
pattern.domain == NULL ||
pattern.organization == NULL)
return(NULL); /* can't handle defaults */
if ((conn = CH_GetFirstCH()) == NULL) {
fprintf(stderr,"Can't open connection to local Clearinghouse\n");
exit(1);
}
/* ask our primary clearinghouse for the address of this thing */
for (i = 5; i > 0; i--) {
DURING {
riresult = Clearinghouse2_RetrieveItem(conn, NULL,
pattern, property, nullagent);
i = -1;
} HANDLER {
if (Exception.Code == REJECT_ERROR) {
fprintf(stderr,"Problem with CH.addrs. CH rejected request\n");
hint.object = hint.domain = hint.organization = NULL;
}
else if (Exception.Code != Clearinghouse2_WrongServer) {
/* some random error */
hint.object = hint.domain = hint.organization = NULL;
}
else hint = CourierErrArgs(Clearinghouse2_WrongServerArgs, hint);
ch2conn = CH_GetOtherCH(conn, hint);
CourierClose(conn);
if (ch2conn == NULL) return(0);
conn = ch2conn;
} END_HANDLER;
}
if (i >= 0) {
return(0);
}
resultaddr = itemtonsaddr(&riresult.value);
if (distnamep != NULL &&
distnamelen >= (2+strlen(riresult.distinguishedObject.object)+
strlen(riresult.distinguishedObject.domain)+
strlen(riresult.distinguishedObject.organization)))
strcpy(distnamep,CH_NameToString(riresult.distinguishedObject));
clear_Clearinghouse2_RetrieveItemResults(&riresult);
CourierClose(conn);
return(resultaddr);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.