2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afs/param.h>
16 #include <sys/socket.h>
28 #include "afsd_init.h"
29 #include <WINNT\afsreg.h>
32 #include "cm_server.h"
45 #include <..\afsrdr\kif.h>
51 /* Copied from afs_tokens.h */
52 #define PIOCTL_LOGON 0x1
55 osi_mutex_t cm_Afsdsbmt_Lock;
57 extern afs_int32 cryptall;
58 extern char cm_NetbiosName[];
60 extern void afsi_log(char *pattern, ...);
62 void cm_InitIoctl(void)
64 lock_InitializeMutex(&cm_Afsdsbmt_Lock, "AFSDSBMT.INI Access Lock");
67 long cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
71 lock_ObtainWrite(&scp->bufCreateLock);
72 code = buf_FlushCleanPages(scp, userp, reqp);
74 lock_ObtainMutex(&scp->mx);
75 scp->cbServerp = NULL;
79 cm_FreeAllACLEnts(scp);
80 lock_ReleaseMutex(&scp->mx);
82 lock_ReleaseWrite(&scp->bufCreateLock);
83 afsi_log("cm_FlushFile scp 0x%x returns error: [%x]",scp, code);
88 * cm_ResetACLCache -- invalidate ACL info for a user that has just
89 * obtained or lost tokens
91 void cm_ResetACLCache(cm_user_t *userp)
96 lock_ObtainWrite(&cm_scacheLock);
97 for (hash=0; hash < cm_data.hashTableSize; hash++) {
98 for (scp=cm_data.hashTablep[hash]; scp; scp=scp->nextp) {
99 cm_HoldSCacheNoLock(scp);
100 lock_ReleaseWrite(&cm_scacheLock);
101 lock_ObtainMutex(&scp->mx);
102 cm_InvalidateACLUser(scp, userp);
103 lock_ReleaseMutex(&scp->mx);
104 lock_ObtainWrite(&cm_scacheLock);
105 cm_ReleaseSCacheNoLock(scp);
108 lock_ReleaseWrite(&cm_scacheLock);
112 * TranslateExtendedChars - This is a fix for TR 54482.
114 * If an extended character (80 - FF) is entered into a file
115 * or directory name in Windows, the character is translated
116 * into the OEM character map before being passed to us. Why
117 * this occurs is unknown. Our pioctl functions must match
118 * this translation for paths given via our own commands (like
119 * fs). If we do not do this, then we will try to perform an
120 * operation on a non-translated path, which we will fail to
121 * find, since the path was created with the translated chars.
122 * This function performs the required translation.
124 void TranslateExtendedChars(char *str)
137 while (*p) *p++ &= 0x7f; /* turn off high bit; probably not right */
141 /* parse the passed-in file name and do a namei on it. If we fail,
142 * return an error code, otherwise return the vnode located in *scpp.
144 long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
148 cm_scache_t *substRootp;
149 char * relativePath = ioctlp->inDatap;
151 char * absRoot[MAX_PATH];
153 wchar_t absRoot_w[MAX_PATH];
156 osi_Log1(afsd_logp, "cm_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,relativePath));
158 /* This is usually the file name, but for StatMountPoint it is the path. */
159 /* ioctlp->inDatap can be either of the form:
162 * \\netbios-name\submount\path\.
163 * \\netbios-name\submount\path\file
165 TranslateExtendedChars(relativePath);
168 /* we have passed the whole path, including the afs prefix.
169 when the pioctl call is made, we perform an ioctl to afsrdr
170 and it returns the correct (full) path. therefore, there is
171 no drive letter, and the path is absolute. */
172 code = cm_NameI(cm_data.rootSCachep, relativePath,
173 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
174 userp, "", reqp, scpp);
179 /* # of bytes of path */
180 code = strlen(ioctlp->inDatap) + 1;
181 ioctlp->inDatap += code;
183 /* This is usually nothing, but for StatMountPoint it is the file name. */
184 TranslateExtendedChars(ioctlp->inDatap);
189 if (relativePath[0] == relativePath[1] &&
190 relativePath[1] == '\\' &&
191 !_strnicmp(cm_NetbiosName,relativePath+2,strlen(cm_NetbiosName)))
197 /* We may have found a UNC path.
198 * If the first component is the NetbiosName,
199 * then throw out the second component (the submount)
200 * since it had better expand into the value of ioctl->tidPathp
203 p = relativePath + 2 + strlen(cm_NetbiosName) + 1; /* buffer overflow vuln.? */
204 if ( !_strnicmp("all", p, 3) )
207 for (i = 0; *p && *p != '\\'; i++,p++ ) {
210 p++; /* skip past trailing slash */
211 shareName[i] = 0; /* terminate string */
213 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
215 /* we found a sharename, therefore use the resulting path */
216 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
217 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
218 userp, sharePath, reqp, &substRootp);
223 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
224 userp, NULL, reqp, scpp);
228 /* otherwise, treat the name as a cellname mounted off the afs root.
229 * This requires that we reconstruct the shareName string with
230 * leading and trailing slashes.
232 p = relativePath + 2 + strlen(cm_NetbiosName) + 1;
233 if ( !_strnicmp("all", p, 3) )
237 for (i = 1; *p && *p != '\\'; i++,p++ ) {
240 p++; /* skip past trailing slash */
241 shareName[i++] = '/'; /* add trailing slash */
242 shareName[i] = 0; /* terminate string */
245 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
246 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
247 userp, shareName, reqp, &substRootp);
251 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
252 userp, NULL, reqp, scpp);
257 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
258 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
259 userp, ioctlp->tidPathp, reqp, &substRootp);
263 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
264 userp, NULL, reqp, scpp);
269 /* # of bytes of path */
270 code = (long)strlen(ioctlp->inDatap) + 1;
271 ioctlp->inDatap += code;
273 /* This is usually nothing, but for StatMountPoint it is the file name. */
274 TranslateExtendedChars(ioctlp->inDatap);
276 /* and return success */
280 void cm_SkipIoctlPath(smb_ioctl_t *ioctlp)
284 temp = (long) strlen(ioctlp->inDatap) + 1;
285 ioctlp->inDatap += temp;
289 /* format the specified path to look like "/afs/<cellname>/usr", by
290 * adding "/afs" (if necessary) in front, changing any \'s to /'s, and
291 * removing any trailing "/"'s. One weirdo caveat: "/afs" will be
292 * intentionally returned as "/afs/"--this makes submount manipulation
293 * easier (because we can always jump past the initial "/afs" to find
294 * the AFS path that should be written into afsdsbmt.ini).
296 void cm_NormalizeAfsPath(char *outpathp, long outlen, char *inpathp)
299 char bslash_mountRoot[256];
301 strncpy(bslash_mountRoot, cm_mountRoot, sizeof(bslash_mountRoot) - 1);
302 bslash_mountRoot[0] = '\\';
304 if (!strnicmp (inpathp, cm_mountRoot, strlen(cm_mountRoot)))
305 StringCbCopy(outpathp, outlen, inpathp);
306 else if (!strnicmp (inpathp, bslash_mountRoot, strlen(bslash_mountRoot)))
307 StringCbCopy(outpathp, outlen, inpathp);
308 else if ((inpathp[0] == '/') || (inpathp[0] == '\\'))
309 StringCbPrintfA(outpathp, outlen, "%s%s", cm_mountRoot, inpathp);
310 else // inpathp looks like "<cell>/usr"
311 StringCbPrintfA(outpathp, outlen, "%s/%s", cm_mountRoot, inpathp);
313 for (cp = outpathp; *cp != 0; ++cp) {
318 if (strlen(outpathp) && (outpathp[strlen(outpathp)-1] == '/')) {
319 outpathp[strlen(outpathp)-1] = 0;
322 if (!strcmpi (outpathp, cm_mountRoot)) {
323 StringCbCopy(outpathp, outlen, cm_mountRoot);
327 #define LEAF_SIZE 256
328 /* parse the passed-in file name and do a namei on its parent. If we fail,
329 * return an error code, otherwise return the vnode located in *scpp.
331 long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
332 cm_scache_t **scpp, char *leafp)
337 cm_scache_t *substRootp;
339 StringCbCopyA(tbuffer, sizeof(tbuffer), ioctlp->inDatap);
340 tp = strrchr(tbuffer, '\\');
341 jp = strrchr(tbuffer, '/');
344 else if (jp && (tp - tbuffer) < (jp - tbuffer))
347 StringCbCopyA(tbuffer, sizeof(tbuffer), "\\");
349 StringCbCopyA(leafp, LEAF_SIZE, ioctlp->inDatap);
354 StringCbCopyA(leafp, LEAF_SIZE, tp+1);
357 if (tbuffer[0] == tbuffer[1] &&
358 tbuffer[1] == '\\' &&
359 !_strnicmp(cm_NetbiosName,tbuffer+2,strlen(cm_NetbiosName)))
365 /* We may have found a UNC path.
366 * If the first component is the NetbiosName,
367 * then throw out the second component (the submount)
368 * since it had better expand into the value of ioctl->tidPathp
371 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
372 if ( !_strnicmp("all", p, 3) )
375 for (i = 0; *p && *p != '\\'; i++,p++ ) {
378 p++; /* skip past trailing slash */
379 shareName[i] = 0; /* terminate string */
381 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
383 /* we found a sharename, therefore use the resulting path */
384 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
385 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
386 userp, sharePath, reqp, &substRootp);
388 if (code) return code;
390 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
391 userp, NULL, reqp, scpp);
392 if (code) return code;
394 /* otherwise, treat the name as a cellname mounted off the afs root.
395 * This requires that we reconstruct the shareName string with
396 * leading and trailing slashes.
398 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
399 if ( !_strnicmp("all", p, 3) )
403 for (i = 1; *p && *p != '\\'; i++,p++ ) {
406 p++; /* skip past trailing slash */
407 shareName[i++] = '/'; /* add trailing slash */
408 shareName[i] = 0; /* terminate string */
410 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
411 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
412 userp, shareName, reqp, &substRootp);
413 if (code) return code;
415 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
416 userp, NULL, reqp, scpp);
417 if (code) return code;
420 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
421 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
422 userp, ioctlp->tidPathp, reqp, &substRootp);
423 if (code) return code;
425 code = cm_NameI(substRootp, tbuffer, CM_FLAG_FOLLOW,
426 userp, NULL, reqp, scpp);
427 if (code) return code;
430 /* # of bytes of path */
431 code = (long)strlen(ioctlp->inDatap) + 1;
432 ioctlp->inDatap += code;
434 /* and return success */
438 long cm_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp)
443 AFSFetchStatus fileStatus;
449 struct rx_connection * callp;
453 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
454 if (code) return code;
456 /* now make the get acl call */
457 fid.Volume = scp->fid.volume;
458 fid.Vnode = scp->fid.vnode;
459 fid.Unique = scp->fid.unique;
461 acl.AFSOpaque_val = ioctlp->outDatap;
462 acl.AFSOpaque_len = 0;
463 code = cm_Conn(&scp->fid, userp, &req, &connp);
466 callp = cm_GetRxConn(connp);
467 code = RXAFS_FetchACL(callp, &fid, &acl, &fileStatus, &volSync);
468 rx_PutConnection(callp);
470 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
471 code = cm_MapRPCError(code, &req);
472 cm_ReleaseSCache(scp);
474 if (code) return code;
476 /* skip over return data */
477 tlen = (int)strlen(ioctlp->outDatap) + 1;
478 ioctlp->outDatap += tlen;
480 /* and return success */
484 long cm_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp)
493 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
494 if (code) return code;
496 #ifdef AFS_FREELANCE_CLIENT
497 if ( cm_freelanceEnabled &&
498 scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
499 scp->fid.volume==AFS_FAKE_ROOT_VOL_ID &&
500 scp->fid.vnode==0x1 && scp->fid.unique==0x1 ) {
501 StringCbCopyA(ioctlp->outDatap, 999999, "Freelance.Local.Root");
502 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
505 #endif /* AFS_FREELANCE_CLIENT */
507 cellp = cm_FindCellByID(scp->fid.cell);
509 StringCbCopyA(ioctlp->outDatap, 999999, cellp->name);
510 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
514 code = CM_ERROR_NOSUCHCELL;
517 cm_ReleaseSCache(scp);
521 long cm_IoctlSetACL(struct smb_ioctl *ioctlp, struct cm_user *userp)
526 AFSFetchStatus fileStatus;
531 struct rx_connection * callp;
535 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
536 if (code) return code;
538 /* now make the get acl call */
539 fid.Volume = scp->fid.volume;
540 fid.Vnode = scp->fid.vnode;
541 fid.Unique = scp->fid.unique;
543 acl.AFSOpaque_val = ioctlp->inDatap;
544 acl.AFSOpaque_len = (u_int)strlen(ioctlp->inDatap)+1;
545 code = cm_Conn(&scp->fid, userp, &req, &connp);
548 callp = cm_GetRxConn(connp);
549 code = RXAFS_StoreACL(callp, &fid, &acl, &fileStatus, &volSync);
550 rx_PutConnection(callp);
552 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
553 code = cm_MapRPCError(code, &req);
555 /* invalidate cache info, since we just trashed the ACL cache */
556 lock_ObtainMutex(&scp->mx);
557 cm_DiscardSCache(scp);
558 lock_ReleaseMutex(&scp->mx);
560 cm_ReleaseSCache(scp);
565 long cm_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
574 lock_ObtainWrite(&cm_scacheLock);
575 for (i=0; i<cm_data.hashTableSize; i++) {
576 for (scp = cm_data.hashTablep[i]; scp; scp = scp->nextp) {
577 cm_HoldSCacheNoLock(scp);
578 lock_ReleaseWrite(&cm_scacheLock);
580 /* now flush the file */
581 code = cm_FlushFile(scp, userp, &req);
582 lock_ObtainWrite(&cm_scacheLock);
583 cm_ReleaseSCacheNoLock(scp);
586 lock_ReleaseWrite(&cm_scacheLock);
591 long cm_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp)
595 unsigned long volume;
601 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
602 if (code) return code;
604 volume = scp->fid.volume;
605 cm_ReleaseSCache(scp);
607 lock_ObtainWrite(&cm_scacheLock);
608 for (i=0; i<cm_data.hashTableSize; i++) {
609 for (scp = cm_data.hashTablep[i]; scp; scp = scp->nextp) {
610 if (scp->fid.volume == volume) {
611 cm_HoldSCacheNoLock(scp);
612 lock_ReleaseWrite(&cm_scacheLock);
614 /* now flush the file */
615 code = cm_FlushFile(scp, userp, &req);
616 lock_ObtainWrite(&cm_scacheLock);
617 cm_ReleaseSCacheNoLock(scp);
621 lock_ReleaseWrite(&cm_scacheLock);
626 long cm_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp)
634 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
635 if (code) return code;
637 cm_FlushFile(scp, userp, &req);
638 cm_ReleaseSCache(scp);
643 long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
647 char offLineMsg[256];
651 AFSFetchVolumeStatus volStat;
652 AFSStoreVolumeStatus storeStat;
657 struct rx_connection * callp;
661 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
662 if (code) return code;
664 cellp = cm_FindCellByID(scp->fid.cell);
667 if (scp->flags & CM_SCACHEFLAG_RO) {
668 cm_ReleaseSCache(scp);
669 return CM_ERROR_READONLY;
672 code = cm_GetVolumeByID(cellp, scp->fid.volume, userp, &req, &tvp);
674 cm_ReleaseSCache(scp);
678 /* Copy the junk out, using cp as a roving pointer. */
679 cp = ioctlp->inDatap;
680 memcpy((char *)&volStat, cp, sizeof(AFSFetchVolumeStatus));
681 cp += sizeof(AFSFetchVolumeStatus);
682 StringCbCopyA(volName, sizeof(volName), cp);
683 cp += strlen(volName)+1;
684 StringCbCopyA(offLineMsg, sizeof(offLineMsg), cp);
685 cp += strlen(offLineMsg)+1;
686 StringCbCopyA(motd, sizeof(motd), cp);
688 if (volStat.MinQuota != -1) {
689 storeStat.MinQuota = volStat.MinQuota;
690 storeStat.Mask |= AFS_SETMINQUOTA;
692 if (volStat.MaxQuota != -1) {
693 storeStat.MaxQuota = volStat.MaxQuota;
694 storeStat.Mask |= AFS_SETMAXQUOTA;
698 code = cm_Conn(&scp->fid, userp, &req, &tcp);
701 callp = cm_GetRxConn(tcp);
702 code = RXAFS_SetVolumeStatus(callp, scp->fid.volume,
703 &storeStat, volName, offLineMsg, motd);
704 rx_PutConnection(callp);
706 } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
707 code = cm_MapRPCError(code, &req);
709 /* return on failure */
710 cm_ReleaseSCache(scp);
715 /* we are sending parms back to make compat. with prev system. should
716 * change interface later to not ask for current status, just set
719 cp = ioctlp->outDatap;
720 memcpy(cp, (char *)&volStat, sizeof(VolumeStatus));
721 cp += sizeof(VolumeStatus);
722 StringCbCopyA(cp, 999999, volName);
723 cp += strlen(volName)+1;
724 StringCbCopyA(cp, 999999, offLineMsg);
725 cp += strlen(offLineMsg)+1;
726 StringCbCopyA(cp, 999999, motd);
727 cp += strlen(motd)+1;
729 /* now return updated return data pointer */
730 ioctlp->outDatap = cp;
735 long cm_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
739 char offLineMsg[256];
743 AFSFetchVolumeStatus volStat;
749 struct rx_connection * callp;
753 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
754 if (code) return code;
757 OfflineMsg = offLineMsg;
760 code = cm_Conn(&scp->fid, userp, &req, &tcp);
763 callp = cm_GetRxConn(tcp);
764 code = RXAFS_GetVolumeStatus(callp, scp->fid.volume,
765 &volStat, &Name, &OfflineMsg, &MOTD);
766 rx_PutConnection(callp);
768 } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
769 code = cm_MapRPCError(code, &req);
771 cm_ReleaseSCache(scp);
772 if (code) return code;
774 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
775 cp = ioctlp->outDatap;
776 memcpy(cp, (char *)&volStat, sizeof(AFSFetchVolumeStatus));
777 cp += sizeof(AFSFetchVolumeStatus);
778 StringCbCopyA(cp, 999999, volName);
779 cp += strlen(volName)+1;
780 StringCbCopyA(cp, 999999, offLineMsg);
781 cp += strlen(offLineMsg)+1;
782 StringCbCopyA(cp, 999999, motd);
783 cp += strlen(motd)+1;
785 /* return new size */
786 ioctlp->outDatap = cp;
791 long cm_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp)
801 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
802 if (code) return code;
804 memset(&fid, 0, sizeof(cm_fid_t));
805 fid.volume = scp->fid.volume;
806 fid.vnode = scp->fid.vnode;
807 fid.unique = scp->fid.unique;
809 cm_ReleaseSCache(scp);
811 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
812 cp = ioctlp->outDatap;
813 memcpy(cp, (char *)&fid, sizeof(cm_fid_t));
814 cp += sizeof(cm_fid_t);
816 /* return new size */
817 ioctlp->outDatap = cp;
822 long cm_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp)
831 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
832 if (code) return code;
834 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
835 cp = ioctlp->outDatap;
836 memcpy(cp, (char *)&scp->owner, sizeof(afs_uint32));
837 cp += sizeof(afs_uint32);
838 memcpy(cp, (char *)&scp->group, sizeof(afs_uint32));
839 cp += sizeof(afs_uint32);
841 /* return new size */
842 ioctlp->outDatap = cp;
844 cm_ReleaseSCache(scp);
849 long cm_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp)
855 cm_serverRef_t **tsrpp, *current;
857 unsigned long volume;
863 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
864 if (code) return code;
866 volume = scp->fid.volume;
868 cellp = cm_FindCellByID(scp->fid.cell);
871 cm_ReleaseSCache(scp);
873 code = cm_GetVolumeByID(cellp, volume, userp, &req, &tvp);
874 if (code) return code;
876 cp = ioctlp->outDatap;
878 lock_ObtainMutex(&tvp->mx);
879 tsrpp = cm_GetVolServers(tvp, volume);
880 lock_ObtainRead(&cm_serverLock);
881 for (current = *tsrpp; current; current = current->next) {
882 tsp = current->server;
883 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
886 lock_ReleaseRead(&cm_serverLock);
887 cm_FreeServerList(tsrpp);
888 lock_ReleaseMutex(&tvp->mx);
890 /* still room for terminating NULL, add it on */
891 volume = 0; /* reuse vbl */
892 memcpy(cp, (char *)&volume, sizeof(long));
895 ioctlp->outDatap = cp;
900 long cm_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
910 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
911 if (code) return code;
913 cp = ioctlp->inDatap;
915 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
916 cm_ReleaseSCache(dscp);
917 if (code) return code;
919 lock_ObtainMutex(&scp->mx);
921 /* now check that this is a real mount point */
922 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
923 lock_ReleaseMutex(&scp->mx);
924 cm_ReleaseSCache(scp);
925 return CM_ERROR_INVAL;
928 code = cm_ReadMountPoint(scp, userp, &req);
930 cp = ioctlp->outDatap;
931 StringCbCopyA(cp, 999999, scp->mountPointStringp);
932 cp += strlen(cp) + 1;
933 ioctlp->outDatap = cp;
935 lock_ReleaseMutex(&scp->mx);
936 cm_ReleaseSCache(scp);
941 long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
951 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
952 if (code) return code;
954 cp = ioctlp->inDatap;
956 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
958 /* if something went wrong, bail out now */
963 lock_ObtainMutex(&scp->mx);
964 code = cm_SyncOp(scp, NULL, userp, &req, 0,
965 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
967 lock_ReleaseMutex(&scp->mx);
968 cm_ReleaseSCache(scp);
972 /* now check that this is a real mount point */
973 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
974 lock_ReleaseMutex(&scp->mx);
975 cm_ReleaseSCache(scp);
976 code = CM_ERROR_INVAL;
980 /* time to make the RPC, so drop the lock */
981 lock_ReleaseMutex(&scp->mx);
982 cm_ReleaseSCache(scp);
984 /* easier to do it this way */
985 code = cm_Unlink(dscp, cp, userp, &req);
986 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
987 smb_NotifyChange(FILE_ACTION_REMOVED,
988 FILE_NOTIFY_CHANGE_DIR_NAME,
989 dscp, cp, NULL, TRUE);
992 cm_ReleaseSCache(dscp);
996 long cm_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp)
1006 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1007 tp = ioctlp->inDatap;
1010 memcpy(&temp, tp, sizeof(temp));
1011 if (temp == 0x12345678) { /* For afs3.3 version */
1012 memcpy(&csi, tp, sizeof(csi));
1013 if (csi.tinterval >= 0) {
1014 cp = ioctlp->outDatap;
1015 memcpy(cp, (char *)&cm_daemonCheckDownInterval, sizeof(long));
1016 ioctlp->outDatap += sizeof(long);
1017 if (csi.tinterval > 0) {
1018 if (!smb_SUser(userp))
1019 return CM_ERROR_NOACCESS;
1020 cm_daemonCheckDownInterval = csi.tinterval;
1028 } else { /* For pre afs3.3 versions */
1029 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
1030 ioctlp->inDatap = cp = ioctlp->inDatap + sizeof(long);
1031 if (cp - ioctlp->inAllocp < ioctlp->inCopied) /* still more data available */
1036 * 1: fast check, don't contact servers.
1037 * 2: local cell only.
1040 /* have cell name, too */
1041 cellp = cm_GetCell(cp, 0);
1042 if (!cellp) return CM_ERROR_NOSUCHCELL;
1044 else cellp = (cm_cell_t *) 0;
1045 if (!cellp && (temp & 2)) {
1046 /* use local cell */
1047 cellp = cm_FindCellByID(1);
1049 if (!(temp & 1)) { /* if not fast, call server checker routine */
1050 /* check down servers */
1051 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS | CM_FLAG_CHECKUPSERVERS,
1055 /* now return the current down server list */
1056 cp = ioctlp->outDatap;
1057 lock_ObtainRead(&cm_serverLock);
1058 for (tsp = cm_allServersp; tsp; tsp=tsp->allNextp) {
1059 if (cellp && tsp->cellp != cellp) continue; /* cell spec'd and wrong */
1060 if ((tsp->flags & CM_SERVERFLAG_DOWN)
1061 && tsp->type == CM_SERVER_FILE) {
1062 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
1066 lock_ReleaseRead(&cm_serverLock);
1068 ioctlp->outDatap = cp;
1072 long cm_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp)
1074 /* we don't print anything superfluous, so we don't support the gag call */
1075 return CM_ERROR_INVAL;
1078 long cm_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
1084 long cm_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp)
1089 cm_SkipIoctlPath(ioctlp);
1091 memcpy(&temp, ioctlp->inDatap, sizeof(temp));
1093 temp = cm_data.buf_nOrigBuffers;
1095 /* temp is in 1K units, convert to # of buffers */
1096 temp = temp / (cm_data.buf_blockSize / 1024);
1099 /* now adjust the cache size */
1100 code = buf_SetNBuffers(temp);
1105 long cm_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
1109 cm_SkipIoctlPath(ioctlp);
1111 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
1115 afsd_ForceTrace(FALSE);
1116 buf_ForceTrace(FALSE);
1120 /* set tracing value to low order bit */
1121 if ((inValue & 1) == 0) {
1122 /* disable tracing */
1123 osi_LogDisable(afsd_logp);
1126 /* enable tracing */
1127 osi_LogEnable(afsd_logp);
1131 /* see if we're supposed to do a reset, too */
1133 osi_LogReset(afsd_logp);
1136 /* and copy out tracing flag */
1137 inValue = afsd_logp->enabled; /* use as a temp vbl */
1138 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
1139 ioctlp->outDatap += sizeof(long);
1143 long cm_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp)
1145 cm_cacheParms_t parms;
1147 memset(&parms, 0, sizeof(parms));
1149 /* first we get, in 1K units, the cache size */
1150 parms.parms[0] = cm_data.buf_nbuffers * (cm_data.buf_blockSize / 1024);
1152 /* and then the actual # of buffers in use (not in the free list, I guess,
1153 * will be what we do).
1155 parms.parms[1] = (cm_data.buf_nbuffers - buf_CountFreeList()) * (cm_data.buf_blockSize / 1024);
1157 memcpy(ioctlp->outDatap, &parms, sizeof(parms));
1158 ioctlp->outDatap += sizeof(parms);
1163 long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1168 cm_serverRef_t *serverRefp;
1169 cm_server_t *serverp;
1175 cm_SkipIoctlPath(ioctlp);
1177 tp = ioctlp->inDatap;
1179 memcpy((char *)&whichCell, tp, sizeof(long));
1182 /* see if more than one long passed in, ignoring the null pathname (the -1) */
1183 if (ioctlp->inCopied-1 > sizeof(long)) {
1184 memcpy((char *)&magic, tp, sizeof(long));
1187 lock_ObtainRead(&cm_cellLock);
1188 for (tcellp = cm_data.allCellsp; tcellp; tcellp = tcellp->nextp) {
1189 if (whichCell == 0) break;
1192 lock_ReleaseRead(&cm_cellLock);
1196 cp = ioctlp->outDatap;
1198 if (magic == 0x12345678) {
1199 memcpy(cp, (char *)&magic, sizeof(long));
1202 memset(cp, 0, max * sizeof(long));
1204 lock_ObtainRead(&cm_serverLock); /* for going down server list */
1205 /* jaltman - do the reference counts to serverRefp contents need to be increased? */
1206 serverRefp = tcellp->vlServersp;
1207 for (i=0; i<max; i++) {
1208 if (!serverRefp) break;
1209 serverp = serverRefp->server;
1210 memcpy(cp, &serverp->addr.sin_addr.s_addr, sizeof(long));
1212 serverRefp = serverRefp->next;
1214 lock_ReleaseRead(&cm_serverLock);
1215 cp = basep + max * sizeof(afs_int32);
1216 StringCbCopyA(cp, 999999, tcellp->name);
1217 cp += strlen(tcellp->name)+1;
1218 ioctlp->outDatap = cp;
1224 return CM_ERROR_NOMORETOKENS; /* mapped to EDOM */
1227 extern long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *namep);
1229 long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1231 /* NT cache manager will read cell information from CellServDB each time
1232 * cell is accessed. So, this call is necessary only if list of server for a cell
1233 * changes (or IP addresses of cell servers changes).
1234 * All that needs to be done is to refresh server information for all cells that
1235 * are already loaded.
1237 * cell list will be cm_CellLock and cm_ServerLock will be held for write.
1242 cm_SkipIoctlPath(ioctlp);
1243 lock_ObtainWrite(&cm_cellLock);
1245 for (cp = cm_data.allCellsp; cp; cp=cp->nextp)
1248 /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
1249 cm_FreeServerList(&cp->vlServersp);
1250 cp->vlServersp = NULL;
1251 code = cm_SearchCellFile(cp->name, cp->name, cm_AddCellProc, cp);
1252 #ifdef AFS_AFSDB_ENV
1254 if (cm_dnsEnabled) {
1256 code = cm_SearchCellByDNS(cp->name, cp->name, &ttl, cm_AddCellProc, cp);
1257 if ( code == 0 ) { /* got cell from DNS */
1258 cp->flags |= CM_CELLFLAG_DNS;
1259 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1260 cp->timeout = time(0) + ttl;
1265 cp->flags &= ~CM_CELLFLAG_DNS;
1267 #endif /* AFS_AFSDB_ENV */
1269 cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
1272 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1273 cm_RandomizeServer(&cp->vlServersp);
1277 lock_ReleaseWrite(&cm_cellLock);
1281 long cm_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
1285 if (cm_freelanceEnabled) {
1286 if (cm_GetRootCellName(ioctlp->outDatap))
1287 StringCbCopyA(ioctlp->outDatap, 999999, "Freelance.Local.Root");
1288 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1289 } else if (cm_data.rootCellp) {
1290 /* return the default cellname to the caller */
1291 StringCbCopyA(ioctlp->outDatap, 999999, cm_data.rootCellp->name);
1292 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1294 /* if we don't know our default cell, return failure */
1295 code = CM_ERROR_NOSUCHCELL;
1301 long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp)
1303 long setSysName, foundname = 0;
1304 char *cp, *cp2, inname[MAXSYSNAME], outname[MAXSYSNAME];
1305 int t, count, num = 0;
1306 char **sysnamelist[MAXSYSNAME];
1308 cm_SkipIoctlPath(ioctlp);
1310 memcpy(&setSysName, ioctlp->inDatap, sizeof(long));
1311 ioctlp->inDatap += sizeof(long);
1315 if ( setSysName < 0 || setSysName > MAXNUMSYSNAMES )
1317 cp2 = ioctlp->inDatap;
1318 for ( cp=ioctlp->inDatap, count = 0; count < setSysName; count++ ) {
1319 /* won't go past end of ioctlp->inDatap since maxsysname*num < ioctlp->inDatap length */
1320 t = (int)strlen(cp);
1321 if (t >= MAXSYSNAME || t <= 0)
1323 /* check for names that can shoot us in the foot */
1324 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
1330 /* inname gets first entry in case we're being a translator */
1331 /* (we are never a translator) */
1332 t = (int)strlen(ioctlp->inDatap);
1333 memcpy(inname, ioctlp->inDatap, t + 1);
1334 ioctlp->inDatap += t + 1;
1338 /* Not xlating, so local case */
1340 osi_panic("cm_IoctlSysName: !cm_sysName\n", __FILE__, __LINE__);
1342 if (!setSysName) { /* user just wants the info */
1343 StringCbCopyA(outname, sizeof(outname), cm_sysName);
1344 foundname = cm_sysNameCount;
1345 *sysnamelist = cm_sysNameList;
1347 /* Local guy; only root can change sysname */
1348 /* clear @sys entries from the dnlc, once afs_lookup can
1349 * do lookups of @sys entries and thinks it can trust them */
1350 /* privs ok, store the entry, ... */
1351 StringCbCopyA(cm_sysName, sizeof(cm_sysName), inname);
1352 StringCbCopyA(cm_sysNameList[0], MAXSYSNAME, inname);
1353 if (setSysName > 1) { /* ... or list */
1354 cp = ioctlp->inDatap;
1355 for (count = 1; count < setSysName; ++count) {
1356 if (!cm_sysNameList[count])
1357 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to write\n",
1358 __FILE__, __LINE__);
1359 t = (int)strlen(cp);
1360 StringCbCopyA(cm_sysNameList[count], MAXSYSNAME, cp);
1364 cm_sysNameCount = setSysName;
1368 /* return the sysname to the caller */
1369 cp = ioctlp->outDatap;
1370 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
1371 cp += sizeof(afs_int32); /* skip found flag */
1373 StringCbCopyA(cp, 999999, outname);
1374 cp += strlen(outname) + 1; /* skip name and terminating null char */
1375 for ( count=1; count < foundname ; ++count) { /* ... or list */
1376 if ( !(*sysnamelist)[count] )
1377 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to read\n",
1378 __FILE__, __LINE__);
1379 t = (int)strlen((*sysnamelist)[count]);
1380 if (t >= MAXSYSNAME)
1381 osi_panic("cm_IoctlSysName: sysname entry garbled\n",
1382 __FILE__, __LINE__);
1383 StringCbCopyA(cp, 999999, (*sysnamelist)[count]);
1387 ioctlp->outDatap = cp;
1394 long cm_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1399 cm_SkipIoctlPath(ioctlp);
1401 cellp = cm_GetCell(ioctlp->inDatap, 0);
1403 return CM_ERROR_NOSUCHCELL;
1406 lock_ObtainMutex(&cellp->mx);
1407 if (cellp->flags & CM_CELLFLAG_SUID)
1408 temp |= CM_SETCELLFLAG_SUID;
1409 lock_ReleaseMutex(&cellp->mx);
1411 /* now copy out parm */
1412 memcpy(ioctlp->outDatap, &temp, sizeof(long));
1413 ioctlp->outDatap += sizeof(long);
1418 long cm_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1423 cm_SkipIoctlPath(ioctlp);
1425 cellp = cm_GetCell(ioctlp->inDatap + 2*sizeof(long), 0);
1427 return CM_ERROR_NOSUCHCELL;
1429 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
1431 lock_ObtainMutex(&cellp->mx);
1432 if (temp & CM_SETCELLFLAG_SUID)
1433 cellp->flags |= CM_CELLFLAG_SUID;
1435 cellp->flags &= ~CM_CELLFLAG_SUID;
1436 lock_ReleaseMutex(&cellp->mx);
1441 long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1443 cm_SSetPref_t *spin; /* input */
1444 cm_SPref_t *srvin; /* one input component */
1446 int i, vlonly, noServers, type;
1447 struct sockaddr_in tmp;
1448 unsigned short rank;
1450 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1452 spin = (cm_SSetPref_t *)ioctlp->inDatap;
1453 noServers = spin->num_servers;
1454 vlonly = spin->flags;
1456 type = CM_SERVER_VLDB;
1458 type = CM_SERVER_FILE;
1460 for ( i=0; i < noServers; i++)
1462 srvin = &(spin->servers[i]);
1463 rank = srvin->rank + (rand() & 0x000f);
1464 tmp.sin_addr = srvin->host;
1465 tmp.sin_family = AF_INET;
1467 tsp = cm_FindServer(&tmp, type);
1468 if ( tsp ) /* an existing server - ref count increased */
1470 tsp->ipRank = rank; /* no need to protect by mutex*/
1472 if (type == CM_SERVER_FILE)
1474 /* find volumes which might have RO copy
1475 /* on server and change the ordering of
1478 cm_ChangeRankVolume(tsp);
1482 /* set preferences for an existing vlserver */
1483 cm_ChangeRankCellVLServer(tsp);
1485 cm_PutServer(tsp); /* decrease refcount */
1487 else /* add a new server without a cell */
1489 tsp = cm_NewServer(&tmp, type, NULL); /* refcount = 1 */
1496 long cm_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1498 cm_SPrefRequest_t *spin; /* input */
1499 cm_SPrefInfo_t *spout; /* output */
1500 cm_SPref_t *srvout; /* one output component */
1502 int i, vlonly, noServers;
1504 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1506 spin = (cm_SPrefRequest_t *)ioctlp->inDatap;
1507 spout = (cm_SPrefInfo_t *) ioctlp->outDatap;
1508 srvout = spout->servers;
1509 noServers = spin->num_servers;
1510 vlonly = spin->flags & CM_SPREF_VLONLY;
1511 spout->num_servers = 0;
1513 lock_ObtainRead(&cm_serverLock); /* get server lock */
1515 for (tsp=cm_allServersp, i=0; tsp && noServers; tsp=tsp->allNextp,i++){
1516 if (spin->offset > i) {
1517 continue; /* catch up to where we left off */
1520 if ( vlonly && (tsp->type == CM_SERVER_FILE) )
1521 continue; /* ignore fileserver for -vlserver option*/
1522 if ( !vlonly && (tsp->type == CM_SERVER_VLDB) )
1523 continue; /* ignore vlservers */
1525 srvout->host = tsp->addr.sin_addr;
1526 srvout->rank = tsp->ipRank;
1528 spout->num_servers++;
1531 lock_ReleaseRead(&cm_serverLock); /* release server lock */
1533 if ( tsp ) /* we ran out of space in the output buffer */
1534 spout->next_offset = i;
1536 spout->next_offset = 0;
1537 ioctlp->outDatap += sizeof(cm_SPrefInfo_t) +
1538 (spout->num_servers -1 ) * sizeof(cm_SPref_t) ;
1542 long cm_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp)
1544 /* we ignore default asynchrony since we only have one way
1545 * of doing this today.
1550 long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1552 char leaf[LEAF_SIZE];
1566 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1567 if (code) return code;
1569 /* Translate chars for the mount point name */
1570 TranslateExtendedChars(leaf);
1573 * The fs command allows the user to specify partial cell names on NT. These must
1574 * be expanded to the full cell name for mount points so that the mount points will
1575 * work on UNIX clients.
1578 /* Extract the possibly partial cell name */
1579 StringCbCopyA(cell, sizeof(cell), ioctlp->inDatap + 1); /* Skip the mp type character */
1581 if (cp = strchr(cell, ':')) {
1582 /* Extract the volume name */
1584 StringCbCopyA(volume, sizeof(volume), cp + 1);
1586 /* Get the full name for this cell */
1587 code = cm_SearchCellFile(cell, fullCell, 0, 0);
1588 #ifdef AFS_AFSDB_ENV
1589 if (code && cm_dnsEnabled)
1590 code = cm_SearchCellByDNS(cell, fullCell, &ttl, 0, 0);
1593 return CM_ERROR_NOSUCHCELL;
1595 StringCbPrintfA(mpInfo, sizeof(mpInfo), "%c%s:%s", *ioctlp->inDatap, fullCell, volume);
1597 /* No cell name specified */
1598 StringCbCopyA(mpInfo, sizeof(mpInfo), ioctlp->inDatap);
1601 #ifdef AFS_FREELANCE_CLIENT
1602 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1603 /* we are adding the mount point to the root dir., so call
1604 * the freelance code to do the add. */
1605 osi_Log0(afsd_logp,"IoctlCreateMountPoint within Freelance root dir");
1606 code = cm_FreelanceAddMount(leaf, fullCell, volume,
1607 *ioctlp->inDatap == '%', NULL);
1611 /* create the symlink with mode 644. The lack of X bits tells
1612 * us that it is a mount point.
1614 tattr.mask = CM_ATTRMASK_UNIXMODEBITS | CM_ATTRMASK_CLIENTMODTIME;
1615 tattr.unixModeBits = 0644;
1616 tattr.clientModTime = time(NULL);
1618 code = cm_SymLink(dscp, leaf, mpInfo, 0, &tattr, userp, &req);
1619 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1620 smb_NotifyChange(FILE_ACTION_ADDED,
1621 FILE_NOTIFY_CHANGE_DIR_NAME,
1622 dscp, leaf, NULL, TRUE);
1624 cm_ReleaseSCache(dscp);
1628 long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1630 char leaf[LEAF_SIZE];
1639 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1640 if (code) return code;
1642 /* Translate chars for the link name */
1643 TranslateExtendedChars(leaf);
1645 /* Translate chars for the linked to name */
1646 TranslateExtendedChars(ioctlp->inDatap);
1648 cp = ioctlp->inDatap; /* contents of link */
1650 #ifdef AFS_FREELANCE_CLIENT
1651 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1652 /* we are adding the symlink to the root dir., so call
1653 * the freelance code to do the add. */
1654 if (cp[0] == cp[1] && cp[1] == '\\' &&
1655 !_strnicmp(cm_NetbiosName,cp+2,strlen(cm_NetbiosName)))
1657 /* skip \\AFS\ or \\AFS\all\ */
1659 p = cp + 2 + strlen(cm_NetbiosName) + 1;
1660 if ( !_strnicmp("all", p, 3) )
1664 osi_Log0(afsd_logp,"IoctlCreateSymlink within Freelance root dir");
1665 code = cm_FreelanceAddSymlink(leaf, cp, NULL);
1670 /* Create symlink with mode 0755. */
1671 tattr.mask = CM_ATTRMASK_UNIXMODEBITS;
1672 tattr.unixModeBits = 0755;
1674 code = cm_SymLink(dscp, leaf, cp, 0, &tattr, userp, &req);
1675 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1676 smb_NotifyChange(FILE_ACTION_ADDED,
1677 FILE_NOTIFY_CHANGE_FILE_NAME
1678 | FILE_NOTIFY_CHANGE_DIR_NAME,
1679 dscp, leaf, NULL, TRUE);
1681 cm_ReleaseSCache(dscp);
1687 long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1694 cm_scache_t *newRootScp;
1699 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1700 if (code) return code;
1702 cp = ioctlp->inDatap;
1704 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1705 cm_ReleaseSCache(dscp);
1706 if (code) return code;
1708 /* Check that it's a real symlink */
1709 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1710 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1711 scp->fileType != CM_SCACHETYPE_INVALID) {
1712 cm_ReleaseSCache(scp);
1713 return CM_ERROR_INVAL;
1716 code = cm_AssembleLink(scp, "", &newRootScp, &spacep, userp, &req);
1717 cm_ReleaseSCache(scp);
1719 cp = ioctlp->outDatap;
1720 if (newRootScp != NULL) {
1721 StringCbCopyA(cp, 999999, cm_mountRoot);
1722 StringCbCatA(cp, 999999, "/");
1725 StringCbCopyA(cp, 999999, spacep->data);
1726 cp += strlen(cp) + 1;
1727 ioctlp->outDatap = cp;
1728 cm_FreeSpace(spacep);
1729 if (newRootScp != NULL)
1730 cm_ReleaseSCache(newRootScp);
1732 } else if (code == CM_ERROR_PATH_NOT_COVERED &&
1733 scp->fileType == CM_SCACHETYPE_DFSLINK ||
1734 code == CM_ERROR_NOSUCHPATH &&
1735 scp->fileType == CM_SCACHETYPE_INVALID) {
1736 cp = ioctlp->outDatap;
1737 StringCbCopyA(cp, 999999, spacep->data);
1738 cp += strlen(cp) + 1;
1739 ioctlp->outDatap = cp;
1740 cm_FreeSpace(spacep);
1741 if (newRootScp != NULL)
1742 cm_ReleaseSCache(newRootScp);
1749 long cm_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1750 {/*CHECK FOR VALID SYMLINK*/
1759 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1760 if (code) return code;
1762 cp = ioctlp->inDatap;
1763 osi_LogEvent("cm_IoctlListlink",NULL," name[%s]",cp);
1765 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1766 cm_ReleaseSCache(dscp);
1767 if (code) return code;
1769 /* Check that it's a real symlink */
1770 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1771 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1772 scp->fileType != CM_SCACHETYPE_INVALID)
1773 code = CM_ERROR_INVAL;
1774 cm_ReleaseSCache(scp);
1778 long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1788 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1789 if (code) return code;
1791 cp = ioctlp->inDatap;
1793 #ifdef AFS_FREELANCE_CLIENT
1794 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1795 /* we are adding the mount point to the root dir., so call
1796 * the freelance code to do the add. */
1797 osi_Log0(afsd_logp,"IoctlDeletelink from Freelance root dir");
1798 code = cm_FreelanceRemoveSymlink(cp);
1803 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1805 /* if something went wrong, bail out now */
1810 lock_ObtainMutex(&scp->mx);
1811 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1812 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1814 lock_ReleaseMutex(&scp->mx);
1815 cm_ReleaseSCache(scp);
1819 /* now check that this is a real symlink */
1820 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1821 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1822 scp->fileType != CM_SCACHETYPE_INVALID) {
1823 lock_ReleaseMutex(&scp->mx);
1824 cm_ReleaseSCache(scp);
1825 code = CM_ERROR_INVAL;
1829 /* time to make the RPC, so drop the lock */
1830 lock_ReleaseMutex(&scp->mx);
1831 cm_ReleaseSCache(scp);
1833 /* easier to do it this way */
1834 code = cm_Unlink(dscp, cp, userp, &req);
1835 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1836 smb_NotifyChange(FILE_ACTION_REMOVED,
1837 FILE_NOTIFY_CHANGE_FILE_NAME
1838 | FILE_NOTIFY_CHANGE_DIR_NAME,
1839 dscp, cp, NULL, TRUE);
1842 cm_ReleaseSCache(dscp);
1846 long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
1853 struct ClearToken ct;
1862 saveDataPtr = ioctlp->inDatap;
1864 cm_SkipIoctlPath(ioctlp);
1866 tp = ioctlp->inDatap;
1869 memcpy(&ticketLen, tp, sizeof(ticketLen));
1870 tp += sizeof(ticketLen);
1871 if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN)
1872 return CM_ERROR_INVAL;
1874 /* remember ticket and skip over it for now */
1878 /* clear token size */
1879 memcpy(&ctSize, tp, sizeof(ctSize));
1880 tp += sizeof(ctSize);
1881 if (ctSize != sizeof(struct ClearToken))
1882 return CM_ERROR_INVAL;
1885 memcpy(&ct, tp, ctSize);
1887 if (ct.AuthHandle == -1)
1888 ct.AuthHandle = 999; /* more rxvab compat stuff */
1890 /* more stuff, if any */
1891 if (ioctlp->inCopied > tp - saveDataPtr) {
1892 /* flags: logon flag */
1893 memcpy(&flags, tp, sizeof(int));
1897 cellp = cm_GetCell(tp, CM_FLAG_CREATE);
1898 if (!cellp) return CM_ERROR_NOSUCHCELL;
1899 tp += strlen(tp) + 1;
1903 tp += strlen(tp) + 1;
1905 #ifndef AFSIFS /* no SMB username, so we cannot log based on this */
1906 if (flags & PIOCTL_LOGON) {
1907 /* SMB user name with which to associate tokens */
1909 osi_Log2(smb_logp,"cm_IoctlSetToken for user [%s] smbname [%s]",
1910 osi_LogSaveString(smb_logp,uname), osi_LogSaveString(smb_logp,smbname));
1911 fprintf(stderr, "SMB name = %s\n", smbname);
1912 tp += strlen(tp) + 1;
1914 osi_Log1(smb_logp,"cm_IoctlSetToken for user [%s]",
1915 osi_LogSaveString(smb_logp,uname));
1919 #ifndef DJGPP /* for win95, session key is back in pioctl */
1921 memcpy(&uuid, tp, sizeof(uuid));
1922 if (!cm_FindTokenEvent(uuid, sessionKey))
1923 return CM_ERROR_INVAL;
1926 cellp = cm_data.rootCellp;
1927 osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
1930 if (flags & PIOCTL_LOGON) {
1931 userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname);
1934 /* store the token */
1935 lock_ObtainMutex(&userp->mx);
1936 ucellp = cm_GetUCell(userp, cellp);
1937 osi_Log1(smb_logp,"cm_IoctlSetToken ucellp %lx", ucellp);
1938 ucellp->ticketLen = ticketLen;
1939 if (ucellp->ticketp)
1940 free(ucellp->ticketp); /* Discard old token if any */
1941 ucellp->ticketp = malloc(ticketLen);
1942 memcpy(ucellp->ticketp, ticket, ticketLen);
1945 * Get the session key from the RPC, rather than from the pioctl.
1948 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
1950 memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
1952 /* for win95, we are getting the session key from the pioctl */
1953 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
1955 ucellp->kvno = ct.AuthHandle;
1956 ucellp->expirationTime = ct.EndTimestamp;
1959 StringCbCopyA(ucellp->userName, MAXKTCNAMELEN, uname);
1960 ucellp->flags |= CM_UCELLFLAG_RXKAD;
1961 lock_ReleaseMutex(&userp->mx);
1963 if (flags & PIOCTL_LOGON) {
1964 ioctlp->flags |= SMB_IOCTLFLAG_LOGON;
1967 cm_ResetACLCache(userp);
1972 long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
1978 struct ClearToken ct;
1980 cm_SkipIoctlPath(ioctlp);
1982 tp = ioctlp->inDatap;
1983 cp = ioctlp->outDatap;
1986 memcpy(&iterator, tp, sizeof(iterator));
1987 tp += sizeof(iterator);
1989 lock_ObtainMutex(&userp->mx);
1991 /* look for token */
1992 for (;;iterator++) {
1993 ucellp = cm_FindUCell(userp, iterator);
1995 lock_ReleaseMutex(&userp->mx);
1996 return CM_ERROR_NOMORETOKENS;
1998 if (ucellp->flags & CM_UCELLFLAG_RXKAD)
2003 temp = ucellp->iterator + 1;
2004 memcpy(cp, &temp, sizeof(temp));
2008 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2009 cp += sizeof(ucellp->ticketLen);
2012 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2013 cp += ucellp->ticketLen;
2015 /* clear token size */
2017 memcpy(cp, &temp, sizeof(temp));
2021 ct.AuthHandle = ucellp->kvno;
2024 * Don't give out a real session key here
2027 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2029 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2031 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2033 ct.ViceId = 37; /* XXX */
2034 ct.BeginTimestamp = 0; /* XXX */
2035 ct.EndTimestamp = ucellp->expirationTime;
2036 memcpy(cp, &ct, sizeof(ct));
2039 /* Primary flag (unused) */
2041 memcpy(cp, &temp, sizeof(temp));
2045 StringCbCopyA(cp, 999999, ucellp->cellp->name);
2046 cp += strlen(cp) + 1;
2049 StringCbCopyA(cp, 999999, ucellp->userName);
2050 cp += strlen(cp) + 1;
2052 ioctlp->outDatap = cp;
2054 lock_ReleaseMutex(&userp->mx);
2059 long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2065 struct ClearToken ct;
2071 cm_SkipIoctlPath(ioctlp);
2073 tp = ioctlp->inDatap;
2075 cp = ioctlp->outDatap;
2077 /* cell name is right here */
2078 cellp = cm_GetCell(tp, 0);
2080 return CM_ERROR_NOSUCHCELL;
2081 tp += strlen(tp) + 1;
2085 memcpy(&uuid, tp, sizeof(uuid));
2088 lock_ObtainMutex(&userp->mx);
2090 ucellp = cm_GetUCell(userp, cellp);
2091 if (!ucellp || !(ucellp->flags & CM_UCELLFLAG_RXKAD)) {
2092 lock_ReleaseMutex(&userp->mx);
2093 return CM_ERROR_NOMORETOKENS;
2097 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2098 cp += sizeof(ucellp->ticketLen);
2101 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2102 cp += ucellp->ticketLen;
2104 /* clear token size */
2106 memcpy(cp, &temp, sizeof(temp));
2110 ct.AuthHandle = ucellp->kvno;
2113 * Don't give out a real session key here
2116 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2118 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2120 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2122 ct.ViceId = 37; /* XXX */
2123 ct.BeginTimestamp = 0; /* XXX */
2124 ct.EndTimestamp = ucellp->expirationTime;
2125 memcpy(cp, &ct, sizeof(ct));
2128 /* Primary flag (unused) */
2130 memcpy(cp, &temp, sizeof(temp));
2134 StringCbCopyA(cp, 999999, ucellp->cellp->name);
2135 cp += strlen(cp) + 1;
2138 StringCbCopyA(cp, 999999, ucellp->userName);
2139 cp += strlen(cp) + 1;
2141 ioctlp->outDatap = cp;
2143 lock_ReleaseMutex(&userp->mx);
2146 cm_RegisterNewTokenEvent(uuid, ucellp->sessionKey.data);
2152 long cm_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2158 cm_SkipIoctlPath(ioctlp);
2160 cp = ioctlp->outDatap;
2162 /* cell name is right here */
2163 cellp = cm_GetCell(ioctlp->inDatap, 0);
2164 if (!cellp) return CM_ERROR_NOSUCHCELL;
2166 lock_ObtainMutex(&userp->mx);
2168 ucellp = cm_GetUCell(userp, cellp);
2170 lock_ReleaseMutex(&userp->mx);
2171 return CM_ERROR_NOMORETOKENS;
2174 osi_Log1(smb_logp,"cm_IoctlDelToken ucellp %lx", ucellp);
2176 if (ucellp->ticketp) {
2177 free(ucellp->ticketp);
2178 ucellp->ticketp = NULL;
2180 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2183 lock_ReleaseMutex(&userp->mx);
2185 cm_ResetACLCache(userp);
2190 long cm_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2194 lock_ObtainMutex(&userp->mx);
2196 for (ucellp = userp->cellInfop; ucellp; ucellp = ucellp->nextp) {
2197 osi_Log1(smb_logp,"cm_IoctlDelAllToken ucellp %lx", ucellp);
2198 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2202 lock_ReleaseMutex(&userp->mx);
2204 cm_ResetACLCache(userp);
2209 long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
2211 char afspath[MAX_PATH];
2213 int nextAutoSubmount;
2215 DWORD dwType, dwSize;
2220 cm_SkipIoctlPath(ioctlp);
2222 /* Serialize this one, to prevent simultaneous mods
2225 lock_ObtainMutex(&cm_Afsdsbmt_Lock);
2227 /* Parse the input parameters--first the required afs path,
2228 * then the requested submount name (which may be "").
2230 cm_NormalizeAfsPath (afspath, sizeof(afspath), ioctlp->inDatap);
2231 submountreqp = ioctlp->inDatap + (strlen(ioctlp->inDatap)+1);
2233 /* If the caller supplied a suggested submount name, see if
2234 * that submount name is in use... if so, the submount's path
2235 * has to match our path.
2238 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
2239 AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
2242 REG_OPTION_NON_VOLATILE,
2243 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
2248 if (submountreqp && *submountreqp) {
2249 char submountPathNormalized[MAX_PATH];
2250 char submountPath[MAX_PATH];
2252 dwSize = sizeof(submountPath);
2253 status = RegQueryValueEx( hkSubmounts, submountreqp, 0,
2254 &dwType, submountPath, &dwSize);
2256 if (status != ERROR_SUCCESS) {
2258 /* The suggested submount name isn't in use now--
2259 * so we can safely map the requested submount name
2260 * to the supplied path. Remember not to write the
2261 * leading "/afs" when writing out the submount.
2263 RegSetValueEx( hkSubmounts, submountreqp, 0,
2265 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2266 &afspath[strlen(cm_mountRoot)]:"/",
2267 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2268 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2270 RegCloseKey( hkSubmounts );
2271 StringCbCopyA(ioctlp->outDatap, 999999, submountreqp);
2272 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2273 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2277 /* The suggested submount name is already in use--if the
2278 * supplied path matches the submount's path, we can still
2279 * use the suggested submount name.
2281 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2282 if (!strcmp (submountPathNormalized, afspath)) {
2283 StringCbCopyA(ioctlp->outDatap, 999999, submountreqp);
2284 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2285 RegCloseKey( hkSubmounts );
2286 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2291 RegQueryInfoKey( hkSubmounts,
2293 NULL, /* lpcClass */
2294 NULL, /* lpReserved */
2295 NULL, /* lpcSubKeys */
2296 NULL, /* lpcMaxSubKeyLen */
2297 NULL, /* lpcMaxClassLen */
2298 &dwSubmounts, /* lpcValues */
2299 NULL, /* lpcMaxValueNameLen */
2300 NULL, /* lpcMaxValueLen */
2301 NULL, /* lpcbSecurityDescriptor */
2302 NULL /* lpftLastWriteTime */
2306 /* Having obtained a list of all available submounts, start
2307 * searching that list for a path which matches the requested
2308 * AFS path. We'll also keep track of the highest "auto15"/"auto47"
2309 * submount, in case we need to add a new one later.
2312 nextAutoSubmount = 1;
2314 for ( dwIndex = 0; dwIndex < dwSubmounts; dwIndex ++ ) {
2315 char submountPathNormalized[MAX_PATH];
2316 char submountPath[MAX_PATH] = "";
2317 DWORD submountPathLen = sizeof(submountPath);
2318 char submountName[MAX_PATH];
2319 DWORD submountNameLen = sizeof(submountName);
2322 RegEnumValue( hkSubmounts, dwIndex, submountName, &submountNameLen, NULL,
2323 &dwType, submountPath, &submountPathLen);
2324 if (dwType == REG_EXPAND_SZ) {
2326 StringCbCopyA(buf, MAX_PATH, submountPath);
2327 submountPathLen = ExpandEnvironmentStrings(buf, submountPath, MAX_PATH);
2328 if (submountPathLen > MAX_PATH)
2332 /* If this is an Auto### submount, remember its ### value */
2333 if ((!strnicmp (submountName, "auto", 4)) &&
2334 (isdigit (submountName[strlen("auto")]))) {
2335 int thisAutoSubmount;
2336 thisAutoSubmount = atoi (&submountName[strlen("auto")]);
2337 nextAutoSubmount = max (nextAutoSubmount,
2338 thisAutoSubmount+1);
2341 if ((submountPathLen == 0) ||
2342 (submountPathLen == sizeof(submountPath) - 1)) {
2346 /* See if the path for this submount matches the path
2347 * that our caller specified. If so, we can return
2350 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2351 if (!strcmp (submountPathNormalized, afspath)) {
2352 StringCbCopyA(ioctlp->outDatap, 999999, submountName);
2353 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2354 RegCloseKey(hkSubmounts);
2355 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2361 /* We've been through the entire list of existing submounts, and
2362 * didn't find any which matched the specified path. So, we'll
2363 * just have to add one. Remember not to write the leading "/afs"
2364 * when writing out the submount.
2367 StringCbPrintfA(ioctlp->outDatap, 999999, "auto%ld", nextAutoSubmount);
2369 RegSetValueEx( hkSubmounts,
2373 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2374 &afspath[strlen(cm_mountRoot)]:"/",
2375 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2376 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2378 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2379 RegCloseKey(hkSubmounts);
2380 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2384 long cm_IoctlGetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2386 memcpy(ioctlp->outDatap, &cryptall, sizeof(cryptall));
2387 ioctlp->outDatap += sizeof(cryptall);
2392 long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2394 cm_SkipIoctlPath(ioctlp);
2396 memcpy(&cryptall, ioctlp->inDatap, sizeof(cryptall));
2401 long cm_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp)
2406 cm_SkipIoctlPath(ioctlp);
2408 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2409 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2412 if (flags & AFSCALL_RXSTATS_ENABLE) {
2413 rx_enableProcessRPCStats();
2415 if (flags & AFSCALL_RXSTATS_DISABLE) {
2416 rx_disableProcessRPCStats();
2418 if (flags & AFSCALL_RXSTATS_CLEAR) {
2419 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
2424 long cm_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp)
2429 cm_SkipIoctlPath(ioctlp);
2431 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2432 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2435 if (flags & AFSCALL_RXSTATS_ENABLE) {
2436 rx_enablePeerRPCStats();
2438 if (flags & AFSCALL_RXSTATS_DISABLE) {
2439 rx_disablePeerRPCStats();
2441 if (flags & AFSCALL_RXSTATS_CLEAR) {
2442 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
2448 extern int afsd_shutdown(int);
2449 extern int afs_shutdown;
2451 long cm_IoctlShutdown(smb_ioctl_t *ioctlp, cm_user_t *userp) {
2452 afs_shutdown = 1; /* flag to shut down */
2457 long cm_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp)
2459 smb_user_t *uidp = ioctlp->uidp;
2461 if (uidp && uidp->unp) {
2462 memcpy(ioctlp->outDatap, uidp->unp->name, strlen(uidp->unp->name));
2463 ioctlp->outDatap += strlen(uidp->unp->name);
2470 * functions to dump contents of various structures.
2471 * In debug build (linked with crt debug library) will dump allocated but not freed memory
2473 extern int cm_DumpSCache(FILE *outputFile, char *cookie, int lock);
2474 extern int cm_DumpBufHashTable(FILE *outputFile, char *cookie, int lock);
2475 extern int smb_DumpVCP(FILE *outputFile, char *cookie, int lock);
2477 long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
2481 char logfileName[MAX_PATH+1];
2486 static _CrtMemState memstate;
2489 cm_SkipIoctlPath(ioctlp);
2490 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
2492 dwSize = GetEnvironmentVariable("TEMP", logfileName, sizeof(logfileName));
2493 if ( dwSize == 0 || dwSize > sizeof(logfileName) )
2495 GetWindowsDirectory(logfileName, sizeof(logfileName));
2497 strncat(logfileName, "\\afsd_alloc.log", sizeof(logfileName));
2499 hLogFile = CreateFile(logfileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2505 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2506 ioctlp->outDatap += sizeof(long);
2511 SetFilePointer(hLogFile, 0, NULL, FILE_END);
2513 cookie = inValue ? "b" : "e";
2519 _CrtMemCheckpoint(&memstate);
2523 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2524 _CrtSetReportFile(_CRT_WARN, hLogFile);
2525 _CrtMemDumpAllObjectsSince(&memstate);
2529 /* dump all interesting data */
2530 cm_DumpSCache(hLogFile, cookie, 1);
2531 cm_DumpBufHashTable(hLogFile, cookie, 1);
2532 smb_DumpVCP(hLogFile, cookie, 1);
2534 CloseHandle(hLogFile);
2536 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2537 ioctlp->outDatap += sizeof(long);