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