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