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