2 * Copyright (c) 2007-2010 Secure Endpoints Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Neither the name of the Secure Endpoints Inc. nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 /* This source file provides the declarations
30 * which specify the AFS Cache Manager Volume Status Event
34 #include <afsconfig.h>
35 #include <afs/param.h>
47 #include <WINNT/afsreg.h>
49 HMODULE hVolStatus = NULL;
50 dll_VolStatus_Funcs_t dll_funcs;
51 cm_VolStatus_Funcs_t cm_funcs;
53 static char volstat_NetbiosName[64] = "";
56 cm_VolStatus_Active(void)
58 return (hVolStatus != NULL);
61 /* This function is used to load any Volume Status Handlers
62 * and their associated function pointers.
65 cm_VolStatus_Initialization(void)
67 long (__fastcall * dll_VolStatus_Initialization)(dll_VolStatus_Funcs_t * dll_funcs, cm_VolStatus_Funcs_t *cm_funcs) = NULL;
71 char wd[MAX_PATH+1] = "";
73 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
74 0, KEY_QUERY_VALUE, &parmKey);
75 if (code == ERROR_SUCCESS) {
76 dummyLen = sizeof(wd);
77 code = RegQueryValueEx(parmKey, "VolStatusHandler", NULL, NULL,
78 (BYTE *) &wd, &dummyLen);
81 dummyLen = sizeof(volstat_NetbiosName);
82 code = RegQueryValueEx(parmKey, "NetbiosName", NULL, NULL,
83 (BYTE *)volstat_NetbiosName, &dummyLen);
85 RegCloseKey (parmKey);
88 if (code == ERROR_SUCCESS && wd[0])
89 hVolStatus = LoadLibrary(wd);
91 (FARPROC) dll_VolStatus_Initialization = GetProcAddress(hVolStatus, "@VolStatus_Initialization@8");
92 if (dll_VolStatus_Initialization) {
93 cm_funcs.version = CM_VOLSTATUS_FUNCS_VERSION;
94 cm_funcs.cm_VolStatus_Path_To_ID = cm_VolStatus_Path_To_ID;
95 cm_funcs.cm_VolStatus_Path_To_DFSlink = cm_VolStatus_Path_To_DFSlink;
97 dll_funcs.version = DLL_VOLSTATUS_FUNCS_VERSION;
98 code = dll_VolStatus_Initialization(&dll_funcs, &cm_funcs);
101 if (dll_VolStatus_Initialization == NULL || code != 0 ||
102 dll_funcs.version != DLL_VOLSTATUS_FUNCS_VERSION) {
103 FreeLibrary(hVolStatus);
109 osi_Log1(afsd_logp,"cm_VolStatus_Initialization 0x%x", code);
114 /* This function is used to unload any Volume Status Handlers
115 * that were loaded during initialization.
118 cm_VolStatus_Finalize(void)
120 osi_Log1(afsd_logp,"cm_VolStatus_Finalize handle 0x%x", hVolStatus);
122 if (hVolStatus == NULL)
125 FreeLibrary(hVolStatus);
130 /* This function notifies the Volume Status Handlers that the
131 * AFS client service has started. If the network is started
132 * at this point we call cm_VolStatus_Network_Started().
135 cm_VolStatus_Service_Started(void)
139 osi_Log1(afsd_logp,"cm_VolStatus_Service_Started handle 0x%x", hVolStatus);
141 if (hVolStatus == NULL)
144 code = dll_funcs.dll_VolStatus_Service_Started();
145 if (code == 0 && smb_IsNetworkStarted())
146 code = dll_funcs.dll_VolStatus_Network_Started(cm_NetbiosName, cm_NetbiosName);
151 /* This function notifies the Volume Status Handlers that the
152 * AFS client service is stopping.
155 cm_VolStatus_Service_Stopped(void)
159 osi_Log1(afsd_logp,"cm_VolStatus_Service_Stopped handle 0x%x", hVolStatus);
161 if (hVolStatus == NULL)
164 code = dll_funcs.dll_VolStatus_Service_Stopped();
170 /* This function notifies the Volume Status Handlers that the
171 * AFS client service is accepting network requests using the
172 * specified netbios names.
176 cm_VolStatus_Network_Started(const char * netbios32, const char * netbios64)
178 cm_VolStatus_Network_Started(const char * netbios32)
183 if (hVolStatus == NULL)
187 code = dll_funcs.dll_VolStatus_Network_Started(netbios32, netbios64);
189 code = dll_funcs.dll_VolStatus_Network_Started(netbios32, netbios32);
195 /* This function notifies the Volume Status Handlers that the
196 * AFS client service is no longer accepting network requests
197 * using the specified netbios names
201 cm_VolStatus_Network_Stopped(const char * netbios32, const char * netbios64)
203 cm_VolStatus_Network_Stopped(const char * netbios32)
208 if (hVolStatus == NULL)
212 code = dll_funcs.dll_VolStatus_Network_Stopped(netbios32, netbios64);
214 code = dll_funcs.dll_VolStatus_Network_Stopped(netbios32, netbios32);
220 /* This function is called when the IP address list changes.
221 * Volume Status Handlers can use this notification as a hint
222 * that it might be possible to determine volume IDs for paths
223 * that previously were not accessible.
226 cm_VolStatus_Network_Addr_Change(void)
230 if (hVolStatus == NULL)
233 code = dll_funcs.dll_VolStatus_Network_Addr_Change();
238 /* This function notifies the Volume Status Handlers that the
239 * state of the specified cell.volume has changed.
242 cm_VolStatus_Change_Notification(afs_uint32 cellID, afs_uint32 volID, enum volstatus status)
246 if (hVolStatus == NULL)
249 code = dll_funcs.dll_VolStatus_Change_Notification(cellID, volID, status);
257 cm_VolStatus_Notify_DFS_Mapping(cm_scache_t *scp, const clientchar_t *ctidPathp,
258 const clientchar_t *cpathp)
263 char * tidPathp = NULL;
266 if (hVolStatus == NULL || dll_funcs.version < 2)
269 tidPathp = cm_ClientStringToUtf8Alloc(ctidPathp, -1, NULL);
270 pathp = cm_ClientStringToUtf8Alloc(cpathp, -1, NULL);
272 snprintf(src,sizeof(src), "\\\\%s%s", volstat_NetbiosName, tidPathp);
274 if ((src[len-1] == '\\' || src[len-1] == '/') &&
275 (pathp[0] == '\\' || pathp[0] == '/'))
276 strncat(src, &pathp[1], sizeof(src));
278 strncat(src, pathp, sizeof(src));
280 for ( p=src; *p; p++ ) {
285 code = dll_funcs.dll_VolStatus_Notify_DFS_Mapping(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
286 src, scp->mountPointStringp);
297 cm_VolStatus_Invalidate_DFS_Mapping(cm_scache_t *scp)
301 if (hVolStatus == NULL || dll_funcs.version < 2)
304 code = dll_funcs.dll_VolStatus_Invalidate_DFS_Mapping(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
311 cm_VolStatus_Path_To_ID(const char * share, const char * path, afs_uint32 * cellID, afs_uint32 * volID, enum volstatus *pstatus)
317 clientchar_t * cpath = NULL;
318 clientchar_t * cshare = NULL;
320 if (cellID == NULL || volID == NULL)
321 return CM_ERROR_INVAL;
323 osi_Log2(afsd_logp,"cm_VolStatus_Path_To_ID share %s path %s",
324 osi_LogSaveString(afsd_logp, (char *)share), osi_LogSaveString(afsd_logp, (char *)path));
328 cpath = cm_FsStringToClientStringAlloc(path, -1, NULL);
329 cshare = cm_FsStringToClientStringAlloc(share, -1, NULL);
331 if (cpath == NULL || cshare == NULL) {
332 osi_Log1(afsd_logp, "Can't convert %s string. Aborting",
333 (cpath == NULL)? "path" : "share");
334 code = CM_ERROR_NOSUCHPATH;
338 code = cm_NameI(cm_RootSCachep(cm_rootUserp, &req), cpath,
339 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
340 cm_rootUserp, cshare, &req, &scp);
344 lock_ObtainWrite(&scp->rw);
345 code = cm_SyncOp(scp, NULL,cm_rootUserp, &req, 0,
346 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
348 lock_ReleaseWrite(&scp->rw);
349 cm_ReleaseSCache(scp);
353 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
355 *cellID = scp->fid.cell;
356 *volID = scp->fid.volume;
357 volp = cm_GetVolumeByFID(&scp->fid);
359 *pstatus = cm_GetVolumeStatus(volp, scp->fid.volume);
362 *pstatus = vl_unknown;
364 lock_ReleaseWrite(&scp->rw);
365 cm_ReleaseSCache(scp);
373 osi_Log1(afsd_logp,"cm_VolStatus_Path_To_ID code 0x%x",code);
378 cm_VolStatus_Path_To_DFSlink(const char * share, const char * path, afs_uint32 *pBufSize, char *pBuffer)
384 clientchar_t *cpath = NULL;
385 clientchar_t *cshare = NULL;
387 if (pBufSize == NULL || (pBuffer == NULL && *pBufSize != 0))
388 return CM_ERROR_INVAL;
390 osi_Log2(afsd_logp,"cm_VolStatus_Path_To_DFSlink share %s path %s",
391 osi_LogSaveString(afsd_logp, (char *)share), osi_LogSaveString(afsd_logp, (char *)path));
395 cpath = cm_FsStringToClientStringAlloc(path, -1, NULL);
396 cshare = cm_FsStringToClientStringAlloc(share, -1, NULL);
398 if (cpath == NULL || cshare == NULL) {
399 osi_Log1(afsd_logp, "Can't convert %s string. Aborting",
400 (cpath == NULL)? "path" : "share");
401 code = CM_ERROR_NOSUCHPATH;
405 code = cm_NameI(cm_RootSCachep(cm_rootUserp, &req), cpath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
406 cm_rootUserp, cshare, &req, &scp);
410 lock_ObtainWrite(&scp->rw);
411 code = cm_SyncOp(scp, NULL, cm_rootUserp, &req, 0,
412 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
414 lock_ReleaseWrite(&scp->rw);
415 cm_ReleaseSCache(scp);
419 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
421 if (scp->fileType != CM_SCACHETYPE_DFSLINK) {
422 code = CM_ERROR_NOT_A_DFSLINK;
426 len = strlen(scp->mountPointStringp) + 1;
429 else if (*pBufSize >= len) {
430 strcpy(pBuffer, scp->mountPointStringp);
433 code = CM_ERROR_TOOBIG;
437 lock_ReleaseWrite(&scp->rw);
438 cm_ReleaseSCache(scp);
446 osi_Log1(afsd_logp,"cm_VolStatus_Path_To_DFSlink code 0x%x",code);