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