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