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