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