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