2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afs/param.h>
11 #include <afsconfig.h>
23 #include <netinet/in.h>
27 #include <afs/assert.h>
30 #include <afs/afsint.h>
31 #include <afs/rxgen_consts.h>
33 #include <afs/errors.h>
34 #include <afs/ihandle.h>
35 #include <afs/vnode.h>
36 #include <afs/volume.h>
37 #ifdef AFS_ATHENA_STDENV
41 #include <afs/ptclient.h>
42 #include <afs/prs_fs.h>
44 #include <afs/afsutil.h>
46 #include <afs/cellconfig.h>
52 #ifdef AFS_PTHREAD_ENV
53 pthread_mutex_t host_glock_mutex;
54 #endif /* AFS_PTHREAD_ENV */
57 extern int CurrentConnections;
59 extern int AnonymousID;
60 extern prlist AnonCPS;
62 extern struct afsconf_dir *confDir; /* config dir object */
63 extern int lwps; /* the max number of server threads */
64 extern afsUUID FS_HostUUID;
66 int CEs = 0; /* active clients */
67 int CEBlocks = 0; /* number of blocks of CEs */
68 struct client *CEFree = 0; /* first free client */
69 struct host *hostList = 0; /* linked list of all hosts */
70 int hostCount = 0; /* number of hosts in hostList */
74 #define CESPERBLOCK 73
75 struct CEBlock /* block of CESPERBLOCK file entries */
77 struct client entry[CESPERBLOCK];
81 * Make sure the subnet macros have been defined.
84 #define IN_SUBNETA(i) ((((afs_int32)(i))&0x80800000)==0x00800000)
87 #ifndef IN_CLASSA_SUBNET
88 #define IN_CLASSA_SUBNET 0xffff0000
92 #define IN_SUBNETB(i) ((((afs_int32)(i))&0xc0008000)==0x80008000)
95 #ifndef IN_CLASSB_SUBNET
96 #define IN_CLASSB_SUBNET 0xffffff00
99 #define rxr_GetEpoch(aconn) (((struct rx_connection *)(aconn))->epoch)
101 #define rxr_CidOf(aconn) (((struct rx_connection *)(aconn))->cid)
103 #define rxr_PortOf(aconn) \
104 rx_PortOf(rx_PeerOf(((struct rx_connection *)(aconn))))
106 #define rxr_HostOf(aconn) \
107 rx_HostOf(rx_PeerOf((struct rx_connection *)(aconn)))
110 /* get a new block of CEs and chain it on CEFree */
111 static void GetCEBlock()
113 register struct CEBlock *block;
116 block = (struct CEBlock *)malloc(sizeof(struct CEBlock));
118 ShutDownAndCore(PANIC);
120 for(i = 0; i < (CESPERBLOCK -1); i++) {
121 Lock_Init(&block->entry[i].lock);
122 block->entry[i].next = &(block->entry[i+1]);
124 block->entry[CESPERBLOCK-1].next = 0;
125 Lock_Init(&block->entry[CESPERBLOCK-1].lock);
126 CEFree = (struct client *)block;
132 /* get the next available CE */
133 static struct client *GetCE()
136 register struct client *entry;
141 ShutDownAndCore(PANIC);
144 CEFree = entry->next;
146 bzero((char *)entry, CLIENT_TO_ZERO(entry));
152 /* return an entry to the free list */
153 static void FreeCE(entry)
154 register struct client *entry;
157 entry->next = CEFree;
164 * The HTs and HTBlocks variables were formerly static, but they are
165 * now referenced elsewhere in the FileServer.
167 int HTs = 0; /* active file entries */
168 int HTBlocks = 0; /* number of blocks of HTs */
169 static struct host *HTFree = 0; /* first free file entry */
172 * Hash tables of host pointers. We need two tables, one
173 * to map IP addresses onto host pointers, and another
174 * to map host UUIDs onto host pointers.
176 static struct h_hashChain *hostHashTable[h_HASHENTRIES];
177 static struct h_hashChain *hostUuidHashTable[h_HASHENTRIES];
178 #define h_HashIndex(hostip) ((hostip) & (h_HASHENTRIES-1))
179 #define h_UuidHashIndex(uuidp) (((int)(afs_uuid_hash(uuidp))) & (h_HASHENTRIES-1))
181 struct HTBlock /* block of HTSPERBLOCK file entries */
183 struct host entry[h_HTSPERBLOCK];
187 /* get a new block of HTs and chain it on HTFree */
188 static void GetHTBlock()
191 register struct HTBlock *block;
193 static int index = 0;
195 block = (struct HTBlock *)malloc(sizeof(struct HTBlock));
197 ShutDownAndCore(PANIC);
199 #ifdef AFS_PTHREAD_ENV
200 for(i=0; i < (h_HTSPERBLOCK); i++)
201 assert(pthread_cond_init(&block->entry[i].cond, NULL) == 0);
202 #endif /* AFS_PTHREAD_ENV */
203 for(i=0; i < (h_HTSPERBLOCK); i++)
204 Lock_Init(&block->entry[i].lock);
205 for(i=0; i < (h_HTSPERBLOCK -1); i++)
206 block->entry[i].next = &(block->entry[i+1]);
207 for (i=0; i< (h_HTSPERBLOCK); i++)
208 block->entry[i].index = index++;
209 block->entry[h_HTSPERBLOCK-1].next = 0;
210 HTFree = (struct host *)block;
211 hosttableptrs[HTBlocks++] = block->entry;
216 /* get the next available HT */
217 static struct host *GetHT()
220 register struct host *entry;
226 HTFree = entry->next;
228 bzero((char *)entry, HOST_TO_ZERO(entry));
234 /* return an entry to the free list */
235 static void FreeHT(entry)
236 register struct host *entry;
239 entry->next = HTFree;
246 static short consolePort = 0;
249 register struct host *host;
258 * If this thread does not have a hold on this host AND
259 * if other threads also dont have any holds on this host AND
260 * If either the HOSTDELETED or CLIENTDELETED flags are set
263 int h_Release_r(host)
264 register struct host *host;
267 if (!((host)->holds[h_holdSlot()] &= ~h_holdbit()) ) {
268 if (! h_OtherHolds_r(host) ) {
269 if ( (host->hostFlags & HOSTDELETED) ||
270 (host->hostFlags & CLIENTDELETED) ) {
279 register struct host *host;
283 retVal = h_Held_r(host);
288 int h_OtherHolds_r(host)
289 register struct host *host;
291 register int i, bit, slot;
294 for (i = 0 ; i < h_maxSlots ; i++) {
295 if (host->holds[i] != ((i == slot) ? bit : 0)) {
302 int h_OtherHolds(host)
303 register struct host *host;
307 retVal = h_OtherHolds_r(host);
313 register struct host *host;
323 * returns 1 if already locked
324 * else returns locks and returns 0
328 register struct host *host;
330 struct Lock *hostLock = &host->lock;
335 if ( !(hostLock->excl_locked) && !(hostLock->readers_reading) )
336 hostLock->excl_locked = WRITE_LOCK;
340 LOCK_UNLOCK(hostLock)
349 #if FS_STATS_DETAILED
350 /*------------------------------------------------------------------------
351 * PRIVATE h_AddrInSameNetwork
354 * Given a target IP address and a candidate IP address (both
355 * in host byte order), return a non-zero value (1) if the
356 * candidate address is in a different network from the target
360 * a_targetAddr : Target address.
361 * a_candAddr : Candidate address.
364 * 1 if the candidate address is in the same net as the target,
368 * The target and candidate addresses are both in host byte
369 * order, NOT network byte order, when passed in. We return
370 * our value as a character, since that's the type of field in
371 * the host structure, where this info will be stored.
375 *------------------------------------------------------------------------*/
377 static char h_AddrInSameNetwork(a_targetAddr, a_candAddr)
378 afs_uint32 a_targetAddr;
379 afs_uint32 a_candAddr;
381 { /*h_AddrInSameNetwork*/
383 afs_uint32 targetNet;
387 * Pull out the network and subnetwork numbers from the target
388 * and candidate addresses. We can short-circuit this whole
389 * affair if the target and candidate addresses are not of the
392 if (IN_CLASSA(a_targetAddr)) {
393 if (!(IN_CLASSA(a_candAddr))) {
396 targetNet = a_targetAddr & IN_CLASSA_NET;
397 candNet = a_candAddr & IN_CLASSA_NET;
400 if (IN_CLASSB(a_targetAddr)) {
401 if (!(IN_CLASSB(a_candAddr))) {
404 targetNet = a_targetAddr & IN_CLASSB_NET;
405 candNet = a_candAddr & IN_CLASSB_NET;
408 if (IN_CLASSC(a_targetAddr)) {
409 if (!(IN_CLASSC(a_candAddr))) {
412 targetNet = a_targetAddr & IN_CLASSC_NET;
413 candNet = a_candAddr & IN_CLASSC_NET;
416 targetNet = a_targetAddr;
417 candNet = a_candAddr;
418 } /*Class D address*/
421 * Now, simply compare the extracted net values for the two addresses
422 * (which at this point are known to be of the same class)
424 if (targetNet == candNet)
429 } /*h_AddrInSameNetwork*/
430 #endif /* FS_STATS_DETAILED */
434 h_gethostcps_r(host,now)
435 register struct host *host;
436 register afs_int32 now;
441 /* at this point, the host might not be locked, nor held */
442 /* make sure that we do not disappear behind the RPC */
443 if ( !(held = h_Held_r(host)) )
446 /* wait if somebody else is already doing the getCPS call */
447 while ( host->hostFlags & HPCS_INPROGRESS )
449 slept = 1; /* I did sleep */
450 host->hostFlags |= HPCS_WAITING; /* I am sleeping now */
451 #ifdef AFS_PTHREAD_ENV
452 pthread_cond_wait(&host->cond, &host_glock_mutex);
453 #else /* AFS_PTHREAD_ENV */
454 if (( code = LWP_WaitProcess( &(host->hostFlags ))) != LWP_SUCCESS)
455 ViceLog(0, ("LWP_WaitProcess returned %d\n", code));
456 #endif /* AFS_PTHREAD_ENV */
460 host->hostFlags |= HPCS_INPROGRESS; /* mark as CPSCall in progress */
461 if (host->hcps.prlist_val)
462 free(host->hcps.prlist_val); /* this is for hostaclRefresh */
463 host->hcps.prlist_val = (afs_int32 *)0;
464 host->hcps.prlist_len = 0;
465 slept? (host->cpsCall = FT_ApproxTime()): (host->cpsCall = now );
468 code = pr_GetHostCPS(htonl(host->host), &host->hcps);
472 * Although ubik_Call (called by pr_GetHostCPS) traverses thru all protection servers
473 * and reevaluates things if no sync server or quorum is found we could still end up
474 * with one of these errors. In such case we would like to reevaluate the rpc call to
475 * find if there's cps for this guy. We treat other errors (except network failures
476 * ones - i.e. code < 0) as an indication that there is no CPS for this host. Ideally
477 * we could like to deal this problem the other way around (i.e. if code == NOCPS
478 * ignore else retry next time) but the problem is that there're other errors (i.e.
479 * EPERM) for which we don't want to retry and we don't know the whole code list!
481 if (code < 0 || code == UNOQUORUM || code == UNOTSYNC) {
483 * We would have preferred to use a while loop and try again since ops in protected
484 * acls for this host will fail now but they'll be reevaluated on any subsequent
485 * call. The attempt to wait for a quorum/sync site or network error won't work
486 * since this problems really should only occurs during a complete fileserver
487 * restart. Since the fileserver will start before the ptservers (and thus before
488 * quorums are complete) clients will be utilizing all the fileserver's lwps!!
490 host->hcpsfailed = 1;
491 ViceLog(0, ("Warning: GetHostCPS failed (%d) for %x; will retry\n", code, host->host));
493 host->hcpsfailed = 0;
494 ViceLog(1, ("gethost: GetHostCPS failed (%d) for %x; ignored\n", code, host->host));
496 if (host->hcps.prlist_val)
497 free(host->hcps.prlist_val);
498 host->hcps.prlist_val = (afs_int32 *)0;
499 host->hcps.prlist_len = 0; /* Make sure it's zero */
501 host->hcpsfailed = 0;
503 host->hostFlags &= ~HPCS_INPROGRESS;
504 /* signal all who are waiting */
505 if ( host->hostFlags & HPCS_WAITING) /* somebody is waiting */
507 host->hostFlags &= ~HPCS_WAITING;
508 #ifdef AFS_PTHREAD_ENV
509 assert(pthread_cond_broadcast(&host->cond) == 0);
510 #else /* AFS_PTHREAD_ENV */
511 if ( (code = LWP_NoYieldSignal( &(host->hostFlags) )) != LWP_SUCCESS )
512 ViceLog(0, ("LWP_NoYieldSignal returns %d\n", code));
513 #endif /* AFS_PTHREAD_ENV */
516 /* if we had held the host, release it now */
521 void h_flushhostcps(hostaddr, hport)
522 register afs_uint32 hostaddr, hport; /* net byte order */
524 register struct host *host;
527 host = h_Lookup_r(hostaddr, hport);
529 host->hcpsfailed = 1;
538 * Allocate a host. It will be identified by the peer (ip,port) info in the
539 * rx connection provided. The host is returned un-held and un-locked
541 #define DEF_ROPCONS 2115
543 struct host *h_Alloc(r_con)
544 register struct rx_connection *r_con;
548 retVal = h_Alloc_r(r_con);
553 struct host *h_Alloc_r(r_con)
554 register struct rx_connection *r_con;
558 struct servent *serverentry;
559 register index = h_HashIndex(rxr_HostOf(r_con));
560 register struct host *host;
561 static struct rx_securityClass *sc = 0;
563 struct h_hashChain* h_hashChain;
564 #if FS_STATS_DETAILED
565 afs_uint32 newHostAddr_HBO; /*New host IP addr, in host byte order*/
566 #endif /* FS_STATS_DETAILED */
570 h_hashChain = (struct h_hashChain*) malloc(sizeof(struct h_hashChain));
572 h_hashChain->hostPtr = host;
573 h_hashChain->addr = rxr_HostOf(r_con);
574 h_hashChain->next = hostHashTable[index];
575 hostHashTable[index] = h_hashChain;
577 host->host = rxr_HostOf(r_con);
578 host->port = rxr_PortOf(r_con);
579 if(consolePort == 0 ) { /* find the portal number for console */
580 #if defined(AFS_OSF_ENV)
581 serverentry = getservbyname("ropcons", "");
583 serverentry = getservbyname("ropcons", 0);
586 consolePort = serverentry->s_port;
588 consolePort = DEF_ROPCONS; /* Use a default */
590 if (host->port == consolePort) host->Console = 1;
591 /* Make a callback channel even for the console, on the off chance that it
592 makes a request that causes a break call back. It shouldn't. */
595 sc = (struct rx_securityClass *) rxnull_NewClientSecurityObject();
596 host->callback_rxcon = rx_NewConnection (host->host, host->port,
598 rx_SetConnDeadTime(host->callback_rxcon, 50);
599 rx_SetConnHardDeadTime(host->callback_rxcon, AFS_HARDDEADTIME);
601 now = host->LastCall = host->cpsCall = host->ActiveCall = FT_ApproxTime();
603 host->hcps.prlist_val = (afs_int32 *)0;
604 host->hcps.prlist_len = 0;
605 host->hcps.prlist_val = (afs_int32 *)0;
607 /*host->hcpsfailed = 0; /* save cycles */
608 /* h_gethostcps(host); do this under host lock */
609 host->FirstClient = 0;
610 h_InsertList_r(host); /* update global host List */
611 #if FS_STATS_DETAILED
613 * Compare the new host's IP address (in host byte order) with ours
614 * (the File Server's), remembering if they are in the same network.
616 newHostAddr_HBO = (afs_uint32)ntohl(host->host);
617 host->InSameNetwork = h_AddrInSameNetwork(FS_HostAddr_HBO,
619 #endif /* FS_STATS_DETAILED */
625 /* Lookup a host given an IP address and UDP port number. */
626 struct host *h_Lookup(hostaddr, hport)
627 afs_uint32 hostaddr, hport; /* network byte order */
631 retVal = h_Lookup_r(hostaddr, hport);
636 struct host *h_Lookup_r(hostaddr, hport)
637 afs_uint32 hostaddr, hport; /* network byte order */
639 register afs_int32 now;
640 register struct host *host=0;
641 register struct h_hashChain* chain;
642 register index = h_HashIndex(hostaddr);
643 extern int hostaclRefresh;
645 for (chain=hostHashTable[index]; chain; chain=chain->next) {
646 host = chain->hostPtr;
648 if (!(host->hostFlags & HOSTDELETED) && chain->addr == hostaddr
649 && host->port == hport) {
650 now = FT_ApproxTime(); /* always evaluate "now" */
651 if (host->hcpsfailed || (host->cpsCall+hostaclRefresh < now )) {
653 * Every hostaclRefresh period (def 2 hrs) get the new membership list for the host.
654 * Note this could be the first time that the host is added to a group.
655 * Also here we also retry on previous legitimate hcps failures
657 h_gethostcps_r(host,now);
667 /* Lookup a host given its UUID. */
668 struct host *h_LookupUuid_r(uuidp)
671 register struct host *host=0;
672 register struct h_hashChain* chain;
673 register index = h_UuidHashIndex(uuidp);
675 for (chain=hostUuidHashTable[index]; chain; chain=chain->next) {
676 host = chain->hostPtr;
678 if (!(host->hostFlags & HOSTDELETED) && host->interface
679 && afs_uuid_equal(&host->interface->uuid, uuidp)) {
690 * h_Hold: Establish a hold by the current LWP on this host--the host
691 * or its clients will not be physically deleted until all holds have
694 * NOTE: h_Hold_r is a macro defined in host.h.
698 register struct host *host;
707 /* h_TossStuff: Toss anything in the host structure (the host or
708 * clients marked for deletion. Called from r_Release ONLY.
709 * To be called, there must be no holds, and either host->deleted
710 * or host->clientDeleted must be set.
713 register struct host *host;
716 register struct client **cp, *client;
719 /* if somebody still has this host held */
720 for (i=0; (i<h_maxSlots)&&(!(host)->holds[i]); i++);
724 /* ASSUMPTION: r_FreeConnection() does not yield */
725 for (cp = &host->FirstClient; client = *cp; ) {
726 if ((host->hostFlags & HOSTDELETED) || client->deleted) {
727 if ((client->ViceId != ANONYMOUSID) && client->CPS.prlist_val) {
728 free(client->CPS.prlist_val);
729 client->CPS.prlist_val = (afs_int32 *)0;
732 rx_SetSpecific(client->tcon, rxcon_client_key, (void *)0);
734 CurrentConnections--;
737 } else cp = &client->next;
739 if (host->hostFlags & HOSTDELETED) {
740 register struct h_hashChain **hp, *th;
741 register struct rx_connection *rxconn;
746 if (host->Console & 1) Console--;
747 if (rxconn = host->callback_rxcon) {
748 host->callback_rxcon = (struct rx_connection *)0;
750 * If rx_DestroyConnection calls h_FreeConnection we will
751 * deadlock on the host_glock_mutex. Work around the problem
752 * by unhooking the client from the connection before
753 * destroying the connection.
755 client = rx_GetSpecific(rxconn, rxcon_client_key);
756 if (client && client->tcon == rxconn)
758 rx_SetSpecific(rxconn, rxcon_client_key, (void *)0);
759 rx_DestroyConnection(rxconn);
761 if (host->hcps.prlist_val)
762 free(host->hcps.prlist_val);
763 host->hcps.prlist_val = (afs_int32 *)0;
764 host->hcps.prlist_len = 0;
765 DeleteAllCallBacks_r(host);
766 host->hostFlags &= ~RESETDONE; /* just to be safe */
768 /* if alternate addresses do not exist */
769 if ( !(host->interface) )
771 for (hp = &hostHashTable[h_HashIndex(host->host)];
772 th = *hp; hp = &th->next)
775 if (th->hostPtr == host)
778 h_DeleteList_r(host);
786 /* delete all hash entries for the UUID */
787 uuidp = &host->interface->uuid;
788 for (hp = &hostUuidHashTable[h_UuidHashIndex(uuidp)];
789 th = *hp; hp = &th->next) {
791 if (th->hostPtr == host)
798 /* delete all hash entries for alternate addresses */
799 assert(host->interface->numberOfInterfaces > 0 );
800 for ( i=0; i < host->interface->numberOfInterfaces; i++)
802 hostAddr = host->interface->addr[i];
803 for (hp = &hostHashTable[h_HashIndex(hostAddr)];
804 th = *hp; hp = &th->next)
807 if (th->hostPtr == host)
815 free(host->interface);
816 host->interface = NULL;
817 h_DeleteList_r(host); /* remove host from global host List */
819 } /* if alternate address exists */
824 /* Called by rx when a server connection disappears */
825 h_FreeConnection(tcon)
826 struct rx_connection *tcon;
829 register struct client *client;
831 client = (struct client *) rx_GetSpecific(tcon, rxcon_client_key);
834 if (client->tcon == tcon)
835 client->tcon = (struct rx_connection *)0;
838 } /*h_FreeConnection*/
841 /* h_Enumerate: Calls (*proc)(host, held, param) for at least each host in the
842 * system at the start of the enumeration (perhaps more). Hosts may be deleted
843 * (have delete flag set); ditto for clients. (*proc) is always called with
844 * host h_held(). The hold state of the host with respect to this lwp is passed
845 * to (*proc) as the param held. The proc should return 0 if the host should be
846 * released, 1 if it should be held after enumeration.
848 h_Enumerate(proc, param)
853 register struct host *host, **list;
855 register int i, count;
858 if (hostCount == 0) {
862 list = (struct host **)malloc(hostCount * sizeof(struct host *));
863 assert(list != NULL);
864 held = (int *)malloc(hostCount * sizeof(int));
865 assert(held != NULL);
866 for (count = 0, host = hostList ; host ; host = host->next, count++) {
868 if (!(held[count] = h_Held_r(host)))
871 assert(count == hostCount);
873 for ( i = 0 ; i < count ; i++) {
874 held[i] = (*proc)(list[i], held[i], param);
876 h_Release(list[i]);/* this might free up the host */
882 /* h_Enumerate_r: Calls (*proc)(host, held, param) for at least each host in
883 * the at the start of the enumeration (perhaps more). Hosts may be deleted
884 * (have delete flag set); ditto for clients. (*proc) is always called with
885 * host h_held() and the global host lock (H_LOCK) locked.The hold state of the
886 * host with respect to this lwp is passed to (*proc) as the param held.
887 * The proc should return 0 if the host should be released, 1 if it should
888 * be held after enumeration.
890 h_Enumerate_r(proc, param)
895 register struct host *host;
898 if (hostCount == 0) {
901 for (host = hostList ; host ; host = host->next) {
902 if (!(held = h_Held_r(host)))
904 held = (*proc)(host, held, param);
906 h_Release_r(host);/* this might free up the host */
911 /* Host is returned held */
912 struct host *h_GetHost_r(tcon)
913 struct rx_connection *tcon;
917 struct host *oldHost;
920 struct interfaceAddr interf;
922 afs_int32 buffer[AFS_MAX_INTERFACE_ADDR];
923 struct Identity *identP = NULL;
928 haddr = rxr_HostOf(tcon);
929 hport = rxr_PortOf(tcon);
932 identP = (struct Identity *)rx_GetSpecific(tcon, rxcon_ident_key);
933 host = h_Lookup_r(haddr, hport);
934 if (host && !identP && !(host->Console&1)) {
935 /* This is a new connection, and we already have a host
936 * structure for this address. Verify that the identity
937 * of the caller matches the identity in the host structure.
939 if (!(held = h_Held_r(host)))
942 if ( !(host->hostFlags & ALTADDR) )
944 /* Another thread is doing initialization */
946 if ( !held) h_Release_r(host);
947 ViceLog(125, ("Host %x starting h_Lookup again\n", host));
950 host->hostFlags &= ~ALTADDR;
952 code = RXAFSCB_WhoAreYou(host->callback_rxcon, &interf);
954 if ( code == RXGEN_OPCODE ) {
955 identP = (struct Identity *)malloc(1);
957 rx_SetSpecific(tcon, rxcon_ident_key, identP);
958 /* The host on this connection was unable to respond to
959 * the WhoAreYou. We will treat this as a new connection
960 * from the existing host. The worst that can happen is
961 * that we maintain some extra callback state information */
962 if (host->interface) {
964 ("Host %x used to support WhoAreYou, deleting.\n",
966 host->hostFlags |= HOSTDELETED;
968 if (!held) h_Release_r(host);
972 } else if (code == 0) {
974 identP = (struct Identity *)malloc(sizeof(struct Identity));
976 identP->uuid = interf.uuid;
977 rx_SetSpecific(tcon, rxcon_ident_key, identP);
978 /* Check whether the UUID on this connection matches
979 * the UUID in the host structure. If they don't match
980 * then this is not the same host as before. */
981 if ( !host->interface
982 || !afs_uuid_equal(&interf.uuid, &host->interface->uuid) ) {
984 ("Host %x has changed its identity, deleting.\n",
986 host->hostFlags |= HOSTDELETED;
988 if (!held) h_Release_r(host);
994 afs_inet_ntoa_r(host->host, hoststr);
995 ViceLog(0,("CB: WhoAreYou failed for %s:%d, error %d\n",
996 hoststr, ntohs(host->port), code));
997 host->hostFlags |= VENUSDOWN;
999 host->hostFlags |= ALTADDR;
1002 if (!(held = h_Held_r(host)))
1004 if ( ! (host->hostFlags & ALTADDR) )
1006 /* another thread is doing the initialisation */
1007 ViceLog(125, ("Host %x waiting for host-init to complete\n",
1011 if ( !held) h_Release_r(host);
1012 ViceLog(125, ("Host %x starting h_Lookup again\n", host));
1015 /* We need to check whether the identity in the host structure
1016 * matches the identity on the connection. If they don't match
1017 * then treat this a new host. */
1018 if ( !(host->Console&1)
1019 && ( ( !identP->valid && host->interface )
1020 || ( identP->valid && !host->interface )
1022 && !afs_uuid_equal(&identP->uuid, &host->interface->uuid) ) ) ) {
1023 /* The host in the cache is not the host for this connection */
1024 host->hostFlags |= HOSTDELETED;
1026 if (!held) h_Release_r(host);
1027 ViceLog(0,("CB: new identity for host %x, deleting\n",
1032 host = h_Alloc_r(tcon);
1035 h_gethostcps_r(host,FT_ApproxTime());
1036 if (!(host->Console&1)) {
1037 if (!identP || !interfValid) {
1039 code = RXAFSCB_WhoAreYou(host->callback_rxcon, &interf);
1041 if ( code == RXGEN_OPCODE ) {
1042 identP = (struct Identity *)malloc(1);
1044 rx_SetSpecific(tcon, rxcon_ident_key, identP);
1046 ("Host %x does not support WhoAreYou.\n",
1049 } else if (code == 0) {
1051 identP = (struct Identity *)malloc(sizeof(struct Identity));
1053 identP->uuid = interf.uuid;
1054 rx_SetSpecific(tcon, rxcon_ident_key, identP);
1055 ViceLog(25,("WhoAreYou success on %x\n", host->host));
1058 if (code == 0 && !identP->valid) {
1060 code = RXAFSCB_InitCallBackState(host->callback_rxcon);
1062 } else if (code == 0) {
1063 oldHost = h_LookupUuid_r(&identP->uuid);
1065 /* This is a new address for an existing host. Update
1066 * the list of interfaces for the existing host and
1067 * delete the host structure we just allocated. */
1068 if (!(held = h_Held_r(oldHost)))
1071 ViceLog(25,("CB: new addr %x for old host %x\n",
1072 host->host, oldHost->host));
1073 host->hostFlags |= HOSTDELETED;
1077 addInterfaceAddr_r(host, haddr);
1079 /* This really is a new host */
1080 hashInsertUuid_r(&identP->uuid, host);
1082 code = RXAFSCB_InitCallBackState3(host->callback_rxcon,
1086 ViceLog(25,("InitCallBackState3 success on %x\n",
1088 assert(interfValid == 1);
1089 initInterfaceAddr_r(host, &interf);
1095 afs_inet_ntoa_r(host->host, hoststr);
1096 ViceLog(0,("CB: RCallBackConnectBack failed for %s:%d\n",
1097 hoststr, ntohs(host->port)));
1098 host->hostFlags |= VENUSDOWN;
1101 host->hostFlags |= RESETDONE;
1104 host->hostFlags |= ALTADDR;/* host structure iniatilisation complete */
1112 static char localcellname[PR_MAXNAMELEN+1];
1113 char local_realm[AFS_REALM_SZ] = "";
1116 void h_InitHostPackage()
1118 afsconf_GetLocalCell (confDir, localcellname, PR_MAXNAMELEN);
1119 if (!local_realm[0]) {
1120 if (afs_krb_get_lrealm(local_realm, 0) != 0/*KSUCCESS*/) {
1121 ViceLog(0, ("afs_krb_get_lrealm failed, using %s.\n",localcellname));
1122 strcpy (local_realm, localcellname);
1125 rxcon_ident_key = rx_KeyCreate((rx_destructor_t)free);
1126 rxcon_client_key = rx_KeyCreate((rx_destructor_t)0);
1127 #ifdef AFS_PTHREAD_ENV
1128 assert(pthread_mutex_init(&host_glock_mutex, NULL) == 0);
1129 #endif /* AFS_PTHREAD_ENV */
1132 static MapName_r(aname, acell, aval)
1141 afs_int32 anamelen, cnamelen;
1145 anamelen=strlen(aname);
1146 if (anamelen >= PR_MAXNAMELEN)
1147 return -1; /* bad name -- caller interprets this as anonymous, but retries later */
1149 lnames.namelist_len = 1;
1150 lnames.namelist_val = (prname *) aname; /* don't malloc in the common case */
1151 lids.idlist_len = 0;
1152 lids.idlist_val = (afs_int32 *) 0;
1154 cnamelen=strlen(acell);
1156 if (strcasecmp(local_realm, acell) && strcasecmp(localcellname, acell)) {
1157 ViceLog(2, ("MapName: cell is foreign. cell=%s, localcell=%s, localrealm=%s\n",
1158 acell, localcellname, local_realm));
1159 if ((anamelen+cnamelen+1) >= PR_MAXNAMELEN) {
1160 ViceLog(2, ("MapName: Name too long, using AnonymousID for %s@%s\n",
1162 *aval = AnonymousID;
1165 foreign = 1; /* attempt cross-cell authentication */
1166 tname = (char *) malloc(anamelen+cnamelen+2);
1167 strcpy(tname, aname);
1168 tname[anamelen] = '@';
1169 strcpy(tname+anamelen+1, acell);
1170 lnames.namelist_val = (prname *) tname;
1175 code = pr_NameToId(&lnames, &lids);
1178 if (lids.idlist_val) {
1179 *aval = lids.idlist_val[0];
1180 if (*aval == AnonymousID) {
1181 ViceLog(2, ("MapName: NameToId on %s returns anonymousID\n", lnames.namelist_val));
1183 free(lids.idlist_val); /* return parms are not malloced in stub if server proc aborts */
1185 ViceLog(0, ("MapName: NameToId on '%s' is unknown\n", lnames.namelist_val));
1191 free(lnames.namelist_val); /* We allocated this above, so we must free it now. */
1198 /* NOTE: this returns the client with a Shared lock */
1199 struct client *h_ID2Client(vid)
1202 register struct client *client;
1203 register struct host *host;
1207 for (host=hostList; host; host=host->next) {
1208 if (host->hostFlags & HOSTDELETED)
1210 for (client = host->FirstClient; client; client = client->next) {
1211 if (!client->deleted && client->ViceId == vid) {
1214 ObtainSharedLock(&client->lock);
1228 * Called by the server main loop. Returns a h_Held client, which must be
1229 * released later the main loop. Allocates a client if the matching one
1230 * isn't around. The client is returned with its reference count incremented
1231 * by one. The caller must call h_ReleaseClient_r when finished with
1234 struct client *h_FindClient_r(tcon)
1235 struct rx_connection *tcon;
1238 register struct client *client;
1239 register struct host *host;
1240 struct client *oldClient;
1245 #if (64-MAXKTCNAMELEN)
1246 ticket name length != 64
1250 char uname[PR_MAXNAMELEN];
1251 char tcell[MAXKTCREALMLEN];
1254 client = (struct client *) rx_GetSpecific(tcon, rxcon_client_key);
1255 if (client && !client->deleted) {
1257 h_Hold_r(client->host);
1258 if (client->prfail != 2) { /* Could add shared lock on client here */
1259 /* note that we don't have to lock entry in this path to
1260 * ensure CPS is initialized, since we don't call rxr_SetSpecific
1261 * until initialization is done, and we only get here if
1262 * rx_GetSpecific located the client structure.
1267 ObtainWriteLock(&client->lock); /* released at end */
1269 } else if (client) {
1273 authClass = rx_SecurityClassOf((struct rx_connection *)tcon);
1274 ViceLog(5,("FindClient: authenticating connection: authClass=%d\n",
1276 if (authClass == 1) {
1277 /* A bcrypt tickets, no longer supported */
1278 ViceLog(1, ("FindClient: bcrypt ticket, using AnonymousID\n"));
1279 viceid = AnonymousID;
1280 expTime = 0x7fffffff;
1281 } else if (authClass == 2) {
1284 /* kerberos ticket */
1285 code = rxkad_GetServerInfo (tcon, /*level*/0, &expTime,
1286 tname, tinst, tcell, &kvno);
1288 ViceLog(1, ("Failed to get rxkad ticket info\n"));
1289 viceid = AnonymousID;
1290 expTime = 0x7fffffff;
1292 int ilen = strlen(tinst);
1294 ("FindClient: rxkad conn: name=%s,inst=%s,cell=%s,exp=%d,kvno=%d\n",
1295 tname, tinst, tcell, expTime, kvno));
1296 strncpy (uname, tname, sizeof(uname));
1298 if (strlen(uname) + 1 + ilen >= sizeof(uname))
1300 strcat (uname, ".");
1301 strcat (uname, tinst);
1303 /* translate the name to a vice id */
1304 code = MapName_r(uname, tcell, &viceid);
1307 ViceLog(1, ("failed to map name=%s, cell=%s -> code=%d\n",
1308 uname, tcell, code));
1310 viceid = AnonymousID;
1311 expTime = 0x7fffffff;
1315 viceid = AnonymousID; /* unknown security class */
1316 expTime = 0x7fffffff;
1320 host = h_GetHost_r(tcon); /* Returns it h_Held */
1322 /* First try to find the client structure */
1323 for (client = host->FirstClient; client; client = client->next) {
1324 if (!client->deleted && (client->sid == rxr_CidOf(tcon)) &&
1325 (client->VenusEpoch == rxr_GetEpoch(tcon))) {
1326 if (client->tcon && (client->tcon != tcon)) {
1327 ViceLog(0, ("*** Vid=%d, sid=%x, tcon=%x, Tcon=%x ***\n",
1328 client->ViceId, client->sid, client->tcon, tcon));
1329 client->tcon = (struct rx_connection *)0;
1333 ObtainWriteLock(&client->lock);
1339 /* Still no client structure - get one */
1342 ObtainWriteLock(&client->lock);
1343 client->host = host;
1344 client->next = host->FirstClient;
1345 host->FirstClient = client;
1346 #if FS_STATS_DETAILED
1347 client->InSameNetwork = host->InSameNetwork;
1348 #endif /* FS_STATS_DETAILED */
1349 client->ViceId = viceid;
1350 client->expTime = expTime; /* rx only */
1351 client->authClass = authClass; /* rx only */
1352 client->sid = rxr_CidOf(tcon);
1353 client->VenusEpoch = rxr_GetEpoch(tcon);
1354 client->CPS.prlist_val = 0;
1355 client->refCount = 1;
1356 CurrentConnections++; /* increment number of connections */
1359 client->prfail = fail;
1361 if (!(client->CPS.prlist_val) || (viceid != client->ViceId)) {
1362 if (client->CPS.prlist_val && (client->ViceId != ANONYMOUSID)) {
1363 free(client->CPS.prlist_val);
1365 client->CPS.prlist_val = (afs_int32 *)0;
1366 client->ViceId = viceid;
1367 client->expTime = expTime;
1369 if (viceid == ANONYMOUSID) {
1370 client->CPS.prlist_len = AnonCPS.prlist_len;
1371 client->CPS.prlist_val = AnonCPS.prlist_val;
1374 code = pr_GetCPS(viceid, &client->CPS);
1377 ViceLog(0, ("pr_GetCPS failed(%d) for user %d, host %x.%d\n",
1378 code, viceid, client->host->host, ntohs(client->host->port)));
1380 /* Although ubik_Call (called by pr_GetCPS) traverses thru
1381 * all protection servers and reevaluates things if no
1382 * sync server or quorum is found we could still end up
1383 * with one of these errors. In such case we would like to
1384 * reevaluate the rpc call to find if there's cps for this
1385 * guy. We treat other errors (except network failures
1386 * ones - i.e. code < 0) as an indication that there is no
1387 * CPS for this host. Ideally we could like to deal this
1388 * problem the other way around (i.e. if code == NOCPS
1389 * ignore else retry next time) but the problem is that
1390 * there're other errors (i.e. EPERM) for which we don't
1391 * want to retry and we don't know the whole code list!
1393 if (code < 0 || code == UNOQUORUM || code == UNOTSYNC)
1397 /* the disabling of system:administrators is so iffy and has so many
1398 * possible failure modes that we will disable it again */
1399 /* Turn off System:Administrator for safety
1400 if (AL_IsAMember(SystemId, client->CPS) == 0)
1401 assert(AL_DisableGroup(SystemId, client->CPS) == 0); */
1404 /* Now, tcon may already be set to a rock, since we blocked with no host
1405 * or client locks set above in pr_GetCPS (XXXX some locking is probably
1406 * required). So, before setting the RPC's rock, we should disconnect
1407 * the RPC from the other client structure's rock.
1409 if (oldClient = (struct client *) rx_GetSpecific(tcon, rxcon_client_key)) {
1410 oldClient->tcon = (struct rx_connection *) 0;
1411 /* rx_SetSpecific will be done immediately below */
1413 client->tcon = tcon;
1414 rx_SetSpecific(tcon, rxcon_client_key, client);
1415 ReleaseWriteLock(&client->lock);
1419 } /*h_FindClient_r*/
1421 int h_ReleaseClient_r(client)
1422 struct client *client;
1424 assert(client->refCount > 0);
1431 * Sigh: this one is used to get the client AGAIN within the individual
1432 * server routines. This does not bother h_Holding the host, since
1433 * this is assumed already have been done by the server main loop.
1434 * It does check tokens, since only the server routines can return the
1435 * VICETOKENDEAD error code
1437 int GetClient(tcon, cp)
1438 struct rx_connection * tcon;
1442 register struct client *client;
1446 *cp = client = (struct client *) rx_GetSpecific(tcon, rxcon_client_key);
1448 assert(client && client->tcon && rxr_CidOf(client->tcon) == client->sid);
1450 client->LastCall > client->expTime && client->expTime) {
1451 ViceLog(1, ("Token for %s at %x.%d expired %d\n",
1452 h_UserName(client), client->host->host, client->host->port, client->expTime));
1454 return VICETOKENDEAD;
1463 /* Client user name for short term use. Note that this is NOT inexpensive */
1464 char *h_UserName(client)
1465 struct client *client;
1468 static char User[PR_MAXNAMELEN+1];
1472 lids.idlist_len = 1;
1473 lids.idlist_val = (afs_int32 *)malloc(1*sizeof(afs_int32));
1474 lnames.namelist_len = 0;
1475 lnames.namelist_val = (prname *)0;
1476 lids.idlist_val[0] = client->ViceId;
1477 if (pr_IdToName(&lids,&lnames)) {
1478 /* We need to free id we alloced above! */
1479 free(lids.idlist_val);
1480 return "*UNKNOWN USER NAME*";
1482 strncpy(User,lnames.namelist_val[0],PR_MAXNAMELEN);
1483 free(lids.idlist_val);
1484 free(lnames.namelist_val);
1494 ("Total Client entries = %d, blocks = %d; Host entries = %d, blocks = %d\n",
1495 CEs, CEBlocks, HTs, HTBlocks));
1500 static int h_PrintClient(host, held, file)
1501 register struct host *host;
1503 StreamHandle_t *file;
1505 register struct client *client;
1511 if (host->hostFlags & HOSTDELETED) {
1515 sprintf(tmpStr,"Host %x.%d down = %d, LastCall %s", host->host,
1516 host->port, (host->hostFlags & VENUSDOWN),
1517 afs_ctime((time_t *)&host->LastCall, tbuffer, sizeof(tbuffer)));
1518 STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
1519 for (client = host->FirstClient; client; client=client->next) {
1520 if (!client->deleted) {
1522 sprintf(tmpStr, " user id=%d, name=%s, sl=%s till %s",
1523 client->ViceId, h_UserName(client),
1524 client->authClass ? "Authenticated" : "Not authenticated",
1526 afs_ctime((time_t *)&client->expTime, tbuffer, sizeof(tbuffer))
1528 STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
1531 sprintf(tmpStr, " user=%s, no current server connection\n",
1532 h_UserName(client));
1533 STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
1535 sprintf(tmpStr, " CPS-%d is [", client->CPS.prlist_len);
1536 STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
1537 if (client->CPS.prlist_val) {
1538 for (i=0; i > client->CPS.prlist_len; i++) {
1539 sprintf(tmpStr, " %d", client->CPS.prlist_val[i]);
1540 STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
1543 sprintf(tmpStr, "]\n");
1544 STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
1555 * Print a list of clients, with last security level and token value seen,
1565 StreamHandle_t *file = STREAM_OPEN(AFSDIR_SERVER_CLNTDUMP_FILEPATH, "w");
1568 ViceLog(0, ("Couldn't create client dump file %s\n", AFSDIR_SERVER_CLNTDUMP_FILEPATH));
1571 now = FT_ApproxTime();
1572 sprintf(tmpStr, "List of active users at %s\n",
1573 afs_ctime(&now, tbuffer, sizeof(tbuffer)));
1574 STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
1575 h_Enumerate(h_PrintClient, (char *)file);
1576 STREAM_REALLYCLOSE(file);
1577 ViceLog(0, ("Created client dump %s\n", AFSDIR_SERVER_CLNTDUMP_FILEPATH));
1583 static int h_DumpHost(host, held, file)
1584 register struct host *host;
1586 StreamHandle_t *file;
1593 sprintf(tmpStr, "ip:%x holds:%d port:%d hidx:%d cbid:%d lock:%x last:%u active:%u down:%d del:%d cons:%d cldel:%d\n\t hpfailed:%d hcpsCall:%u hcps [",
1594 host->host, host->holds, host->port, host->index, host->cblist,
1595 CheckLock(&host->lock), host->LastCall, host->ActiveCall,
1596 (host->hostFlags & VENUSDOWN), host->hostFlags&HOSTDELETED,
1597 host->Console, host->hostFlags & CLIENTDELETED,
1598 host->hcpsfailed, host->cpsCall);
1599 STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
1600 if (host->hcps.prlist_val)
1601 for (i=0; i < host->hcps.prlist_len; i++) {
1602 sprintf(tmpStr, " %d", host->hcps.prlist_val[i]);
1603 STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
1605 sprintf(tmpStr, "] [");
1606 STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
1607 if ( host->interface)
1608 for (i=0; i < host->interface->numberOfInterfaces; i++) {
1609 sprintf(tmpStr, " %x", host->interface->addr[i]);
1610 STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
1612 sprintf(tmpStr, "]\n");
1613 STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
1624 StreamHandle_t *file = STREAM_OPEN(AFSDIR_SERVER_HOSTDUMP_FILEPATH, "w");
1629 ViceLog(0, ("Couldn't create host dump file %s\n", AFSDIR_SERVER_HOSTDUMP_FILEPATH));
1632 now = FT_ApproxTime();
1633 sprintf(tmpStr, "List of active hosts at %s\n",
1634 afs_ctime(&now, tbuffer, sizeof(tbuffer)));
1635 STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
1636 h_Enumerate(h_DumpHost, (char *) file);
1637 STREAM_REALLYCLOSE(file);
1638 ViceLog(0, ("Created host dump %s\n", AFSDIR_SERVER_HOSTDUMP_FILEPATH));
1644 * This counts the number of workstations, the number of active workstations,
1645 * and the number of workstations declared "down" (i.e. not heard from
1646 * recently). An active workstation has received a call since the cutoff
1647 * time argument passed.
1649 h_GetWorkStats(nump, activep, delp, cutofftime)
1653 afs_int32 cutofftime;
1657 register struct host *host;
1658 register int num=0, active=0, del=0;
1661 for (host = hostList; host; host = host->next) {
1662 if (!(host->hostFlags & HOSTDELETED)) {
1664 if (host->ActiveCall > cutofftime)
1666 if (host->hostFlags & VENUSDOWN)
1678 } /*h_GetWorkStats*/
1681 /*------------------------------------------------------------------------
1682 * PRIVATE h_ClassifyAddress
1685 * Given a target IP address and a candidate IP address (both
1686 * in host byte order), classify the candidate into one of three
1687 * buckets in relation to the target by bumping the counters passed
1691 * a_targetAddr : Target address.
1692 * a_candAddr : Candidate address.
1693 * a_sameNetOrSubnetP : Ptr to counter to bump when the two
1694 * addresses are either in the same network
1695 * or the same subnet.
1696 * a_diffSubnetP : ...when the candidate is in a different
1698 * a_diffNetworkP : ...when the candidate is in a different
1705 * The target and candidate addresses are both in host byte
1706 * order, NOT network byte order, when passed in.
1710 *------------------------------------------------------------------------*/
1712 static void h_ClassifyAddress(a_targetAddr, a_candAddr, a_sameNetOrSubnetP,
1713 a_diffSubnetP, a_diffNetworkP)
1714 afs_uint32 a_targetAddr;
1715 afs_uint32 a_candAddr;
1716 afs_int32 *a_sameNetOrSubnetP;
1717 afs_int32 *a_diffSubnetP;
1718 afs_int32 *a_diffNetworkP;
1720 { /*h_ClassifyAddress*/
1722 register int i; /*Iterator thru host hash table*/
1723 register struct host *hostP; /*Ptr to current host entry*/
1724 register afs_uint32 currHostAddr; /*Current host address*/
1725 afs_uint32 targetNet;
1726 afs_uint32 targetSubnet;
1728 afs_uint32 candSubnet;
1731 * Put bad values into the subnet info to start with.
1733 targetSubnet = (afs_uint32) 0;
1734 candSubnet = (afs_uint32) 0;
1737 * Pull out the network and subnetwork numbers from the target
1738 * and candidate addresses. We can short-circuit this whole
1739 * affair if the target and candidate addresses are not of the
1742 if (IN_CLASSA(a_targetAddr)) {
1743 if (!(IN_CLASSA(a_candAddr))) {
1744 (*a_diffNetworkP)++;
1747 targetNet = a_targetAddr & IN_CLASSA_NET;
1748 candNet = a_candAddr & IN_CLASSA_NET;
1749 if (IN_SUBNETA(a_targetAddr))
1750 targetSubnet = a_targetAddr & IN_CLASSA_SUBNET;
1751 if (IN_SUBNETA(a_candAddr))
1752 candSubnet = a_candAddr & IN_CLASSA_SUBNET;
1755 if (IN_CLASSB(a_targetAddr)) {
1756 if (!(IN_CLASSB(a_candAddr))) {
1757 (*a_diffNetworkP)++;
1760 targetNet = a_targetAddr & IN_CLASSB_NET;
1761 candNet = a_candAddr & IN_CLASSB_NET;
1762 if (IN_SUBNETB(a_targetAddr))
1763 targetSubnet = a_targetAddr & IN_CLASSB_SUBNET;
1764 if (IN_SUBNETB(a_candAddr))
1765 candSubnet = a_candAddr & IN_CLASSB_SUBNET;
1766 } /*Class B target*/
1768 if (IN_CLASSC(a_targetAddr)) {
1769 if (!(IN_CLASSC(a_candAddr))) {
1770 (*a_diffNetworkP)++;
1773 targetNet = a_targetAddr & IN_CLASSC_NET;
1774 candNet = a_candAddr & IN_CLASSC_NET;
1777 * Note that class C addresses can't have subnets,
1778 * so we leave the defaults untouched.
1780 } /*Class C target*/
1782 targetNet = a_targetAddr;
1783 candNet = a_candAddr;
1784 } /*Class D address*/
1787 * Now, simply compare the extracted net and subnet values for
1788 * the two addresses (which at this point are known to be of the
1791 if (targetNet == candNet) {
1792 if (targetSubnet == candSubnet)
1793 (*a_sameNetOrSubnetP)++;
1798 (*a_diffNetworkP)++;
1800 } /*h_ClassifyAddress*/
1803 /*------------------------------------------------------------------------
1804 * EXPORTED h_GetHostNetStats
1807 * Iterate through the host table, and classify each (non-deleted)
1808 * host entry into ``proximity'' categories (same net or subnet,
1809 * different subnet, different network).
1812 * a_numHostsP : Set to total number of (non-deleted) hosts.
1813 * a_sameNetOrSubnetP : Set to # hosts on same net/subnet as server.
1814 * a_diffSubnetP : Set to # hosts on diff subnet as server.
1815 * a_diffNetworkP : Set to # hosts on diff network as server.
1821 * We only count non-deleted hosts. The storage pointed to by our
1822 * parameters is zeroed upon entry.
1826 *------------------------------------------------------------------------*/
1828 void h_GetHostNetStats(a_numHostsP, a_sameNetOrSubnetP, a_diffSubnetP,
1830 afs_int32 *a_numHostsP;
1831 afs_int32 *a_sameNetOrSubnetP;
1832 afs_int32 *a_diffSubnetP;
1833 afs_int32 *a_diffNetworkP;
1835 { /*h_GetHostNetStats*/
1837 register struct host *hostP; /*Ptr to current host entry*/
1838 register afs_uint32 currAddr_HBO; /*Curr host addr, host byte order*/
1841 * Clear out the storage pointed to by our parameters.
1843 *a_numHostsP = (afs_int32) 0;
1844 *a_sameNetOrSubnetP = (afs_int32) 0;
1845 *a_diffSubnetP = (afs_int32) 0;
1846 *a_diffNetworkP = (afs_int32) 0;
1849 for (hostP = hostList; hostP; hostP = hostP->next) {
1850 if (!(hostP->hostFlags & HOSTDELETED)) {
1852 * Bump the number of undeleted host entries found.
1853 * In classifying the current entry's address, make
1854 * sure to first convert to host byte order.
1857 currAddr_HBO = (afs_uint32)ntohl(hostP->host);
1858 h_ClassifyAddress(FS_HostAddr_HBO,
1863 } /*Only look at non-deleted hosts*/
1864 } /*For each host record hashed to this index*/
1867 } /*h_GetHostNetStats*/
1869 static afs_uint32 checktime;
1870 static afs_uint32 clientdeletetime;
1871 static struct AFSFid zerofid;
1875 * XXXX: This routine could use Multi-R to avoid serializing the timeouts.
1876 * Since it can serialize them, and pile up, it should be a separate LWP
1877 * from other events.
1879 int CheckHost(host, held)
1880 register struct host *host;
1884 register struct client *client;
1885 struct interfaceAddr interf;
1888 /* Host is held by h_Enumerate */
1890 for (client = host->FirstClient; client; client = client->next) {
1891 if (client->refCount == 0 && client->LastCall < clientdeletetime) {
1892 client->deleted = 1;
1893 host->hostFlags |= CLIENTDELETED;
1896 if (host->LastCall < checktime) {
1898 if (!(host->hostFlags & HOSTDELETED)) {
1899 if (host->LastCall < clientdeletetime) {
1900 host->hostFlags |= HOSTDELETED;
1901 if (!(host->hostFlags & VENUSDOWN)) {
1902 host->hostFlags &= ~ALTADDR; /* alternate address invalid*/
1903 if (host->interface) {
1905 code = RXAFSCB_InitCallBackState3(host->callback_rxcon,
1910 code = RXAFSCB_InitCallBackState(host->callback_rxcon);
1913 host->hostFlags |= ALTADDR; /* alternate addresses valid */
1917 afs_inet_ntoa_r(host->host, hoststr);
1919 ("CB: RCallBackConnectBack (host.c) failed for host %s:%d\n",
1920 hoststr, ntohs(host->port)));
1921 host->hostFlags |= VENUSDOWN;
1923 /* Note: it's safe to delete hosts even if they have call
1924 * back state, because break delayed callbacks (called when a
1925 * message is received from the workstation) will always send a
1926 * break all call backs to the workstation if there is no
1932 if (!(host->hostFlags & VENUSDOWN) && host->cblist) {
1933 if (host->interface) {
1934 afsUUID uuid = host->interface->uuid;
1936 code = RXAFSCB_ProbeUuid(host->callback_rxcon, &uuid);
1939 if ( MultiProbeAlternateAddress_r(host) ) {
1941 afs_inet_ntoa_r(host->host, hoststr);
1943 ("ProbeUuid failed for host %s:%d\n",
1944 hoststr, ntohs(host->port)));
1945 host->hostFlags |= VENUSDOWN;
1950 code = RXAFSCB_Probe(host->callback_rxcon);
1954 afs_inet_ntoa_r(host->host, hoststr);
1955 ViceLog(0, ("ProbeUuid failed for host %s:%d\n",
1956 hoststr, ntohs(host->port)));
1957 host->hostFlags |= VENUSDOWN;
1972 * Set VenusDown for any hosts that have not had a call in 15 minutes and
1973 * don't respond to a probe. Note that VenusDown can only be cleared if
1974 * a message is received from the host (see ServerLWP in file.c).
1975 * Delete hosts that have not had any calls in 1 hour, clients that
1976 * have not had any calls in 15 minutes.
1978 * This routine is called roughly every 5 minutes.
1982 afs_uint32 now = FT_ApproxTime();
1984 bzero((char *)&zerofid, sizeof(zerofid));
1986 * Send a probe to the workstation if it hasn't been heard from in
1989 checktime = now - 15*60;
1990 clientdeletetime = now - 120*60; /* 2 hours ago */
1991 h_Enumerate(CheckHost, (char *) 0);
1996 * This is called with host locked and held. At this point, the
1997 * hostHashTable should not be having entries for the alternate
1998 * interfaces. This function has to insert these entries in the
2001 * The addresses in the ineterfaceAddr list are in host byte order.
2004 initInterfaceAddr_r(host, interf)
2006 struct interfaceAddr *interf;
2010 afs_int32 myPort, myHost;
2012 struct Interface *interface;
2017 ViceLog(125,("initInterfaceAddr : host %x numAddr %d\n",
2018 host->host, interf->numberOfInterfaces));
2020 number = interf->numberOfInterfaces;
2021 myPort = host->port;
2022 myHost = host->host; /* current interface address */
2024 /* validation checks */
2027 ViceLog(0,("Number of alternate addresses returned is %d\n",
2033 * Convert IP addresses to network byte order, and remove for
2034 * duplicate IP addresses from the interface list.
2036 for (i = 0, count = 0, found = 0; i < number; i++)
2038 interf->addr_in[i] = htonl(interf->addr_in[i]);
2039 for (j = 0 ; j < count ; j++) {
2040 if (interf->addr_in[j] == interf->addr_in[i])
2044 interf->addr_in[count] = interf->addr_in[i];
2045 if (interf->addr_in[count] == myHost)
2052 * Allocate and initialize an interface structure for this host.
2055 interface = (struct Interface *)
2056 malloc(sizeof(struct Interface) +
2057 (sizeof(afs_int32) * (count-1)));
2059 interface->numberOfInterfaces = count;
2061 interface = (struct Interface *)
2062 malloc(sizeof(struct Interface) +
2063 (sizeof(afs_int32) * count));
2065 interface->numberOfInterfaces = count + 1;
2066 interface->addr[count] = myHost;
2068 interface->uuid = interf->uuid;
2069 for (i = 0 ; i < count ; i++)
2070 interface->addr[i] = interf->addr_in[i];
2072 assert(!host->interface);
2073 host->interface = interface;
2075 for ( i=0; i < host->interface->numberOfInterfaces; i++)
2077 ViceLog(125,("--- alt address %x\n", host->interface->addr[i]));
2084 * This is called with host locked and held. At this point, the
2085 * hostHashTable should not be having entries for the alternate
2086 * interfaces. This function has to insert these entries in the
2089 * All addresses are in network byte order.
2092 addInterfaceAddr_r(host, addr)
2099 struct Interface *interface;
2102 assert(host->interface);
2104 ViceLog(125,("addInterfaceAddr : host %x addr %d\n",
2108 * Make sure this address is on the list of known addresses
2111 number = host->interface->numberOfInterfaces;
2112 for ( i=0, found=0; i < number && !found; i++)
2114 if ( host->interface->addr[i] == addr)
2118 interface = (struct Interface *)
2119 malloc(sizeof(struct Interface) +
2120 (sizeof(afs_int32) * number));
2121 interface->numberOfInterfaces = number + 1;
2122 interface->uuid = host->interface->uuid;
2123 for (i = 0 ; i < number ; i++)
2124 interface->addr[i] = host->interface->addr[i];
2125 interface->addr[number] = addr;
2126 free(host->interface);
2127 host->interface = interface;
2131 * Create a hash table entry for this address
2133 hashInsert_r(addr, host);
2138 /* inserts a new HashChain structure corresponding to this address */
2139 hashInsert_r(addr, host)
2144 struct h_hashChain* chain;
2146 /* hash into proper bucket */
2147 index = h_HashIndex(addr);
2149 /* insert into beginning of list for this bucket */
2150 chain = (struct h_hashChain *)malloc(sizeof(struct h_hashChain));
2152 chain->hostPtr = host;
2153 chain->next = hostHashTable[index];
2155 hostHashTable[index] = chain;
2159 /* inserts a new HashChain structure corresponding to this UUID */
2160 hashInsertUuid_r(uuid, host)
2161 struct afsUUID *uuid;
2165 struct h_hashChain* chain;
2167 /* hash into proper bucket */
2168 index = h_UuidHashIndex(uuid);
2170 /* insert into beginning of list for this bucket */
2171 chain = (struct h_hashChain *)malloc(sizeof(struct h_hashChain));
2173 chain->hostPtr = host;
2174 chain->next = hostUuidHashTable[index];
2175 hostUuidHashTable[index] = chain;
2178 /* deleted a HashChain structure for this address and host */
2179 /* returns 1 on success */
2181 hashDelete_r(addr, host)
2187 register struct h_hashChain **hp, *th;
2189 for (hp = &hostHashTable[h_HashIndex(addr)]; th = *hp; )
2191 assert(th->hostPtr);
2192 if (th->hostPtr == host && th->addr == addr)
2207 ** prints out all alternate interface address for the host. The 'level'
2208 ** parameter indicates what level of debugging sets this output
2210 printInterfaceAddr(host, level)
2215 if ( host-> interface )
2217 /* check alternate addresses */
2218 number = host->interface->numberOfInterfaces;
2219 assert( number > 0 );
2220 for ( i=0; i < number; i++)
2221 ViceLog(level, ("%x ", host->interface->addr[i]));
2223 ViceLog(level, ("\n"));