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