unroll-macos-104-20050523
[openafs.git] / src / afs / afs_server.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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
8  */
9
10 /*
11  * Implements:
12  * afs_MarkServerUpOrDown
13  * afs_ServerDown
14  * afs_CountServers
15  * afs_CheckServers
16  * afs_FindServer
17  * afs_random
18  * afs_randomMod127
19  * afs_SortServers
20  * afsi_SetServerIPRank
21  * afs_GetServer
22  * afs_ActivateServer
23  * 
24  *
25  * Local:
26  * HaveCallBacksFrom
27  * CheckVLServer
28  * afs_SortOneServer
29  * afs_SetServerPrefs
30  * 
31  */
32 #include <afsconfig.h>
33 #include "afs/param.h"
34
35 RCSID
36     ("$Header$");
37
38 #include "afs/stds.h"
39 #include "afs/sysincludes.h"    /* Standard vendor system headers */
40
41 #if !defined(UKERNEL)
42 #if !defined(AFS_LINUX20_ENV)
43 #include <net/if.h>
44 #endif
45 #include <netinet/in.h>
46
47 #ifdef AFS_SGI62_ENV
48 #include "h/hashing.h"
49 #endif
50 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN60_ENV)
51 #include <netinet/in_var.h>
52 #endif /* AFS_HPUX110_ENV */
53 #ifdef AFS_DARWIN60_ENV
54 #include <net/if_var.h>
55 #endif
56 #endif /* !defined(UKERNEL) */
57
58 #include "afsincludes.h"        /* Afs-based standard headers */
59 #include "afs/afs_stats.h"      /* afs statistics */
60 #include "rx/rx_multi.h"
61
62 #if     defined(AFS_SUN56_ENV)
63 #include <inet/led.h>
64 #include <inet/common.h>
65 #if     defined(AFS_SUN58_ENV)
66 # include <netinet/ip6.h>
67 # define ipif_local_addr ipif_lcl_addr
68 #  ifndef V4_PART_OF_V6
69 #  define V4_PART_OF_V6(v6)       v6.s6_addr32[3]
70 #  endif
71 # endif
72 #include <inet/ip.h>
73 #endif
74
75 /* Exported variables */
76 afs_rwlock_t afs_xserver;       /* allocation lock for servers */
77 struct server *afs_setTimeHost = 0;     /* last host we used for time */
78 struct server *afs_servers[NSERVERS];   /* Hashed by server`s uuid & 1st ip */
79 afs_rwlock_t afs_xsrvAddr;      /* allocation lock for srvAddrs */
80 struct srvAddr *afs_srvAddrs[NSERVERS]; /* Hashed by server's ip */
81
82
83 /* debugging aids - number of alloc'd server and srvAddr structs. */
84 int afs_reuseServers = 0;
85 int afs_reuseSrvAddrs = 0;
86 int afs_totalServers = 0;
87 int afs_totalSrvAddrs = 0;
88
89
90
91 static struct afs_stats_SrvUpDownInfo *
92 GetUpDownStats(struct server *srv)
93 {
94     struct afs_stats_SrvUpDownInfo *upDownP;
95     u_short fsport = AFS_FSPORT;
96
97     if (srv->cell)
98         fsport = srv->cell->fsport;
99
100     if (srv->addr->sa_portal == fsport)
101         upDownP = afs_stats_cmperf.fs_UpDown;
102     else
103         upDownP = afs_stats_cmperf.vl_UpDown;
104
105     if (srv->cell && afs_IsPrimaryCell(srv->cell))
106         return &upDownP[AFS_STATS_UPDOWN_IDX_SAME_CELL];
107     else
108         return &upDownP[AFS_STATS_UPDOWN_IDX_DIFF_CELL];
109 }
110
111
112 /*------------------------------------------------------------------------
113  * afs_MarkServerUpOrDown
114  *
115  * Description:
116  *      Mark the given server up or down, and track its uptime stats.
117  *
118  * Arguments:
119  *      a_serverP : Ptr to server record to fiddle with.
120  *      a_isDown  : Is the server is to be marked down?
121  *
122  * Returns:
123  *      Nothing.
124  *
125  * Environment:
126  *      The CM server structures must be write-locked.
127  *
128  * Side Effects:
129  *      As advertised.
130  *------------------------------------------------------------------------*/
131
132 void
133 afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
134 {
135     register struct server *a_serverP = sa->server;
136     register struct srvAddr *sap;
137     osi_timeval_t currTime, *currTimeP; /*Current time */
138     afs_int32 downTime;         /*Computed downtime, in seconds */
139     struct afs_stats_SrvUpDownInfo *upDownP;    /*Ptr to up/down info record */
140
141     /*
142      * If the server record is marked the same as the new status we've
143      * been fed, then there isn't much to be done.
144      */
145     if ((a_isDown && (sa->sa_flags & SRVADDR_ISDOWN))
146         || (!a_isDown && !(sa->sa_flags & SRVADDR_ISDOWN)))
147         return;
148
149     if (a_isDown) {
150         sa->sa_flags |= SRVADDR_ISDOWN;
151         for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
152             if (!(sap->sa_flags & SRVADDR_ISDOWN)) {
153                 /* Not all ips are up so don't bother with the
154                  * server's up/down stats */
155                 return;
156             }
157         }
158         /* 
159          * All ips are down we treat the whole server down
160          */
161         a_serverP->flags |= SRVR_ISDOWN;
162         /*
163          * If this was our time server, search for another time server
164          */
165         if (a_serverP == afs_setTimeHost)
166             afs_setTimeHost = 0;
167     } else {
168         sa->sa_flags &= ~SRVADDR_ISDOWN;
169         /* If any ips are up, the server is also marked up */
170         a_serverP->flags &= ~SRVR_ISDOWN;
171         for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
172             if (sap->sa_flags & SRVADDR_ISDOWN) {
173                 /* Not all ips are up so don't bother with the
174                  * server's up/down stats */
175                 return;
176             }
177         }
178     }
179 #ifndef AFS_NOSTATS
180     /*
181      * Compute the current time and which overall stats record is to be
182      * updated; we'll need them one way or another.
183      */
184     currTimeP = &currTime;
185     osi_GetuTime(currTimeP);
186
187     upDownP = GetUpDownStats(a_serverP);
188
189     if (a_isDown) {
190         /*
191          * Server going up -> down; remember the beginning of this
192          * downtime incident.
193          */
194         a_serverP->lastDowntimeStart = currTime.tv_sec;
195
196         (upDownP->numDownRecords)++;
197         (upDownP->numUpRecords)--;
198     } /*Server being marked down */
199     else {
200         /*
201          * Server going down -> up; remember everything about this
202          * newly-completed downtime incident.
203          */
204         downTime = currTime.tv_sec - a_serverP->lastDowntimeStart;
205         (a_serverP->numDowntimeIncidents)++;
206         a_serverP->sumOfDowntimes += downTime;
207
208         (upDownP->numUpRecords)++;
209         (upDownP->numDownRecords)--;
210         (upDownP->numDowntimeIncidents)++;
211         if (a_serverP->numDowntimeIncidents == 1)
212             (upDownP->numRecordsNeverDown)--;
213         upDownP->sumOfDowntimes += downTime;
214         if ((upDownP->shortestDowntime == 0)
215             || (downTime < upDownP->shortestDowntime))
216             upDownP->shortestDowntime = downTime;
217         if ((upDownP->longestDowntime == 0)
218             || (downTime > upDownP->longestDowntime))
219             upDownP->longestDowntime = downTime;
220
221
222         if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET0)
223             (upDownP->downDurations[0])++;
224         else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET1)
225             (upDownP->downDurations[1])++;
226         else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET2)
227             (upDownP->downDurations[2])++;
228         else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET3)
229             (upDownP->downDurations[3])++;
230         else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET4)
231             (upDownP->downDurations[4])++;
232         else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET5)
233             (upDownP->downDurations[5])++;
234         else
235             (upDownP->downDurations[6])++;
236
237     }                           /*Server being marked up */
238 #endif
239 }                               /*MarkServerUpOrDown */
240
241
242 void
243 afs_ServerDown(struct srvAddr *sa)
244 {
245     register struct server *aserver = sa->server;
246
247     AFS_STATCNT(ServerDown);
248     if (aserver->flags & SRVR_ISDOWN || sa->sa_flags & SRVADDR_ISDOWN)
249         return;
250     afs_MarkServerUpOrDown(sa, SRVR_ISDOWN);
251     if (sa->sa_portal == aserver->cell->vlport)
252         print_internet_address
253             ("afs: Lost contact with volume location server ", sa, "", 1);
254     else
255         print_internet_address("afs: Lost contact with file server ", sa, "",
256                                1);
257
258 }                               /*ServerDown */
259
260
261 /* return true if we have any callback promises from this server */
262 int
263 afs_HaveCallBacksFrom(struct server *aserver)
264 {
265     register afs_int32 now;
266     register int i;
267     register struct vcache *tvc;
268
269     AFS_STATCNT(HaveCallBacksFrom);
270     now = osi_Time();           /* for checking for expired callbacks */
271     for (i = 0; i < VCSIZE; i++) {      /* for all guys in the hash table */
272         for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
273             /*
274              * Check to see if this entry has an unexpired callback promise
275              * from the required host
276              */
277             if (aserver == tvc->callback && tvc->cbExpires >= now
278                 && ((tvc->states & CRO) == 0))
279                 return 1;
280         }
281     }
282     return 0;
283
284 }                               /*HaveCallBacksFrom */
285
286
287 static void
288 CheckVLServer(register struct srvAddr *sa, struct vrequest *areq)
289 {
290     register struct server *aserver = sa->server;
291     register struct conn *tc;
292     register afs_int32 code;
293
294     AFS_STATCNT(CheckVLServer);
295     /* Ping dead servers to see if they're back */
296     if (!((aserver->flags & SRVR_ISDOWN) || (sa->sa_flags & SRVADDR_ISDOWN))
297         || (aserver->flags & SRVR_ISGONE))
298         return;
299     if (!aserver->cell)
300         return;                 /* can't do much */
301
302     tc = afs_ConnByHost(aserver, aserver->cell->vlport,
303                         aserver->cell->cellNum, areq, 1, SHARED_LOCK);
304     if (!tc)
305         return;
306     rx_SetConnDeadTime(tc->id, 3);
307
308     RX_AFS_GUNLOCK();
309     code = VL_ProbeServer(tc->id);
310     RX_AFS_GLOCK();
311     rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
312     afs_PutConn(tc, SHARED_LOCK);
313     /*
314      * If probe worked, or probe call not yet defined (for compatibility
315      * with old vlsevers), then we treat this server as running again
316      */
317     if (code == 0 || (code <= -450 && code >= -470)) {
318         if (tc->srvr == sa) {
319             afs_MarkServerUpOrDown(sa, 0);
320             print_internet_address("afs: volume location server ", sa,
321                                    " is back up", 2);
322         }
323     }
324
325 }                               /*CheckVLServer */
326
327
328 #ifndef AFS_MINCHANGE           /* So that some can increase it in param.h */
329 #define AFS_MINCHANGE 2         /* min change we'll bother with */
330 #endif
331 #ifndef AFS_MAXCHANGEBACK
332 #define AFS_MAXCHANGEBACK 10    /* max seconds we'll set a clock back at once */
333 #endif
334
335
336 /*------------------------------------------------------------------------
337  * EXPORTED afs_CountServers
338  *
339  * Description:
340  *      Originally meant to count the number of servers and determining
341  *      up/down info, this routine will now simply sum up all of the
342  *      server record ages.  All other up/down information is kept on the
343  *      fly.
344  *
345  * Arguments:
346  *      None.
347  *
348  * Returns:
349  *      Nothing.
350  *
351  * Environment:
352  *      This routine locks afs_xserver for write for the duration.
353  *
354  * Side Effects:
355  *      Set CM perf stats field sumOfRecordAges for all server record
356  *      entries.
357  *------------------------------------------------------------------------*/
358
359 void
360 afs_CountServers(void)
361 {
362     int currIdx;                /*Curr idx into srv table */
363     struct server *currSrvP;    /*Ptr to curr server record */
364     afs_int32 currChainLen;     /*Length of curr hash chain */
365     osi_timeval_t currTime;     /*Current time */
366     osi_timeval_t *currTimeP;   /*Ptr to above */
367     afs_int32 srvRecordAge;     /*Age of server record, in secs */
368     struct afs_stats_SrvUpDownInfo *upDownP;    /*Ptr to current up/down
369                                                  * info being manipulated */
370
371     /*
372      * Write-lock the server table so we don't get any interference.
373      */
374     ObtainReadLock(&afs_xserver);
375
376     /*
377      * Iterate over each hash index in the server table, walking down each
378      * chain and tallying what we haven't computed from the records there on
379      * the fly.  First, though, initialize the tallies that will change.
380      */
381     afs_stats_cmperf.srvMaxChainLength = 0;
382
383     afs_stats_cmperf.fs_UpDown[0].sumOfRecordAges = 0;
384     afs_stats_cmperf.fs_UpDown[0].ageOfYoungestRecord = 0;
385     afs_stats_cmperf.fs_UpDown[0].ageOfOldestRecord = 0;
386     memset((char *)afs_stats_cmperf.fs_UpDown[0].downIncidents, 0,
387            AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
388
389     afs_stats_cmperf.fs_UpDown[1].sumOfRecordAges = 0;
390     afs_stats_cmperf.fs_UpDown[1].ageOfYoungestRecord = 0;
391     afs_stats_cmperf.fs_UpDown[1].ageOfOldestRecord = 0;
392     memset((char *)afs_stats_cmperf.fs_UpDown[1].downIncidents, 0,
393            AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
394
395     afs_stats_cmperf.vl_UpDown[0].sumOfRecordAges = 0;
396     afs_stats_cmperf.vl_UpDown[0].ageOfYoungestRecord = 0;
397     afs_stats_cmperf.vl_UpDown[0].ageOfOldestRecord = 0;
398     memset((char *)afs_stats_cmperf.vl_UpDown[0].downIncidents, 0,
399            AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
400
401     afs_stats_cmperf.vl_UpDown[1].sumOfRecordAges = 0;
402     afs_stats_cmperf.vl_UpDown[1].ageOfYoungestRecord = 0;
403     afs_stats_cmperf.vl_UpDown[1].ageOfOldestRecord = 0;
404     memset((char *)afs_stats_cmperf.vl_UpDown[1].downIncidents, 0,
405            AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
406
407     /*
408      * Compute the current time, used to figure out server record ages.
409      */
410     currTimeP = &currTime;
411     osi_GetuTime(currTimeP);
412
413     /*
414      * Sweep the server hash table, tallying all we need to know.
415      */
416     for (currIdx = 0; currIdx < NSERVERS; currIdx++) {
417         currChainLen = 0;
418         for (currSrvP = afs_servers[currIdx]; currSrvP;
419              currSrvP = currSrvP->next) {
420             /*
421              * Bump the current chain length.
422              */
423             currChainLen++;
424
425             /*
426              * Any further tallying for this record will only be done if it has
427              * been activated. 
428              */
429             if ((currSrvP->flags & AFS_SERVER_FLAG_ACTIVATED)
430                 && currSrvP->addr && currSrvP->cell) {
431
432                 /*
433                  * Compute the current server record's age, then remember it
434                  * in the appropriate places.
435                  */
436                 srvRecordAge = currTime.tv_sec - currSrvP->activationTime;
437                 upDownP = GetUpDownStats(currSrvP);
438                 upDownP->sumOfRecordAges += srvRecordAge;
439                 if ((upDownP->ageOfYoungestRecord == 0)
440                     || (srvRecordAge < upDownP->ageOfYoungestRecord))
441                     upDownP->ageOfYoungestRecord = srvRecordAge;
442                 if ((upDownP->ageOfOldestRecord == 0)
443                     || (srvRecordAge > upDownP->ageOfOldestRecord))
444                     upDownP->ageOfOldestRecord = srvRecordAge;
445
446                 if (currSrvP->numDowntimeIncidents <=
447                     AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET0)
448                     (upDownP->downIncidents[0])++;
449                 else if (currSrvP->numDowntimeIncidents <=
450                          AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET1)
451                     (upDownP->downIncidents[1])++;
452                 else if (currSrvP->numDowntimeIncidents <=
453                          AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET2)
454                     (upDownP->downIncidents[2])++;
455                 else if (currSrvP->numDowntimeIncidents <=
456                          AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET3)
457                     (upDownP->downIncidents[3])++;
458                 else if (currSrvP->numDowntimeIncidents <=
459                          AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET4)
460                     (upDownP->downIncidents[4])++;
461                 else
462                     (upDownP->downIncidents[5])++;
463
464
465             }                   /*Current server has been active */
466         }                       /*Walk this chain */
467
468         /*
469          * Before advancing to the next chain, remember facts about this one.
470          */
471         if (currChainLen > afs_stats_cmperf.srvMaxChainLength) {
472             /*
473              * We beat out the former champion (which was initially set to 0
474              * here).  Mark down the new winner, and also remember if it's an
475              * all-time winner.
476              */
477             afs_stats_cmperf.srvMaxChainLength = currChainLen;
478             if (currChainLen > afs_stats_cmperf.srvMaxChainLengthHWM)
479                 afs_stats_cmperf.srvMaxChainLengthHWM = currChainLen;
480         }                       /*Update chain length maximum */
481     }                           /*For each hash chain */
482
483     /*
484      * We're done.  Unlock the server table before returning to our caller.
485      */
486     ReleaseReadLock(&afs_xserver);
487
488 }                               /*afs_CountServers */
489
490
491 /* check down servers (if adown), or running servers (if !adown) */
492 void
493 afs_CheckServers(int adown, struct cell *acellp)
494 {
495     struct vrequest treq;
496     struct server *ts;
497     struct srvAddr *sa;
498     struct conn *tc;
499     afs_int32 i, j;
500     afs_int32 code;
501     afs_int32 start, end = 0, delta;
502     osi_timeval_t tv;
503     struct unixuser *tu;
504     char tbuffer[CVBS];
505     int srvAddrCount;
506     struct srvAddr **addrs;
507     struct conn **conns;
508     int nconns;
509     struct rx_connection **rxconns;      
510     afs_int32 *conntimer, *deltas, *results;
511
512     AFS_STATCNT(afs_CheckServers);
513
514     conns = (struct conn **)0;
515     rxconns = (struct rx_connection **) 0;
516     conntimer = 0;
517     nconns = 0;
518
519     if ((code = afs_InitReq(&treq, afs_osi_credp)))
520         return;
521     ObtainReadLock(&afs_xserver);       /* Necessary? */
522     ObtainReadLock(&afs_xsrvAddr);
523
524     srvAddrCount = 0;
525     for (i = 0; i < NSERVERS; i++) {
526         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
527             srvAddrCount++;
528         }
529     }
530
531     addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
532     j = 0;
533     for (i = 0; i < NSERVERS; i++) {
534         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
535             if (j >= srvAddrCount)
536                 break;
537             addrs[j++] = sa;
538         }
539     }
540
541     ReleaseReadLock(&afs_xsrvAddr);
542     ReleaseReadLock(&afs_xserver);
543
544     conns = (struct conn **)afs_osi_Alloc(j * sizeof(struct conn *));
545     rxconns = (struct rx_connection **)afs_osi_Alloc(j * sizeof(struct rx_connection *));
546     conntimer = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
547     deltas = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
548     results = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
549
550     for (i = 0; i < j; i++) {
551         deltas[i] = 0;
552         sa = addrs[i];
553         ts = sa->server;
554         if (!ts)
555             continue;
556
557         /* See if a cell to check was specified.  If it is spec'd and not
558          * this server's cell, just skip the server.
559          */
560         if (acellp && acellp != ts->cell)
561             continue;
562
563         if ((!adown && (sa->sa_flags & SRVADDR_ISDOWN))
564             || (adown && !(sa->sa_flags & SRVADDR_ISDOWN)))
565             continue;
566
567         /* check vlserver with special code */
568         if (sa->sa_portal == AFS_VLPORT) {
569             CheckVLServer(sa, &treq);
570             continue;
571         }
572
573         if (!ts->cell)          /* not really an active server, anyway, it must */
574             continue;           /* have just been added by setsprefs */
575
576         /* get a connection, even if host is down; bumps conn ref count */
577         tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
578         tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
579                           1 /*force */ , 1 /*create */ , SHARED_LOCK);
580         afs_PutUser(tu, SHARED_LOCK);
581         if (!tc)
582             continue;
583
584         if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)
585             || (tc->srvr->server == afs_setTimeHost)) {
586             conns[nconns]=tc; 
587             rxconns[nconns]=tc->id;
588             if (sa->sa_flags & SRVADDR_ISDOWN) {
589                 rx_SetConnDeadTime(tc->id, 3);
590                 conntimer[nconns]=1;
591             } else {
592                 conntimer[nconns]=0;
593             }
594             nconns++;
595         }
596     } /* Outer loop over addrs */
597
598     start = osi_Time();         /* time the gettimeofday call */
599     AFS_GUNLOCK(); 
600     multi_Rx(rxconns,nconns)
601       {
602         tv.tv_sec = tv.tv_usec = 0;
603         multi_RXAFS_GetTime(&tv.tv_sec, &tv.tv_usec);
604         tc = conns[multi_i];
605         sa = tc->srvr;
606         if (conntimer[multi_i] == 0)
607           rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
608         end = osi_Time();
609         results[multi_i]=multi_error;
610         if ((start == end) && !multi_error)
611           deltas[multi_i] = end - tv.tv_sec;
612         
613       } multi_End;
614     AFS_GLOCK(); 
615     
616     for(i=0;i<nconns;i++){
617       tc = conns[i];
618       sa = tc->srvr;
619       
620       if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) && (tc->srvr == sa)) {
621         /* server back up */
622         print_internet_address("afs: file server ", sa, " is back up", 2);
623         
624         ObtainWriteLock(&afs_xserver, 244);
625         ObtainWriteLock(&afs_xsrvAddr, 245);        
626         afs_MarkServerUpOrDown(sa, 0);
627         ReleaseWriteLock(&afs_xsrvAddr);
628         ReleaseWriteLock(&afs_xserver);
629         
630         if (afs_waitForeverCount) {
631           afs_osi_Wakeup(&afs_waitForever);
632         }
633       } else {
634         if (results[i] < 0) {
635           /* server crashed */
636           afs_ServerDown(sa);
637           ForceNewConnections(sa);  /* multi homed clients */
638         }
639       }
640     }
641
642     /*
643      * If we're supposed to set the time, and the call worked
644      * quickly (same second response) and this is the host we
645      * use for the time and the time is really different, then
646      * really set the time
647      */
648     if (afs_setTime != 0) {
649         for (i=0; i<nconns; i++) {
650             delta = deltas[i];
651             tc = conns[i];
652             sa = tc->srvr;
653             
654             if ((tc->srvr->server == afs_setTimeHost ||
655                  /* Sync only to a server in the local cell */
656                  (afs_setTimeHost == (struct server *)0 &&
657                   afs_IsPrimaryCell(sa->server->cell)))) {
658                 /* set the time */
659                 char msgbuf[90];  /* strlen("afs: setting clock...") + slop */
660                 delta = end - tv.tv_sec;   /* how many secs fast we are */
661                 
662                 afs_setTimeHost = tc->srvr->server;
663                 /* see if clock has changed enough to make it worthwhile */
664                 if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
665                     end = osi_Time();
666                     if (delta > AFS_MAXCHANGEBACK) {
667                         /* setting clock too far back, just do it a little */
668                         tv.tv_sec = end - AFS_MAXCHANGEBACK;
669                     } else {
670                         tv.tv_sec = end - delta;
671                     }
672                     afs_osi_SetTime(&tv);
673                     if (delta > 0) {
674                         strcpy(msgbuf, "afs: setting clock back ");
675                         if (delta > AFS_MAXCHANGEBACK) {
676                             afs_strcat(msgbuf, 
677                                        afs_cv2string(&tbuffer[CVBS], 
678                                                      AFS_MAXCHANGEBACK));
679                             afs_strcat(msgbuf, " seconds (of ");
680                             afs_strcat(msgbuf, 
681                                        afs_cv2string(&tbuffer[CVBS], 
682                                                      delta - 
683                                                      AFS_MAXCHANGEBACK));
684                             afs_strcat(msgbuf, ", via ");
685                             print_internet_address(msgbuf, sa, 
686                                                    "); clock is still fast.",
687                                                    0);
688                         } else {
689                             afs_strcat(msgbuf, 
690                                        afs_cv2string(&tbuffer[CVBS], delta));
691                             afs_strcat(msgbuf, " seconds (via ");
692                             print_internet_address(msgbuf, sa, ").", 0);
693                         }
694                     } else {
695                         strcpy(msgbuf, "afs: setting clock ahead ");
696                         afs_strcat(msgbuf, 
697                                    afs_cv2string(&tbuffer[CVBS], -delta));
698                         afs_strcat(msgbuf, " seconds (via ");
699                         print_internet_address(msgbuf, sa, ").", 0);
700                     }
701                     /* We're only going to set it once; why bother looping? */
702                     break; 
703                 }
704             }
705         }
706     }
707     for (i = 0; i < nconns; i++) {
708         afs_PutConn(conns[i], SHARED_LOCK);     /* done with it now */
709     }
710     
711     afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
712     afs_osi_Free(conns, j * sizeof(struct conn *));
713     afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
714     afs_osi_Free(conntimer, j * sizeof(afs_int32));
715     afs_osi_Free(deltas, j * sizeof(afs_int32));
716     afs_osi_Free(results, j * sizeof(afs_int32));
717     
718 } /*afs_CheckServers*/
719
720
721 /* find a server structure given the host address */
722 struct server *
723 afs_FindServer(afs_int32 aserver, afs_uint16 aport, afsUUID * uuidp,
724                afs_int32 locktype)
725 {
726     struct server *ts;
727     struct srvAddr *sa;
728     int i;
729
730     AFS_STATCNT(afs_FindServer);
731     if (uuidp) {
732         i = afs_uuid_hash(uuidp) % NSERVERS;
733         for (ts = afs_servers[i]; ts; ts = ts->next) {
734             if ((ts->flags & SRVR_MULTIHOMED)
735                 &&
736                 (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp))
737                  == 0) && (!ts->addr || (ts->addr->sa_portal == aport)))
738                 return ts;
739         }
740     } else {
741         i = SHash(aserver);
742         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
743             if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
744                 return sa->server;
745             }
746         }
747     }
748     return NULL;
749
750 }                               /*afs_FindServer */
751
752
753 /* some code for creating new server structs and setting preferences follows
754  * in the next few lines...
755  */
756
757 #define MAXDEFRANK 60000
758 #define DEFRANK    40000
759
760 /* Random number generator and constants from KnuthV2 2d ed, p170 */
761
762 /* Rules:
763    X = (aX + c) % m
764    m is a power of two 
765    a % 8 is 5
766    a is 0.73m  should be 0.01m .. 0.99m
767    c is more or less immaterial.  1 or a is suggested.
768   
769 NB:  LOW ORDER BITS are not very random.  To get small random numbers,
770      treat result as <1, with implied binary point, and multiply by 
771      desired modulus.
772 NB:  Has to be unsigned, since shifts on signed quantities may preserve
773      the sign bit.
774 */
775 /* added rxi_getaddr() to try to get as much initial randomness as 
776    possible, since at least one customer reboots ALL their clients 
777    simultaneously -- so osi_Time is bound to be the same on some of the
778    clients.  This is probably OK, but I don't want to see too much of it.
779 */
780
781 #define ranstage(x)     (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
782
783 unsigned int
784 afs_random(void)
785 {
786     static afs_int32 state = 0;
787     register int i;
788
789     AFS_STATCNT(afs_random);
790     if (!state) {
791         osi_timeval_t t;
792         osi_GetTime(&t);
793         /*
794          * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
795          * bits are in a tv_usec
796          */
797         state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
798         state += (t.tv_sec & 0xff);
799         for (i = 0; i < 30; i++) {
800             ranstage(state);
801         }
802     }
803
804     ranstage(state);
805     return (state);
806
807 }                               /*afs_random */
808
809 /* returns int 0..14 using the high bits of a pseudo-random number instead of
810    the low bits, as the low bits are "less random" than the high ones...
811    slight roundoff error exists, an excercise for the reader.
812    need to multiply by something with lots of ones in it, so multiply by 
813    8 or 16 is right out.
814  */
815 int
816 afs_randomMod15(void)
817 {
818     afs_uint32 temp;
819
820     temp = afs_random() >> 4;
821     temp = (temp * 15) >> 28;
822
823     return temp;
824 }
825
826 int
827 afs_randomMod127(void)
828 {
829     afs_uint32 temp;
830
831     temp = afs_random() >> 7;
832     temp = (temp * 127) >> 25;
833
834     return temp;
835 }
836
837 /* afs_SortOneServer()
838  * Sort all of the srvAddrs, of a server struct, by rank from low to high.
839  */
840 void
841 afs_SortOneServer(struct server *asp)
842 {
843     struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
844     int lowrank, rank;
845
846     for (rootsa = &(asp->addr); *rootsa; rootsa = &(lowsa->next_sa)) {
847         lowprev = NULL;
848         lowsa = *rootsa;        /* lowest sa is the first one */
849         lowrank = lowsa->sa_iprank;
850
851         for (tsa = *rootsa; tsa->next_sa; tsa = tsa->next_sa) {
852             rank = tsa->next_sa->sa_iprank;
853             if (rank < lowrank) {
854                 lowprev = tsa;
855                 lowsa = tsa->next_sa;
856                 lowrank = lowsa->sa_iprank;
857             }
858         }
859         if (lowprev) {          /* found one lower, so rearrange them */
860             lowprev->next_sa = lowsa->next_sa;
861             lowsa->next_sa = *rootsa;
862             *rootsa = lowsa;
863         }
864     }
865 }
866
867 /* afs_SortServer()
868  * Sort the pointer to servers by the server's rank (its lowest rank).
869  * It is assumed that the server already has its IP addrs sorted (the
870  * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
871  */
872 void
873 afs_SortServers(struct server *aservers[], int count)
874 {
875     struct server *ts;
876     int i, j, low;
877
878     AFS_STATCNT(afs_SortServers);
879
880     for (i = 0; i < count; i++) {
881         if (!aservers[i])
882             break;
883         for (low = i, j = i + 1; j <= count; j++) {
884             if ((!aservers[j]) || (!aservers[j]->addr))
885                 break;
886             if ((!aservers[low]) || (!aservers[low]->addr))
887                 break;
888             if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
889                 low = j;
890             }
891         }
892         if (low != i) {
893             ts = aservers[i];
894             aservers[i] = aservers[low];
895             aservers[low] = ts;
896         }
897     }
898 }                               /*afs_SortServers */
899
900 /* afs_SetServerPrefs is rather system-dependent.  It pokes around in kernel
901    data structures to determine what the local IP addresses and subnet masks 
902    are in order to choose which server(s) are on the local subnet.
903
904    As I see it, there are several cases:
905    1. The server address is one of this host's local addresses.  In this case
906           this server is to be preferred over all others.
907    2. The server is on the same subnet as one of the this host's local
908       addresses.  (ie, an odd-sized subnet, not class A,B,orC)
909    3. The server is on the same net as this host (class A,B or C)
910    4. The server is on a different logical subnet or net than this host, but
911    this host is a 'metric 0 gateway' to it.  Ie, two address-spaces share
912    one physical medium.
913    5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the 
914    server.
915    6. This host and the server are disjoint.
916
917    That is a rough order of preference.  If a point-to-point link has a high
918    metric, I'm assuming that it is a very slow link, and putting it at the 
919    bottom of the list (at least until RX works better over slow links).  If 
920    its metric is 1, I'm assuming that it's relatively fast (T1) and putting 
921    it ahead of #6.
922    It's not easy to check for case #4, so I'm ignoring it for the time being.
923
924    BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
925    That could be used to prefer certain servers fairly easily.  Maybe some 
926    other time...
927
928    NOTE: this code is very system-dependent, and very dependent on the TCP/IP
929    protocols (well, addresses that are stored in uint32s, at any rate).
930  */
931
932 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
933 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
934
935 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
936 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
937 #define TOPR 5000
938 #define HI  20000
939 #define MED 30000
940 #define LO DEFRANK
941 #define PPWEIGHT 4096
942
943 #define USEIFADDR
944
945
946 #if     defined(AFS_SUN5_ENV) && ! defined(AFS_SUN56_ENV)
947 #include <inet/common.h>
948 /* IP interface structure, one per local address */
949 typedef struct ipif_s {
950      /**/ struct ipif_s *ipif_next;
951     struct ill_s *ipif_ill;     /* Back pointer to our ill */
952     long ipif_id;               /* Logical unit number */
953     u_int ipif_mtu;             /* Starts at ipif_ill->ill_max_frag */
954     afs_int32 ipif_local_addr;  /* Local IP address for this if. */
955     afs_int32 ipif_net_mask;    /* Net mask for this interface. */
956     afs_int32 ipif_broadcast_addr;      /* Broadcast addr for this interface. */
957     afs_int32 ipif_pp_dst_addr; /* Point-to-point dest address. */
958     u_int ipif_flags;           /* Interface flags. */
959     u_int ipif_metric;          /* BSD if metric, for compatibility. */
960     u_int ipif_ire_type;        /* LOCAL or LOOPBACK */
961     mblk_t *ipif_arp_down_mp;   /* Allocated at time arp comes up to
962                                  * prevent awkward out of mem condition
963                                  * later
964                                  */
965     mblk_t *ipif_saved_ire_mp;  /* Allocated for each extra IRE_SUBNET/
966                                  * RESOLVER on this interface so that
967                                  * they can survive ifconfig down.
968                                  */
969     /*
970      * The packet counts in the ipif contain the sum of the
971      * packet counts in dead IREs that were affiliated with
972      * this ipif.
973      */
974     u_long ipif_fo_pkt_count;   /* Forwarded thru our dead IREs */
975     u_long ipif_ib_pkt_count;   /* Inbound packets for our dead IREs */
976     u_long ipif_ob_pkt_count;   /* Outbound packets to our dead IREs */
977     unsigned int
978       ipif_multicast_up:1,      /* We have joined the allhosts group */
979     : 0;
980 } ipif_t;
981
982 typedef struct ipfb_s {
983      /**/ struct ipf_s *ipfb_ipf;       /* List of ... */
984     kmutex_t ipfb_lock;         /* Protect all ipf in list */
985 } ipfb_t;
986
987 typedef struct ilm_s {
988      /**/ afs_int32 ilm_addr;
989     int ilm_refcnt;
990     u_int ilm_timer;            /* IGMP */
991     struct ipif_s *ilm_ipif;    /* Back pointer to ipif */
992     struct ilm_s *ilm_next;     /* Linked list for each ill */
993 } ilm_t;
994
995 typedef struct ill_s {
996      /**/ struct ill_s *ill_next;       /* Chained in at ill_g_head. */
997     struct ill_s **ill_ptpn;    /* Pointer to previous next. */
998     queue_t *ill_rq;            /* Read queue. */
999     queue_t *ill_wq;            /* Write queue. */
1000
1001     int ill_error;              /* Error value sent up by device. */
1002
1003     ipif_t *ill_ipif;           /* Interface chain for this ILL. */
1004     u_int ill_ipif_up_count;    /* Number of IPIFs currently up. */
1005     u_int ill_max_frag;         /* Max IDU. */
1006     char *ill_name;             /* Our name. */
1007     u_int ill_name_length;      /* Name length, incl. terminator. */
1008     u_int ill_subnet_type;      /* IRE_RESOLVER or IRE_SUBNET. */
1009     u_int ill_ppa;              /* Physical Point of Attachment num. */
1010     u_long ill_sap;
1011     int ill_sap_length;         /* Including sign (for position) */
1012     u_int ill_phys_addr_length; /* Excluding the sap. */
1013     mblk_t *ill_frag_timer_mp;  /* Reassembly timer state. */
1014     ipfb_t *ill_frag_hash_tbl;  /* Fragment hash list head. */
1015
1016     queue_t *ill_bind_pending_q;        /* Queue waiting for DL_BIND_ACK. */
1017     ipif_t *ill_ipif_pending;   /* IPIF waiting for DL_BIND_ACK. */
1018
1019     /* ill_hdr_length and ill_hdr_mp will be non zero if
1020      * the underlying device supports the M_DATA fastpath
1021      */
1022     int ill_hdr_length;
1023
1024     ilm_t *ill_ilm;             /* Multicast mebership for lower ill */
1025
1026     /* All non-nil cells between 'ill_first_mp_to_free' and
1027      * 'ill_last_mp_to_free' are freed in ill_delete.
1028      */
1029 #define ill_first_mp_to_free    ill_hdr_mp
1030     mblk_t *ill_hdr_mp;         /* Contains fastpath template */
1031     mblk_t *ill_bcast_mp;       /* DLPI header for broadcasts. */
1032     mblk_t *ill_bind_pending;   /* T_BIND_REQ awaiting completion. */
1033     mblk_t *ill_resolver_mp;    /* Resolver template. */
1034     mblk_t *ill_attach_mp;
1035     mblk_t *ill_bind_mp;
1036     mblk_t *ill_unbind_mp;
1037     mblk_t *ill_detach_mp;
1038 #define ill_last_mp_to_free     ill_detach_mp
1039
1040     u_int ill_frag_timer_running:1, ill_needs_attach:1, ill_is_ptp:1,
1041         ill_priv_stream:1, ill_unbind_pending:1, ill_pad_to_bit_31:27;
1042       MI_HRT_DCL(ill_rtime)
1043       MI_HRT_DCL(ill_rtmp)
1044 } ill_t;
1045 #endif
1046
1047 #ifdef AFS_USERSPACE_IP_ADDR
1048 #ifndef afs_min
1049 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1050 #endif
1051 /*
1052  * The IP addresses and ranks are determined by afsd (in user space) and
1053  * passed into the kernel at startup time through the AFSOP_ADVISEADDR
1054  * system call. These are stored in the data structure 
1055  * called 'afs_cb_interface'. 
1056  *
1057  * struct srvAddr *sa;         remote server
1058  * afs_int32 addr;                one of my local addr in net order
1059  * afs_uint32 subnetmask;         subnet mask of local addr in net order
1060  *
1061  */
1062 void
1063 afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
1064                      afs_uint32 subnetmask)
1065 {
1066     afs_uint32 myAddr, myNet, mySubnet, netMask;
1067     afs_uint32 serverAddr;
1068
1069     myAddr = ntohl(addr);       /* one of my IP addr in host order */
1070     serverAddr = ntohl(sa->sa_ip);      /* server's IP addr in host order */
1071     subnetmask = ntohl(subnetmask);     /* subnet mask in host order */
1072
1073     if (IN_CLASSA(myAddr))
1074         netMask = IN_CLASSA_NET;
1075     else if (IN_CLASSB(myAddr))
1076         netMask = IN_CLASSB_NET;
1077     else if (IN_CLASSC(myAddr))
1078         netMask = IN_CLASSC_NET;
1079     else
1080         netMask = 0;
1081
1082     myNet = myAddr & netMask;
1083     mySubnet = myAddr & subnetmask;
1084
1085     if ((serverAddr & netMask) == myNet) {
1086         if ((serverAddr & subnetmask) == mySubnet) {
1087             if (serverAddr == myAddr) { /* same machine */
1088                 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1089             } else {            /* same subnet */
1090                 sa->sa_iprank = afs_min(sa->sa_iprank, HI);
1091             }
1092         } else {                /* same net */
1093             sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1094         }
1095     }
1096 }
1097 #else /* AFS_USERSPACE_IP_ADDR */
1098 #if (! defined(AFS_SUN5_ENV)) && !defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
1099 void
1100 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
1101 {
1102     struct sockaddr_in *sin;
1103     int t;
1104
1105     if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1106         if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1107             sin = IA_SIN(ifa);
1108             if (SA2ULONG(sin) == ntohl(sa->sa_ip)) {    /* ie, ME!!!  */
1109                 sa->sa_iprank = TOPR;
1110             } else {
1111                 t = HI + ifa->ia_ifp->if_metric;        /* case #2 */
1112                 if (sa->sa_iprank > t)
1113                     sa->sa_iprank = t;
1114             }
1115         } else {
1116             t = MED + ifa->ia_ifp->if_metric;   /* case #3 */
1117             if (sa->sa_iprank > t)
1118                 sa->sa_iprank = t;
1119         }
1120     }
1121 #ifdef  IFF_POINTTOPOINT
1122     /* check for case #4 -- point-to-point link */
1123     if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1124         && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1125         if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1126             t = MAXDEFRANK;
1127         else
1128             t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1129         if (sa->sa_iprank > t)
1130             sa->sa_iprank = t;
1131     }
1132 #endif /* IFF_POINTTOPOINT */
1133 }
1134 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1135 #if defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
1136 #ifndef afs_min
1137 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1138 #endif
1139 void
1140 afsi_SetServerIPRank(sa, ifa)
1141      struct srvAddr *sa;
1142      struct ifaddr *ifa;
1143 {
1144     struct sockaddr_in *sin;
1145     int t;
1146
1147     afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1148     afs_uint32 serverAddr;
1149
1150     if (ifa->ifa_addr->sa_family != AF_INET)
1151         return;
1152     sin = (struct sockaddr_in *)ifa->ifa_addr;
1153     myAddr = ntohl(sin->sin_addr.s_addr);       /* one of my IP addr in host order */
1154     serverAddr = ntohl(sa->sa_ip);      /* server's IP addr in host order */
1155     sin = (struct sockaddr_in *)ifa->ifa_netmask;
1156     subnetmask = ntohl(sin->sin_addr.s_addr);   /* subnet mask in host order */
1157     sin = (struct sockaddr_in *)ifa->ifa_dstaddr;
1158     if (sin)
1159         myDstaddr = sin->sin_addr.s_addr;
1160
1161     if (IN_CLASSA(myAddr))
1162         netMask = IN_CLASSA_NET;
1163     else if (IN_CLASSB(myAddr))
1164         netMask = IN_CLASSB_NET;
1165     else if (IN_CLASSC(myAddr))
1166         netMask = IN_CLASSC_NET;
1167     else
1168         netMask = 0;
1169
1170     myNet = myAddr & netMask;
1171     mySubnet = myAddr & subnetmask;
1172
1173     if ((serverAddr & netMask) == myNet) {
1174         if ((serverAddr & subnetmask) == mySubnet) {
1175             if (serverAddr == myAddr) { /* same machine */
1176                 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1177             } else {            /* same subnet */
1178                 sa->sa_iprank = afs_min(sa->sa_iprank, HI + ifa->ifa_metric);
1179             }
1180         } else {                /* same net */
1181             sa->sa_iprank = afs_min(sa->sa_iprank, MED + ifa->ifa_metric);
1182         }
1183     }
1184 #ifdef  IFF_POINTTOPOINT
1185     /* check for case #4 -- point-to-point link */
1186     if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1187         && (myDstaddr == serverAddr)) {
1188         if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1189             t = MAXDEFRANK;
1190         else
1191             t = MED + (PPWEIGHT << ifa->->ifa_metric);
1192         if (sa->sa_iprank > t)
1193             sa->sa_iprank = t;
1194         }
1195 #endif /* IFF_POINTTOPOINT */
1196 }
1197 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1198 #endif /* else AFS_USERSPACE_IP_ADDR */
1199
1200 #ifdef AFS_SGI62_ENV
1201 static int
1202
1203   afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1204                      caddr_t arg2) {
1205     afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1206     return 0;                   /* Never match, so we enumerate everyone */
1207 }
1208 #endif                          /* AFS_SGI62_ENV */
1209 static int afs_SetServerPrefs(struct srvAddr *sa) {
1210 #if     defined(AFS_USERSPACE_IP_ADDR)
1211     int i;
1212
1213       sa->sa_iprank = LO;
1214     for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1215         afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1216                              afs_cb_interface.subnetmask[i]);
1217     }
1218 #else                           /* AFS_USERSPACE_IP_ADDR */
1219 #if     defined(AFS_SUN5_ENV)
1220 #ifdef AFS_SUN510_ENV
1221     ill_walk_context_t ctx;
1222 #else
1223     extern struct ill_s *ill_g_headp;
1224     long *addr = (long *)ill_g_headp;
1225 #endif
1226     ill_t *ill;
1227     ipif_t *ipif;
1228     int subnet, subnetmask, net, netmask;
1229
1230     if (sa)
1231           sa->sa_iprank = 0;
1232 #ifdef AFS_SUN510_ENV
1233     for (ill = ILL_START_WALK_ALL(&ctx) ; ill ; ill = ill_next(&ctx, ill)) {
1234 #else
1235     for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1236          ill = ill->ill_next) {
1237 #endif
1238 #ifdef AFS_SUN58_ENV
1239         /* Make sure this is an IPv4 ILL */
1240         if (ill->ill_isv6)
1241             continue;
1242 #endif
1243         for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1244             subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1245             subnetmask = ipif->ipif_net_mask;
1246             /*
1247              * Generate the local net using the local address and 
1248              * whate we know about Class A, B and C networks.
1249              */
1250             if (IN_CLASSA(ipif->ipif_local_addr)) {
1251                 netmask = IN_CLASSA_NET;
1252             } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1253                 netmask = IN_CLASSB_NET;
1254             } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1255                 netmask = IN_CLASSC_NET;
1256             } else {
1257                 netmask = 0;
1258             }
1259             net = ipif->ipif_local_addr & netmask;
1260 #ifdef notdef
1261             if (!s) {
1262                 if (ipif->ipif_local_addr != 0x7f000001) {      /* ignore loopback */
1263                     *cnt += 1;
1264                     if (*cnt > 16)
1265                         return;
1266                     *addrp++ = ipif->ipif_local_addr;
1267                 }
1268             } else
1269 #endif /* notdef */
1270             {
1271                 /* XXXXXX Do the individual ip ranking below XXXXX */
1272                 if ((sa->sa_ip & netmask) == net) {
1273                     if ((sa->sa_ip & subnetmask) == subnet) {
1274                         if (ipif->ipif_local_addr == sa->sa_ip) {       /* ie, ME!  */
1275                             sa->sa_iprank = TOPR;
1276                         } else {
1277                             sa->sa_iprank = HI + ipif->ipif_metric;     /* case #2 */
1278                         }
1279                     } else {
1280                         sa->sa_iprank = MED + ipif->ipif_metric;        /* case #3 */
1281                     }
1282                 } else {
1283                     sa->sa_iprank = LO + ipif->ipif_metric;     /* case #4 */
1284                 }
1285                 /* check for case #5 -- point-to-point link */
1286                 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1287                     && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1288
1289                     if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1290                         sa->sa_iprank = MAXDEFRANK;
1291                     else
1292                         sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1293                 }
1294             }
1295         }
1296     }
1297 #else
1298 #ifndef USEIFADDR
1299     struct ifnet *ifn = NULL;
1300     struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1301     struct sockaddr_in *sin;
1302
1303     if (!sa) {
1304 #ifdef notdef                   /* clean up, remove this */
1305         for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1306             for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
1307                 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1308                     && !(ifn->if_flags & IFF_LOOPBACK)) {
1309                     *cnt += 1;
1310                     if (*cnt > 16)
1311                         return;
1312                     *addrp++ =
1313                         ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
1314                         s_addr;
1315                 }
1316         }}
1317 #endif                          /* notdef */
1318         return;
1319     }
1320     sa->sa_iprank = 0;
1321 #ifdef  ADAPT_MTU
1322     ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1323 #endif
1324     if (ifn) {                  /* local, more or less */
1325 #ifdef IFF_LOOPBACK
1326         if (ifn->if_flags & IFF_LOOPBACK) {
1327             sa->sa_iprank = TOPR;
1328             goto end;
1329         }
1330 #endif /* IFF_LOOPBACK */
1331         sin = (struct sockaddr_in *)IA_SIN(ifad);
1332         if (SA2ULONG(sin) == sa->sa_ip) {
1333             sa->sa_iprank = TOPR;
1334             goto end;
1335         }
1336 #ifdef IFF_BROADCAST
1337         if (ifn->if_flags & IFF_BROADCAST) {
1338             if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1339                 sa->sa_iprank = HI;
1340                 goto end;
1341             }
1342         }
1343 #endif /* IFF_BROADCAST */
1344 #ifdef IFF_POINTOPOINT
1345         if (ifn->if_flags & IFF_POINTOPOINT) {
1346             if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1347                 if (ifn->if_metric > 4) {
1348                     sa->sa_iprank = LO;
1349                     goto end;
1350                 } else
1351                     sa->sa_iprank = ifn->if_metric;
1352             }
1353         }
1354 #endif /* IFF_POINTOPOINT */
1355         sa->sa_iprank += MED + ifn->if_metric;  /* couldn't find anything better */
1356     }
1357 #else                           /* USEIFADDR */
1358
1359     if (sa)
1360         sa->sa_iprank = LO;
1361 #ifdef AFS_SGI62_ENV
1362     (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1363                     (caddr_t) sa, NULL);
1364 #elif defined(AFS_DARWIN60_ENV)
1365     {
1366         struct ifnet *ifn;
1367         struct ifaddr *ifa;
1368           TAILQ_FOREACH(ifn, &ifnet, if_link) {
1369             TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1370                 afsi_SetServerIPRank(sa, ifa);
1371     }}}
1372 #elif defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1373     {
1374         struct in_ifaddr *ifa;
1375           TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1376             afsi_SetServerIPRank(sa, ifa);
1377     }}
1378 #elif defined(AFS_OBSD_ENV)
1379     {
1380         extern struct in_ifaddrhead in_ifaddr;
1381         struct in_ifaddr *ifa;
1382         for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1383             afsi_SetServerIPRank(sa, ifa);
1384     }
1385 #else
1386     {
1387         struct in_ifaddr *ifa;
1388         for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1389             afsi_SetServerIPRank(sa, ifa);
1390     }}
1391 #endif
1392     end:
1393 #endif                          /* USEIFADDR */
1394 #endif                          /* AFS_SUN5_ENV */
1395 #endif                          /* else AFS_USERSPACE_IP_ADDR */
1396     if (sa)
1397           sa->sa_iprank += afs_randomMod15();
1398
1399     return 0;
1400 }                               /* afs_SetServerPrefs */
1401
1402 #undef TOPR
1403 #undef HI
1404 #undef MED
1405 #undef LO
1406 #undef PPWEIGHT
1407
1408 /* afs_FlushServer()
1409  * The addresses on this server struct has changed in some way and will
1410  * clean up all other structures that may reference it.
1411  * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1412  */
1413 void afs_FlushServer(struct server *srvp) {
1414     afs_int32 i;
1415     struct server *ts, **pts;
1416
1417     /* Find any volumes residing on this server and flush their state */
1418       afs_ResetVolumes(srvp);
1419
1420     /* Flush all callbacks in the all vcaches for this specific server */
1421       afs_FlushServerCBs(srvp);
1422
1423     /* Remove all the callbacks structs */
1424     if (srvp->cbrs) {
1425         struct afs_cbr *cb, *cbnext;
1426
1427           MObtainWriteLock(&afs_xvcb, 300);
1428         for (cb = srvp->cbrs; cb; cb = cbnext) {
1429             cbnext = cb->next;
1430             afs_FreeCBR(cb);
1431         } srvp->cbrs = (struct afs_cbr *)0;
1432         ReleaseWriteLock(&afs_xvcb);
1433     }
1434
1435     /* If no more srvAddr structs hanging off of this server struct,
1436      * then clean it up.
1437      */
1438     if (!srvp->addr) {
1439         /* Remove the server structure from the cell list - if there */
1440         afs_RemoveCellEntry(srvp);
1441
1442         /* Remove from the afs_servers hash chain */
1443         for (i = 0; i < NSERVERS; i++) {
1444             for (pts = &(afs_servers[i]), ts = *pts; ts;
1445                  pts = &(ts->next), ts = *pts) {
1446                 if (ts == srvp)
1447                     break;
1448             }
1449             if (ts)
1450                 break;
1451         }
1452         if (ts) {
1453             *pts = ts->next;    /* Found it. Remove it */
1454             afs_osi_Free(ts, sizeof(struct server));    /* Free it */
1455             afs_totalServers--;
1456         }
1457     }
1458 }
1459
1460 /* afs_RemoveSrvAddr()
1461  * This removes a SrvAddr structure from its server structure.
1462  * The srvAddr struct is not free'd because it connections may still
1463  * be open to it. It is up to the calling process to make sure it
1464  * remains connected to a server struct.
1465  * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1466  *    It is not removed from the afs_srvAddrs hash chain.
1467  */
1468 void afs_RemoveSrvAddr(struct srvAddr *sap) {
1469     struct srvAddr **psa, *sa;
1470     struct server *srv;
1471
1472     if (!sap)
1473           return;
1474       srv = sap->server;
1475
1476     /* Find the srvAddr in the server's list and remove it */
1477     for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1478         if (sa == sap)
1479             break;
1480     } if (sa) {
1481         *psa = sa->next_sa;
1482         sa->next_sa = 0;
1483         sa->server = 0;
1484
1485         /* Flush the server struct since it's IP address has changed */
1486         afs_FlushServer(srv);
1487     }
1488 }
1489
1490 /* afs_GetServer()
1491  * Return an updated and properly initialized server structure
1492  * corresponding to the server ID, cell, and port specified.
1493  * If one does not exist, then one will be created.
1494  * aserver and aport must be in NET byte order.
1495  */
1496 struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
1497                              afs_int32 acell, u_short aport,
1498                              afs_int32 locktype, afsUUID * uuidp,
1499                              afs_int32 addr_uniquifier) {
1500     struct server *oldts = 0, *ts, *newts, *orphts = 0;
1501     struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1502     u_short fsport;
1503     afs_int32 iphash, k, srvcount = 0;
1504     unsigned int srvhash;
1505
1506     AFS_STATCNT(afs_GetServer);
1507
1508     ObtainSharedLock(&afs_xserver, 13);
1509
1510     /* Check if the server struct exists and is up to date */
1511     if (!uuidp) {
1512         if (nservers != 1)
1513             panic("afs_GetServer: incorect count of servers");
1514         ObtainReadLock(&afs_xsrvAddr);
1515         ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1516         ReleaseReadLock(&afs_xsrvAddr);
1517         if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1518             /* Found a server struct that is not multihomed and has the
1519              * IP address associated with it. A correct match.
1520              */
1521             ReleaseSharedLock(&afs_xserver);
1522             return (ts);
1523         }
1524     } else {
1525         if (nservers <= 0)
1526             panic("afs_GetServer: incorrect count of servers");
1527         ts = afs_FindServer(0, aport, uuidp, locktype);
1528         if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1529             /* Found a server struct that is multihomed and same
1530              * uniqufier (same IP addrs). The above if statement is the
1531              * same as in InstallUVolumeEntry().
1532              */
1533             ReleaseSharedLock(&afs_xserver);
1534             return ts;
1535         }
1536         if (ts)
1537             oldts = ts;         /* Will reuse if same uuid */
1538     }
1539
1540     UpgradeSToWLock(&afs_xserver, 36);
1541     ObtainWriteLock(&afs_xsrvAddr, 116);
1542
1543     srvcount = afs_totalServers;
1544
1545     /* Reuse/allocate a new server structure */
1546     if (oldts) {
1547         newts = oldts;
1548     } else {
1549         newts = (struct server *)afs_osi_Alloc(sizeof(struct server));
1550         if (!newts)
1551             panic("malloc of server struct");
1552         afs_totalServers++;
1553         memset((char *)newts, 0, sizeof(struct server));
1554
1555         /* Add the server struct to the afs_servers[] hash chain */
1556         srvhash =
1557             (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1558         newts->next = afs_servers[srvhash];
1559         afs_servers[srvhash] = newts;
1560     }
1561
1562     /* Initialize the server structure */
1563     if (uuidp) {                /* Multihomed */
1564         newts->sr_uuid = *uuidp;
1565         newts->sr_addr_uniquifier = addr_uniquifier;
1566         newts->flags |= SRVR_MULTIHOMED;
1567     }
1568     if (acell)
1569         newts->cell = afs_GetCell(acell, 0);
1570
1571     fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
1572
1573     /* For each IP address we are registering */
1574     for (k = 0; k < nservers; k++) {
1575         iphash = SHash(aserverp[k]);
1576
1577         /* Check if the srvAddr structure already exists. If so, remove
1578          * it from its server structure and add it to the new one.
1579          */
1580         for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1581             if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1582                 break;
1583         }
1584         if (oldsa && (oldsa->server != newts)) {
1585             afs_RemoveSrvAddr(oldsa);   /* Remove from its server struct */
1586             oldsa->next_sa = newts->addr;       /* Add to the  new server struct */
1587             newts->addr = oldsa;
1588         }
1589
1590         /* Reuse/allocate a new srvAddr structure */
1591         if (oldsa) {
1592             newsa = oldsa;
1593         } else {
1594             newsa = (struct srvAddr *)afs_osi_Alloc(sizeof(struct srvAddr));
1595             if (!newsa)
1596                 panic("malloc of srvAddr struct");
1597             afs_totalSrvAddrs++;
1598             memset((char *)newsa, 0, sizeof(struct srvAddr));
1599
1600             /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1601             newsa->next_bkt = afs_srvAddrs[iphash];
1602             afs_srvAddrs[iphash] = newsa;
1603
1604             /* Hang off of the server structure  */
1605             newsa->next_sa = newts->addr;
1606             newts->addr = newsa;
1607
1608             /* Initialize the srvAddr Structure */
1609             newsa->sa_ip = aserverp[k];
1610             newsa->sa_portal = aport;
1611         }
1612
1613         /* Update the srvAddr Structure */
1614         newsa->server = newts;
1615         if (newts->flags & SRVR_ISDOWN)
1616             newsa->sa_flags |= SRVADDR_ISDOWN;
1617         if (uuidp)
1618             newsa->sa_flags |= SRVADDR_MH;
1619         else
1620             newsa->sa_flags &= ~SRVADDR_MH;
1621
1622         /* Compute preference values and resort */
1623         if (!newsa->sa_iprank) {
1624             if (aport == fsport) {
1625                 afs_SetServerPrefs(newsa);      /* new fileserver rank */
1626             } else {
1627                 newsa->sa_iprank = 10000 + afs_randomMod127();  /* new vlserver rank */
1628             }
1629         }
1630     }
1631     afs_SortOneServer(newts);   /* Sort by rank */
1632
1633     /* If we reused the server struct, remove any of its srvAddr
1634      * structs that will no longer be associated with this server.
1635      */
1636     if (oldts) {                /* reused the server struct */
1637         for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1638             nextsa = orphsa->next_sa;
1639             for (k = 0; k < nservers; k++) {
1640                 if (orphsa->sa_ip == aserverp[k])
1641                     break;      /* belongs */
1642             }
1643             if (k < nservers)
1644                 continue;       /* belongs */
1645
1646             /* Have a srvAddr struct. Now get a server struct (if not already) */
1647             if (!orphts) {
1648                 orphts =
1649                     (struct server *)afs_osi_Alloc(sizeof(struct server));
1650                 if (!orphts)
1651                     panic("malloc of lo server struct");
1652                 memset((char *)orphts, 0, sizeof(struct server));
1653                 afs_totalServers++;
1654
1655                 /* Add the orphaned server to the afs_servers[] hash chain.
1656                  * Its iphash does not matter since we never look up the server
1657                  * in the afs_servers table by its ip address (only by uuid - 
1658                  * which this has none).
1659                  */
1660                 iphash = SHash(aserverp[k]);
1661                 orphts->next = afs_servers[iphash];
1662                 afs_servers[iphash] = orphts;
1663
1664                 if (acell)
1665                     orphts->cell = afs_GetCell(acell, 0);
1666             }
1667
1668             /* Hang the srvAddr struct off of the server structure. The server
1669              * may have multiple srvAddrs, but it won't be marked multihomed.
1670              */
1671             afs_RemoveSrvAddr(orphsa);  /* remove */
1672             orphsa->next_sa = orphts->addr;     /* hang off server struct */
1673             orphts->addr = orphsa;
1674             orphsa->server = orphts;
1675             orphsa->sa_flags |= SRVADDR_NOUSE;  /* flag indicating not in use */
1676             orphsa->sa_flags &= ~SRVADDR_MH;    /* Not multihomed */
1677         }
1678     }
1679
1680     srvcount = afs_totalServers - srvcount;     /* # servers added and removed */
1681     if (srvcount) {
1682         struct afs_stats_SrvUpDownInfo *upDownP;
1683         /* With the introduction of this new record, we need to adjust the
1684          * proper individual & global server up/down info.
1685          */
1686         upDownP = GetUpDownStats(newts);
1687         upDownP->numTtlRecords += srvcount;
1688         afs_stats_cmperf.srvRecords += srvcount;
1689         if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1690             afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1691     }
1692
1693     ReleaseWriteLock(&afs_xsrvAddr);
1694     ReleaseWriteLock(&afs_xserver);
1695     return (newts);
1696 }                               /* afs_GetServer */
1697
1698 void afs_ActivateServer(struct srvAddr *sap) {
1699     osi_timeval_t currTime;     /*Filled with current time */
1700     osi_timeval_t *currTimeP;   /*Ptr to above */
1701     struct afs_stats_SrvUpDownInfo *upDownP;    /*Ptr to up/down info record */
1702     struct server *aserver = sap->server;
1703
1704     if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1705         /*
1706          * This server record has not yet been activated.  Go for it,
1707          * recording its ``birth''.
1708          */
1709         aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1710         currTimeP = &currTime;
1711         osi_GetuTime(currTimeP);
1712         aserver->activationTime = currTime.tv_sec;
1713         upDownP = GetUpDownStats(aserver);
1714         if (aserver->flags & SRVR_ISDOWN) {
1715             upDownP->numDownRecords++;
1716         } else {
1717             upDownP->numUpRecords++;
1718             upDownP->numRecordsNeverDown++;
1719         }
1720     }
1721 }
1722
1723
1724 void shutdown_server()
1725 {
1726     int i;
1727
1728     for (i = 0; i < NSERVERS; i++) {
1729         struct server *ts, *next;
1730
1731         ts = afs_servers[i];
1732         while(ts) {
1733             next = ts->next;
1734             afs_osi_Free(ts, sizeof(struct server));
1735             ts = next;
1736         }
1737     }
1738
1739     for (i = 0; i < NSERVERS; i++) {
1740         struct srvAddr *sa, *next;
1741
1742         sa = afs_srvAddrs[i];
1743         while(sa) {
1744             next = sa->next_bkt;
1745             afs_osi_Free(sa, sizeof(struct srvAddr));
1746             sa = next;
1747         }
1748     }
1749 }