dont-leak-random-kernel-data-20040415
[openafs.git] / src / afs / afs_callback.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  * afs_callback.c:
12  *      Exported routines (and their private support) to implement
13  *      the callback RPC interface.
14  */
15
16 #include <afsconfig.h>
17 #include "afs/param.h"
18
19 RCSID
20     ("$Header$");
21
22 #include "afs/sysincludes.h"    /*Standard vendor system headers */
23 #include "afsincludes.h"        /*AFS-based standard headers */
24 #include "afs/afs_stats.h"      /*Cache Manager stats */
25 #include "afs/afs_args.h"
26
27 afs_int32 afs_allCBs = 0;       /*Break callbacks on all objects */
28 afs_int32 afs_oddCBs = 0;       /*Break callbacks on dirs */
29 afs_int32 afs_evenCBs = 0;      /*Break callbacks received on files */
30 afs_int32 afs_allZaps = 0;      /*Objects entries deleted */
31 afs_int32 afs_oddZaps = 0;      /*Dir cache entries deleted */
32 afs_int32 afs_evenZaps = 0;     /*File cache entries deleted */
33 afs_int32 afs_connectBacks = 0;
34
35 /*
36  * Some debugging aids.
37  */
38 static struct ltable {
39     char *name;
40     char *addr;
41 } ltable[] = {
42     {
43     "afs_xvcache", (char *)&afs_xvcache}, {
44     "afs_xdcache", (char *)&afs_xdcache}, {
45     "afs_xserver", (char *)&afs_xserver}, {
46     "afs_xvcb", (char *)&afs_xvcb}, {
47     "afs_xbrs", (char *)&afs_xbrs}, {
48     "afs_xcell", (char *)&afs_xcell}, {
49     "afs_xconn", (char *)&afs_xconn}, {
50     "afs_xuser", (char *)&afs_xuser}, {
51     "afs_xvolume", (char *)&afs_xvolume}, {
52     "puttofile", (char *)&afs_puttofileLock}, {
53     "afs_ftf", (char *)&afs_ftf}, {
54     "afs_xcbhash", (char *)&afs_xcbhash}, {
55     "afs_xaxs", (char *)&afs_xaxs}, {
56     "afs_xinterface", (char *)&afs_xinterface},
57 #ifndef UKERNEL
58     {
59     "afs_xosi", (char *)&afs_xosi},
60 #endif
61     {
62     "afs_xsrvAddr", (char *)&afs_xsrvAddr}
63 };
64 unsigned long lastCallBack_vnode;
65 unsigned int lastCallBack_dv;
66 osi_timeval_t lastCallBack_time;
67
68 /* these are for storing alternate interface addresses */
69 struct interfaceAddr afs_cb_interface;
70
71 /*------------------------------------------------------------------------
72  * EXPORTED SRXAFSCB_GetCE
73  *
74  * Description:
75  *      Routine called by the server-side callback RPC interface to
76  *      implement pulling out the contents of the i'th cache entry.
77  *
78  * Arguments:
79  *      a_call   : Ptr to Rx call on which this request came in.
80  *      a_index  : Index of desired cache entry.
81  *      a_result : Ptr to a buffer for the given cache entry.
82  *
83  * Returns:
84  *      0 if everything went fine,
85  *      1 if we were given a bad index.
86  *
87  * Environment:
88  *      Nothing interesting.
89  *
90  * Side Effects:
91  *      As advertised.
92  *------------------------------------------------------------------------*/
93
94 int
95 SRXAFSCB_GetCE(struct rx_call *a_call, afs_int32 a_index,
96                struct AFSDBCacheEntry *a_result)
97 {
98
99     register int i;             /*Loop variable */
100     register struct vcache *tvc;        /*Ptr to current cache entry */
101     int code;                   /*Return code */
102     XSTATS_DECLS;
103
104     RX_AFS_GLOCK();
105
106     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE);
107
108     AFS_STATCNT(SRXAFSCB_GetCE);
109     for (i = 0; i < VCSIZE; i++) {
110         for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
111             if (a_index == 0)
112                 goto searchDone;
113             a_index--;
114         }                       /*Zip through current hash chain */
115     }                           /*Zip through hash chains */
116
117   searchDone:
118     if (tvc == NULL) {
119         /*Past EOF */
120         code = 1;
121         goto fcnDone;
122     }
123
124     /*
125      * Copy out the located entry.
126      */
127     a_result->addr = afs_data_pointer_to_int32(tvc);
128     a_result->cell = tvc->fid.Cell;
129     a_result->netFid.Volume = tvc->fid.Fid.Volume;
130     a_result->netFid.Vnode = tvc->fid.Fid.Vnode;
131     a_result->netFid.Unique = tvc->fid.Fid.Unique;
132     a_result->lock.waitStates = tvc->lock.wait_states;
133     a_result->lock.exclLocked = tvc->lock.excl_locked;
134     a_result->lock.readersReading = tvc->lock.readers_reading;
135     a_result->lock.numWaiting = tvc->lock.num_waiting;
136 #if defined(INSTRUMENT_LOCKS)
137     a_result->lock.pid_last_reader = tvc->lock.pid_last_reader;
138     a_result->lock.pid_writer = tvc->lock.pid_writer;
139     a_result->lock.src_indicator = tvc->lock.src_indicator;
140 #else
141     /* On osf20 , the vcache does not maintain these three fields */
142     a_result->lock.pid_last_reader = 0;
143     a_result->lock.pid_writer = 0;
144     a_result->lock.src_indicator = 0;
145 #endif /* AFS_OSF20_ENV */
146 #ifdef AFS_64BIT_CLIENT
147     a_result->Length = (afs_int32) tvc->m.Length & 0xffffffff;
148 #else /* AFS_64BIT_CLIENT */
149     a_result->Length = tvc->m.Length;
150 #endif /* AFS_64BIT_CLIENT */
151     a_result->DataVersion = hgetlo(tvc->m.DataVersion);
152     a_result->callback = afs_data_pointer_to_int32(tvc->callback);      /* XXXX Now a pointer; change it XXXX */
153     a_result->cbExpires = tvc->cbExpires;
154     a_result->refCount = VREFCOUNT(tvc);
155     a_result->opens = tvc->opens;
156     a_result->writers = tvc->execsOrWriters;
157     a_result->mvstat = tvc->mvstat;
158     a_result->states = tvc->states;
159     code = 0;
160
161     /*
162      * Return our results.
163      */
164   fcnDone:
165     XSTATS_END_TIME;
166
167     RX_AFS_GUNLOCK();
168
169     return (code);
170
171 }                               /*SRXAFSCB_GetCE */
172
173 int
174 SRXAFSCB_GetCE64(struct rx_call *a_call, afs_int32 a_index,
175                  struct AFSDBCacheEntry64 *a_result)
176 {
177     register int i;             /*Loop variable */
178     register struct vcache *tvc;        /*Ptr to current cache entry */
179     int code;                   /*Return code */
180     XSTATS_DECLS;
181
182     RX_AFS_GLOCK();
183
184     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE);
185
186     AFS_STATCNT(SRXAFSCB_GetCE64);
187     for (i = 0; i < VCSIZE; i++) {
188         for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
189             if (a_index == 0)
190                 goto searchDone;
191             a_index--;
192         }                       /*Zip through current hash chain */
193     }                           /*Zip through hash chains */
194
195   searchDone:
196     if (tvc == NULL) {
197         /*Past EOF */
198         code = 1;
199         goto fcnDone;
200     }
201
202     /*
203      * Copy out the located entry.
204      */
205     a_result->addr = afs_data_pointer_to_int32(tvc);
206     a_result->cell = tvc->fid.Cell;
207     a_result->netFid.Volume = tvc->fid.Fid.Volume;
208     a_result->netFid.Vnode = tvc->fid.Fid.Vnode;
209     a_result->netFid.Unique = tvc->fid.Fid.Unique;
210     a_result->lock.waitStates = tvc->lock.wait_states;
211     a_result->lock.exclLocked = tvc->lock.excl_locked;
212     a_result->lock.readersReading = tvc->lock.readers_reading;
213     a_result->lock.numWaiting = tvc->lock.num_waiting;
214 #if defined(INSTRUMENT_LOCKS)
215     a_result->lock.pid_last_reader = tvc->lock.pid_last_reader;
216     a_result->lock.pid_writer = tvc->lock.pid_writer;
217     a_result->lock.src_indicator = tvc->lock.src_indicator;
218 #else
219     /* On osf20 , the vcache does not maintain these three fields */
220     a_result->lock.pid_last_reader = 0;
221     a_result->lock.pid_writer = 0;
222     a_result->lock.src_indicator = 0;
223 #endif /* AFS_OSF20_ENV */
224 #ifdef AFS_64BIT_ENV
225     a_result->Length = tvc->m.Length;
226 #else /* AFS_64BIT_ENV */
227 #ifdef AFS_64BIT_CLIENT
228     a_result->Length = tvc->m.Length;
229 #else /* AFS_64BIT_CLIENT */
230     a_result->Length.high = 0;
231     a_result->Length.low = tvc->m.Length;
232 #endif /* AFS_64BIT_CLIENT */
233 #endif /* AFS_64BIT_ENV */
234     a_result->DataVersion = hgetlo(tvc->m.DataVersion);
235     a_result->callback = afs_data_pointer_to_int32(tvc->callback);      /* XXXX Now a pointer; change it XXXX */
236     a_result->cbExpires = tvc->cbExpires;
237     a_result->refCount = VREFCOUNT(tvc);
238     a_result->opens = tvc->opens;
239     a_result->writers = tvc->execsOrWriters;
240     a_result->mvstat = tvc->mvstat;
241     a_result->states = tvc->states;
242     code = 0;
243
244     /*
245      * Return our results.
246      */
247   fcnDone:
248     XSTATS_END_TIME;
249
250     RX_AFS_GUNLOCK();
251
252     return (code);
253
254 }                               /*SRXAFSCB_GetCE64 */
255
256
257 /*------------------------------------------------------------------------
258  * EXPORTED SRXAFSCB_GetLock
259  *
260  * Description:
261  *      Routine called by the server-side callback RPC interface to
262  *      implement pulling out the contents of a lock in the lock
263  *      table.
264  *
265  * Arguments:
266  *      a_call   : Ptr to Rx call on which this request came in.
267  *      a_index  : Index of desired lock.
268  *      a_result : Ptr to a buffer for the given lock.
269  *
270  * Returns:
271  *      0 if everything went fine,
272  *      1 if we were given a bad index.
273  *
274  * Environment:
275  *      Nothing interesting.
276  *
277  * Side Effects:
278  *      As advertised.
279  *------------------------------------------------------------------------*/
280
281 int
282 SRXAFSCB_GetLock(struct rx_call *a_call, afs_int32 a_index,
283                  struct AFSDBLock *a_result)
284 {
285     struct ltable *tl;          /*Ptr to lock table entry */
286     int nentries;               /*Num entries in table */
287     int code;                   /*Return code */
288     XSTATS_DECLS;
289
290     RX_AFS_GLOCK();
291
292     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETLOCK);
293
294     AFS_STATCNT(SRXAFSCB_GetLock);
295     nentries = sizeof(ltable) / sizeof(struct ltable);
296     if (a_index < 0 || a_index >= nentries) {
297         /*
298          * Past EOF
299          */
300         code = 1;
301     } else {
302         /*
303          * Found it - copy out its contents.
304          */
305         tl = &ltable[a_index];
306         strcpy(a_result->name, tl->name);
307         a_result->lock.waitStates =
308             ((struct afs_lock *)(tl->addr))->wait_states;
309         a_result->lock.exclLocked =
310             ((struct afs_lock *)(tl->addr))->excl_locked;
311         a_result->lock.readersReading =
312             ((struct afs_lock *)(tl->addr))->readers_reading;
313         a_result->lock.numWaiting =
314             ((struct afs_lock *)(tl->addr))->num_waiting;
315 #ifdef INSTRUMENT_LOCKS
316         a_result->lock.pid_last_reader =
317             ((struct afs_lock *)(tl->addr))->pid_last_reader;
318         a_result->lock.pid_writer =
319             ((struct afs_lock *)(tl->addr))->pid_writer;
320         a_result->lock.src_indicator =
321             ((struct afs_lock *)(tl->addr))->src_indicator;
322 #else
323         a_result->lock.pid_last_reader = 0;
324         a_result->lock.pid_writer = 0;
325         a_result->lock.src_indicator = 0;
326 #endif
327         code = 0;
328     }
329
330     XSTATS_END_TIME;
331
332     RX_AFS_GUNLOCK();
333
334     return (code);
335
336 }                               /*SRXAFSCB_GetLock */
337
338
339 /*------------------------------------------------------------------------
340  * static ClearCallBack
341  *
342  * Description:
343  *      Clear out callback information for the specified file, or
344  *      even a whole volume.  Used to worry about callback was from 
345  *      within the particular cell or not.  Now we don't bother with
346  *      that anymore; it's not worth the time.
347  *
348  * Arguments:
349  *      a_conn : Ptr to Rx connection involved.
350  *      a_fid  : Ptr to AFS fid being cleared.
351  *
352  * Returns:
353  *      0 (always)
354  *
355  * Environment:
356  *      Nothing interesting.
357  *
358  * Side Effects:
359  *      As advertised.
360
361 Appears to need to be called with GLOCK held, as the icl_Event4 stuff asserts otherwise
362
363  *------------------------------------------------------------------------*/
364
365 static int
366 ClearCallBack(register struct rx_connection *a_conn,
367               register struct AFSFid *a_fid)
368 {
369     register struct vcache *tvc;
370     register int i;
371     struct VenusFid localFid;
372     struct volume *tv;
373
374     AFS_STATCNT(ClearCallBack);
375
376     AFS_ASSERT_GLOCK();
377
378     /*
379      * XXXX Don't hold any server locks here because of callback protocol XXX
380      */
381     localFid.Cell = 0;
382     localFid.Fid.Volume = a_fid->Volume;
383     localFid.Fid.Vnode = a_fid->Vnode;
384     localFid.Fid.Unique = a_fid->Unique;
385
386     /*
387      * Volume ID of zero means don't do anything.
388      */
389     if (a_fid->Volume != 0) {
390         if (a_fid->Vnode == 0) {
391             /*
392              * Clear callback for the whole volume.  Zip through the
393              * hash chain, nullifying entries whose volume ID matches.
394              */
395             for (i = 0; i < VCSIZE; i++)
396                 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
397                     if (tvc->fid.Fid.Volume == a_fid->Volume) {
398                         tvc->callback = NULL;
399                         tvc->quick.stamp = 0;
400                         if (!localFid.Cell)
401                             localFid.Cell = tvc->fid.Cell;
402                         tvc->h1.dchint = NULL;  /* invalidate hints */
403                         ObtainWriteLock(&afs_xcbhash, 449);
404                         afs_DequeueCallback(tvc);
405                         tvc->states &= ~(CStatd | CUnique | CBulkFetching);
406                         afs_allCBs++;
407                         if (tvc->fid.Fid.Vnode & 1)
408                             afs_oddCBs++;
409                         else
410                             afs_evenCBs++;
411                         ReleaseWriteLock(&afs_xcbhash);
412                         if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
413                             osi_dnlc_purgedp(tvc);
414                         afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
415                                    ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
416                                    tvc->states, ICL_TYPE_INT32,
417                                    a_fid->Volume);
418                     } else if ((tvc->states & CMValid)
419                                && (tvc->mvid->Fid.Volume == a_fid->Volume)) {
420                         tvc->states &= ~CMValid;
421                         if (!localFid.Cell)
422                             localFid.Cell = tvc->mvid->Cell;
423                     }
424                 }
425
426             /*
427              * XXXX Don't hold any locks here XXXX
428              */
429             tv = afs_FindVolume(&localFid, 0);
430             if (tv) {
431                 afs_ResetVolumeInfo(tv);
432                 afs_PutVolume(tv, 0);
433                 /* invalidate mtpoint? */
434             }
435         } /*Clear callbacks for whole volume */
436         else {
437             /*
438              * Clear callbacks just for the one file.
439              */
440             afs_allCBs++;
441             if (a_fid->Vnode & 1)
442                 afs_oddCBs++;   /*Could do this on volume basis, too */
443             else
444                 afs_evenCBs++;  /*A particular fid was specified */
445             i = VCHash(&localFid);
446             for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
447                 if (tvc->fid.Fid.Vnode == a_fid->Vnode
448                     && tvc->fid.Fid.Volume == a_fid->Volume
449                     && tvc->fid.Fid.Unique == a_fid->Unique) {
450                     tvc->callback = NULL;
451                     tvc->quick.stamp = 0;
452                     tvc->h1.dchint = NULL;      /* invalidate hints */
453                     ObtainWriteLock(&afs_xcbhash, 450);
454                     afs_DequeueCallback(tvc);
455                     tvc->states &= ~(CStatd | CUnique | CBulkFetching);
456                     ReleaseWriteLock(&afs_xcbhash);
457                     if (a_fid->Vnode & 1 || (vType(tvc) == VDIR))
458                         osi_dnlc_purgedp(tvc);
459                     afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
460                                ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
461                                tvc->states, ICL_TYPE_LONG, 0);
462 #ifdef CBDEBUG
463                     lastCallBack_vnode = afid->Vnode;
464                     lastCallBack_dv = tvc->mstat.DataVersion.low;
465                     osi_GetuTime(&lastCallBack_time);
466 #endif /* CBDEBUG */
467                 }
468             }                   /*Walk through hash table */
469         }                       /*Clear callbacks for one file */
470     }
471
472     /*Fid has non-zero volume ID */
473     /*
474      * Always return a predictable value.
475      */
476     return (0);
477
478 }                               /*ClearCallBack */
479
480
481 /*------------------------------------------------------------------------
482  * EXPORTED SRXAFSCB_CallBack
483  *
484  * Description:
485  *      Routine called by the server-side callback RPC interface to
486  *      implement passing in callback information.
487  *      table.
488  *
489  * Arguments:
490  *      a_call      : Ptr to Rx call on which this request came in.
491  *      a_fids      : Ptr to array of fids involved.
492  *      a_callbacks : Ptr to matching callback info for the fids.
493  *
494  * Returns:
495  *      0 (always).
496  *
497  * Environment:
498  *      Nothing interesting.
499  *
500  * Side Effects:
501  *      As advertised.
502  *------------------------------------------------------------------------*/
503
504 int
505 SRXAFSCB_CallBack(struct rx_call *a_call, register struct AFSCBFids *a_fids,
506                   struct AFSCBs *a_callbacks)
507 {
508     register int i;             /*Loop variable */
509     struct AFSFid *tfid;        /*Ptr to current fid */
510     register struct rx_connection *tconn;       /*Call's connection */
511     int code = 0;
512     XSTATS_DECLS;
513
514     RX_AFS_GLOCK();
515
516     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_CALLBACK);
517
518     AFS_STATCNT(SRXAFSCB_CallBack);
519     if (!(tconn = rx_ConnectionOf(a_call)))
520         return (0);
521     tfid = (struct AFSFid *)a_fids->AFSCBFids_val;
522
523     /*
524      * For now, we ignore callbacks, since the File Server only *breaks*
525      * callbacks at present.
526      */
527     for (i = 0; i < a_fids->AFSCBFids_len; i++)
528         ClearCallBack(tconn, &tfid[i]);
529
530     XSTATS_END_TIME;
531
532     RX_AFS_GUNLOCK();
533
534     return (0);
535
536 }                               /*SRXAFSCB_CallBack */
537
538
539 /*------------------------------------------------------------------------
540  * EXPORTED SRXAFSCB_Probe
541  *
542  * Description:
543  *      Routine called by the server-side callback RPC interface to
544  *      implement ``probing'' the Cache Manager, just making sure it's
545  *      still there.
546  *
547  * Arguments:
548  *      a_call : Ptr to Rx call on which this request came in.
549  *
550  * Returns:
551  *      0 (always).
552  *
553  * Environment:
554  *      Nothing interesting.
555  *
556  * Side Effects:
557  *      As advertised.
558  *------------------------------------------------------------------------*/
559
560 int
561 SRXAFSCB_Probe(struct rx_call *a_call)
562 {
563     int code = 0;
564     XSTATS_DECLS;
565
566     RX_AFS_GLOCK();
567     AFS_STATCNT(SRXAFSCB_Probe);
568
569     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
570     XSTATS_END_TIME;
571
572     RX_AFS_GUNLOCK();
573
574     return (0);
575
576 }                               /*SRXAFSCB_Probe */
577
578
579 /*------------------------------------------------------------------------
580  * EXPORTED SRXAFSCB_InitCallBackState
581  *
582  * Description:
583  *      Routine called by the server-side callback RPC interface to
584  *      implement clearing all callbacks from this host.
585  *
586  * Arguments:
587  *      a_call : Ptr to Rx call on which this request came in.
588  *
589  * Returns:
590  *      0 (always).
591  *
592  * Environment:
593  *      Nothing interesting.
594  *
595  * Side Effects:
596  *      As advertised.
597  *------------------------------------------------------------------------*/
598
599 int
600 SRXAFSCB_InitCallBackState(struct rx_call *a_call)
601 {
602     register int i;
603     register struct vcache *tvc;
604     register struct rx_connection *tconn;
605     register struct rx_peer *peer;
606     struct server *ts;
607     int code = 0;
608     XSTATS_DECLS;
609
610     RX_AFS_GLOCK();
611
612     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_INITCALLBACKSTATE);
613     AFS_STATCNT(SRXAFSCB_InitCallBackState);
614
615     /*
616      * Find the address of the host making this call
617      */
618     if ((tconn = rx_ConnectionOf(a_call)) && (peer = rx_PeerOf(tconn))) {
619
620         afs_allCBs++;
621         afs_oddCBs++;           /*Including any missed via create race */
622         afs_evenCBs++;          /*Including any missed via create race */
623
624         ts = afs_FindServer(rx_HostOf(peer), rx_PortOf(peer), (afsUUID *) 0,
625                             0);
626         if (ts) {
627             for (i = 0; i < VCSIZE; i++)
628                 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
629                     if (tvc->callback == ts) {
630                         ObtainWriteLock(&afs_xcbhash, 451);
631                         afs_DequeueCallback(tvc);
632                         tvc->callback = NULL;
633                         tvc->states &= ~(CStatd | CUnique | CBulkFetching);
634                         ReleaseWriteLock(&afs_xcbhash);
635                     }
636                 }
637         }
638
639
640
641         /* find any volumes residing on this server and flush their state */
642         {
643             register struct volume *tv;
644             register int j;
645
646             for (i = 0; i < NVOLS; i++)
647                 for (tv = afs_volumes[i]; tv; tv = tv->next) {
648                     for (j = 0; j < MAXHOSTS; j++)
649                         if (tv->serverHost[j] == ts)
650                             afs_ResetVolumeInfo(tv);
651                 }
652         }
653         osi_dnlc_purge();       /* may be a little bit extreme */
654     }
655
656     XSTATS_END_TIME;
657
658     RX_AFS_GUNLOCK();
659
660     return (0);
661
662 }                               /*SRXAFSCB_InitCallBackState */
663
664
665 /*------------------------------------------------------------------------
666  * EXPORTED SRXAFSCB_XStatsVersion
667  *
668  * Description:
669  *      Routine called by the server-side callback RPC interface to
670  *      implement pulling out the xstat version number for the Cache
671  *      Manager.
672  *
673  * Arguments:
674  *      a_versionP : Ptr to the version number variable to set.
675  *
676  * Returns:
677  *      0 (always)
678  *
679  * Environment:
680  *      Nothing interesting.
681  *
682  * Side Effects:
683  *      As advertised.
684  *------------------------------------------------------------------------*/
685
686 int
687 SRXAFSCB_XStatsVersion(struct rx_call *a_call, afs_int32 * a_versionP)
688 {
689     int code = 0;
690
691     XSTATS_DECLS;
692
693     RX_AFS_GLOCK();
694     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_XSTATSVERSION);
695
696     *a_versionP = AFSCB_XSTAT_VERSION;
697
698     XSTATS_END_TIME;
699
700     RX_AFS_GUNLOCK();
701
702     return (0);
703 }                               /*SRXAFSCB_XStatsVersion */
704
705
706 /*------------------------------------------------------------------------
707  * EXPORTED SRXAFSCB_GetXStats
708  *
709  * Description:
710  *      Routine called by the server-side callback RPC interface to
711  *      implement getting the given data collection from the extended
712  *      Cache Manager statistics.
713  *
714  * Arguments:
715  *      a_call              : Ptr to Rx call on which this request came in.
716  *      a_clientVersionNum  : Client version number.
717  *      a_opCode            : Desired operation.
718  *      a_serverVersionNumP : Ptr to version number to set.
719  *      a_timeP             : Ptr to time value (seconds) to set.
720  *      a_dataArray         : Ptr to variable array structure to return
721  *                            stuff in.
722  *
723  * Returns:
724  *      0 (always).
725  *
726  * Environment:
727  *      Nothing interesting.
728  *
729  * Side Effects:
730  *      As advertised.
731  *------------------------------------------------------------------------*/
732
733 int
734 SRXAFSCB_GetXStats(struct rx_call *a_call, afs_int32 a_clientVersionNum,
735                    afs_int32 a_collectionNumber, afs_int32 * a_srvVersionNumP,
736                    afs_int32 * a_timeP, AFSCB_CollData * a_dataP)
737 {
738     register int code;          /*Return value */
739     afs_int32 *dataBuffP;       /*Ptr to data to be returned */
740     afs_int32 dataBytes;        /*Bytes in data buffer */
741     XSTATS_DECLS;
742
743     RX_AFS_GLOCK();
744
745     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETXSTATS);
746
747     /*
748      * Record the time of day and the server version number.
749      */
750     *a_srvVersionNumP = AFSCB_XSTAT_VERSION;
751     *a_timeP = osi_Time();
752
753     /*
754      * Stuff the appropriate data in there (assume victory)
755      */
756     code = 0;
757
758 #ifdef AFS_NOSTATS
759     /*
760      * We're not keeping stats, so just return successfully with
761      * no data.
762      */
763     a_dataP->AFSCB_CollData_len = 0;
764     a_dataP->AFSCB_CollData_val = NULL;
765 #else
766     switch (a_collectionNumber) {
767     case AFSCB_XSTATSCOLL_CALL_INFO:
768         /*
769          * Pass back all the call-count-related data.
770          *
771          * >>> We are forced to allocate a separate area in which to
772          * >>> put this stuff in by the RPC stub generator, since it
773          * >>> will be freed at the tail end of the server stub code.
774          */
775         dataBytes = sizeof(struct afs_CMStats);
776         dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
777         memcpy((char *)dataBuffP, (char *)&afs_cmstats, dataBytes);
778         a_dataP->AFSCB_CollData_len = dataBytes >> 2;
779         a_dataP->AFSCB_CollData_val = dataBuffP;
780         break;
781
782     case AFSCB_XSTATSCOLL_PERF_INFO:
783         /*
784          * Update and then pass back all the performance-related data.
785          * Note: the only performance fields that need to be computed
786          * at this time are the number of accesses for this collection
787          * and the current server record info.
788          *
789          * >>> We are forced to allocate a separate area in which to
790          * >>> put this stuff in by the RPC stub generator, since it
791          * >>> will be freed at the tail end of the server stub code.
792          */
793         afs_stats_cmperf.numPerfCalls++;
794         afs_CountServers();
795         dataBytes = sizeof(afs_stats_cmperf);
796         dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
797         memcpy((char *)dataBuffP, (char *)&afs_stats_cmperf, dataBytes);
798         a_dataP->AFSCB_CollData_len = dataBytes >> 2;
799         a_dataP->AFSCB_CollData_val = dataBuffP;
800         break;
801
802     case AFSCB_XSTATSCOLL_FULL_PERF_INFO:
803         /*
804          * Pass back the full range of performance and statistical
805          * data available.  We have to bring the normal performance
806          * data collection up to date, then copy that data into
807          * the full collection.
808          *
809          * >>> We are forced to allocate a separate area in which to
810          * >>> put this stuff in by the RPC stub generator, since it
811          * >>> will be freed at the tail end of the server stub code.
812          */
813         afs_stats_cmperf.numPerfCalls++;
814         afs_CountServers();
815         memcpy((char *)(&(afs_stats_cmfullperf.perf)),
816                (char *)(&afs_stats_cmperf), sizeof(struct afs_stats_CMPerf));
817         afs_stats_cmfullperf.numFullPerfCalls++;
818
819         dataBytes = sizeof(afs_stats_cmfullperf);
820         dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
821         memcpy((char *)dataBuffP, (char *)(&afs_stats_cmfullperf), dataBytes);
822         a_dataP->AFSCB_CollData_len = dataBytes >> 2;
823         a_dataP->AFSCB_CollData_val = dataBuffP;
824         break;
825
826     default:
827         /*
828          * Illegal collection number.
829          */
830         a_dataP->AFSCB_CollData_len = 0;
831         a_dataP->AFSCB_CollData_val = NULL;
832         code = 1;
833     }                           /*Switch on collection number */
834 #endif /* AFS_NOSTATS */
835
836     XSTATS_END_TIME;
837
838     RX_AFS_GUNLOCK();
839
840     return (code);
841
842 }                               /*SRXAFSCB_GetXStats */
843
844
845 /*------------------------------------------------------------------------
846  * EXPORTED afs_RXCallBackServer
847  *
848  * Description:
849  *      Body of the thread supporting callback services.
850  *
851  * Arguments:
852  *      None.
853  *
854  * Returns:
855  *      0 (always).
856  *
857  * Environment:
858  *      Nothing interesting.
859  *
860  * Side Effects:
861  *      As advertised.
862  *------------------------------------------------------------------------*/
863
864 int
865 afs_RXCallBackServer(void)
866 {
867     AFS_STATCNT(afs_RXCallBackServer);
868
869     while (1) {
870         if (afs_server)
871             break;
872         afs_osi_Sleep(&afs_server);
873     }
874
875     /*
876      * Donate this process to Rx.
877      */
878     rx_ServerProc();
879     return (0);
880
881 }                               /*afs_RXCallBackServer */
882
883
884 /*------------------------------------------------------------------------
885  * EXPORTED shutdown_CB
886  *
887  * Description:
888  *      Zero out important Cache Manager data structures.
889  *
890  * Arguments:
891  *      None.
892  *
893  * Returns:
894  *      0 (always).
895  *
896  * Environment:
897  *      Nothing interesting.
898  *
899  * Side Effects:
900  *      As advertised.
901  *------------------------------------------------------------------------*/
902
903 int
904 shutdown_CB(void)
905 {
906     AFS_STATCNT(shutdown_CB);
907
908     if (afs_cold_shutdown) {
909         afs_oddCBs = afs_evenCBs = afs_allCBs = afs_allZaps = afs_oddZaps =
910             afs_evenZaps = afs_connectBacks = 0;
911     }
912
913     return (0);
914
915 }                               /*shutdown_CB */
916
917 /*------------------------------------------------------------------------
918  * EXPORTED SRXAFSCB_InitCallBackState2
919  *
920  * Description:
921  *      This routine was used in the AFS 3.5 beta release, but not anymore.
922  *      It has since been replaced by SRXAFSCB_InitCallBackState3.
923  *
924  * Arguments:
925  *      a_call : Ptr to Rx call on which this request came in.
926  *
927  * Returns:
928  *      RXGEN_OPCODE (always). 
929  *
930  * Environment:
931  *      Nothing interesting.
932  *
933  * Side Effects:
934  *      None
935  *------------------------------------------------------------------------*/
936
937 int
938 SRXAFSCB_InitCallBackState2(struct rx_call *a_call,
939                             struct interfaceAddr *addr)
940 {
941     return RXGEN_OPCODE;
942 }
943
944 /*------------------------------------------------------------------------
945  * EXPORTED SRXAFSCB_WhoAreYou
946  *
947  * Description:
948  *      Routine called by the server-side callback RPC interface to
949  *      obtain a unique identifier for the client. The server uses
950  *      this identifier to figure out whether or not two RX connections
951  *      are from the same client, and to find out which addresses go
952  *      with which clients.
953  *
954  * Arguments:
955  *      a_call : Ptr to Rx call on which this request came in.
956  *      addr: Ptr to return the list of interfaces for this client.
957  *
958  * Returns:
959  *      0 (Always)
960  *
961  * Environment:
962  *      Nothing interesting.
963  *
964  * Side Effects:
965  *      As advertised.
966  *------------------------------------------------------------------------*/
967
968 int
969 SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr)
970 {
971     int i;
972     int code = 0;
973
974     RX_AFS_GLOCK();
975
976     AFS_STATCNT(SRXAFSCB_WhoAreYou);
977
978     memset(addr, 0, sizeof(*addr));
979
980     ObtainReadLock(&afs_xinterface);
981
982     /* return all network interface addresses */
983     addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
984     addr->uuid = afs_cb_interface.uuid;
985     for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
986         addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
987         addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
988         addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
989     }
990
991     ReleaseReadLock(&afs_xinterface);
992
993     RX_AFS_GUNLOCK();
994
995     return code;
996 }
997
998
999 /*------------------------------------------------------------------------
1000  * EXPORTED SRXAFSCB_InitCallBackState3
1001  *
1002  * Description:
1003  *      Routine called by the server-side callback RPC interface to
1004  *      implement clearing all callbacks from this host.
1005  *
1006  * Arguments:
1007  *      a_call : Ptr to Rx call on which this request came in.
1008  *
1009  * Returns:
1010  *      0 (always).
1011  *
1012  * Environment:
1013  *      Nothing interesting.
1014  *
1015  * Side Effects:
1016  *      As advertised.
1017  *------------------------------------------------------------------------*/
1018
1019 int
1020 SRXAFSCB_InitCallBackState3(struct rx_call *a_call, afsUUID * a_uuid)
1021 {
1022     int code;
1023
1024     /*
1025      * TBD: Lookup the server by the UUID instead of its IP address.
1026      */
1027     code = SRXAFSCB_InitCallBackState(a_call);
1028
1029     return code;
1030 }
1031
1032
1033 /*------------------------------------------------------------------------
1034  * EXPORTED SRXAFSCB_ProbeUuid
1035  *
1036  * Description:
1037  *      Routine called by the server-side callback RPC interface to
1038  *      implement ``probing'' the Cache Manager, just making sure it's
1039  *      still there is still the same client it used to be.
1040  *
1041  * Arguments:
1042  *      a_call : Ptr to Rx call on which this request came in.
1043  *      a_uuid : Ptr to UUID that must match the client's UUID.
1044  *
1045  * Returns:
1046  *      0 if a_uuid matches the UUID for this client
1047  *      Non-zero otherwize
1048  *
1049  * Environment:
1050  *      Nothing interesting.
1051  *
1052  * Side Effects:
1053  *      As advertised.
1054  *------------------------------------------------------------------------*/
1055
1056 int
1057 SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID * a_uuid)
1058 {
1059     int code = 0;
1060     XSTATS_DECLS;
1061
1062     RX_AFS_GLOCK();
1063     AFS_STATCNT(SRXAFSCB_Probe);
1064
1065     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
1066     if (!afs_uuid_equal(a_uuid, &afs_cb_interface.uuid))
1067         code = 1;               /* failure */
1068     XSTATS_END_TIME;
1069
1070     RX_AFS_GUNLOCK();
1071
1072     return code;
1073 }
1074
1075
1076 /*------------------------------------------------------------------------
1077  * EXPORTED SRXAFSCB_GetServerPrefs
1078  *
1079  * Description:
1080  *      Routine to list server preferences used by this client.
1081  *
1082  * Arguments:
1083  *      a_call  : Ptr to Rx call on which this request came in.
1084  *      a_index : Input server index
1085  *      a_srvr_addr  : Output server address in host byte order
1086  *                     (0xffffffff on last server)
1087  *      a_srvr_rank  : Output server rank
1088  *
1089  * Returns:
1090  *      0 on success
1091  *
1092  * Environment:
1093  *      Nothing interesting.
1094  *
1095  * Side Effects:
1096  *      As advertised.
1097  *------------------------------------------------------------------------*/
1098
1099 int
1100 SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
1101                         afs_int32 * a_srvr_addr, afs_int32 * a_srvr_rank)
1102 {
1103     int i, j;
1104     struct srvAddr *sa;
1105
1106     RX_AFS_GLOCK();
1107     AFS_STATCNT(SRXAFSCB_GetServerPrefs);
1108
1109     ObtainReadLock(&afs_xserver);
1110
1111     /* Search the hash table for the server with this index */
1112     *a_srvr_addr = 0xffffffff;
1113     *a_srvr_rank = 0xffffffff;
1114     for (i = 0, j = 0; j < NSERVERS && i <= a_index; j++) {
1115         for (sa = afs_srvAddrs[j]; sa && i <= a_index; sa = sa->next_bkt, i++) {
1116             if (i == a_index) {
1117                 *a_srvr_addr = ntohl(sa->sa_ip);
1118                 *a_srvr_rank = sa->sa_iprank;
1119             }
1120         }
1121     }
1122
1123     ReleaseReadLock(&afs_xserver);
1124
1125     RX_AFS_GUNLOCK();
1126
1127     return 0;
1128 }
1129
1130
1131 /*------------------------------------------------------------------------
1132  * EXPORTED SRXAFSCB_GetCellServDB
1133  *
1134  * Description:
1135  *      Routine to list cells configured for this client
1136  *
1137  * Arguments:
1138  *      a_call  : Ptr to Rx call on which this request came in.
1139  *      a_index : Input cell index
1140  *      a_name  : Output cell name ("" on last cell)
1141  *      a_hosts : Output cell database servers in host byte order.
1142  *
1143  * Returns:
1144  *      0 on success
1145  *
1146  * Environment:
1147  *      Nothing interesting.
1148  *
1149  * Side Effects:
1150  *      As advertised.
1151  *------------------------------------------------------------------------*/
1152
1153 int
1154 SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
1155                        char **a_name, serverList * a_hosts)
1156 {
1157     afs_int32 i, j = 0;
1158     struct cell *tcell;
1159     char *t_name, *p_name = NULL;
1160
1161     RX_AFS_GLOCK();
1162     AFS_STATCNT(SRXAFSCB_GetCellServDB);
1163
1164     tcell = afs_GetCellByIndex(a_index, READ_LOCK);
1165
1166     if (!tcell) {
1167         i = 0;
1168         a_hosts->serverList_val = 0;
1169         a_hosts->serverList_len = 0;
1170     } else {
1171         p_name = tcell->cellName;
1172         for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++);
1173         i = strlen(p_name);
1174         a_hosts->serverList_val =
1175             (afs_int32 *) afs_osi_Alloc(j * sizeof(afs_int32));
1176         a_hosts->serverList_len = j;
1177         for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++)
1178             a_hosts->serverList_val[j] =
1179                 ntohl(tcell->cellHosts[j]->addr->sa_ip);
1180         afs_PutCell(tcell, READ_LOCK);
1181     }
1182
1183     t_name = (char *)afs_osi_Alloc(i + 1);
1184     if (t_name == NULL) {
1185         afs_osi_Free(a_hosts->serverList_val, (j * sizeof(afs_int32)));
1186         RX_AFS_GUNLOCK();
1187         return ENOMEM;
1188     }
1189
1190     t_name[i] = '\0';
1191     if (p_name)
1192         memcpy(t_name, p_name, i);
1193
1194     RX_AFS_GUNLOCK();
1195
1196     *a_name = t_name;
1197     return 0;
1198 }
1199
1200
1201 /*------------------------------------------------------------------------
1202  * EXPORTED SRXAFSCB_GetLocalCell
1203  *
1204  * Description:
1205  *      Routine to return name of client's local cell
1206  *
1207  * Arguments:
1208  *      a_call  : Ptr to Rx call on which this request came in.
1209  *      a_name  : Output cell name
1210  *
1211  * Returns:
1212  *      0 on success
1213  *
1214  * Environment:
1215  *      Nothing interesting.
1216  *
1217  * Side Effects:
1218  *      As advertised.
1219  *------------------------------------------------------------------------*/
1220
1221 int
1222 SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
1223 {
1224     int plen;
1225     struct cell *tcell;
1226     char *t_name, *p_name = NULL;
1227
1228     RX_AFS_GLOCK();
1229     AFS_STATCNT(SRXAFSCB_GetLocalCell);
1230
1231     /* Search the list for the primary cell. Cell number 1 is only
1232      * the primary cell is when no other cell is explicitly marked as
1233      * the primary cell.  */
1234     tcell = afs_GetPrimaryCell(READ_LOCK);
1235     if (tcell)
1236         p_name = tcell->cellName;
1237     if (p_name)
1238         plen = strlen(p_name);
1239     else
1240         plen = 0;
1241     t_name = (char *)afs_osi_Alloc(plen + 1);
1242     if (t_name == NULL) {
1243         if (tcell)
1244             afs_PutCell(tcell, READ_LOCK);
1245         RX_AFS_GUNLOCK();
1246         return ENOMEM;
1247     }
1248
1249     t_name[plen] = '\0';
1250     if (p_name)
1251         memcpy(t_name, p_name, plen);
1252
1253     RX_AFS_GUNLOCK();
1254
1255     *a_name = t_name;
1256     if (tcell)
1257         afs_PutCell(tcell, READ_LOCK);
1258     return 0;
1259 }
1260
1261
1262 /*
1263  * afs_MarshallCacheConfig - marshall client cache configuration
1264  *
1265  * PARAMETERS
1266  *
1267  * IN callerVersion - the rpc stat version of the caller.
1268  *
1269  * IN config - client cache configuration.
1270  *
1271  * OUT ptr - buffer where configuration is marshalled.
1272  *
1273  * RETURN CODES
1274  *
1275  * Returns void.
1276  */
1277 static void
1278 afs_MarshallCacheConfig(afs_uint32 callerVersion, cm_initparams_v1 * config,
1279                         afs_uint32 * ptr)
1280 {
1281     AFS_STATCNT(afs_MarshallCacheConfig);
1282     /*
1283      * We currently only support version 1.
1284      */
1285     *(ptr++) = config->nChunkFiles;
1286     *(ptr++) = config->nStatCaches;
1287     *(ptr++) = config->nDataCaches;
1288     *(ptr++) = config->nVolumeCaches;
1289     *(ptr++) = config->firstChunkSize;
1290     *(ptr++) = config->otherChunkSize;
1291     *(ptr++) = config->cacheSize;
1292     *(ptr++) = config->setTime;
1293     *(ptr++) = config->memCache;
1294 }
1295
1296
1297 /*------------------------------------------------------------------------
1298  * EXPORTED SRXAFSCB_GetCacheConfig
1299  *
1300  * Description:
1301  *      Routine to return parameters used to initialize client cache.
1302  *      Client may request any format version. Server may not return
1303  *      format version greater than version requested by client.
1304  *
1305  * Arguments:
1306  *      a_call:        Ptr to Rx call on which this request came in.
1307  *      callerVersion: Data format version desired by the client.
1308  *      serverVersion: Data format version of output data.
1309  *      configCount:   Number bytes allocated for output data.
1310  *      config:        Client cache configuration.
1311  *
1312  * Returns:
1313  *      0 on success
1314  *
1315  * Environment:
1316  *      Nothing interesting.
1317  *
1318  * Side Effects:
1319  *      As advertised.
1320  *------------------------------------------------------------------------*/
1321
1322 int
1323 SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
1324                         afs_uint32 * serverVersion, afs_uint32 * configCount,
1325                         cacheConfig * config)
1326 {
1327     afs_uint32 *t_config;
1328     size_t allocsize;
1329     cm_initparams_v1 cm_config;
1330
1331     RX_AFS_GLOCK();
1332     AFS_STATCNT(SRXAFSCB_GetCacheConfig);
1333
1334     /*
1335      * Currently only support version 1
1336      */
1337     allocsize = sizeof(cm_initparams_v1);
1338     t_config = (afs_uint32 *) afs_osi_Alloc(allocsize);
1339     if (t_config == NULL) {
1340         RX_AFS_GUNLOCK();
1341         return ENOMEM;
1342     }
1343
1344     cm_config.nChunkFiles = cm_initParams.cmi_nChunkFiles;
1345     cm_config.nStatCaches = cm_initParams.cmi_nStatCaches;
1346     cm_config.nDataCaches = cm_initParams.cmi_nDataCaches;
1347     cm_config.nVolumeCaches = cm_initParams.cmi_nVolumeCaches;
1348     cm_config.firstChunkSize = cm_initParams.cmi_firstChunkSize;
1349     cm_config.otherChunkSize = cm_initParams.cmi_otherChunkSize;
1350     cm_config.cacheSize = cm_initParams.cmi_cacheSize;
1351     cm_config.setTime = cm_initParams.cmi_setTime;
1352     cm_config.memCache = cm_initParams.cmi_memCache;
1353
1354     afs_MarshallCacheConfig(callerVersion, &cm_config, t_config);
1355
1356     *serverVersion = AFS_CLIENT_RETRIEVAL_FIRST_EDITION;
1357     *configCount = allocsize;
1358     config->cacheConfig_val = t_config;
1359     config->cacheConfig_len = allocsize / sizeof(afs_uint32);
1360
1361     RX_AFS_GUNLOCK();
1362
1363     return 0;
1364 }
1365
1366 /*------------------------------------------------------------------------
1367  * EXPORTED SRXAFSCB_FetchData
1368  *
1369  * Description:
1370  *      Routine to do third party move from a remioserver to the original
1371  *      issuer of an ArchiveData request. Presently supported only by the
1372  *      "fs" command, not by the AFS client.
1373  *
1374  * Arguments:
1375  *      rxcall:        Ptr to Rx call on which this request came in.
1376  *      Fid:           pointer to AFSFid structure.
1377  *      Fd:            File descriptor inside fs command.
1378  *      Position:      Offset in the file.
1379  *      Length:        Data length to transfer.
1380  *      TotalLength:   Pointer to total file length field
1381  *
1382  * Returns:
1383  *      0 on success
1384  *
1385  * Environment:
1386  *      Nothing interesting.
1387  *
1388  * Side Effects:
1389  *------------------------------------------------------------------------*/
1390 int
1391 SRXAFSCB_FetchData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
1392                    afs_int64 Position, afs_int64 Length,
1393                    afs_int64 * TotalLength)
1394 {
1395     return ENOSYS;
1396 }
1397
1398 /*------------------------------------------------------------------------
1399  * EXPORTED SRXAFSCB_StoreData
1400  *
1401  * Description:
1402  *      Routine to do third party move from a remioserver to the original
1403  *      issuer of a RetrieveData request. Presently supported only by the
1404  *      "fs" command, not by the AFS client.
1405  *
1406  * Arguments:
1407  *      rxcall:        Ptr to Rx call on which this request came in.
1408  *      Fid:           pointer to AFSFid structure.
1409  *      Fd:            File descriptor inside fs command.
1410  *      Position:      Offset in the file.
1411  *      Length:        Data length to transfer.
1412  *      TotalLength:   Pointer to total file length field
1413  *
1414  * Returns:
1415  *      0 on success
1416  *
1417  * Environment:
1418  *      Nothing interesting.
1419  *
1420  * Side Effects:
1421  *      As advertised.
1422  *------------------------------------------------------------------------*/
1423 int
1424 SRXAFSCB_StoreData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
1425                    afs_int64 Position, afs_int64 Length,
1426                    afs_int64 * TotalLength)
1427 {
1428     return ENOSYS;
1429 }
1430
1431 /*------------------------------------------------------------------------
1432  * EXPORTED SRXAFSCB_GetCellByNum
1433  *
1434  * Description:
1435  *      Routine to get information about a cell specified by its
1436  *      cell number (returned by GetCE/GetCE64).
1437  *
1438  * Arguments:
1439  *      a_call    : Ptr to Rx call on which this request came in.
1440  *      a_cellnum : Input cell number
1441  *      a_name    : Output cell name (one zero byte when no such cell).
1442  *      a_hosts   : Output cell database servers in host byte order.
1443  *
1444  * Returns:
1445  *      0 on success
1446  *
1447  * Environment:
1448  *      Nothing interesting.
1449  *
1450  * Side Effects:
1451  *      As advertised.
1452  *------------------------------------------------------------------------*/
1453
1454 int
1455 SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum,
1456                       char **a_name, serverList * a_hosts)
1457 {
1458     afs_int32 i, sn;
1459     struct cell *tcell;
1460
1461     RX_AFS_GLOCK();
1462     AFS_STATCNT(SRXAFSCB_GetCellByNum);
1463
1464     a_hosts->serverList_val = 0;
1465     a_hosts->serverList_len = 0;
1466
1467     tcell = afs_GetCellStale(a_cellnum, READ_LOCK);
1468     if (!tcell) {
1469         *a_name = afs_strdup("");
1470         RX_AFS_GUNLOCK();
1471         return 0;
1472     }
1473
1474     ObtainReadLock(&tcell->lock);
1475     *a_name = afs_strdup(tcell->cellName);
1476
1477     for (sn = 0; sn < AFSMAXCELLHOSTS && tcell->cellHosts[sn]; sn++);
1478     a_hosts->serverList_len = sn;
1479     a_hosts->serverList_val =
1480         (afs_int32 *) afs_osi_Alloc(sn * sizeof(afs_int32));
1481
1482     for (i = 0; i < sn; i++)
1483         a_hosts->serverList_val[i] = ntohl(tcell->cellHosts[i]->addr->sa_ip);
1484     ReleaseReadLock(&tcell->lock);
1485     afs_PutCell(tcell, READ_LOCK);
1486
1487     RX_AFS_GUNLOCK();
1488     return 0;
1489 }
1490
1491 int
1492 SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call,
1493                              struct interfaceAddr *addr,
1494                              Capabilities * capabilities)
1495 {
1496     int i;
1497     int code = 0;
1498     afs_int32 *dataBuffP;
1499     afs_int32 dataBytes;
1500
1501     RX_AFS_GLOCK();
1502
1503     AFS_STATCNT(SRXAFSCB_WhoAreYou);
1504
1505     ObtainReadLock(&afs_xinterface);
1506
1507     /* return all network interface addresses */
1508     addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
1509     addr->uuid = afs_cb_interface.uuid;
1510     for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1511         addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
1512         addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
1513         addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
1514     }
1515
1516     ReleaseReadLock(&afs_xinterface);
1517
1518     RX_AFS_GUNLOCK();
1519
1520     dataBytes = 1 * sizeof(afs_int32);
1521     dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
1522     dataBuffP[0] = CAPABILITY_ERRORTRANS;
1523     capabilities->Capabilities_len = dataBytes / sizeof(afs_int32);
1524     capabilities->Capabilities_val = dataBuffP;
1525
1526     return code;
1527 }