2 Copyright (C) 2003 - 2010 Chaskiel Grundman
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
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.
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.
27 #include <afsconfig.h>
28 #include <afs/param.h>
32 #include <afs/afsutil.h>
38 #include "afscp_internal.h"
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;
46 * Initialize the callback interface structure
51 int cm_noIPAddr; /* number of client network interfaces */
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().
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 */
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);
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
78 rx_mtu)) ? cm_NetMtu[i] : rx_mtu;
81 afs_cb_interface.numberOfInterfaces = 0;
84 afs_uuid_create(&afs_cb_interface.uuid);
86 rx_getAllAddr((afs_uint32 *) afs_cb_interface.addr_in,
87 AFS_MAX_INTERFACE_ADDR);
89 afs_cb_interface.numberOfInterfaces = 0;
91 afs_cb_interface.numberOfInterfaces = cm_noIPAddr;
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)
104 struct afscp_callback *use = NULL, *newlist;
105 struct afscp_venusfid f;
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));
117 allcallbacks[i].valid = 0;
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];
132 if (afscp_maxcallbacks >= afscp_cballoced) {
133 if (afscp_cballoced != 0)
134 afscp_cballoced = afscp_cballoced * 2;
137 newlist = realloc(allcallbacks, afscp_cballoced *
138 sizeof(struct afscp_callback));
139 if (newlist == NULL) {
142 allcallbacks = newlist;
144 use = &allcallbacks[afscp_maxcallbacks++];
147 use->server = server;
148 memmove(&use->fid, fid, sizeof(struct AFSFid));
149 memmove(&use->cb, cb, sizeof(struct AFSCallBack));
151 f.cell = afscp_CellById(server->cell);
152 memcpy(&f.fid, fid, sizeof(struct AFSFid));
155 } /* afscp_AddCallBack */
158 afscp_RemoveCallBack(const struct afscp_server *server,
159 const struct afscp_venusfid *f)
161 struct afscp_callback *cb;
165 if (server == NULL) {
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)) {
179 } /* afscp_ReturnCallBacks */
182 afscp_ReturnCallBacks(const struct afscp_server *server)
184 struct AFSCBFids theFids;
185 struct AFSCBs theCBs;
186 struct afscp_callback *cb;
187 struct afscp_venusfid f;
188 struct rx_connection *c;
196 for (i = 0; i < afscp_maxcallbacks; i++) {
197 cb = &allcallbacks[i];
198 if (cb->server != server) {
201 if (cb->cb.ExpirationTime + cb->as_of < now) {
203 f.cell = afscp_CellById(cb->server->cell);
204 memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
211 theFids.AFSCBFids_val = malloc(sizeof(struct AFSFid) * AFSCBMAX);
212 if (!theFids.AFSCBFids_val) {
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);
222 memset(theCBs.AFSCBs_val, 0,
223 sizeof(struct AFSCallBack) * AFSCBMAX);
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);
234 code = RXAFS_GiveUpCallBacks(c, &theFids, &theCBs);
240 memmove(&theFids.AFSCBFids_val[ncallbacks], &cb->fid,
241 sizeof(struct AFSFid));
242 memmove(&theCBs.AFSCBs_val[ncallbacks], &cb->cb,
243 sizeof(struct AFSCallBack));
245 theCBs.AFSCBs_val[ncallbacks].CallBackType = CB_DROPPED;
248 f.cell = afscp_CellById(cb->server->cell);
249 memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
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);
262 code = RXAFS_GiveUpCallBacks(c, &theFids, &theCBs);
266 free(theFids.AFSCBFids_val);
267 free(theCBs.AFSCBs_val);
270 } /* afscp_ReturnCallBacks */
273 afscp_ReturnAllCallBacks(void)
275 struct afscp_server *s;
278 if (allcallbacks == NULL)
280 for (i = 0; (s = afscp_ServerByIndex(i)); i++) {
281 afscp_ReturnCallBacks(s);
285 afscp_maxcallbacks = 0;
288 } /* afscp_ReturnAllCallBacks */
291 * Handle a set of callbacks from the File Server.
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.
297 * \post Returns RXGEN_SUCCESS on success, Error value otherwise.
301 SRXAFSCB_CallBack(struct rx_call * rxcall, AFSCBFids * Fids_Array,
302 AFSCBs * CallBack_Array)
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;
312 if (server == NULL) {
315 for (i = 0; i < afscp_maxcallbacks; i++) {
316 cb = &allcallbacks[i];
317 if (cb->server != server)
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))
325 f.cell = afscp_CellById(cb->server->cell);
326 memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
331 return RXGEN_SUCCESS;
332 } /*SRXAFSCB_CallBack */
335 * Initialize callback state on this ``Cache Manager''.
337 * \param[in] rxcall Ptr to the associated Rx call structure.
339 * \post Returns RXGEN_SUCCESS on success, Error value otherwise.
341 * \note This will definitely be called by the File Server (exactly once),
342 * since it will think we are another new ``Cache Manager''.
345 SRXAFSCB_InitCallBackState(struct rx_call * rxcall)
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;
354 if (server == NULL) {
357 for (i = 0; i < afscp_maxcallbacks; i++) {
358 cb = &allcallbacks[i];
359 if (cb->server != server)
362 f.cell = afscp_CellById(cb->server->cell);
363 memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
368 return RXGEN_SUCCESS;
369 } /* SRXAFSCB_InitCallBackState */
372 * Respond to a probe from the File Server.
374 * \param[in] rxcall Ptr to the associated Rx call structure.
376 * \post Returns RXGEN_SUCCESS (always)
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.
384 SRXAFSCB_Probe(struct rx_call * rxcall)
386 return RXGEN_SUCCESS;
387 } /* SRXAFSCB_Probe */
390 * Respond minimally to a request for returning the contents of
391 * a cache lock, since someone out there thinks you're a Cache
394 * \param[in] rxcall Ptr to the associated Rx call structure.
398 * \post Returns RXGEN_SUCCESS (always)
402 SRXAFSCB_GetLock(struct rx_call * rxcall, afs_int32 index, AFSDBLock * lock)
404 return RXGEN_SUCCESS;
406 } /*SRXAFSCB_GetLock */
409 * Respond minimally to a request for returning the contents of
410 * a cache entry, since someone out there thinks you're a Cache
413 * \param[in] rxcall Ptr to the associated Rx call structure.
415 * \param[out] ce Ptr to cache entry
417 * \post Returns RXGEN_SUCCESS (always)
421 SRXAFSCB_GetCE(struct rx_call * rxcall, afs_int32 index, AFSDBCacheEntry * ce)
423 return RXGEN_SUCCESS;
424 } /* SRXAFSCB_GetCE */
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())
431 * \param[in] rxcall Ptr to the associated Rx call structure.
433 * \param[out] ce Ptr to cache entry
435 * \post Returns RXGEN_SUCCESS (always)
439 SRXAFSCB_GetCE64(struct rx_call * rxcall, afs_int32 index,
440 AFSDBCacheEntry64 * ce)
442 return RXGEN_SUCCESS;
443 } /*SRXAFSCB_GetCE */
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.
450 * \param[in] rxcall Ptr to the associated Rx call structure
451 * \param[out] versionNumberP
453 * \post Returns RXGEN_SUCCESS (always)
457 SRXAFSCB_XStatsVersion(struct rx_call * rxcall, afs_int32 * versionNumberP)
459 return RXGEN_SUCCESS;
460 } /*SRXAFSCB_XStatsVersion */
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.
467 * \param[in] z_call Ptr to the associated Rx call structure
468 * \param[in] clientVersionNumber
469 * \param[in] collectionNumber
470 * \param[out] srvVersionNumberP
474 * \post Returns RXGEN_SUCCESS (always)
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)
482 return RXGEN_SUCCESS;
483 } /*SRXAFSCB_GetXStats */
486 * This routine was used in the AFS 3.5 beta release, but not anymore.
487 * It has since been replaced by SRXAFSCB_InitCallBackState3.
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
492 * \post Returns RXGEN_SUCCESS (always)
496 SRXAFSCB_InitCallBackState2(struct rx_call * rxcall,
497 struct interfaceAddr * addr)
500 } /* SRXAFSCB_InitCallBackState2 */
504 * \param rxcall Ptr to the associated Rx call structure.
506 * \post Returns RXGEN_SUCCESS (always)
510 SRXAFSCB_TellMeAboutYourself(struct rx_call * a_call,
511 struct interfaceAddr * addr,
512 Capabilities * capabilities)
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 */
523 cm_noIPAddr = CM_MAXINTERFACE_ADDR;
524 code = syscfg_GetIFInfo(&cm_noIPAddr,
525 cm_IPAddr, cm_SubnetMask, cm_NetMtu, cm_NetFlags);
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
535 rx_mtu)) ? cm_NetMtu[i] : rx_mtu;
538 addr->numberOfInterfaces = 0;
541 if (a_call && addr) {
544 *addr = afs_cb_interface;
547 if (capabilities != NULL) {
548 afs_uint32 *dataBuffP;
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;
557 return RXGEN_SUCCESS;
558 } /* SRXAFSCB_TellMeAboutYourself */
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.
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
570 * \post Returns output of TellMeAboutYourself (which
571 * should be RXGEN_SUCCESS).
575 SRXAFSCB_WhoAreYou(struct rx_call * rxcall, struct interfaceAddr * addr)
577 return SRXAFSCB_TellMeAboutYourself(rxcall, addr, NULL);
578 } /* SRXAFSCB_WhoAreYou */
581 * Routine called by the server-side callback RPC interface to
582 * implement clearing all callbacks from this host.
584 * \param[in] rxcall Ptr to the associated Rx call structure.
585 * \param[in] serverUuid Ptr to UUID
587 * \post Returns RXGEN_SUCCESS (always)
591 SRXAFSCB_InitCallBackState3(struct rx_call * rxcall, afsUUID * serverUuid)
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;
600 if (server == NULL) {
603 for (i = 0; i < afscp_maxcallbacks; i++) {
604 cb = &allcallbacks[i];
605 if (cb->server != server)
608 f.cell = afscp_CellById(cb->server->cell);
609 memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
614 return RXGEN_SUCCESS;
615 } /* SRXAFSCB_InitCallBackState3 */
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.
622 * \param rxcall Ptr to the associated Rx call structure.
623 * \param clientUuid Ptr to UUID that must match the client's UUID
625 * \post Returns RXGEN_SUCCESS (always)
629 SRXAFSCB_ProbeUuid(struct rx_call * rxcall, afsUUID * clientUuid)
634 if (!afs_uuid_equal(clientUuid, &afs_cb_interface.uuid))
635 code = 1; /* failure */
637 } /* SRXAFSCB_ProbeUuid */
640 * Routine to list server preferences used by this client.
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
647 * \post Returns RXGEN_SUCCESS (always)
651 SRXAFSCB_GetServerPrefs(struct rx_call * a_call, afs_int32 a_index,
652 afs_int32 * a_srvr_addr, afs_int32 * a_srvr_rank)
654 *a_srvr_addr = 0xffffffff;
655 *a_srvr_rank = 0xffffffff;
656 return RXGEN_SUCCESS;
657 } /* SRXAFSCB_GetServerPrefs */
660 * Routine to list cells configured for this client
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
667 * \post Returns RXGEN_OPCODE (always)
671 SRXAFSCB_GetCellServDB(struct rx_call * a_call, afs_int32 a_index,
672 char **a_name, afs_int32 * a_hosts)
675 } /* SRXAFSCB_GetCellServDB */
678 * Routine to return name of client's local cell
680 * \param[in] a_call Ptr to Rx call on which this request came in.
681 * \param[out] a_name Output cell name
683 * \post Returns RXGEN_SUCCESS (always)
687 SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
690 } /* SRXAFSCB_GetLocalCell */
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.
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.
703 * \post Returns RXGEN_SUCCESS (always)
707 SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
708 afs_uint32 * serverVersion, afs_uint32 * configCount,
709 cacheConfig * config)
712 } /* SRXAFSCB_GetCacheConfig */
717 * \param[in] rxcall Ptr to the associated Rx call structure.
719 * \post Returns RXGEN_OPCODE (always)
723 SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_index,
724 char **a_name, afs_int32 * a_hosts)
727 } /* SRXAFSCB_GetCellByNum */