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>
38 #include <..\afsrdr\kif.h>
45 /* Copied from afs_tokens.h */
46 #define PIOCTL_LOGON 0x1
49 osi_mutex_t cm_Afsdsbmt_Lock;
51 extern afs_int32 cryptall;
52 extern char cm_NetbiosName[];
54 extern void afsi_log(char *pattern, ...);
56 void cm_InitIoctl(void)
58 lock_InitializeMutex(&cm_Afsdsbmt_Lock, "AFSDSBMT.INI Access Lock");
61 long cm_CleanFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
65 lock_ObtainWrite(&scp->bufCreateLock);
66 code = buf_CleanVnode(scp, userp, reqp);
68 lock_ObtainMutex(&scp->mx);
69 cm_DiscardSCache(scp);
70 lock_ReleaseMutex(&scp->mx);
72 lock_ReleaseWrite(&scp->bufCreateLock);
73 osi_Log2(afsd_logp,"cm_CleanFile scp 0x%x returns error: [%x]",scp, code);
77 long cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
81 #ifdef AFS_FREELANCE_CLIENT
82 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
83 cm_noteLocalMountPointChange();
88 lock_ObtainWrite(&scp->bufCreateLock);
89 code = buf_FlushCleanPages(scp, userp, reqp);
91 lock_ObtainMutex(&scp->mx);
92 cm_DiscardSCache(scp);
94 lock_ReleaseMutex(&scp->mx);
96 lock_ReleaseWrite(&scp->bufCreateLock);
97 osi_Log2(afsd_logp,"cm_FlushFile scp 0x%x returns error: [%x]",scp, code);
101 long cm_FlushParent(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
106 pscp = cm_FindSCacheParent(scp);
108 /* now flush the file */
109 code = cm_FlushFile(pscp, userp, reqp);
110 cm_ReleaseSCache(pscp);
116 long cm_FlushVolume(cm_user_t *userp, cm_req_t *reqp, afs_uint32 cell, afs_uint32 volume)
122 #ifdef AFS_FREELANCE_CLIENT
123 if ( cell == AFS_FAKE_ROOT_CELL_ID && volume == AFS_FAKE_ROOT_VOL_ID ) {
124 cm_noteLocalMountPointChange();
129 lock_ObtainWrite(&cm_scacheLock);
130 for (i=0; i<cm_data.scacheHashTableSize; i++) {
131 for (scp = cm_data.scacheHashTablep[i]; scp; scp = scp->nextp) {
132 if (scp->fid.volume == volume && scp->fid.cell == cell) {
133 cm_HoldSCacheNoLock(scp);
134 lock_ReleaseWrite(&cm_scacheLock);
136 /* now flush the file */
137 code = cm_FlushFile(scp, userp, reqp);
138 lock_ObtainWrite(&cm_scacheLock);
139 cm_ReleaseSCacheNoLock(scp);
143 lock_ReleaseWrite(&cm_scacheLock);
149 * cm_ResetACLCache -- invalidate ACL info for a user that has just
150 * obtained or lost tokens
152 void cm_ResetACLCache(cm_user_t *userp)
157 lock_ObtainWrite(&cm_scacheLock);
158 for (hash=0; hash < cm_data.scacheHashTableSize; hash++) {
159 for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
160 cm_HoldSCacheNoLock(scp);
161 lock_ReleaseWrite(&cm_scacheLock);
162 lock_ObtainMutex(&scp->mx);
163 cm_InvalidateACLUser(scp, userp);
164 lock_ReleaseMutex(&scp->mx);
165 lock_ObtainWrite(&cm_scacheLock);
166 cm_ReleaseSCacheNoLock(scp);
169 lock_ReleaseWrite(&cm_scacheLock);
173 * TranslateExtendedChars - This is a fix for TR 54482.
175 * If an extended character (80 - FF) is entered into a file
176 * or directory name in Windows, the character is translated
177 * into the OEM character map before being passed to us. Why
178 * this occurs is unknown. Our pioctl functions must match
179 * this translation for paths given via our own commands (like
180 * fs). If we do not do this, then we will try to perform an
181 * operation on a non-translated path, which we will fail to
182 * find, since the path was created with the translated chars.
183 * This function performs the required translation.
185 void TranslateExtendedChars(char *str)
193 /* parse the passed-in file name and do a namei on it. If we fail,
194 * return an error code, otherwise return the vnode located in *scpp.
196 long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
201 cm_scache_t *substRootp = NULL;
202 cm_scache_t *iscp = NULL;
205 char * lastComponent = NULL;
206 afs_uint32 follow = 0;
208 relativePath = ioctlp->inDatap;
209 /* setup the next data value for the caller to use */
210 ioctlp->inDatap += (long)strlen(ioctlp->inDatap) + 1;;
212 osi_Log1(afsd_logp, "cm_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,relativePath));
214 /* This is usually the file name, but for StatMountPoint it is the path. */
215 /* ioctlp->inDatap can be either of the form:
218 * \\netbios-name\submount\path\.
219 * \\netbios-name\submount\path\file
221 TranslateExtendedChars(relativePath);
223 /* This is usually nothing, but for StatMountPoint it is the file name. */
224 TranslateExtendedChars(ioctlp->inDatap);
227 /* we have passed the whole path, including the afs prefix.
228 when the pioctl call is made, we perform an ioctl to afsrdr
229 and it returns the correct (full) path. therefore, there is
230 no drive letter, and the path is absolute. */
231 code = cm_NameI(cm_data.rootSCachep, relativePath,
232 CM_FLAG_CASEFOLD | follow,
233 userp, "", reqp, scpp);
236 osi_Log1(afsd_logp,"cm_ParseIoctlPath code 0x%x", code);
241 if (relativePath[0] == relativePath[1] &&
242 relativePath[1] == '\\' &&
243 !_strnicmp(cm_NetbiosName,relativePath+2,strlen(cm_NetbiosName)))
249 /* We may have found a UNC path.
250 * If the first component is the NetbiosName,
251 * then throw out the second component (the submount)
252 * since it had better expand into the value of ioctl->tidPathp
255 p = relativePath + 2 + strlen(cm_NetbiosName) + 1; /* buffer overflow vuln.? */
256 if ( !_strnicmp("all", p, 3) )
259 for (i = 0; *p && *p != '\\'; i++,p++ ) {
262 p++; /* skip past trailing slash */
263 shareName[i] = 0; /* terminate string */
265 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
267 /* we found a sharename, therefore use the resulting path */
268 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
269 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
270 userp, sharePath, reqp, &substRootp);
273 osi_Log1(afsd_logp,"cm_ParseIoctlPath [1] code 0x%x", code);
277 lastComponent = strrchr(p, '\\');
278 if (lastComponent && (lastComponent - p) > 1 &&strlen(lastComponent) > 1) {
279 *lastComponent = '\0';
282 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
283 userp, NULL, reqp, &iscp);
285 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | CM_FLAG_NOMOUNTCHASE,
286 userp, NULL, reqp, scpp);
288 cm_ReleaseSCache(iscp);
290 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
291 userp, NULL, reqp, scpp);
293 cm_ReleaseSCache(substRootp);
295 osi_Log1(afsd_logp,"cm_ParseIoctlPath [2] code 0x%x", code);
299 /* otherwise, treat the name as a cellname mounted off the afs root.
300 * This requires that we reconstruct the shareName string with
301 * leading and trailing slashes.
303 p = relativePath + 2 + strlen(cm_NetbiosName) + 1;
304 if ( !_strnicmp("all", p, 3) )
308 for (i = 1; *p && *p != '\\'; i++,p++ ) {
311 p++; /* skip past trailing slash */
312 shareName[i++] = '/'; /* add trailing slash */
313 shareName[i] = 0; /* terminate string */
316 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
317 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
318 userp, shareName, reqp, &substRootp);
320 osi_Log1(afsd_logp,"cm_ParseIoctlPath [3] code 0x%x", code);
324 lastComponent = strrchr(p, '\\');
325 if (lastComponent && (lastComponent - p) > 1 &&strlen(lastComponent) > 1) {
326 *lastComponent = '\0';
329 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
330 userp, NULL, reqp, &iscp);
332 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | CM_FLAG_NOMOUNTCHASE,
333 userp, NULL, reqp, scpp);
335 cm_ReleaseSCache(iscp);
337 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
338 userp, NULL, reqp, scpp);
342 cm_ReleaseSCache(substRootp);
343 osi_Log1(afsd_logp,"cm_ParseIoctlPath code [4] 0x%x", code);
348 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
349 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
350 userp, ioctlp->tidPathp, reqp, &substRootp);
352 osi_Log1(afsd_logp,"cm_ParseIoctlPath [6] code 0x%x", code);
356 lastComponent = strrchr(relativePath, '\\');
357 if (lastComponent && (lastComponent - relativePath) > 1 && strlen(lastComponent) > 1) {
358 *lastComponent = '\0';
361 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
362 userp, NULL, reqp, &iscp);
364 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | CM_FLAG_NOMOUNTCHASE,
365 userp, NULL, reqp, scpp);
367 cm_ReleaseSCache(iscp);
369 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD,
370 userp, NULL, reqp, scpp);
373 cm_ReleaseSCache(substRootp);
374 osi_Log1(afsd_logp,"cm_ParseIoctlPath [7] code 0x%x", code);
381 cm_ReleaseSCache(substRootp);
383 /* and return success */
384 osi_Log1(afsd_logp,"cm_ParseIoctlPath [8] code 0x%x", code);
388 void cm_SkipIoctlPath(smb_ioctl_t *ioctlp)
392 temp = (long) strlen(ioctlp->inDatap) + 1;
393 ioctlp->inDatap += temp;
397 /* format the specified path to look like "/afs/<cellname>/usr", by
398 * adding "/afs" (if necessary) in front, changing any \'s to /'s, and
399 * removing any trailing "/"'s. One weirdo caveat: "/afs" will be
400 * intentionally returned as "/afs/"--this makes submount manipulation
401 * easier (because we can always jump past the initial "/afs" to find
402 * the AFS path that should be written into afsdsbmt.ini).
404 void cm_NormalizeAfsPath(char *outpathp, long outlen, char *inpathp)
407 char bslash_mountRoot[256];
409 strncpy(bslash_mountRoot, cm_mountRoot, sizeof(bslash_mountRoot) - 1);
410 bslash_mountRoot[0] = '\\';
412 if (!strnicmp (inpathp, cm_mountRoot, strlen(cm_mountRoot)))
413 StringCbCopy(outpathp, outlen, inpathp);
414 else if (!strnicmp (inpathp, bslash_mountRoot, strlen(bslash_mountRoot)))
415 StringCbCopy(outpathp, outlen, inpathp);
416 else if ((inpathp[0] == '/') || (inpathp[0] == '\\'))
417 StringCbPrintfA(outpathp, outlen, "%s%s", cm_mountRoot, inpathp);
418 else // inpathp looks like "<cell>/usr"
419 StringCbPrintfA(outpathp, outlen, "%s/%s", cm_mountRoot, inpathp);
421 for (cp = outpathp; *cp != 0; ++cp) {
426 if (strlen(outpathp) && (outpathp[strlen(outpathp)-1] == '/')) {
427 outpathp[strlen(outpathp)-1] = 0;
430 if (!strcmpi (outpathp, cm_mountRoot)) {
431 StringCbCopy(outpathp, outlen, cm_mountRoot);
435 #define LEAF_SIZE 256
436 /* parse the passed-in file name and do a namei on its parent. If we fail,
437 * return an error code, otherwise return the vnode located in *scpp.
439 long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
440 cm_scache_t **scpp, char *leafp)
445 cm_scache_t *substRootp = NULL;
447 StringCbCopyA(tbuffer, sizeof(tbuffer), ioctlp->inDatap);
448 tp = strrchr(tbuffer, '\\');
449 jp = strrchr(tbuffer, '/');
452 else if (jp && (tp - tbuffer) < (jp - tbuffer))
455 StringCbCopyA(tbuffer, sizeof(tbuffer), "\\");
457 StringCbCopyA(leafp, LEAF_SIZE, ioctlp->inDatap);
462 StringCbCopyA(leafp, LEAF_SIZE, tp+1);
465 if (tbuffer[0] == tbuffer[1] &&
466 tbuffer[1] == '\\' &&
467 !_strnicmp(cm_NetbiosName,tbuffer+2,strlen(cm_NetbiosName)))
473 /* We may have found a UNC path.
474 * If the first component is the NetbiosName,
475 * then throw out the second component (the submount)
476 * since it had better expand into the value of ioctl->tidPathp
479 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
480 if ( !_strnicmp("all", p, 3) )
483 for (i = 0; *p && *p != '\\'; i++,p++ ) {
486 p++; /* skip past trailing slash */
487 shareName[i] = 0; /* terminate string */
489 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
491 /* we found a sharename, therefore use the resulting path */
492 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
493 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
494 userp, sharePath, reqp, &substRootp);
496 if (code) return code;
498 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
499 userp, NULL, reqp, scpp);
500 cm_ReleaseSCache(substRootp);
501 if (code) return code;
503 /* otherwise, treat the name as a cellname mounted off the afs root.
504 * This requires that we reconstruct the shareName string with
505 * leading and trailing slashes.
507 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
508 if ( !_strnicmp("all", p, 3) )
512 for (i = 1; *p && *p != '\\'; i++,p++ ) {
515 p++; /* skip past trailing slash */
516 shareName[i++] = '/'; /* add trailing slash */
517 shareName[i] = 0; /* terminate string */
519 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
520 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
521 userp, shareName, reqp, &substRootp);
522 if (code) return code;
524 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
525 userp, NULL, reqp, scpp);
526 cm_ReleaseSCache(substRootp);
527 if (code) return code;
530 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
531 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
532 userp, ioctlp->tidPathp, reqp, &substRootp);
533 if (code) return code;
535 code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
536 userp, NULL, reqp, scpp);
537 cm_ReleaseSCache(substRootp);
538 if (code) return code;
541 /* # of bytes of path */
542 code = (long)strlen(ioctlp->inDatap) + 1;
543 ioctlp->inDatap += code;
545 /* and return success */
549 long cm_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp)
554 AFSFetchStatus fileStatus;
560 struct rx_connection * callp;
564 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
565 if (code) return code;
567 /* now make the get acl call */
568 #ifdef AFS_FREELANCE_CLIENT
569 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
571 ioctlp->outDatap[0] ='\0';
575 fid.Volume = scp->fid.volume;
576 fid.Vnode = scp->fid.vnode;
577 fid.Unique = scp->fid.unique;
579 acl.AFSOpaque_val = ioctlp->outDatap;
580 acl.AFSOpaque_len = 0;
581 code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
584 callp = cm_GetRxConn(connp);
585 code = RXAFS_FetchACL(callp, &fid, &acl, &fileStatus, &volSync);
586 rx_PutConnection(callp);
588 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
589 code = cm_MapRPCError(code, &req);
590 cm_ReleaseSCache(scp);
592 if (code) return code;
594 /* skip over return data */
595 tlen = (int)strlen(ioctlp->outDatap) + 1;
596 ioctlp->outDatap += tlen;
598 /* and return success */
602 long cm_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp)
611 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
612 if (code) return code;
614 #ifdef AFS_FREELANCE_CLIENT
615 if ( cm_freelanceEnabled &&
616 scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
617 scp->fid.volume==AFS_FAKE_ROOT_VOL_ID &&
618 scp->fid.vnode==0x1 && scp->fid.unique==0x1 ) {
619 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "Freelance.Local.Root");
620 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
623 #endif /* AFS_FREELANCE_CLIENT */
625 cellp = cm_FindCellByID(scp->fid.cell);
627 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), cellp->name);
628 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
632 code = CM_ERROR_NOSUCHCELL;
635 cm_ReleaseSCache(scp);
639 long cm_IoctlSetACL(struct smb_ioctl *ioctlp, struct cm_user *userp)
644 AFSFetchStatus fileStatus;
649 struct rx_connection * callp;
653 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
654 if (code) return code;
656 #ifdef AFS_FREELANCE_CLIENT
657 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
658 code = CM_ERROR_NOACCESS;
662 /* now make the get acl call */
663 fid.Volume = scp->fid.volume;
664 fid.Vnode = scp->fid.vnode;
665 fid.Unique = scp->fid.unique;
667 acl.AFSOpaque_val = ioctlp->inDatap;
668 acl.AFSOpaque_len = (u_int)strlen(ioctlp->inDatap)+1;
669 code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
672 callp = cm_GetRxConn(connp);
673 code = RXAFS_StoreACL(callp, &fid, &acl, &fileStatus, &volSync);
674 rx_PutConnection(callp);
676 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
677 code = cm_MapRPCError(code, &req);
679 /* invalidate cache info, since we just trashed the ACL cache */
680 lock_ObtainMutex(&scp->mx);
681 cm_DiscardSCache(scp);
682 lock_ReleaseMutex(&scp->mx);
684 cm_ReleaseSCache(scp);
691 long cm_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
700 lock_ObtainWrite(&cm_scacheLock);
701 for (i=0; i<cm_data.scacheHashTableSize; i++) {
702 for (scp = cm_data.scacheHashTablep[i]; scp; scp = scp->nextp) {
703 cm_HoldSCacheNoLock(scp);
704 lock_ReleaseWrite(&cm_scacheLock);
706 /* now flush the file */
707 code = cm_FlushFile(scp, userp, &req);
708 lock_ObtainWrite(&cm_scacheLock);
709 cm_ReleaseSCacheNoLock(scp);
712 lock_ReleaseWrite(&cm_scacheLock);
717 long cm_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp)
721 unsigned long volume;
727 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
728 if (code) return code;
730 #ifdef AFS_FREELANCE_CLIENT
731 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
732 code = CM_ERROR_NOACCESS;
736 volume = scp->fid.volume;
737 cell = scp->fid.cell;
738 cm_ReleaseSCache(scp);
740 code = cm_FlushVolume(userp, &req, cell, volume);
745 long cm_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp)
753 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
754 if (code) return code;
756 #ifdef AFS_FREELANCE_CLIENT
757 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
758 code = CM_ERROR_NOACCESS;
762 cm_FlushFile(scp, userp, &req);
764 cm_ReleaseSCache(scp);
769 long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
773 char offLineMsg[256];
777 AFSFetchVolumeStatus volStat;
778 AFSStoreVolumeStatus storeStat;
783 struct rx_connection * callp;
787 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
788 if (code) return code;
790 #ifdef AFS_FREELANCE_CLIENT
791 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
792 code = CM_ERROR_NOACCESS;
796 cellp = cm_FindCellByID(scp->fid.cell);
797 osi_assertx(cellp, "null cm_cell_t");
799 if (scp->flags & CM_SCACHEFLAG_RO) {
800 cm_ReleaseSCache(scp);
801 return CM_ERROR_READONLY;
804 code = cm_GetVolumeByID(cellp, scp->fid.volume, userp, &req,
805 CM_GETVOL_FLAG_CREATE, &tvp);
807 cm_ReleaseSCache(scp);
812 /* Copy the junk out, using cp as a roving pointer. */
813 cp = ioctlp->inDatap;
814 memcpy((char *)&volStat, cp, sizeof(AFSFetchVolumeStatus));
815 cp += sizeof(AFSFetchVolumeStatus);
816 StringCbCopyA(volName, sizeof(volName), cp);
817 cp += strlen(volName)+1;
818 StringCbCopyA(offLineMsg, sizeof(offLineMsg), cp);
819 cp += strlen(offLineMsg)+1;
820 StringCbCopyA(motd, sizeof(motd), cp);
822 if (volStat.MinQuota != -1) {
823 storeStat.MinQuota = volStat.MinQuota;
824 storeStat.Mask |= AFS_SETMINQUOTA;
826 if (volStat.MaxQuota != -1) {
827 storeStat.MaxQuota = volStat.MaxQuota;
828 storeStat.Mask |= AFS_SETMAXQUOTA;
832 code = cm_ConnFromFID(&scp->fid, userp, &req, &tcp);
835 callp = cm_GetRxConn(tcp);
836 code = RXAFS_SetVolumeStatus(callp, scp->fid.volume,
837 &storeStat, volName, offLineMsg, motd);
838 rx_PutConnection(callp);
840 } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
841 code = cm_MapRPCError(code, &req);
844 /* return on failure */
845 cm_ReleaseSCache(scp);
850 /* we are sending parms back to make compat. with prev system. should
851 * change interface later to not ask for current status, just set
854 cp = ioctlp->outDatap;
855 memcpy(cp, (char *)&volStat, sizeof(VolumeStatus));
856 cp += sizeof(VolumeStatus);
857 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), volName);
858 cp += strlen(volName)+1;
859 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), offLineMsg);
860 cp += strlen(offLineMsg)+1;
861 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), motd);
862 cp += strlen(motd)+1;
864 /* now return updated return data pointer */
865 ioctlp->outDatap = cp;
870 long cm_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
874 char offLineMsg[256];
878 AFSFetchVolumeStatus volStat;
884 struct rx_connection * callp;
888 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
889 if (code) return code;
891 #ifdef AFS_FREELANCE_CLIENT
892 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
894 strncpy(volName, "Freelance.Local.Root", sizeof(volName));
895 offLineMsg[0] = '\0';
896 strncpy(motd, "Freelance mode in use.", sizeof(motd));
897 volStat.Vid = scp->fid.volume;
898 volStat.MaxQuota = 0;
899 volStat.BlocksInUse = 100;
900 volStat.PartBlocksAvail = 0;
901 volStat.PartMaxBlocks = 100;
906 OfflineMsg = offLineMsg;
909 code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
912 callp = cm_GetRxConn(connp);
913 code = RXAFS_GetVolumeStatus(callp, scp->fid.volume,
914 &volStat, &Name, &OfflineMsg, &MOTD);
915 rx_PutConnection(callp);
917 } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
918 code = cm_MapRPCError(code, &req);
921 cm_ReleaseSCache(scp);
922 if (code) return code;
924 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
925 cp = ioctlp->outDatap;
926 memcpy(cp, (char *)&volStat, sizeof(AFSFetchVolumeStatus));
927 cp += sizeof(AFSFetchVolumeStatus);
928 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), volName);
929 cp += strlen(volName)+1;
930 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), offLineMsg);
931 cp += strlen(offLineMsg)+1;
932 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), motd);
933 cp += strlen(motd)+1;
935 /* return new size */
936 ioctlp->outDatap = cp;
941 long cm_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp)
951 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
952 if (code) return code;
954 memset(&fid, 0, sizeof(cm_fid_t));
955 fid.volume = scp->fid.volume;
956 fid.vnode = scp->fid.vnode;
957 fid.unique = scp->fid.unique;
959 cm_ReleaseSCache(scp);
961 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
962 cp = ioctlp->outDatap;
963 memcpy(cp, (char *)&fid, sizeof(cm_fid_t));
964 cp += sizeof(cm_fid_t);
966 /* return new size */
967 ioctlp->outDatap = cp;
972 long cm_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp)
981 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
982 if (code) return code;
984 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
985 cp = ioctlp->outDatap;
986 memcpy(cp, (char *)&scp->owner, sizeof(afs_uint32));
987 cp += sizeof(afs_uint32);
988 memcpy(cp, (char *)&scp->group, sizeof(afs_uint32));
989 cp += sizeof(afs_uint32);
991 /* return new size */
992 ioctlp->outDatap = cp;
994 cm_ReleaseSCache(scp);
999 long cm_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1005 cm_serverRef_t **tsrpp, *current;
1007 unsigned long volume;
1013 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
1014 if (code) return code;
1016 volume = scp->fid.volume;
1018 cellp = cm_FindCellByID(scp->fid.cell);
1020 cm_ReleaseSCache(scp);
1023 return CM_ERROR_NOSUCHCELL;
1025 code = cm_GetVolumeByID(cellp, volume, userp, &req, CM_GETVOL_FLAG_CREATE, &tvp);
1029 cp = ioctlp->outDatap;
1031 lock_ObtainMutex(&tvp->mx);
1032 tsrpp = cm_GetVolServers(tvp, volume);
1033 lock_ObtainRead(&cm_serverLock);
1034 for (current = *tsrpp; current; current = current->next) {
1035 tsp = current->server;
1036 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
1039 lock_ReleaseRead(&cm_serverLock);
1040 cm_FreeServerList(tsrpp, 0);
1041 lock_ReleaseMutex(&tvp->mx);
1043 /* still room for terminating NULL, add it on */
1044 volume = 0; /* reuse vbl */
1045 memcpy(cp, (char *)&volume, sizeof(long));
1048 ioctlp->outDatap = cp;
1053 long cm_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1063 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1064 if (code) return code;
1066 cp = ioctlp->inDatap;
1068 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1069 cm_ReleaseSCache(dscp);
1070 if (code) return code;
1072 lock_ObtainMutex(&scp->mx);
1074 /* now check that this is a real mount point */
1075 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
1076 lock_ReleaseMutex(&scp->mx);
1077 cm_ReleaseSCache(scp);
1078 return CM_ERROR_INVAL;
1081 code = cm_ReadMountPoint(scp, userp, &req);
1083 cp = ioctlp->outDatap;
1084 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), scp->mountPointStringp);
1085 cp += strlen(cp) + 1;
1086 ioctlp->outDatap = cp;
1088 lock_ReleaseMutex(&scp->mx);
1089 cm_ReleaseSCache(scp);
1094 long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1104 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1105 if (code) return code;
1107 cp = ioctlp->inDatap;
1109 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1111 /* if something went wrong, bail out now */
1116 lock_ObtainMutex(&scp->mx);
1117 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1118 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1120 lock_ReleaseMutex(&scp->mx);
1121 cm_ReleaseSCache(scp);
1125 /* now check that this is a real mount point */
1126 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
1127 lock_ReleaseMutex(&scp->mx);
1128 cm_ReleaseSCache(scp);
1129 code = CM_ERROR_INVAL;
1133 /* time to make the RPC, so drop the lock */
1134 lock_ReleaseMutex(&scp->mx);
1135 cm_ReleaseSCache(scp);
1137 /* easier to do it this way */
1138 code = cm_Unlink(dscp, cp, userp, &req);
1139 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1140 smb_NotifyChange(FILE_ACTION_REMOVED,
1141 FILE_NOTIFY_CHANGE_DIR_NAME,
1142 dscp, cp, NULL, TRUE);
1145 lock_ObtainMutex(&scp->mx);
1146 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1147 lock_ReleaseMutex(&scp->mx);
1150 cm_ReleaseSCache(dscp);
1154 long cm_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp)
1164 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1165 tp = ioctlp->inDatap;
1168 memcpy(&temp, tp, sizeof(temp));
1169 if (temp == 0x12345678) { /* For afs3.3 version */
1170 memcpy(&csi, tp, sizeof(csi));
1171 if (csi.tinterval >= 0) {
1172 cp = ioctlp->outDatap;
1173 memcpy(cp, (char *)&cm_daemonCheckDownInterval, sizeof(long));
1174 ioctlp->outDatap += sizeof(long);
1175 if (csi.tinterval > 0) {
1176 if (!smb_SUser(userp))
1177 return CM_ERROR_NOACCESS;
1178 cm_daemonCheckDownInterval = csi.tinterval;
1186 } else { /* For pre afs3.3 versions */
1187 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
1188 ioctlp->inDatap = cp = ioctlp->inDatap + sizeof(long);
1189 if (cp - ioctlp->inAllocp < ioctlp->inCopied) /* still more data available */
1194 * 1: fast check, don't contact servers.
1195 * 2: local cell only.
1198 /* have cell name, too */
1199 cellp = cm_GetCell(cp, 0);
1201 return CM_ERROR_NOSUCHCELL;
1203 else cellp = (cm_cell_t *) 0;
1204 if (!cellp && (temp & 2)) {
1205 /* use local cell */
1206 cellp = cm_FindCellByID(1);
1208 if (!(temp & 1)) { /* if not fast, call server checker routine */
1209 /* check down servers */
1210 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS | CM_FLAG_CHECKUPSERVERS,
1214 /* now return the current down server list */
1215 cp = ioctlp->outDatap;
1216 lock_ObtainRead(&cm_serverLock);
1217 for (tsp = cm_allServersp; tsp; tsp=tsp->allNextp) {
1218 if (cellp && tsp->cellp != cellp) continue; /* cell spec'd and wrong */
1219 if ((tsp->flags & CM_SERVERFLAG_DOWN)
1220 && tsp->type == CM_SERVER_FILE) {
1221 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
1225 lock_ReleaseRead(&cm_serverLock);
1227 ioctlp->outDatap = cp;
1231 long cm_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp)
1233 /* we don't print anything superfluous, so we don't support the gag call */
1234 return CM_ERROR_INVAL;
1237 long cm_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
1239 cm_RefreshVolumes();
1243 long cm_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp)
1248 cm_SkipIoctlPath(ioctlp);
1250 memcpy(&temp, ioctlp->inDatap, sizeof(temp));
1252 temp = cm_data.buf_nOrigBuffers;
1254 /* temp is in 1K units, convert to # of buffers */
1255 temp = temp / (cm_data.buf_blockSize / 1024);
1258 /* now adjust the cache size */
1259 code = buf_SetNBuffers(temp);
1264 long cm_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
1268 cm_SkipIoctlPath(ioctlp);
1270 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
1274 afsd_ForceTrace(FALSE);
1275 buf_ForceTrace(FALSE);
1279 /* set tracing value to low order bit */
1280 if ((inValue & 1) == 0) {
1281 /* disable tracing */
1282 osi_LogDisable(afsd_logp);
1283 rx_DebugOnOff(FALSE);
1286 /* enable tracing */
1287 osi_LogEnable(afsd_logp);
1288 rx_DebugOnOff(TRUE);
1292 /* see if we're supposed to do a reset, too */
1294 osi_LogReset(afsd_logp);
1297 /* and copy out tracing flag */
1298 inValue = afsd_logp->enabled; /* use as a temp vbl */
1299 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
1300 ioctlp->outDatap += sizeof(long);
1304 long cm_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp)
1306 cm_cacheParms_t parms;
1308 memset(&parms, 0, sizeof(parms));
1310 /* first we get, in 1K units, the cache size */
1311 parms.parms[0] = cm_data.buf_nbuffers * (cm_data.buf_blockSize / 1024);
1313 /* and then the actual # of buffers in use (not in the free list, I guess,
1314 * will be what we do).
1316 parms.parms[1] = (cm_data.buf_nbuffers - buf_CountFreeList()) * (cm_data.buf_blockSize / 1024);
1318 memcpy(ioctlp->outDatap, &parms, sizeof(parms));
1319 ioctlp->outDatap += sizeof(parms);
1324 long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1329 cm_serverRef_t *serverRefp;
1330 cm_server_t *serverp;
1336 cm_SkipIoctlPath(ioctlp);
1338 tp = ioctlp->inDatap;
1340 memcpy((char *)&whichCell, tp, sizeof(long));
1343 /* see if more than one long passed in, ignoring the null pathname (the -1) */
1344 if (ioctlp->inCopied-1 > sizeof(long)) {
1345 memcpy((char *)&magic, tp, sizeof(long));
1348 lock_ObtainRead(&cm_cellLock);
1349 for (tcellp = cm_data.allCellsp; tcellp; tcellp = tcellp->allNextp) {
1350 if (whichCell == 0) break;
1353 lock_ReleaseRead(&cm_cellLock);
1357 cp = ioctlp->outDatap;
1359 if (magic == 0x12345678) {
1360 memcpy(cp, (char *)&magic, sizeof(long));
1363 memset(cp, 0, max * sizeof(long));
1365 lock_ObtainRead(&cm_serverLock); /* for going down server list */
1366 /* jaltman - do the reference counts to serverRefp contents need to be increased? */
1367 serverRefp = tcellp->vlServersp;
1368 for (i=0; i<max; i++) {
1369 if (!serverRefp) break;
1370 serverp = serverRefp->server;
1371 memcpy(cp, &serverp->addr.sin_addr.s_addr, sizeof(long));
1373 serverRefp = serverRefp->next;
1375 lock_ReleaseRead(&cm_serverLock);
1376 cp = basep + max * sizeof(afs_int32);
1377 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), tcellp->name);
1378 cp += strlen(tcellp->name)+1;
1379 ioctlp->outDatap = cp;
1385 return CM_ERROR_NOMORETOKENS; /* mapped to EDOM */
1388 extern long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *namep);
1390 long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1392 /* NT cache manager will read cell information from CellServDB each time
1393 * cell is accessed. So, this call is necessary only if list of server for a cell
1394 * changes (or IP addresses of cell servers changes).
1395 * All that needs to be done is to refresh server information for all cells that
1396 * are already loaded.
1398 * cell list will be cm_CellLock and cm_ServerLock will be held for write.
1403 cm_SkipIoctlPath(ioctlp);
1404 lock_ObtainWrite(&cm_cellLock);
1406 for (cp = cm_data.allCellsp; cp; cp=cp->allNextp)
1409 lock_ObtainMutex(&cp->mx);
1410 /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
1411 cm_FreeServerList(&cp->vlServersp, CM_FREESERVERLIST_DELETE);
1412 cp->vlServersp = NULL;
1413 code = cm_SearchCellFile(cp->name, cp->name, cm_AddCellProc, cp);
1414 #ifdef AFS_AFSDB_ENV
1416 if (cm_dnsEnabled) {
1418 code = cm_SearchCellByDNS(cp->name, cp->name, &ttl, cm_AddCellProc, cp);
1419 if ( code == 0 ) { /* got cell from DNS */
1420 cp->flags |= CM_CELLFLAG_DNS;
1421 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1422 cp->timeout = time(0) + ttl;
1427 cp->flags &= ~CM_CELLFLAG_DNS;
1429 #endif /* AFS_AFSDB_ENV */
1431 cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
1434 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1435 cm_RandomizeServer(&cp->vlServersp);
1437 lock_ReleaseMutex(&cp->mx);
1440 lock_ReleaseWrite(&cm_cellLock);
1444 long cm_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
1448 if (cm_freelanceEnabled) {
1449 if (cm_GetRootCellName(ioctlp->outDatap))
1450 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "Freelance.Local.Root");
1451 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1452 } else if (cm_data.rootCellp) {
1453 /* return the default cellname to the caller */
1454 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), cm_data.rootCellp->name);
1455 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1457 /* if we don't know our default cell, return failure */
1458 code = CM_ERROR_NOSUCHCELL;
1464 long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp)
1466 long setSysName, foundname = 0;
1467 char *cp, *cp2, inname[MAXSYSNAME], outname[MAXSYSNAME];
1468 int t, count, num = 0;
1469 char **sysnamelist[MAXSYSNAME];
1471 cm_SkipIoctlPath(ioctlp);
1473 memcpy(&setSysName, ioctlp->inDatap, sizeof(long));
1474 ioctlp->inDatap += sizeof(long);
1478 if ( setSysName < 0 || setSysName > MAXNUMSYSNAMES )
1480 cp2 = ioctlp->inDatap;
1481 for ( cp=ioctlp->inDatap, count = 0; count < setSysName; count++ ) {
1482 /* won't go past end of ioctlp->inDatap since maxsysname*num < ioctlp->inDatap length */
1483 t = (int)strlen(cp);
1484 if (t >= MAXSYSNAME || t <= 0)
1486 /* check for names that can shoot us in the foot */
1487 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
1493 /* inname gets first entry in case we're being a translator */
1494 /* (we are never a translator) */
1495 t = (int)strlen(ioctlp->inDatap);
1496 memcpy(inname, ioctlp->inDatap, t + 1);
1497 ioctlp->inDatap += t + 1;
1501 /* Not xlating, so local case */
1503 osi_panic("cm_IoctlSysName: !cm_sysName\n", __FILE__, __LINE__);
1505 if (!setSysName) { /* user just wants the info */
1506 StringCbCopyA(outname, sizeof(outname), cm_sysName);
1507 foundname = cm_sysNameCount;
1508 *sysnamelist = cm_sysNameList;
1510 /* Local guy; only root can change sysname */
1511 /* clear @sys entries from the dnlc, once afs_lookup can
1512 * do lookups of @sys entries and thinks it can trust them */
1513 /* privs ok, store the entry, ... */
1514 StringCbCopyA(cm_sysName, sizeof(cm_sysName), inname);
1515 StringCbCopyA(cm_sysNameList[0], MAXSYSNAME, inname);
1516 if (setSysName > 1) { /* ... or list */
1517 cp = ioctlp->inDatap;
1518 for (count = 1; count < setSysName; ++count) {
1519 if (!cm_sysNameList[count])
1520 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to write\n",
1521 __FILE__, __LINE__);
1522 t = (int)strlen(cp);
1523 StringCbCopyA(cm_sysNameList[count], MAXSYSNAME, cp);
1527 cm_sysNameCount = setSysName;
1531 /* return the sysname to the caller */
1532 cp = ioctlp->outDatap;
1533 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
1534 cp += sizeof(afs_int32); /* skip found flag */
1536 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), outname);
1537 cp += strlen(outname) + 1; /* skip name and terminating null char */
1538 for ( count=1; count < foundname ; ++count) { /* ... or list */
1539 if ( !(*sysnamelist)[count] )
1540 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to read\n",
1541 __FILE__, __LINE__);
1542 t = (int)strlen((*sysnamelist)[count]);
1543 if (t >= MAXSYSNAME)
1544 osi_panic("cm_IoctlSysName: sysname entry garbled\n",
1545 __FILE__, __LINE__);
1546 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), (*sysnamelist)[count]);
1550 ioctlp->outDatap = cp;
1557 long cm_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1562 cm_SkipIoctlPath(ioctlp);
1564 cellp = cm_GetCell(ioctlp->inDatap, 0);
1566 return CM_ERROR_NOSUCHCELL;
1569 lock_ObtainMutex(&cellp->mx);
1570 if (cellp->flags & CM_CELLFLAG_SUID)
1571 temp |= CM_SETCELLFLAG_SUID;
1572 lock_ReleaseMutex(&cellp->mx);
1574 /* now copy out parm */
1575 memcpy(ioctlp->outDatap, &temp, sizeof(long));
1576 ioctlp->outDatap += sizeof(long);
1581 long cm_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1586 cm_SkipIoctlPath(ioctlp);
1588 cellp = cm_GetCell(ioctlp->inDatap + 2*sizeof(long), 0);
1590 return CM_ERROR_NOSUCHCELL;
1592 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
1594 lock_ObtainMutex(&cellp->mx);
1595 if (temp & CM_SETCELLFLAG_SUID)
1596 cellp->flags |= CM_CELLFLAG_SUID;
1598 cellp->flags &= ~CM_CELLFLAG_SUID;
1599 lock_ReleaseMutex(&cellp->mx);
1604 long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1606 cm_SSetPref_t *spin; /* input */
1607 cm_SPref_t *srvin; /* one input component */
1609 int i, vlonly, noServers, type;
1610 struct sockaddr_in tmp;
1611 unsigned short rank;
1613 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1615 spin = (cm_SSetPref_t *)ioctlp->inDatap;
1616 noServers = spin->num_servers;
1617 vlonly = spin->flags;
1619 type = CM_SERVER_VLDB;
1621 type = CM_SERVER_FILE;
1623 for ( i=0; i < noServers; i++)
1625 srvin = &(spin->servers[i]);
1626 rank = srvin->rank + (rand() & 0x000f);
1627 tmp.sin_addr = srvin->host;
1628 tmp.sin_family = AF_INET;
1630 tsp = cm_FindServer(&tmp, type);
1631 if ( tsp ) /* an existing server - ref count increased */
1633 tsp->ipRank = rank; /* no need to protect by mutex*/
1635 if (type == CM_SERVER_FILE)
1637 /* find volumes which might have RO copy
1638 /* on server and change the ordering of
1641 cm_ChangeRankVolume(tsp);
1645 /* set preferences for an existing vlserver */
1646 cm_ChangeRankCellVLServer(tsp);
1649 else /* add a new server without a cell */
1651 tsp = cm_NewServer(&tmp, type, NULL); /* refcount = 1 */
1654 lock_ObtainMutex(&tsp->mx);
1655 tsp->flags |= CM_SERVERFLAG_PREF_SET;
1656 lock_ReleaseMutex(&tsp->mx);
1657 cm_PutServer(tsp); /* decrease refcount */
1662 long cm_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1664 cm_SPrefRequest_t *spin; /* input */
1665 cm_SPrefInfo_t *spout; /* output */
1666 cm_SPref_t *srvout; /* one output component */
1668 int i, vlonly, noServers;
1670 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1672 spin = (cm_SPrefRequest_t *)ioctlp->inDatap;
1673 spout = (cm_SPrefInfo_t *) ioctlp->outDatap;
1674 srvout = spout->servers;
1675 noServers = spin->num_servers;
1676 vlonly = spin->flags & CM_SPREF_VLONLY;
1677 spout->num_servers = 0;
1679 lock_ObtainRead(&cm_serverLock); /* get server lock */
1681 for (tsp=cm_allServersp, i=0; tsp && noServers; tsp=tsp->allNextp,i++){
1682 if (spin->offset > i) {
1683 continue; /* catch up to where we left off */
1686 if ( vlonly && (tsp->type == CM_SERVER_FILE) )
1687 continue; /* ignore fileserver for -vlserver option*/
1688 if ( !vlonly && (tsp->type == CM_SERVER_VLDB) )
1689 continue; /* ignore vlservers */
1691 srvout->host = tsp->addr.sin_addr;
1692 srvout->rank = tsp->ipRank;
1694 spout->num_servers++;
1697 lock_ReleaseRead(&cm_serverLock); /* release server lock */
1699 if ( tsp ) /* we ran out of space in the output buffer */
1700 spout->next_offset = i;
1702 spout->next_offset = 0;
1703 ioctlp->outDatap += sizeof(cm_SPrefInfo_t) +
1704 (spout->num_servers -1 ) * sizeof(cm_SPref_t) ;
1708 long cm_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp)
1710 /* we ignore default asynchrony since we only have one way
1711 * of doing this today.
1716 long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1718 char leaf[LEAF_SIZE];
1732 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1736 /* Translate chars for the mount point name */
1737 TranslateExtendedChars(leaf);
1740 * The fs command allows the user to specify partial cell names on NT. These must
1741 * be expanded to the full cell name for mount points so that the mount points will
1742 * work on UNIX clients.
1745 /* Extract the possibly partial cell name */
1746 StringCbCopyA(cell, sizeof(cell), ioctlp->inDatap + 1); /* Skip the mp type character */
1748 if (cp = strchr(cell, ':')) {
1749 /* Extract the volume name */
1751 StringCbCopyA(volume, sizeof(volume), cp + 1);
1753 /* Get the full name for this cell */
1754 code = cm_SearchCellFile(cell, fullCell, 0, 0);
1755 #ifdef AFS_AFSDB_ENV
1756 if (code && cm_dnsEnabled)
1757 code = cm_SearchCellByDNS(cell, fullCell, &ttl, 0, 0);
1760 cm_ReleaseSCache(dscp);
1761 return CM_ERROR_NOSUCHCELL;
1764 StringCbPrintfA(mpInfo, sizeof(mpInfo), "%c%s:%s", *ioctlp->inDatap, fullCell, volume);
1766 /* No cell name specified */
1767 StringCbCopyA(mpInfo, sizeof(mpInfo), ioctlp->inDatap);
1770 #ifdef AFS_FREELANCE_CLIENT
1771 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1772 /* we are adding the mount point to the root dir., so call
1773 * the freelance code to do the add. */
1774 osi_Log0(afsd_logp,"IoctlCreateMountPoint within Freelance root dir");
1775 code = cm_FreelanceAddMount(leaf, fullCell, volume,
1776 *ioctlp->inDatap == '%', NULL);
1777 cm_ReleaseSCache(dscp);
1781 /* create the symlink with mode 644. The lack of X bits tells
1782 * us that it is a mount point.
1784 tattr.mask = CM_ATTRMASK_UNIXMODEBITS | CM_ATTRMASK_CLIENTMODTIME;
1785 tattr.unixModeBits = 0644;
1786 tattr.clientModTime = time(NULL);
1788 code = cm_SymLink(dscp, leaf, mpInfo, 0, &tattr, userp, &req);
1789 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1790 smb_NotifyChange(FILE_ACTION_ADDED,
1791 FILE_NOTIFY_CHANGE_DIR_NAME,
1792 dscp, leaf, NULL, TRUE);
1794 cm_ReleaseSCache(dscp);
1798 long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1800 char leaf[LEAF_SIZE];
1809 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1810 if (code) return code;
1812 /* Translate chars for the link name */
1813 TranslateExtendedChars(leaf);
1815 /* Translate chars for the linked to name */
1816 TranslateExtendedChars(ioctlp->inDatap);
1818 cp = ioctlp->inDatap; /* contents of link */
1820 #ifdef AFS_FREELANCE_CLIENT
1821 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1822 /* we are adding the symlink to the root dir., so call
1823 * the freelance code to do the add. */
1824 if (cp[0] == cp[1] && cp[1] == '\\' &&
1825 !_strnicmp(cm_NetbiosName,cp+2,strlen(cm_NetbiosName)))
1827 /* skip \\AFS\ or \\AFS\all\ */
1829 p = cp + 2 + strlen(cm_NetbiosName) + 1;
1830 if ( !_strnicmp("all", p, 3) )
1834 osi_Log0(afsd_logp,"IoctlCreateSymlink within Freelance root dir");
1835 code = cm_FreelanceAddSymlink(leaf, cp, NULL);
1836 cm_ReleaseSCache(dscp);
1841 /* Create symlink with mode 0755. */
1842 tattr.mask = CM_ATTRMASK_UNIXMODEBITS;
1843 tattr.unixModeBits = 0755;
1845 code = cm_SymLink(dscp, leaf, cp, 0, &tattr, userp, &req);
1846 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1847 smb_NotifyChange(FILE_ACTION_ADDED,
1848 FILE_NOTIFY_CHANGE_FILE_NAME
1849 | FILE_NOTIFY_CHANGE_DIR_NAME,
1850 dscp, leaf, NULL, TRUE);
1852 cm_ReleaseSCache(dscp);
1858 long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1865 cm_scache_t *newRootScp;
1870 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1871 if (code) return code;
1873 cp = ioctlp->inDatap;
1875 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1876 cm_ReleaseSCache(dscp);
1877 if (code) return code;
1879 /* Check that it's a real symlink */
1880 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1881 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1882 scp->fileType != CM_SCACHETYPE_INVALID) {
1883 cm_ReleaseSCache(scp);
1884 return CM_ERROR_INVAL;
1887 code = cm_AssembleLink(scp, "", &newRootScp, &spacep, userp, &req);
1888 cm_ReleaseSCache(scp);
1890 cp = ioctlp->outDatap;
1891 if (newRootScp != NULL) {
1892 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), cm_mountRoot);
1893 StringCbCatA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), "/");
1896 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), spacep->data);
1897 cp += strlen(cp) + 1;
1898 ioctlp->outDatap = cp;
1899 cm_FreeSpace(spacep);
1900 if (newRootScp != NULL)
1901 cm_ReleaseSCache(newRootScp);
1903 } else if (code == CM_ERROR_PATH_NOT_COVERED &&
1904 scp->fileType == CM_SCACHETYPE_DFSLINK ||
1905 code == CM_ERROR_NOSUCHPATH &&
1906 scp->fileType == CM_SCACHETYPE_INVALID) {
1908 cp = ioctlp->outDatap;
1909 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), scp->mountPointStringp);
1910 cp += strlen(cp) + 1;
1911 ioctlp->outDatap = cp;
1918 long cm_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1919 {/*CHECK FOR VALID SYMLINK*/
1928 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1929 if (code) return code;
1931 cp = ioctlp->inDatap;
1932 osi_LogEvent("cm_IoctlListlink",NULL," name[%s]",cp);
1934 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1935 cm_ReleaseSCache(dscp);
1936 if (code) return code;
1938 /* Check that it's a real symlink */
1939 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1940 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1941 scp->fileType != CM_SCACHETYPE_INVALID)
1942 code = CM_ERROR_INVAL;
1943 cm_ReleaseSCache(scp);
1947 long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1957 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1958 if (code) return code;
1960 cp = ioctlp->inDatap;
1962 #ifdef AFS_FREELANCE_CLIENT
1963 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1964 /* we are adding the mount point to the root dir., so call
1965 * the freelance code to do the add. */
1966 osi_Log0(afsd_logp,"IoctlDeletelink from Freelance root dir");
1967 code = cm_FreelanceRemoveSymlink(cp);
1968 cm_ReleaseSCache(dscp);
1973 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1975 /* if something went wrong, bail out now */
1979 lock_ObtainMutex(&scp->mx);
1980 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1981 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1985 /* now check that this is a real symlink */
1986 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1987 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1988 scp->fileType != CM_SCACHETYPE_INVALID) {
1989 code = CM_ERROR_INVAL;
1993 /* time to make the RPC, so drop the lock */
1994 lock_ReleaseMutex(&scp->mx);
1996 /* easier to do it this way */
1997 code = cm_Unlink(dscp, cp, userp, &req);
1998 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1999 smb_NotifyChange(FILE_ACTION_REMOVED,
2000 FILE_NOTIFY_CHANGE_FILE_NAME
2001 | FILE_NOTIFY_CHANGE_DIR_NAME,
2002 dscp, cp, NULL, TRUE);
2004 lock_ObtainMutex(&scp->mx);
2006 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2009 lock_ReleaseMutex(&scp->mx);
2010 cm_ReleaseSCache(scp);
2013 cm_ReleaseSCache(dscp);
2018 long cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid)
2023 static struct afsconf_cell info;
2024 struct rx_connection *serverconns[MAXSERVERS];
2025 struct rx_securityClass *sc[3];
2026 afs_int32 scIndex = 2; /* authenticated - we have a token */
2027 struct ubik_client *pruclient = NULL;
2028 struct afsconf_dir *tdir;
2032 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
2033 code = afsconf_GetCellInfo(tdir, ucellp->cellp->name, "afsprot", &info);
2034 afsconf_Close(tdir);
2040 /* we have the token that was given to us in the settoken
2041 * call. we just have to use it.
2043 scIndex = 2; /* kerberos ticket */
2044 sc[2] = rxkad_NewClientSecurityObject(rxkad_clear, &ucellp->sessionKey,
2045 ucellp->kvno, ucellp->ticketLen,
2048 memset(serverconns, 0, sizeof(serverconns)); /* terminate list!!! */
2049 for (i = 0; i < info.numServers; i++)
2051 rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
2052 info.hostAddr[i].sin_port, PRSRV, sc[scIndex],
2055 code = ubik_ClientInit(serverconns, &pruclient);
2060 code = rxs_Release(sc[scIndex]);
2062 lids.idlist_len = 0;
2063 lids.idlist_val = 0;
2064 lnames.namelist_len = 1;
2065 lnames.namelist_val = (prname *) malloc(PR_MAXNAMELEN);
2066 strncpy(lnames.namelist_val[0], uname, PR_MAXNAMELEN);
2067 lnames.namelist_val[0][PR_MAXNAMELEN-1] = '\0';
2068 for ( p=lnames.namelist_val[0], r=NULL; *p; p++ ) {
2074 if (r && !stricmp(r+1,ucellp->cellp->name))
2077 code = ubik_PR_NameToID(pruclient, 0, &lnames, &lids);
2078 if (lids.idlist_val) {
2079 *uid = *lids.idlist_val;
2080 free(lids.idlist_val);
2082 if (lnames.namelist_val)
2083 free(lnames.namelist_val);
2086 ubik_ClientDestroy(pruclient);
2092 #endif /* QUERY_AFSID */
2094 long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2101 struct ClearToken ct;
2111 int release_userp = 0;
2114 saveDataPtr = ioctlp->inDatap;
2116 cm_SkipIoctlPath(ioctlp);
2118 tp = ioctlp->inDatap;
2121 memcpy(&ticketLen, tp, sizeof(ticketLen));
2122 tp += sizeof(ticketLen);
2123 if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN)
2124 return CM_ERROR_INVAL;
2126 /* remember ticket and skip over it for now */
2130 /* clear token size */
2131 memcpy(&ctSize, tp, sizeof(ctSize));
2132 tp += sizeof(ctSize);
2133 if (ctSize != sizeof(struct ClearToken))
2134 return CM_ERROR_INVAL;
2137 memcpy(&ct, tp, ctSize);
2139 if (ct.AuthHandle == -1)
2140 ct.AuthHandle = 999; /* more rxvab compat stuff */
2142 /* more stuff, if any */
2143 if (ioctlp->inCopied > tp - saveDataPtr) {
2144 /* flags: logon flag */
2145 memcpy(&flags, tp, sizeof(int));
2149 cellp = cm_GetCell(tp, CM_FLAG_CREATE);
2151 return CM_ERROR_NOSUCHCELL;
2152 tp += strlen(tp) + 1;
2156 tp += strlen(tp) + 1;
2158 #ifndef AFSIFS /* no SMB username, so we cannot logon based on this */
2159 if (flags & PIOCTL_LOGON) {
2160 /* SMB user name with which to associate tokens */
2162 osi_Log2(smb_logp,"cm_IoctlSetToken for user [%s] smbname [%s]",
2163 osi_LogSaveString(smb_logp,uname), osi_LogSaveString(smb_logp,smbname));
2164 fprintf(stderr, "SMB name = %s\n", smbname);
2165 tp += strlen(tp) + 1;
2167 osi_Log1(smb_logp,"cm_IoctlSetToken for user [%s]",
2168 osi_LogSaveString(smb_logp, uname));
2173 memcpy(&uuid, tp, sizeof(uuid));
2174 if (!cm_FindTokenEvent(uuid, sessionKey))
2175 return CM_ERROR_INVAL;
2177 cellp = cm_data.rootCellp;
2178 osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
2182 if (flags & PIOCTL_LOGON) {
2183 userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname,
2184 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
2189 /* store the token */
2190 lock_ObtainMutex(&userp->mx);
2191 ucellp = cm_GetUCell(userp, cellp);
2192 osi_Log1(smb_logp,"cm_IoctlSetToken ucellp %lx", ucellp);
2193 ucellp->ticketLen = ticketLen;
2194 if (ucellp->ticketp)
2195 free(ucellp->ticketp); /* Discard old token if any */
2196 ucellp->ticketp = malloc(ticketLen);
2197 memcpy(ucellp->ticketp, ticket, ticketLen);
2199 * Get the session key from the RPC, rather than from the pioctl.
2202 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
2204 memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
2205 ucellp->kvno = ct.AuthHandle;
2206 ucellp->expirationTime = ct.EndTimestamp;
2209 ucellp->uid = ANONYMOUSID;
2212 StringCbCopyA(ucellp->userName, MAXKTCNAMELEN, uname);
2214 cm_UsernameToId(uname, ucellp, &ucellp->uid);
2217 ucellp->flags |= CM_UCELLFLAG_RXKAD;
2218 lock_ReleaseMutex(&userp->mx);
2220 if (flags & PIOCTL_LOGON) {
2221 ioctlp->flags |= SMB_IOCTLFLAG_LOGON;
2224 cm_ResetACLCache(userp);
2227 cm_ReleaseUser(userp);
2232 long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
2238 struct ClearToken ct;
2240 cm_SkipIoctlPath(ioctlp);
2242 tp = ioctlp->inDatap;
2243 cp = ioctlp->outDatap;
2246 memcpy(&iterator, tp, sizeof(iterator));
2247 tp += sizeof(iterator);
2249 lock_ObtainMutex(&userp->mx);
2251 /* look for token */
2252 for (;;iterator++) {
2253 ucellp = cm_FindUCell(userp, iterator);
2255 lock_ReleaseMutex(&userp->mx);
2256 return CM_ERROR_NOMORETOKENS;
2258 if (ucellp->flags & CM_UCELLFLAG_RXKAD)
2263 temp = ucellp->iterator + 1;
2264 memcpy(cp, &temp, sizeof(temp));
2268 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2269 cp += sizeof(ucellp->ticketLen);
2272 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2273 cp += ucellp->ticketLen;
2275 /* clear token size */
2277 memcpy(cp, &temp, sizeof(temp));
2281 ct.AuthHandle = ucellp->kvno;
2283 * Don't give out a real session key here
2286 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2288 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2289 ct.ViceId = 37; /* XXX */
2290 ct.BeginTimestamp = 0; /* XXX */
2291 ct.EndTimestamp = ucellp->expirationTime;
2292 memcpy(cp, &ct, sizeof(ct));
2295 /* Primary flag (unused) */
2297 memcpy(cp, &temp, sizeof(temp));
2301 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->cellp->name);
2302 cp += strlen(cp) + 1;
2305 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->userName);
2306 cp += strlen(cp) + 1;
2308 ioctlp->outDatap = cp;
2310 lock_ReleaseMutex(&userp->mx);
2315 long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2321 struct ClearToken ct;
2324 cm_SkipIoctlPath(ioctlp);
2326 tp = ioctlp->inDatap;
2328 cp = ioctlp->outDatap;
2330 /* cell name is right here */
2331 cellp = cm_GetCell(tp, 0);
2333 return CM_ERROR_NOSUCHCELL;
2334 tp += strlen(tp) + 1;
2337 memcpy(&uuid, tp, sizeof(uuid));
2339 lock_ObtainMutex(&userp->mx);
2341 ucellp = cm_GetUCell(userp, cellp);
2342 if (!ucellp || !(ucellp->flags & CM_UCELLFLAG_RXKAD)) {
2343 lock_ReleaseMutex(&userp->mx);
2344 return CM_ERROR_NOMORETOKENS;
2348 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2349 cp += sizeof(ucellp->ticketLen);
2352 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2353 cp += ucellp->ticketLen;
2355 /* clear token size */
2357 memcpy(cp, &temp, sizeof(temp));
2361 ct.AuthHandle = ucellp->kvno;
2363 * Don't give out a real session key here
2366 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2368 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2369 ct.ViceId = 37; /* XXX */
2370 ct.BeginTimestamp = 0; /* XXX */
2371 ct.EndTimestamp = ucellp->expirationTime;
2372 memcpy(cp, &ct, sizeof(ct));
2375 /* Primary flag (unused) */
2377 memcpy(cp, &temp, sizeof(temp));
2381 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->cellp->name);
2382 cp += strlen(cp) + 1;
2385 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->userName);
2386 cp += strlen(cp) + 1;
2388 ioctlp->outDatap = cp;
2390 lock_ReleaseMutex(&userp->mx);
2392 cm_RegisterNewTokenEvent(uuid, ucellp->sessionKey.data);
2397 long cm_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2403 cm_SkipIoctlPath(ioctlp);
2405 cp = ioctlp->outDatap;
2407 /* cell name is right here */
2408 cellp = cm_GetCell(ioctlp->inDatap, 0);
2410 return CM_ERROR_NOSUCHCELL;
2412 lock_ObtainMutex(&userp->mx);
2414 ucellp = cm_GetUCell(userp, cellp);
2416 lock_ReleaseMutex(&userp->mx);
2417 return CM_ERROR_NOMORETOKENS;
2420 osi_Log1(smb_logp,"cm_IoctlDelToken ucellp %lx", ucellp);
2422 if (ucellp->ticketp) {
2423 free(ucellp->ticketp);
2424 ucellp->ticketp = NULL;
2426 ucellp->ticketLen = 0;
2427 memset(ucellp->sessionKey.data, 0, 8);
2429 ucellp->expirationTime = 0;
2430 ucellp->userName[0] = '\0';
2431 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2434 lock_ReleaseMutex(&userp->mx);
2436 cm_ResetACLCache(userp);
2441 long cm_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2445 lock_ObtainMutex(&userp->mx);
2447 for (ucellp = userp->cellInfop; ucellp; ucellp = ucellp->nextp) {
2448 osi_Log1(smb_logp,"cm_IoctlDelAllToken ucellp %lx", ucellp);
2450 if (ucellp->ticketp) {
2451 free(ucellp->ticketp);
2452 ucellp->ticketp = NULL;
2454 ucellp->ticketLen = 0;
2455 memset(ucellp->sessionKey.data, 0, 8);
2457 ucellp->expirationTime = 0;
2458 ucellp->userName[0] = '\0';
2459 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2463 lock_ReleaseMutex(&userp->mx);
2465 cm_ResetACLCache(userp);
2470 long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
2472 char afspath[MAX_PATH];
2474 int nextAutoSubmount;
2476 DWORD dwType, dwSize;
2481 cm_SkipIoctlPath(ioctlp);
2483 /* Serialize this one, to prevent simultaneous mods
2486 lock_ObtainMutex(&cm_Afsdsbmt_Lock);
2488 /* Parse the input parameters--first the required afs path,
2489 * then the requested submount name (which may be "").
2491 cm_NormalizeAfsPath (afspath, sizeof(afspath), ioctlp->inDatap);
2492 submountreqp = ioctlp->inDatap + (strlen(ioctlp->inDatap)+1);
2494 /* If the caller supplied a suggested submount name, see if
2495 * that submount name is in use... if so, the submount's path
2496 * has to match our path.
2499 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
2500 AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
2503 REG_OPTION_NON_VOLATILE,
2504 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
2509 if (submountreqp && *submountreqp) {
2510 char submountPathNormalized[MAX_PATH];
2511 char submountPath[MAX_PATH];
2513 dwSize = sizeof(submountPath);
2514 status = RegQueryValueEx( hkSubmounts, submountreqp, 0,
2515 &dwType, submountPath, &dwSize);
2517 if (status != ERROR_SUCCESS) {
2519 /* The suggested submount name isn't in use now--
2520 * so we can safely map the requested submount name
2521 * to the supplied path. Remember not to write the
2522 * leading "/afs" when writing out the submount.
2524 RegSetValueEx( hkSubmounts, submountreqp, 0,
2526 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2527 &afspath[strlen(cm_mountRoot)]:"/",
2528 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2529 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2531 RegCloseKey( hkSubmounts );
2532 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountreqp);
2533 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2534 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2538 /* The suggested submount name is already in use--if the
2539 * supplied path matches the submount's path, we can still
2540 * use the suggested submount name.
2542 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2543 if (!strcmp (submountPathNormalized, afspath)) {
2544 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountreqp);
2545 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2546 RegCloseKey( hkSubmounts );
2547 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2552 RegQueryInfoKey( hkSubmounts,
2554 NULL, /* lpcClass */
2555 NULL, /* lpReserved */
2556 NULL, /* lpcSubKeys */
2557 NULL, /* lpcMaxSubKeyLen */
2558 NULL, /* lpcMaxClassLen */
2559 &dwSubmounts, /* lpcValues */
2560 NULL, /* lpcMaxValueNameLen */
2561 NULL, /* lpcMaxValueLen */
2562 NULL, /* lpcbSecurityDescriptor */
2563 NULL /* lpftLastWriteTime */
2567 /* Having obtained a list of all available submounts, start
2568 * searching that list for a path which matches the requested
2569 * AFS path. We'll also keep track of the highest "auto15"/"auto47"
2570 * submount, in case we need to add a new one later.
2573 nextAutoSubmount = 1;
2575 for ( dwIndex = 0; dwIndex < dwSubmounts; dwIndex ++ ) {
2576 char submountPathNormalized[MAX_PATH];
2577 char submountPath[MAX_PATH] = "";
2578 DWORD submountPathLen = sizeof(submountPath);
2579 char submountName[MAX_PATH];
2580 DWORD submountNameLen = sizeof(submountName);
2583 RegEnumValue( hkSubmounts, dwIndex, submountName, &submountNameLen, NULL,
2584 &dwType, submountPath, &submountPathLen);
2585 if (dwType == REG_EXPAND_SZ) {
2587 StringCbCopyA(buf, MAX_PATH, submountPath);
2588 submountPathLen = ExpandEnvironmentStrings(buf, submountPath, MAX_PATH);
2589 if (submountPathLen > MAX_PATH)
2593 /* If this is an Auto### submount, remember its ### value */
2594 if ((!strnicmp (submountName, "auto", 4)) &&
2595 (isdigit (submountName[strlen("auto")]))) {
2596 int thisAutoSubmount;
2597 thisAutoSubmount = atoi (&submountName[strlen("auto")]);
2598 nextAutoSubmount = max (nextAutoSubmount,
2599 thisAutoSubmount+1);
2602 if ((submountPathLen == 0) ||
2603 (submountPathLen == sizeof(submountPath) - 1)) {
2607 /* See if the path for this submount matches the path
2608 * that our caller specified. If so, we can return
2611 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2612 if (!strcmp (submountPathNormalized, afspath)) {
2613 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountName);
2614 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2615 RegCloseKey(hkSubmounts);
2616 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2622 /* We've been through the entire list of existing submounts, and
2623 * didn't find any which matched the specified path. So, we'll
2624 * just have to add one. Remember not to write the leading "/afs"
2625 * when writing out the submount.
2628 StringCbPrintfA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "auto%ld", nextAutoSubmount);
2630 RegSetValueEx( hkSubmounts,
2634 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2635 &afspath[strlen(cm_mountRoot)]:"/",
2636 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2637 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2639 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2640 RegCloseKey(hkSubmounts);
2641 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2645 long cm_IoctlGetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2647 memcpy(ioctlp->outDatap, &cryptall, sizeof(cryptall));
2648 ioctlp->outDatap += sizeof(cryptall);
2653 long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2655 afs_int32 c = cryptall;
2657 cm_SkipIoctlPath(ioctlp);
2659 memcpy(&cryptall, ioctlp->inDatap, sizeof(cryptall));
2661 if (c != cryptall) {
2663 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_ON);
2665 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_OFF);
2670 long cm_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp)
2675 cm_SkipIoctlPath(ioctlp);
2677 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2678 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2681 if (flags & AFSCALL_RXSTATS_ENABLE) {
2682 rx_enableProcessRPCStats();
2684 if (flags & AFSCALL_RXSTATS_DISABLE) {
2685 rx_disableProcessRPCStats();
2687 if (flags & AFSCALL_RXSTATS_CLEAR) {
2688 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
2693 long cm_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp)
2698 cm_SkipIoctlPath(ioctlp);
2700 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2701 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2704 if (flags & AFSCALL_RXSTATS_ENABLE) {
2705 rx_enablePeerRPCStats();
2707 if (flags & AFSCALL_RXSTATS_DISABLE) {
2708 rx_disablePeerRPCStats();
2710 if (flags & AFSCALL_RXSTATS_CLEAR) {
2711 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
2716 long cm_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp)
2718 smb_user_t *uidp = ioctlp->uidp;
2720 if (uidp && uidp->unp) {
2721 memcpy(ioctlp->outDatap, uidp->unp->name, strlen(uidp->unp->name));
2722 ioctlp->outDatap += strlen(uidp->unp->name);
2728 long cm_IoctlUUIDControl(struct smb_ioctl * ioctlp, struct cm_user *userp)
2733 memcpy(&cmd, ioctlp->inDatap, sizeof(long));
2735 if (cmd) { /* generate a new UUID */
2736 UuidCreate((UUID *) &uuid);
2737 cm_data.Uuid = uuid;
2738 cm_ForceNewConnectionsAllServers();
2741 memcpy(ioctlp->outDatap, &cm_data.Uuid, sizeof(cm_data.Uuid));
2742 ioctlp->outDatap += sizeof(cm_data.Uuid);
2748 * functions to dump contents of various structures.
2749 * In debug build (linked with crt debug library) will dump allocated but not freed memory
2751 extern int cm_DumpSCache(FILE *outputFile, char *cookie, int lock);
2752 extern int cm_DumpBufHashTable(FILE *outputFile, char *cookie, int lock);
2753 extern int smb_DumpVCP(FILE *outputFile, char *cookie, int lock);
2755 long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
2759 char logfileName[MAX_PATH+1];
2764 static _CrtMemState memstate;
2767 cm_SkipIoctlPath(ioctlp);
2768 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
2770 dwSize = GetEnvironmentVariable("TEMP", logfileName, sizeof(logfileName));
2771 if ( dwSize == 0 || dwSize > sizeof(logfileName) )
2773 GetWindowsDirectory(logfileName, sizeof(logfileName));
2775 strncat(logfileName, "\\afsd_alloc.log", sizeof(logfileName));
2777 hLogFile = CreateFile(logfileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2783 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2784 ioctlp->outDatap += sizeof(long);
2789 SetFilePointer(hLogFile, 0, NULL, FILE_END);
2791 cookie = inValue ? "b" : "e";
2797 _CrtMemCheckpoint(&memstate);
2801 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2802 _CrtSetReportFile(_CRT_WARN, hLogFile);
2803 _CrtMemDumpAllObjectsSince(&memstate);
2807 /* dump all interesting data */
2808 cm_MemDumpDirStats(hLogFile, cookie, 1);
2809 cm_MemDumpBPlusStats(hLogFile, cookie, 1);
2810 cm_DumpCells(hLogFile, cookie, 1);
2811 cm_DumpVolumes(hLogFile, cookie, 1);
2812 cm_DumpSCache(hLogFile, cookie, 1);
2813 cm_DumpBufHashTable(hLogFile, cookie, 1);
2814 smb_DumpVCP(hLogFile, cookie, 1);
2816 CloseHandle(hLogFile);
2818 inValue = 0; /* success */
2819 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2820 ioctlp->outDatap += sizeof(long);
2827 cm_CheckServersStatus(cm_serverRef_t *serversp)
2830 cm_serverRef_t *tsrp;
2832 int someBusy = 0, someOffline = 0, allOffline = 1, allBusy = 1, allDown = 1;
2834 if (serversp == NULL) {
2835 osi_Log1(afsd_logp, "cm_CheckServersStatus returning 0x%x", CM_ERROR_ALLDOWN);
2836 return CM_ERROR_ALLDOWN;
2839 lock_ObtainRead(&cm_serverLock);
2840 for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
2841 if (tsp = tsrp->server) {
2842 cm_GetServerNoLock(tsp);
2843 lock_ReleaseRead(&cm_serverLock);
2844 if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
2846 if (tsrp->status == srv_busy) {
2849 } else if (tsrp->status == srv_offline) {
2859 lock_ObtainRead(&cm_serverLock);
2860 cm_PutServerNoLock(tsp);
2863 lock_ReleaseRead(&cm_serverLock);
2866 code = CM_ERROR_ALLDOWN;
2868 code = CM_ERROR_ALLBUSY;
2869 else if (allOffline || (someBusy && someOffline))
2870 code = CM_ERROR_ALLOFFLINE;
2873 osi_Log1(afsd_logp, "cm_CheckServersStatus returning 0x%x", code);
2878 long cm_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp)
2884 cm_vol_state_t *statep;
2890 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
2894 #ifdef AFS_FREELANCE_CLIENT
2895 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
2897 cm_ReleaseSCache(scp);
2901 volume = scp->fid.volume;
2903 cellp = cm_FindCellByID(scp->fid.cell);
2905 cm_ReleaseSCache(scp);
2908 return CM_ERROR_NOSUCHCELL;
2910 code = cm_GetVolumeByID(cellp, volume, userp, &req, CM_GETVOL_FLAG_CREATE, &tvp);
2914 if (volume == tvp->rw.ID)
2916 else if (volume == tvp->ro.ID)
2921 switch (statep->state) {
2927 code = CM_ERROR_ALLBUSY;
2930 code = CM_ERROR_ALLOFFLINE;
2933 code = CM_ERROR_ALLDOWN;
2942 long cm_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp)
2945 cm_cell_t *cellp = NULL;
2947 cm_vol_state_t *statep;
2948 struct VolStatTest * testp;
2955 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
2956 testp = (struct VolStatTest *)ioctlp->inDatap;
2958 #ifdef AFS_FREELANCE_CLIENT
2959 if (testp->fid.cell == -1)
2960 return CM_ERROR_NOACCESS;
2963 if (testp->flags & VOLSTAT_TEST_CHECK_VOLUME) {
2964 cm_CheckOfflineVolumes();
2968 if (testp->flags & VOLSTAT_TEST_NETWORK_UP) {
2969 cm_VolStatus_Network_Started(cm_NetbiosName
2977 if (testp->flags & VOLSTAT_TEST_NETWORK_DOWN) {
2978 cm_VolStatus_Network_Stopped(cm_NetbiosName
2986 if (testp->cellname[0]) {
2987 n = atoi(testp->cellname);
2989 testp->fid.cell = n;
2991 cellp = cm_GetCell(testp->cellname, 0);
2994 if (testp->fid.cell > 0) {
2995 cellp = cm_FindCellByID(testp->fid.cell);
2999 return CM_ERROR_NOSUCHCELL;
3001 if (testp->volname[0]) {
3002 n = atoi(testp->volname);
3004 testp->fid.volume = n;
3006 code = cm_GetVolumeByName(cellp, testp->volname, userp, &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
3009 if (testp->fid.volume > 0)
3010 code = cm_GetVolumeByID(cellp, testp->fid.volume, userp, &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
3015 if (testp->fid.volume) {
3016 if (testp->fid.volume == volp->rw.ID)
3018 else if (testp->fid.volume == volp->ro.ID)
3023 len = strlen(testp->volname);
3025 if (stricmp(".readonly", &testp->volname[len-9]) == 0)
3027 else if (stricmp(".backup", &testp->volname[len-7]) == 0)
3034 statep->state = testp->state;
3035 code = cm_VolStatus_Change_Notification(cellp->cellID, statep->ID, testp->state);