backport to buster
[hcoop/debian/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 */