refactor afs_CheckServers
[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 static void
527 CkSrv_MarkUpDown(struct afs_conn **conns, int nconns, afs_int32 *results)
528 {
529     struct srvAddr *sa;
530     struct afs_conn *tc;
531     afs_int32 i;
532
533     for(i = 0; i < nconns; i++){
534         tc = conns[i];
535         sa = tc->parent->srvr;
536
537         if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) &&
538             (tc->parent->srvr == sa)) {
539             /* server back up */
540             print_internet_address("afs: file server ", sa, " is back up", 2);
541
542             ObtainWriteLock(&afs_xserver, 244);
543             ObtainWriteLock(&afs_xsrvAddr, 245);
544             afs_MarkServerUpOrDown(sa, 0);
545             ReleaseWriteLock(&afs_xsrvAddr);
546             ReleaseWriteLock(&afs_xserver);
547
548             if (afs_waitForeverCount) {
549                 afs_osi_Wakeup(&afs_waitForever);
550             }
551         } else {
552             if (results[i] < 0) {
553                 /* server crashed */
554                 afs_ServerDown(sa);
555                 ForceNewConnections(sa);  /* multi homed clients */
556             }
557         }
558     }
559 }
560
561 void
562 CkSrv_SetTime(struct rx_connection **rxconns, int nconns, int nservers,
563               struct afs_conn **conns, struct srvAddr **addrs)
564 {
565     struct afs_conn *tc;
566     afs_int32 start, end = 0, delta;
567     osi_timeval_t tv;
568     struct srvAddr *sa;
569     afs_int32 *conntimer, *results, *deltas;
570     afs_int32 i = 0;
571     char tbuffer[CVBS];
572
573     conntimer = afs_osi_Alloc(nservers * sizeof (afs_int32));
574     osi_Assert(conntimer != NULL);
575     results = afs_osi_Alloc(nservers * sizeof (afs_int32));
576     osi_Assert(results != NULL);
577     deltas = afs_osi_Alloc(nservers * sizeof (afs_int32));
578     osi_Assert(deltas != NULL);
579
580     /* make sure we're starting from zero */
581     memset(&deltas, 0, sizeof(deltas));
582
583     start = osi_Time();         /* time the gettimeofday call */
584     AFS_GUNLOCK();
585     if ( afs_setTimeHost == NULL ) {
586         multi_Rx(rxconns,nconns)
587         {
588             tv.tv_sec = tv.tv_usec = 0;
589             multi_RXAFS_GetTime(
590                 (afs_uint32 *)&tv.tv_sec, (afs_uint32 *)&tv.tv_usec);
591             tc = conns[multi_i];
592             sa = tc->parent->srvr;
593             if (conntimer[multi_i] == 1)
594                 rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
595             end = osi_Time();
596             results[multi_i]=multi_error;
597             if ((start == end) && !multi_error)
598                 deltas[multi_i] = end - tv.tv_sec;
599         } multi_End;
600     } else {                    /* find and query setTimeHost only */
601         for ( i = 0 ; i < nservers ; i++ ) {
602             if ( conns[i] == NULL || conns[i]->parent->srvr == NULL )
603                 continue;
604             if ( conns[i]->parent->srvr->server == afs_setTimeHost ) {
605                 tv.tv_sec = tv.tv_usec = 0;
606                 results[i] = RXAFS_GetTime(rxconns[i],
607                                            (afs_uint32 *)&tv.tv_sec,
608                                            (afs_uint32 *)&tv.tv_usec);
609                 end = osi_Time();
610                 if ((start == end) && !results[i])
611                     deltas[i] = end - tv.tv_sec;
612                 break;
613             }
614         }
615     }
616     AFS_GLOCK();
617
618     if ( afs_setTimeHost == NULL )
619         CkSrv_MarkUpDown(conns, nconns, results);
620     else /* We lack info for other than this host */
621         CkSrv_MarkUpDown(&conns[i], 1, &results[i]);
622
623     /*
624      * If we're supposed to set the time, and the call worked
625      * quickly (same second response) and this is the host we
626      * use for the time and the time is really different, then
627      * really set the time
628      */
629     if (afs_setTime != 0) {
630         for (i=0; i<nconns; i++) {
631             delta = deltas[i];
632             tc = conns[i];
633             sa = tc->parent->srvr;
634
635             if ((tc->parent->srvr->server == afs_setTimeHost ||
636                  /* Sync only to a server in the local cell */
637                  (afs_setTimeHost == (struct server *)0 &&
638                   afs_IsPrimaryCell(sa->server->cell)))) {
639                 /* set the time */
640                 char msgbuf[90];  /* strlen("afs: setting clock...") + slop */
641                 delta = end - tv.tv_sec;   /* how many secs fast we are */
642
643                 afs_setTimeHost = tc->parent->srvr->server;
644                 /* see if clock has changed enough to make it worthwhile */
645                 if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
646                     end = osi_Time();
647                     if (delta > AFS_MAXCHANGEBACK) {
648                         /* setting clock too far back, just do it a little */
649                         tv.tv_sec = end - AFS_MAXCHANGEBACK;
650                     } else {
651                         tv.tv_sec = end - delta;
652                     }
653                     afs_osi_SetTime(&tv);
654                     if (delta > 0) {
655                         strcpy(msgbuf, "afs: setting clock back ");
656                         if (delta > AFS_MAXCHANGEBACK) {
657                             afs_strcat(msgbuf,
658                                        afs_cv2string(&tbuffer[CVBS],
659                                                      AFS_MAXCHANGEBACK));
660                             afs_strcat(msgbuf, " seconds (of ");
661                             afs_strcat(msgbuf,
662                                        afs_cv2string(&tbuffer[CVBS],
663                                                      delta -
664                                                      AFS_MAXCHANGEBACK));
665                             afs_strcat(msgbuf, ", via ");
666                             print_internet_address(msgbuf, sa,
667                                                    "); clock is still fast.",
668                                                    0);
669                         } else {
670                             afs_strcat(msgbuf,
671                                        afs_cv2string(&tbuffer[CVBS], delta));
672                             afs_strcat(msgbuf, " seconds (via ");
673                             print_internet_address(msgbuf, sa, ").", 0);
674                         }
675                     } else {
676                         strcpy(msgbuf, "afs: setting clock ahead ");
677                         afs_strcat(msgbuf,
678                                    afs_cv2string(&tbuffer[CVBS], -delta));
679                         afs_strcat(msgbuf, " seconds (via ");
680                         print_internet_address(msgbuf, sa, ").", 0);
681                     }
682                     /* We're only going to set it once; why bother looping? */
683                     break;
684                 }
685             }
686         }
687     }
688     afs_osi_Free(conntimer, nservers * sizeof(afs_int32));
689     afs_osi_Free(deltas, nservers * sizeof(afs_int32));
690     afs_osi_Free(results, nservers * sizeof(afs_int32));
691 }
692
693 void
694 CkSrv_GetCaps(struct rx_connection **rxconns, int nconns, int nservers,
695               struct afs_conn **conns, struct srvAddr **addrs)
696 {
697     Capabilities *caps;
698     afs_int32 *results;
699     afs_int32 i;
700     struct server *ts;
701
702     caps = afs_osi_Alloc(nservers * sizeof (Capabilities));
703     osi_Assert(caps != NULL);
704     memset(caps, 0, nservers * sizeof(Capabilities));
705
706     results = afs_osi_Alloc(nservers * sizeof (afs_int32));
707     osi_Assert(results != NULL);
708
709     AFS_GUNLOCK();
710     multi_Rx(rxconns,nconns)
711       {
712         multi_RXAFS_GetCapabilities(&caps[multi_i]);
713         results[multi_i] = multi_error;
714       } multi_End;
715     AFS_GLOCK();
716
717     for ( i = 0 ; i < nconns ; i++ ) {
718         ts = addrs[i]->server;
719         if ( !ts )
720             continue;
721         ts->capabilities = 0;
722         ts->flags |= SCAPS_KNOWN;
723         if ( results[i] == RXGEN_OPCODE ) {
724             /* Mark server as up - it responded */
725             results[i] = 0;
726             continue;
727         }
728         if ( results[i] >= 0 )
729             /* we currently handle 32-bits of capabilities */
730             if (caps[i].Capabilities_len > 0) {
731                 ts->capabilities = caps[i].Capabilities_val[0];
732                 xdr_free((xdrproc_t)xdr_Capabilities, &caps[i]);
733                 caps[i].Capabilities_val = NULL;
734                 caps[i].Capabilities_len = 0;
735             }
736     }
737     CkSrv_MarkUpDown(conns, nconns, results);
738
739     afs_osi_Free(caps, nservers * sizeof(Capabilities));
740     afs_osi_Free(results, nservers * sizeof(afs_int32));
741 }
742
743 /* check down servers (if adown), or running servers (if !adown) */
744 void
745 afs_CheckServers(int adown, struct cell *acellp)
746 {
747     afs_LoopServers(adown?AFS_LS_DOWN:AFS_LS_UP, acellp, 1, CkSrv_GetCaps,
748                     afs_setTime?CkSrv_SetTime:NULL);
749 }
750
751 /* adown: 0 - check only down. 1 - check only up. 2 - check all */
752 void
753 afs_LoopServers(int adown, struct cell *acellp, int vlalso,
754                 void (*func1) (struct rx_connection **rxconns, int nconns,
755                                int nservers, struct afs_conn **conns,
756                                struct srvAddr **addrs),
757                 void (*func2) (struct rx_connection **rxconns, int nconns,
758                                int nservers, struct afs_conn **conns,
759                                struct srvAddr **addrs))
760 {
761     struct vrequest treq;
762     struct server *ts;
763     struct srvAddr *sa;
764     struct afs_conn *tc = NULL;
765     afs_int32 i, j;
766     afs_int32 code;
767     struct unixuser *tu;
768     int srvAddrCount;
769     struct srvAddr **addrs;
770     struct afs_conn **conns;
771     int nconns;
772     struct rx_connection **rxconns;
773     afs_int32 *conntimer, *results;
774
775     AFS_STATCNT(afs_CheckServers);
776
777     /*
778      * No sense in doing the server checks if we are running in disconnected
779      * mode
780      */
781     if (AFS_IS_DISCONNECTED)
782         return;
783
784     conns = (struct afs_conn **)0;
785     rxconns = (struct rx_connection **) 0;
786     conntimer = 0;
787     nconns = 0;
788
789     if ((code = afs_InitReq(&treq, afs_osi_credp)))
790         return;
791     ObtainReadLock(&afs_xserver);       /* Necessary? */
792     ObtainReadLock(&afs_xsrvAddr);
793
794     srvAddrCount = 0;
795     for (i = 0; i < NSERVERS; i++) {
796         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
797             srvAddrCount++;
798         }
799     }
800
801     addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
802     osi_Assert(addrs != NULL);
803     j = 0;
804     for (i = 0; i < NSERVERS; i++) {
805         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
806             if (j >= srvAddrCount)
807                 break;
808             addrs[j++] = sa;
809         }
810     }
811
812     ReleaseReadLock(&afs_xsrvAddr);
813     ReleaseReadLock(&afs_xserver);
814
815     conns = afs_osi_Alloc(j * sizeof(struct afs_conn *));
816     osi_Assert(conns != NULL);
817     rxconns = afs_osi_Alloc(j * sizeof(struct rx_connection *));
818     osi_Assert(rxconns != NULL);
819     conntimer = afs_osi_Alloc(j * sizeof (afs_int32));
820     osi_Assert(conntimer != NULL);
821     results = afs_osi_Alloc(j * sizeof (afs_int32));
822     osi_Assert(results != NULL);
823
824     for (i = 0; i < j; i++) {
825         sa = addrs[i];
826         ts = sa->server;
827         if (!ts)
828             continue;
829
830         /* See if a cell to check was specified.  If it is spec'd and not
831          * this server's cell, just skip the server.
832          */
833         if (acellp && acellp != ts->cell)
834             continue;
835
836         if (((adown==AFS_LS_DOWN) && (sa->sa_flags & SRVADDR_ISDOWN))
837             || ((adown==AFS_LS_UP) && !(sa->sa_flags & SRVADDR_ISDOWN)))
838             continue;
839
840         /* check vlserver with special code */
841         if (sa->sa_portal == AFS_VLPORT) {
842             if (vlalso)
843                 CheckVLServer(sa, &treq);
844             continue;
845         }
846
847         if (!ts->cell)          /* not really an active server, anyway, it must */
848             continue;           /* have just been added by setsprefs */
849
850         /* get a connection, even if host is down; bumps conn ref count */
851         tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
852         tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
853                           1 /*force */ , 1 /*create */ , SHARED_LOCK);
854         afs_PutUser(tu, SHARED_LOCK);
855         if (!tc)
856             continue;
857
858         if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)
859             || (tc->parent->srvr->server == afs_setTimeHost)) {
860             conns[nconns]=tc;
861             rxconns[nconns]=tc->id;
862             if (sa->sa_flags & SRVADDR_ISDOWN) {
863                 rx_SetConnDeadTime(tc->id, 3);
864                 conntimer[nconns]=1;
865             } else {
866                 conntimer[nconns]=0;
867             }
868             nconns++;
869         }
870     } /* Outer loop over addrs */
871
872     (*func1)(rxconns, nconns, j, conns, addrs);
873
874     if (func2) {
875         (*func2)(rxconns, nconns, j, conns, addrs);
876     }
877
878     for (i = 0; i < nconns; i++) {
879         if (conntimer[i] == 1)
880             rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
881         afs_PutConn(conns[i], SHARED_LOCK);     /* done with it now */
882     }
883
884     afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
885     afs_osi_Free(conns, j * sizeof(struct afs_conn *));
886     afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
887     afs_osi_Free(conntimer, j * sizeof(afs_int32));
888     afs_osi_Free(results, j * sizeof(afs_int32));
889
890 } /*afs_CheckServers*/
891
892
893 /* find a server structure given the host address */
894 struct server *
895 afs_FindServer(afs_int32 aserver, afs_uint16 aport, afsUUID * uuidp,
896                afs_int32 locktype)
897 {
898     struct server *ts;
899     struct srvAddr *sa;
900     int i;
901
902     AFS_STATCNT(afs_FindServer);
903     if (uuidp) {
904         i = afs_uuid_hash(uuidp) % NSERVERS;
905         for (ts = afs_servers[i]; ts; ts = ts->next) {
906             if ((ts->flags & SRVR_MULTIHOMED)
907                 &&
908                 (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp))
909                  == 0) && (!ts->addr || (ts->addr->sa_portal == aport)))
910                 return ts;
911         }
912     } else {
913         i = SHash(aserver);
914         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
915             if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
916                 return sa->server;
917             }
918         }
919     }
920     return NULL;
921
922 }                               /*afs_FindServer */
923
924
925 /* some code for creating new server structs and setting preferences follows
926  * in the next few lines...
927  */
928
929 #define MAXDEFRANK 60000
930 #define DEFRANK    40000
931
932 /* Random number generator and constants from KnuthV2 2d ed, p170 */
933
934 /* Rules:
935    X = (aX + c) % m
936    m is a power of two
937    a % 8 is 5
938    a is 0.73m  should be 0.01m .. 0.99m
939    c is more or less immaterial.  1 or a is suggested.
940
941 NB:  LOW ORDER BITS are not very random.  To get small random numbers,
942      treat result as <1, with implied binary point, and multiply by
943      desired modulus.
944 NB:  Has to be unsigned, since shifts on signed quantities may preserve
945      the sign bit.
946 */
947 /* added rxi_getaddr() to try to get as much initial randomness as
948    possible, since at least one customer reboots ALL their clients
949    simultaneously -- so osi_Time is bound to be the same on some of the
950    clients.  This is probably OK, but I don't want to see too much of it.
951 */
952
953 #define ranstage(x)     (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
954
955 unsigned int
956 afs_random(void)
957 {
958     static afs_int32 state = 0;
959     int i;
960
961     AFS_STATCNT(afs_random);
962     if (!state) {
963         osi_timeval_t t;
964         osi_GetTime(&t);
965         /*
966          * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
967          * bits are in a tv_usec
968          */
969         state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
970         state += (t.tv_sec & 0xff);
971         for (i = 0; i < 30; i++) {
972             ranstage(state);
973         }
974     }
975
976     ranstage(state);
977     return (state);
978
979 }                               /*afs_random */
980
981 /* returns int 0..14 using the high bits of a pseudo-random number instead of
982    the low bits, as the low bits are "less random" than the high ones...
983    slight roundoff error exists, an excercise for the reader.
984    need to multiply by something with lots of ones in it, so multiply by
985    8 or 16 is right out.
986  */
987 int
988 afs_randomMod15(void)
989 {
990     afs_uint32 temp;
991
992     temp = afs_random() >> 4;
993     temp = (temp * 15) >> 28;
994
995     return temp;
996 }
997
998 int
999 afs_randomMod127(void)
1000 {
1001     afs_uint32 temp;
1002
1003     temp = afs_random() >> 7;
1004     temp = (temp * 127) >> 25;
1005
1006     return temp;
1007 }
1008
1009 /* afs_SortOneServer()
1010  * Sort all of the srvAddrs, of a server struct, by rank from low to high.
1011  */
1012 void
1013 afs_SortOneServer(struct server *asp)
1014 {
1015     struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
1016     int lowrank, rank;
1017
1018     for (rootsa = &(asp->addr); *rootsa; rootsa = &(lowsa->next_sa)) {
1019         lowprev = NULL;
1020         lowsa = *rootsa;        /* lowest sa is the first one */
1021         lowrank = lowsa->sa_iprank;
1022
1023         for (tsa = *rootsa; tsa->next_sa; tsa = tsa->next_sa) {
1024             rank = tsa->next_sa->sa_iprank;
1025             if (rank < lowrank) {
1026                 lowprev = tsa;
1027                 lowsa = tsa->next_sa;
1028                 lowrank = lowsa->sa_iprank;
1029             }
1030         }
1031         if (lowprev) {          /* found one lower, so rearrange them */
1032             lowprev->next_sa = lowsa->next_sa;
1033             lowsa->next_sa = *rootsa;
1034             *rootsa = lowsa;
1035         }
1036     }
1037 }
1038
1039 /* afs_SortServer()
1040  * Sort the pointer to servers by the server's rank (its lowest rank).
1041  * It is assumed that the server already has its IP addrs sorted (the
1042  * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
1043  */
1044 void
1045 afs_SortServers(struct server *aservers[], int count)
1046 {
1047     struct server *ts;
1048     int i, j, low;
1049
1050     AFS_STATCNT(afs_SortServers);
1051
1052     for (i = 0; i < count; i++) {
1053         if (!aservers[i])
1054             break;
1055         for (low = i, j = i + 1; j <= count; j++) {
1056             if ((!aservers[j]) || (!aservers[j]->addr))
1057                 break;
1058             if ((!aservers[low]) || (!aservers[low]->addr))
1059                 break;
1060             if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
1061                 low = j;
1062             }
1063         }
1064         if (low != i) {
1065             ts = aservers[i];
1066             aservers[i] = aservers[low];
1067             aservers[low] = ts;
1068         }
1069     }
1070 }                               /*afs_SortServers */
1071
1072 /* afs_SetServerPrefs is rather system-dependent.  It pokes around in kernel
1073    data structures to determine what the local IP addresses and subnet masks
1074    are in order to choose which server(s) are on the local subnet.
1075
1076    As I see it, there are several cases:
1077    1. The server address is one of this host's local addresses.  In this case
1078           this server is to be preferred over all others.
1079    2. The server is on the same subnet as one of the this host's local
1080       addresses.  (ie, an odd-sized subnet, not class A,B,orC)
1081    3. The server is on the same net as this host (class A,B or C)
1082    4. The server is on a different logical subnet or net than this host, but
1083    this host is a 'metric 0 gateway' to it.  Ie, two address-spaces share
1084    one physical medium.
1085    5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
1086    server.
1087    6. This host and the server are disjoint.
1088
1089    That is a rough order of preference.  If a point-to-point link has a high
1090    metric, I'm assuming that it is a very slow link, and putting it at the
1091    bottom of the list (at least until RX works better over slow links).  If
1092    its metric is 1, I'm assuming that it's relatively fast (T1) and putting
1093    it ahead of #6.
1094    It's not easy to check for case #4, so I'm ignoring it for the time being.
1095
1096    BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
1097    That could be used to prefer certain servers fairly easily.  Maybe some
1098    other time...
1099
1100    NOTE: this code is very system-dependent, and very dependent on the TCP/IP
1101    protocols (well, addresses that are stored in uint32s, at any rate).
1102  */
1103
1104 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
1105 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
1106
1107 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
1108 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
1109 #define TOPR 5000
1110 #define HI  20000
1111 #define MED 30000
1112 #define LO DEFRANK
1113 #define PPWEIGHT 4096
1114
1115 #define USEIFADDR
1116
1117
1118 #if     defined(AFS_SUN5_ENV) && ! defined(AFS_SUN56_ENV)
1119 #include <inet/common.h>
1120 /* IP interface structure, one per local address */
1121 typedef struct ipif_s {
1122      /**/ struct ipif_s *ipif_next;
1123     struct ill_s *ipif_ill;     /* Back pointer to our ill */
1124     long ipif_id;               /* Logical unit number */
1125     u_int ipif_mtu;             /* Starts at ipif_ill->ill_max_frag */
1126     afs_int32 ipif_local_addr;  /* Local IP address for this if. */
1127     afs_int32 ipif_net_mask;    /* Net mask for this interface. */
1128     afs_int32 ipif_broadcast_addr;      /* Broadcast addr for this interface. */
1129     afs_int32 ipif_pp_dst_addr; /* Point-to-point dest address. */
1130     u_int ipif_flags;           /* Interface flags. */
1131     u_int ipif_metric;          /* BSD if metric, for compatibility. */
1132     u_int ipif_ire_type;        /* LOCAL or LOOPBACK */
1133     mblk_t *ipif_arp_down_mp;   /* Allocated at time arp comes up to
1134                                  * prevent awkward out of mem condition
1135                                  * later
1136                                  */
1137     mblk_t *ipif_saved_ire_mp;  /* Allocated for each extra IRE_SUBNET/
1138                                  * RESOLVER on this interface so that
1139                                  * they can survive ifconfig down.
1140                                  */
1141     /*
1142      * The packet counts in the ipif contain the sum of the
1143      * packet counts in dead IREs that were affiliated with
1144      * this ipif.
1145      */
1146     u_long ipif_fo_pkt_count;   /* Forwarded thru our dead IREs */
1147     u_long ipif_ib_pkt_count;   /* Inbound packets for our dead IREs */
1148     u_long ipif_ob_pkt_count;   /* Outbound packets to our dead IREs */
1149     unsigned int
1150       ipif_multicast_up:1,      /* We have joined the allhosts group */
1151     : 0;
1152 } ipif_t;
1153
1154 typedef struct ipfb_s {
1155      /**/ struct ipf_s *ipfb_ipf;       /* List of ... */
1156     kmutex_t ipfb_lock;         /* Protect all ipf in list */
1157 } ipfb_t;
1158
1159 typedef struct ilm_s {
1160      /**/ afs_int32 ilm_addr;
1161     int ilm_refcnt;
1162     u_int ilm_timer;            /* IGMP */
1163     struct ipif_s *ilm_ipif;    /* Back pointer to ipif */
1164     struct ilm_s *ilm_next;     /* Linked list for each ill */
1165 } ilm_t;
1166
1167 typedef struct ill_s {
1168      /**/ struct ill_s *ill_next;       /* Chained in at ill_g_head. */
1169     struct ill_s **ill_ptpn;    /* Pointer to previous next. */
1170     queue_t *ill_rq;            /* Read queue. */
1171     queue_t *ill_wq;            /* Write queue. */
1172
1173     int ill_error;              /* Error value sent up by device. */
1174
1175     ipif_t *ill_ipif;           /* Interface chain for this ILL. */
1176     u_int ill_ipif_up_count;    /* Number of IPIFs currently up. */
1177     u_int ill_max_frag;         /* Max IDU. */
1178     char *ill_name;             /* Our name. */
1179     u_int ill_name_length;      /* Name length, incl. terminator. */
1180     u_int ill_subnet_type;      /* IRE_RESOLVER or IRE_SUBNET. */
1181     u_int ill_ppa;              /* Physical Point of Attachment num. */
1182     u_long ill_sap;
1183     int ill_sap_length;         /* Including sign (for position) */
1184     u_int ill_phys_addr_length; /* Excluding the sap. */
1185     mblk_t *ill_frag_timer_mp;  /* Reassembly timer state. */
1186     ipfb_t *ill_frag_hash_tbl;  /* Fragment hash list head. */
1187
1188     queue_t *ill_bind_pending_q;        /* Queue waiting for DL_BIND_ACK. */
1189     ipif_t *ill_ipif_pending;   /* IPIF waiting for DL_BIND_ACK. */
1190
1191     /* ill_hdr_length and ill_hdr_mp will be non zero if
1192      * the underlying device supports the M_DATA fastpath
1193      */
1194     int ill_hdr_length;
1195
1196     ilm_t *ill_ilm;             /* Multicast mebership for lower ill */
1197
1198     /* All non-nil cells between 'ill_first_mp_to_free' and
1199      * 'ill_last_mp_to_free' are freed in ill_delete.
1200      */
1201 #define ill_first_mp_to_free    ill_hdr_mp
1202     mblk_t *ill_hdr_mp;         /* Contains fastpath template */
1203     mblk_t *ill_bcast_mp;       /* DLPI header for broadcasts. */
1204     mblk_t *ill_bind_pending;   /* T_BIND_REQ awaiting completion. */
1205     mblk_t *ill_resolver_mp;    /* Resolver template. */
1206     mblk_t *ill_attach_mp;
1207     mblk_t *ill_bind_mp;
1208     mblk_t *ill_unbind_mp;
1209     mblk_t *ill_detach_mp;
1210 #define ill_last_mp_to_free     ill_detach_mp
1211
1212     u_int ill_frag_timer_running:1, ill_needs_attach:1, ill_is_ptp:1,
1213         ill_priv_stream:1, ill_unbind_pending:1, ill_pad_to_bit_31:27;
1214       MI_HRT_DCL(ill_rtime)
1215       MI_HRT_DCL(ill_rtmp)
1216 } ill_t;
1217 #endif
1218
1219 #ifdef AFS_USERSPACE_IP_ADDR
1220 #ifndef afs_min
1221 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1222 #endif
1223 /*
1224  * The IP addresses and ranks are determined by afsd (in user space) and
1225  * passed into the kernel at startup time through the AFSOP_ADVISEADDR
1226  * system call. These are stored in the data structure
1227  * called 'afs_cb_interface'.
1228  *
1229  * struct srvAddr *sa;         remote server
1230  * afs_int32 addr;                one of my local addr in net order
1231  * afs_uint32 subnetmask;         subnet mask of local addr in net order
1232  *
1233  */
1234 void
1235 afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
1236                      afs_uint32 subnetmask)
1237 {
1238     afs_uint32 myAddr, myNet, mySubnet, netMask;
1239     afs_uint32 serverAddr;
1240
1241     myAddr = ntohl(addr);       /* one of my IP addr in host order */
1242     serverAddr = ntohl(sa->sa_ip);      /* server's IP addr in host order */
1243     subnetmask = ntohl(subnetmask);     /* subnet mask in host order */
1244
1245     if (IN_CLASSA(myAddr))
1246         netMask = IN_CLASSA_NET;
1247     else if (IN_CLASSB(myAddr))
1248         netMask = IN_CLASSB_NET;
1249     else if (IN_CLASSC(myAddr))
1250         netMask = IN_CLASSC_NET;
1251     else
1252         netMask = 0;
1253
1254     myNet = myAddr & netMask;
1255     mySubnet = myAddr & subnetmask;
1256
1257     if ((serverAddr & netMask) == myNet) {
1258         if ((serverAddr & subnetmask) == mySubnet) {
1259             if (serverAddr == myAddr) { /* same machine */
1260                 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1261             } else {            /* same subnet */
1262                 sa->sa_iprank = afs_min(sa->sa_iprank, HI);
1263             }
1264         } else {                /* same net */
1265             sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1266         }
1267     }
1268     return;
1269 }
1270 #else /* AFS_USERSPACE_IP_ADDR */
1271 #if (! defined(AFS_SUN5_ENV)) && (! defined(AFS_DARWIN_ENV)) && (! defined(AFS_OBSD47_ENV)) && defined(USEIFADDR)
1272 void
1273 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
1274 {
1275     struct sockaddr_in *sin;
1276     int t;
1277
1278     if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1279         if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1280             sin = IA_SIN(ifa);
1281             if (SA2ULONG(sin) == ntohl(sa->sa_ip)) {    /* ie, ME!!!  */
1282                 sa->sa_iprank = TOPR;
1283             } else {
1284                 t = HI + ifa->ia_ifp->if_metric;        /* case #2 */
1285                 if (sa->sa_iprank > t)
1286                     sa->sa_iprank = t;
1287             }
1288         } else {
1289             t = MED + ifa->ia_ifp->if_metric;   /* case #3 */
1290             if (sa->sa_iprank > t)
1291                 sa->sa_iprank = t;
1292         }
1293     }
1294 #ifdef  IFF_POINTTOPOINT
1295     /* check for case #4 -- point-to-point link */
1296     if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1297         && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1298         if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1299             t = MAXDEFRANK;
1300         else
1301             t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1302         if (sa->sa_iprank > t)
1303             sa->sa_iprank = t;
1304     }
1305 #endif /* IFF_POINTTOPOINT */
1306 }
1307 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1308 #if (defined(AFS_DARWIN_ENV) || defined(AFS_OBSD47_ENV)) && defined(USEIFADDR)
1309 #ifndef afs_min
1310 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1311 #endif
1312 void
1313 afsi_SetServerIPRank(struct srvAddr *sa, rx_ifaddr_t ifa)
1314 {
1315     struct sockaddr sout;
1316     struct sockaddr_in *sin;
1317     int t;
1318
1319     afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1320     afs_uint32 serverAddr;
1321
1322     if (rx_ifaddr_address_family(ifa) != AF_INET)
1323         return;
1324     t = rx_ifaddr_address(ifa, &sout, sizeof(sout));
1325     if (t != 0) {
1326         sin = (struct sockaddr_in *)&sout;
1327         myAddr = ntohl(sin->sin_addr.s_addr);   /* one of my IP addr in host order */
1328     } else {
1329         myAddr = 0;
1330     }
1331     serverAddr = ntohl(sa->sa_ip);      /* server's IP addr in host order */
1332     t = rx_ifaddr_netmask(ifa, &sout, sizeof(sout));
1333     if (t != 0) {
1334         sin = (struct sockaddr_in *)&sout;
1335         subnetmask = ntohl(sin->sin_addr.s_addr);       /* subnet mask in host order */
1336     } else {
1337         subnetmask = 0;
1338     }
1339     t = rx_ifaddr_dstaddress(ifa, &sout, sizeof(sout));
1340     if (t != 0) {
1341         sin = (struct sockaddr_in *)&sout;
1342         myDstaddr = ntohl(sin->sin_addr.s_addr);
1343     } else {
1344         myDstaddr = 0;
1345     }
1346
1347     if (IN_CLASSA(myAddr))
1348         netMask = IN_CLASSA_NET;
1349     else if (IN_CLASSB(myAddr))
1350         netMask = IN_CLASSB_NET;
1351     else if (IN_CLASSC(myAddr))
1352         netMask = IN_CLASSC_NET;
1353     else
1354         netMask = 0;
1355
1356     myNet = myAddr & netMask;
1357     mySubnet = myAddr & subnetmask;
1358
1359     if ((serverAddr & netMask) == myNet) {
1360         if ((serverAddr & subnetmask) == mySubnet) {
1361             if (serverAddr == myAddr) { /* same machine */
1362                 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1363             } else {            /* same subnet */
1364                 sa->sa_iprank = afs_min(sa->sa_iprank, HI + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1365             }
1366         } else {                /* same net */
1367             sa->sa_iprank = afs_min(sa->sa_iprank, MED + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1368         }
1369     }
1370 #ifdef  IFF_POINTTOPOINT
1371     /* check for case #4 -- point-to-point link */
1372     if ((rx_ifnet_flags(rx_ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
1373         && (myDstaddr == serverAddr)) {
1374         if (rx_ifnet_metric(rx_ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
1375             t = MAXDEFRANK;
1376         else
1377             t = MED + (PPWEIGHT << rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1378         if (sa->sa_iprank > t)
1379             sa->sa_iprank = t;
1380         }
1381 #endif /* IFF_POINTTOPOINT */
1382 }
1383 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1384 #endif /* else AFS_USERSPACE_IP_ADDR */
1385
1386 #ifdef AFS_SGI62_ENV
1387 static int
1388 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1389                    caddr_t arg2)
1390 {
1391     afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1392     return 0;                   /* Never match, so we enumerate everyone */
1393 }
1394 #endif                          /* AFS_SGI62_ENV */
1395 static int
1396 afs_SetServerPrefs(struct srvAddr *sa)
1397 {
1398 #if     defined(AFS_USERSPACE_IP_ADDR)
1399     int i;
1400
1401       sa->sa_iprank = LO;
1402     for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1403         afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1404                              afs_cb_interface.subnetmask[i]);
1405     }
1406 #else                           /* AFS_USERSPACE_IP_ADDR */
1407 #if     defined(AFS_SUN5_ENV)
1408 #ifdef AFS_SUN510_ENV
1409     int i = 0;
1410 #else
1411     extern struct ill_s *ill_g_headp;
1412     long *addr = (long *)ill_g_headp;
1413     ill_t *ill;
1414     ipif_t *ipif;
1415 #endif
1416     int subnet, subnetmask, net, netmask;
1417
1418     if (sa)
1419           sa->sa_iprank = 0;
1420 #ifdef AFS_SUN510_ENV
1421     rw_enter(&afsifinfo_lock, RW_READER);
1422
1423     for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
1424
1425         if (IN_CLASSA(afsifinfo[i].ipaddr)) {
1426             netmask = IN_CLASSA_NET;
1427         } else if (IN_CLASSB(afsifinfo[i].ipaddr)) {
1428             netmask = IN_CLASSB_NET;
1429         } else if (IN_CLASSC(afsifinfo[i].ipaddr)) {
1430             netmask = IN_CLASSC_NET;
1431         } else {
1432             netmask = 0;
1433         }
1434         net = afsifinfo[i].ipaddr & netmask;
1435
1436 #ifdef notdef
1437         if (!s) {
1438             if (!rx_IsLoopbackAddr(afsifinfo[i].ipaddr)) {      /* ignore loopback */
1439                 *cnt += 1;
1440                 if (*cnt > 16)
1441                     return;
1442                 *addrp++ = afsifinfo[i].ipaddr;
1443             }
1444         } else
1445 #endif /* notdef */
1446         {
1447             /* XXXXXX Do the individual ip ranking below XXXXX */
1448             if ((sa->sa_ip & netmask) == net) {
1449                 if ((sa->sa_ip & subnetmask) == subnet) {
1450                     if (afsifinfo[i].ipaddr == sa->sa_ip) {   /* ie, ME!  */
1451                         sa->sa_iprank = TOPR;
1452                     } else {
1453                         sa->sa_iprank = HI + afsifinfo[i].metric; /* case #2 */
1454                     }
1455                 } else {
1456                     sa->sa_iprank = MED + afsifinfo[i].metric;    /* case #3 */
1457                 }
1458             } else {
1459                     sa->sa_iprank = LO + afsifinfo[i].metric;     /* case #4 */
1460             }
1461             /* check for case #5 -- point-to-point link */
1462             if ((afsifinfo[i].flags & IFF_POINTOPOINT)
1463                 && (afsifinfo[i].dstaddr == sa->sa_ip)) {
1464
1465                     if (afsifinfo[i].metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1466                         sa->sa_iprank = MAXDEFRANK;
1467                     else
1468                         sa->sa_iprank = MED + (PPWEIGHT << afsifinfo[i].metric);
1469             }
1470         }
1471     }
1472
1473     rw_exit(&afsifinfo_lock);
1474 #else
1475     for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1476          ill = ill->ill_next) {
1477 #ifdef AFS_SUN58_ENV
1478         /* Make sure this is an IPv4 ILL */
1479         if (ill->ill_isv6)
1480             continue;
1481 #endif
1482         for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1483             subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1484             subnetmask = ipif->ipif_net_mask;
1485             /*
1486              * Generate the local net using the local address and
1487              * whate we know about Class A, B and C networks.
1488              */
1489             if (IN_CLASSA(ipif->ipif_local_addr)) {
1490                 netmask = IN_CLASSA_NET;
1491             } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1492                 netmask = IN_CLASSB_NET;
1493             } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1494                 netmask = IN_CLASSC_NET;
1495             } else {
1496                 netmask = 0;
1497             }
1498             net = ipif->ipif_local_addr & netmask;
1499 #ifdef notdef
1500             if (!s) {
1501                 if (!rx_IsLoopbackAddr(ipif->ipif_local_addr)) {        /* ignore loopback */
1502                     *cnt += 1;
1503                     if (*cnt > 16)
1504                         return;
1505                     *addrp++ = ipif->ipif_local_addr;
1506                 }
1507             } else
1508 #endif /* notdef */
1509             {
1510                 /* XXXXXX Do the individual ip ranking below XXXXX */
1511                 if ((sa->sa_ip & netmask) == net) {
1512                     if ((sa->sa_ip & subnetmask) == subnet) {
1513                         if (ipif->ipif_local_addr == sa->sa_ip) {       /* ie, ME!  */
1514                             sa->sa_iprank = TOPR;
1515                         } else {
1516                             sa->sa_iprank = HI + ipif->ipif_metric;     /* case #2 */
1517                         }
1518                     } else {
1519                         sa->sa_iprank = MED + ipif->ipif_metric;        /* case #3 */
1520                     }
1521                 } else {
1522                     sa->sa_iprank = LO + ipif->ipif_metric;     /* case #4 */
1523                 }
1524                 /* check for case #5 -- point-to-point link */
1525                 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1526                     && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1527
1528                     if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1529                         sa->sa_iprank = MAXDEFRANK;
1530                     else
1531                         sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1532                 }
1533             }
1534         }
1535     }
1536 #endif /* AFS_SUN510_ENV */
1537 #else
1538 #ifndef USEIFADDR
1539     rx_ifnet_t ifn = NULL;
1540     struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1541     struct sockaddr_in *sin;
1542
1543     if (!sa) {
1544 #ifdef notdef                   /* clean up, remove this */
1545         for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1546             for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
1547                 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1548                     && !(ifn->if_flags & IFF_LOOPBACK)) {
1549                     *cnt += 1;
1550                     if (*cnt > 16)
1551                         return;
1552                     *addrp++ =
1553                         ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
1554                         s_addr;
1555                 }
1556         }}
1557 #endif                          /* notdef */
1558         return;
1559     }
1560     sa->sa_iprank = 0;
1561 #ifdef  ADAPT_MTU
1562     ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1563 #endif
1564     if (ifn) {                  /* local, more or less */
1565 #ifdef IFF_LOOPBACK
1566         if (ifn->if_flags & IFF_LOOPBACK) {
1567             sa->sa_iprank = TOPR;
1568             goto end;
1569         }
1570 #endif /* IFF_LOOPBACK */
1571         sin = (struct sockaddr_in *)IA_SIN(ifad);
1572         if (SA2ULONG(sin) == sa->sa_ip) {
1573             sa->sa_iprank = TOPR;
1574             goto end;
1575         }
1576 #ifdef IFF_BROADCAST
1577         if (ifn->if_flags & IFF_BROADCAST) {
1578             if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1579                 sa->sa_iprank = HI;
1580                 goto end;
1581             }
1582         }
1583 #endif /* IFF_BROADCAST */
1584 #ifdef IFF_POINTOPOINT
1585         if (ifn->if_flags & IFF_POINTOPOINT) {
1586             if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1587                 if (ifn->if_metric > 4) {
1588                     sa->sa_iprank = LO;
1589                     goto end;
1590                 } else
1591                     sa->sa_iprank = ifn->if_metric;
1592             }
1593         }
1594 #endif /* IFF_POINTOPOINT */
1595         sa->sa_iprank += MED + ifn->if_metric;  /* couldn't find anything better */
1596     }
1597 #else                           /* USEIFADDR */
1598
1599     if (sa)
1600         sa->sa_iprank = LO;
1601 #ifdef AFS_SGI62_ENV
1602     (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1603                     (caddr_t) sa, NULL);
1604 #elif defined(AFS_DARWIN80_ENV)
1605     {
1606         errno_t t;
1607         unsigned int count;
1608         int cnt=0, m, j;
1609         rx_ifaddr_t *ifads;
1610         rx_ifnet_t *ifns;
1611
1612         if (!ifnet_list_get(AF_INET, &ifns, &count)) {
1613             for (m = 0; m < count; m++) {
1614                 if (!ifnet_get_address_list(ifns[m], &ifads)) {
1615                     for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
1616                         afsi_SetServerIPRank(sa, ifads[j]);
1617                         cnt++;
1618                     }
1619                     ifnet_free_address_list(ifads);
1620                 }
1621             }
1622             ifnet_list_free(ifns);
1623         }
1624     }
1625 #elif defined(AFS_DARWIN_ENV)
1626     {
1627         rx_ifnet_t ifn;
1628         rx_ifaddr_t ifa;
1629           TAILQ_FOREACH(ifn, &ifnet, if_link) {
1630             TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1631                 afsi_SetServerIPRank(sa, ifa);
1632     }}}
1633 #elif defined(AFS_FBSD_ENV)
1634     {
1635         struct in_ifaddr *ifa;
1636           TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1637             afsi_SetServerIPRank(sa, ifa);
1638     }}
1639 #elif defined(AFS_OBSD_ENV)
1640     {
1641         extern struct in_ifaddrhead in_ifaddr;
1642         struct in_ifaddr *ifa;
1643         for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1644             afsi_SetServerIPRank(sa, ifa);
1645     }
1646 #elif defined(AFS_NBSD40_ENV)
1647      {
1648        extern struct in_ifaddrhead in_ifaddrhead;
1649        struct in_ifaddr *ifa;
1650        for (ifa = in_ifaddrhead.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1651            afsi_SetServerIPRank(sa, ifa);
1652      }
1653 #else
1654     {
1655         struct in_ifaddr *ifa;
1656         for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1657             afsi_SetServerIPRank(sa, ifa);
1658     }}
1659 #endif
1660 #endif                          /* USEIFADDR */
1661 #ifndef USEIFADDR
1662     end:
1663 #endif
1664 #endif                          /* AFS_SUN5_ENV */
1665 #endif                          /* else AFS_USERSPACE_IP_ADDR */
1666     if (sa)
1667           sa->sa_iprank += afs_randomMod15();
1668
1669     return 0;
1670 }                               /* afs_SetServerPrefs */
1671
1672 #undef TOPR
1673 #undef HI
1674 #undef MED
1675 #undef LO
1676 #undef PPWEIGHT
1677
1678 /* afs_FlushServer()
1679  * The addresses on this server struct has changed in some way and will
1680  * clean up all other structures that may reference it.
1681  * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1682  */
1683 void
1684 afs_FlushServer(struct server *srvp)
1685 {
1686     afs_int32 i;
1687     struct server *ts, **pts;
1688
1689     /* Find any volumes residing on this server and flush their state */
1690       afs_ResetVolumes(srvp);
1691
1692     /* Flush all callbacks in the all vcaches for this specific server */
1693       afs_FlushServerCBs(srvp);
1694
1695     /* Remove all the callbacks structs */
1696     if (srvp->cbrs) {
1697         struct afs_cbr *cb, *cbnext;
1698
1699           ObtainWriteLock(&afs_xvcb, 300);
1700         for (cb = srvp->cbrs; cb; cb = cbnext) {
1701             cbnext = cb->next;
1702             afs_FreeCBR(cb);
1703         } srvp->cbrs = (struct afs_cbr *)0;
1704         ReleaseWriteLock(&afs_xvcb);
1705     }
1706
1707     /* If no more srvAddr structs hanging off of this server struct,
1708      * then clean it up.
1709      */
1710     if (!srvp->addr) {
1711         /* Remove the server structure from the cell list - if there */
1712         afs_RemoveCellEntry(srvp);
1713
1714         /* Remove from the afs_servers hash chain */
1715         for (i = 0; i < NSERVERS; i++) {
1716             for (pts = &(afs_servers[i]), ts = *pts; ts;
1717                  pts = &(ts->next), ts = *pts) {
1718                 if (ts == srvp)
1719                     break;
1720             }
1721             if (ts)
1722                 break;
1723         }
1724         if (ts) {
1725             *pts = ts->next;    /* Found it. Remove it */
1726             afs_osi_Free(ts, sizeof(struct server));    /* Free it */
1727             afs_totalServers--;
1728         }
1729     }
1730 }
1731
1732 /* afs_RemoveSrvAddr()
1733  * This removes a SrvAddr structure from its server structure.
1734  * The srvAddr struct is not free'd because it connections may still
1735  * be open to it. It is up to the calling process to make sure it
1736  * remains connected to a server struct.
1737  * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1738  *    It is not removed from the afs_srvAddrs hash chain.
1739  */
1740 void
1741 afs_RemoveSrvAddr(struct srvAddr *sap)
1742 {
1743     struct srvAddr **psa, *sa;
1744     struct server *srv;
1745
1746     if (!sap)
1747           return;
1748       srv = sap->server;
1749
1750     /* Find the srvAddr in the server's list and remove it */
1751     for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1752         if (sa == sap)
1753             break;
1754     } if (sa) {
1755         *psa = sa->next_sa;
1756         sa->next_sa = 0;
1757         sa->server = 0;
1758
1759         /* Flush the server struct since it's IP address has changed */
1760         afs_FlushServer(srv);
1761     }
1762 }
1763
1764 /* afs_GetCapabilities
1765  * Try and retrieve capabilities of a given file server. Carps on actual
1766  * failure. Servers are not expected to support this RPC. */
1767 void
1768 afs_GetCapabilities(struct server *ts)
1769 {
1770     Capabilities caps = {0, NULL};
1771     struct vrequest treq;
1772     struct afs_conn *tc;
1773     struct unixuser *tu;
1774     afs_int32 code;
1775
1776     if ( !ts || !ts->cell )
1777         return;
1778     if ( !afs_osi_credp )
1779         return;
1780
1781     if ((code = afs_InitReq(&treq, afs_osi_credp)))
1782         return;
1783     tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
1784     if ( !tu )
1785         return;
1786     tc = afs_ConnBySA(ts->addr, ts->cell->fsport, ts->cell->cellNum, tu, 0, 1,
1787                                                                 SHARED_LOCK);
1788     if ( !tc )
1789         return;
1790     /* InitCallBackStateN, triggered by our RPC, may need this */
1791     ReleaseWriteLock(&afs_xserver);
1792     code = RXAFS_GetCapabilities(tc->id, &caps);
1793     ObtainWriteLock(&afs_xserver, 723);
1794     /* we forced a conn above; important we mark it down if needed */
1795     if ((code < 0) && (code != RXGEN_OPCODE)) {
1796         afs_ServerDown(tc->parent->srvr);
1797         ForceNewConnections(tc->parent->srvr); /* multi homed clients */
1798     }
1799     afs_PutConn(tc, SHARED_LOCK);
1800     if ( code && code != RXGEN_OPCODE ) {
1801         afs_warn("RXAFS_GetCapabilities failed with code %d\n", code);
1802         /* better not be anything to free. we failed! */
1803         return;
1804     }
1805
1806     ts->flags |= SCAPS_KNOWN;
1807
1808     if ( caps.Capabilities_len > 0 ) {
1809         ts->capabilities = caps.Capabilities_val[0];
1810         xdr_free((xdrproc_t)xdr_Capabilities, &caps);
1811         caps.Capabilities_len = 0;
1812         caps.Capabilities_val = NULL;
1813     }
1814
1815 }
1816
1817 /* afs_GetServer()
1818  * Return an updated and properly initialized server structure
1819  * corresponding to the server ID, cell, and port specified.
1820  * If one does not exist, then one will be created.
1821  * aserver and aport must be in NET byte order.
1822  */
1823 struct server *
1824 afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers, afs_int32 acell,
1825               u_short aport, afs_int32 locktype, afsUUID * uuidp,
1826               afs_int32 addr_uniquifier)
1827 {
1828     struct server *oldts = 0, *ts, *newts, *orphts = 0;
1829     struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1830     u_short fsport;
1831     afs_int32 iphash, k, srvcount = 0;
1832     unsigned int srvhash;
1833
1834     AFS_STATCNT(afs_GetServer);
1835
1836     ObtainSharedLock(&afs_xserver, 13);
1837
1838     /* Check if the server struct exists and is up to date */
1839     if (!uuidp) {
1840         if (nservers != 1)
1841             panic("afs_GetServer: incorect count of servers");
1842         ObtainReadLock(&afs_xsrvAddr);
1843         ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1844         ReleaseReadLock(&afs_xsrvAddr);
1845         if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1846             /* Found a server struct that is not multihomed and has the
1847              * IP address associated with it. A correct match.
1848              */
1849             ReleaseSharedLock(&afs_xserver);
1850             return (ts);
1851         }
1852     } else {
1853         if (nservers <= 0)
1854             panic("afs_GetServer: incorrect count of servers");
1855         ts = afs_FindServer(0, aport, uuidp, locktype);
1856         if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1857             /* Found a server struct that is multihomed and same
1858              * uniqufier (same IP addrs). The above if statement is the
1859              * same as in InstallUVolumeEntry().
1860              */
1861             ReleaseSharedLock(&afs_xserver);
1862             return ts;
1863         }
1864         if (ts)
1865             oldts = ts;         /* Will reuse if same uuid */
1866     }
1867
1868     UpgradeSToWLock(&afs_xserver, 36);
1869     ObtainWriteLock(&afs_xsrvAddr, 116);
1870
1871     srvcount = afs_totalServers;
1872
1873     /* Reuse/allocate a new server structure */
1874     if (oldts) {
1875         newts = oldts;
1876     } else {
1877         newts = afs_osi_Alloc(sizeof(struct server));
1878         if (!newts)
1879             panic("malloc of server struct");
1880         afs_totalServers++;
1881         memset(newts, 0, sizeof(struct server));
1882
1883         /* Add the server struct to the afs_servers[] hash chain */
1884         srvhash =
1885             (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1886         newts->next = afs_servers[srvhash];
1887         afs_servers[srvhash] = newts;
1888     }
1889
1890     /* Initialize the server structure */
1891     if (uuidp) {                /* Multihomed */
1892         newts->sr_uuid = *uuidp;
1893         newts->sr_addr_uniquifier = addr_uniquifier;
1894         newts->flags |= SRVR_MULTIHOMED;
1895     }
1896     if (acell)
1897         newts->cell = afs_GetCell(acell, 0);
1898
1899     fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
1900
1901     /* For each IP address we are registering */
1902     for (k = 0; k < nservers; k++) {
1903         iphash = SHash(aserverp[k]);
1904
1905         /* Check if the srvAddr structure already exists. If so, remove
1906          * it from its server structure and add it to the new one.
1907          */
1908         for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1909             if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1910                 break;
1911         }
1912         if (oldsa && (oldsa->server != newts)) {
1913             afs_RemoveSrvAddr(oldsa);   /* Remove from its server struct */
1914             oldsa->next_sa = newts->addr;       /* Add to the  new server struct */
1915             newts->addr = oldsa;
1916         }
1917
1918         /* Reuse/allocate a new srvAddr structure */
1919         if (oldsa) {
1920             newsa = oldsa;
1921         } else {
1922             newsa = afs_osi_Alloc(sizeof(struct srvAddr));
1923             if (!newsa)
1924                 panic("malloc of srvAddr struct");
1925             afs_totalSrvAddrs++;
1926             memset(newsa, 0, sizeof(struct srvAddr));
1927
1928             /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1929             newsa->next_bkt = afs_srvAddrs[iphash];
1930             afs_srvAddrs[iphash] = newsa;
1931
1932             /* Hang off of the server structure  */
1933             newsa->next_sa = newts->addr;
1934             newts->addr = newsa;
1935
1936             /* Initialize the srvAddr Structure */
1937             newsa->sa_ip = aserverp[k];
1938             newsa->sa_portal = aport;
1939         }
1940
1941         /* Update the srvAddr Structure */
1942         newsa->server = newts;
1943         if (newts->flags & SRVR_ISDOWN)
1944             newsa->sa_flags |= SRVADDR_ISDOWN;
1945         if (uuidp)
1946             newsa->sa_flags |= SRVADDR_MH;
1947         else
1948             newsa->sa_flags &= ~SRVADDR_MH;
1949
1950         /* Compute preference values and resort */
1951         if (!newsa->sa_iprank) {
1952             afs_SetServerPrefs(newsa);  /* new server rank */
1953         }
1954     }
1955     afs_SortOneServer(newts);   /* Sort by rank */
1956
1957     /* If we reused the server struct, remove any of its srvAddr
1958      * structs that will no longer be associated with this server.
1959      */
1960     if (oldts) {                /* reused the server struct */
1961         for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1962             nextsa = orphsa->next_sa;
1963             for (k = 0; k < nservers; k++) {
1964                 if (orphsa->sa_ip == aserverp[k])
1965                     break;      /* belongs */
1966             }
1967             if (k < nservers)
1968                 continue;       /* belongs */
1969
1970             /* Have a srvAddr struct. Now get a server struct (if not already) */
1971             if (!orphts) {
1972                 orphts = afs_osi_Alloc(sizeof(struct server));
1973                 if (!orphts)
1974                     panic("malloc of lo server struct");
1975                 memset(orphts, 0, sizeof(struct server));
1976                 afs_totalServers++;
1977
1978                 /* Add the orphaned server to the afs_servers[] hash chain.
1979                  * Its iphash does not matter since we never look up the server
1980                  * in the afs_servers table by its ip address (only by uuid -
1981                  * which this has none).
1982                  */
1983                 iphash = SHash(aserverp[k]);
1984                 orphts->next = afs_servers[iphash];
1985                 afs_servers[iphash] = orphts;
1986
1987                 if (acell)
1988                     orphts->cell = afs_GetCell(acell, 0);
1989             }
1990
1991             /* Hang the srvAddr struct off of the server structure. The server
1992              * may have multiple srvAddrs, but it won't be marked multihomed.
1993              */
1994             afs_RemoveSrvAddr(orphsa);  /* remove */
1995             orphsa->next_sa = orphts->addr;     /* hang off server struct */
1996             orphts->addr = orphsa;
1997             orphsa->server = orphts;
1998             orphsa->sa_flags |= SRVADDR_NOUSE;  /* flag indicating not in use */
1999             orphsa->sa_flags &= ~SRVADDR_MH;    /* Not multihomed */
2000         }
2001     }
2002
2003     srvcount = afs_totalServers - srvcount;     /* # servers added and removed */
2004     if (srvcount) {
2005         struct afs_stats_SrvUpDownInfo *upDownP;
2006         /* With the introduction of this new record, we need to adjust the
2007          * proper individual & global server up/down info.
2008          */
2009         upDownP = GetUpDownStats(newts);
2010         upDownP->numTtlRecords += srvcount;
2011         afs_stats_cmperf.srvRecords += srvcount;
2012         if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
2013             afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
2014     }
2015
2016     ReleaseWriteLock(&afs_xsrvAddr);
2017
2018     if ( aport == AFS_FSPORT && !(newts->flags & SCAPS_KNOWN))
2019         afs_GetCapabilities(newts);
2020
2021     ReleaseWriteLock(&afs_xserver);
2022     return (newts);
2023 }                               /* afs_GetServer */
2024
2025 void
2026 afs_ActivateServer(struct srvAddr *sap)
2027 {
2028     osi_timeval_t currTime;     /*Filled with current time */
2029     osi_timeval_t *currTimeP;   /*Ptr to above */
2030     struct afs_stats_SrvUpDownInfo *upDownP;    /*Ptr to up/down info record */
2031     struct server *aserver = sap->server;
2032
2033     if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
2034         /*
2035          * This server record has not yet been activated.  Go for it,
2036          * recording its ``birth''.
2037          */
2038         aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
2039         currTimeP = &currTime;
2040         osi_GetuTime(currTimeP);
2041         aserver->activationTime = currTime.tv_sec;
2042         upDownP = GetUpDownStats(aserver);
2043         if (aserver->flags & SRVR_ISDOWN) {
2044             upDownP->numDownRecords++;
2045         } else {
2046             upDownP->numUpRecords++;
2047             upDownP->numRecordsNeverDown++;
2048         }
2049     }
2050 }
2051
2052 void
2053 afs_RemoveAllConns(void)
2054 {
2055     int i;
2056     struct server *ts, *nts;
2057     struct srvAddr *sa;
2058
2059     ObtainReadLock(&afs_xserver);
2060     ObtainWriteLock(&afs_xconn, 1001);
2061
2062     /*printf("Destroying connections ... ");*/
2063     for (i = 0; i < NSERVERS; i++) {
2064         for (ts = afs_servers[i]; ts; ts = nts) {
2065             nts = ts->next;
2066             for (sa = ts->addr; sa; sa = sa->next_sa) {
2067                 if (sa->conns) {
2068                     afs_ReleaseConns(sa->conns);
2069                     sa->conns = NULL;
2070                 }
2071             }
2072         }
2073     }
2074     /*printf("done\n");*/
2075
2076     ReleaseWriteLock(&afs_xconn);
2077     ReleaseReadLock(&afs_xserver);
2078
2079 }
2080
2081 void
2082 afs_MarkAllServersUp(void)
2083 {
2084     int i;
2085     struct server *ts;
2086     struct srvAddr *sa;
2087
2088     ObtainWriteLock(&afs_xserver, 721);
2089     ObtainWriteLock(&afs_xsrvAddr, 722);
2090     for (i = 0; i< NSERVERS; i++) {
2091         for (ts = afs_servers[i]; ts; ts = ts->next) {
2092             for (sa = ts->addr; sa; sa = sa->next_sa) {
2093                 afs_MarkServerUpOrDown(sa, 0);
2094             }
2095         }
2096     }
2097     ReleaseWriteLock(&afs_xsrvAddr);
2098     ReleaseWriteLock(&afs_xserver);
2099 }