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