macos104-not-yet-20050511
[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 #ifdef AFS_DARWIN80_ENV
1143      ifaddr_t ifa;
1144 #else
1145      struct ifaddr *ifa;
1146 #endif
1147 {
1148     struct sockaddr sout;
1149     struct sockaddr_in *sin;
1150     int t;
1151
1152     afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1153     afs_uint32 serverAddr;
1154
1155     if (ifaddr_address_family(ifa) != AF_INET)
1156         return;
1157     t = ifaddr_address(ifa, &sout, sizeof(sout));
1158     if (t == 0) {
1159         sin = (struct sockaddr_in *)&sout;
1160         myAddr = ntohl(sin->sin_addr.s_addr);   /* one of my IP addr in host order */
1161     } else {
1162         myAddr = 0;
1163     }
1164     serverAddr = ntohl(sa->sa_ip);      /* server's IP addr in host order */
1165     t = ifaddr_netmask(ifa, &sout, sizeof(sout));
1166     if (t == 0) {
1167         sin = (struct sockaddr_in *)&sout;
1168         subnetmask = ntohl(sin->sin_addr.s_addr);       /* subnet mask in host order */
1169     } else {
1170         subnetmask = 0;
1171     }
1172     t = ifaddr_dstaddress(ifa, &sout, sizeof(sout));
1173     if (t == 0) {
1174         sin = (struct sockaddr_in *)&sout;
1175         myDstaddr = sin->sin_addr.s_addr;
1176     } else {
1177         myDstaddr = 0;
1178     }
1179
1180     if (IN_CLASSA(myAddr))
1181         netMask = IN_CLASSA_NET;
1182     else if (IN_CLASSB(myAddr))
1183         netMask = IN_CLASSB_NET;
1184     else if (IN_CLASSC(myAddr))
1185         netMask = IN_CLASSC_NET;
1186     else
1187         netMask = 0;
1188
1189     myNet = myAddr & netMask;
1190     mySubnet = myAddr & subnetmask;
1191
1192     if ((serverAddr & netMask) == myNet) {
1193         if ((serverAddr & subnetmask) == mySubnet) {
1194             if (serverAddr == myAddr) { /* same machine */
1195                 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1196             } else {            /* same subnet */
1197                 sa->sa_iprank = afs_min(sa->sa_iprank, HI + ifnet_metric(ifaddr_ifnet(ifa)));
1198             }
1199         } else {                /* same net */
1200             sa->sa_iprank = afs_min(sa->sa_iprank, MED + ifnet_metric(ifaddr_ifnet(ifa)));
1201         }
1202     }
1203 #ifdef  IFF_POINTTOPOINT
1204     /* check for case #4 -- point-to-point link */
1205     if ((ifnet_flags(ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
1206         && (myDstaddr == serverAddr)) {
1207         if (ifnet_metric(ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
1208             t = MAXDEFRANK;
1209         else
1210             t = MED + (PPWEIGHT << ifnet_metric(ifaddr_ifnet(ifa)));
1211         if (sa->sa_iprank > t)
1212             sa->sa_iprank = t;
1213         }
1214 #endif /* IFF_POINTTOPOINT */
1215 }
1216 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1217 #endif /* else AFS_USERSPACE_IP_ADDR */
1218
1219 #ifdef AFS_SGI62_ENV
1220 static int
1221
1222   afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1223                      caddr_t arg2) {
1224     afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1225     return 0;                   /* Never match, so we enumerate everyone */
1226 }
1227 #endif                          /* AFS_SGI62_ENV */
1228 static int afs_SetServerPrefs(struct srvAddr *sa) {
1229 #if     defined(AFS_USERSPACE_IP_ADDR)
1230     int i;
1231
1232       sa->sa_iprank = LO;
1233     for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1234         afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1235                              afs_cb_interface.subnetmask[i]);
1236     }
1237 #else                           /* AFS_USERSPACE_IP_ADDR */
1238 #if     defined(AFS_SUN5_ENV)
1239 #ifdef AFS_SUN510_ENV
1240     ill_walk_context_t ctx;
1241 #else
1242     extern struct ill_s *ill_g_headp;
1243     long *addr = (long *)ill_g_headp;
1244 #endif
1245     ill_t *ill;
1246     ipif_t *ipif;
1247     int subnet, subnetmask, net, netmask;
1248
1249     if (sa)
1250           sa->sa_iprank = 0;
1251 #ifdef AFS_SUN510_ENV
1252     for (ill = ILL_START_WALK_ALL(&ctx) ; ill ; ill = ill_next(&ctx, ill)) {
1253 #else
1254     for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1255          ill = ill->ill_next) {
1256 #endif
1257 #ifdef AFS_SUN58_ENV
1258         /* Make sure this is an IPv4 ILL */
1259         if (ill->ill_isv6)
1260             continue;
1261 #endif
1262         for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1263             subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1264             subnetmask = ipif->ipif_net_mask;
1265             /*
1266              * Generate the local net using the local address and 
1267              * whate we know about Class A, B and C networks.
1268              */
1269             if (IN_CLASSA(ipif->ipif_local_addr)) {
1270                 netmask = IN_CLASSA_NET;
1271             } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1272                 netmask = IN_CLASSB_NET;
1273             } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1274                 netmask = IN_CLASSC_NET;
1275             } else {
1276                 netmask = 0;
1277             }
1278             net = ipif->ipif_local_addr & netmask;
1279 #ifdef notdef
1280             if (!s) {
1281                 if (ipif->ipif_local_addr != 0x7f000001) {      /* ignore loopback */
1282                     *cnt += 1;
1283                     if (*cnt > 16)
1284                         return;
1285                     *addrp++ = ipif->ipif_local_addr;
1286                 }
1287             } else
1288 #endif /* notdef */
1289             {
1290                 /* XXXXXX Do the individual ip ranking below XXXXX */
1291                 if ((sa->sa_ip & netmask) == net) {
1292                     if ((sa->sa_ip & subnetmask) == subnet) {
1293                         if (ipif->ipif_local_addr == sa->sa_ip) {       /* ie, ME!  */
1294                             sa->sa_iprank = TOPR;
1295                         } else {
1296                             sa->sa_iprank = HI + ipif->ipif_metric;     /* case #2 */
1297                         }
1298                     } else {
1299                         sa->sa_iprank = MED + ipif->ipif_metric;        /* case #3 */
1300                     }
1301                 } else {
1302                     sa->sa_iprank = LO + ipif->ipif_metric;     /* case #4 */
1303                 }
1304                 /* check for case #5 -- point-to-point link */
1305                 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1306                     && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1307
1308                     if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1309                         sa->sa_iprank = MAXDEFRANK;
1310                     else
1311                         sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1312                 }
1313             }
1314         }
1315     }
1316 #else
1317 #ifndef USEIFADDR
1318     struct ifnet *ifn = NULL;
1319     struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1320     struct sockaddr_in *sin;
1321
1322     if (!sa) {
1323 #ifdef notdef                   /* clean up, remove this */
1324         for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1325             for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
1326                 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1327                     && !(ifn->if_flags & IFF_LOOPBACK)) {
1328                     *cnt += 1;
1329                     if (*cnt > 16)
1330                         return;
1331                     *addrp++ =
1332                         ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
1333                         s_addr;
1334                 }
1335         }}
1336 #endif                          /* notdef */
1337         return;
1338     }
1339     sa->sa_iprank = 0;
1340 #ifdef  ADAPT_MTU
1341     ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1342 #endif
1343     if (ifn) {                  /* local, more or less */
1344 #ifdef IFF_LOOPBACK
1345         if (ifn->if_flags & IFF_LOOPBACK) {
1346             sa->sa_iprank = TOPR;
1347             goto end;
1348         }
1349 #endif /* IFF_LOOPBACK */
1350         sin = (struct sockaddr_in *)IA_SIN(ifad);
1351         if (SA2ULONG(sin) == sa->sa_ip) {
1352             sa->sa_iprank = TOPR;
1353             goto end;
1354         }
1355 #ifdef IFF_BROADCAST
1356         if (ifn->if_flags & IFF_BROADCAST) {
1357             if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1358                 sa->sa_iprank = HI;
1359                 goto end;
1360             }
1361         }
1362 #endif /* IFF_BROADCAST */
1363 #ifdef IFF_POINTOPOINT
1364         if (ifn->if_flags & IFF_POINTOPOINT) {
1365             if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1366                 if (ifn->if_metric > 4) {
1367                     sa->sa_iprank = LO;
1368                     goto end;
1369                 } else
1370                     sa->sa_iprank = ifn->if_metric;
1371             }
1372         }
1373 #endif /* IFF_POINTOPOINT */
1374         sa->sa_iprank += MED + ifn->if_metric;  /* couldn't find anything better */
1375     }
1376 #else                           /* USEIFADDR */
1377
1378     if (sa)
1379         sa->sa_iprank = LO;
1380 #ifdef AFS_SGI62_ENV
1381     (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1382                     (caddr_t) sa, NULL);
1383 #elif defined(AFS_DARWIN80_ENV)
1384     {
1385         errno_t t;
1386         int cnt=0;
1387         ifaddr_t *addresses, address;
1388         t = ifnet_get_address_list_family(NULL, &addresses, AF_INET);
1389         if (t == 0) {
1390             while(addresses[cnt] != NULL) {
1391                 afsi_SetServerIPRank(sa, address);
1392                 cnt++;
1393             }
1394             ifnet_free_address_list(addresses);
1395         }
1396     }
1397 #elif defined(AFS_DARWIN60_ENV)
1398     {
1399         struct ifnet *ifn;
1400         struct ifaddr *ifa;
1401           TAILQ_FOREACH(ifn, &ifnet, if_link) {
1402             TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1403                 afsi_SetServerIPRank(sa, ifa);
1404     }}}
1405 #elif defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1406     {
1407         struct in_ifaddr *ifa;
1408           TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1409             afsi_SetServerIPRank(sa, ifa);
1410     }}
1411 #elif defined(AFS_OBSD_ENV)
1412     {
1413         extern struct in_ifaddrhead in_ifaddr;
1414         struct in_ifaddr *ifa;
1415         for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1416             afsi_SetServerIPRank(sa, ifa);
1417     }
1418 #else
1419     {
1420         struct in_ifaddr *ifa;
1421         for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1422             afsi_SetServerIPRank(sa, ifa);
1423     }}
1424 #endif
1425     end:
1426 #endif                          /* USEIFADDR */
1427 #endif                          /* AFS_SUN5_ENV */
1428 #endif                          /* else AFS_USERSPACE_IP_ADDR */
1429     if (sa)
1430           sa->sa_iprank += afs_randomMod15();
1431
1432     return 0;
1433 }                               /* afs_SetServerPrefs */
1434
1435 #undef TOPR
1436 #undef HI
1437 #undef MED
1438 #undef LO
1439 #undef PPWEIGHT
1440
1441 /* afs_FlushServer()
1442  * The addresses on this server struct has changed in some way and will
1443  * clean up all other structures that may reference it.
1444  * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1445  */
1446 void afs_FlushServer(struct server *srvp) {
1447     afs_int32 i;
1448     struct server *ts, **pts;
1449
1450     /* Find any volumes residing on this server and flush their state */
1451       afs_ResetVolumes(srvp);
1452
1453     /* Flush all callbacks in the all vcaches for this specific server */
1454       afs_FlushServerCBs(srvp);
1455
1456     /* Remove all the callbacks structs */
1457     if (srvp->cbrs) {
1458         struct afs_cbr *cb, *cbnext;
1459
1460           MObtainWriteLock(&afs_xvcb, 300);
1461         for (cb = srvp->cbrs; cb; cb = cbnext) {
1462             cbnext = cb->next;
1463             afs_FreeCBR(cb);
1464         } srvp->cbrs = (struct afs_cbr *)0;
1465         ReleaseWriteLock(&afs_xvcb);
1466     }
1467
1468     /* If no more srvAddr structs hanging off of this server struct,
1469      * then clean it up.
1470      */
1471     if (!srvp->addr) {
1472         /* Remove the server structure from the cell list - if there */
1473         afs_RemoveCellEntry(srvp);
1474
1475         /* Remove from the afs_servers hash chain */
1476         for (i = 0; i < NSERVERS; i++) {
1477             for (pts = &(afs_servers[i]), ts = *pts; ts;
1478                  pts = &(ts->next), ts = *pts) {
1479                 if (ts == srvp)
1480                     break;
1481             }
1482             if (ts)
1483                 break;
1484         }
1485         if (ts) {
1486             *pts = ts->next;    /* Found it. Remove it */
1487             afs_osi_Free(ts, sizeof(struct server));    /* Free it */
1488             afs_totalServers--;
1489         }
1490     }
1491 }
1492
1493 /* afs_RemoveSrvAddr()
1494  * This removes a SrvAddr structure from its server structure.
1495  * The srvAddr struct is not free'd because it connections may still
1496  * be open to it. It is up to the calling process to make sure it
1497  * remains connected to a server struct.
1498  * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1499  *    It is not removed from the afs_srvAddrs hash chain.
1500  */
1501 void afs_RemoveSrvAddr(struct srvAddr *sap) {
1502     struct srvAddr **psa, *sa;
1503     struct server *srv;
1504
1505     if (!sap)
1506           return;
1507       srv = sap->server;
1508
1509     /* Find the srvAddr in the server's list and remove it */
1510     for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1511         if (sa == sap)
1512             break;
1513     } if (sa) {
1514         *psa = sa->next_sa;
1515         sa->next_sa = 0;
1516         sa->server = 0;
1517
1518         /* Flush the server struct since it's IP address has changed */
1519         afs_FlushServer(srv);
1520     }
1521 }
1522
1523 /* afs_GetServer()
1524  * Return an updated and properly initialized server structure
1525  * corresponding to the server ID, cell, and port specified.
1526  * If one does not exist, then one will be created.
1527  * aserver and aport must be in NET byte order.
1528  */
1529 struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
1530                              afs_int32 acell, u_short aport,
1531                              afs_int32 locktype, afsUUID * uuidp,
1532                              afs_int32 addr_uniquifier) {
1533     struct server *oldts = 0, *ts, *newts, *orphts = 0;
1534     struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1535     u_short fsport;
1536     afs_int32 iphash, k, srvcount = 0;
1537     unsigned int srvhash;
1538
1539     AFS_STATCNT(afs_GetServer);
1540
1541     ObtainSharedLock(&afs_xserver, 13);
1542
1543     /* Check if the server struct exists and is up to date */
1544     if (!uuidp) {
1545         if (nservers != 1)
1546             panic("afs_GetServer: incorect count of servers");
1547         ObtainReadLock(&afs_xsrvAddr);
1548         ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1549         ReleaseReadLock(&afs_xsrvAddr);
1550         if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1551             /* Found a server struct that is not multihomed and has the
1552              * IP address associated with it. A correct match.
1553              */
1554             ReleaseSharedLock(&afs_xserver);
1555             return (ts);
1556         }
1557     } else {
1558         if (nservers <= 0)
1559             panic("afs_GetServer: incorrect count of servers");
1560         ts = afs_FindServer(0, aport, uuidp, locktype);
1561         if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1562             /* Found a server struct that is multihomed and same
1563              * uniqufier (same IP addrs). The above if statement is the
1564              * same as in InstallUVolumeEntry().
1565              */
1566             ReleaseSharedLock(&afs_xserver);
1567             return ts;
1568         }
1569         if (ts)
1570             oldts = ts;         /* Will reuse if same uuid */
1571     }
1572
1573     UpgradeSToWLock(&afs_xserver, 36);
1574     ObtainWriteLock(&afs_xsrvAddr, 116);
1575
1576     srvcount = afs_totalServers;
1577
1578     /* Reuse/allocate a new server structure */
1579     if (oldts) {
1580         newts = oldts;
1581     } else {
1582         newts = (struct server *)afs_osi_Alloc(sizeof(struct server));
1583         if (!newts)
1584             panic("malloc of server struct");
1585         afs_totalServers++;
1586         memset((char *)newts, 0, sizeof(struct server));
1587
1588         /* Add the server struct to the afs_servers[] hash chain */
1589         srvhash =
1590             (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1591         newts->next = afs_servers[srvhash];
1592         afs_servers[srvhash] = newts;
1593     }
1594
1595     /* Initialize the server structure */
1596     if (uuidp) {                /* Multihomed */
1597         newts->sr_uuid = *uuidp;
1598         newts->sr_addr_uniquifier = addr_uniquifier;
1599         newts->flags |= SRVR_MULTIHOMED;
1600     }
1601     if (acell)
1602         newts->cell = afs_GetCell(acell, 0);
1603
1604     fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
1605
1606     /* For each IP address we are registering */
1607     for (k = 0; k < nservers; k++) {
1608         iphash = SHash(aserverp[k]);
1609
1610         /* Check if the srvAddr structure already exists. If so, remove
1611          * it from its server structure and add it to the new one.
1612          */
1613         for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1614             if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1615                 break;
1616         }
1617         if (oldsa && (oldsa->server != newts)) {
1618             afs_RemoveSrvAddr(oldsa);   /* Remove from its server struct */
1619             oldsa->next_sa = newts->addr;       /* Add to the  new server struct */
1620             newts->addr = oldsa;
1621         }
1622
1623         /* Reuse/allocate a new srvAddr structure */
1624         if (oldsa) {
1625             newsa = oldsa;
1626         } else {
1627             newsa = (struct srvAddr *)afs_osi_Alloc(sizeof(struct srvAddr));
1628             if (!newsa)
1629                 panic("malloc of srvAddr struct");
1630             afs_totalSrvAddrs++;
1631             memset((char *)newsa, 0, sizeof(struct srvAddr));
1632
1633             /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1634             newsa->next_bkt = afs_srvAddrs[iphash];
1635             afs_srvAddrs[iphash] = newsa;
1636
1637             /* Hang off of the server structure  */
1638             newsa->next_sa = newts->addr;
1639             newts->addr = newsa;
1640
1641             /* Initialize the srvAddr Structure */
1642             newsa->sa_ip = aserverp[k];
1643             newsa->sa_portal = aport;
1644         }
1645
1646         /* Update the srvAddr Structure */
1647         newsa->server = newts;
1648         if (newts->flags & SRVR_ISDOWN)
1649             newsa->sa_flags |= SRVADDR_ISDOWN;
1650         if (uuidp)
1651             newsa->sa_flags |= SRVADDR_MH;
1652         else
1653             newsa->sa_flags &= ~SRVADDR_MH;
1654
1655         /* Compute preference values and resort */
1656         if (!newsa->sa_iprank) {
1657             if (aport == fsport) {
1658                 afs_SetServerPrefs(newsa);      /* new fileserver rank */
1659             } else {
1660                 newsa->sa_iprank = 10000 + afs_randomMod127();  /* new vlserver rank */
1661             }
1662         }
1663     }
1664     afs_SortOneServer(newts);   /* Sort by rank */
1665
1666     /* If we reused the server struct, remove any of its srvAddr
1667      * structs that will no longer be associated with this server.
1668      */
1669     if (oldts) {                /* reused the server struct */
1670         for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1671             nextsa = orphsa->next_sa;
1672             for (k = 0; k < nservers; k++) {
1673                 if (orphsa->sa_ip == aserverp[k])
1674                     break;      /* belongs */
1675             }
1676             if (k < nservers)
1677                 continue;       /* belongs */
1678
1679             /* Have a srvAddr struct. Now get a server struct (if not already) */
1680             if (!orphts) {
1681                 orphts =
1682                     (struct server *)afs_osi_Alloc(sizeof(struct server));
1683                 if (!orphts)
1684                     panic("malloc of lo server struct");
1685                 memset((char *)orphts, 0, sizeof(struct server));
1686                 afs_totalServers++;
1687
1688                 /* Add the orphaned server to the afs_servers[] hash chain.
1689                  * Its iphash does not matter since we never look up the server
1690                  * in the afs_servers table by its ip address (only by uuid - 
1691                  * which this has none).
1692                  */
1693                 iphash = SHash(aserverp[k]);
1694                 orphts->next = afs_servers[iphash];
1695                 afs_servers[iphash] = orphts;
1696
1697                 if (acell)
1698                     orphts->cell = afs_GetCell(acell, 0);
1699             }
1700
1701             /* Hang the srvAddr struct off of the server structure. The server
1702              * may have multiple srvAddrs, but it won't be marked multihomed.
1703              */
1704             afs_RemoveSrvAddr(orphsa);  /* remove */
1705             orphsa->next_sa = orphts->addr;     /* hang off server struct */
1706             orphts->addr = orphsa;
1707             orphsa->server = orphts;
1708             orphsa->sa_flags |= SRVADDR_NOUSE;  /* flag indicating not in use */
1709             orphsa->sa_flags &= ~SRVADDR_MH;    /* Not multihomed */
1710         }
1711     }
1712
1713     srvcount = afs_totalServers - srvcount;     /* # servers added and removed */
1714     if (srvcount) {
1715         struct afs_stats_SrvUpDownInfo *upDownP;
1716         /* With the introduction of this new record, we need to adjust the
1717          * proper individual & global server up/down info.
1718          */
1719         upDownP = GetUpDownStats(newts);
1720         upDownP->numTtlRecords += srvcount;
1721         afs_stats_cmperf.srvRecords += srvcount;
1722         if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1723             afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1724     }
1725
1726     ReleaseWriteLock(&afs_xsrvAddr);
1727     ReleaseWriteLock(&afs_xserver);
1728     return (newts);
1729 }                               /* afs_GetServer */
1730
1731 void afs_ActivateServer(struct srvAddr *sap) {
1732     osi_timeval_t currTime;     /*Filled with current time */
1733     osi_timeval_t *currTimeP;   /*Ptr to above */
1734     struct afs_stats_SrvUpDownInfo *upDownP;    /*Ptr to up/down info record */
1735     struct server *aserver = sap->server;
1736
1737     if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1738         /*
1739          * This server record has not yet been activated.  Go for it,
1740          * recording its ``birth''.
1741          */
1742         aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1743         currTimeP = &currTime;
1744         osi_GetuTime(currTimeP);
1745         aserver->activationTime = currTime.tv_sec;
1746         upDownP = GetUpDownStats(aserver);
1747         if (aserver->flags & SRVR_ISDOWN) {
1748             upDownP->numDownRecords++;
1749         } else {
1750             upDownP->numUpRecords++;
1751             upDownP->numRecordsNeverDown++;
1752         }
1753     }
1754 }
1755
1756
1757 void shutdown_server()
1758 {
1759     int i;
1760
1761     for (i = 0; i < NSERVERS; i++) {
1762         struct server *ts, *next;
1763
1764         ts = afs_servers[i];
1765         while(ts) {
1766             next = ts->next;
1767             afs_osi_Free(ts, sizeof(struct server));
1768             ts = next;
1769         }
1770     }
1771
1772     for (i = 0; i < NSERVERS; i++) {
1773         struct srvAddr *sa, *next;
1774
1775         sa = afs_srvAddrs[i];
1776         while(sa) {
1777             next = sa->next_bkt;
1778             afs_osi_Free(sa, sizeof(struct srvAddr));
1779             sa = next;
1780         }
1781     }
1782 }