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>
52 /* Copied from afs_tokens.h */
53 #define PIOCTL_LOGON 0x1
56 osi_mutex_t cm_Afsdsbmt_Lock;
58 extern afs_int32 cryptall;
59 extern char cm_NetbiosName[];
61 extern void afsi_log(char *pattern, ...);
63 void cm_InitIoctl(void)
65 lock_InitializeMutex(&cm_Afsdsbmt_Lock, "AFSDSBMT.INI Access Lock");
68 long cm_CleanFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
72 lock_ObtainWrite(&scp->bufCreateLock);
73 code = buf_CleanVnode(scp, userp, reqp);
75 lock_ObtainMutex(&scp->mx);
76 cm_DiscardSCache(scp);
77 lock_ReleaseMutex(&scp->mx);
79 lock_ReleaseWrite(&scp->bufCreateLock);
80 osi_Log2(afsd_logp,"cm_CleanFile scp 0x%x returns error: [%x]",scp, code);
84 long cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
88 lock_ObtainWrite(&scp->bufCreateLock);
89 code = buf_FlushCleanPages(scp, userp, reqp);
91 lock_ObtainMutex(&scp->mx);
92 cm_DiscardSCache(scp);
94 lock_ReleaseMutex(&scp->mx);
96 lock_ReleaseWrite(&scp->bufCreateLock);
97 osi_Log2(afsd_logp,"cm_FlushFile scp 0x%x returns error: [%x]",scp, code);
101 long cm_FlushParent(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
106 pscp = cm_FindSCacheParent(scp);
108 /* now flush the file */
109 code = cm_FlushFile(pscp, userp, reqp);
110 cm_ReleaseSCache(scp);
116 long cm_FlushVolume(cm_user_t *userp, cm_req_t *reqp, afs_uint32 cell, afs_uint32 volume)
122 lock_ObtainWrite(&cm_scacheLock);
123 for (i=0; i<cm_data.hashTableSize; i++) {
124 for (scp = cm_data.hashTablep[i]; scp; scp = scp->nextp) {
125 if (scp->fid.volume == volume && scp->fid.cell == cell) {
126 cm_HoldSCacheNoLock(scp);
127 lock_ReleaseWrite(&cm_scacheLock);
129 /* now flush the file */
130 code = cm_FlushFile(scp, userp, reqp);
131 lock_ObtainWrite(&cm_scacheLock);
132 cm_ReleaseSCacheNoLock(scp);
136 lock_ReleaseWrite(&cm_scacheLock);
142 * cm_ResetACLCache -- invalidate ACL info for a user that has just
143 * obtained or lost tokens
145 void cm_ResetACLCache(cm_user_t *userp)
150 lock_ObtainWrite(&cm_scacheLock);
151 for (hash=0; hash < cm_data.hashTableSize; hash++) {
152 for (scp=cm_data.hashTablep[hash]; scp; scp=scp->nextp) {
153 cm_HoldSCacheNoLock(scp);
154 lock_ReleaseWrite(&cm_scacheLock);
155 lock_ObtainMutex(&scp->mx);
156 cm_InvalidateACLUser(scp, userp);
157 lock_ReleaseMutex(&scp->mx);
158 lock_ObtainWrite(&cm_scacheLock);
159 cm_ReleaseSCacheNoLock(scp);
162 lock_ReleaseWrite(&cm_scacheLock);
166 * TranslateExtendedChars - This is a fix for TR 54482.
168 * If an extended character (80 - FF) is entered into a file
169 * or directory name in Windows, the character is translated
170 * into the OEM character map before being passed to us. Why
171 * this occurs is unknown. Our pioctl functions must match
172 * this translation for paths given via our own commands (like
173 * fs). If we do not do this, then we will try to perform an
174 * operation on a non-translated path, which we will fail to
175 * find, since the path was created with the translated chars.
176 * This function performs the required translation.
178 void TranslateExtendedChars(char *str)
191 while (*p) *p++ &= 0x7f; /* turn off high bit; probably not right */
195 /* parse the passed-in file name and do a namei on it. If we fail,
196 * return an error code, otherwise return the vnode located in *scpp.
198 long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
202 cm_scache_t *substRootp;
203 char * relativePath = ioctlp->inDatap;
205 char * absRoot[MAX_PATH];
207 wchar_t absRoot_w[MAX_PATH];
210 osi_Log1(afsd_logp, "cm_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,relativePath));
212 /* This is usually the file name, but for StatMountPoint it is the path. */
213 /* ioctlp->inDatap can be either of the form:
216 * \\netbios-name\submount\path\.
217 * \\netbios-name\submount\path\file
219 TranslateExtendedChars(relativePath);
222 /* we have passed the whole path, including the afs prefix.
223 when the pioctl call is made, we perform an ioctl to afsrdr
224 and it returns the correct (full) path. therefore, there is
225 no drive letter, and the path is absolute. */
226 code = cm_NameI(cm_data.rootSCachep, relativePath,
227 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
228 userp, "", reqp, scpp);
233 /* # of bytes of path */
234 code = strlen(ioctlp->inDatap) + 1;
235 ioctlp->inDatap += code;
237 /* This is usually nothing, but for StatMountPoint it is the file name. */
238 TranslateExtendedChars(ioctlp->inDatap);
243 if (relativePath[0] == relativePath[1] &&
244 relativePath[1] == '\\' &&
245 !_strnicmp(cm_NetbiosName,relativePath+2,strlen(cm_NetbiosName)))
251 /* We may have found a UNC path.
252 * If the first component is the NetbiosName,
253 * then throw out the second component (the submount)
254 * since it had better expand into the value of ioctl->tidPathp
257 p = relativePath + 2 + strlen(cm_NetbiosName) + 1; /* buffer overflow vuln.? */
258 if ( !_strnicmp("all", p, 3) )
261 for (i = 0; *p && *p != '\\'; i++,p++ ) {
264 p++; /* skip past trailing slash */
265 shareName[i] = 0; /* terminate string */
267 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
269 /* we found a sharename, therefore use the resulting path */
270 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
271 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
272 userp, sharePath, reqp, &substRootp);
277 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
278 userp, NULL, reqp, scpp);
282 /* otherwise, treat the name as a cellname mounted off the afs root.
283 * This requires that we reconstruct the shareName string with
284 * leading and trailing slashes.
286 p = relativePath + 2 + strlen(cm_NetbiosName) + 1;
287 if ( !_strnicmp("all", p, 3) )
291 for (i = 1; *p && *p != '\\'; i++,p++ ) {
294 p++; /* skip past trailing slash */
295 shareName[i++] = '/'; /* add trailing slash */
296 shareName[i] = 0; /* terminate string */
299 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
300 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
301 userp, shareName, reqp, &substRootp);
305 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
306 userp, NULL, reqp, scpp);
311 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
312 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
313 userp, ioctlp->tidPathp, reqp, &substRootp);
317 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
318 userp, NULL, reqp, scpp);
323 /* # of bytes of path */
324 code = (long)strlen(ioctlp->inDatap) + 1;
325 ioctlp->inDatap += code;
327 /* This is usually nothing, but for StatMountPoint it is the file name. */
328 TranslateExtendedChars(ioctlp->inDatap);
330 /* and return success */
334 void cm_SkipIoctlPath(smb_ioctl_t *ioctlp)
338 temp = (long) strlen(ioctlp->inDatap) + 1;
339 ioctlp->inDatap += temp;
343 /* format the specified path to look like "/afs/<cellname>/usr", by
344 * adding "/afs" (if necessary) in front, changing any \'s to /'s, and
345 * removing any trailing "/"'s. One weirdo caveat: "/afs" will be
346 * intentionally returned as "/afs/"--this makes submount manipulation
347 * easier (because we can always jump past the initial "/afs" to find
348 * the AFS path that should be written into afsdsbmt.ini).
350 void cm_NormalizeAfsPath(char *outpathp, long outlen, char *inpathp)
353 char bslash_mountRoot[256];
355 strncpy(bslash_mountRoot, cm_mountRoot, sizeof(bslash_mountRoot) - 1);
356 bslash_mountRoot[0] = '\\';
358 if (!strnicmp (inpathp, cm_mountRoot, strlen(cm_mountRoot)))
359 StringCbCopy(outpathp, outlen, inpathp);
360 else if (!strnicmp (inpathp, bslash_mountRoot, strlen(bslash_mountRoot)))
361 StringCbCopy(outpathp, outlen, inpathp);
362 else if ((inpathp[0] == '/') || (inpathp[0] == '\\'))
363 StringCbPrintfA(outpathp, outlen, "%s%s", cm_mountRoot, inpathp);
364 else // inpathp looks like "<cell>/usr"
365 StringCbPrintfA(outpathp, outlen, "%s/%s", cm_mountRoot, inpathp);
367 for (cp = outpathp; *cp != 0; ++cp) {
372 if (strlen(outpathp) && (outpathp[strlen(outpathp)-1] == '/')) {
373 outpathp[strlen(outpathp)-1] = 0;
376 if (!strcmpi (outpathp, cm_mountRoot)) {
377 StringCbCopy(outpathp, outlen, cm_mountRoot);
381 #define LEAF_SIZE 256
382 /* parse the passed-in file name and do a namei on its parent. If we fail,
383 * return an error code, otherwise return the vnode located in *scpp.
385 long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
386 cm_scache_t **scpp, char *leafp)
391 cm_scache_t *substRootp;
393 StringCbCopyA(tbuffer, sizeof(tbuffer), ioctlp->inDatap);
394 tp = strrchr(tbuffer, '\\');
395 jp = strrchr(tbuffer, '/');
398 else if (jp && (tp - tbuffer) < (jp - tbuffer))
401 StringCbCopyA(tbuffer, sizeof(tbuffer), "\\");
403 StringCbCopyA(leafp, LEAF_SIZE, ioctlp->inDatap);
408 StringCbCopyA(leafp, LEAF_SIZE, tp+1);
411 if (tbuffer[0] == tbuffer[1] &&
412 tbuffer[1] == '\\' &&
413 !_strnicmp(cm_NetbiosName,tbuffer+2,strlen(cm_NetbiosName)))
419 /* We may have found a UNC path.
420 * If the first component is the NetbiosName,
421 * then throw out the second component (the submount)
422 * since it had better expand into the value of ioctl->tidPathp
425 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
426 if ( !_strnicmp("all", p, 3) )
429 for (i = 0; *p && *p != '\\'; i++,p++ ) {
432 p++; /* skip past trailing slash */
433 shareName[i] = 0; /* terminate string */
435 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
437 /* we found a sharename, therefore use the resulting path */
438 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
439 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
440 userp, sharePath, reqp, &substRootp);
442 if (code) return code;
444 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
445 userp, NULL, reqp, scpp);
446 if (code) return code;
448 /* otherwise, treat the name as a cellname mounted off the afs root.
449 * This requires that we reconstruct the shareName string with
450 * leading and trailing slashes.
452 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
453 if ( !_strnicmp("all", p, 3) )
457 for (i = 1; *p && *p != '\\'; i++,p++ ) {
460 p++; /* skip past trailing slash */
461 shareName[i++] = '/'; /* add trailing slash */
462 shareName[i] = 0; /* terminate string */
464 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
465 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
466 userp, shareName, reqp, &substRootp);
467 if (code) return code;
469 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
470 userp, NULL, reqp, scpp);
471 if (code) return code;
474 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
475 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
476 userp, ioctlp->tidPathp, reqp, &substRootp);
477 if (code) return code;
479 code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
480 userp, NULL, reqp, scpp);
481 if (code) return code;
484 /* # of bytes of path */
485 code = (long)strlen(ioctlp->inDatap) + 1;
486 ioctlp->inDatap += code;
488 /* and return success */
492 long cm_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp)
497 AFSFetchStatus fileStatus;
503 struct rx_connection * callp;
507 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
508 if (code) return code;
510 /* now make the get acl call */
511 fid.Volume = scp->fid.volume;
512 fid.Vnode = scp->fid.vnode;
513 fid.Unique = scp->fid.unique;
515 acl.AFSOpaque_val = ioctlp->outDatap;
516 acl.AFSOpaque_len = 0;
517 code = cm_Conn(&scp->fid, userp, &req, &connp);
520 callp = cm_GetRxConn(connp);
521 code = RXAFS_FetchACL(callp, &fid, &acl, &fileStatus, &volSync);
522 rx_PutConnection(callp);
524 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
525 code = cm_MapRPCError(code, &req);
526 cm_ReleaseSCache(scp);
528 if (code) return code;
530 /* skip over return data */
531 tlen = (int)strlen(ioctlp->outDatap) + 1;
532 ioctlp->outDatap += tlen;
534 /* and return success */
538 long cm_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp)
547 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
548 if (code) return code;
550 #ifdef AFS_FREELANCE_CLIENT
551 if ( cm_freelanceEnabled &&
552 scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
553 scp->fid.volume==AFS_FAKE_ROOT_VOL_ID &&
554 scp->fid.vnode==0x1 && scp->fid.unique==0x1 ) {
555 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "Freelance.Local.Root");
556 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
559 #endif /* AFS_FREELANCE_CLIENT */
561 cellp = cm_FindCellByID(scp->fid.cell);
563 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), cellp->name);
564 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
568 code = CM_ERROR_NOSUCHCELL;
571 cm_ReleaseSCache(scp);
575 long cm_IoctlSetACL(struct smb_ioctl *ioctlp, struct cm_user *userp)
580 AFSFetchStatus fileStatus;
585 struct rx_connection * callp;
589 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
590 if (code) return code;
592 /* now make the get acl call */
593 fid.Volume = scp->fid.volume;
594 fid.Vnode = scp->fid.vnode;
595 fid.Unique = scp->fid.unique;
597 acl.AFSOpaque_val = ioctlp->inDatap;
598 acl.AFSOpaque_len = (u_int)strlen(ioctlp->inDatap)+1;
599 code = cm_Conn(&scp->fid, userp, &req, &connp);
602 callp = cm_GetRxConn(connp);
603 code = RXAFS_StoreACL(callp, &fid, &acl, &fileStatus, &volSync);
604 rx_PutConnection(callp);
606 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
607 code = cm_MapRPCError(code, &req);
609 /* invalidate cache info, since we just trashed the ACL cache */
610 lock_ObtainMutex(&scp->mx);
611 cm_DiscardSCache(scp);
612 lock_ReleaseMutex(&scp->mx);
614 cm_ReleaseSCache(scp);
621 long cm_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
630 lock_ObtainWrite(&cm_scacheLock);
631 for (i=0; i<cm_data.hashTableSize; i++) {
632 for (scp = cm_data.hashTablep[i]; scp; scp = scp->nextp) {
633 cm_HoldSCacheNoLock(scp);
634 lock_ReleaseWrite(&cm_scacheLock);
636 /* now flush the file */
637 code = cm_FlushFile(scp, userp, &req);
638 lock_ObtainWrite(&cm_scacheLock);
639 cm_ReleaseSCacheNoLock(scp);
642 lock_ReleaseWrite(&cm_scacheLock);
647 long cm_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp)
651 unsigned long volume;
657 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
658 if (code) return code;
660 volume = scp->fid.volume;
661 cell = scp->fid.cell;
662 cm_ReleaseSCache(scp);
664 code = cm_FlushVolume(userp, &req, cell, volume);
669 long cm_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp)
677 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
678 if (code) return code;
680 cm_FlushFile(scp, userp, &req);
681 cm_ReleaseSCache(scp);
686 long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
690 char offLineMsg[256];
694 AFSFetchVolumeStatus volStat;
695 AFSStoreVolumeStatus storeStat;
700 struct rx_connection * callp;
704 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
705 if (code) return code;
707 cellp = cm_FindCellByID(scp->fid.cell);
710 if (scp->flags & CM_SCACHEFLAG_RO) {
711 cm_ReleaseSCache(scp);
712 return CM_ERROR_READONLY;
715 code = cm_GetVolumeByID(cellp, scp->fid.volume, userp, &req, &tvp);
717 cm_ReleaseSCache(scp);
721 /* Copy the junk out, using cp as a roving pointer. */
722 cp = ioctlp->inDatap;
723 memcpy((char *)&volStat, cp, sizeof(AFSFetchVolumeStatus));
724 cp += sizeof(AFSFetchVolumeStatus);
725 StringCbCopyA(volName, sizeof(volName), cp);
726 cp += strlen(volName)+1;
727 StringCbCopyA(offLineMsg, sizeof(offLineMsg), cp);
728 cp += strlen(offLineMsg)+1;
729 StringCbCopyA(motd, sizeof(motd), cp);
731 if (volStat.MinQuota != -1) {
732 storeStat.MinQuota = volStat.MinQuota;
733 storeStat.Mask |= AFS_SETMINQUOTA;
735 if (volStat.MaxQuota != -1) {
736 storeStat.MaxQuota = volStat.MaxQuota;
737 storeStat.Mask |= AFS_SETMAXQUOTA;
741 code = cm_Conn(&scp->fid, userp, &req, &tcp);
744 callp = cm_GetRxConn(tcp);
745 code = RXAFS_SetVolumeStatus(callp, scp->fid.volume,
746 &storeStat, volName, offLineMsg, motd);
747 rx_PutConnection(callp);
749 } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
750 code = cm_MapRPCError(code, &req);
752 /* return on failure */
753 cm_ReleaseSCache(scp);
758 /* we are sending parms back to make compat. with prev system. should
759 * change interface later to not ask for current status, just set
762 cp = ioctlp->outDatap;
763 memcpy(cp, (char *)&volStat, sizeof(VolumeStatus));
764 cp += sizeof(VolumeStatus);
765 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), volName);
766 cp += strlen(volName)+1;
767 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), offLineMsg);
768 cp += strlen(offLineMsg)+1;
769 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), motd);
770 cp += strlen(motd)+1;
772 /* now return updated return data pointer */
773 ioctlp->outDatap = cp;
778 long cm_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
782 char offLineMsg[256];
786 AFSFetchVolumeStatus volStat;
792 struct rx_connection * callp;
796 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
797 if (code) return code;
800 OfflineMsg = offLineMsg;
803 code = cm_Conn(&scp->fid, userp, &req, &tcp);
806 callp = cm_GetRxConn(tcp);
807 code = RXAFS_GetVolumeStatus(callp, scp->fid.volume,
808 &volStat, &Name, &OfflineMsg, &MOTD);
809 rx_PutConnection(callp);
811 } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
812 code = cm_MapRPCError(code, &req);
814 cm_ReleaseSCache(scp);
815 if (code) return code;
817 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
818 cp = ioctlp->outDatap;
819 memcpy(cp, (char *)&volStat, sizeof(AFSFetchVolumeStatus));
820 cp += sizeof(AFSFetchVolumeStatus);
821 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), volName);
822 cp += strlen(volName)+1;
823 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), offLineMsg);
824 cp += strlen(offLineMsg)+1;
825 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), motd);
826 cp += strlen(motd)+1;
828 /* return new size */
829 ioctlp->outDatap = cp;
834 long cm_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp)
844 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
845 if (code) return code;
847 memset(&fid, 0, sizeof(cm_fid_t));
848 fid.volume = scp->fid.volume;
849 fid.vnode = scp->fid.vnode;
850 fid.unique = scp->fid.unique;
852 cm_ReleaseSCache(scp);
854 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
855 cp = ioctlp->outDatap;
856 memcpy(cp, (char *)&fid, sizeof(cm_fid_t));
857 cp += sizeof(cm_fid_t);
859 /* return new size */
860 ioctlp->outDatap = cp;
865 long cm_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp)
874 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
875 if (code) return code;
877 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
878 cp = ioctlp->outDatap;
879 memcpy(cp, (char *)&scp->owner, sizeof(afs_uint32));
880 cp += sizeof(afs_uint32);
881 memcpy(cp, (char *)&scp->group, sizeof(afs_uint32));
882 cp += sizeof(afs_uint32);
884 /* return new size */
885 ioctlp->outDatap = cp;
887 cm_ReleaseSCache(scp);
892 long cm_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp)
898 cm_serverRef_t **tsrpp, *current;
900 unsigned long volume;
906 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
907 if (code) return code;
909 volume = scp->fid.volume;
911 cellp = cm_FindCellByID(scp->fid.cell);
914 cm_ReleaseSCache(scp);
916 code = cm_GetVolumeByID(cellp, volume, userp, &req, &tvp);
917 if (code) return code;
919 cp = ioctlp->outDatap;
921 lock_ObtainMutex(&tvp->mx);
922 tsrpp = cm_GetVolServers(tvp, volume);
923 lock_ObtainRead(&cm_serverLock);
924 for (current = *tsrpp; current; current = current->next) {
925 tsp = current->server;
926 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
929 lock_ReleaseRead(&cm_serverLock);
930 cm_FreeServerList(tsrpp);
931 lock_ReleaseMutex(&tvp->mx);
933 /* still room for terminating NULL, add it on */
934 volume = 0; /* reuse vbl */
935 memcpy(cp, (char *)&volume, sizeof(long));
938 ioctlp->outDatap = cp;
943 long cm_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
953 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
954 if (code) return code;
956 cp = ioctlp->inDatap;
958 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
959 cm_ReleaseSCache(dscp);
960 if (code) return code;
962 lock_ObtainMutex(&scp->mx);
964 /* now check that this is a real mount point */
965 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
966 lock_ReleaseMutex(&scp->mx);
967 cm_ReleaseSCache(scp);
968 return CM_ERROR_INVAL;
971 code = cm_ReadMountPoint(scp, userp, &req);
973 cp = ioctlp->outDatap;
974 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), scp->mountPointStringp);
975 cp += strlen(cp) + 1;
976 ioctlp->outDatap = cp;
978 lock_ReleaseMutex(&scp->mx);
979 cm_ReleaseSCache(scp);
984 long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
994 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
995 if (code) return code;
997 cp = ioctlp->inDatap;
999 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1001 /* if something went wrong, bail out now */
1006 lock_ObtainMutex(&scp->mx);
1007 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1008 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1010 lock_ReleaseMutex(&scp->mx);
1011 cm_ReleaseSCache(scp);
1015 /* now check that this is a real mount point */
1016 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
1017 lock_ReleaseMutex(&scp->mx);
1018 cm_ReleaseSCache(scp);
1019 code = CM_ERROR_INVAL;
1023 /* time to make the RPC, so drop the lock */
1024 lock_ReleaseMutex(&scp->mx);
1025 cm_ReleaseSCache(scp);
1027 /* easier to do it this way */
1028 code = cm_Unlink(dscp, cp, userp, &req);
1029 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1030 smb_NotifyChange(FILE_ACTION_REMOVED,
1031 FILE_NOTIFY_CHANGE_DIR_NAME,
1032 dscp, cp, NULL, TRUE);
1035 cm_ReleaseSCache(dscp);
1039 long cm_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp)
1049 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1050 tp = ioctlp->inDatap;
1053 memcpy(&temp, tp, sizeof(temp));
1054 if (temp == 0x12345678) { /* For afs3.3 version */
1055 memcpy(&csi, tp, sizeof(csi));
1056 if (csi.tinterval >= 0) {
1057 cp = ioctlp->outDatap;
1058 memcpy(cp, (char *)&cm_daemonCheckDownInterval, sizeof(long));
1059 ioctlp->outDatap += sizeof(long);
1060 if (csi.tinterval > 0) {
1061 if (!smb_SUser(userp))
1062 return CM_ERROR_NOACCESS;
1063 cm_daemonCheckDownInterval = csi.tinterval;
1071 } else { /* For pre afs3.3 versions */
1072 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
1073 ioctlp->inDatap = cp = ioctlp->inDatap + sizeof(long);
1074 if (cp - ioctlp->inAllocp < ioctlp->inCopied) /* still more data available */
1079 * 1: fast check, don't contact servers.
1080 * 2: local cell only.
1083 /* have cell name, too */
1084 cellp = cm_GetCell(cp, 0);
1085 if (!cellp) return CM_ERROR_NOSUCHCELL;
1087 else cellp = (cm_cell_t *) 0;
1088 if (!cellp && (temp & 2)) {
1089 /* use local cell */
1090 cellp = cm_FindCellByID(1);
1092 if (!(temp & 1)) { /* if not fast, call server checker routine */
1093 /* check down servers */
1094 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS | CM_FLAG_CHECKUPSERVERS,
1098 /* now return the current down server list */
1099 cp = ioctlp->outDatap;
1100 lock_ObtainRead(&cm_serverLock);
1101 for (tsp = cm_allServersp; tsp; tsp=tsp->allNextp) {
1102 if (cellp && tsp->cellp != cellp) continue; /* cell spec'd and wrong */
1103 if ((tsp->flags & CM_SERVERFLAG_DOWN)
1104 && tsp->type == CM_SERVER_FILE) {
1105 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
1109 lock_ReleaseRead(&cm_serverLock);
1111 ioctlp->outDatap = cp;
1115 long cm_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp)
1117 /* we don't print anything superfluous, so we don't support the gag call */
1118 return CM_ERROR_INVAL;
1121 long cm_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
1127 long cm_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp)
1132 cm_SkipIoctlPath(ioctlp);
1134 memcpy(&temp, ioctlp->inDatap, sizeof(temp));
1136 temp = cm_data.buf_nOrigBuffers;
1138 /* temp is in 1K units, convert to # of buffers */
1139 temp = temp / (cm_data.buf_blockSize / 1024);
1142 /* now adjust the cache size */
1143 code = buf_SetNBuffers(temp);
1148 long cm_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
1152 cm_SkipIoctlPath(ioctlp);
1154 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
1158 afsd_ForceTrace(FALSE);
1159 buf_ForceTrace(FALSE);
1163 /* set tracing value to low order bit */
1164 if ((inValue & 1) == 0) {
1165 /* disable tracing */
1166 osi_LogDisable(afsd_logp);
1167 rx_DebugOnOff(FALSE);
1170 /* enable tracing */
1171 osi_LogEnable(afsd_logp);
1172 rx_DebugOnOff(TRUE);
1176 /* see if we're supposed to do a reset, too */
1178 osi_LogReset(afsd_logp);
1181 /* and copy out tracing flag */
1182 inValue = afsd_logp->enabled; /* use as a temp vbl */
1183 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
1184 ioctlp->outDatap += sizeof(long);
1188 long cm_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp)
1190 cm_cacheParms_t parms;
1192 memset(&parms, 0, sizeof(parms));
1194 /* first we get, in 1K units, the cache size */
1195 parms.parms[0] = cm_data.buf_nbuffers * (cm_data.buf_blockSize / 1024);
1197 /* and then the actual # of buffers in use (not in the free list, I guess,
1198 * will be what we do).
1200 parms.parms[1] = (cm_data.buf_nbuffers - buf_CountFreeList()) * (cm_data.buf_blockSize / 1024);
1202 memcpy(ioctlp->outDatap, &parms, sizeof(parms));
1203 ioctlp->outDatap += sizeof(parms);
1208 long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1213 cm_serverRef_t *serverRefp;
1214 cm_server_t *serverp;
1220 cm_SkipIoctlPath(ioctlp);
1222 tp = ioctlp->inDatap;
1224 memcpy((char *)&whichCell, tp, sizeof(long));
1227 /* see if more than one long passed in, ignoring the null pathname (the -1) */
1228 if (ioctlp->inCopied-1 > sizeof(long)) {
1229 memcpy((char *)&magic, tp, sizeof(long));
1232 lock_ObtainRead(&cm_cellLock);
1233 for (tcellp = cm_data.allCellsp; tcellp; tcellp = tcellp->nextp) {
1234 if (whichCell == 0) break;
1237 lock_ReleaseRead(&cm_cellLock);
1241 cp = ioctlp->outDatap;
1243 if (magic == 0x12345678) {
1244 memcpy(cp, (char *)&magic, sizeof(long));
1247 memset(cp, 0, max * sizeof(long));
1249 lock_ObtainRead(&cm_serverLock); /* for going down server list */
1250 /* jaltman - do the reference counts to serverRefp contents need to be increased? */
1251 serverRefp = tcellp->vlServersp;
1252 for (i=0; i<max; i++) {
1253 if (!serverRefp) break;
1254 serverp = serverRefp->server;
1255 memcpy(cp, &serverp->addr.sin_addr.s_addr, sizeof(long));
1257 serverRefp = serverRefp->next;
1259 lock_ReleaseRead(&cm_serverLock);
1260 cp = basep + max * sizeof(afs_int32);
1261 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), tcellp->name);
1262 cp += strlen(tcellp->name)+1;
1263 ioctlp->outDatap = cp;
1269 return CM_ERROR_NOMORETOKENS; /* mapped to EDOM */
1272 extern long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *namep);
1274 long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1276 /* NT cache manager will read cell information from CellServDB each time
1277 * cell is accessed. So, this call is necessary only if list of server for a cell
1278 * changes (or IP addresses of cell servers changes).
1279 * All that needs to be done is to refresh server information for all cells that
1280 * are already loaded.
1282 * cell list will be cm_CellLock and cm_ServerLock will be held for write.
1287 cm_SkipIoctlPath(ioctlp);
1288 lock_ObtainWrite(&cm_cellLock);
1290 for (cp = cm_data.allCellsp; cp; cp=cp->nextp)
1293 lock_ObtainMutex(&cp->mx);
1294 /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
1295 cm_FreeServerList(&cp->vlServersp);
1296 cp->vlServersp = NULL;
1297 code = cm_SearchCellFile(cp->name, cp->name, cm_AddCellProc, cp);
1298 #ifdef AFS_AFSDB_ENV
1300 if (cm_dnsEnabled) {
1302 code = cm_SearchCellByDNS(cp->name, cp->name, &ttl, cm_AddCellProc, cp);
1303 if ( code == 0 ) { /* got cell from DNS */
1304 cp->flags |= CM_CELLFLAG_DNS;
1305 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1306 cp->timeout = time(0) + ttl;
1311 cp->flags &= ~CM_CELLFLAG_DNS;
1313 #endif /* AFS_AFSDB_ENV */
1315 cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
1318 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1319 cm_RandomizeServer(&cp->vlServersp);
1321 lock_ReleaseMutex(&cp->mx);
1324 lock_ReleaseWrite(&cm_cellLock);
1328 long cm_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
1332 if (cm_freelanceEnabled) {
1333 if (cm_GetRootCellName(ioctlp->outDatap))
1334 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "Freelance.Local.Root");
1335 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1336 } else if (cm_data.rootCellp) {
1337 /* return the default cellname to the caller */
1338 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), cm_data.rootCellp->name);
1339 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1341 /* if we don't know our default cell, return failure */
1342 code = CM_ERROR_NOSUCHCELL;
1348 long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp)
1350 long setSysName, foundname = 0;
1351 char *cp, *cp2, inname[MAXSYSNAME], outname[MAXSYSNAME];
1352 int t, count, num = 0;
1353 char **sysnamelist[MAXSYSNAME];
1355 cm_SkipIoctlPath(ioctlp);
1357 memcpy(&setSysName, ioctlp->inDatap, sizeof(long));
1358 ioctlp->inDatap += sizeof(long);
1362 if ( setSysName < 0 || setSysName > MAXNUMSYSNAMES )
1364 cp2 = ioctlp->inDatap;
1365 for ( cp=ioctlp->inDatap, count = 0; count < setSysName; count++ ) {
1366 /* won't go past end of ioctlp->inDatap since maxsysname*num < ioctlp->inDatap length */
1367 t = (int)strlen(cp);
1368 if (t >= MAXSYSNAME || t <= 0)
1370 /* check for names that can shoot us in the foot */
1371 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
1377 /* inname gets first entry in case we're being a translator */
1378 /* (we are never a translator) */
1379 t = (int)strlen(ioctlp->inDatap);
1380 memcpy(inname, ioctlp->inDatap, t + 1);
1381 ioctlp->inDatap += t + 1;
1385 /* Not xlating, so local case */
1387 osi_panic("cm_IoctlSysName: !cm_sysName\n", __FILE__, __LINE__);
1389 if (!setSysName) { /* user just wants the info */
1390 StringCbCopyA(outname, sizeof(outname), cm_sysName);
1391 foundname = cm_sysNameCount;
1392 *sysnamelist = cm_sysNameList;
1394 /* Local guy; only root can change sysname */
1395 /* clear @sys entries from the dnlc, once afs_lookup can
1396 * do lookups of @sys entries and thinks it can trust them */
1397 /* privs ok, store the entry, ... */
1398 StringCbCopyA(cm_sysName, sizeof(cm_sysName), inname);
1399 StringCbCopyA(cm_sysNameList[0], MAXSYSNAME, inname);
1400 if (setSysName > 1) { /* ... or list */
1401 cp = ioctlp->inDatap;
1402 for (count = 1; count < setSysName; ++count) {
1403 if (!cm_sysNameList[count])
1404 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to write\n",
1405 __FILE__, __LINE__);
1406 t = (int)strlen(cp);
1407 StringCbCopyA(cm_sysNameList[count], MAXSYSNAME, cp);
1411 cm_sysNameCount = setSysName;
1415 /* return the sysname to the caller */
1416 cp = ioctlp->outDatap;
1417 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
1418 cp += sizeof(afs_int32); /* skip found flag */
1420 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), outname);
1421 cp += strlen(outname) + 1; /* skip name and terminating null char */
1422 for ( count=1; count < foundname ; ++count) { /* ... or list */
1423 if ( !(*sysnamelist)[count] )
1424 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to read\n",
1425 __FILE__, __LINE__);
1426 t = (int)strlen((*sysnamelist)[count]);
1427 if (t >= MAXSYSNAME)
1428 osi_panic("cm_IoctlSysName: sysname entry garbled\n",
1429 __FILE__, __LINE__);
1430 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), (*sysnamelist)[count]);
1434 ioctlp->outDatap = cp;
1441 long cm_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1446 cm_SkipIoctlPath(ioctlp);
1448 cellp = cm_GetCell(ioctlp->inDatap, 0);
1450 return CM_ERROR_NOSUCHCELL;
1453 lock_ObtainMutex(&cellp->mx);
1454 if (cellp->flags & CM_CELLFLAG_SUID)
1455 temp |= CM_SETCELLFLAG_SUID;
1456 lock_ReleaseMutex(&cellp->mx);
1458 /* now copy out parm */
1459 memcpy(ioctlp->outDatap, &temp, sizeof(long));
1460 ioctlp->outDatap += sizeof(long);
1465 long cm_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1470 cm_SkipIoctlPath(ioctlp);
1472 cellp = cm_GetCell(ioctlp->inDatap + 2*sizeof(long), 0);
1474 return CM_ERROR_NOSUCHCELL;
1476 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
1478 lock_ObtainMutex(&cellp->mx);
1479 if (temp & CM_SETCELLFLAG_SUID)
1480 cellp->flags |= CM_CELLFLAG_SUID;
1482 cellp->flags &= ~CM_CELLFLAG_SUID;
1483 lock_ReleaseMutex(&cellp->mx);
1488 long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1490 cm_SSetPref_t *spin; /* input */
1491 cm_SPref_t *srvin; /* one input component */
1493 int i, vlonly, noServers, type;
1494 struct sockaddr_in tmp;
1495 unsigned short rank;
1497 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1499 spin = (cm_SSetPref_t *)ioctlp->inDatap;
1500 noServers = spin->num_servers;
1501 vlonly = spin->flags;
1503 type = CM_SERVER_VLDB;
1505 type = CM_SERVER_FILE;
1507 for ( i=0; i < noServers; i++)
1509 srvin = &(spin->servers[i]);
1510 rank = srvin->rank + (rand() & 0x000f);
1511 tmp.sin_addr = srvin->host;
1512 tmp.sin_family = AF_INET;
1514 tsp = cm_FindServer(&tmp, type);
1515 if ( tsp ) /* an existing server - ref count increased */
1517 tsp->ipRank = rank; /* no need to protect by mutex*/
1519 if (type == CM_SERVER_FILE)
1521 /* find volumes which might have RO copy
1522 /* on server and change the ordering of
1525 cm_ChangeRankVolume(tsp);
1529 /* set preferences for an existing vlserver */
1530 cm_ChangeRankCellVLServer(tsp);
1533 else /* add a new server without a cell */
1535 tsp = cm_NewServer(&tmp, type, NULL); /* refcount = 1 */
1538 lock_ObtainMutex(&tsp->mx);
1539 tsp->flags |= CM_SERVERFLAG_PREF_SET;
1540 lock_ReleaseMutex(&tsp->mx);
1541 cm_PutServer(tsp); /* decrease refcount */
1546 long cm_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1548 cm_SPrefRequest_t *spin; /* input */
1549 cm_SPrefInfo_t *spout; /* output */
1550 cm_SPref_t *srvout; /* one output component */
1552 int i, vlonly, noServers;
1554 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1556 spin = (cm_SPrefRequest_t *)ioctlp->inDatap;
1557 spout = (cm_SPrefInfo_t *) ioctlp->outDatap;
1558 srvout = spout->servers;
1559 noServers = spin->num_servers;
1560 vlonly = spin->flags & CM_SPREF_VLONLY;
1561 spout->num_servers = 0;
1563 lock_ObtainRead(&cm_serverLock); /* get server lock */
1565 for (tsp=cm_allServersp, i=0; tsp && noServers; tsp=tsp->allNextp,i++){
1566 if (spin->offset > i) {
1567 continue; /* catch up to where we left off */
1570 if ( vlonly && (tsp->type == CM_SERVER_FILE) )
1571 continue; /* ignore fileserver for -vlserver option*/
1572 if ( !vlonly && (tsp->type == CM_SERVER_VLDB) )
1573 continue; /* ignore vlservers */
1575 srvout->host = tsp->addr.sin_addr;
1576 srvout->rank = tsp->ipRank;
1578 spout->num_servers++;
1581 lock_ReleaseRead(&cm_serverLock); /* release server lock */
1583 if ( tsp ) /* we ran out of space in the output buffer */
1584 spout->next_offset = i;
1586 spout->next_offset = 0;
1587 ioctlp->outDatap += sizeof(cm_SPrefInfo_t) +
1588 (spout->num_servers -1 ) * sizeof(cm_SPref_t) ;
1592 long cm_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp)
1594 /* we ignore default asynchrony since we only have one way
1595 * of doing this today.
1600 long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1602 char leaf[LEAF_SIZE];
1616 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1617 if (code) return code;
1619 /* Translate chars for the mount point name */
1620 TranslateExtendedChars(leaf);
1623 * The fs command allows the user to specify partial cell names on NT. These must
1624 * be expanded to the full cell name for mount points so that the mount points will
1625 * work on UNIX clients.
1628 /* Extract the possibly partial cell name */
1629 StringCbCopyA(cell, sizeof(cell), ioctlp->inDatap + 1); /* Skip the mp type character */
1631 if (cp = strchr(cell, ':')) {
1632 /* Extract the volume name */
1634 StringCbCopyA(volume, sizeof(volume), cp + 1);
1636 /* Get the full name for this cell */
1637 code = cm_SearchCellFile(cell, fullCell, 0, 0);
1638 #ifdef AFS_AFSDB_ENV
1639 if (code && cm_dnsEnabled)
1640 code = cm_SearchCellByDNS(cell, fullCell, &ttl, 0, 0);
1643 return CM_ERROR_NOSUCHCELL;
1645 StringCbPrintfA(mpInfo, sizeof(mpInfo), "%c%s:%s", *ioctlp->inDatap, fullCell, volume);
1647 /* No cell name specified */
1648 StringCbCopyA(mpInfo, sizeof(mpInfo), ioctlp->inDatap);
1651 #ifdef AFS_FREELANCE_CLIENT
1652 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1653 /* we are adding the mount point to the root dir., so call
1654 * the freelance code to do the add. */
1655 osi_Log0(afsd_logp,"IoctlCreateMountPoint within Freelance root dir");
1656 code = cm_FreelanceAddMount(leaf, fullCell, volume,
1657 *ioctlp->inDatap == '%', NULL);
1661 /* create the symlink with mode 644. The lack of X bits tells
1662 * us that it is a mount point.
1664 tattr.mask = CM_ATTRMASK_UNIXMODEBITS | CM_ATTRMASK_CLIENTMODTIME;
1665 tattr.unixModeBits = 0644;
1666 tattr.clientModTime = time(NULL);
1668 code = cm_SymLink(dscp, leaf, mpInfo, 0, &tattr, userp, &req);
1669 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1670 smb_NotifyChange(FILE_ACTION_ADDED,
1671 FILE_NOTIFY_CHANGE_DIR_NAME,
1672 dscp, leaf, NULL, TRUE);
1674 cm_ReleaseSCache(dscp);
1678 long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1680 char leaf[LEAF_SIZE];
1689 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1690 if (code) return code;
1692 /* Translate chars for the link name */
1693 TranslateExtendedChars(leaf);
1695 /* Translate chars for the linked to name */
1696 TranslateExtendedChars(ioctlp->inDatap);
1698 cp = ioctlp->inDatap; /* contents of link */
1700 #ifdef AFS_FREELANCE_CLIENT
1701 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1702 /* we are adding the symlink to the root dir., so call
1703 * the freelance code to do the add. */
1704 if (cp[0] == cp[1] && cp[1] == '\\' &&
1705 !_strnicmp(cm_NetbiosName,cp+2,strlen(cm_NetbiosName)))
1707 /* skip \\AFS\ or \\AFS\all\ */
1709 p = cp + 2 + strlen(cm_NetbiosName) + 1;
1710 if ( !_strnicmp("all", p, 3) )
1714 osi_Log0(afsd_logp,"IoctlCreateSymlink within Freelance root dir");
1715 code = cm_FreelanceAddSymlink(leaf, cp, NULL);
1720 /* Create symlink with mode 0755. */
1721 tattr.mask = CM_ATTRMASK_UNIXMODEBITS;
1722 tattr.unixModeBits = 0755;
1724 code = cm_SymLink(dscp, leaf, cp, 0, &tattr, userp, &req);
1725 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1726 smb_NotifyChange(FILE_ACTION_ADDED,
1727 FILE_NOTIFY_CHANGE_FILE_NAME
1728 | FILE_NOTIFY_CHANGE_DIR_NAME,
1729 dscp, leaf, NULL, TRUE);
1731 cm_ReleaseSCache(dscp);
1737 long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1744 cm_scache_t *newRootScp;
1749 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1750 if (code) return code;
1752 cp = ioctlp->inDatap;
1754 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1755 cm_ReleaseSCache(dscp);
1756 if (code) return code;
1758 /* Check that it's a real symlink */
1759 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1760 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1761 scp->fileType != CM_SCACHETYPE_INVALID) {
1762 cm_ReleaseSCache(scp);
1763 return CM_ERROR_INVAL;
1766 code = cm_AssembleLink(scp, "", &newRootScp, &spacep, userp, &req);
1767 cm_ReleaseSCache(scp);
1769 cp = ioctlp->outDatap;
1770 if (newRootScp != NULL) {
1771 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), cm_mountRoot);
1772 StringCbCatA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), "/");
1775 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), spacep->data);
1776 cp += strlen(cp) + 1;
1777 ioctlp->outDatap = cp;
1778 cm_FreeSpace(spacep);
1779 if (newRootScp != NULL)
1780 cm_ReleaseSCache(newRootScp);
1782 } else if (code == CM_ERROR_PATH_NOT_COVERED &&
1783 scp->fileType == CM_SCACHETYPE_DFSLINK ||
1784 code == CM_ERROR_NOSUCHPATH &&
1785 scp->fileType == CM_SCACHETYPE_INVALID) {
1786 cp = ioctlp->outDatap;
1787 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), spacep->data);
1788 cp += strlen(cp) + 1;
1789 ioctlp->outDatap = cp;
1790 cm_FreeSpace(spacep);
1791 if (newRootScp != NULL)
1792 cm_ReleaseSCache(newRootScp);
1799 long cm_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1800 {/*CHECK FOR VALID SYMLINK*/
1809 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1810 if (code) return code;
1812 cp = ioctlp->inDatap;
1813 osi_LogEvent("cm_IoctlListlink",NULL," name[%s]",cp);
1815 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1816 cm_ReleaseSCache(dscp);
1817 if (code) return code;
1819 /* Check that it's a real symlink */
1820 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1821 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1822 scp->fileType != CM_SCACHETYPE_INVALID)
1823 code = CM_ERROR_INVAL;
1824 cm_ReleaseSCache(scp);
1828 long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1838 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1839 if (code) return code;
1841 cp = ioctlp->inDatap;
1843 #ifdef AFS_FREELANCE_CLIENT
1844 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1845 /* we are adding the mount point to the root dir., so call
1846 * the freelance code to do the add. */
1847 osi_Log0(afsd_logp,"IoctlDeletelink from Freelance root dir");
1848 code = cm_FreelanceRemoveSymlink(cp);
1853 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1855 /* if something went wrong, bail out now */
1860 lock_ObtainMutex(&scp->mx);
1861 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1862 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1864 lock_ReleaseMutex(&scp->mx);
1865 cm_ReleaseSCache(scp);
1869 /* now check that this is a real symlink */
1870 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1871 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1872 scp->fileType != CM_SCACHETYPE_INVALID) {
1873 lock_ReleaseMutex(&scp->mx);
1874 cm_ReleaseSCache(scp);
1875 code = CM_ERROR_INVAL;
1879 /* time to make the RPC, so drop the lock */
1880 lock_ReleaseMutex(&scp->mx);
1881 cm_ReleaseSCache(scp);
1883 /* easier to do it this way */
1884 code = cm_Unlink(dscp, cp, userp, &req);
1885 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1886 smb_NotifyChange(FILE_ACTION_REMOVED,
1887 FILE_NOTIFY_CHANGE_FILE_NAME
1888 | FILE_NOTIFY_CHANGE_DIR_NAME,
1889 dscp, cp, NULL, TRUE);
1892 cm_ReleaseSCache(dscp);
1896 long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
1903 struct ClearToken ct;
1911 int release_userp = 0;
1913 saveDataPtr = ioctlp->inDatap;
1915 cm_SkipIoctlPath(ioctlp);
1917 tp = ioctlp->inDatap;
1920 memcpy(&ticketLen, tp, sizeof(ticketLen));
1921 tp += sizeof(ticketLen);
1922 if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN)
1923 return CM_ERROR_INVAL;
1925 /* remember ticket and skip over it for now */
1929 /* clear token size */
1930 memcpy(&ctSize, tp, sizeof(ctSize));
1931 tp += sizeof(ctSize);
1932 if (ctSize != sizeof(struct ClearToken))
1933 return CM_ERROR_INVAL;
1936 memcpy(&ct, tp, ctSize);
1938 if (ct.AuthHandle == -1)
1939 ct.AuthHandle = 999; /* more rxvab compat stuff */
1941 /* more stuff, if any */
1942 if (ioctlp->inCopied > tp - saveDataPtr) {
1943 /* flags: logon flag */
1944 memcpy(&flags, tp, sizeof(int));
1948 cellp = cm_GetCell(tp, CM_FLAG_CREATE);
1949 if (!cellp) return CM_ERROR_NOSUCHCELL;
1950 tp += strlen(tp) + 1;
1954 tp += strlen(tp) + 1;
1956 #ifndef AFSIFS /* no SMB username, so we cannot log based on this */
1957 if (flags & PIOCTL_LOGON) {
1958 /* SMB user name with which to associate tokens */
1960 osi_Log2(smb_logp,"cm_IoctlSetToken for user [%s] smbname [%s]",
1961 osi_LogSaveString(smb_logp,uname), osi_LogSaveString(smb_logp,smbname));
1962 fprintf(stderr, "SMB name = %s\n", smbname);
1963 tp += strlen(tp) + 1;
1965 osi_Log1(smb_logp,"cm_IoctlSetToken for user [%s]",
1966 osi_LogSaveString(smb_logp,uname));
1970 #ifndef DJGPP /* for win95, session key is back in pioctl */
1972 memcpy(&uuid, tp, sizeof(uuid));
1973 if (!cm_FindTokenEvent(uuid, sessionKey))
1974 return CM_ERROR_INVAL;
1977 cellp = cm_data.rootCellp;
1978 osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
1981 if (flags & PIOCTL_LOGON) {
1982 userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname,
1983 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1987 /* store the token */
1988 lock_ObtainMutex(&userp->mx);
1989 ucellp = cm_GetUCell(userp, cellp);
1990 osi_Log1(smb_logp,"cm_IoctlSetToken ucellp %lx", ucellp);
1991 ucellp->ticketLen = ticketLen;
1992 if (ucellp->ticketp)
1993 free(ucellp->ticketp); /* Discard old token if any */
1994 ucellp->ticketp = malloc(ticketLen);
1995 memcpy(ucellp->ticketp, ticket, ticketLen);
1998 * Get the session key from the RPC, rather than from the pioctl.
2001 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
2003 memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
2005 /* for win95, we are getting the session key from the pioctl */
2006 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
2008 ucellp->kvno = ct.AuthHandle;
2009 ucellp->expirationTime = ct.EndTimestamp;
2012 StringCbCopyA(ucellp->userName, MAXKTCNAMELEN, uname);
2013 ucellp->flags |= CM_UCELLFLAG_RXKAD;
2014 lock_ReleaseMutex(&userp->mx);
2016 if (flags & PIOCTL_LOGON) {
2017 ioctlp->flags |= SMB_IOCTLFLAG_LOGON;
2020 cm_ResetACLCache(userp);
2023 cm_ReleaseUser(userp);
2028 long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
2034 struct ClearToken ct;
2036 cm_SkipIoctlPath(ioctlp);
2038 tp = ioctlp->inDatap;
2039 cp = ioctlp->outDatap;
2042 memcpy(&iterator, tp, sizeof(iterator));
2043 tp += sizeof(iterator);
2045 lock_ObtainMutex(&userp->mx);
2047 /* look for token */
2048 for (;;iterator++) {
2049 ucellp = cm_FindUCell(userp, iterator);
2051 lock_ReleaseMutex(&userp->mx);
2052 return CM_ERROR_NOMORETOKENS;
2054 if (ucellp->flags & CM_UCELLFLAG_RXKAD)
2059 temp = ucellp->iterator + 1;
2060 memcpy(cp, &temp, sizeof(temp));
2064 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2065 cp += sizeof(ucellp->ticketLen);
2068 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2069 cp += ucellp->ticketLen;
2071 /* clear token size */
2073 memcpy(cp, &temp, sizeof(temp));
2077 ct.AuthHandle = ucellp->kvno;
2080 * Don't give out a real session key here
2083 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2085 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2087 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2089 ct.ViceId = 37; /* XXX */
2090 ct.BeginTimestamp = 0; /* XXX */
2091 ct.EndTimestamp = ucellp->expirationTime;
2092 memcpy(cp, &ct, sizeof(ct));
2095 /* Primary flag (unused) */
2097 memcpy(cp, &temp, sizeof(temp));
2101 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->cellp->name);
2102 cp += strlen(cp) + 1;
2105 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->userName);
2106 cp += strlen(cp) + 1;
2108 ioctlp->outDatap = cp;
2110 lock_ReleaseMutex(&userp->mx);
2115 long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2121 struct ClearToken ct;
2127 cm_SkipIoctlPath(ioctlp);
2129 tp = ioctlp->inDatap;
2131 cp = ioctlp->outDatap;
2133 /* cell name is right here */
2134 cellp = cm_GetCell(tp, 0);
2136 return CM_ERROR_NOSUCHCELL;
2137 tp += strlen(tp) + 1;
2141 memcpy(&uuid, tp, sizeof(uuid));
2144 lock_ObtainMutex(&userp->mx);
2146 ucellp = cm_GetUCell(userp, cellp);
2147 if (!ucellp || !(ucellp->flags & CM_UCELLFLAG_RXKAD)) {
2148 lock_ReleaseMutex(&userp->mx);
2149 return CM_ERROR_NOMORETOKENS;
2153 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2154 cp += sizeof(ucellp->ticketLen);
2157 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2158 cp += ucellp->ticketLen;
2160 /* clear token size */
2162 memcpy(cp, &temp, sizeof(temp));
2166 ct.AuthHandle = ucellp->kvno;
2169 * Don't give out a real session key here
2172 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2174 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2176 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2178 ct.ViceId = 37; /* XXX */
2179 ct.BeginTimestamp = 0; /* XXX */
2180 ct.EndTimestamp = ucellp->expirationTime;
2181 memcpy(cp, &ct, sizeof(ct));
2184 /* Primary flag (unused) */
2186 memcpy(cp, &temp, sizeof(temp));
2190 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->cellp->name);
2191 cp += strlen(cp) + 1;
2194 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->userName);
2195 cp += strlen(cp) + 1;
2197 ioctlp->outDatap = cp;
2199 lock_ReleaseMutex(&userp->mx);
2202 cm_RegisterNewTokenEvent(uuid, ucellp->sessionKey.data);
2208 long cm_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2214 cm_SkipIoctlPath(ioctlp);
2216 cp = ioctlp->outDatap;
2218 /* cell name is right here */
2219 cellp = cm_GetCell(ioctlp->inDatap, 0);
2220 if (!cellp) return CM_ERROR_NOSUCHCELL;
2222 lock_ObtainMutex(&userp->mx);
2224 ucellp = cm_GetUCell(userp, cellp);
2226 lock_ReleaseMutex(&userp->mx);
2227 return CM_ERROR_NOMORETOKENS;
2230 osi_Log1(smb_logp,"cm_IoctlDelToken ucellp %lx", ucellp);
2232 if (ucellp->ticketp) {
2233 free(ucellp->ticketp);
2234 ucellp->ticketp = NULL;
2236 ucellp->ticketLen = 0;
2237 memset(ucellp->sessionKey.data, 0, 8);
2239 ucellp->expirationTime = 0;
2240 ucellp->userName[0] = '\0';
2241 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2244 lock_ReleaseMutex(&userp->mx);
2246 cm_ResetACLCache(userp);
2251 long cm_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2255 lock_ObtainMutex(&userp->mx);
2257 for (ucellp = userp->cellInfop; ucellp; ucellp = ucellp->nextp) {
2258 osi_Log1(smb_logp,"cm_IoctlDelAllToken ucellp %lx", ucellp);
2260 if (ucellp->ticketp) {
2261 free(ucellp->ticketp);
2262 ucellp->ticketp = NULL;
2264 ucellp->ticketLen = 0;
2265 memset(ucellp->sessionKey.data, 0, 8);
2267 ucellp->expirationTime = 0;
2268 ucellp->userName[0] = '\0';
2269 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2273 lock_ReleaseMutex(&userp->mx);
2275 cm_ResetACLCache(userp);
2280 long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
2282 char afspath[MAX_PATH];
2284 int nextAutoSubmount;
2286 DWORD dwType, dwSize;
2291 cm_SkipIoctlPath(ioctlp);
2293 /* Serialize this one, to prevent simultaneous mods
2296 lock_ObtainMutex(&cm_Afsdsbmt_Lock);
2298 /* Parse the input parameters--first the required afs path,
2299 * then the requested submount name (which may be "").
2301 cm_NormalizeAfsPath (afspath, sizeof(afspath), ioctlp->inDatap);
2302 submountreqp = ioctlp->inDatap + (strlen(ioctlp->inDatap)+1);
2304 /* If the caller supplied a suggested submount name, see if
2305 * that submount name is in use... if so, the submount's path
2306 * has to match our path.
2309 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
2310 AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
2313 REG_OPTION_NON_VOLATILE,
2314 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
2319 if (submountreqp && *submountreqp) {
2320 char submountPathNormalized[MAX_PATH];
2321 char submountPath[MAX_PATH];
2323 dwSize = sizeof(submountPath);
2324 status = RegQueryValueEx( hkSubmounts, submountreqp, 0,
2325 &dwType, submountPath, &dwSize);
2327 if (status != ERROR_SUCCESS) {
2329 /* The suggested submount name isn't in use now--
2330 * so we can safely map the requested submount name
2331 * to the supplied path. Remember not to write the
2332 * leading "/afs" when writing out the submount.
2334 RegSetValueEx( hkSubmounts, submountreqp, 0,
2336 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2337 &afspath[strlen(cm_mountRoot)]:"/",
2338 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2339 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2341 RegCloseKey( hkSubmounts );
2342 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountreqp);
2343 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2344 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2348 /* The suggested submount name is already in use--if the
2349 * supplied path matches the submount's path, we can still
2350 * use the suggested submount name.
2352 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2353 if (!strcmp (submountPathNormalized, afspath)) {
2354 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountreqp);
2355 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2356 RegCloseKey( hkSubmounts );
2357 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2362 RegQueryInfoKey( hkSubmounts,
2364 NULL, /* lpcClass */
2365 NULL, /* lpReserved */
2366 NULL, /* lpcSubKeys */
2367 NULL, /* lpcMaxSubKeyLen */
2368 NULL, /* lpcMaxClassLen */
2369 &dwSubmounts, /* lpcValues */
2370 NULL, /* lpcMaxValueNameLen */
2371 NULL, /* lpcMaxValueLen */
2372 NULL, /* lpcbSecurityDescriptor */
2373 NULL /* lpftLastWriteTime */
2377 /* Having obtained a list of all available submounts, start
2378 * searching that list for a path which matches the requested
2379 * AFS path. We'll also keep track of the highest "auto15"/"auto47"
2380 * submount, in case we need to add a new one later.
2383 nextAutoSubmount = 1;
2385 for ( dwIndex = 0; dwIndex < dwSubmounts; dwIndex ++ ) {
2386 char submountPathNormalized[MAX_PATH];
2387 char submountPath[MAX_PATH] = "";
2388 DWORD submountPathLen = sizeof(submountPath);
2389 char submountName[MAX_PATH];
2390 DWORD submountNameLen = sizeof(submountName);
2393 RegEnumValue( hkSubmounts, dwIndex, submountName, &submountNameLen, NULL,
2394 &dwType, submountPath, &submountPathLen);
2395 if (dwType == REG_EXPAND_SZ) {
2397 StringCbCopyA(buf, MAX_PATH, submountPath);
2398 submountPathLen = ExpandEnvironmentStrings(buf, submountPath, MAX_PATH);
2399 if (submountPathLen > MAX_PATH)
2403 /* If this is an Auto### submount, remember its ### value */
2404 if ((!strnicmp (submountName, "auto", 4)) &&
2405 (isdigit (submountName[strlen("auto")]))) {
2406 int thisAutoSubmount;
2407 thisAutoSubmount = atoi (&submountName[strlen("auto")]);
2408 nextAutoSubmount = max (nextAutoSubmount,
2409 thisAutoSubmount+1);
2412 if ((submountPathLen == 0) ||
2413 (submountPathLen == sizeof(submountPath) - 1)) {
2417 /* See if the path for this submount matches the path
2418 * that our caller specified. If so, we can return
2421 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2422 if (!strcmp (submountPathNormalized, afspath)) {
2423 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountName);
2424 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2425 RegCloseKey(hkSubmounts);
2426 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2432 /* We've been through the entire list of existing submounts, and
2433 * didn't find any which matched the specified path. So, we'll
2434 * just have to add one. Remember not to write the leading "/afs"
2435 * when writing out the submount.
2438 StringCbPrintfA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "auto%ld", nextAutoSubmount);
2440 RegSetValueEx( hkSubmounts,
2444 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2445 &afspath[strlen(cm_mountRoot)]:"/",
2446 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2447 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2449 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2450 RegCloseKey(hkSubmounts);
2451 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2455 long cm_IoctlGetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2457 memcpy(ioctlp->outDatap, &cryptall, sizeof(cryptall));
2458 ioctlp->outDatap += sizeof(cryptall);
2463 long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2465 afs_int32 c = cryptall;
2467 cm_SkipIoctlPath(ioctlp);
2469 memcpy(&cryptall, ioctlp->inDatap, sizeof(cryptall));
2471 if (c != cryptall) {
2473 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_ON);
2475 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_OFF);
2480 long cm_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp)
2485 cm_SkipIoctlPath(ioctlp);
2487 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2488 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2491 if (flags & AFSCALL_RXSTATS_ENABLE) {
2492 rx_enableProcessRPCStats();
2494 if (flags & AFSCALL_RXSTATS_DISABLE) {
2495 rx_disableProcessRPCStats();
2497 if (flags & AFSCALL_RXSTATS_CLEAR) {
2498 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
2503 long cm_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp)
2508 cm_SkipIoctlPath(ioctlp);
2510 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2511 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2514 if (flags & AFSCALL_RXSTATS_ENABLE) {
2515 rx_enablePeerRPCStats();
2517 if (flags & AFSCALL_RXSTATS_DISABLE) {
2518 rx_disablePeerRPCStats();
2520 if (flags & AFSCALL_RXSTATS_CLEAR) {
2521 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
2527 extern int afsd_shutdown(int);
2528 extern int afs_shutdown;
2530 long cm_IoctlShutdown(smb_ioctl_t *ioctlp, cm_user_t *userp) {
2531 afs_shutdown = 1; /* flag to shut down */
2536 long cm_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp)
2538 smb_user_t *uidp = ioctlp->uidp;
2540 if (uidp && uidp->unp) {
2541 memcpy(ioctlp->outDatap, uidp->unp->name, strlen(uidp->unp->name));
2542 ioctlp->outDatap += strlen(uidp->unp->name);
2549 * functions to dump contents of various structures.
2550 * In debug build (linked with crt debug library) will dump allocated but not freed memory
2552 extern int cm_DumpSCache(FILE *outputFile, char *cookie, int lock);
2553 extern int cm_DumpBufHashTable(FILE *outputFile, char *cookie, int lock);
2554 extern int smb_DumpVCP(FILE *outputFile, char *cookie, int lock);
2556 long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
2560 char logfileName[MAX_PATH+1];
2565 static _CrtMemState memstate;
2568 cm_SkipIoctlPath(ioctlp);
2569 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
2571 dwSize = GetEnvironmentVariable("TEMP", logfileName, sizeof(logfileName));
2572 if ( dwSize == 0 || dwSize > sizeof(logfileName) )
2574 GetWindowsDirectory(logfileName, sizeof(logfileName));
2576 strncat(logfileName, "\\afsd_alloc.log", sizeof(logfileName));
2578 hLogFile = CreateFile(logfileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2584 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2585 ioctlp->outDatap += sizeof(long);
2590 SetFilePointer(hLogFile, 0, NULL, FILE_END);
2592 cookie = inValue ? "b" : "e";
2598 _CrtMemCheckpoint(&memstate);
2602 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2603 _CrtSetReportFile(_CRT_WARN, hLogFile);
2604 _CrtMemDumpAllObjectsSince(&memstate);
2608 /* dump all interesting data */
2609 cm_DumpSCache(hLogFile, cookie, 1);
2610 cm_DumpBufHashTable(hLogFile, cookie, 1);
2611 smb_DumpVCP(hLogFile, cookie, 1);
2613 CloseHandle(hLogFile);
2615 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2616 ioctlp->outDatap += sizeof(long);