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