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