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>
12 #include <afs/cellconfig.h>
13 #include <afs/ptserver.h>
27 #include "afsd_init.h"
28 #include <WINNT\afsreg.h>
31 #include "cm_server.h"
39 #include <..\afsrdr\kif.h>
46 /* Copied from afs_tokens.h */
47 #define PIOCTL_LOGON 0x1
50 osi_mutex_t cm_Afsdsbmt_Lock;
52 extern afs_int32 cryptall;
53 extern char cm_NetbiosName[];
55 extern void afsi_log(char *pattern, ...);
57 void cm_InitIoctl(void)
59 lock_InitializeMutex(&cm_Afsdsbmt_Lock, "AFSDSBMT.INI Access Lock");
62 long cm_CleanFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
66 lock_ObtainWrite(&scp->bufCreateLock);
67 code = buf_CleanVnode(scp, userp, reqp);
69 lock_ObtainMutex(&scp->mx);
70 cm_DiscardSCache(scp);
71 lock_ReleaseMutex(&scp->mx);
73 lock_ReleaseWrite(&scp->bufCreateLock);
74 osi_Log2(afsd_logp,"cm_CleanFile scp 0x%x returns error: [%x]",scp, code);
78 long cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
82 #ifdef AFS_FREELANCE_CLIENT
83 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
84 cm_noteLocalMountPointChange();
89 lock_ObtainWrite(&scp->bufCreateLock);
90 code = buf_FlushCleanPages(scp, userp, reqp);
92 lock_ObtainMutex(&scp->mx);
93 cm_DiscardSCache(scp);
95 lock_ReleaseMutex(&scp->mx);
97 lock_ReleaseWrite(&scp->bufCreateLock);
98 osi_Log2(afsd_logp,"cm_FlushFile scp 0x%x returns error: [%x]",scp, code);
102 long cm_FlushParent(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
107 pscp = cm_FindSCacheParent(scp);
109 /* now flush the file */
110 code = cm_FlushFile(pscp, userp, reqp);
111 cm_ReleaseSCache(pscp);
117 long cm_FlushVolume(cm_user_t *userp, cm_req_t *reqp, afs_uint32 cell, afs_uint32 volume)
123 #ifdef AFS_FREELANCE_CLIENT
124 if ( cell == AFS_FAKE_ROOT_CELL_ID && volume == AFS_FAKE_ROOT_VOL_ID ) {
125 cm_noteLocalMountPointChange();
130 lock_ObtainWrite(&cm_scacheLock);
131 for (i=0; i<cm_data.hashTableSize; i++) {
132 for (scp = cm_data.hashTablep[i]; scp; scp = scp->nextp) {
133 if (scp->fid.volume == volume && scp->fid.cell == cell) {
134 cm_HoldSCacheNoLock(scp);
135 lock_ReleaseWrite(&cm_scacheLock);
137 /* now flush the file */
138 code = cm_FlushFile(scp, userp, reqp);
139 lock_ObtainWrite(&cm_scacheLock);
140 cm_ReleaseSCacheNoLock(scp);
144 lock_ReleaseWrite(&cm_scacheLock);
150 * cm_ResetACLCache -- invalidate ACL info for a user that has just
151 * obtained or lost tokens
153 void cm_ResetACLCache(cm_user_t *userp)
158 lock_ObtainWrite(&cm_scacheLock);
159 for (hash=0; hash < cm_data.hashTableSize; hash++) {
160 for (scp=cm_data.hashTablep[hash]; scp; scp=scp->nextp) {
161 cm_HoldSCacheNoLock(scp);
162 lock_ReleaseWrite(&cm_scacheLock);
163 lock_ObtainMutex(&scp->mx);
164 cm_InvalidateACLUser(scp, userp);
165 lock_ReleaseMutex(&scp->mx);
166 lock_ObtainWrite(&cm_scacheLock);
167 cm_ReleaseSCacheNoLock(scp);
170 lock_ReleaseWrite(&cm_scacheLock);
174 * TranslateExtendedChars - This is a fix for TR 54482.
176 * If an extended character (80 - FF) is entered into a file
177 * or directory name in Windows, the character is translated
178 * into the OEM character map before being passed to us. Why
179 * this occurs is unknown. Our pioctl functions must match
180 * this translation for paths given via our own commands (like
181 * fs). If we do not do this, then we will try to perform an
182 * operation on a non-translated path, which we will fail to
183 * find, since the path was created with the translated chars.
184 * This function performs the required translation.
186 void TranslateExtendedChars(char *str)
194 /* parse the passed-in file name and do a namei on it. If we fail,
195 * return an error code, otherwise return the vnode located in *scpp.
197 long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
202 cm_scache_t *substRootp = NULL;
204 char * relativePath = ioctlp->inDatap;
206 osi_Log1(afsd_logp, "cm_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,relativePath));
208 /* This is usually the file name, but for StatMountPoint it is the path. */
209 /* ioctlp->inDatap can be either of the form:
212 * \\netbios-name\submount\path\.
213 * \\netbios-name\submount\path\file
215 TranslateExtendedChars(relativePath);
218 /* we have passed the whole path, including the afs prefix.
219 when the pioctl call is made, we perform an ioctl to afsrdr
220 and it returns the correct (full) path. therefore, there is
221 no drive letter, and the path is absolute. */
222 code = cm_NameI(cm_data.rootSCachep, relativePath,
223 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
224 userp, "", reqp, scpp);
227 osi_Log1(afsd_logp,"cm_ParseIoctlPath code 0x%x", code);
231 if (relativePath[0] == relativePath[1] &&
232 relativePath[1] == '\\' &&
233 !_strnicmp(cm_NetbiosName,relativePath+2,strlen(cm_NetbiosName)))
239 /* We may have found a UNC path.
240 * If the first component is the NetbiosName,
241 * then throw out the second component (the submount)
242 * since it had better expand into the value of ioctl->tidPathp
245 p = relativePath + 2 + strlen(cm_NetbiosName) + 1; /* buffer overflow vuln.? */
246 if ( !_strnicmp("all", p, 3) )
249 for (i = 0; *p && *p != '\\'; i++,p++ ) {
252 p++; /* skip past trailing slash */
253 shareName[i] = 0; /* terminate string */
255 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
257 /* we found a sharename, therefore use the resulting path */
258 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
259 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
260 userp, sharePath, reqp, &substRootp);
263 osi_Log1(afsd_logp,"cm_ParseIoctlPath [1] code 0x%x", code);
267 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
268 userp, NULL, reqp, scpp);
270 osi_Log1(afsd_logp,"cm_ParseIoctlPath [2] code 0x%x", code);
274 /* otherwise, treat the name as a cellname mounted off the afs root.
275 * This requires that we reconstruct the shareName string with
276 * leading and trailing slashes.
278 p = relativePath + 2 + strlen(cm_NetbiosName) + 1;
279 if ( !_strnicmp("all", p, 3) )
283 for (i = 1; *p && *p != '\\'; i++,p++ ) {
286 p++; /* skip past trailing slash */
287 shareName[i++] = '/'; /* add trailing slash */
288 shareName[i] = 0; /* terminate string */
291 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
292 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
293 userp, shareName, reqp, &substRootp);
295 osi_Log1(afsd_logp,"cm_ParseIoctlPath [3] code 0x%x", code);
299 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
300 userp, NULL, reqp, scpp);
302 cm_ReleaseSCache(substRootp);
303 osi_Log1(afsd_logp,"cm_ParseIoctlPath code [4] 0x%x", code);
308 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
309 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
310 userp, ioctlp->tidPathp, reqp, &substRootp);
312 osi_Log1(afsd_logp,"cm_ParseIoctlPath [6] code 0x%x", code);
316 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
317 userp, NULL, reqp, scpp);
319 cm_ReleaseSCache(substRootp);
320 osi_Log1(afsd_logp,"cm_ParseIoctlPath [7] code 0x%x", code);
326 /* # of bytes of path */
327 code = (long)strlen(ioctlp->inDatap) + 1;
328 ioctlp->inDatap += code;
330 /* This is usually nothing, but for StatMountPoint it is the file name. */
331 TranslateExtendedChars(ioctlp->inDatap);
334 cm_ReleaseSCache(substRootp);
336 /* and return success */
337 osi_Log1(afsd_logp,"cm_ParseIoctlPath [8] code 0x%x", code);
341 void cm_SkipIoctlPath(smb_ioctl_t *ioctlp)
345 temp = (long) strlen(ioctlp->inDatap) + 1;
346 ioctlp->inDatap += temp;
350 /* format the specified path to look like "/afs/<cellname>/usr", by
351 * adding "/afs" (if necessary) in front, changing any \'s to /'s, and
352 * removing any trailing "/"'s. One weirdo caveat: "/afs" will be
353 * intentionally returned as "/afs/"--this makes submount manipulation
354 * easier (because we can always jump past the initial "/afs" to find
355 * the AFS path that should be written into afsdsbmt.ini).
357 void cm_NormalizeAfsPath(char *outpathp, long outlen, char *inpathp)
360 char bslash_mountRoot[256];
362 strncpy(bslash_mountRoot, cm_mountRoot, sizeof(bslash_mountRoot) - 1);
363 bslash_mountRoot[0] = '\\';
365 if (!strnicmp (inpathp, cm_mountRoot, strlen(cm_mountRoot)))
366 StringCbCopy(outpathp, outlen, inpathp);
367 else if (!strnicmp (inpathp, bslash_mountRoot, strlen(bslash_mountRoot)))
368 StringCbCopy(outpathp, outlen, inpathp);
369 else if ((inpathp[0] == '/') || (inpathp[0] == '\\'))
370 StringCbPrintfA(outpathp, outlen, "%s%s", cm_mountRoot, inpathp);
371 else // inpathp looks like "<cell>/usr"
372 StringCbPrintfA(outpathp, outlen, "%s/%s", cm_mountRoot, inpathp);
374 for (cp = outpathp; *cp != 0; ++cp) {
379 if (strlen(outpathp) && (outpathp[strlen(outpathp)-1] == '/')) {
380 outpathp[strlen(outpathp)-1] = 0;
383 if (!strcmpi (outpathp, cm_mountRoot)) {
384 StringCbCopy(outpathp, outlen, cm_mountRoot);
388 #define LEAF_SIZE 256
389 /* parse the passed-in file name and do a namei on its parent. If we fail,
390 * return an error code, otherwise return the vnode located in *scpp.
392 long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
393 cm_scache_t **scpp, char *leafp)
398 cm_scache_t *substRootp;
400 StringCbCopyA(tbuffer, sizeof(tbuffer), ioctlp->inDatap);
401 tp = strrchr(tbuffer, '\\');
402 jp = strrchr(tbuffer, '/');
405 else if (jp && (tp - tbuffer) < (jp - tbuffer))
408 StringCbCopyA(tbuffer, sizeof(tbuffer), "\\");
410 StringCbCopyA(leafp, LEAF_SIZE, ioctlp->inDatap);
415 StringCbCopyA(leafp, LEAF_SIZE, tp+1);
418 if (tbuffer[0] == tbuffer[1] &&
419 tbuffer[1] == '\\' &&
420 !_strnicmp(cm_NetbiosName,tbuffer+2,strlen(cm_NetbiosName)))
426 /* We may have found a UNC path.
427 * If the first component is the NetbiosName,
428 * then throw out the second component (the submount)
429 * since it had better expand into the value of ioctl->tidPathp
432 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
433 if ( !_strnicmp("all", p, 3) )
436 for (i = 0; *p && *p != '\\'; i++,p++ ) {
439 p++; /* skip past trailing slash */
440 shareName[i] = 0; /* terminate string */
442 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
444 /* we found a sharename, therefore use the resulting path */
445 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
446 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
447 userp, sharePath, reqp, &substRootp);
449 if (code) return code;
451 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
452 userp, NULL, reqp, scpp);
453 if (code) return code;
455 /* otherwise, treat the name as a cellname mounted off the afs root.
456 * This requires that we reconstruct the shareName string with
457 * leading and trailing slashes.
459 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
460 if ( !_strnicmp("all", p, 3) )
464 for (i = 1; *p && *p != '\\'; i++,p++ ) {
467 p++; /* skip past trailing slash */
468 shareName[i++] = '/'; /* add trailing slash */
469 shareName[i] = 0; /* terminate string */
471 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
472 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
473 userp, shareName, reqp, &substRootp);
474 if (code) return code;
476 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
477 userp, NULL, reqp, scpp);
478 if (code) return code;
481 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
482 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
483 userp, ioctlp->tidPathp, reqp, &substRootp);
484 if (code) return code;
486 code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
487 userp, NULL, reqp, scpp);
488 if (code) return code;
491 /* # of bytes of path */
492 code = (long)strlen(ioctlp->inDatap) + 1;
493 ioctlp->inDatap += code;
495 /* and return success */
499 long cm_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp)
504 AFSFetchStatus fileStatus;
510 struct rx_connection * callp;
514 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
515 if (code) return code;
517 /* now make the get acl call */
518 fid.Volume = scp->fid.volume;
519 fid.Vnode = scp->fid.vnode;
520 fid.Unique = scp->fid.unique;
522 acl.AFSOpaque_val = ioctlp->outDatap;
523 acl.AFSOpaque_len = 0;
524 code = cm_Conn(&scp->fid, userp, &req, &connp);
527 callp = cm_GetRxConn(connp);
528 code = RXAFS_FetchACL(callp, &fid, &acl, &fileStatus, &volSync);
529 rx_PutConnection(callp);
531 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
532 code = cm_MapRPCError(code, &req);
533 cm_ReleaseSCache(scp);
535 if (code) return code;
537 /* skip over return data */
538 tlen = (int)strlen(ioctlp->outDatap) + 1;
539 ioctlp->outDatap += tlen;
541 /* and return success */
545 long cm_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp)
554 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
555 if (code) return code;
557 #ifdef AFS_FREELANCE_CLIENT
558 if ( cm_freelanceEnabled &&
559 scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
560 scp->fid.volume==AFS_FAKE_ROOT_VOL_ID &&
561 scp->fid.vnode==0x1 && scp->fid.unique==0x1 ) {
562 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "Freelance.Local.Root");
563 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
566 #endif /* AFS_FREELANCE_CLIENT */
568 cellp = cm_FindCellByID(scp->fid.cell);
570 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), cellp->name);
571 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
575 code = CM_ERROR_NOSUCHCELL;
578 cm_ReleaseSCache(scp);
582 long cm_IoctlSetACL(struct smb_ioctl *ioctlp, struct cm_user *userp)
587 AFSFetchStatus fileStatus;
592 struct rx_connection * callp;
596 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
597 if (code) return code;
599 /* now make the get acl call */
600 fid.Volume = scp->fid.volume;
601 fid.Vnode = scp->fid.vnode;
602 fid.Unique = scp->fid.unique;
604 acl.AFSOpaque_val = ioctlp->inDatap;
605 acl.AFSOpaque_len = (u_int)strlen(ioctlp->inDatap)+1;
606 code = cm_Conn(&scp->fid, userp, &req, &connp);
609 callp = cm_GetRxConn(connp);
610 code = RXAFS_StoreACL(callp, &fid, &acl, &fileStatus, &volSync);
611 rx_PutConnection(callp);
613 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
614 code = cm_MapRPCError(code, &req);
616 /* invalidate cache info, since we just trashed the ACL cache */
617 lock_ObtainMutex(&scp->mx);
618 cm_DiscardSCache(scp);
619 lock_ReleaseMutex(&scp->mx);
621 cm_ReleaseSCache(scp);
628 long cm_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
637 lock_ObtainWrite(&cm_scacheLock);
638 for (i=0; i<cm_data.hashTableSize; i++) {
639 for (scp = cm_data.hashTablep[i]; scp; scp = scp->nextp) {
640 cm_HoldSCacheNoLock(scp);
641 lock_ReleaseWrite(&cm_scacheLock);
643 /* now flush the file */
644 code = cm_FlushFile(scp, userp, &req);
645 lock_ObtainWrite(&cm_scacheLock);
646 cm_ReleaseSCacheNoLock(scp);
649 lock_ReleaseWrite(&cm_scacheLock);
654 long cm_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp)
658 unsigned long volume;
664 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
665 if (code) return code;
667 volume = scp->fid.volume;
668 cell = scp->fid.cell;
669 cm_ReleaseSCache(scp);
671 code = cm_FlushVolume(userp, &req, cell, volume);
676 long cm_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp)
684 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
685 if (code) return code;
687 cm_FlushFile(scp, userp, &req);
688 cm_ReleaseSCache(scp);
693 long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
697 char offLineMsg[256];
701 AFSFetchVolumeStatus volStat;
702 AFSStoreVolumeStatus storeStat;
707 struct rx_connection * callp;
711 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
712 if (code) return code;
714 cellp = cm_FindCellByID(scp->fid.cell);
717 if (scp->flags & CM_SCACHEFLAG_RO) {
718 cm_ReleaseSCache(scp);
719 return CM_ERROR_READONLY;
722 code = cm_GetVolumeByID(cellp, scp->fid.volume, userp, &req, &tvp);
724 cm_ReleaseSCache(scp);
728 /* Copy the junk out, using cp as a roving pointer. */
729 cp = ioctlp->inDatap;
730 memcpy((char *)&volStat, cp, sizeof(AFSFetchVolumeStatus));
731 cp += sizeof(AFSFetchVolumeStatus);
732 StringCbCopyA(volName, sizeof(volName), cp);
733 cp += strlen(volName)+1;
734 StringCbCopyA(offLineMsg, sizeof(offLineMsg), cp);
735 cp += strlen(offLineMsg)+1;
736 StringCbCopyA(motd, sizeof(motd), cp);
738 if (volStat.MinQuota != -1) {
739 storeStat.MinQuota = volStat.MinQuota;
740 storeStat.Mask |= AFS_SETMINQUOTA;
742 if (volStat.MaxQuota != -1) {
743 storeStat.MaxQuota = volStat.MaxQuota;
744 storeStat.Mask |= AFS_SETMAXQUOTA;
748 code = cm_Conn(&scp->fid, userp, &req, &tcp);
751 callp = cm_GetRxConn(tcp);
752 code = RXAFS_SetVolumeStatus(callp, scp->fid.volume,
753 &storeStat, volName, offLineMsg, motd);
754 rx_PutConnection(callp);
756 } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
757 code = cm_MapRPCError(code, &req);
759 /* return on failure */
760 cm_ReleaseSCache(scp);
765 /* we are sending parms back to make compat. with prev system. should
766 * change interface later to not ask for current status, just set
769 cp = ioctlp->outDatap;
770 memcpy(cp, (char *)&volStat, sizeof(VolumeStatus));
771 cp += sizeof(VolumeStatus);
772 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), volName);
773 cp += strlen(volName)+1;
774 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), offLineMsg);
775 cp += strlen(offLineMsg)+1;
776 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), motd);
777 cp += strlen(motd)+1;
779 /* now return updated return data pointer */
780 ioctlp->outDatap = cp;
785 long cm_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
789 char offLineMsg[256];
793 AFSFetchVolumeStatus volStat;
799 struct rx_connection * callp;
803 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
804 if (code) return code;
807 OfflineMsg = offLineMsg;
810 code = cm_Conn(&scp->fid, userp, &req, &tcp);
813 callp = cm_GetRxConn(tcp);
814 code = RXAFS_GetVolumeStatus(callp, scp->fid.volume,
815 &volStat, &Name, &OfflineMsg, &MOTD);
816 rx_PutConnection(callp);
818 } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
819 code = cm_MapRPCError(code, &req);
821 cm_ReleaseSCache(scp);
822 if (code) return code;
824 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
825 cp = ioctlp->outDatap;
826 memcpy(cp, (char *)&volStat, sizeof(AFSFetchVolumeStatus));
827 cp += sizeof(AFSFetchVolumeStatus);
828 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), volName);
829 cp += strlen(volName)+1;
830 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), offLineMsg);
831 cp += strlen(offLineMsg)+1;
832 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), motd);
833 cp += strlen(motd)+1;
835 /* return new size */
836 ioctlp->outDatap = cp;
841 long cm_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp)
851 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
852 if (code) return code;
854 memset(&fid, 0, sizeof(cm_fid_t));
855 fid.volume = scp->fid.volume;
856 fid.vnode = scp->fid.vnode;
857 fid.unique = scp->fid.unique;
859 cm_ReleaseSCache(scp);
861 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
862 cp = ioctlp->outDatap;
863 memcpy(cp, (char *)&fid, sizeof(cm_fid_t));
864 cp += sizeof(cm_fid_t);
866 /* return new size */
867 ioctlp->outDatap = cp;
872 long cm_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp)
881 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
882 if (code) return code;
884 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
885 cp = ioctlp->outDatap;
886 memcpy(cp, (char *)&scp->owner, sizeof(afs_uint32));
887 cp += sizeof(afs_uint32);
888 memcpy(cp, (char *)&scp->group, sizeof(afs_uint32));
889 cp += sizeof(afs_uint32);
891 /* return new size */
892 ioctlp->outDatap = cp;
894 cm_ReleaseSCache(scp);
899 long cm_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp)
905 cm_serverRef_t **tsrpp, *current;
907 unsigned long volume;
913 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
914 if (code) return code;
916 volume = scp->fid.volume;
918 cellp = cm_FindCellByID(scp->fid.cell);
921 cm_ReleaseSCache(scp);
923 code = cm_GetVolumeByID(cellp, volume, userp, &req, &tvp);
924 if (code) return code;
926 cp = ioctlp->outDatap;
928 lock_ObtainMutex(&tvp->mx);
929 tsrpp = cm_GetVolServers(tvp, volume);
930 lock_ObtainRead(&cm_serverLock);
931 for (current = *tsrpp; current; current = current->next) {
932 tsp = current->server;
933 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
936 lock_ReleaseRead(&cm_serverLock);
937 cm_FreeServerList(tsrpp);
938 lock_ReleaseMutex(&tvp->mx);
940 /* still room for terminating NULL, add it on */
941 volume = 0; /* reuse vbl */
942 memcpy(cp, (char *)&volume, sizeof(long));
945 ioctlp->outDatap = cp;
950 long cm_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
960 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
961 if (code) return code;
963 cp = ioctlp->inDatap;
965 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
966 cm_ReleaseSCache(dscp);
967 if (code) return code;
969 lock_ObtainMutex(&scp->mx);
971 /* now check that this is a real mount point */
972 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
973 lock_ReleaseMutex(&scp->mx);
974 cm_ReleaseSCache(scp);
975 return CM_ERROR_INVAL;
978 code = cm_ReadMountPoint(scp, userp, &req);
980 cp = ioctlp->outDatap;
981 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), scp->mountPointStringp);
982 cp += strlen(cp) + 1;
983 ioctlp->outDatap = cp;
985 lock_ReleaseMutex(&scp->mx);
986 cm_ReleaseSCache(scp);
991 long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1001 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1002 if (code) return code;
1004 cp = ioctlp->inDatap;
1006 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1008 /* if something went wrong, bail out now */
1013 lock_ObtainMutex(&scp->mx);
1014 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1015 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1017 lock_ReleaseMutex(&scp->mx);
1018 cm_ReleaseSCache(scp);
1022 /* now check that this is a real mount point */
1023 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
1024 lock_ReleaseMutex(&scp->mx);
1025 cm_ReleaseSCache(scp);
1026 code = CM_ERROR_INVAL;
1030 /* time to make the RPC, so drop the lock */
1031 lock_ReleaseMutex(&scp->mx);
1032 cm_ReleaseSCache(scp);
1034 /* easier to do it this way */
1035 code = cm_Unlink(dscp, cp, userp, &req);
1036 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1037 smb_NotifyChange(FILE_ACTION_REMOVED,
1038 FILE_NOTIFY_CHANGE_DIR_NAME,
1039 dscp, cp, NULL, TRUE);
1042 lock_ObtainMutex(&scp->mx);
1043 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1044 lock_ReleaseMutex(&scp->mx);
1047 cm_ReleaseSCache(dscp);
1051 long cm_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp)
1061 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1062 tp = ioctlp->inDatap;
1065 memcpy(&temp, tp, sizeof(temp));
1066 if (temp == 0x12345678) { /* For afs3.3 version */
1067 memcpy(&csi, tp, sizeof(csi));
1068 if (csi.tinterval >= 0) {
1069 cp = ioctlp->outDatap;
1070 memcpy(cp, (char *)&cm_daemonCheckDownInterval, sizeof(long));
1071 ioctlp->outDatap += sizeof(long);
1072 if (csi.tinterval > 0) {
1073 if (!smb_SUser(userp))
1074 return CM_ERROR_NOACCESS;
1075 cm_daemonCheckDownInterval = csi.tinterval;
1083 } else { /* For pre afs3.3 versions */
1084 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
1085 ioctlp->inDatap = cp = ioctlp->inDatap + sizeof(long);
1086 if (cp - ioctlp->inAllocp < ioctlp->inCopied) /* still more data available */
1091 * 1: fast check, don't contact servers.
1092 * 2: local cell only.
1095 /* have cell name, too */
1096 cellp = cm_GetCell(cp, 0);
1097 if (!cellp) return CM_ERROR_NOSUCHCELL;
1099 else cellp = (cm_cell_t *) 0;
1100 if (!cellp && (temp & 2)) {
1101 /* use local cell */
1102 cellp = cm_FindCellByID(1);
1104 if (!(temp & 1)) { /* if not fast, call server checker routine */
1105 /* check down servers */
1106 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS | CM_FLAG_CHECKUPSERVERS,
1110 /* now return the current down server list */
1111 cp = ioctlp->outDatap;
1112 lock_ObtainRead(&cm_serverLock);
1113 for (tsp = cm_allServersp; tsp; tsp=tsp->allNextp) {
1114 if (cellp && tsp->cellp != cellp) continue; /* cell spec'd and wrong */
1115 if ((tsp->flags & CM_SERVERFLAG_DOWN)
1116 && tsp->type == CM_SERVER_FILE) {
1117 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
1121 lock_ReleaseRead(&cm_serverLock);
1123 ioctlp->outDatap = cp;
1127 long cm_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp)
1129 /* we don't print anything superfluous, so we don't support the gag call */
1130 return CM_ERROR_INVAL;
1133 long cm_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
1139 long cm_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp)
1144 cm_SkipIoctlPath(ioctlp);
1146 memcpy(&temp, ioctlp->inDatap, sizeof(temp));
1148 temp = cm_data.buf_nOrigBuffers;
1150 /* temp is in 1K units, convert to # of buffers */
1151 temp = temp / (cm_data.buf_blockSize / 1024);
1154 /* now adjust the cache size */
1155 code = buf_SetNBuffers(temp);
1160 long cm_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
1164 cm_SkipIoctlPath(ioctlp);
1166 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
1170 afsd_ForceTrace(FALSE);
1171 buf_ForceTrace(FALSE);
1175 /* set tracing value to low order bit */
1176 if ((inValue & 1) == 0) {
1177 /* disable tracing */
1178 osi_LogDisable(afsd_logp);
1179 rx_DebugOnOff(FALSE);
1182 /* enable tracing */
1183 osi_LogEnable(afsd_logp);
1184 rx_DebugOnOff(TRUE);
1188 /* see if we're supposed to do a reset, too */
1190 osi_LogReset(afsd_logp);
1193 /* and copy out tracing flag */
1194 inValue = afsd_logp->enabled; /* use as a temp vbl */
1195 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
1196 ioctlp->outDatap += sizeof(long);
1200 long cm_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp)
1202 cm_cacheParms_t parms;
1204 memset(&parms, 0, sizeof(parms));
1206 /* first we get, in 1K units, the cache size */
1207 parms.parms[0] = cm_data.buf_nbuffers * (cm_data.buf_blockSize / 1024);
1209 /* and then the actual # of buffers in use (not in the free list, I guess,
1210 * will be what we do).
1212 parms.parms[1] = (cm_data.buf_nbuffers - buf_CountFreeList()) * (cm_data.buf_blockSize / 1024);
1214 memcpy(ioctlp->outDatap, &parms, sizeof(parms));
1215 ioctlp->outDatap += sizeof(parms);
1220 long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1225 cm_serverRef_t *serverRefp;
1226 cm_server_t *serverp;
1232 cm_SkipIoctlPath(ioctlp);
1234 tp = ioctlp->inDatap;
1236 memcpy((char *)&whichCell, tp, sizeof(long));
1239 /* see if more than one long passed in, ignoring the null pathname (the -1) */
1240 if (ioctlp->inCopied-1 > sizeof(long)) {
1241 memcpy((char *)&magic, tp, sizeof(long));
1244 lock_ObtainRead(&cm_cellLock);
1245 for (tcellp = cm_data.allCellsp; tcellp; tcellp = tcellp->nextp) {
1246 if (whichCell == 0) break;
1249 lock_ReleaseRead(&cm_cellLock);
1253 cp = ioctlp->outDatap;
1255 if (magic == 0x12345678) {
1256 memcpy(cp, (char *)&magic, sizeof(long));
1259 memset(cp, 0, max * sizeof(long));
1261 lock_ObtainRead(&cm_serverLock); /* for going down server list */
1262 /* jaltman - do the reference counts to serverRefp contents need to be increased? */
1263 serverRefp = tcellp->vlServersp;
1264 for (i=0; i<max; i++) {
1265 if (!serverRefp) break;
1266 serverp = serverRefp->server;
1267 memcpy(cp, &serverp->addr.sin_addr.s_addr, sizeof(long));
1269 serverRefp = serverRefp->next;
1271 lock_ReleaseRead(&cm_serverLock);
1272 cp = basep + max * sizeof(afs_int32);
1273 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), tcellp->name);
1274 cp += strlen(tcellp->name)+1;
1275 ioctlp->outDatap = cp;
1281 return CM_ERROR_NOMORETOKENS; /* mapped to EDOM */
1284 extern long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *namep);
1286 long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1288 /* NT cache manager will read cell information from CellServDB each time
1289 * cell is accessed. So, this call is necessary only if list of server for a cell
1290 * changes (or IP addresses of cell servers changes).
1291 * All that needs to be done is to refresh server information for all cells that
1292 * are already loaded.
1294 * cell list will be cm_CellLock and cm_ServerLock will be held for write.
1299 cm_SkipIoctlPath(ioctlp);
1300 lock_ObtainWrite(&cm_cellLock);
1302 for (cp = cm_data.allCellsp; cp; cp=cp->nextp)
1305 lock_ObtainMutex(&cp->mx);
1306 /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
1307 cm_FreeServerList(&cp->vlServersp);
1308 cp->vlServersp = NULL;
1309 code = cm_SearchCellFile(cp->name, cp->name, cm_AddCellProc, cp);
1310 #ifdef AFS_AFSDB_ENV
1312 if (cm_dnsEnabled) {
1314 code = cm_SearchCellByDNS(cp->name, cp->name, &ttl, cm_AddCellProc, cp);
1315 if ( code == 0 ) { /* got cell from DNS */
1316 cp->flags |= CM_CELLFLAG_DNS;
1317 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1318 cp->timeout = time(0) + ttl;
1323 cp->flags &= ~CM_CELLFLAG_DNS;
1325 #endif /* AFS_AFSDB_ENV */
1327 cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
1330 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1331 cm_RandomizeServer(&cp->vlServersp);
1333 lock_ReleaseMutex(&cp->mx);
1336 lock_ReleaseWrite(&cm_cellLock);
1340 long cm_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
1344 if (cm_freelanceEnabled) {
1345 if (cm_GetRootCellName(ioctlp->outDatap))
1346 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "Freelance.Local.Root");
1347 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1348 } else if (cm_data.rootCellp) {
1349 /* return the default cellname to the caller */
1350 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), cm_data.rootCellp->name);
1351 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1353 /* if we don't know our default cell, return failure */
1354 code = CM_ERROR_NOSUCHCELL;
1360 long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp)
1362 long setSysName, foundname = 0;
1363 char *cp, *cp2, inname[MAXSYSNAME], outname[MAXSYSNAME];
1364 int t, count, num = 0;
1365 char **sysnamelist[MAXSYSNAME];
1367 cm_SkipIoctlPath(ioctlp);
1369 memcpy(&setSysName, ioctlp->inDatap, sizeof(long));
1370 ioctlp->inDatap += sizeof(long);
1374 if ( setSysName < 0 || setSysName > MAXNUMSYSNAMES )
1376 cp2 = ioctlp->inDatap;
1377 for ( cp=ioctlp->inDatap, count = 0; count < setSysName; count++ ) {
1378 /* won't go past end of ioctlp->inDatap since maxsysname*num < ioctlp->inDatap length */
1379 t = (int)strlen(cp);
1380 if (t >= MAXSYSNAME || t <= 0)
1382 /* check for names that can shoot us in the foot */
1383 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
1389 /* inname gets first entry in case we're being a translator */
1390 /* (we are never a translator) */
1391 t = (int)strlen(ioctlp->inDatap);
1392 memcpy(inname, ioctlp->inDatap, t + 1);
1393 ioctlp->inDatap += t + 1;
1397 /* Not xlating, so local case */
1399 osi_panic("cm_IoctlSysName: !cm_sysName\n", __FILE__, __LINE__);
1401 if (!setSysName) { /* user just wants the info */
1402 StringCbCopyA(outname, sizeof(outname), cm_sysName);
1403 foundname = cm_sysNameCount;
1404 *sysnamelist = cm_sysNameList;
1406 /* Local guy; only root can change sysname */
1407 /* clear @sys entries from the dnlc, once afs_lookup can
1408 * do lookups of @sys entries and thinks it can trust them */
1409 /* privs ok, store the entry, ... */
1410 StringCbCopyA(cm_sysName, sizeof(cm_sysName), inname);
1411 StringCbCopyA(cm_sysNameList[0], MAXSYSNAME, inname);
1412 if (setSysName > 1) { /* ... or list */
1413 cp = ioctlp->inDatap;
1414 for (count = 1; count < setSysName; ++count) {
1415 if (!cm_sysNameList[count])
1416 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to write\n",
1417 __FILE__, __LINE__);
1418 t = (int)strlen(cp);
1419 StringCbCopyA(cm_sysNameList[count], MAXSYSNAME, cp);
1423 cm_sysNameCount = setSysName;
1427 /* return the sysname to the caller */
1428 cp = ioctlp->outDatap;
1429 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
1430 cp += sizeof(afs_int32); /* skip found flag */
1432 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), outname);
1433 cp += strlen(outname) + 1; /* skip name and terminating null char */
1434 for ( count=1; count < foundname ; ++count) { /* ... or list */
1435 if ( !(*sysnamelist)[count] )
1436 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to read\n",
1437 __FILE__, __LINE__);
1438 t = (int)strlen((*sysnamelist)[count]);
1439 if (t >= MAXSYSNAME)
1440 osi_panic("cm_IoctlSysName: sysname entry garbled\n",
1441 __FILE__, __LINE__);
1442 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), (*sysnamelist)[count]);
1446 ioctlp->outDatap = cp;
1453 long cm_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1458 cm_SkipIoctlPath(ioctlp);
1460 cellp = cm_GetCell(ioctlp->inDatap, 0);
1462 return CM_ERROR_NOSUCHCELL;
1465 lock_ObtainMutex(&cellp->mx);
1466 if (cellp->flags & CM_CELLFLAG_SUID)
1467 temp |= CM_SETCELLFLAG_SUID;
1468 lock_ReleaseMutex(&cellp->mx);
1470 /* now copy out parm */
1471 memcpy(ioctlp->outDatap, &temp, sizeof(long));
1472 ioctlp->outDatap += sizeof(long);
1477 long cm_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1482 cm_SkipIoctlPath(ioctlp);
1484 cellp = cm_GetCell(ioctlp->inDatap + 2*sizeof(long), 0);
1486 return CM_ERROR_NOSUCHCELL;
1488 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
1490 lock_ObtainMutex(&cellp->mx);
1491 if (temp & CM_SETCELLFLAG_SUID)
1492 cellp->flags |= CM_CELLFLAG_SUID;
1494 cellp->flags &= ~CM_CELLFLAG_SUID;
1495 lock_ReleaseMutex(&cellp->mx);
1500 long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1502 cm_SSetPref_t *spin; /* input */
1503 cm_SPref_t *srvin; /* one input component */
1505 int i, vlonly, noServers, type;
1506 struct sockaddr_in tmp;
1507 unsigned short rank;
1509 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1511 spin = (cm_SSetPref_t *)ioctlp->inDatap;
1512 noServers = spin->num_servers;
1513 vlonly = spin->flags;
1515 type = CM_SERVER_VLDB;
1517 type = CM_SERVER_FILE;
1519 for ( i=0; i < noServers; i++)
1521 srvin = &(spin->servers[i]);
1522 rank = srvin->rank + (rand() & 0x000f);
1523 tmp.sin_addr = srvin->host;
1524 tmp.sin_family = AF_INET;
1526 tsp = cm_FindServer(&tmp, type);
1527 if ( tsp ) /* an existing server - ref count increased */
1529 tsp->ipRank = rank; /* no need to protect by mutex*/
1531 if (type == CM_SERVER_FILE)
1533 /* find volumes which might have RO copy
1534 /* on server and change the ordering of
1537 cm_ChangeRankVolume(tsp);
1541 /* set preferences for an existing vlserver */
1542 cm_ChangeRankCellVLServer(tsp);
1545 else /* add a new server without a cell */
1547 tsp = cm_NewServer(&tmp, type, NULL); /* refcount = 1 */
1550 lock_ObtainMutex(&tsp->mx);
1551 tsp->flags |= CM_SERVERFLAG_PREF_SET;
1552 lock_ReleaseMutex(&tsp->mx);
1553 cm_PutServer(tsp); /* decrease refcount */
1558 long cm_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1560 cm_SPrefRequest_t *spin; /* input */
1561 cm_SPrefInfo_t *spout; /* output */
1562 cm_SPref_t *srvout; /* one output component */
1564 int i, vlonly, noServers;
1566 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1568 spin = (cm_SPrefRequest_t *)ioctlp->inDatap;
1569 spout = (cm_SPrefInfo_t *) ioctlp->outDatap;
1570 srvout = spout->servers;
1571 noServers = spin->num_servers;
1572 vlonly = spin->flags & CM_SPREF_VLONLY;
1573 spout->num_servers = 0;
1575 lock_ObtainRead(&cm_serverLock); /* get server lock */
1577 for (tsp=cm_allServersp, i=0; tsp && noServers; tsp=tsp->allNextp,i++){
1578 if (spin->offset > i) {
1579 continue; /* catch up to where we left off */
1582 if ( vlonly && (tsp->type == CM_SERVER_FILE) )
1583 continue; /* ignore fileserver for -vlserver option*/
1584 if ( !vlonly && (tsp->type == CM_SERVER_VLDB) )
1585 continue; /* ignore vlservers */
1587 srvout->host = tsp->addr.sin_addr;
1588 srvout->rank = tsp->ipRank;
1590 spout->num_servers++;
1593 lock_ReleaseRead(&cm_serverLock); /* release server lock */
1595 if ( tsp ) /* we ran out of space in the output buffer */
1596 spout->next_offset = i;
1598 spout->next_offset = 0;
1599 ioctlp->outDatap += sizeof(cm_SPrefInfo_t) +
1600 (spout->num_servers -1 ) * sizeof(cm_SPref_t) ;
1604 long cm_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp)
1606 /* we ignore default asynchrony since we only have one way
1607 * of doing this today.
1612 long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1614 char leaf[LEAF_SIZE];
1628 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1629 if (code) return code;
1631 /* Translate chars for the mount point name */
1632 TranslateExtendedChars(leaf);
1635 * The fs command allows the user to specify partial cell names on NT. These must
1636 * be expanded to the full cell name for mount points so that the mount points will
1637 * work on UNIX clients.
1640 /* Extract the possibly partial cell name */
1641 StringCbCopyA(cell, sizeof(cell), ioctlp->inDatap + 1); /* Skip the mp type character */
1643 if (cp = strchr(cell, ':')) {
1644 /* Extract the volume name */
1646 StringCbCopyA(volume, sizeof(volume), cp + 1);
1648 /* Get the full name for this cell */
1649 code = cm_SearchCellFile(cell, fullCell, 0, 0);
1650 #ifdef AFS_AFSDB_ENV
1651 if (code && cm_dnsEnabled)
1652 code = cm_SearchCellByDNS(cell, fullCell, &ttl, 0, 0);
1655 return CM_ERROR_NOSUCHCELL;
1657 StringCbPrintfA(mpInfo, sizeof(mpInfo), "%c%s:%s", *ioctlp->inDatap, fullCell, volume);
1659 /* No cell name specified */
1660 StringCbCopyA(mpInfo, sizeof(mpInfo), ioctlp->inDatap);
1663 #ifdef AFS_FREELANCE_CLIENT
1664 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1665 /* we are adding the mount point to the root dir., so call
1666 * the freelance code to do the add. */
1667 osi_Log0(afsd_logp,"IoctlCreateMountPoint within Freelance root dir");
1668 code = cm_FreelanceAddMount(leaf, fullCell, volume,
1669 *ioctlp->inDatap == '%', NULL);
1673 /* create the symlink with mode 644. The lack of X bits tells
1674 * us that it is a mount point.
1676 tattr.mask = CM_ATTRMASK_UNIXMODEBITS | CM_ATTRMASK_CLIENTMODTIME;
1677 tattr.unixModeBits = 0644;
1678 tattr.clientModTime = time(NULL);
1680 code = cm_SymLink(dscp, leaf, mpInfo, 0, &tattr, userp, &req);
1681 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1682 smb_NotifyChange(FILE_ACTION_ADDED,
1683 FILE_NOTIFY_CHANGE_DIR_NAME,
1684 dscp, leaf, NULL, TRUE);
1686 cm_ReleaseSCache(dscp);
1690 long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1692 char leaf[LEAF_SIZE];
1701 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1702 if (code) return code;
1704 /* Translate chars for the link name */
1705 TranslateExtendedChars(leaf);
1707 /* Translate chars for the linked to name */
1708 TranslateExtendedChars(ioctlp->inDatap);
1710 cp = ioctlp->inDatap; /* contents of link */
1712 #ifdef AFS_FREELANCE_CLIENT
1713 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1714 /* we are adding the symlink to the root dir., so call
1715 * the freelance code to do the add. */
1716 if (cp[0] == cp[1] && cp[1] == '\\' &&
1717 !_strnicmp(cm_NetbiosName,cp+2,strlen(cm_NetbiosName)))
1719 /* skip \\AFS\ or \\AFS\all\ */
1721 p = cp + 2 + strlen(cm_NetbiosName) + 1;
1722 if ( !_strnicmp("all", p, 3) )
1726 osi_Log0(afsd_logp,"IoctlCreateSymlink within Freelance root dir");
1727 code = cm_FreelanceAddSymlink(leaf, cp, NULL);
1732 /* Create symlink with mode 0755. */
1733 tattr.mask = CM_ATTRMASK_UNIXMODEBITS;
1734 tattr.unixModeBits = 0755;
1736 code = cm_SymLink(dscp, leaf, cp, 0, &tattr, userp, &req);
1737 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1738 smb_NotifyChange(FILE_ACTION_ADDED,
1739 FILE_NOTIFY_CHANGE_FILE_NAME
1740 | FILE_NOTIFY_CHANGE_DIR_NAME,
1741 dscp, leaf, NULL, TRUE);
1743 cm_ReleaseSCache(dscp);
1749 long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1756 cm_scache_t *newRootScp;
1761 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1762 if (code) return code;
1764 cp = ioctlp->inDatap;
1766 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1767 cm_ReleaseSCache(dscp);
1768 if (code) return code;
1770 /* Check that it's a real symlink */
1771 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1772 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1773 scp->fileType != CM_SCACHETYPE_INVALID) {
1774 cm_ReleaseSCache(scp);
1775 return CM_ERROR_INVAL;
1778 code = cm_AssembleLink(scp, "", &newRootScp, &spacep, userp, &req);
1779 cm_ReleaseSCache(scp);
1781 cp = ioctlp->outDatap;
1782 if (newRootScp != NULL) {
1783 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), cm_mountRoot);
1784 StringCbCatA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), "/");
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);
1794 } else if (code == CM_ERROR_PATH_NOT_COVERED &&
1795 scp->fileType == CM_SCACHETYPE_DFSLINK ||
1796 code == CM_ERROR_NOSUCHPATH &&
1797 scp->fileType == CM_SCACHETYPE_INVALID) {
1798 cp = ioctlp->outDatap;
1799 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), spacep->data);
1800 cp += strlen(cp) + 1;
1801 ioctlp->outDatap = cp;
1802 cm_FreeSpace(spacep);
1803 if (newRootScp != NULL)
1804 cm_ReleaseSCache(newRootScp);
1811 long cm_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1812 {/*CHECK FOR VALID SYMLINK*/
1821 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1822 if (code) return code;
1824 cp = ioctlp->inDatap;
1825 osi_LogEvent("cm_IoctlListlink",NULL," name[%s]",cp);
1827 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1828 cm_ReleaseSCache(dscp);
1829 if (code) return code;
1831 /* Check that it's a real symlink */
1832 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1833 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1834 scp->fileType != CM_SCACHETYPE_INVALID)
1835 code = CM_ERROR_INVAL;
1836 cm_ReleaseSCache(scp);
1840 long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1850 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1851 if (code) return code;
1853 cp = ioctlp->inDatap;
1855 #ifdef AFS_FREELANCE_CLIENT
1856 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1857 /* we are adding the mount point to the root dir., so call
1858 * the freelance code to do the add. */
1859 osi_Log0(afsd_logp,"IoctlDeletelink from Freelance root dir");
1860 code = cm_FreelanceRemoveSymlink(cp);
1865 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1867 /* if something went wrong, bail out now */
1872 lock_ObtainMutex(&scp->mx);
1873 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1874 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1876 lock_ReleaseMutex(&scp->mx);
1877 cm_ReleaseSCache(scp);
1881 /* now check that this is a real symlink */
1882 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1883 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1884 scp->fileType != CM_SCACHETYPE_INVALID) {
1885 lock_ReleaseMutex(&scp->mx);
1886 cm_ReleaseSCache(scp);
1887 code = CM_ERROR_INVAL;
1891 /* time to make the RPC, so drop the lock */
1892 lock_ReleaseMutex(&scp->mx);
1893 cm_ReleaseSCache(scp);
1895 /* easier to do it this way */
1896 code = cm_Unlink(dscp, cp, userp, &req);
1897 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1898 smb_NotifyChange(FILE_ACTION_REMOVED,
1899 FILE_NOTIFY_CHANGE_FILE_NAME
1900 | FILE_NOTIFY_CHANGE_DIR_NAME,
1901 dscp, cp, NULL, TRUE);
1904 lock_ObtainMutex(&scp->mx);
1905 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1906 lock_ReleaseMutex(&scp->mx);
1909 cm_ReleaseSCache(dscp);
1914 long cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid)
1919 static struct afsconf_cell info;
1920 struct rx_connection *serverconns[MAXSERVERS];
1921 struct rx_securityClass *sc[3];
1922 afs_int32 scIndex = 2; /* authenticated - we have a token */
1923 struct ubik_client *pruclient = NULL;
1924 struct afsconf_dir *tdir;
1928 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
1929 code = afsconf_GetCellInfo(tdir, ucellp->cellp->name, "afsprot", &info);
1930 afsconf_Close(tdir);
1936 /* we have the token that was given to us in the settoken
1937 * call. we just have to use it.
1939 scIndex = 2; /* kerberos ticket */
1940 sc[2] = rxkad_NewClientSecurityObject(rxkad_clear, &ucellp->sessionKey,
1941 ucellp->kvno, ucellp->ticketLen,
1944 memset(serverconns, 0, sizeof(serverconns)); /* terminate list!!! */
1945 for (i = 0; i < info.numServers; i++)
1947 rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
1948 info.hostAddr[i].sin_port, PRSRV, sc[scIndex],
1951 code = ubik_ClientInit(serverconns, &pruclient);
1956 code = rxs_Release(sc[scIndex]);
1958 lids.idlist_len = 0;
1959 lids.idlist_val = 0;
1960 lnames.namelist_len = 1;
1961 lnames.namelist_val = (prname *) malloc(PR_MAXNAMELEN);
1962 strncpy(lnames.namelist_val[0], uname, PR_MAXNAMELEN);
1963 lnames.namelist_val[0][PR_MAXNAMELEN-1] = '\0';
1964 for ( p=lnames.namelist_val[0], r=NULL; *p; p++ ) {
1970 if (r && !stricmp(r+1,ucellp->cellp->name))
1973 code = ubik_Call(PR_NameToID, pruclient, 0, &lnames, &lids);
1974 if (lids.idlist_val) {
1975 *uid = *lids.idlist_val;
1976 free(lids.idlist_val);
1978 if (lnames.namelist_val)
1979 free(lnames.namelist_val);
1982 ubik_ClientDestroy(pruclient);
1988 #endif /* QUERY_AFSID */
1990 long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
1997 struct ClearToken ct;
2007 int release_userp = 0;
2010 saveDataPtr = ioctlp->inDatap;
2012 cm_SkipIoctlPath(ioctlp);
2014 tp = ioctlp->inDatap;
2017 memcpy(&ticketLen, tp, sizeof(ticketLen));
2018 tp += sizeof(ticketLen);
2019 if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN)
2020 return CM_ERROR_INVAL;
2022 /* remember ticket and skip over it for now */
2026 /* clear token size */
2027 memcpy(&ctSize, tp, sizeof(ctSize));
2028 tp += sizeof(ctSize);
2029 if (ctSize != sizeof(struct ClearToken))
2030 return CM_ERROR_INVAL;
2033 memcpy(&ct, tp, ctSize);
2035 if (ct.AuthHandle == -1)
2036 ct.AuthHandle = 999; /* more rxvab compat stuff */
2038 /* more stuff, if any */
2039 if (ioctlp->inCopied > tp - saveDataPtr) {
2040 /* flags: logon flag */
2041 memcpy(&flags, tp, sizeof(int));
2045 cellp = cm_GetCell(tp, CM_FLAG_CREATE);
2046 if (!cellp) return CM_ERROR_NOSUCHCELL;
2047 tp += strlen(tp) + 1;
2051 tp += strlen(tp) + 1;
2053 #ifndef AFSIFS /* no SMB username, so we cannot logon based on this */
2054 if (flags & PIOCTL_LOGON) {
2055 /* SMB user name with which to associate tokens */
2057 osi_Log2(smb_logp,"cm_IoctlSetToken for user [%s] smbname [%s]",
2058 osi_LogSaveString(smb_logp,uname), osi_LogSaveString(smb_logp,smbname));
2059 fprintf(stderr, "SMB name = %s\n", smbname);
2060 tp += strlen(tp) + 1;
2062 osi_Log1(smb_logp,"cm_IoctlSetToken for user [%s]",
2063 osi_LogSaveString(smb_logp, uname));
2068 memcpy(&uuid, tp, sizeof(uuid));
2069 if (!cm_FindTokenEvent(uuid, sessionKey))
2070 return CM_ERROR_INVAL;
2072 cellp = cm_data.rootCellp;
2073 osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
2077 if (flags & PIOCTL_LOGON) {
2078 userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname,
2079 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
2084 /* store the token */
2085 lock_ObtainMutex(&userp->mx);
2086 ucellp = cm_GetUCell(userp, cellp);
2087 osi_Log1(smb_logp,"cm_IoctlSetToken ucellp %lx", ucellp);
2088 ucellp->ticketLen = ticketLen;
2089 if (ucellp->ticketp)
2090 free(ucellp->ticketp); /* Discard old token if any */
2091 ucellp->ticketp = malloc(ticketLen);
2092 memcpy(ucellp->ticketp, ticket, ticketLen);
2094 * Get the session key from the RPC, rather than from the pioctl.
2097 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
2099 memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
2100 ucellp->kvno = ct.AuthHandle;
2101 ucellp->expirationTime = ct.EndTimestamp;
2104 ucellp->uid = ANONYMOUSID;
2107 StringCbCopyA(ucellp->userName, MAXKTCNAMELEN, uname);
2109 cm_UsernameToId(uname, ucellp, &ucellp->uid);
2112 ucellp->flags |= CM_UCELLFLAG_RXKAD;
2113 lock_ReleaseMutex(&userp->mx);
2115 if (flags & PIOCTL_LOGON) {
2116 ioctlp->flags |= SMB_IOCTLFLAG_LOGON;
2119 cm_ResetACLCache(userp);
2122 cm_ReleaseUser(userp);
2127 long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
2133 struct ClearToken ct;
2135 cm_SkipIoctlPath(ioctlp);
2137 tp = ioctlp->inDatap;
2138 cp = ioctlp->outDatap;
2141 memcpy(&iterator, tp, sizeof(iterator));
2142 tp += sizeof(iterator);
2144 lock_ObtainMutex(&userp->mx);
2146 /* look for token */
2147 for (;;iterator++) {
2148 ucellp = cm_FindUCell(userp, iterator);
2150 lock_ReleaseMutex(&userp->mx);
2151 return CM_ERROR_NOMORETOKENS;
2153 if (ucellp->flags & CM_UCELLFLAG_RXKAD)
2158 temp = ucellp->iterator + 1;
2159 memcpy(cp, &temp, sizeof(temp));
2163 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2164 cp += sizeof(ucellp->ticketLen);
2167 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2168 cp += ucellp->ticketLen;
2170 /* clear token size */
2172 memcpy(cp, &temp, sizeof(temp));
2176 ct.AuthHandle = ucellp->kvno;
2178 * Don't give out a real session key here
2181 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2183 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2184 ct.ViceId = 37; /* XXX */
2185 ct.BeginTimestamp = 0; /* XXX */
2186 ct.EndTimestamp = ucellp->expirationTime;
2187 memcpy(cp, &ct, sizeof(ct));
2190 /* Primary flag (unused) */
2192 memcpy(cp, &temp, sizeof(temp));
2196 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->cellp->name);
2197 cp += strlen(cp) + 1;
2200 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->userName);
2201 cp += strlen(cp) + 1;
2203 ioctlp->outDatap = cp;
2205 lock_ReleaseMutex(&userp->mx);
2210 long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2216 struct ClearToken ct;
2219 cm_SkipIoctlPath(ioctlp);
2221 tp = ioctlp->inDatap;
2223 cp = ioctlp->outDatap;
2225 /* cell name is right here */
2226 cellp = cm_GetCell(tp, 0);
2228 return CM_ERROR_NOSUCHCELL;
2229 tp += strlen(tp) + 1;
2232 memcpy(&uuid, tp, sizeof(uuid));
2234 lock_ObtainMutex(&userp->mx);
2236 ucellp = cm_GetUCell(userp, cellp);
2237 if (!ucellp || !(ucellp->flags & CM_UCELLFLAG_RXKAD)) {
2238 lock_ReleaseMutex(&userp->mx);
2239 return CM_ERROR_NOMORETOKENS;
2243 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2244 cp += sizeof(ucellp->ticketLen);
2247 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2248 cp += ucellp->ticketLen;
2250 /* clear token size */
2252 memcpy(cp, &temp, sizeof(temp));
2256 ct.AuthHandle = ucellp->kvno;
2258 * Don't give out a real session key here
2261 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2263 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2264 ct.ViceId = 37; /* XXX */
2265 ct.BeginTimestamp = 0; /* XXX */
2266 ct.EndTimestamp = ucellp->expirationTime;
2267 memcpy(cp, &ct, sizeof(ct));
2270 /* Primary flag (unused) */
2272 memcpy(cp, &temp, sizeof(temp));
2276 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->cellp->name);
2277 cp += strlen(cp) + 1;
2280 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->userName);
2281 cp += strlen(cp) + 1;
2283 ioctlp->outDatap = cp;
2285 lock_ReleaseMutex(&userp->mx);
2287 cm_RegisterNewTokenEvent(uuid, ucellp->sessionKey.data);
2292 long cm_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2298 cm_SkipIoctlPath(ioctlp);
2300 cp = ioctlp->outDatap;
2302 /* cell name is right here */
2303 cellp = cm_GetCell(ioctlp->inDatap, 0);
2304 if (!cellp) return CM_ERROR_NOSUCHCELL;
2306 lock_ObtainMutex(&userp->mx);
2308 ucellp = cm_GetUCell(userp, cellp);
2310 lock_ReleaseMutex(&userp->mx);
2311 return CM_ERROR_NOMORETOKENS;
2314 osi_Log1(smb_logp,"cm_IoctlDelToken ucellp %lx", ucellp);
2316 if (ucellp->ticketp) {
2317 free(ucellp->ticketp);
2318 ucellp->ticketp = NULL;
2320 ucellp->ticketLen = 0;
2321 memset(ucellp->sessionKey.data, 0, 8);
2323 ucellp->expirationTime = 0;
2324 ucellp->userName[0] = '\0';
2325 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2328 lock_ReleaseMutex(&userp->mx);
2330 cm_ResetACLCache(userp);
2335 long cm_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2339 lock_ObtainMutex(&userp->mx);
2341 for (ucellp = userp->cellInfop; ucellp; ucellp = ucellp->nextp) {
2342 osi_Log1(smb_logp,"cm_IoctlDelAllToken ucellp %lx", ucellp);
2344 if (ucellp->ticketp) {
2345 free(ucellp->ticketp);
2346 ucellp->ticketp = NULL;
2348 ucellp->ticketLen = 0;
2349 memset(ucellp->sessionKey.data, 0, 8);
2351 ucellp->expirationTime = 0;
2352 ucellp->userName[0] = '\0';
2353 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2357 lock_ReleaseMutex(&userp->mx);
2359 cm_ResetACLCache(userp);
2364 long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
2366 char afspath[MAX_PATH];
2368 int nextAutoSubmount;
2370 DWORD dwType, dwSize;
2375 cm_SkipIoctlPath(ioctlp);
2377 /* Serialize this one, to prevent simultaneous mods
2380 lock_ObtainMutex(&cm_Afsdsbmt_Lock);
2382 /* Parse the input parameters--first the required afs path,
2383 * then the requested submount name (which may be "").
2385 cm_NormalizeAfsPath (afspath, sizeof(afspath), ioctlp->inDatap);
2386 submountreqp = ioctlp->inDatap + (strlen(ioctlp->inDatap)+1);
2388 /* If the caller supplied a suggested submount name, see if
2389 * that submount name is in use... if so, the submount's path
2390 * has to match our path.
2393 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
2394 AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
2397 REG_OPTION_NON_VOLATILE,
2398 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
2403 if (submountreqp && *submountreqp) {
2404 char submountPathNormalized[MAX_PATH];
2405 char submountPath[MAX_PATH];
2407 dwSize = sizeof(submountPath);
2408 status = RegQueryValueEx( hkSubmounts, submountreqp, 0,
2409 &dwType, submountPath, &dwSize);
2411 if (status != ERROR_SUCCESS) {
2413 /* The suggested submount name isn't in use now--
2414 * so we can safely map the requested submount name
2415 * to the supplied path. Remember not to write the
2416 * leading "/afs" when writing out the submount.
2418 RegSetValueEx( hkSubmounts, submountreqp, 0,
2420 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2421 &afspath[strlen(cm_mountRoot)]:"/",
2422 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2423 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2425 RegCloseKey( hkSubmounts );
2426 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountreqp);
2427 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2428 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2432 /* The suggested submount name is already in use--if the
2433 * supplied path matches the submount's path, we can still
2434 * use the suggested submount name.
2436 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2437 if (!strcmp (submountPathNormalized, afspath)) {
2438 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountreqp);
2439 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2440 RegCloseKey( hkSubmounts );
2441 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2446 RegQueryInfoKey( hkSubmounts,
2448 NULL, /* lpcClass */
2449 NULL, /* lpReserved */
2450 NULL, /* lpcSubKeys */
2451 NULL, /* lpcMaxSubKeyLen */
2452 NULL, /* lpcMaxClassLen */
2453 &dwSubmounts, /* lpcValues */
2454 NULL, /* lpcMaxValueNameLen */
2455 NULL, /* lpcMaxValueLen */
2456 NULL, /* lpcbSecurityDescriptor */
2457 NULL /* lpftLastWriteTime */
2461 /* Having obtained a list of all available submounts, start
2462 * searching that list for a path which matches the requested
2463 * AFS path. We'll also keep track of the highest "auto15"/"auto47"
2464 * submount, in case we need to add a new one later.
2467 nextAutoSubmount = 1;
2469 for ( dwIndex = 0; dwIndex < dwSubmounts; dwIndex ++ ) {
2470 char submountPathNormalized[MAX_PATH];
2471 char submountPath[MAX_PATH] = "";
2472 DWORD submountPathLen = sizeof(submountPath);
2473 char submountName[MAX_PATH];
2474 DWORD submountNameLen = sizeof(submountName);
2477 RegEnumValue( hkSubmounts, dwIndex, submountName, &submountNameLen, NULL,
2478 &dwType, submountPath, &submountPathLen);
2479 if (dwType == REG_EXPAND_SZ) {
2481 StringCbCopyA(buf, MAX_PATH, submountPath);
2482 submountPathLen = ExpandEnvironmentStrings(buf, submountPath, MAX_PATH);
2483 if (submountPathLen > MAX_PATH)
2487 /* If this is an Auto### submount, remember its ### value */
2488 if ((!strnicmp (submountName, "auto", 4)) &&
2489 (isdigit (submountName[strlen("auto")]))) {
2490 int thisAutoSubmount;
2491 thisAutoSubmount = atoi (&submountName[strlen("auto")]);
2492 nextAutoSubmount = max (nextAutoSubmount,
2493 thisAutoSubmount+1);
2496 if ((submountPathLen == 0) ||
2497 (submountPathLen == sizeof(submountPath) - 1)) {
2501 /* See if the path for this submount matches the path
2502 * that our caller specified. If so, we can return
2505 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2506 if (!strcmp (submountPathNormalized, afspath)) {
2507 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountName);
2508 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2509 RegCloseKey(hkSubmounts);
2510 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2516 /* We've been through the entire list of existing submounts, and
2517 * didn't find any which matched the specified path. So, we'll
2518 * just have to add one. Remember not to write the leading "/afs"
2519 * when writing out the submount.
2522 StringCbPrintfA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "auto%ld", nextAutoSubmount);
2524 RegSetValueEx( hkSubmounts,
2528 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2529 &afspath[strlen(cm_mountRoot)]:"/",
2530 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2531 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2533 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2534 RegCloseKey(hkSubmounts);
2535 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2539 long cm_IoctlGetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2541 memcpy(ioctlp->outDatap, &cryptall, sizeof(cryptall));
2542 ioctlp->outDatap += sizeof(cryptall);
2547 long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2549 afs_int32 c = cryptall;
2551 cm_SkipIoctlPath(ioctlp);
2553 memcpy(&cryptall, ioctlp->inDatap, sizeof(cryptall));
2555 if (c != cryptall) {
2557 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_ON);
2559 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_OFF);
2564 long cm_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp)
2569 cm_SkipIoctlPath(ioctlp);
2571 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2572 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2575 if (flags & AFSCALL_RXSTATS_ENABLE) {
2576 rx_enableProcessRPCStats();
2578 if (flags & AFSCALL_RXSTATS_DISABLE) {
2579 rx_disableProcessRPCStats();
2581 if (flags & AFSCALL_RXSTATS_CLEAR) {
2582 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
2587 long cm_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp)
2592 cm_SkipIoctlPath(ioctlp);
2594 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2595 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2598 if (flags & AFSCALL_RXSTATS_ENABLE) {
2599 rx_enablePeerRPCStats();
2601 if (flags & AFSCALL_RXSTATS_DISABLE) {
2602 rx_disablePeerRPCStats();
2604 if (flags & AFSCALL_RXSTATS_CLEAR) {
2605 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
2610 long cm_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp)
2612 smb_user_t *uidp = ioctlp->uidp;
2614 if (uidp && uidp->unp) {
2615 memcpy(ioctlp->outDatap, uidp->unp->name, strlen(uidp->unp->name));
2616 ioctlp->outDatap += strlen(uidp->unp->name);
2622 long cm_IoctlUUIDControl(struct smb_ioctl * ioctlp, struct cm_user *userp)
2627 memcpy(&cmd, ioctlp->inDatap, sizeof(long));
2629 if (cmd) { /* generate a new UUID */
2630 UuidCreate((UUID *) &uuid);
2631 cm_data.Uuid = uuid;
2632 cm_ForceNewConnectionsAllServers();
2635 memcpy(ioctlp->outDatap, &cm_data.Uuid, sizeof(cm_data.Uuid));
2636 ioctlp->outDatap += sizeof(cm_data.Uuid);
2642 * functions to dump contents of various structures.
2643 * In debug build (linked with crt debug library) will dump allocated but not freed memory
2645 extern int cm_DumpSCache(FILE *outputFile, char *cookie, int lock);
2646 extern int cm_DumpBufHashTable(FILE *outputFile, char *cookie, int lock);
2647 extern int smb_DumpVCP(FILE *outputFile, char *cookie, int lock);
2649 long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
2653 char logfileName[MAX_PATH+1];
2658 static _CrtMemState memstate;
2661 cm_SkipIoctlPath(ioctlp);
2662 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
2664 dwSize = GetEnvironmentVariable("TEMP", logfileName, sizeof(logfileName));
2665 if ( dwSize == 0 || dwSize > sizeof(logfileName) )
2667 GetWindowsDirectory(logfileName, sizeof(logfileName));
2669 strncat(logfileName, "\\afsd_alloc.log", sizeof(logfileName));
2671 hLogFile = CreateFile(logfileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2677 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2678 ioctlp->outDatap += sizeof(long);
2683 SetFilePointer(hLogFile, 0, NULL, FILE_END);
2685 cookie = inValue ? "b" : "e";
2691 _CrtMemCheckpoint(&memstate);
2695 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2696 _CrtSetReportFile(_CRT_WARN, hLogFile);
2697 _CrtMemDumpAllObjectsSince(&memstate);
2701 /* dump all interesting data */
2702 cm_DumpSCache(hLogFile, cookie, 1);
2703 cm_DumpBufHashTable(hLogFile, cookie, 1);
2704 smb_DumpVCP(hLogFile, cookie, 1);
2706 CloseHandle(hLogFile);
2708 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2709 ioctlp->outDatap += sizeof(long);