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);
269 cm_ReleaseSCache(substRootp);
271 osi_Log1(afsd_logp,"cm_ParseIoctlPath [2] code 0x%x", code);
275 /* otherwise, treat the name as a cellname mounted off the afs root.
276 * This requires that we reconstruct the shareName string with
277 * leading and trailing slashes.
279 p = relativePath + 2 + strlen(cm_NetbiosName) + 1;
280 if ( !_strnicmp("all", p, 3) )
284 for (i = 1; *p && *p != '\\'; i++,p++ ) {
287 p++; /* skip past trailing slash */
288 shareName[i++] = '/'; /* add trailing slash */
289 shareName[i] = 0; /* terminate string */
292 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
293 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
294 userp, shareName, reqp, &substRootp);
296 osi_Log1(afsd_logp,"cm_ParseIoctlPath [3] code 0x%x", code);
300 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
301 userp, NULL, reqp, scpp);
303 cm_ReleaseSCache(substRootp);
304 osi_Log1(afsd_logp,"cm_ParseIoctlPath code [4] 0x%x", code);
309 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
310 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
311 userp, ioctlp->tidPathp, reqp, &substRootp);
313 osi_Log1(afsd_logp,"cm_ParseIoctlPath [6] code 0x%x", code);
317 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
318 userp, NULL, reqp, scpp);
320 cm_ReleaseSCache(substRootp);
321 osi_Log1(afsd_logp,"cm_ParseIoctlPath [7] code 0x%x", code);
327 /* # of bytes of path */
328 code = (long)strlen(ioctlp->inDatap) + 1;
329 ioctlp->inDatap += code;
331 /* This is usually nothing, but for StatMountPoint it is the file name. */
332 TranslateExtendedChars(ioctlp->inDatap);
335 cm_ReleaseSCache(substRootp);
337 /* and return success */
338 osi_Log1(afsd_logp,"cm_ParseIoctlPath [8] code 0x%x", code);
342 void cm_SkipIoctlPath(smb_ioctl_t *ioctlp)
346 temp = (long) strlen(ioctlp->inDatap) + 1;
347 ioctlp->inDatap += temp;
351 /* format the specified path to look like "/afs/<cellname>/usr", by
352 * adding "/afs" (if necessary) in front, changing any \'s to /'s, and
353 * removing any trailing "/"'s. One weirdo caveat: "/afs" will be
354 * intentionally returned as "/afs/"--this makes submount manipulation
355 * easier (because we can always jump past the initial "/afs" to find
356 * the AFS path that should be written into afsdsbmt.ini).
358 void cm_NormalizeAfsPath(char *outpathp, long outlen, char *inpathp)
361 char bslash_mountRoot[256];
363 strncpy(bslash_mountRoot, cm_mountRoot, sizeof(bslash_mountRoot) - 1);
364 bslash_mountRoot[0] = '\\';
366 if (!strnicmp (inpathp, cm_mountRoot, strlen(cm_mountRoot)))
367 StringCbCopy(outpathp, outlen, inpathp);
368 else if (!strnicmp (inpathp, bslash_mountRoot, strlen(bslash_mountRoot)))
369 StringCbCopy(outpathp, outlen, inpathp);
370 else if ((inpathp[0] == '/') || (inpathp[0] == '\\'))
371 StringCbPrintfA(outpathp, outlen, "%s%s", cm_mountRoot, inpathp);
372 else // inpathp looks like "<cell>/usr"
373 StringCbPrintfA(outpathp, outlen, "%s/%s", cm_mountRoot, inpathp);
375 for (cp = outpathp; *cp != 0; ++cp) {
380 if (strlen(outpathp) && (outpathp[strlen(outpathp)-1] == '/')) {
381 outpathp[strlen(outpathp)-1] = 0;
384 if (!strcmpi (outpathp, cm_mountRoot)) {
385 StringCbCopy(outpathp, outlen, cm_mountRoot);
389 #define LEAF_SIZE 256
390 /* parse the passed-in file name and do a namei on its parent. If we fail,
391 * return an error code, otherwise return the vnode located in *scpp.
393 long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
394 cm_scache_t **scpp, char *leafp)
399 cm_scache_t *substRootp = NULL;
401 StringCbCopyA(tbuffer, sizeof(tbuffer), ioctlp->inDatap);
402 tp = strrchr(tbuffer, '\\');
403 jp = strrchr(tbuffer, '/');
406 else if (jp && (tp - tbuffer) < (jp - tbuffer))
409 StringCbCopyA(tbuffer, sizeof(tbuffer), "\\");
411 StringCbCopyA(leafp, LEAF_SIZE, ioctlp->inDatap);
416 StringCbCopyA(leafp, LEAF_SIZE, tp+1);
419 if (tbuffer[0] == tbuffer[1] &&
420 tbuffer[1] == '\\' &&
421 !_strnicmp(cm_NetbiosName,tbuffer+2,strlen(cm_NetbiosName)))
427 /* We may have found a UNC path.
428 * If the first component is the NetbiosName,
429 * then throw out the second component (the submount)
430 * since it had better expand into the value of ioctl->tidPathp
433 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
434 if ( !_strnicmp("all", p, 3) )
437 for (i = 0; *p && *p != '\\'; i++,p++ ) {
440 p++; /* skip past trailing slash */
441 shareName[i] = 0; /* terminate string */
443 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
445 /* we found a sharename, therefore use the resulting path */
446 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
447 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
448 userp, sharePath, reqp, &substRootp);
450 if (code) return code;
452 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
453 userp, NULL, reqp, scpp);
454 cm_ReleaseSCache(substRootp);
455 if (code) return code;
457 /* otherwise, treat the name as a cellname mounted off the afs root.
458 * This requires that we reconstruct the shareName string with
459 * leading and trailing slashes.
461 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
462 if ( !_strnicmp("all", p, 3) )
466 for (i = 1; *p && *p != '\\'; i++,p++ ) {
469 p++; /* skip past trailing slash */
470 shareName[i++] = '/'; /* add trailing slash */
471 shareName[i] = 0; /* terminate string */
473 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
474 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
475 userp, shareName, reqp, &substRootp);
476 if (code) return code;
478 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
479 userp, NULL, reqp, scpp);
480 cm_ReleaseSCache(substRootp);
481 if (code) return code;
484 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
485 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
486 userp, ioctlp->tidPathp, reqp, &substRootp);
487 if (code) return code;
489 code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
490 userp, NULL, reqp, scpp);
491 cm_ReleaseSCache(substRootp);
492 if (code) return code;
495 /* # of bytes of path */
496 code = (long)strlen(ioctlp->inDatap) + 1;
497 ioctlp->inDatap += code;
499 /* and return success */
503 long cm_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp)
508 AFSFetchStatus fileStatus;
514 struct rx_connection * callp;
518 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
519 if (code) return code;
521 /* now make the get acl call */
522 fid.Volume = scp->fid.volume;
523 fid.Vnode = scp->fid.vnode;
524 fid.Unique = scp->fid.unique;
526 acl.AFSOpaque_val = ioctlp->outDatap;
527 acl.AFSOpaque_len = 0;
528 code = cm_Conn(&scp->fid, userp, &req, &connp);
531 callp = cm_GetRxConn(connp);
532 code = RXAFS_FetchACL(callp, &fid, &acl, &fileStatus, &volSync);
533 rx_PutConnection(callp);
535 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
536 code = cm_MapRPCError(code, &req);
537 cm_ReleaseSCache(scp);
539 if (code) return code;
541 /* skip over return data */
542 tlen = (int)strlen(ioctlp->outDatap) + 1;
543 ioctlp->outDatap += tlen;
545 /* and return success */
549 long cm_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp)
558 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
559 if (code) return code;
561 #ifdef AFS_FREELANCE_CLIENT
562 if ( cm_freelanceEnabled &&
563 scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
564 scp->fid.volume==AFS_FAKE_ROOT_VOL_ID &&
565 scp->fid.vnode==0x1 && scp->fid.unique==0x1 ) {
566 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "Freelance.Local.Root");
567 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
570 #endif /* AFS_FREELANCE_CLIENT */
572 cellp = cm_FindCellByID(scp->fid.cell);
574 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), cellp->name);
575 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
579 code = CM_ERROR_NOSUCHCELL;
582 cm_ReleaseSCache(scp);
586 long cm_IoctlSetACL(struct smb_ioctl *ioctlp, struct cm_user *userp)
591 AFSFetchStatus fileStatus;
596 struct rx_connection * callp;
600 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
601 if (code) return code;
603 /* now make the get acl call */
604 fid.Volume = scp->fid.volume;
605 fid.Vnode = scp->fid.vnode;
606 fid.Unique = scp->fid.unique;
608 acl.AFSOpaque_val = ioctlp->inDatap;
609 acl.AFSOpaque_len = (u_int)strlen(ioctlp->inDatap)+1;
610 code = cm_Conn(&scp->fid, userp, &req, &connp);
613 callp = cm_GetRxConn(connp);
614 code = RXAFS_StoreACL(callp, &fid, &acl, &fileStatus, &volSync);
615 rx_PutConnection(callp);
617 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
618 code = cm_MapRPCError(code, &req);
620 /* invalidate cache info, since we just trashed the ACL cache */
621 lock_ObtainMutex(&scp->mx);
622 cm_DiscardSCache(scp);
623 lock_ReleaseMutex(&scp->mx);
625 cm_ReleaseSCache(scp);
632 long cm_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
641 lock_ObtainWrite(&cm_scacheLock);
642 for (i=0; i<cm_data.hashTableSize; i++) {
643 for (scp = cm_data.hashTablep[i]; scp; scp = scp->nextp) {
644 cm_HoldSCacheNoLock(scp);
645 lock_ReleaseWrite(&cm_scacheLock);
647 /* now flush the file */
648 code = cm_FlushFile(scp, userp, &req);
649 lock_ObtainWrite(&cm_scacheLock);
650 cm_ReleaseSCacheNoLock(scp);
653 lock_ReleaseWrite(&cm_scacheLock);
658 long cm_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp)
662 unsigned long volume;
668 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
669 if (code) return code;
671 volume = scp->fid.volume;
672 cell = scp->fid.cell;
673 cm_ReleaseSCache(scp);
675 code = cm_FlushVolume(userp, &req, cell, volume);
680 long cm_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp)
688 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
689 if (code) return code;
691 cm_FlushFile(scp, userp, &req);
692 cm_ReleaseSCache(scp);
697 long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
701 char offLineMsg[256];
705 AFSFetchVolumeStatus volStat;
706 AFSStoreVolumeStatus storeStat;
711 struct rx_connection * callp;
715 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
716 if (code) return code;
718 cellp = cm_FindCellByID(scp->fid.cell);
721 if (scp->flags & CM_SCACHEFLAG_RO) {
722 cm_ReleaseSCache(scp);
723 return CM_ERROR_READONLY;
726 code = cm_GetVolumeByID(cellp, scp->fid.volume, userp, &req, &tvp);
728 cm_ReleaseSCache(scp);
732 /* Copy the junk out, using cp as a roving pointer. */
733 cp = ioctlp->inDatap;
734 memcpy((char *)&volStat, cp, sizeof(AFSFetchVolumeStatus));
735 cp += sizeof(AFSFetchVolumeStatus);
736 StringCbCopyA(volName, sizeof(volName), cp);
737 cp += strlen(volName)+1;
738 StringCbCopyA(offLineMsg, sizeof(offLineMsg), cp);
739 cp += strlen(offLineMsg)+1;
740 StringCbCopyA(motd, sizeof(motd), cp);
742 if (volStat.MinQuota != -1) {
743 storeStat.MinQuota = volStat.MinQuota;
744 storeStat.Mask |= AFS_SETMINQUOTA;
746 if (volStat.MaxQuota != -1) {
747 storeStat.MaxQuota = volStat.MaxQuota;
748 storeStat.Mask |= AFS_SETMAXQUOTA;
752 code = cm_Conn(&scp->fid, userp, &req, &tcp);
755 callp = cm_GetRxConn(tcp);
756 code = RXAFS_SetVolumeStatus(callp, scp->fid.volume,
757 &storeStat, volName, offLineMsg, motd);
758 rx_PutConnection(callp);
760 } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
761 code = cm_MapRPCError(code, &req);
763 /* return on failure */
764 cm_ReleaseSCache(scp);
769 /* we are sending parms back to make compat. with prev system. should
770 * change interface later to not ask for current status, just set
773 cp = ioctlp->outDatap;
774 memcpy(cp, (char *)&volStat, sizeof(VolumeStatus));
775 cp += sizeof(VolumeStatus);
776 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), volName);
777 cp += strlen(volName)+1;
778 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), offLineMsg);
779 cp += strlen(offLineMsg)+1;
780 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), motd);
781 cp += strlen(motd)+1;
783 /* now return updated return data pointer */
784 ioctlp->outDatap = cp;
789 long cm_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
793 char offLineMsg[256];
797 AFSFetchVolumeStatus volStat;
803 struct rx_connection * callp;
807 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
808 if (code) return code;
811 OfflineMsg = offLineMsg;
814 code = cm_Conn(&scp->fid, userp, &req, &tcp);
817 callp = cm_GetRxConn(tcp);
818 code = RXAFS_GetVolumeStatus(callp, scp->fid.volume,
819 &volStat, &Name, &OfflineMsg, &MOTD);
820 rx_PutConnection(callp);
822 } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
823 code = cm_MapRPCError(code, &req);
825 cm_ReleaseSCache(scp);
826 if (code) return code;
828 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
829 cp = ioctlp->outDatap;
830 memcpy(cp, (char *)&volStat, sizeof(AFSFetchVolumeStatus));
831 cp += sizeof(AFSFetchVolumeStatus);
832 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), volName);
833 cp += strlen(volName)+1;
834 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), offLineMsg);
835 cp += strlen(offLineMsg)+1;
836 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), motd);
837 cp += strlen(motd)+1;
839 /* return new size */
840 ioctlp->outDatap = cp;
845 long cm_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp)
855 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
856 if (code) return code;
858 memset(&fid, 0, sizeof(cm_fid_t));
859 fid.volume = scp->fid.volume;
860 fid.vnode = scp->fid.vnode;
861 fid.unique = scp->fid.unique;
863 cm_ReleaseSCache(scp);
865 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
866 cp = ioctlp->outDatap;
867 memcpy(cp, (char *)&fid, sizeof(cm_fid_t));
868 cp += sizeof(cm_fid_t);
870 /* return new size */
871 ioctlp->outDatap = cp;
876 long cm_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp)
885 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
886 if (code) return code;
888 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
889 cp = ioctlp->outDatap;
890 memcpy(cp, (char *)&scp->owner, sizeof(afs_uint32));
891 cp += sizeof(afs_uint32);
892 memcpy(cp, (char *)&scp->group, sizeof(afs_uint32));
893 cp += sizeof(afs_uint32);
895 /* return new size */
896 ioctlp->outDatap = cp;
898 cm_ReleaseSCache(scp);
903 long cm_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp)
909 cm_serverRef_t **tsrpp, *current;
911 unsigned long volume;
917 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
918 if (code) return code;
920 volume = scp->fid.volume;
922 cellp = cm_FindCellByID(scp->fid.cell);
925 cm_ReleaseSCache(scp);
927 code = cm_GetVolumeByID(cellp, volume, userp, &req, &tvp);
928 if (code) return code;
930 cp = ioctlp->outDatap;
932 lock_ObtainMutex(&tvp->mx);
933 tsrpp = cm_GetVolServers(tvp, volume);
934 lock_ObtainRead(&cm_serverLock);
935 for (current = *tsrpp; current; current = current->next) {
936 tsp = current->server;
937 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
940 lock_ReleaseRead(&cm_serverLock);
941 cm_FreeServerList(tsrpp);
942 lock_ReleaseMutex(&tvp->mx);
944 /* still room for terminating NULL, add it on */
945 volume = 0; /* reuse vbl */
946 memcpy(cp, (char *)&volume, sizeof(long));
949 ioctlp->outDatap = cp;
954 long cm_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
964 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
965 if (code) return code;
967 cp = ioctlp->inDatap;
969 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
970 cm_ReleaseSCache(dscp);
971 if (code) return code;
973 lock_ObtainMutex(&scp->mx);
975 /* now check that this is a real mount point */
976 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
977 lock_ReleaseMutex(&scp->mx);
978 cm_ReleaseSCache(scp);
979 return CM_ERROR_INVAL;
982 code = cm_ReadMountPoint(scp, userp, &req);
984 cp = ioctlp->outDatap;
985 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), scp->mountPointStringp);
986 cp += strlen(cp) + 1;
987 ioctlp->outDatap = cp;
989 lock_ReleaseMutex(&scp->mx);
990 cm_ReleaseSCache(scp);
995 long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1005 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1006 if (code) return code;
1008 cp = ioctlp->inDatap;
1010 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1012 /* if something went wrong, bail out now */
1017 lock_ObtainMutex(&scp->mx);
1018 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1019 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1021 lock_ReleaseMutex(&scp->mx);
1022 cm_ReleaseSCache(scp);
1026 /* now check that this is a real mount point */
1027 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
1028 lock_ReleaseMutex(&scp->mx);
1029 cm_ReleaseSCache(scp);
1030 code = CM_ERROR_INVAL;
1034 /* time to make the RPC, so drop the lock */
1035 lock_ReleaseMutex(&scp->mx);
1036 cm_ReleaseSCache(scp);
1038 /* easier to do it this way */
1039 code = cm_Unlink(dscp, cp, userp, &req);
1040 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1041 smb_NotifyChange(FILE_ACTION_REMOVED,
1042 FILE_NOTIFY_CHANGE_DIR_NAME,
1043 dscp, cp, NULL, TRUE);
1046 lock_ObtainMutex(&scp->mx);
1047 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1048 lock_ReleaseMutex(&scp->mx);
1051 cm_ReleaseSCache(dscp);
1055 long cm_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp)
1065 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1066 tp = ioctlp->inDatap;
1069 memcpy(&temp, tp, sizeof(temp));
1070 if (temp == 0x12345678) { /* For afs3.3 version */
1071 memcpy(&csi, tp, sizeof(csi));
1072 if (csi.tinterval >= 0) {
1073 cp = ioctlp->outDatap;
1074 memcpy(cp, (char *)&cm_daemonCheckDownInterval, sizeof(long));
1075 ioctlp->outDatap += sizeof(long);
1076 if (csi.tinterval > 0) {
1077 if (!smb_SUser(userp))
1078 return CM_ERROR_NOACCESS;
1079 cm_daemonCheckDownInterval = csi.tinterval;
1087 } else { /* For pre afs3.3 versions */
1088 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
1089 ioctlp->inDatap = cp = ioctlp->inDatap + sizeof(long);
1090 if (cp - ioctlp->inAllocp < ioctlp->inCopied) /* still more data available */
1095 * 1: fast check, don't contact servers.
1096 * 2: local cell only.
1099 /* have cell name, too */
1100 cellp = cm_GetCell(cp, 0);
1101 if (!cellp) return CM_ERROR_NOSUCHCELL;
1103 else cellp = (cm_cell_t *) 0;
1104 if (!cellp && (temp & 2)) {
1105 /* use local cell */
1106 cellp = cm_FindCellByID(1);
1108 if (!(temp & 1)) { /* if not fast, call server checker routine */
1109 /* check down servers */
1110 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS | CM_FLAG_CHECKUPSERVERS,
1114 /* now return the current down server list */
1115 cp = ioctlp->outDatap;
1116 lock_ObtainRead(&cm_serverLock);
1117 for (tsp = cm_allServersp; tsp; tsp=tsp->allNextp) {
1118 if (cellp && tsp->cellp != cellp) continue; /* cell spec'd and wrong */
1119 if ((tsp->flags & CM_SERVERFLAG_DOWN)
1120 && tsp->type == CM_SERVER_FILE) {
1121 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
1125 lock_ReleaseRead(&cm_serverLock);
1127 ioctlp->outDatap = cp;
1131 long cm_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp)
1133 /* we don't print anything superfluous, so we don't support the gag call */
1134 return CM_ERROR_INVAL;
1137 long cm_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
1143 long cm_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp)
1148 cm_SkipIoctlPath(ioctlp);
1150 memcpy(&temp, ioctlp->inDatap, sizeof(temp));
1152 temp = cm_data.buf_nOrigBuffers;
1154 /* temp is in 1K units, convert to # of buffers */
1155 temp = temp / (cm_data.buf_blockSize / 1024);
1158 /* now adjust the cache size */
1159 code = buf_SetNBuffers(temp);
1164 long cm_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
1168 cm_SkipIoctlPath(ioctlp);
1170 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
1174 afsd_ForceTrace(FALSE);
1175 buf_ForceTrace(FALSE);
1179 /* set tracing value to low order bit */
1180 if ((inValue & 1) == 0) {
1181 /* disable tracing */
1182 osi_LogDisable(afsd_logp);
1183 rx_DebugOnOff(FALSE);
1186 /* enable tracing */
1187 osi_LogEnable(afsd_logp);
1188 rx_DebugOnOff(TRUE);
1192 /* see if we're supposed to do a reset, too */
1194 osi_LogReset(afsd_logp);
1197 /* and copy out tracing flag */
1198 inValue = afsd_logp->enabled; /* use as a temp vbl */
1199 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
1200 ioctlp->outDatap += sizeof(long);
1204 long cm_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp)
1206 cm_cacheParms_t parms;
1208 memset(&parms, 0, sizeof(parms));
1210 /* first we get, in 1K units, the cache size */
1211 parms.parms[0] = cm_data.buf_nbuffers * (cm_data.buf_blockSize / 1024);
1213 /* and then the actual # of buffers in use (not in the free list, I guess,
1214 * will be what we do).
1216 parms.parms[1] = (cm_data.buf_nbuffers - buf_CountFreeList()) * (cm_data.buf_blockSize / 1024);
1218 memcpy(ioctlp->outDatap, &parms, sizeof(parms));
1219 ioctlp->outDatap += sizeof(parms);
1224 long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1229 cm_serverRef_t *serverRefp;
1230 cm_server_t *serverp;
1236 cm_SkipIoctlPath(ioctlp);
1238 tp = ioctlp->inDatap;
1240 memcpy((char *)&whichCell, tp, sizeof(long));
1243 /* see if more than one long passed in, ignoring the null pathname (the -1) */
1244 if (ioctlp->inCopied-1 > sizeof(long)) {
1245 memcpy((char *)&magic, tp, sizeof(long));
1248 lock_ObtainRead(&cm_cellLock);
1249 for (tcellp = cm_data.allCellsp; tcellp; tcellp = tcellp->nextp) {
1250 if (whichCell == 0) break;
1253 lock_ReleaseRead(&cm_cellLock);
1257 cp = ioctlp->outDatap;
1259 if (magic == 0x12345678) {
1260 memcpy(cp, (char *)&magic, sizeof(long));
1263 memset(cp, 0, max * sizeof(long));
1265 lock_ObtainRead(&cm_serverLock); /* for going down server list */
1266 /* jaltman - do the reference counts to serverRefp contents need to be increased? */
1267 serverRefp = tcellp->vlServersp;
1268 for (i=0; i<max; i++) {
1269 if (!serverRefp) break;
1270 serverp = serverRefp->server;
1271 memcpy(cp, &serverp->addr.sin_addr.s_addr, sizeof(long));
1273 serverRefp = serverRefp->next;
1275 lock_ReleaseRead(&cm_serverLock);
1276 cp = basep + max * sizeof(afs_int32);
1277 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), tcellp->name);
1278 cp += strlen(tcellp->name)+1;
1279 ioctlp->outDatap = cp;
1285 return CM_ERROR_NOMORETOKENS; /* mapped to EDOM */
1288 extern long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *namep);
1290 long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1292 /* NT cache manager will read cell information from CellServDB each time
1293 * cell is accessed. So, this call is necessary only if list of server for a cell
1294 * changes (or IP addresses of cell servers changes).
1295 * All that needs to be done is to refresh server information for all cells that
1296 * are already loaded.
1298 * cell list will be cm_CellLock and cm_ServerLock will be held for write.
1303 cm_SkipIoctlPath(ioctlp);
1304 lock_ObtainWrite(&cm_cellLock);
1306 for (cp = cm_data.allCellsp; cp; cp=cp->nextp)
1309 lock_ObtainMutex(&cp->mx);
1310 /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
1311 cm_FreeServerList(&cp->vlServersp);
1312 cp->vlServersp = NULL;
1313 code = cm_SearchCellFile(cp->name, cp->name, cm_AddCellProc, cp);
1314 #ifdef AFS_AFSDB_ENV
1316 if (cm_dnsEnabled) {
1318 code = cm_SearchCellByDNS(cp->name, cp->name, &ttl, cm_AddCellProc, cp);
1319 if ( code == 0 ) { /* got cell from DNS */
1320 cp->flags |= CM_CELLFLAG_DNS;
1321 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1322 cp->timeout = time(0) + ttl;
1327 cp->flags &= ~CM_CELLFLAG_DNS;
1329 #endif /* AFS_AFSDB_ENV */
1331 cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
1334 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1335 cm_RandomizeServer(&cp->vlServersp);
1337 lock_ReleaseMutex(&cp->mx);
1340 lock_ReleaseWrite(&cm_cellLock);
1344 long cm_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
1348 if (cm_freelanceEnabled) {
1349 if (cm_GetRootCellName(ioctlp->outDatap))
1350 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "Freelance.Local.Root");
1351 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1352 } else if (cm_data.rootCellp) {
1353 /* return the default cellname to the caller */
1354 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), cm_data.rootCellp->name);
1355 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1357 /* if we don't know our default cell, return failure */
1358 code = CM_ERROR_NOSUCHCELL;
1364 long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp)
1366 long setSysName, foundname = 0;
1367 char *cp, *cp2, inname[MAXSYSNAME], outname[MAXSYSNAME];
1368 int t, count, num = 0;
1369 char **sysnamelist[MAXSYSNAME];
1371 cm_SkipIoctlPath(ioctlp);
1373 memcpy(&setSysName, ioctlp->inDatap, sizeof(long));
1374 ioctlp->inDatap += sizeof(long);
1378 if ( setSysName < 0 || setSysName > MAXNUMSYSNAMES )
1380 cp2 = ioctlp->inDatap;
1381 for ( cp=ioctlp->inDatap, count = 0; count < setSysName; count++ ) {
1382 /* won't go past end of ioctlp->inDatap since maxsysname*num < ioctlp->inDatap length */
1383 t = (int)strlen(cp);
1384 if (t >= MAXSYSNAME || t <= 0)
1386 /* check for names that can shoot us in the foot */
1387 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
1393 /* inname gets first entry in case we're being a translator */
1394 /* (we are never a translator) */
1395 t = (int)strlen(ioctlp->inDatap);
1396 memcpy(inname, ioctlp->inDatap, t + 1);
1397 ioctlp->inDatap += t + 1;
1401 /* Not xlating, so local case */
1403 osi_panic("cm_IoctlSysName: !cm_sysName\n", __FILE__, __LINE__);
1405 if (!setSysName) { /* user just wants the info */
1406 StringCbCopyA(outname, sizeof(outname), cm_sysName);
1407 foundname = cm_sysNameCount;
1408 *sysnamelist = cm_sysNameList;
1410 /* Local guy; only root can change sysname */
1411 /* clear @sys entries from the dnlc, once afs_lookup can
1412 * do lookups of @sys entries and thinks it can trust them */
1413 /* privs ok, store the entry, ... */
1414 StringCbCopyA(cm_sysName, sizeof(cm_sysName), inname);
1415 StringCbCopyA(cm_sysNameList[0], MAXSYSNAME, inname);
1416 if (setSysName > 1) { /* ... or list */
1417 cp = ioctlp->inDatap;
1418 for (count = 1; count < setSysName; ++count) {
1419 if (!cm_sysNameList[count])
1420 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to write\n",
1421 __FILE__, __LINE__);
1422 t = (int)strlen(cp);
1423 StringCbCopyA(cm_sysNameList[count], MAXSYSNAME, cp);
1427 cm_sysNameCount = setSysName;
1431 /* return the sysname to the caller */
1432 cp = ioctlp->outDatap;
1433 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
1434 cp += sizeof(afs_int32); /* skip found flag */
1436 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), outname);
1437 cp += strlen(outname) + 1; /* skip name and terminating null char */
1438 for ( count=1; count < foundname ; ++count) { /* ... or list */
1439 if ( !(*sysnamelist)[count] )
1440 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to read\n",
1441 __FILE__, __LINE__);
1442 t = (int)strlen((*sysnamelist)[count]);
1443 if (t >= MAXSYSNAME)
1444 osi_panic("cm_IoctlSysName: sysname entry garbled\n",
1445 __FILE__, __LINE__);
1446 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), (*sysnamelist)[count]);
1450 ioctlp->outDatap = cp;
1457 long cm_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1462 cm_SkipIoctlPath(ioctlp);
1464 cellp = cm_GetCell(ioctlp->inDatap, 0);
1466 return CM_ERROR_NOSUCHCELL;
1469 lock_ObtainMutex(&cellp->mx);
1470 if (cellp->flags & CM_CELLFLAG_SUID)
1471 temp |= CM_SETCELLFLAG_SUID;
1472 lock_ReleaseMutex(&cellp->mx);
1474 /* now copy out parm */
1475 memcpy(ioctlp->outDatap, &temp, sizeof(long));
1476 ioctlp->outDatap += sizeof(long);
1481 long cm_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1486 cm_SkipIoctlPath(ioctlp);
1488 cellp = cm_GetCell(ioctlp->inDatap + 2*sizeof(long), 0);
1490 return CM_ERROR_NOSUCHCELL;
1492 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
1494 lock_ObtainMutex(&cellp->mx);
1495 if (temp & CM_SETCELLFLAG_SUID)
1496 cellp->flags |= CM_CELLFLAG_SUID;
1498 cellp->flags &= ~CM_CELLFLAG_SUID;
1499 lock_ReleaseMutex(&cellp->mx);
1504 long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1506 cm_SSetPref_t *spin; /* input */
1507 cm_SPref_t *srvin; /* one input component */
1509 int i, vlonly, noServers, type;
1510 struct sockaddr_in tmp;
1511 unsigned short rank;
1513 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1515 spin = (cm_SSetPref_t *)ioctlp->inDatap;
1516 noServers = spin->num_servers;
1517 vlonly = spin->flags;
1519 type = CM_SERVER_VLDB;
1521 type = CM_SERVER_FILE;
1523 for ( i=0; i < noServers; i++)
1525 srvin = &(spin->servers[i]);
1526 rank = srvin->rank + (rand() & 0x000f);
1527 tmp.sin_addr = srvin->host;
1528 tmp.sin_family = AF_INET;
1530 tsp = cm_FindServer(&tmp, type);
1531 if ( tsp ) /* an existing server - ref count increased */
1533 tsp->ipRank = rank; /* no need to protect by mutex*/
1535 if (type == CM_SERVER_FILE)
1537 /* find volumes which might have RO copy
1538 /* on server and change the ordering of
1541 cm_ChangeRankVolume(tsp);
1545 /* set preferences for an existing vlserver */
1546 cm_ChangeRankCellVLServer(tsp);
1549 else /* add a new server without a cell */
1551 tsp = cm_NewServer(&tmp, type, NULL); /* refcount = 1 */
1554 lock_ObtainMutex(&tsp->mx);
1555 tsp->flags |= CM_SERVERFLAG_PREF_SET;
1556 lock_ReleaseMutex(&tsp->mx);
1557 cm_PutServer(tsp); /* decrease refcount */
1562 long cm_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1564 cm_SPrefRequest_t *spin; /* input */
1565 cm_SPrefInfo_t *spout; /* output */
1566 cm_SPref_t *srvout; /* one output component */
1568 int i, vlonly, noServers;
1570 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1572 spin = (cm_SPrefRequest_t *)ioctlp->inDatap;
1573 spout = (cm_SPrefInfo_t *) ioctlp->outDatap;
1574 srvout = spout->servers;
1575 noServers = spin->num_servers;
1576 vlonly = spin->flags & CM_SPREF_VLONLY;
1577 spout->num_servers = 0;
1579 lock_ObtainRead(&cm_serverLock); /* get server lock */
1581 for (tsp=cm_allServersp, i=0; tsp && noServers; tsp=tsp->allNextp,i++){
1582 if (spin->offset > i) {
1583 continue; /* catch up to where we left off */
1586 if ( vlonly && (tsp->type == CM_SERVER_FILE) )
1587 continue; /* ignore fileserver for -vlserver option*/
1588 if ( !vlonly && (tsp->type == CM_SERVER_VLDB) )
1589 continue; /* ignore vlservers */
1591 srvout->host = tsp->addr.sin_addr;
1592 srvout->rank = tsp->ipRank;
1594 spout->num_servers++;
1597 lock_ReleaseRead(&cm_serverLock); /* release server lock */
1599 if ( tsp ) /* we ran out of space in the output buffer */
1600 spout->next_offset = i;
1602 spout->next_offset = 0;
1603 ioctlp->outDatap += sizeof(cm_SPrefInfo_t) +
1604 (spout->num_servers -1 ) * sizeof(cm_SPref_t) ;
1608 long cm_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp)
1610 /* we ignore default asynchrony since we only have one way
1611 * of doing this today.
1616 long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1618 char leaf[LEAF_SIZE];
1632 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1633 if (code) return code;
1635 /* Translate chars for the mount point name */
1636 TranslateExtendedChars(leaf);
1639 * The fs command allows the user to specify partial cell names on NT. These must
1640 * be expanded to the full cell name for mount points so that the mount points will
1641 * work on UNIX clients.
1644 /* Extract the possibly partial cell name */
1645 StringCbCopyA(cell, sizeof(cell), ioctlp->inDatap + 1); /* Skip the mp type character */
1647 if (cp = strchr(cell, ':')) {
1648 /* Extract the volume name */
1650 StringCbCopyA(volume, sizeof(volume), cp + 1);
1652 /* Get the full name for this cell */
1653 code = cm_SearchCellFile(cell, fullCell, 0, 0);
1654 #ifdef AFS_AFSDB_ENV
1655 if (code && cm_dnsEnabled)
1656 code = cm_SearchCellByDNS(cell, fullCell, &ttl, 0, 0);
1659 return CM_ERROR_NOSUCHCELL;
1661 StringCbPrintfA(mpInfo, sizeof(mpInfo), "%c%s:%s", *ioctlp->inDatap, fullCell, volume);
1663 /* No cell name specified */
1664 StringCbCopyA(mpInfo, sizeof(mpInfo), ioctlp->inDatap);
1667 #ifdef AFS_FREELANCE_CLIENT
1668 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1669 /* we are adding the mount point to the root dir., so call
1670 * the freelance code to do the add. */
1671 osi_Log0(afsd_logp,"IoctlCreateMountPoint within Freelance root dir");
1672 code = cm_FreelanceAddMount(leaf, fullCell, volume,
1673 *ioctlp->inDatap == '%', NULL);
1674 cm_ReleaseSCache(dscp);
1678 /* create the symlink with mode 644. The lack of X bits tells
1679 * us that it is a mount point.
1681 tattr.mask = CM_ATTRMASK_UNIXMODEBITS | CM_ATTRMASK_CLIENTMODTIME;
1682 tattr.unixModeBits = 0644;
1683 tattr.clientModTime = time(NULL);
1685 code = cm_SymLink(dscp, leaf, mpInfo, 0, &tattr, userp, &req);
1686 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1687 smb_NotifyChange(FILE_ACTION_ADDED,
1688 FILE_NOTIFY_CHANGE_DIR_NAME,
1689 dscp, leaf, NULL, TRUE);
1691 cm_ReleaseSCache(dscp);
1695 long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1697 char leaf[LEAF_SIZE];
1706 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1707 if (code) return code;
1709 /* Translate chars for the link name */
1710 TranslateExtendedChars(leaf);
1712 /* Translate chars for the linked to name */
1713 TranslateExtendedChars(ioctlp->inDatap);
1715 cp = ioctlp->inDatap; /* contents of link */
1717 #ifdef AFS_FREELANCE_CLIENT
1718 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1719 /* we are adding the symlink to the root dir., so call
1720 * the freelance code to do the add. */
1721 if (cp[0] == cp[1] && cp[1] == '\\' &&
1722 !_strnicmp(cm_NetbiosName,cp+2,strlen(cm_NetbiosName)))
1724 /* skip \\AFS\ or \\AFS\all\ */
1726 p = cp + 2 + strlen(cm_NetbiosName) + 1;
1727 if ( !_strnicmp("all", p, 3) )
1731 osi_Log0(afsd_logp,"IoctlCreateSymlink within Freelance root dir");
1732 code = cm_FreelanceAddSymlink(leaf, cp, NULL);
1733 cm_ReleaseSCache(dscp);
1738 /* Create symlink with mode 0755. */
1739 tattr.mask = CM_ATTRMASK_UNIXMODEBITS;
1740 tattr.unixModeBits = 0755;
1742 code = cm_SymLink(dscp, leaf, cp, 0, &tattr, userp, &req);
1743 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1744 smb_NotifyChange(FILE_ACTION_ADDED,
1745 FILE_NOTIFY_CHANGE_FILE_NAME
1746 | FILE_NOTIFY_CHANGE_DIR_NAME,
1747 dscp, leaf, NULL, TRUE);
1749 cm_ReleaseSCache(dscp);
1755 long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1762 cm_scache_t *newRootScp;
1767 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1768 if (code) return code;
1770 cp = ioctlp->inDatap;
1772 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1773 cm_ReleaseSCache(dscp);
1774 if (code) return code;
1776 /* Check that it's a real symlink */
1777 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1778 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1779 scp->fileType != CM_SCACHETYPE_INVALID) {
1780 cm_ReleaseSCache(scp);
1781 return CM_ERROR_INVAL;
1784 code = cm_AssembleLink(scp, "", &newRootScp, &spacep, userp, &req);
1785 cm_ReleaseSCache(scp);
1787 cp = ioctlp->outDatap;
1788 if (newRootScp != NULL) {
1789 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), cm_mountRoot);
1790 StringCbCatA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), "/");
1793 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), spacep->data);
1794 cp += strlen(cp) + 1;
1795 ioctlp->outDatap = cp;
1796 cm_FreeSpace(spacep);
1797 if (newRootScp != NULL)
1798 cm_ReleaseSCache(newRootScp);
1800 } else if (code == CM_ERROR_PATH_NOT_COVERED &&
1801 scp->fileType == CM_SCACHETYPE_DFSLINK ||
1802 code == CM_ERROR_NOSUCHPATH &&
1803 scp->fileType == CM_SCACHETYPE_INVALID) {
1804 cp = ioctlp->outDatap;
1805 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), spacep->data);
1806 cp += strlen(cp) + 1;
1807 ioctlp->outDatap = cp;
1808 cm_FreeSpace(spacep);
1809 if (newRootScp != NULL)
1810 cm_ReleaseSCache(newRootScp);
1817 long cm_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1818 {/*CHECK FOR VALID SYMLINK*/
1827 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1828 if (code) return code;
1830 cp = ioctlp->inDatap;
1831 osi_LogEvent("cm_IoctlListlink",NULL," name[%s]",cp);
1833 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1834 cm_ReleaseSCache(dscp);
1835 if (code) return code;
1837 /* Check that it's a real symlink */
1838 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1839 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1840 scp->fileType != CM_SCACHETYPE_INVALID)
1841 code = CM_ERROR_INVAL;
1842 cm_ReleaseSCache(scp);
1846 long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1856 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1857 if (code) return code;
1859 cp = ioctlp->inDatap;
1861 #ifdef AFS_FREELANCE_CLIENT
1862 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1863 /* we are adding the mount point to the root dir., so call
1864 * the freelance code to do the add. */
1865 osi_Log0(afsd_logp,"IoctlDeletelink from Freelance root dir");
1866 code = cm_FreelanceRemoveSymlink(cp);
1867 cm_ReleaseSCache(dscp);
1872 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1874 /* if something went wrong, bail out now */
1878 lock_ObtainMutex(&scp->mx);
1879 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1880 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1884 /* now check that this is a real symlink */
1885 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1886 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1887 scp->fileType != CM_SCACHETYPE_INVALID) {
1888 code = CM_ERROR_INVAL;
1892 /* time to make the RPC, so drop the lock */
1893 lock_ReleaseMutex(&scp->mx);
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);
1903 lock_ObtainMutex(&scp->mx);
1905 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1908 lock_ReleaseMutex(&scp->mx);
1909 cm_ReleaseSCache(scp);
1912 cm_ReleaseSCache(dscp);
1917 long cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid)
1922 static struct afsconf_cell info;
1923 struct rx_connection *serverconns[MAXSERVERS];
1924 struct rx_securityClass *sc[3];
1925 afs_int32 scIndex = 2; /* authenticated - we have a token */
1926 struct ubik_client *pruclient = NULL;
1927 struct afsconf_dir *tdir;
1931 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
1932 code = afsconf_GetCellInfo(tdir, ucellp->cellp->name, "afsprot", &info);
1933 afsconf_Close(tdir);
1939 /* we have the token that was given to us in the settoken
1940 * call. we just have to use it.
1942 scIndex = 2; /* kerberos ticket */
1943 sc[2] = rxkad_NewClientSecurityObject(rxkad_clear, &ucellp->sessionKey,
1944 ucellp->kvno, ucellp->ticketLen,
1947 memset(serverconns, 0, sizeof(serverconns)); /* terminate list!!! */
1948 for (i = 0; i < info.numServers; i++)
1950 rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
1951 info.hostAddr[i].sin_port, PRSRV, sc[scIndex],
1954 code = ubik_ClientInit(serverconns, &pruclient);
1959 code = rxs_Release(sc[scIndex]);
1961 lids.idlist_len = 0;
1962 lids.idlist_val = 0;
1963 lnames.namelist_len = 1;
1964 lnames.namelist_val = (prname *) malloc(PR_MAXNAMELEN);
1965 strncpy(lnames.namelist_val[0], uname, PR_MAXNAMELEN);
1966 lnames.namelist_val[0][PR_MAXNAMELEN-1] = '\0';
1967 for ( p=lnames.namelist_val[0], r=NULL; *p; p++ ) {
1973 if (r && !stricmp(r+1,ucellp->cellp->name))
1976 code = ubik_Call(PR_NameToID, pruclient, 0, &lnames, &lids);
1977 if (lids.idlist_val) {
1978 *uid = *lids.idlist_val;
1979 free(lids.idlist_val);
1981 if (lnames.namelist_val)
1982 free(lnames.namelist_val);
1985 ubik_ClientDestroy(pruclient);
1991 #endif /* QUERY_AFSID */
1993 long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2000 struct ClearToken ct;
2010 int release_userp = 0;
2013 saveDataPtr = ioctlp->inDatap;
2015 cm_SkipIoctlPath(ioctlp);
2017 tp = ioctlp->inDatap;
2020 memcpy(&ticketLen, tp, sizeof(ticketLen));
2021 tp += sizeof(ticketLen);
2022 if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN)
2023 return CM_ERROR_INVAL;
2025 /* remember ticket and skip over it for now */
2029 /* clear token size */
2030 memcpy(&ctSize, tp, sizeof(ctSize));
2031 tp += sizeof(ctSize);
2032 if (ctSize != sizeof(struct ClearToken))
2033 return CM_ERROR_INVAL;
2036 memcpy(&ct, tp, ctSize);
2038 if (ct.AuthHandle == -1)
2039 ct.AuthHandle = 999; /* more rxvab compat stuff */
2041 /* more stuff, if any */
2042 if (ioctlp->inCopied > tp - saveDataPtr) {
2043 /* flags: logon flag */
2044 memcpy(&flags, tp, sizeof(int));
2048 cellp = cm_GetCell(tp, CM_FLAG_CREATE);
2049 if (!cellp) return CM_ERROR_NOSUCHCELL;
2050 tp += strlen(tp) + 1;
2054 tp += strlen(tp) + 1;
2056 #ifndef AFSIFS /* no SMB username, so we cannot logon based on this */
2057 if (flags & PIOCTL_LOGON) {
2058 /* SMB user name with which to associate tokens */
2060 osi_Log2(smb_logp,"cm_IoctlSetToken for user [%s] smbname [%s]",
2061 osi_LogSaveString(smb_logp,uname), osi_LogSaveString(smb_logp,smbname));
2062 fprintf(stderr, "SMB name = %s\n", smbname);
2063 tp += strlen(tp) + 1;
2065 osi_Log1(smb_logp,"cm_IoctlSetToken for user [%s]",
2066 osi_LogSaveString(smb_logp, uname));
2071 memcpy(&uuid, tp, sizeof(uuid));
2072 if (!cm_FindTokenEvent(uuid, sessionKey))
2073 return CM_ERROR_INVAL;
2075 cellp = cm_data.rootCellp;
2076 osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
2080 if (flags & PIOCTL_LOGON) {
2081 userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname,
2082 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
2087 /* store the token */
2088 lock_ObtainMutex(&userp->mx);
2089 ucellp = cm_GetUCell(userp, cellp);
2090 osi_Log1(smb_logp,"cm_IoctlSetToken ucellp %lx", ucellp);
2091 ucellp->ticketLen = ticketLen;
2092 if (ucellp->ticketp)
2093 free(ucellp->ticketp); /* Discard old token if any */
2094 ucellp->ticketp = malloc(ticketLen);
2095 memcpy(ucellp->ticketp, ticket, ticketLen);
2097 * Get the session key from the RPC, rather than from the pioctl.
2100 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
2102 memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
2103 ucellp->kvno = ct.AuthHandle;
2104 ucellp->expirationTime = ct.EndTimestamp;
2107 ucellp->uid = ANONYMOUSID;
2110 StringCbCopyA(ucellp->userName, MAXKTCNAMELEN, uname);
2112 cm_UsernameToId(uname, ucellp, &ucellp->uid);
2115 ucellp->flags |= CM_UCELLFLAG_RXKAD;
2116 lock_ReleaseMutex(&userp->mx);
2118 if (flags & PIOCTL_LOGON) {
2119 ioctlp->flags |= SMB_IOCTLFLAG_LOGON;
2122 cm_ResetACLCache(userp);
2125 cm_ReleaseUser(userp);
2130 long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
2136 struct ClearToken ct;
2138 cm_SkipIoctlPath(ioctlp);
2140 tp = ioctlp->inDatap;
2141 cp = ioctlp->outDatap;
2144 memcpy(&iterator, tp, sizeof(iterator));
2145 tp += sizeof(iterator);
2147 lock_ObtainMutex(&userp->mx);
2149 /* look for token */
2150 for (;;iterator++) {
2151 ucellp = cm_FindUCell(userp, iterator);
2153 lock_ReleaseMutex(&userp->mx);
2154 return CM_ERROR_NOMORETOKENS;
2156 if (ucellp->flags & CM_UCELLFLAG_RXKAD)
2161 temp = ucellp->iterator + 1;
2162 memcpy(cp, &temp, sizeof(temp));
2166 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2167 cp += sizeof(ucellp->ticketLen);
2170 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2171 cp += ucellp->ticketLen;
2173 /* clear token size */
2175 memcpy(cp, &temp, sizeof(temp));
2179 ct.AuthHandle = ucellp->kvno;
2181 * Don't give out a real session key here
2184 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2186 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2187 ct.ViceId = 37; /* XXX */
2188 ct.BeginTimestamp = 0; /* XXX */
2189 ct.EndTimestamp = ucellp->expirationTime;
2190 memcpy(cp, &ct, sizeof(ct));
2193 /* Primary flag (unused) */
2195 memcpy(cp, &temp, sizeof(temp));
2199 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->cellp->name);
2200 cp += strlen(cp) + 1;
2203 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->userName);
2204 cp += strlen(cp) + 1;
2206 ioctlp->outDatap = cp;
2208 lock_ReleaseMutex(&userp->mx);
2213 long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2219 struct ClearToken ct;
2222 cm_SkipIoctlPath(ioctlp);
2224 tp = ioctlp->inDatap;
2226 cp = ioctlp->outDatap;
2228 /* cell name is right here */
2229 cellp = cm_GetCell(tp, 0);
2231 return CM_ERROR_NOSUCHCELL;
2232 tp += strlen(tp) + 1;
2235 memcpy(&uuid, tp, sizeof(uuid));
2237 lock_ObtainMutex(&userp->mx);
2239 ucellp = cm_GetUCell(userp, cellp);
2240 if (!ucellp || !(ucellp->flags & CM_UCELLFLAG_RXKAD)) {
2241 lock_ReleaseMutex(&userp->mx);
2242 return CM_ERROR_NOMORETOKENS;
2246 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2247 cp += sizeof(ucellp->ticketLen);
2250 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2251 cp += ucellp->ticketLen;
2253 /* clear token size */
2255 memcpy(cp, &temp, sizeof(temp));
2259 ct.AuthHandle = ucellp->kvno;
2261 * Don't give out a real session key here
2264 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2266 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2267 ct.ViceId = 37; /* XXX */
2268 ct.BeginTimestamp = 0; /* XXX */
2269 ct.EndTimestamp = ucellp->expirationTime;
2270 memcpy(cp, &ct, sizeof(ct));
2273 /* Primary flag (unused) */
2275 memcpy(cp, &temp, sizeof(temp));
2279 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->cellp->name);
2280 cp += strlen(cp) + 1;
2283 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->userName);
2284 cp += strlen(cp) + 1;
2286 ioctlp->outDatap = cp;
2288 lock_ReleaseMutex(&userp->mx);
2290 cm_RegisterNewTokenEvent(uuid, ucellp->sessionKey.data);
2295 long cm_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2301 cm_SkipIoctlPath(ioctlp);
2303 cp = ioctlp->outDatap;
2305 /* cell name is right here */
2306 cellp = cm_GetCell(ioctlp->inDatap, 0);
2307 if (!cellp) return CM_ERROR_NOSUCHCELL;
2309 lock_ObtainMutex(&userp->mx);
2311 ucellp = cm_GetUCell(userp, cellp);
2313 lock_ReleaseMutex(&userp->mx);
2314 return CM_ERROR_NOMORETOKENS;
2317 osi_Log1(smb_logp,"cm_IoctlDelToken ucellp %lx", ucellp);
2319 if (ucellp->ticketp) {
2320 free(ucellp->ticketp);
2321 ucellp->ticketp = NULL;
2323 ucellp->ticketLen = 0;
2324 memset(ucellp->sessionKey.data, 0, 8);
2326 ucellp->expirationTime = 0;
2327 ucellp->userName[0] = '\0';
2328 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2331 lock_ReleaseMutex(&userp->mx);
2333 cm_ResetACLCache(userp);
2338 long cm_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2342 lock_ObtainMutex(&userp->mx);
2344 for (ucellp = userp->cellInfop; ucellp; ucellp = ucellp->nextp) {
2345 osi_Log1(smb_logp,"cm_IoctlDelAllToken ucellp %lx", ucellp);
2347 if (ucellp->ticketp) {
2348 free(ucellp->ticketp);
2349 ucellp->ticketp = NULL;
2351 ucellp->ticketLen = 0;
2352 memset(ucellp->sessionKey.data, 0, 8);
2354 ucellp->expirationTime = 0;
2355 ucellp->userName[0] = '\0';
2356 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2360 lock_ReleaseMutex(&userp->mx);
2362 cm_ResetACLCache(userp);
2367 long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
2369 char afspath[MAX_PATH];
2371 int nextAutoSubmount;
2373 DWORD dwType, dwSize;
2378 cm_SkipIoctlPath(ioctlp);
2380 /* Serialize this one, to prevent simultaneous mods
2383 lock_ObtainMutex(&cm_Afsdsbmt_Lock);
2385 /* Parse the input parameters--first the required afs path,
2386 * then the requested submount name (which may be "").
2388 cm_NormalizeAfsPath (afspath, sizeof(afspath), ioctlp->inDatap);
2389 submountreqp = ioctlp->inDatap + (strlen(ioctlp->inDatap)+1);
2391 /* If the caller supplied a suggested submount name, see if
2392 * that submount name is in use... if so, the submount's path
2393 * has to match our path.
2396 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
2397 AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
2400 REG_OPTION_NON_VOLATILE,
2401 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
2406 if (submountreqp && *submountreqp) {
2407 char submountPathNormalized[MAX_PATH];
2408 char submountPath[MAX_PATH];
2410 dwSize = sizeof(submountPath);
2411 status = RegQueryValueEx( hkSubmounts, submountreqp, 0,
2412 &dwType, submountPath, &dwSize);
2414 if (status != ERROR_SUCCESS) {
2416 /* The suggested submount name isn't in use now--
2417 * so we can safely map the requested submount name
2418 * to the supplied path. Remember not to write the
2419 * leading "/afs" when writing out the submount.
2421 RegSetValueEx( hkSubmounts, submountreqp, 0,
2423 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2424 &afspath[strlen(cm_mountRoot)]:"/",
2425 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2426 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2428 RegCloseKey( hkSubmounts );
2429 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountreqp);
2430 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2431 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2435 /* The suggested submount name is already in use--if the
2436 * supplied path matches the submount's path, we can still
2437 * use the suggested submount name.
2439 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2440 if (!strcmp (submountPathNormalized, afspath)) {
2441 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountreqp);
2442 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2443 RegCloseKey( hkSubmounts );
2444 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2449 RegQueryInfoKey( hkSubmounts,
2451 NULL, /* lpcClass */
2452 NULL, /* lpReserved */
2453 NULL, /* lpcSubKeys */
2454 NULL, /* lpcMaxSubKeyLen */
2455 NULL, /* lpcMaxClassLen */
2456 &dwSubmounts, /* lpcValues */
2457 NULL, /* lpcMaxValueNameLen */
2458 NULL, /* lpcMaxValueLen */
2459 NULL, /* lpcbSecurityDescriptor */
2460 NULL /* lpftLastWriteTime */
2464 /* Having obtained a list of all available submounts, start
2465 * searching that list for a path which matches the requested
2466 * AFS path. We'll also keep track of the highest "auto15"/"auto47"
2467 * submount, in case we need to add a new one later.
2470 nextAutoSubmount = 1;
2472 for ( dwIndex = 0; dwIndex < dwSubmounts; dwIndex ++ ) {
2473 char submountPathNormalized[MAX_PATH];
2474 char submountPath[MAX_PATH] = "";
2475 DWORD submountPathLen = sizeof(submountPath);
2476 char submountName[MAX_PATH];
2477 DWORD submountNameLen = sizeof(submountName);
2480 RegEnumValue( hkSubmounts, dwIndex, submountName, &submountNameLen, NULL,
2481 &dwType, submountPath, &submountPathLen);
2482 if (dwType == REG_EXPAND_SZ) {
2484 StringCbCopyA(buf, MAX_PATH, submountPath);
2485 submountPathLen = ExpandEnvironmentStrings(buf, submountPath, MAX_PATH);
2486 if (submountPathLen > MAX_PATH)
2490 /* If this is an Auto### submount, remember its ### value */
2491 if ((!strnicmp (submountName, "auto", 4)) &&
2492 (isdigit (submountName[strlen("auto")]))) {
2493 int thisAutoSubmount;
2494 thisAutoSubmount = atoi (&submountName[strlen("auto")]);
2495 nextAutoSubmount = max (nextAutoSubmount,
2496 thisAutoSubmount+1);
2499 if ((submountPathLen == 0) ||
2500 (submountPathLen == sizeof(submountPath) - 1)) {
2504 /* See if the path for this submount matches the path
2505 * that our caller specified. If so, we can return
2508 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2509 if (!strcmp (submountPathNormalized, afspath)) {
2510 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountName);
2511 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2512 RegCloseKey(hkSubmounts);
2513 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2519 /* We've been through the entire list of existing submounts, and
2520 * didn't find any which matched the specified path. So, we'll
2521 * just have to add one. Remember not to write the leading "/afs"
2522 * when writing out the submount.
2525 StringCbPrintfA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "auto%ld", nextAutoSubmount);
2527 RegSetValueEx( hkSubmounts,
2531 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2532 &afspath[strlen(cm_mountRoot)]:"/",
2533 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2534 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2536 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2537 RegCloseKey(hkSubmounts);
2538 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2542 long cm_IoctlGetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2544 memcpy(ioctlp->outDatap, &cryptall, sizeof(cryptall));
2545 ioctlp->outDatap += sizeof(cryptall);
2550 long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2552 afs_int32 c = cryptall;
2554 cm_SkipIoctlPath(ioctlp);
2556 memcpy(&cryptall, ioctlp->inDatap, sizeof(cryptall));
2558 if (c != cryptall) {
2560 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_ON);
2562 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_OFF);
2567 long cm_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp)
2572 cm_SkipIoctlPath(ioctlp);
2574 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2575 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2578 if (flags & AFSCALL_RXSTATS_ENABLE) {
2579 rx_enableProcessRPCStats();
2581 if (flags & AFSCALL_RXSTATS_DISABLE) {
2582 rx_disableProcessRPCStats();
2584 if (flags & AFSCALL_RXSTATS_CLEAR) {
2585 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
2590 long cm_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp)
2595 cm_SkipIoctlPath(ioctlp);
2597 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2598 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2601 if (flags & AFSCALL_RXSTATS_ENABLE) {
2602 rx_enablePeerRPCStats();
2604 if (flags & AFSCALL_RXSTATS_DISABLE) {
2605 rx_disablePeerRPCStats();
2607 if (flags & AFSCALL_RXSTATS_CLEAR) {
2608 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
2613 long cm_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp)
2615 smb_user_t *uidp = ioctlp->uidp;
2617 if (uidp && uidp->unp) {
2618 memcpy(ioctlp->outDatap, uidp->unp->name, strlen(uidp->unp->name));
2619 ioctlp->outDatap += strlen(uidp->unp->name);
2625 long cm_IoctlUUIDControl(struct smb_ioctl * ioctlp, struct cm_user *userp)
2630 memcpy(&cmd, ioctlp->inDatap, sizeof(long));
2632 if (cmd) { /* generate a new UUID */
2633 UuidCreate((UUID *) &uuid);
2634 cm_data.Uuid = uuid;
2635 cm_ForceNewConnectionsAllServers();
2638 memcpy(ioctlp->outDatap, &cm_data.Uuid, sizeof(cm_data.Uuid));
2639 ioctlp->outDatap += sizeof(cm_data.Uuid);
2645 * functions to dump contents of various structures.
2646 * In debug build (linked with crt debug library) will dump allocated but not freed memory
2648 extern int cm_DumpSCache(FILE *outputFile, char *cookie, int lock);
2649 extern int cm_DumpBufHashTable(FILE *outputFile, char *cookie, int lock);
2650 extern int smb_DumpVCP(FILE *outputFile, char *cookie, int lock);
2652 long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
2656 char logfileName[MAX_PATH+1];
2661 static _CrtMemState memstate;
2664 cm_SkipIoctlPath(ioctlp);
2665 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
2667 dwSize = GetEnvironmentVariable("TEMP", logfileName, sizeof(logfileName));
2668 if ( dwSize == 0 || dwSize > sizeof(logfileName) )
2670 GetWindowsDirectory(logfileName, sizeof(logfileName));
2672 strncat(logfileName, "\\afsd_alloc.log", sizeof(logfileName));
2674 hLogFile = CreateFile(logfileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2680 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2681 ioctlp->outDatap += sizeof(long);
2686 SetFilePointer(hLogFile, 0, NULL, FILE_END);
2688 cookie = inValue ? "b" : "e";
2694 _CrtMemCheckpoint(&memstate);
2698 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2699 _CrtSetReportFile(_CRT_WARN, hLogFile);
2700 _CrtMemDumpAllObjectsSince(&memstate);
2704 /* dump all interesting data */
2705 cm_DumpSCache(hLogFile, cookie, 1);
2706 cm_DumpBufHashTable(hLogFile, cookie, 1);
2707 smb_DumpVCP(hLogFile, cookie, 1);
2709 CloseHandle(hLogFile);
2711 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2712 ioctlp->outDatap += sizeof(long);