b5fde52b57126d27a0f8d5d95d5a39d66dc79b51
[openafs.git] / src / libafscp / afscp_callback.c
1 /* AUTORIGHTS
2 Copyright (C) 2003 - 2010 Chaskiel Grundman
3 All rights reserved
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
9 1. Redistributions of source code must retain the above copyright
10    notice, this list of conditions and the following disclaimer.
11
12 2. Redistributions in binary form must reproduce the above copyright
13    notice, this list of conditions and the following disclaimer in the
14    documentation and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 #include <afsconfig.h>
28 #include <afs/param.h>
29
30 #include <roken.h>
31
32 #ifdef AFS_NT40_ENV
33 #include <windows.h>
34 #include <rpc.h>
35 #include <afs/cm_server.h>
36 #include <WINNT/syscfg.h>
37 #endif
38
39 #include <afs/afsutil.h>
40 #include "afscp.h"
41 #include "afscp_internal.h"
42
43 int afs_cb_inited = 0;
44 struct interfaceAddr afs_cb_interface;
45 static int afscp_maxcallbacks = 0, afscp_cballoced = 0;
46 struct afscp_callback *allcallbacks = NULL;
47
48 /*!
49  * Initialize the callback interface structure
50  */
51 static int
52 init_afs_cb(void)
53 {
54     int cm_noIPAddr;            /* number of client network interfaces */
55 #ifdef AFS_NT40_ENV
56     /*
57      * This Windows section was pulled in from changes to src/venus/afsio.c but is
58      * untested here and may be unnecessary if rx_getAllAddr() can be used on that
59      * platform.  However, there was already an ifdef here surrounding UuidCreate().
60      */
61     long rx_mtu = -1;
62     int code;
63     int cm_IPAddr[CM_MAXINTERFACE_ADDR];        /* client's IP address in host order */
64     int cm_SubnetMask[CM_MAXINTERFACE_ADDR];    /* client's subnet mask in host order */
65     int cm_NetMtu[CM_MAXINTERFACE_ADDR];        /* client's MTU sizes */
66     int cm_NetFlags[CM_MAXINTERFACE_ADDR];      /* network flags */
67     int i;
68
69     UuidCreate((UUID *) & afs_cb_interface.uuid);
70     cm_noIPAddr = CM_MAXINTERFACE_ADDR;
71     code = syscfg_GetIFInfo(&cm_noIPAddr,
72                             cm_IPAddr, cm_SubnetMask, cm_NetMtu, cm_NetFlags);
73     if (code > 0) {
74         /* return all network interface addresses */
75         afs_cb_interface.numberOfInterfaces = cm_noIPAddr;
76         for (i = 0; i < cm_noIPAddr; i++) {
77             afs_cb_interface.addr_in[i] = cm_IPAddr[i];
78             afs_cb_interface.subnetmask[i] = cm_SubnetMask[i];
79             afs_cb_interface.mtu[i] = (rx_mtu == -1
80                                        || (rx_mtu != -1
81                                            && cm_NetMtu[i] <
82                                            rx_mtu)) ? cm_NetMtu[i] : rx_mtu;
83         }
84     } else {
85         afs_cb_interface.numberOfInterfaces = 0;
86     }
87 #else
88     afs_uuid_create(&afs_cb_interface.uuid);
89     cm_noIPAddr =
90         rx_getAllAddr((afs_uint32 *) afs_cb_interface.addr_in,
91                       AFS_MAX_INTERFACE_ADDR);
92     if (cm_noIPAddr < 0)
93         afs_cb_interface.numberOfInterfaces = 0;
94     else
95         afs_cb_interface.numberOfInterfaces = cm_noIPAddr;
96 #endif
97     afs_cb_inited = 1;
98     return 0;
99 }                               /* init_afs_cb */
100
101 int
102 afscp_FindCallBack(const struct afscp_venusfid *f, const struct afscp_server *server, struct afscp_callback *ret)
103 {
104     int i;
105     struct afscp_callback *use = NULL, *cb;
106     time_t now;
107     struct afscp_venusfid fid;
108
109     ret = NULL;
110
111     time(&now);
112     for (i = 0; i < afscp_maxcallbacks; i++) {
113         cb = &allcallbacks[i];
114         if ((f->fid.Volume == cb->fid.Volume) &&
115             (f->fid.Vnode == cb->fid.Vnode) &&
116             (f->fid.Unique == cb->fid.Unique)) {
117             if (server && (cb->server != server))
118                 continue;
119             use = cb;
120             break;
121         }
122     }
123     if (!use)
124         return -1;
125
126     if (use->cb.ExpirationTime + use->as_of < now) {
127         if (use->valid) {
128             fid.cell = afscp_CellById(use->server->cell);
129             memcpy(&fid.fid, &use->fid, sizeof(struct AFSFid));
130             _StatInvalidate(&fid);
131         }
132         use->valid = 0;
133     }
134
135     if (use->valid)
136         ret = use;
137     else
138         return -1;
139
140     return 0;
141 }
142
143 int
144 afscp_AddCallBack(const struct afscp_server *server,
145                   const struct AFSFid *fid,
146                   const struct AFSFetchStatus *fst,
147                   const struct AFSCallBack *cb, const time_t as_of)
148 {
149     int i;
150     struct afscp_callback *use = NULL, *newlist;
151     struct afscp_venusfid f;
152     time_t now;
153     
154     time(&now);
155     
156     for (i = 0; i < afscp_maxcallbacks; i++) {
157         if (allcallbacks[i].cb.ExpirationTime + allcallbacks[i].as_of < now) {
158             if (allcallbacks[i].valid) {
159                 f.cell = afscp_CellById(allcallbacks[i].server->cell);
160                 memcpy(&f.fid, &allcallbacks[i].fid, sizeof(struct AFSFid));
161                 _StatInvalidate(&f);
162             }
163             allcallbacks[i].valid = 0;
164         }
165         
166         if (allcallbacks[i].valid == 0)
167             use = &allcallbacks[i];
168         if ((allcallbacks[i].server == server) &&
169             (fid->Volume == allcallbacks[i].fid.Volume) &&
170             (fid->Vnode == allcallbacks[i].fid.Vnode) &&
171             (fid->Unique == allcallbacks[i].fid.Unique)) {
172             use = &allcallbacks[i];
173             break;
174         }
175     }
176     if (use == NULL) {
177         if (afscp_maxcallbacks >= afscp_cballoced) {
178             if (afscp_cballoced != 0)
179                 afscp_cballoced = afscp_cballoced * 2;
180             else
181                 afscp_cballoced = 4;
182             newlist = realloc(allcallbacks, afscp_cballoced *
183                               sizeof(struct afscp_callback));
184             if (newlist == NULL) {
185                 return -1;
186             }
187             allcallbacks = newlist;
188         }
189         use = &allcallbacks[afscp_maxcallbacks++];
190     }
191     use->valid = 1;
192     use->server = server;
193     memmove(&use->fid, fid, sizeof(struct AFSFid));
194     memmove(&use->cb, cb, sizeof(struct AFSCallBack));
195     use->as_of = as_of;
196     f.cell = afscp_CellById(server->cell);
197     memcpy(&f.fid, fid, sizeof(struct AFSFid));
198     _StatStuff(&f, fst);
199     return 0;
200 }                               /* afscp_AddCallBack */
201
202 int
203 afscp_RemoveCallBack(const struct afscp_server *server,
204                      const struct afscp_venusfid *f)
205 {
206     struct afscp_callback *cb;
207     int i;
208
209     _StatInvalidate(f);
210     if (server == NULL) {
211         return 0;
212     }
213     for (i = 0; i < afscp_maxcallbacks; i++) {
214         cb = &allcallbacks[i];
215         if ((cb->server == server) &&
216             (f->fid.Volume == cb->fid.Volume) &&
217             (f->fid.Vnode == cb->fid.Vnode) &&
218             (f->fid.Unique == cb->fid.Unique)) {
219             cb->valid = 0;
220             break;
221         }
222     }
223     return 0;
224 }                               /* afscp_ReturnCallBacks */
225
226 int
227 afscp_ReturnCallBacks(const struct afscp_server *server)
228 {
229     struct AFSCBFids theFids;
230     struct AFSCBs theCBs;
231     struct afscp_callback *cb;
232     struct afscp_venusfid f;
233     struct rx_connection *c;
234     int inited = 0;
235     int ncallbacks = 0;
236     int i, j, code;
237     time_t now;
238
239     time(&now);
240
241     for (i = 0; i < afscp_maxcallbacks; i++) {
242         cb = &allcallbacks[i];
243         if (cb->server != server) {
244             continue;
245         }
246         if (cb->cb.ExpirationTime + cb->as_of < now) {
247             if (cb->valid) {
248                 f.cell = afscp_CellById(cb->server->cell);
249                 memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
250                 _StatInvalidate(&f);
251             }
252             cb->valid = 0;
253             continue;
254         }
255         if (!inited) {
256             theFids.AFSCBFids_val = malloc(sizeof(struct AFSFid) * AFSCBMAX);
257             if (!theFids.AFSCBFids_val) {
258                 return -1;
259             }
260             memset(theFids.AFSCBFids_val, 0,
261                    sizeof(struct AFSFid) * AFSCBMAX);
262             theCBs.AFSCBs_val = malloc(sizeof(struct AFSCallBack) * AFSCBMAX);
263             if (!theCBs.AFSCBs_val) {
264                 free(theFids.AFSCBFids_val);
265                 return -1;
266             }
267             memset(theCBs.AFSCBs_val, 0,
268                    sizeof(struct AFSCallBack) * AFSCBMAX);
269             inited = 1;
270         }
271
272         if (ncallbacks == AFSCBMAX) {
273             theFids.AFSCBFids_len = ncallbacks;
274             theCBs.AFSCBs_len = ncallbacks;
275             for (j = 0; j < server->naddrs; j++) {
276                 c = afscp_ServerConnection(server, j);
277                 if (c == NULL)
278                     break;
279                 code = RXAFS_GiveUpCallBacks(c, &theFids, &theCBs);
280                 if (code == 0)
281                     break;
282             }
283             ncallbacks = 0;
284         }
285         memmove(&theFids.AFSCBFids_val[ncallbacks], &cb->fid,
286                 sizeof(struct AFSFid));
287         memmove(&theCBs.AFSCBs_val[ncallbacks], &cb->cb,
288                 sizeof(struct AFSCallBack));
289
290         theCBs.AFSCBs_val[ncallbacks].CallBackType = CB_DROPPED;
291         ncallbacks++;
292         if (cb->valid) {
293             f.cell = afscp_CellById(cb->server->cell);
294             memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
295             _StatInvalidate(&f);
296         }
297
298         cb->valid = 0;
299     }
300     if (ncallbacks > 0) {
301         theFids.AFSCBFids_len = ncallbacks;
302         theCBs.AFSCBs_len = ncallbacks;
303         for (j = 0; j < server->naddrs; j++) {
304             c = afscp_ServerConnection(server, j);
305             if (c == NULL)
306                 break;
307             code = RXAFS_GiveUpCallBacks(c, &theFids, &theCBs);
308             if (code == 0)
309                 break;
310         }
311         free(theFids.AFSCBFids_val);
312         free(theCBs.AFSCBs_val);
313     }
314     return 0;
315 }                               /* afscp_ReturnCallBacks */
316
317 int
318 afscp_ReturnAllCallBacks(void)
319 {
320     struct afscp_server *s;
321     int i;
322
323     if (allcallbacks == NULL)
324         return 0;
325     for (i = 0; (s = afscp_ServerByIndex(i)); i++) {
326         afscp_ReturnCallBacks(s);
327     }
328     free(allcallbacks);
329     allcallbacks = NULL;
330     afscp_maxcallbacks = 0;
331     afscp_cballoced = 0;
332     return 0;
333 }                               /* afscp_ReturnAllCallBacks */
334
335 /*!
336  * Handle a set of callbacks from the File Server.
337  *
338  * \param[in]   rxcall          Ptr to the associated Rx call structure.
339  * \param[in]   Fids_Array      Ptr to the set of Fids.
340  * \param[in]   CallBacks_Array Ptr to the set of callbacks.
341  *
342  * \post Returns RXGEN_SUCCESS on success, Error value otherwise.
343  *
344  */
345 afs_int32
346 SRXAFSCB_CallBack(struct rx_call * rxcall, AFSCBFids * Fids_Array,
347                   AFSCBs * CallBack_Array)
348 {
349     struct rx_connection *rxconn = rx_ConnectionOf(rxcall);
350     struct rx_peer *rxpeer = rx_PeerOf(rxconn);
351     struct afscp_server *server = afscp_AnyServerByAddr(rx_HostOf(rxpeer));
352     struct afscp_callback *cb;
353     struct afscp_venusfid f;
354     struct AFSFid *fid;
355     int i;
356     unsigned int j;
357
358     if (server == NULL) {
359         return 0;
360     }
361     for (i = 0; i < afscp_maxcallbacks; i++) {
362         cb = &allcallbacks[i];
363         if (cb->server != server)
364             continue;
365         for (j = 0; j < Fids_Array->AFSCBFids_len; j++) {
366             fid = &Fids_Array->AFSCBFids_val[j];
367             if ((fid->Volume == cb->fid.Volume) &&
368                 (fid->Vnode == cb->fid.Vnode) &&
369                 (fid->Unique == cb->fid.Unique))
370                 cb->valid = 0;
371             f.cell = afscp_CellById(cb->server->cell);
372             memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
373             _StatInvalidate(&f);
374         }
375     }
376
377     return RXGEN_SUCCESS;
378 }                               /*SRXAFSCB_CallBack */
379
380 /*!
381  * Initialize callback state on this ``Cache Manager''.
382  *
383  * \param[in]   rxcall  Ptr to the associated Rx call structure.
384  *
385  * \post Returns RXGEN_SUCCESS on success, Error value otherwise.
386  *
387  * \note This will definitely be called by the File Server (exactly once),
388  *       since it will think we are another new ``Cache Manager''.
389  */
390 afs_int32
391 SRXAFSCB_InitCallBackState(struct rx_call * rxcall)
392 {
393     struct rx_connection *rxconn = rx_ConnectionOf(rxcall);
394     struct rx_peer *rxpeer = rx_PeerOf(rxconn);
395     struct afscp_server *server = afscp_AnyServerByAddr(rx_HostOf(rxpeer));
396     struct afscp_callback *cb;
397     struct afscp_venusfid f;
398     int i;
399
400     if (server == NULL) {
401         return 0;
402     }
403     for (i = 0; i < afscp_maxcallbacks; i++) {
404         cb = &allcallbacks[i];
405         if (cb->server != server)
406             continue;
407         if (cb->valid) {
408             f.cell = afscp_CellById(cb->server->cell);
409             memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
410             _StatInvalidate(&f);
411         }
412         cb->valid = 0;
413     }
414     return RXGEN_SUCCESS;
415 }                               /* SRXAFSCB_InitCallBackState */
416
417 /*!
418  * Respond to a probe from the File Server.
419  *
420  * \param[in] rxcall    Ptr to the associated Rx call structure.
421  *
422  * \post Returns RXGEN_SUCCESS (always)
423  *
424  * \note If a File Server doesn't hear from you every so often, it will
425  *       send you a probe to make sure you're there, just like any other
426  *       ``Cache Manager'' it's keeping track of.
427  *
428  */
429 afs_int32
430 SRXAFSCB_Probe(struct rx_call * rxcall)
431 {
432     return RXGEN_SUCCESS;
433 }                               /* SRXAFSCB_Probe */
434
435 /*!
436  * Respond minimally to a request for returning the contents of
437  * a cache lock, since someone out there thinks you're a Cache
438  * Manager.
439  *
440  * \param[in]   rxcall  Ptr to the associated Rx call structure.
441  * \param[in]   index
442  * \param[out]  lock
443  *
444  * \post Returns RXGEN_SUCCESS (always)
445  *
446  */
447 afs_int32
448 SRXAFSCB_GetLock(struct rx_call * rxcall, afs_int32 index, AFSDBLock * lock)
449 {
450     return RXGEN_SUCCESS;
451
452 }                               /*SRXAFSCB_GetLock */
453
454 /*!
455  * Respond minimally to a request for returning the contents of
456  * a cache entry, since someone out there thinks you're a Cache
457  * Manager.
458  *
459  * \param[in]   rxcall  Ptr to the associated Rx call structure.
460  * \param[in]   index
461  * \param[out]  ce      Ptr to cache entry
462  *
463  * \post Returns RXGEN_SUCCESS (always)
464  *
465  */
466 afs_int32
467 SRXAFSCB_GetCE(struct rx_call * rxcall, afs_int32 index, AFSDBCacheEntry * ce)
468 {
469     return RXGEN_SUCCESS;
470 }                               /* SRXAFSCB_GetCE */
471
472 /*!
473  * Respond minimally to a request for returning the contents of
474  * a cache entry, since someone out there thinks you're a Cache
475  * Manager. (64-bit version, though same as SRXAFSCB_GetCE())
476  *
477  * \param[in]   rxcall  Ptr to the associated Rx call structure.
478  * \param[in]   index
479  * \param[out]  ce      Ptr to cache entry
480  *
481  * \post Returns RXGEN_SUCCESS (always)
482  *
483  */
484 afs_int32
485 SRXAFSCB_GetCE64(struct rx_call * rxcall, afs_int32 index,
486                  AFSDBCacheEntry64 * ce)
487 {
488     return RXGEN_SUCCESS;
489 }                               /*SRXAFSCB_GetCE */
490
491 /*!
492  * Respond minimally to a request for fetching the version of
493  * extended Cache Manager statistics offered, since someone out
494  * there thinks you're a Cache Manager.
495  *
496  * \param[in]   rxcall          Ptr to the associated Rx call structure
497  * \param[out]  versionNumberP
498  *
499  * \post Returns RXGEN_SUCCESS (always)
500  *
501  */
502 afs_int32
503 SRXAFSCB_XStatsVersion(struct rx_call * rxcall, afs_int32 * versionNumberP)
504 {
505     return RXGEN_SUCCESS;
506 }                               /*SRXAFSCB_XStatsVersion */
507
508 /*!
509  * Respond minimally to a request for returning extended
510  * statistics for a Cache Manager, since someone out there thinks
511  * you're a Cache Manager.
512  *
513  * \param[in]   z_call                  Ptr to the associated Rx call structure
514  * \param[in]   clientVersionNumber
515  * \param[in]   collectionNumber
516  * \param[out]  srvVersionNumberP
517  * \param[out]  timeP
518  * \param[out]  dataP
519  *
520  * \post Returns RXGEN_SUCCESS (always)
521  *
522  */
523 afs_int32
524 SRXAFSCB_GetXStats(struct rx_call * z_call, afs_int32 clientVersionNumber,
525                    afs_int32 collectionNumber, afs_int32 * srvVersionNumberP,
526                    afs_int32 * timeP, AFSCB_CollData * dataP)
527 {
528     return RXGEN_SUCCESS;
529 }                               /*SRXAFSCB_GetXStats */
530
531 /*!
532  * This routine was used in the AFS 3.5 beta release, but not anymore.
533  * It has since been replaced by SRXAFSCB_InitCallBackState3.
534  *
535  * \param[in]   rxcall  Ptr to the associated Rx call structure.
536  * \param[out]  addr    Ptr to return the list of interfaces for this client
537  *
538  * \post Returns RXGEN_SUCCESS (always)
539  *
540  */
541 afs_int32
542 SRXAFSCB_InitCallBackState2(struct rx_call * rxcall,
543                             struct interfaceAddr * addr)
544 {
545     return RXGEN_OPCODE;
546 }                               /* SRXAFSCB_InitCallBackState2 */
547
548 /*!
549  *
550  * \param       rxcall  Ptr to the associated Rx call structure.
551  *
552  * \post Returns RXGEN_SUCCESS (always)
553  *
554  */
555 afs_int32
556 SRXAFSCB_TellMeAboutYourself(struct rx_call * a_call,
557                              struct interfaceAddr * addr,
558                              Capabilities * capabilities)
559 {
560 #ifdef AFS_NT40_ENV
561     int code;
562     int cm_noIPAddr;            /* number of client network interfaces */
563     int cm_IPAddr[CM_MAXINTERFACE_ADDR];        /* client's IP address in host order */
564     int cm_SubnetMask[CM_MAXINTERFACE_ADDR];    /* client's subnet mask in host order */
565     int cm_NetMtu[CM_MAXINTERFACE_ADDR];        /* client's MTU sizes */
566     int cm_NetFlags[CM_MAXINTERFACE_ADDR];      /* network flags */
567     int i;
568
569     cm_noIPAddr = CM_MAXINTERFACE_ADDR;
570     code = syscfg_GetIFInfo(&cm_noIPAddr,
571                             cm_IPAddr, cm_SubnetMask, cm_NetMtu, cm_NetFlags);
572     if (code > 0) {
573         /* return all network interface addresses */
574         addr->numberOfInterfaces = cm_noIPAddr;
575         for (i = 0; i < cm_noIPAddr; i++) {
576             addr->addr_in[i] = cm_IPAddr[i];
577             addr->subnetmask[i] = cm_SubnetMask[i];
578             addr->mtu[i] = cm_NetMtu[i];
579         }
580     } else {
581         addr->numberOfInterfaces = 0;
582     }
583 #else
584     if (a_call && addr) {
585         if (!afs_cb_inited)
586             init_afs_cb();
587         *addr = afs_cb_interface;
588     }
589 #endif
590     if (capabilities != NULL) {
591         afs_uint32 *dataBuffP;
592         afs_int32 dataBytes;
593
594         dataBytes = 1 * sizeof(afs_uint32);
595         dataBuffP = (afs_uint32 *) xdr_alloc(dataBytes);
596         dataBuffP[0] = CLIENT_CAPABILITY_ERRORTRANS;
597         capabilities->Capabilities_len = dataBytes / sizeof(afs_uint32);
598         capabilities->Capabilities_val = dataBuffP;
599     }
600     return RXGEN_SUCCESS;
601 }                               /* SRXAFSCB_TellMeAboutYourself */
602
603 /*!
604  * Routine called by the server-side callback RPC interface to
605  * obtain a unique identifier for the client. The server uses
606  * this identifier to figure out whether or not two RX connections
607  * are from the same client, and to find out which addresses go
608  * with which clients.
609  *
610  * \param[in]   rxcall  Ptr to the associated Rx call structure.
611  * \param[out]  addr    Ptr to return the list of interfaces for this client
612  *
613  * \post Returns output of TellMeAboutYourself (which
614  *       should be RXGEN_SUCCESS).
615  *
616  */
617 afs_int32
618 SRXAFSCB_WhoAreYou(struct rx_call * rxcall, struct interfaceAddr * addr)
619 {
620     return SRXAFSCB_TellMeAboutYourself(rxcall, addr, NULL);
621 }                               /* SRXAFSCB_WhoAreYou */
622
623 /*!
624  * Routine called by the server-side callback RPC interface to
625  * implement clearing all callbacks from this host.
626  *
627  * \param[in]   rxcall          Ptr to the associated Rx call structure.
628  * \param[in]   serverUuid      Ptr to UUID
629  *
630  * \post Returns RXGEN_SUCCESS (always)
631  *
632  */
633 afs_int32
634 SRXAFSCB_InitCallBackState3(struct rx_call * rxcall, afsUUID * serverUuid)
635 {
636     struct rx_connection *rxconn = rx_ConnectionOf(rxcall);
637     struct rx_peer *rxpeer = rx_PeerOf(rxconn);
638     struct afscp_server *server = afscp_AnyServerByAddr(rx_HostOf(rxpeer));
639     struct afscp_callback *cb;
640     struct afscp_venusfid f;
641     int i;
642
643     if (server == NULL) {
644         return 0;
645     }
646     for (i = 0; i < afscp_maxcallbacks; i++) {
647         cb = &allcallbacks[i];
648         if (cb->server != server)
649             continue;
650         if (cb->valid) {
651             f.cell = afscp_CellById(cb->server->cell);
652             memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
653             _StatInvalidate(&f);
654         }
655         cb->valid = 0;
656     }
657     return RXGEN_SUCCESS;
658 }                               /* SRXAFSCB_InitCallBackState3 */
659
660 /*!
661  * Routine called by the server-side callback RPC interface to
662  * implement ``probing'' the Cache Manager, just making sure it's
663  * still there is still the same client it used to be.
664  *
665  * \param       rxcall          Ptr to the associated Rx call structure.
666  * \param       clientUuid      Ptr to UUID that must match the client's UUID
667  *
668  * \post Returns RXGEN_SUCCESS (always)
669  *
670  */
671 afs_int32
672 SRXAFSCB_ProbeUuid(struct rx_call * rxcall, afsUUID * clientUuid)
673 {
674     int code = 0;
675     if (!afs_cb_inited)
676         init_afs_cb();
677     if (!afs_uuid_equal(clientUuid, &afs_cb_interface.uuid))
678         code = 1;               /* failure */
679     return code;
680 }                               /* SRXAFSCB_ProbeUuid */
681
682 /*!
683  * Routine to list server preferences used by this client.
684  *
685  * \param[in]   a_call          Ptr to Rx call on which this request came in.
686  * \param[in]   a_index         Input server index
687  * \param[out]  a_srvr_addr     Output server address (0xffffffff on last server)
688  * \param[out]  a_srvr_rank     Output server rank
689  *
690  * \post Returns RXGEN_SUCCESS (always)
691  *
692  */
693 afs_int32
694 SRXAFSCB_GetServerPrefs(struct rx_call * a_call, afs_int32 a_index,
695                         afs_int32 * a_srvr_addr, afs_int32 * a_srvr_rank)
696 {
697     *a_srvr_addr = 0xffffffff;
698     *a_srvr_rank = 0xffffffff;
699     return RXGEN_SUCCESS;
700 }                               /* SRXAFSCB_GetServerPrefs */
701
702 /*!
703  * Routine to list cells configured for this client
704  *
705  * \param[in]   a_call  Ptr to Rx call on which this request came in.
706  * \param[in]   a_index Input cell index
707  * \param[out]  a_name  Output cell name ("" on last cell)
708  * \param[out]  a_hosts Output cell database servers
709  *
710  * \post Returns RXGEN_OPCODE (always)
711  *
712  */
713 afs_int32
714 SRXAFSCB_GetCellServDB(struct rx_call * a_call, afs_int32 a_index,
715                        char **a_name, afs_int32 * a_hosts)
716 {
717     return RXGEN_OPCODE;
718 }                               /* SRXAFSCB_GetCellServDB */
719
720 /*!
721  * Routine to return name of client's local cell
722  *
723  * \param[in]   a_call  Ptr to Rx call on which this request came in.
724  * \param[out]  a_name  Output cell name
725  *
726  * \post Returns RXGEN_SUCCESS (always)
727  *
728  */
729 int
730 SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
731 {
732     return RXGEN_OPCODE;
733 }                               /* SRXAFSCB_GetLocalCell */
734
735 /*!
736  * Routine to return parameters used to initialize client cache.
737  * Client may request any format version. Server may not return
738  * format version greater than version requested by client.
739  *
740  * \param[in]   a_call          Ptr to Rx call on which this request came in.
741  * \param[in]   callerVersion   Data format version desired by the client.
742  * \param[out]  serverVersion   Data format version of output data.
743  * \param[out]  configCount     Number bytes allocated for output data.
744  * \param[out]  config          Client cache configuration.
745  *
746  * \post Returns RXGEN_SUCCESS (always)
747  *
748  */
749 int
750 SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
751                         afs_uint32 * serverVersion, afs_uint32 * configCount,
752                         cacheConfig * config)
753 {
754     return RXGEN_OPCODE;
755 }                               /* SRXAFSCB_GetCacheConfig */
756
757 /*!
758
759  *
760  * \param[in]   rxcall  Ptr to the associated Rx call structure.
761  *
762  * \post Returns RXGEN_OPCODE (always)
763  *
764  */
765 int
766 SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_index,
767                       char **a_name, afs_int32 * a_hosts)
768 {
769     return RXGEN_OPCODE;
770 }                               /* SRXAFSCB_GetCellByNum */