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>
35 #include <afs/cm_server.h>
36 #include <WINNT/syscfg.h>
39 #include <afs/afsutil.h>
41 #include "afscp_internal.h"
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;
49 * Initialize the callback interface structure
54 int cm_noIPAddr; /* number of client network interfaces */
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().
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 */
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);
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
82 rx_mtu)) ? cm_NetMtu[i] : rx_mtu;
85 afs_cb_interface.numberOfInterfaces = 0;
88 afs_uuid_create(&afs_cb_interface.uuid);
90 rx_getAllAddr((afs_uint32 *) afs_cb_interface.addr_in,
91 AFS_MAX_INTERFACE_ADDR);
93 afs_cb_interface.numberOfInterfaces = 0;
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]);
106 afscp_FindCallBack(const struct afscp_venusfid *f, const struct afscp_server *server, struct afscp_callback *ret)
109 struct afscp_callback *use = NULL, *cb;
111 struct afscp_venusfid fid;
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))
130 if (use->cb.ExpirationTime + use->as_of < now) {
132 fid.cell = afscp_CellById(use->server->cell);
133 memcpy(&fid.fid, &use->fid, sizeof(struct AFSFid));
134 _StatInvalidate(&fid);
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)
154 struct afscp_callback *use = NULL, *newlist;
155 struct afscp_venusfid f;
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));
167 allcallbacks[i].valid = 0;
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];
181 if (afscp_maxcallbacks >= afscp_cballoced) {
182 if (afscp_cballoced != 0)
183 afscp_cballoced = afscp_cballoced * 2;
186 newlist = realloc(allcallbacks, afscp_cballoced *
187 sizeof(struct afscp_callback));
188 if (newlist == NULL) {
191 allcallbacks = newlist;
193 use = &allcallbacks[afscp_maxcallbacks++];
196 use->server = server;
197 memmove(&use->fid, fid, sizeof(struct AFSFid));
198 memmove(&use->cb, cb, sizeof(struct AFSCallBack));
200 f.cell = afscp_CellById(server->cell);
201 memcpy(&f.fid, fid, sizeof(struct AFSFid));
204 } /* afscp_AddCallBack */
207 afscp_RemoveCallBack(const struct afscp_server *server,
208 const struct afscp_venusfid *f)
210 struct afscp_callback *cb;
214 if (server == NULL) {
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)) {
228 } /* afscp_ReturnCallBacks */
231 afscp_ReturnCallBacks(const struct afscp_server *server)
233 struct AFSCBFids theFids;
234 struct AFSCBs theCBs;
235 struct afscp_callback *cb;
236 struct afscp_venusfid f;
237 struct rx_connection *c;
245 for (i = 0; i < afscp_maxcallbacks; i++) {
246 cb = &allcallbacks[i];
247 if (cb->server != server) {
250 if (cb->cb.ExpirationTime + cb->as_of < now) {
252 f.cell = afscp_CellById(cb->server->cell);
253 memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
260 theFids.AFSCBFids_val = malloc(sizeof(struct AFSFid) * AFSCBMAX);
261 if (!theFids.AFSCBFids_val) {
264 memset(theFids.AFSCBFids_val, 0,
265 sizeof(struct AFSFid) * AFSCBMAX);
266 theCBs.AFSCBs_val = malloc(sizeof(struct AFSCallBack) * AFSCBMAX);
267 if (!theCBs.AFSCBs_val) {
268 free(theFids.AFSCBFids_val);
271 memset(theCBs.AFSCBs_val, 0,
272 sizeof(struct AFSCallBack) * AFSCBMAX);
276 if (ncallbacks == AFSCBMAX) {
277 theFids.AFSCBFids_len = ncallbacks;
278 theCBs.AFSCBs_len = ncallbacks;
279 for (j = 0; j < server->naddrs; j++) {
280 c = afscp_ServerConnection(server, j);
283 code = RXAFS_GiveUpCallBacks(c, &theFids, &theCBs);
289 memmove(&theFids.AFSCBFids_val[ncallbacks], &cb->fid,
290 sizeof(struct AFSFid));
291 memmove(&theCBs.AFSCBs_val[ncallbacks], &cb->cb,
292 sizeof(struct AFSCallBack));
294 theCBs.AFSCBs_val[ncallbacks].CallBackType = CB_DROPPED;
297 f.cell = afscp_CellById(cb->server->cell);
298 memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
304 if (ncallbacks > 0) {
305 theFids.AFSCBFids_len = ncallbacks;
306 theCBs.AFSCBs_len = ncallbacks;
307 for (j = 0; j < server->naddrs; j++) {
308 c = afscp_ServerConnection(server, j);
311 code = RXAFS_GiveUpCallBacks(c, &theFids, &theCBs);
315 free(theFids.AFSCBFids_val);
316 free(theCBs.AFSCBs_val);
319 } /* afscp_ReturnCallBacks */
322 afscp_ReturnAllCallBacks(void)
324 struct afscp_server *s;
327 if (allcallbacks == NULL)
329 for (i = 0; (s = afscp_ServerByIndex(i)); i++) {
330 afscp_ReturnCallBacks(s);
334 afscp_maxcallbacks = 0;
337 } /* afscp_ReturnAllCallBacks */
340 * Handle a set of callbacks from the File Server.
342 * \param[in] rxcall Ptr to the associated Rx call structure.
343 * \param[in] Fids_Array Ptr to the set of Fids.
344 * \param[in] CallBacks_Array Ptr to the set of callbacks.
346 * \post Returns RXGEN_SUCCESS on success, Error value otherwise.
350 SRXAFSCB_CallBack(struct rx_call * rxcall, AFSCBFids * Fids_Array,
351 AFSCBs * CallBack_Array)
353 struct rx_connection *rxconn = rx_ConnectionOf(rxcall);
354 struct rx_peer *rxpeer = rx_PeerOf(rxconn);
355 struct afscp_server *server = afscp_AnyServerByAddr(rx_HostOf(rxpeer));
356 struct afscp_callback *cb;
357 struct afscp_venusfid f;
362 if (server == NULL) {
365 for (i = 0; i < afscp_maxcallbacks; i++) {
366 cb = &allcallbacks[i];
367 if (cb->server != server)
369 for (j = 0; j < Fids_Array->AFSCBFids_len; j++) {
370 fid = &Fids_Array->AFSCBFids_val[j];
371 if ((fid->Volume == cb->fid.Volume) &&
372 (fid->Vnode == cb->fid.Vnode) &&
373 (fid->Unique == cb->fid.Unique))
375 f.cell = afscp_CellById(cb->server->cell);
376 memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
381 return RXGEN_SUCCESS;
382 } /*SRXAFSCB_CallBack */
385 * Initialize callback state on this ``Cache Manager''.
387 * \param[in] rxcall Ptr to the associated Rx call structure.
389 * \post Returns RXGEN_SUCCESS on success, Error value otherwise.
391 * \note This will definitely be called by the File Server (exactly once),
392 * since it will think we are another new ``Cache Manager''.
395 SRXAFSCB_InitCallBackState(struct rx_call * rxcall)
397 struct rx_connection *rxconn = rx_ConnectionOf(rxcall);
398 struct rx_peer *rxpeer = rx_PeerOf(rxconn);
399 struct afscp_server *server = afscp_AnyServerByAddr(rx_HostOf(rxpeer));
400 struct afscp_callback *cb;
401 struct afscp_venusfid f;
404 if (server == NULL) {
407 for (i = 0; i < afscp_maxcallbacks; i++) {
408 cb = &allcallbacks[i];
409 if (cb->server != server)
412 f.cell = afscp_CellById(cb->server->cell);
413 memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
418 return RXGEN_SUCCESS;
419 } /* SRXAFSCB_InitCallBackState */
422 * Respond to a probe from the File Server.
424 * \param[in] rxcall Ptr to the associated Rx call structure.
426 * \post Returns RXGEN_SUCCESS (always)
428 * \note If a File Server doesn't hear from you every so often, it will
429 * send you a probe to make sure you're there, just like any other
430 * ``Cache Manager'' it's keeping track of.
434 SRXAFSCB_Probe(struct rx_call * rxcall)
436 return RXGEN_SUCCESS;
437 } /* SRXAFSCB_Probe */
440 * Respond minimally to a request for returning the contents of
441 * a cache lock, since someone out there thinks you're a Cache
444 * \param[in] rxcall Ptr to the associated Rx call structure.
448 * \post Returns RXGEN_SUCCESS (always)
452 SRXAFSCB_GetLock(struct rx_call * rxcall, afs_int32 index, AFSDBLock * lock)
454 return RXGEN_SUCCESS;
456 } /*SRXAFSCB_GetLock */
459 * Respond minimally to a request for returning the contents of
460 * a cache entry, since someone out there thinks you're a Cache
463 * \param[in] rxcall Ptr to the associated Rx call structure.
465 * \param[out] ce Ptr to cache entry
467 * \post Returns RXGEN_SUCCESS (always)
471 SRXAFSCB_GetCE(struct rx_call * rxcall, afs_int32 index, AFSDBCacheEntry * ce)
473 return RXGEN_SUCCESS;
474 } /* SRXAFSCB_GetCE */
477 * Respond minimally to a request for returning the contents of
478 * a cache entry, since someone out there thinks you're a Cache
479 * Manager. (64-bit version, though same as SRXAFSCB_GetCE())
481 * \param[in] rxcall Ptr to the associated Rx call structure.
483 * \param[out] ce Ptr to cache entry
485 * \post Returns RXGEN_SUCCESS (always)
489 SRXAFSCB_GetCE64(struct rx_call * rxcall, afs_int32 index,
490 AFSDBCacheEntry64 * ce)
492 return RXGEN_SUCCESS;
493 } /*SRXAFSCB_GetCE */
496 * Respond minimally to a request for fetching the version of
497 * extended Cache Manager statistics offered, since someone out
498 * there thinks you're a Cache Manager.
500 * \param[in] rxcall Ptr to the associated Rx call structure
501 * \param[out] versionNumberP
503 * \post Returns RXGEN_SUCCESS (always)
507 SRXAFSCB_XStatsVersion(struct rx_call * rxcall, afs_int32 * versionNumberP)
509 return RXGEN_SUCCESS;
510 } /*SRXAFSCB_XStatsVersion */
513 * Respond minimally to a request for returning extended
514 * statistics for a Cache Manager, since someone out there thinks
515 * you're a Cache Manager.
517 * \param[in] z_call Ptr to the associated Rx call structure
518 * \param[in] clientVersionNumber
519 * \param[in] collectionNumber
520 * \param[out] srvVersionNumberP
524 * \post Returns RXGEN_SUCCESS (always)
528 SRXAFSCB_GetXStats(struct rx_call * z_call, afs_int32 clientVersionNumber,
529 afs_int32 collectionNumber, afs_int32 * srvVersionNumberP,
530 afs_int32 * timeP, AFSCB_CollData * dataP)
532 return RXGEN_SUCCESS;
533 } /*SRXAFSCB_GetXStats */
536 * This routine was used in the AFS 3.5 beta release, but not anymore.
537 * It has since been replaced by SRXAFSCB_InitCallBackState3.
539 * \param[in] rxcall Ptr to the associated Rx call structure.
540 * \param[out] addr Ptr to return the list of interfaces for this client
542 * \post Returns RXGEN_SUCCESS (always)
546 SRXAFSCB_InitCallBackState2(struct rx_call * rxcall,
547 struct interfaceAddr * addr)
550 } /* SRXAFSCB_InitCallBackState2 */
554 * \param rxcall Ptr to the associated Rx call structure.
556 * \post Returns RXGEN_SUCCESS (always)
560 SRXAFSCB_TellMeAboutYourself(struct rx_call * a_call,
561 struct interfaceAddr * addr,
562 Capabilities * capabilities)
566 int cm_noIPAddr; /* number of client network interfaces */
567 int cm_IPAddr[CM_MAXINTERFACE_ADDR]; /* client's IP address in host order */
568 int cm_SubnetMask[CM_MAXINTERFACE_ADDR]; /* client's subnet mask in host order */
569 int cm_NetMtu[CM_MAXINTERFACE_ADDR]; /* client's MTU sizes */
570 int cm_NetFlags[CM_MAXINTERFACE_ADDR]; /* network flags */
573 cm_noIPAddr = CM_MAXINTERFACE_ADDR;
574 code = syscfg_GetIFInfo(&cm_noIPAddr,
575 cm_IPAddr, cm_SubnetMask, cm_NetMtu, cm_NetFlags);
577 /* return all network interface addresses */
578 addr->numberOfInterfaces = cm_noIPAddr;
579 for (i = 0; i < cm_noIPAddr; i++) {
580 addr->addr_in[i] = cm_IPAddr[i];
581 addr->subnetmask[i] = cm_SubnetMask[i];
582 addr->mtu[i] = cm_NetMtu[i];
585 addr->numberOfInterfaces = 0;
588 if (a_call && addr) {
591 *addr = afs_cb_interface;
594 if (capabilities != NULL) {
595 afs_uint32 *dataBuffP;
598 dataBytes = 1 * sizeof(afs_uint32);
599 dataBuffP = (afs_uint32 *) xdr_alloc(dataBytes);
600 dataBuffP[0] = CLIENT_CAPABILITY_ERRORTRANS;
601 capabilities->Capabilities_len = dataBytes / sizeof(afs_uint32);
602 capabilities->Capabilities_val = dataBuffP;
604 return RXGEN_SUCCESS;
605 } /* SRXAFSCB_TellMeAboutYourself */
608 * Routine called by the server-side callback RPC interface to
609 * obtain a unique identifier for the client. The server uses
610 * this identifier to figure out whether or not two RX connections
611 * are from the same client, and to find out which addresses go
612 * with which clients.
614 * \param[in] rxcall Ptr to the associated Rx call structure.
615 * \param[out] addr Ptr to return the list of interfaces for this client
617 * \post Returns output of TellMeAboutYourself (which
618 * should be RXGEN_SUCCESS).
622 SRXAFSCB_WhoAreYou(struct rx_call * rxcall, struct interfaceAddr * addr)
624 return SRXAFSCB_TellMeAboutYourself(rxcall, addr, NULL);
625 } /* SRXAFSCB_WhoAreYou */
628 * Routine called by the server-side callback RPC interface to
629 * implement clearing all callbacks from this host.
631 * \param[in] rxcall Ptr to the associated Rx call structure.
632 * \param[in] serverUuid Ptr to UUID
634 * \post Returns RXGEN_SUCCESS (always)
638 SRXAFSCB_InitCallBackState3(struct rx_call * rxcall, afsUUID * serverUuid)
640 struct rx_connection *rxconn = rx_ConnectionOf(rxcall);
641 struct rx_peer *rxpeer = rx_PeerOf(rxconn);
642 struct afscp_server *server = afscp_AnyServerByAddr(rx_HostOf(rxpeer));
643 struct afscp_callback *cb;
644 struct afscp_venusfid f;
647 if (server == NULL) {
650 for (i = 0; i < afscp_maxcallbacks; i++) {
651 cb = &allcallbacks[i];
652 if (cb->server != server)
655 f.cell = afscp_CellById(cb->server->cell);
656 memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
661 return RXGEN_SUCCESS;
662 } /* SRXAFSCB_InitCallBackState3 */
665 * Routine called by the server-side callback RPC interface to
666 * implement ``probing'' the Cache Manager, just making sure it's
667 * still there is still the same client it used to be.
669 * \param rxcall Ptr to the associated Rx call structure.
670 * \param clientUuid Ptr to UUID that must match the client's UUID
672 * \post Returns RXGEN_SUCCESS (always)
676 SRXAFSCB_ProbeUuid(struct rx_call * rxcall, afsUUID * clientUuid)
681 if (!afs_uuid_equal(clientUuid, &afs_cb_interface.uuid))
682 code = 1; /* failure */
684 } /* SRXAFSCB_ProbeUuid */
687 * Routine to list server preferences used by this client.
689 * \param[in] a_call Ptr to Rx call on which this request came in.
690 * \param[in] a_index Input server index
691 * \param[out] a_srvr_addr Output server address (0xffffffff on last server)
692 * \param[out] a_srvr_rank Output server rank
694 * \post Returns RXGEN_SUCCESS (always)
698 SRXAFSCB_GetServerPrefs(struct rx_call * a_call, afs_int32 a_index,
699 afs_int32 * a_srvr_addr, afs_int32 * a_srvr_rank)
701 *a_srvr_addr = 0xffffffff;
702 *a_srvr_rank = 0xffffffff;
703 return RXGEN_SUCCESS;
704 } /* SRXAFSCB_GetServerPrefs */
707 * Routine to list cells configured for this client
709 * \param[in] a_call Ptr to Rx call on which this request came in.
710 * \param[in] a_index Input cell index
711 * \param[out] a_name Output cell name ("" on last cell)
712 * \param[out] a_hosts Output cell database servers
714 * \post Returns RXGEN_OPCODE (always)
718 SRXAFSCB_GetCellServDB(struct rx_call * a_call, afs_int32 a_index,
719 char **a_name, afs_int32 * a_hosts)
722 } /* SRXAFSCB_GetCellServDB */
725 * Routine to return name of client's local cell
727 * \param[in] a_call Ptr to Rx call on which this request came in.
728 * \param[out] a_name Output cell name
730 * \post Returns RXGEN_SUCCESS (always)
734 SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
737 } /* SRXAFSCB_GetLocalCell */
740 * Routine to return parameters used to initialize client cache.
741 * Client may request any format version. Server may not return
742 * format version greater than version requested by client.
744 * \param[in] a_call Ptr to Rx call on which this request came in.
745 * \param[in] callerVersion Data format version desired by the client.
746 * \param[out] serverVersion Data format version of output data.
747 * \param[out] configCount Number bytes allocated for output data.
748 * \param[out] config Client cache configuration.
750 * \post Returns RXGEN_SUCCESS (always)
754 SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
755 afs_uint32 * serverVersion, afs_uint32 * configCount,
756 cacheConfig * config)
759 } /* SRXAFSCB_GetCacheConfig */
764 * \param[in] rxcall Ptr to the associated Rx call structure.
766 * \post Returns RXGEN_OPCODE (always)
770 SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_index,
771 char **a_name, afs_int32 * a_hosts)
774 } /* SRXAFSCB_GetCellByNum */