libafs: Correct afs_LoopServers flags
[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: AFS_LS_UP   - check only up
752  *        AFS_LS_DOWN - check only down.
753  *        AFS_LS_ALL  - check all */
754 void
755 afs_LoopServers(int adown, struct cell *acellp, int vlalso,
756                 void (*func1) (struct rx_connection **rxconns, int nconns,
757                                int nservers, struct afs_conn **conns,
758                                struct srvAddr **addrs),
759                 void (*func2) (struct rx_connection **rxconns, int nconns,
760                                int nservers, struct afs_conn **conns,
761                                struct srvAddr **addrs))
762 {
763     struct vrequest treq;
764     struct server *ts;
765     struct srvAddr *sa;
766     struct afs_conn *tc = NULL;
767     afs_int32 i, j;
768     afs_int32 code;
769     struct unixuser *tu;
770     int srvAddrCount;
771     struct srvAddr **addrs;
772     struct afs_conn **conns;
773     int nconns;
774     struct rx_connection **rxconns;
775     afs_int32 *conntimer, *results;
776
777     AFS_STATCNT(afs_CheckServers);
778
779     /*
780      * No sense in doing the server checks if we are running in disconnected
781      * mode
782      */
783     if (AFS_IS_DISCONNECTED)
784         return;
785
786     conns = (struct afs_conn **)0;
787     rxconns = (struct rx_connection **) 0;
788     conntimer = 0;
789     nconns = 0;
790
791     if ((code = afs_InitReq(&treq, afs_osi_credp)))
792         return;
793     ObtainReadLock(&afs_xserver);       /* Necessary? */
794     ObtainReadLock(&afs_xsrvAddr);
795
796     srvAddrCount = 0;
797     for (i = 0; i < NSERVERS; i++) {
798         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
799             srvAddrCount++;
800         }
801     }
802
803     addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
804     osi_Assert(addrs != NULL);
805     j = 0;
806     for (i = 0; i < NSERVERS; i++) {
807         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
808             if (j >= srvAddrCount)
809                 break;
810             addrs[j++] = sa;
811         }
812     }
813
814     ReleaseReadLock(&afs_xsrvAddr);
815     ReleaseReadLock(&afs_xserver);
816
817     conns = afs_osi_Alloc(j * sizeof(struct afs_conn *));
818     osi_Assert(conns != NULL);
819     rxconns = afs_osi_Alloc(j * sizeof(struct rx_connection *));
820     osi_Assert(rxconns != NULL);
821     conntimer = afs_osi_Alloc(j * sizeof (afs_int32));
822     osi_Assert(conntimer != NULL);
823     results = afs_osi_Alloc(j * sizeof (afs_int32));
824     osi_Assert(results != NULL);
825
826     for (i = 0; i < j; i++) {
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);
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]=tc->id;
864             if (sa->sa_flags & SRVADDR_ISDOWN) {
865                 rx_SetConnDeadTime(tc->id, 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(tc->id, afs_rx_deadtime);
883         afs_PutConn(conns[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
1120 #if     defined(AFS_SUN5_ENV) && ! defined(AFS_SUN56_ENV)
1121 #include <inet/common.h>
1122 /* IP interface structure, one per local address */
1123 typedef struct ipif_s {
1124      /**/ struct ipif_s *ipif_next;
1125     struct ill_s *ipif_ill;     /* Back pointer to our ill */
1126     long ipif_id;               /* Logical unit number */
1127     u_int ipif_mtu;             /* Starts at ipif_ill->ill_max_frag */
1128     afs_int32 ipif_local_addr;  /* Local IP address for this if. */
1129     afs_int32 ipif_net_mask;    /* Net mask for this interface. */
1130     afs_int32 ipif_broadcast_addr;      /* Broadcast addr for this interface. */
1131     afs_int32 ipif_pp_dst_addr; /* Point-to-point dest address. */
1132     u_int ipif_flags;           /* Interface flags. */
1133     u_int ipif_metric;          /* BSD if metric, for compatibility. */
1134     u_int ipif_ire_type;        /* LOCAL or LOOPBACK */
1135     mblk_t *ipif_arp_down_mp;   /* Allocated at time arp comes up to
1136                                  * prevent awkward out of mem condition
1137                                  * later
1138                                  */
1139     mblk_t *ipif_saved_ire_mp;  /* Allocated for each extra IRE_SUBNET/
1140                                  * RESOLVER on this interface so that
1141                                  * they can survive ifconfig down.
1142                                  */
1143     /*
1144      * The packet counts in the ipif contain the sum of the
1145      * packet counts in dead IREs that were affiliated with
1146      * this ipif.
1147      */
1148     u_long ipif_fo_pkt_count;   /* Forwarded thru our dead IREs */
1149     u_long ipif_ib_pkt_count;   /* Inbound packets for our dead IREs */
1150     u_long ipif_ob_pkt_count;   /* Outbound packets to our dead IREs */
1151     unsigned int
1152       ipif_multicast_up:1,      /* We have joined the allhosts group */
1153     : 0;
1154 } ipif_t;
1155
1156 typedef struct ipfb_s {
1157      /**/ struct ipf_s *ipfb_ipf;       /* List of ... */
1158     kmutex_t ipfb_lock;         /* Protect all ipf in list */
1159 } ipfb_t;
1160
1161 typedef struct ilm_s {
1162      /**/ afs_int32 ilm_addr;
1163     int ilm_refcnt;
1164     u_int ilm_timer;            /* IGMP */
1165     struct ipif_s *ilm_ipif;    /* Back pointer to ipif */
1166     struct ilm_s *ilm_next;     /* Linked list for each ill */
1167 } ilm_t;
1168
1169 typedef struct ill_s {
1170      /**/ struct ill_s *ill_next;       /* Chained in at ill_g_head. */
1171     struct ill_s **ill_ptpn;    /* Pointer to previous next. */
1172     queue_t *ill_rq;            /* Read queue. */
1173     queue_t *ill_wq;            /* Write queue. */
1174
1175     int ill_error;              /* Error value sent up by device. */
1176
1177     ipif_t *ill_ipif;           /* Interface chain for this ILL. */
1178     u_int ill_ipif_up_count;    /* Number of IPIFs currently up. */
1179     u_int ill_max_frag;         /* Max IDU. */
1180     char *ill_name;             /* Our name. */
1181     u_int ill_name_length;      /* Name length, incl. terminator. */
1182     u_int ill_subnet_type;      /* IRE_RESOLVER or IRE_SUBNET. */
1183     u_int ill_ppa;              /* Physical Point of Attachment num. */
1184     u_long ill_sap;
1185     int ill_sap_length;         /* Including sign (for position) */
1186     u_int ill_phys_addr_length; /* Excluding the sap. */
1187     mblk_t *ill_frag_timer_mp;  /* Reassembly timer state. */
1188     ipfb_t *ill_frag_hash_tbl;  /* Fragment hash list head. */
1189
1190     queue_t *ill_bind_pending_q;        /* Queue waiting for DL_BIND_ACK. */
1191     ipif_t *ill_ipif_pending;   /* IPIF waiting for DL_BIND_ACK. */
1192
1193     /* ill_hdr_length and ill_hdr_mp will be non zero if
1194      * the underlying device supports the M_DATA fastpath
1195      */
1196     int ill_hdr_length;
1197
1198     ilm_t *ill_ilm;             /* Multicast mebership for lower ill */
1199
1200     /* All non-nil cells between 'ill_first_mp_to_free' and
1201      * 'ill_last_mp_to_free' are freed in ill_delete.
1202      */
1203 #define ill_first_mp_to_free    ill_hdr_mp
1204     mblk_t *ill_hdr_mp;         /* Contains fastpath template */
1205     mblk_t *ill_bcast_mp;       /* DLPI header for broadcasts. */
1206     mblk_t *ill_bind_pending;   /* T_BIND_REQ awaiting completion. */
1207     mblk_t *ill_resolver_mp;    /* Resolver template. */
1208     mblk_t *ill_attach_mp;
1209     mblk_t *ill_bind_mp;
1210     mblk_t *ill_unbind_mp;
1211     mblk_t *ill_detach_mp;
1212 #define ill_last_mp_to_free     ill_detach_mp
1213
1214     u_int ill_frag_timer_running:1, ill_needs_attach:1, ill_is_ptp:1,
1215         ill_priv_stream:1, ill_unbind_pending:1, ill_pad_to_bit_31:27;
1216       MI_HRT_DCL(ill_rtime)
1217       MI_HRT_DCL(ill_rtmp)
1218 } ill_t;
1219 #endif
1220
1221 #ifdef AFS_USERSPACE_IP_ADDR
1222 #ifndef afs_min
1223 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1224 #endif
1225 /*
1226  * The IP addresses and ranks are determined by afsd (in user space) and
1227  * passed into the kernel at startup time through the AFSOP_ADVISEADDR
1228  * system call. These are stored in the data structure
1229  * called 'afs_cb_interface'.
1230  *
1231  * struct srvAddr *sa;         remote server
1232  * afs_int32 addr;                one of my local addr in net order
1233  * afs_uint32 subnetmask;         subnet mask of local addr in net order
1234  *
1235  */
1236 void
1237 afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
1238                      afs_uint32 subnetmask)
1239 {
1240     afs_uint32 myAddr, myNet, mySubnet, netMask;
1241     afs_uint32 serverAddr;
1242
1243     myAddr = ntohl(addr);       /* one of my IP addr in host order */
1244     serverAddr = ntohl(sa->sa_ip);      /* server's IP addr in host order */
1245     subnetmask = ntohl(subnetmask);     /* subnet mask in host order */
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);
1265             }
1266         } else {                /* same net */
1267             sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1268         }
1269     }
1270     return;
1271 }
1272 #else /* AFS_USERSPACE_IP_ADDR */
1273 #if (! defined(AFS_SUN5_ENV)) && (! defined(AFS_DARWIN_ENV)) && (! defined(AFS_OBSD47_ENV)) && defined(USEIFADDR)
1274 void
1275 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
1276 {
1277     struct sockaddr_in *sin;
1278     int t;
1279
1280     if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1281         if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1282             sin = IA_SIN(ifa);
1283             if (SA2ULONG(sin) == ntohl(sa->sa_ip)) {    /* ie, ME!!!  */
1284                 sa->sa_iprank = TOPR;
1285             } else {
1286                 t = HI + ifa->ia_ifp->if_metric;        /* case #2 */
1287                 if (sa->sa_iprank > t)
1288                     sa->sa_iprank = t;
1289             }
1290         } else {
1291             t = MED + ifa->ia_ifp->if_metric;   /* case #3 */
1292             if (sa->sa_iprank > t)
1293                 sa->sa_iprank = t;
1294         }
1295     }
1296 #ifdef  IFF_POINTTOPOINT
1297     /* check for case #4 -- point-to-point link */
1298     if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1299         && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1300         if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1301             t = MAXDEFRANK;
1302         else
1303             t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1304         if (sa->sa_iprank > t)
1305             sa->sa_iprank = t;
1306     }
1307 #endif /* IFF_POINTTOPOINT */
1308 }
1309 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1310 #if (defined(AFS_DARWIN_ENV) || defined(AFS_OBSD47_ENV)) && defined(USEIFADDR)
1311 #ifndef afs_min
1312 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1313 #endif
1314 void
1315 afsi_SetServerIPRank(struct srvAddr *sa, rx_ifaddr_t ifa)
1316 {
1317     struct sockaddr sout;
1318     struct sockaddr_in *sin;
1319     int t;
1320
1321     afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1322     afs_uint32 serverAddr;
1323
1324     if (rx_ifaddr_address_family(ifa) != AF_INET)
1325         return;
1326     t = rx_ifaddr_address(ifa, &sout, sizeof(sout));
1327     if (t != 0) {
1328         sin = (struct sockaddr_in *)&sout;
1329         myAddr = ntohl(sin->sin_addr.s_addr);   /* one of my IP addr in host order */
1330     } else {
1331         myAddr = 0;
1332     }
1333     serverAddr = ntohl(sa->sa_ip);      /* server's IP addr in host order */
1334     t = rx_ifaddr_netmask(ifa, &sout, sizeof(sout));
1335     if (t != 0) {
1336         sin = (struct sockaddr_in *)&sout;
1337         subnetmask = ntohl(sin->sin_addr.s_addr);       /* subnet mask in host order */
1338     } else {
1339         subnetmask = 0;
1340     }
1341     t = rx_ifaddr_dstaddress(ifa, &sout, sizeof(sout));
1342     if (t != 0) {
1343         sin = (struct sockaddr_in *)&sout;
1344         myDstaddr = ntohl(sin->sin_addr.s_addr);
1345     } else {
1346         myDstaddr = 0;
1347     }
1348
1349     if (IN_CLASSA(myAddr))
1350         netMask = IN_CLASSA_NET;
1351     else if (IN_CLASSB(myAddr))
1352         netMask = IN_CLASSB_NET;
1353     else if (IN_CLASSC(myAddr))
1354         netMask = IN_CLASSC_NET;
1355     else
1356         netMask = 0;
1357
1358     myNet = myAddr & netMask;
1359     mySubnet = myAddr & subnetmask;
1360
1361     if ((serverAddr & netMask) == myNet) {
1362         if ((serverAddr & subnetmask) == mySubnet) {
1363             if (serverAddr == myAddr) { /* same machine */
1364                 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1365             } else {            /* same subnet */
1366                 sa->sa_iprank = afs_min(sa->sa_iprank, HI + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1367             }
1368         } else {                /* same net */
1369             sa->sa_iprank = afs_min(sa->sa_iprank, MED + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1370         }
1371     }
1372 #ifdef  IFF_POINTTOPOINT
1373     /* check for case #4 -- point-to-point link */
1374     if ((rx_ifnet_flags(rx_ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
1375         && (myDstaddr == serverAddr)) {
1376         if (rx_ifnet_metric(rx_ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
1377             t = MAXDEFRANK;
1378         else
1379             t = MED + (PPWEIGHT << rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1380         if (sa->sa_iprank > t)
1381             sa->sa_iprank = t;
1382         }
1383 #endif /* IFF_POINTTOPOINT */
1384 }
1385 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1386 #endif /* else AFS_USERSPACE_IP_ADDR */
1387
1388 #ifdef AFS_SGI62_ENV
1389 static int
1390 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1391                    caddr_t arg2)
1392 {
1393     afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1394     return 0;                   /* Never match, so we enumerate everyone */
1395 }
1396 #endif                          /* AFS_SGI62_ENV */
1397 static int
1398 afs_SetServerPrefs(struct srvAddr *sa)
1399 {
1400 #if     defined(AFS_USERSPACE_IP_ADDR)
1401     int i;
1402
1403       sa->sa_iprank = LO;
1404     for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1405         afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1406                              afs_cb_interface.subnetmask[i]);
1407     }
1408 #else                           /* AFS_USERSPACE_IP_ADDR */
1409 #if     defined(AFS_SUN5_ENV)
1410 #ifdef AFS_SUN510_ENV
1411     int i = 0;
1412 #else
1413     extern struct ill_s *ill_g_headp;
1414     long *addr = (long *)ill_g_headp;
1415     ill_t *ill;
1416     ipif_t *ipif;
1417 #endif
1418     int subnet, subnetmask, net, netmask;
1419
1420     if (sa)
1421           sa->sa_iprank = 0;
1422 #ifdef AFS_SUN510_ENV
1423     rw_enter(&afsifinfo_lock, RW_READER);
1424
1425     for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
1426
1427         if (IN_CLASSA(afsifinfo[i].ipaddr)) {
1428             netmask = IN_CLASSA_NET;
1429         } else if (IN_CLASSB(afsifinfo[i].ipaddr)) {
1430             netmask = IN_CLASSB_NET;
1431         } else if (IN_CLASSC(afsifinfo[i].ipaddr)) {
1432             netmask = IN_CLASSC_NET;
1433         } else {
1434             netmask = 0;
1435         }
1436         net = afsifinfo[i].ipaddr & netmask;
1437
1438 #ifdef notdef
1439         if (!s) {
1440             if (!rx_IsLoopbackAddr(afsifinfo[i].ipaddr)) {      /* ignore loopback */
1441                 *cnt += 1;
1442                 if (*cnt > 16)
1443                     return;
1444                 *addrp++ = afsifinfo[i].ipaddr;
1445             }
1446         } else
1447 #endif /* notdef */
1448         {
1449             /* XXXXXX Do the individual ip ranking below XXXXX */
1450             if ((sa->sa_ip & netmask) == net) {
1451                 if ((sa->sa_ip & subnetmask) == subnet) {
1452                     if (afsifinfo[i].ipaddr == sa->sa_ip) {   /* ie, ME!  */
1453                         sa->sa_iprank = TOPR;
1454                     } else {
1455                         sa->sa_iprank = HI + afsifinfo[i].metric; /* case #2 */
1456                     }
1457                 } else {
1458                     sa->sa_iprank = MED + afsifinfo[i].metric;    /* case #3 */
1459                 }
1460             } else {
1461                     sa->sa_iprank = LO + afsifinfo[i].metric;     /* case #4 */
1462             }
1463             /* check for case #5 -- point-to-point link */
1464             if ((afsifinfo[i].flags & IFF_POINTOPOINT)
1465                 && (afsifinfo[i].dstaddr == sa->sa_ip)) {
1466
1467                     if (afsifinfo[i].metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1468                         sa->sa_iprank = MAXDEFRANK;
1469                     else
1470                         sa->sa_iprank = MED + (PPWEIGHT << afsifinfo[i].metric);
1471             }
1472         }
1473     }
1474
1475     rw_exit(&afsifinfo_lock);
1476 #else
1477     for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1478          ill = ill->ill_next) {
1479 #ifdef AFS_SUN58_ENV
1480         /* Make sure this is an IPv4 ILL */
1481         if (ill->ill_isv6)
1482             continue;
1483 #endif
1484         for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1485             subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1486             subnetmask = ipif->ipif_net_mask;
1487             /*
1488              * Generate the local net using the local address and
1489              * whate we know about Class A, B and C networks.
1490              */
1491             if (IN_CLASSA(ipif->ipif_local_addr)) {
1492                 netmask = IN_CLASSA_NET;
1493             } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1494                 netmask = IN_CLASSB_NET;
1495             } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1496                 netmask = IN_CLASSC_NET;
1497             } else {
1498                 netmask = 0;
1499             }
1500             net = ipif->ipif_local_addr & netmask;
1501 #ifdef notdef
1502             if (!s) {
1503                 if (!rx_IsLoopbackAddr(ipif->ipif_local_addr)) {        /* ignore loopback */
1504                     *cnt += 1;
1505                     if (*cnt > 16)
1506                         return;
1507                     *addrp++ = ipif->ipif_local_addr;
1508                 }
1509             } else
1510 #endif /* notdef */
1511             {
1512                 /* XXXXXX Do the individual ip ranking below XXXXX */
1513                 if ((sa->sa_ip & netmask) == net) {
1514                     if ((sa->sa_ip & subnetmask) == subnet) {
1515                         if (ipif->ipif_local_addr == sa->sa_ip) {       /* ie, ME!  */
1516                             sa->sa_iprank = TOPR;
1517                         } else {
1518                             sa->sa_iprank = HI + ipif->ipif_metric;     /* case #2 */
1519                         }
1520                     } else {
1521                         sa->sa_iprank = MED + ipif->ipif_metric;        /* case #3 */
1522                     }
1523                 } else {
1524                     sa->sa_iprank = LO + ipif->ipif_metric;     /* case #4 */
1525                 }
1526                 /* check for case #5 -- point-to-point link */
1527                 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1528                     && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1529
1530                     if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1531                         sa->sa_iprank = MAXDEFRANK;
1532                     else
1533                         sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1534                 }
1535             }
1536         }
1537     }
1538 #endif /* AFS_SUN510_ENV */
1539 #else
1540 #ifndef USEIFADDR
1541     rx_ifnet_t ifn = NULL;
1542     struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1543     struct sockaddr_in *sin;
1544
1545     if (!sa) {
1546 #ifdef notdef                   /* clean up, remove this */
1547         for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1548             for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
1549                 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1550                     && !(ifn->if_flags & IFF_LOOPBACK)) {
1551                     *cnt += 1;
1552                     if (*cnt > 16)
1553                         return;
1554                     *addrp++ =
1555                         ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
1556                         s_addr;
1557                 }
1558         }}
1559 #endif                          /* notdef */
1560         return;
1561     }
1562     sa->sa_iprank = 0;
1563 #ifdef  ADAPT_MTU
1564     ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1565 #endif
1566     if (ifn) {                  /* local, more or less */
1567 #ifdef IFF_LOOPBACK
1568         if (ifn->if_flags & IFF_LOOPBACK) {
1569             sa->sa_iprank = TOPR;
1570             goto end;
1571         }
1572 #endif /* IFF_LOOPBACK */
1573         sin = (struct sockaddr_in *)IA_SIN(ifad);
1574         if (SA2ULONG(sin) == sa->sa_ip) {
1575             sa->sa_iprank = TOPR;
1576             goto end;
1577         }
1578 #ifdef IFF_BROADCAST
1579         if (ifn->if_flags & IFF_BROADCAST) {
1580             if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1581                 sa->sa_iprank = HI;
1582                 goto end;
1583             }
1584         }
1585 #endif /* IFF_BROADCAST */
1586 #ifdef IFF_POINTOPOINT
1587         if (ifn->if_flags & IFF_POINTOPOINT) {
1588             if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1589                 if (ifn->if_metric > 4) {
1590                     sa->sa_iprank = LO;
1591                     goto end;
1592                 } else
1593                     sa->sa_iprank = ifn->if_metric;
1594             }
1595         }
1596 #endif /* IFF_POINTOPOINT */
1597         sa->sa_iprank += MED + ifn->if_metric;  /* couldn't find anything better */
1598     }
1599 #else                           /* USEIFADDR */
1600
1601     if (sa)
1602         sa->sa_iprank = LO;
1603 #ifdef AFS_SGI62_ENV
1604     (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1605                     (caddr_t) sa, NULL);
1606 #elif defined(AFS_DARWIN80_ENV)
1607     {
1608         errno_t t;
1609         unsigned int count;
1610         int cnt=0, m, j;
1611         rx_ifaddr_t *ifads;
1612         rx_ifnet_t *ifns;
1613
1614         if (!ifnet_list_get(AF_INET, &ifns, &count)) {
1615             for (m = 0; m < count; m++) {
1616                 if (!ifnet_get_address_list(ifns[m], &ifads)) {
1617                     for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
1618                         afsi_SetServerIPRank(sa, ifads[j]);
1619                         cnt++;
1620                     }
1621                     ifnet_free_address_list(ifads);
1622                 }
1623             }
1624             ifnet_list_free(ifns);
1625         }
1626     }
1627 #elif defined(AFS_DARWIN_ENV)
1628     {
1629         rx_ifnet_t ifn;
1630         rx_ifaddr_t ifa;
1631           TAILQ_FOREACH(ifn, &ifnet, if_link) {
1632             TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1633                 afsi_SetServerIPRank(sa, ifa);
1634     }}}
1635 #elif defined(AFS_FBSD_ENV)
1636     {
1637         struct in_ifaddr *ifa;
1638           TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1639             afsi_SetServerIPRank(sa, ifa);
1640     }}
1641 #elif defined(AFS_OBSD_ENV)
1642     {
1643         extern struct in_ifaddrhead in_ifaddr;
1644         struct in_ifaddr *ifa;
1645         for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1646             afsi_SetServerIPRank(sa, ifa);
1647     }
1648 #elif defined(AFS_NBSD40_ENV)
1649      {
1650        extern struct in_ifaddrhead in_ifaddrhead;
1651        struct in_ifaddr *ifa;
1652        for (ifa = in_ifaddrhead.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1653            afsi_SetServerIPRank(sa, ifa);
1654      }
1655 #else
1656     {
1657         struct in_ifaddr *ifa;
1658         for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1659             afsi_SetServerIPRank(sa, ifa);
1660     }}
1661 #endif
1662 #endif                          /* USEIFADDR */
1663 #ifndef USEIFADDR
1664     end:
1665 #endif
1666 #endif                          /* AFS_SUN5_ENV */
1667 #endif                          /* else AFS_USERSPACE_IP_ADDR */
1668     if (sa)
1669           sa->sa_iprank += afs_randomMod15();
1670
1671     return 0;
1672 }                               /* afs_SetServerPrefs */
1673
1674 #undef TOPR
1675 #undef HI
1676 #undef MED
1677 #undef LO
1678 #undef PPWEIGHT
1679
1680 /* afs_FlushServer()
1681  * The addresses on this server struct has changed in some way and will
1682  * clean up all other structures that may reference it.
1683  * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1684  */
1685 void
1686 afs_FlushServer(struct server *srvp)
1687 {
1688     afs_int32 i;
1689     struct server *ts, **pts;
1690
1691     /* Find any volumes residing on this server and flush their state */
1692       afs_ResetVolumes(srvp);
1693
1694     /* Flush all callbacks in the all vcaches for this specific server */
1695       afs_FlushServerCBs(srvp);
1696
1697     /* Remove all the callbacks structs */
1698     if (srvp->cbrs) {
1699         struct afs_cbr *cb, *cbnext;
1700
1701           ObtainWriteLock(&afs_xvcb, 300);
1702         for (cb = srvp->cbrs; cb; cb = cbnext) {
1703             cbnext = cb->next;
1704             afs_FreeCBR(cb);
1705         } srvp->cbrs = (struct afs_cbr *)0;
1706         ReleaseWriteLock(&afs_xvcb);
1707     }
1708
1709     /* If no more srvAddr structs hanging off of this server struct,
1710      * then clean it up.
1711      */
1712     if (!srvp->addr) {
1713         /* Remove the server structure from the cell list - if there */
1714         afs_RemoveCellEntry(srvp);
1715
1716         /* Remove from the afs_servers hash chain */
1717         for (i = 0; i < NSERVERS; i++) {
1718             for (pts = &(afs_servers[i]), ts = *pts; ts;
1719                  pts = &(ts->next), ts = *pts) {
1720                 if (ts == srvp)
1721                     break;
1722             }
1723             if (ts)
1724                 break;
1725         }
1726         if (ts) {
1727             *pts = ts->next;    /* Found it. Remove it */
1728             afs_osi_Free(ts, sizeof(struct server));    /* Free it */
1729             afs_totalServers--;
1730         }
1731     }
1732 }
1733
1734 /* afs_RemoveSrvAddr()
1735  * This removes a SrvAddr structure from its server structure.
1736  * The srvAddr struct is not free'd because it connections may still
1737  * be open to it. It is up to the calling process to make sure it
1738  * remains connected to a server struct.
1739  * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1740  *    It is not removed from the afs_srvAddrs hash chain.
1741  */
1742 void
1743 afs_RemoveSrvAddr(struct srvAddr *sap)
1744 {
1745     struct srvAddr **psa, *sa;
1746     struct server *srv;
1747
1748     if (!sap)
1749           return;
1750       srv = sap->server;
1751
1752     /* Find the srvAddr in the server's list and remove it */
1753     for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1754         if (sa == sap)
1755             break;
1756     } if (sa) {
1757         *psa = sa->next_sa;
1758         sa->next_sa = 0;
1759         sa->server = 0;
1760
1761         /* Flush the server struct since it's IP address has changed */
1762         afs_FlushServer(srv);
1763     }
1764 }
1765
1766 /* afs_GetCapabilities
1767  * Try and retrieve capabilities of a given file server. Carps on actual
1768  * failure. Servers are not expected to support this RPC. */
1769 void
1770 afs_GetCapabilities(struct server *ts)
1771 {
1772     Capabilities caps = {0, NULL};
1773     struct vrequest treq;
1774     struct afs_conn *tc;
1775     struct unixuser *tu;
1776     afs_int32 code;
1777
1778     if ( !ts || !ts->cell )
1779         return;
1780     if ( !afs_osi_credp )
1781         return;
1782
1783     if ((code = afs_InitReq(&treq, afs_osi_credp)))
1784         return;
1785     tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
1786     if ( !tu )
1787         return;
1788     tc = afs_ConnBySA(ts->addr, ts->cell->fsport, ts->cell->cellNum, tu, 0, 1,
1789                                                                 SHARED_LOCK);
1790     if ( !tc )
1791         return;
1792     /* InitCallBackStateN, triggered by our RPC, may need this */
1793     ReleaseWriteLock(&afs_xserver);
1794     code = RXAFS_GetCapabilities(tc->id, &caps);
1795     ObtainWriteLock(&afs_xserver, 723);
1796     /* we forced a conn above; important we mark it down if needed */
1797     if ((code < 0) && (code != RXGEN_OPCODE)) {
1798         afs_ServerDown(tc->parent->srvr);
1799         ForceNewConnections(tc->parent->srvr); /* multi homed clients */
1800     }
1801     afs_PutConn(tc, SHARED_LOCK);
1802     if ( code && code != RXGEN_OPCODE ) {
1803         afs_warn("RXAFS_GetCapabilities failed with code %d\n", code);
1804         /* better not be anything to free. we failed! */
1805         return;
1806     }
1807
1808     ts->flags |= SCAPS_KNOWN;
1809
1810     if ( caps.Capabilities_len > 0 ) {
1811         ts->capabilities = caps.Capabilities_val[0];
1812         xdr_free((xdrproc_t)xdr_Capabilities, &caps);
1813         caps.Capabilities_len = 0;
1814         caps.Capabilities_val = NULL;
1815     }
1816
1817 }
1818
1819 /* afs_GetServer()
1820  * Return an updated and properly initialized server structure
1821  * corresponding to the server ID, cell, and port specified.
1822  * If one does not exist, then one will be created.
1823  * aserver and aport must be in NET byte order.
1824  */
1825 struct server *
1826 afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers, afs_int32 acell,
1827               u_short aport, afs_int32 locktype, afsUUID * uuidp,
1828               afs_int32 addr_uniquifier)
1829 {
1830     struct server *oldts = 0, *ts, *newts, *orphts = 0;
1831     struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1832     afs_int32 iphash, k, srvcount = 0;
1833     unsigned int srvhash;
1834
1835     AFS_STATCNT(afs_GetServer);
1836
1837     ObtainSharedLock(&afs_xserver, 13);
1838
1839     /* Check if the server struct exists and is up to date */
1840     if (!uuidp) {
1841         if (nservers != 1)
1842             panic("afs_GetServer: incorect count of servers");
1843         ObtainReadLock(&afs_xsrvAddr);
1844         ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1845         ReleaseReadLock(&afs_xsrvAddr);
1846         if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1847             /* Found a server struct that is not multihomed and has the
1848              * IP address associated with it. A correct match.
1849              */
1850             ReleaseSharedLock(&afs_xserver);
1851             return (ts);
1852         }
1853     } else {
1854         if (nservers <= 0)
1855             panic("afs_GetServer: incorrect count of servers");
1856         ts = afs_FindServer(0, aport, uuidp, locktype);
1857         if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1858             /* Found a server struct that is multihomed and same
1859              * uniqufier (same IP addrs). The above if statement is the
1860              * same as in InstallUVolumeEntry().
1861              */
1862             ReleaseSharedLock(&afs_xserver);
1863             return ts;
1864         }
1865         if (ts)
1866             oldts = ts;         /* Will reuse if same uuid */
1867     }
1868
1869     UpgradeSToWLock(&afs_xserver, 36);
1870     ObtainWriteLock(&afs_xsrvAddr, 116);
1871
1872     srvcount = afs_totalServers;
1873
1874     /* Reuse/allocate a new server structure */
1875     if (oldts) {
1876         newts = oldts;
1877     } else {
1878         newts = afs_osi_Alloc(sizeof(struct server));
1879         if (!newts)
1880             panic("malloc of server struct");
1881         afs_totalServers++;
1882         memset(newts, 0, sizeof(struct server));
1883
1884         /* Add the server struct to the afs_servers[] hash chain */
1885         srvhash =
1886             (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1887         newts->next = afs_servers[srvhash];
1888         afs_servers[srvhash] = newts;
1889     }
1890
1891     /* Initialize the server structure */
1892     if (uuidp) {                /* Multihomed */
1893         newts->sr_uuid = *uuidp;
1894         newts->sr_addr_uniquifier = addr_uniquifier;
1895         newts->flags |= SRVR_MULTIHOMED;
1896     }
1897     if (acell)
1898         newts->cell = afs_GetCell(acell, 0);
1899
1900     /* For each IP address we are registering */
1901     for (k = 0; k < nservers; k++) {
1902         iphash = SHash(aserverp[k]);
1903
1904         /* Check if the srvAddr structure already exists. If so, remove
1905          * it from its server structure and add it to the new one.
1906          */
1907         for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1908             if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1909                 break;
1910         }
1911         if (oldsa && (oldsa->server != newts)) {
1912             afs_RemoveSrvAddr(oldsa);   /* Remove from its server struct */
1913             oldsa->next_sa = newts->addr;       /* Add to the  new server struct */
1914             newts->addr = oldsa;
1915         }
1916
1917         /* Reuse/allocate a new srvAddr structure */
1918         if (oldsa) {
1919             newsa = oldsa;
1920         } else {
1921             newsa = afs_osi_Alloc(sizeof(struct srvAddr));
1922             if (!newsa)
1923                 panic("malloc of srvAddr struct");
1924             afs_totalSrvAddrs++;
1925             memset(newsa, 0, sizeof(struct srvAddr));
1926
1927             /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1928             newsa->next_bkt = afs_srvAddrs[iphash];
1929             afs_srvAddrs[iphash] = newsa;
1930
1931             /* Hang off of the server structure  */
1932             newsa->next_sa = newts->addr;
1933             newts->addr = newsa;
1934
1935             /* Initialize the srvAddr Structure */
1936             newsa->sa_ip = aserverp[k];
1937             newsa->sa_portal = aport;
1938         }
1939
1940         /* Update the srvAddr Structure */
1941         newsa->server = newts;
1942         if (newts->flags & SRVR_ISDOWN)
1943             newsa->sa_flags |= SRVADDR_ISDOWN;
1944         if (uuidp)
1945             newsa->sa_flags |= SRVADDR_MH;
1946         else
1947             newsa->sa_flags &= ~SRVADDR_MH;
1948
1949         /* Compute preference values and resort */
1950         if (!newsa->sa_iprank) {
1951             afs_SetServerPrefs(newsa);  /* new server rank */
1952         }
1953     }
1954     afs_SortOneServer(newts);   /* Sort by rank */
1955
1956     /* If we reused the server struct, remove any of its srvAddr
1957      * structs that will no longer be associated with this server.
1958      */
1959     if (oldts) {                /* reused the server struct */
1960         for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1961             nextsa = orphsa->next_sa;
1962             for (k = 0; k < nservers; k++) {
1963                 if (orphsa->sa_ip == aserverp[k])
1964                     break;      /* belongs */
1965             }
1966             if (k < nservers)
1967                 continue;       /* belongs */
1968
1969             /* Have a srvAddr struct. Now get a server struct (if not already) */
1970             if (!orphts) {
1971                 orphts = afs_osi_Alloc(sizeof(struct server));
1972                 if (!orphts)
1973                     panic("malloc of lo server struct");
1974                 memset(orphts, 0, sizeof(struct server));
1975                 afs_totalServers++;
1976
1977                 /* Add the orphaned server to the afs_servers[] hash chain.
1978                  * Its iphash does not matter since we never look up the server
1979                  * in the afs_servers table by its ip address (only by uuid -
1980                  * which this has none).
1981                  */
1982                 iphash = SHash(aserverp[k]);
1983                 orphts->next = afs_servers[iphash];
1984                 afs_servers[iphash] = orphts;
1985
1986                 if (acell)
1987                     orphts->cell = afs_GetCell(acell, 0);
1988             }
1989
1990             /* Hang the srvAddr struct off of the server structure. The server
1991              * may have multiple srvAddrs, but it won't be marked multihomed.
1992              */
1993             afs_RemoveSrvAddr(orphsa);  /* remove */
1994             orphsa->next_sa = orphts->addr;     /* hang off server struct */
1995             orphts->addr = orphsa;
1996             orphsa->server = orphts;
1997             orphsa->sa_flags |= SRVADDR_NOUSE;  /* flag indicating not in use */
1998             orphsa->sa_flags &= ~SRVADDR_MH;    /* Not multihomed */
1999         }
2000     }
2001
2002     srvcount = afs_totalServers - srvcount;     /* # servers added and removed */
2003     if (srvcount) {
2004         struct afs_stats_SrvUpDownInfo *upDownP;
2005         /* With the introduction of this new record, we need to adjust the
2006          * proper individual & global server up/down info.
2007          */
2008         upDownP = GetUpDownStats(newts);
2009         upDownP->numTtlRecords += srvcount;
2010         afs_stats_cmperf.srvRecords += srvcount;
2011         if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
2012             afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
2013     }
2014
2015     ReleaseWriteLock(&afs_xsrvAddr);
2016
2017     if ( aport == AFS_FSPORT && !(newts->flags & SCAPS_KNOWN))
2018         afs_GetCapabilities(newts);
2019
2020     ReleaseWriteLock(&afs_xserver);
2021     return (newts);
2022 }                               /* afs_GetServer */
2023
2024 void
2025 afs_ActivateServer(struct srvAddr *sap)
2026 {
2027     osi_timeval_t currTime;     /*Filled with current time */
2028     osi_timeval_t *currTimeP;   /*Ptr to above */
2029     struct afs_stats_SrvUpDownInfo *upDownP;    /*Ptr to up/down info record */
2030     struct server *aserver = sap->server;
2031
2032     if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
2033         /*
2034          * This server record has not yet been activated.  Go for it,
2035          * recording its ``birth''.
2036          */
2037         aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
2038         currTimeP = &currTime;
2039         osi_GetuTime(currTimeP);
2040         aserver->activationTime = currTime.tv_sec;
2041         upDownP = GetUpDownStats(aserver);
2042         if (aserver->flags & SRVR_ISDOWN) {
2043             upDownP->numDownRecords++;
2044         } else {
2045             upDownP->numUpRecords++;
2046             upDownP->numRecordsNeverDown++;
2047         }
2048     }
2049 }
2050
2051 void
2052 afs_RemoveAllConns(void)
2053 {
2054     int i;
2055     struct server *ts, *nts;
2056     struct srvAddr *sa;
2057
2058     ObtainReadLock(&afs_xserver);
2059     ObtainWriteLock(&afs_xconn, 1001);
2060
2061     /*printf("Destroying connections ... ");*/
2062     for (i = 0; i < NSERVERS; i++) {
2063         for (ts = afs_servers[i]; ts; ts = nts) {
2064             nts = ts->next;
2065             for (sa = ts->addr; sa; sa = sa->next_sa) {
2066                 if (sa->conns) {
2067                     afs_ReleaseConns(sa->conns);
2068                     sa->conns = NULL;
2069                 }
2070             }
2071         }
2072     }
2073     /*printf("done\n");*/
2074
2075     ReleaseWriteLock(&afs_xconn);
2076     ReleaseReadLock(&afs_xserver);
2077
2078 }
2079
2080 void
2081 afs_MarkAllServersUp(void)
2082 {
2083     int i;
2084     struct server *ts;
2085     struct srvAddr *sa;
2086
2087     ObtainWriteLock(&afs_xserver, 721);
2088     ObtainWriteLock(&afs_xsrvAddr, 722);
2089     for (i = 0; i< NSERVERS; i++) {
2090         for (ts = afs_servers[i]; ts; ts = ts->next) {
2091             for (sa = ts->addr; sa; sa = sa->next_sa) {
2092                 afs_MarkServerUpOrDown(sa, 0);
2093             }
2094         }
2095     }
2096     ReleaseWriteLock(&afs_xsrvAddr);
2097     ReleaseWriteLock(&afs_xserver);
2098 }