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 */
57 * This Windows section was pulled in from changes to src/venus/afsio.c but is
58 * untested here and may be unnecessary if rx_getAllAddr() can be used on that
59 * platform. However, there was already an ifdef here surrounding UuidCreate().
63 int cm_IPAddr[CM_MAXINTERFACE_ADDR]; /* client's IP address in host order */
64 int cm_SubnetMask[CM_MAXINTERFACE_ADDR]; /* client's subnet mask in host order */
65 int cm_NetMtu[CM_MAXINTERFACE_ADDR]; /* client's MTU sizes */
66 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;
102 afscp_AddCallBack(const struct afscp_server *server,
103 const struct AFSFid *fid,
104 const struct AFSFetchStatus *fst,
105 const struct AFSCallBack *cb, const time_t as_of)
108 struct afscp_callback *use = NULL, *newlist;
109 struct afscp_venusfid f;
114 for (i = 0; i < afscp_maxcallbacks; i++) {
115 if (allcallbacks[i].cb.ExpirationTime + allcallbacks[i].as_of < now) {
116 if (allcallbacks[i].valid) {
117 f.cell = afscp_CellById(allcallbacks[i].server->cell);
118 memcpy(&f.fid, &allcallbacks[i].fid, sizeof(struct AFSFid));
121 allcallbacks[i].valid = 0;
125 if (allcallbacks[i].valid == 0)
126 use = &allcallbacks[i];
127 if ((allcallbacks[i].server == server) &&
128 (fid->Volume == allcallbacks[i].fid.Volume) &&
129 (fid->Vnode == allcallbacks[i].fid.Vnode) &&
130 (fid->Unique == allcallbacks[i].fid.Unique)) {
131 use = &allcallbacks[i];
136 if (afscp_maxcallbacks >= afscp_cballoced) {
137 if (afscp_cballoced != 0)
138 afscp_cballoced = afscp_cballoced * 2;
141 newlist = realloc(allcallbacks, afscp_cballoced *
142 sizeof(struct afscp_callback));
143 if (newlist == NULL) {
146 allcallbacks = newlist;
148 use = &allcallbacks[afscp_maxcallbacks++];
151 use->server = server;
152 memmove(&use->fid, fid, sizeof(struct AFSFid));
153 memmove(&use->cb, cb, sizeof(struct AFSCallBack));
155 f.cell = afscp_CellById(server->cell);
156 memcpy(&f.fid, fid, sizeof(struct AFSFid));
159 } /* afscp_AddCallBack */
162 afscp_RemoveCallBack(const struct afscp_server *server,
163 const struct afscp_venusfid *f)
165 struct afscp_callback *cb;
169 if (server == NULL) {
172 for (i = 0; i < afscp_maxcallbacks; i++) {
173 cb = &allcallbacks[i];
174 if ((cb->server == server) &&
175 (f->fid.Volume == cb->fid.Volume) &&
176 (f->fid.Vnode == cb->fid.Vnode) &&
177 (f->fid.Unique == cb->fid.Unique)) {
183 } /* afscp_ReturnCallBacks */
186 afscp_ReturnCallBacks(const struct afscp_server *server)
188 struct AFSCBFids theFids;
189 struct AFSCBs theCBs;
190 struct afscp_callback *cb;
191 struct afscp_venusfid f;
192 struct rx_connection *c;
200 for (i = 0; i < afscp_maxcallbacks; i++) {
201 cb = &allcallbacks[i];
202 if (cb->server != server) {
205 if (cb->cb.ExpirationTime + cb->as_of < now) {
207 f.cell = afscp_CellById(cb->server->cell);
208 memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
215 theFids.AFSCBFids_val = malloc(sizeof(struct AFSFid) * AFSCBMAX);
216 if (!theFids.AFSCBFids_val) {
219 memset(theFids.AFSCBFids_val, 0,
220 sizeof(struct AFSFid) * AFSCBMAX);
221 theCBs.AFSCBs_val = malloc(sizeof(struct AFSCallBack) * AFSCBMAX);
222 if (!theCBs.AFSCBs_val) {
223 free(theFids.AFSCBFids_val);
226 memset(theCBs.AFSCBs_val, 0,
227 sizeof(struct AFSCallBack) * AFSCBMAX);
231 if (ncallbacks == AFSCBMAX) {
232 theFids.AFSCBFids_len = ncallbacks;
233 theCBs.AFSCBs_len = ncallbacks;
234 for (j = 0; j < server->naddrs; j++) {
235 c = afscp_ServerConnection(server, j);
238 code = RXAFS_GiveUpCallBacks(c, &theFids, &theCBs);
244 memmove(&theFids.AFSCBFids_val[ncallbacks], &cb->fid,
245 sizeof(struct AFSFid));
246 memmove(&theCBs.AFSCBs_val[ncallbacks], &cb->cb,
247 sizeof(struct AFSCallBack));
249 theCBs.AFSCBs_val[ncallbacks].CallBackType = CB_DROPPED;
252 f.cell = afscp_CellById(cb->server->cell);
253 memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
259 if (ncallbacks > 0) {
260 theFids.AFSCBFids_len = ncallbacks;
261 theCBs.AFSCBs_len = ncallbacks;
262 for (j = 0; j < server->naddrs; j++) {
263 c = afscp_ServerConnection(server, j);
266 code = RXAFS_GiveUpCallBacks(c, &theFids, &theCBs);
270 free(theFids.AFSCBFids_val);
271 free(theCBs.AFSCBs_val);
274 } /* afscp_ReturnCallBacks */
277 afscp_ReturnAllCallBacks(void)
279 struct afscp_server *s;
282 if (allcallbacks == NULL)
284 for (i = 0; (s = afscp_ServerByIndex(i)); i++) {
285 afscp_ReturnCallBacks(s);
289 afscp_maxcallbacks = 0;
292 } /* afscp_ReturnAllCallBacks */
295 * Handle a set of callbacks from the File Server.
297 * \param[in] rxcall Ptr to the associated Rx call structure.
298 * \param[in] Fids_Array Ptr to the set of Fids.
299 * \param[in] CallBacks_Array Ptr to the set of callbacks.
301 * \post Returns RXGEN_SUCCESS on success, Error value otherwise.
305 SRXAFSCB_CallBack(struct rx_call * rxcall, AFSCBFids * Fids_Array,
306 AFSCBs * CallBack_Array)
308 struct rx_connection *rxconn = rx_ConnectionOf(rxcall);
309 struct rx_peer *rxpeer = rx_PeerOf(rxconn);
310 struct afscp_server *server = afscp_AnyServerByAddr(rx_HostOf(rxpeer));
311 struct afscp_callback *cb;
312 struct afscp_venusfid f;
317 if (server == NULL) {
320 for (i = 0; i < afscp_maxcallbacks; i++) {
321 cb = &allcallbacks[i];
322 if (cb->server != server)
324 for (j = 0; j < Fids_Array->AFSCBFids_len; j++) {
325 fid = &Fids_Array->AFSCBFids_val[j];
326 if ((fid->Volume == cb->fid.Volume) &&
327 (fid->Vnode == cb->fid.Vnode) &&
328 (fid->Unique == cb->fid.Unique))
330 f.cell = afscp_CellById(cb->server->cell);
331 memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
336 return RXGEN_SUCCESS;
337 } /*SRXAFSCB_CallBack */
340 * Initialize callback state on this ``Cache Manager''.
342 * \param[in] rxcall Ptr to the associated Rx call structure.
344 * \post Returns RXGEN_SUCCESS on success, Error value otherwise.
346 * \note This will definitely be called by the File Server (exactly once),
347 * since it will think we are another new ``Cache Manager''.
350 SRXAFSCB_InitCallBackState(struct rx_call * rxcall)
352 struct rx_connection *rxconn = rx_ConnectionOf(rxcall);
353 struct rx_peer *rxpeer = rx_PeerOf(rxconn);
354 struct afscp_server *server = afscp_AnyServerByAddr(rx_HostOf(rxpeer));
355 struct afscp_callback *cb;
356 struct afscp_venusfid f;
359 if (server == NULL) {
362 for (i = 0; i < afscp_maxcallbacks; i++) {
363 cb = &allcallbacks[i];
364 if (cb->server != server)
367 f.cell = afscp_CellById(cb->server->cell);
368 memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
373 return RXGEN_SUCCESS;
374 } /* SRXAFSCB_InitCallBackState */
377 * Respond to a probe from the File Server.
379 * \param[in] rxcall Ptr to the associated Rx call structure.
381 * \post Returns RXGEN_SUCCESS (always)
383 * \note If a File Server doesn't hear from you every so often, it will
384 * send you a probe to make sure you're there, just like any other
385 * ``Cache Manager'' it's keeping track of.
389 SRXAFSCB_Probe(struct rx_call * rxcall)
391 return RXGEN_SUCCESS;
392 } /* SRXAFSCB_Probe */
395 * Respond minimally to a request for returning the contents of
396 * a cache lock, since someone out there thinks you're a Cache
399 * \param[in] rxcall Ptr to the associated Rx call structure.
403 * \post Returns RXGEN_SUCCESS (always)
407 SRXAFSCB_GetLock(struct rx_call * rxcall, afs_int32 index, AFSDBLock * lock)
409 return RXGEN_SUCCESS;
411 } /*SRXAFSCB_GetLock */
414 * Respond minimally to a request for returning the contents of
415 * a cache entry, since someone out there thinks you're a Cache
418 * \param[in] rxcall Ptr to the associated Rx call structure.
420 * \param[out] ce Ptr to cache entry
422 * \post Returns RXGEN_SUCCESS (always)
426 SRXAFSCB_GetCE(struct rx_call * rxcall, afs_int32 index, AFSDBCacheEntry * ce)
428 return RXGEN_SUCCESS;
429 } /* SRXAFSCB_GetCE */
432 * Respond minimally to a request for returning the contents of
433 * a cache entry, since someone out there thinks you're a Cache
434 * Manager. (64-bit version, though same as SRXAFSCB_GetCE())
436 * \param[in] rxcall Ptr to the associated Rx call structure.
438 * \param[out] ce Ptr to cache entry
440 * \post Returns RXGEN_SUCCESS (always)
444 SRXAFSCB_GetCE64(struct rx_call * rxcall, afs_int32 index,
445 AFSDBCacheEntry64 * ce)
447 return RXGEN_SUCCESS;
448 } /*SRXAFSCB_GetCE */
451 * Respond minimally to a request for fetching the version of
452 * extended Cache Manager statistics offered, since someone out
453 * there thinks you're a Cache Manager.
455 * \param[in] rxcall Ptr to the associated Rx call structure
456 * \param[out] versionNumberP
458 * \post Returns RXGEN_SUCCESS (always)
462 SRXAFSCB_XStatsVersion(struct rx_call * rxcall, afs_int32 * versionNumberP)
464 return RXGEN_SUCCESS;
465 } /*SRXAFSCB_XStatsVersion */
468 * Respond minimally to a request for returning extended
469 * statistics for a Cache Manager, since someone out there thinks
470 * you're a Cache Manager.
472 * \param[in] z_call Ptr to the associated Rx call structure
473 * \param[in] clientVersionNumber
474 * \param[in] collectionNumber
475 * \param[out] srvVersionNumberP
479 * \post Returns RXGEN_SUCCESS (always)
483 SRXAFSCB_GetXStats(struct rx_call * z_call, afs_int32 clientVersionNumber,
484 afs_int32 collectionNumber, afs_int32 * srvVersionNumberP,
485 afs_int32 * timeP, AFSCB_CollData * dataP)
487 return RXGEN_SUCCESS;
488 } /*SRXAFSCB_GetXStats */
491 * This routine was used in the AFS 3.5 beta release, but not anymore.
492 * It has since been replaced by SRXAFSCB_InitCallBackState3.
494 * \param[in] rxcall Ptr to the associated Rx call structure.
495 * \param[out] addr Ptr to return the list of interfaces for this client
497 * \post Returns RXGEN_SUCCESS (always)
501 SRXAFSCB_InitCallBackState2(struct rx_call * rxcall,
502 struct interfaceAddr * addr)
505 } /* SRXAFSCB_InitCallBackState2 */
509 * \param rxcall Ptr to the associated Rx call structure.
511 * \post Returns RXGEN_SUCCESS (always)
515 SRXAFSCB_TellMeAboutYourself(struct rx_call * a_call,
516 struct interfaceAddr * addr,
517 Capabilities * capabilities)
521 int cm_noIPAddr; /* number of client network interfaces */
522 int cm_IPAddr[CM_MAXINTERFACE_ADDR]; /* client's IP address in host order */
523 int cm_SubnetMask[CM_MAXINTERFACE_ADDR]; /* client's subnet mask in host order */
524 int cm_NetMtu[CM_MAXINTERFACE_ADDR]; /* client's MTU sizes */
525 int cm_NetFlags[CM_MAXINTERFACE_ADDR]; /* network flags */
528 cm_noIPAddr = CM_MAXINTERFACE_ADDR;
529 code = syscfg_GetIFInfo(&cm_noIPAddr,
530 cm_IPAddr, cm_SubnetMask, cm_NetMtu, cm_NetFlags);
532 /* return all network interface addresses */
533 addr->numberOfInterfaces = cm_noIPAddr;
534 for (i = 0; i < cm_noIPAddr; i++) {
535 addr->addr_in[i] = cm_IPAddr[i];
536 addr->subnetmask[i] = cm_SubnetMask[i];
537 addr->mtu[i] = cm_NetMtu[i];
540 addr->numberOfInterfaces = 0;
543 if (a_call && addr) {
546 *addr = afs_cb_interface;
549 if (capabilities != NULL) {
550 afs_uint32 *dataBuffP;
553 dataBytes = 1 * sizeof(afs_uint32);
554 dataBuffP = (afs_uint32 *) xdr_alloc(dataBytes);
555 dataBuffP[0] = CLIENT_CAPABILITY_ERRORTRANS;
556 capabilities->Capabilities_len = dataBytes / sizeof(afs_uint32);
557 capabilities->Capabilities_val = dataBuffP;
559 return RXGEN_SUCCESS;
560 } /* SRXAFSCB_TellMeAboutYourself */
563 * Routine called by the server-side callback RPC interface to
564 * obtain a unique identifier for the client. The server uses
565 * this identifier to figure out whether or not two RX connections
566 * are from the same client, and to find out which addresses go
567 * with which clients.
569 * \param[in] rxcall Ptr to the associated Rx call structure.
570 * \param[out] addr Ptr to return the list of interfaces for this client
572 * \post Returns output of TellMeAboutYourself (which
573 * should be RXGEN_SUCCESS).
577 SRXAFSCB_WhoAreYou(struct rx_call * rxcall, struct interfaceAddr * addr)
579 return SRXAFSCB_TellMeAboutYourself(rxcall, addr, NULL);
580 } /* SRXAFSCB_WhoAreYou */
583 * Routine called by the server-side callback RPC interface to
584 * implement clearing all callbacks from this host.
586 * \param[in] rxcall Ptr to the associated Rx call structure.
587 * \param[in] serverUuid Ptr to UUID
589 * \post Returns RXGEN_SUCCESS (always)
593 SRXAFSCB_InitCallBackState3(struct rx_call * rxcall, afsUUID * serverUuid)
595 struct rx_connection *rxconn = rx_ConnectionOf(rxcall);
596 struct rx_peer *rxpeer = rx_PeerOf(rxconn);
597 struct afscp_server *server = afscp_AnyServerByAddr(rx_HostOf(rxpeer));
598 struct afscp_callback *cb;
599 struct afscp_venusfid f;
602 if (server == NULL) {
605 for (i = 0; i < afscp_maxcallbacks; i++) {
606 cb = &allcallbacks[i];
607 if (cb->server != server)
610 f.cell = afscp_CellById(cb->server->cell);
611 memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid));
616 return RXGEN_SUCCESS;
617 } /* SRXAFSCB_InitCallBackState3 */
620 * Routine called by the server-side callback RPC interface to
621 * implement ``probing'' the Cache Manager, just making sure it's
622 * still there is still the same client it used to be.
624 * \param rxcall Ptr to the associated Rx call structure.
625 * \param clientUuid Ptr to UUID that must match the client's UUID
627 * \post Returns RXGEN_SUCCESS (always)
631 SRXAFSCB_ProbeUuid(struct rx_call * rxcall, afsUUID * clientUuid)
636 if (!afs_uuid_equal(clientUuid, &afs_cb_interface.uuid))
637 code = 1; /* failure */
639 } /* SRXAFSCB_ProbeUuid */
642 * Routine to list server preferences used by this client.
644 * \param[in] a_call Ptr to Rx call on which this request came in.
645 * \param[in] a_index Input server index
646 * \param[out] a_srvr_addr Output server address (0xffffffff on last server)
647 * \param[out] a_srvr_rank Output server rank
649 * \post Returns RXGEN_SUCCESS (always)
653 SRXAFSCB_GetServerPrefs(struct rx_call * a_call, afs_int32 a_index,
654 afs_int32 * a_srvr_addr, afs_int32 * a_srvr_rank)
656 *a_srvr_addr = 0xffffffff;
657 *a_srvr_rank = 0xffffffff;
658 return RXGEN_SUCCESS;
659 } /* SRXAFSCB_GetServerPrefs */
662 * Routine to list cells configured for this client
664 * \param[in] a_call Ptr to Rx call on which this request came in.
665 * \param[in] a_index Input cell index
666 * \param[out] a_name Output cell name ("" on last cell)
667 * \param[out] a_hosts Output cell database servers
669 * \post Returns RXGEN_OPCODE (always)
673 SRXAFSCB_GetCellServDB(struct rx_call * a_call, afs_int32 a_index,
674 char **a_name, afs_int32 * a_hosts)
677 } /* SRXAFSCB_GetCellServDB */
680 * Routine to return name of client's local cell
682 * \param[in] a_call Ptr to Rx call on which this request came in.
683 * \param[out] a_name Output cell name
685 * \post Returns RXGEN_SUCCESS (always)
689 SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
692 } /* SRXAFSCB_GetLocalCell */
695 * Routine to return parameters used to initialize client cache.
696 * Client may request any format version. Server may not return
697 * format version greater than version requested by client.
699 * \param[in] a_call Ptr to Rx call on which this request came in.
700 * \param[in] callerVersion Data format version desired by the client.
701 * \param[out] serverVersion Data format version of output data.
702 * \param[out] configCount Number bytes allocated for output data.
703 * \param[out] config Client cache configuration.
705 * \post Returns RXGEN_SUCCESS (always)
709 SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
710 afs_uint32 * serverVersion, afs_uint32 * configCount,
711 cacheConfig * config)
714 } /* SRXAFSCB_GetCacheConfig */
719 * \param[in] rxcall Ptr to the associated Rx call structure.
721 * \post Returns RXGEN_OPCODE (always)
725 SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_index,
726 char **a_name, afs_int32 * a_hosts)
729 } /* SRXAFSCB_GetCellByNum */