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