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