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