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