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;
204 char * relativePath = ioctlp->inDatap;
205 char * lastComponent = NULL;
206 afs_uint32 follow = 0;
208 osi_Log1(afsd_logp, "cm_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,relativePath));
210 /* This is usually the file name, but for StatMountPoint it is the path. */
211 /* ioctlp->inDatap can be either of the form:
214 * \\netbios-name\submount\path\.
215 * \\netbios-name\submount\path\file
217 TranslateExtendedChars(relativePath);
220 /* we have passed the whole path, including the afs prefix.
221 when the pioctl call is made, we perform an ioctl to afsrdr
222 and it returns the correct (full) path. therefore, there is
223 no drive letter, and the path is absolute. */
224 code = cm_NameI(cm_data.rootSCachep, relativePath,
225 CM_FLAG_CASEFOLD | follow,
226 userp, "", reqp, scpp);
229 osi_Log1(afsd_logp,"cm_ParseIoctlPath code 0x%x", code);
234 if (relativePath[0] == relativePath[1] &&
235 relativePath[1] == '\\' &&
236 !_strnicmp(cm_NetbiosName,relativePath+2,strlen(cm_NetbiosName)))
242 /* We may have found a UNC path.
243 * If the first component is the NetbiosName,
244 * then throw out the second component (the submount)
245 * since it had better expand into the value of ioctl->tidPathp
248 p = relativePath + 2 + strlen(cm_NetbiosName) + 1; /* buffer overflow vuln.? */
249 if ( !_strnicmp("all", p, 3) )
252 for (i = 0; *p && *p != '\\'; i++,p++ ) {
255 p++; /* skip past trailing slash */
256 shareName[i] = 0; /* terminate string */
258 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
260 /* we found a sharename, therefore use the resulting path */
261 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
262 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
263 userp, sharePath, reqp, &substRootp);
266 osi_Log1(afsd_logp,"cm_ParseIoctlPath [1] code 0x%x", code);
270 lastComponent = strrchr(p, '\\');
271 if (lastComponent && (lastComponent - p) > 1 &&strlen(lastComponent) > 1) {
272 *lastComponent = '\0';
275 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
276 userp, NULL, reqp, &iscp);
278 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | CM_FLAG_NOMOUNTCHASE,
279 userp, NULL, reqp, scpp);
281 cm_ReleaseSCache(iscp);
283 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
284 userp, NULL, reqp, scpp);
286 cm_ReleaseSCache(substRootp);
288 osi_Log1(afsd_logp,"cm_ParseIoctlPath [2] code 0x%x", code);
292 /* otherwise, treat the name as a cellname mounted off the afs root.
293 * This requires that we reconstruct the shareName string with
294 * leading and trailing slashes.
296 p = relativePath + 2 + strlen(cm_NetbiosName) + 1;
297 if ( !_strnicmp("all", p, 3) )
301 for (i = 1; *p && *p != '\\'; i++,p++ ) {
304 p++; /* skip past trailing slash */
305 shareName[i++] = '/'; /* add trailing slash */
306 shareName[i] = 0; /* terminate string */
309 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
310 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
311 userp, shareName, reqp, &substRootp);
313 osi_Log1(afsd_logp,"cm_ParseIoctlPath [3] code 0x%x", code);
317 lastComponent = strrchr(p, '\\');
318 if (lastComponent && (lastComponent - p) > 1 &&strlen(lastComponent) > 1) {
319 *lastComponent = '\0';
322 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
323 userp, NULL, reqp, &iscp);
325 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | CM_FLAG_NOMOUNTCHASE,
326 userp, NULL, reqp, scpp);
328 cm_ReleaseSCache(iscp);
330 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
331 userp, NULL, reqp, scpp);
335 cm_ReleaseSCache(substRootp);
336 osi_Log1(afsd_logp,"cm_ParseIoctlPath code [4] 0x%x", code);
341 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
342 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
343 userp, ioctlp->tidPathp, reqp, &substRootp);
345 osi_Log1(afsd_logp,"cm_ParseIoctlPath [6] code 0x%x", code);
349 lastComponent = strrchr(relativePath, '\\');
350 if (lastComponent && (lastComponent - relativePath) > 1 && strlen(lastComponent) > 1) {
351 *lastComponent = '\0';
354 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
355 userp, NULL, reqp, &iscp);
357 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | CM_FLAG_NOMOUNTCHASE,
358 userp, NULL, reqp, scpp);
360 cm_ReleaseSCache(iscp);
362 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD,
363 userp, NULL, reqp, scpp);
366 cm_ReleaseSCache(substRootp);
367 osi_Log1(afsd_logp,"cm_ParseIoctlPath [7] code 0x%x", code);
373 /* # of bytes of path */
374 code = (long)strlen(ioctlp->inDatap) + 1;
375 ioctlp->inDatap += code;
377 /* This is usually nothing, but for StatMountPoint it is the file name. */
378 TranslateExtendedChars(ioctlp->inDatap);
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);
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) {
1907 cp = ioctlp->outDatap;
1908 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), spacep->data);
1909 cp += strlen(cp) + 1;
1910 ioctlp->outDatap = cp;
1911 cm_FreeSpace(spacep);
1912 if (newRootScp != NULL)
1913 cm_ReleaseSCache(newRootScp);
1920 long cm_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1921 {/*CHECK FOR VALID SYMLINK*/
1930 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1931 if (code) return code;
1933 cp = ioctlp->inDatap;
1934 osi_LogEvent("cm_IoctlListlink",NULL," name[%s]",cp);
1936 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1937 cm_ReleaseSCache(dscp);
1938 if (code) return code;
1940 /* Check that it's a real symlink */
1941 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1942 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1943 scp->fileType != CM_SCACHETYPE_INVALID)
1944 code = CM_ERROR_INVAL;
1945 cm_ReleaseSCache(scp);
1949 long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1959 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1960 if (code) return code;
1962 cp = ioctlp->inDatap;
1964 #ifdef AFS_FREELANCE_CLIENT
1965 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1966 /* we are adding the mount point to the root dir., so call
1967 * the freelance code to do the add. */
1968 osi_Log0(afsd_logp,"IoctlDeletelink from Freelance root dir");
1969 code = cm_FreelanceRemoveSymlink(cp);
1970 cm_ReleaseSCache(dscp);
1975 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1977 /* if something went wrong, bail out now */
1981 lock_ObtainMutex(&scp->mx);
1982 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1983 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1987 /* now check that this is a real symlink */
1988 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1989 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1990 scp->fileType != CM_SCACHETYPE_INVALID) {
1991 code = CM_ERROR_INVAL;
1995 /* time to make the RPC, so drop the lock */
1996 lock_ReleaseMutex(&scp->mx);
1998 /* easier to do it this way */
1999 code = cm_Unlink(dscp, cp, userp, &req);
2000 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
2001 smb_NotifyChange(FILE_ACTION_REMOVED,
2002 FILE_NOTIFY_CHANGE_FILE_NAME
2003 | FILE_NOTIFY_CHANGE_DIR_NAME,
2004 dscp, cp, NULL, TRUE);
2006 lock_ObtainMutex(&scp->mx);
2008 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2011 lock_ReleaseMutex(&scp->mx);
2012 cm_ReleaseSCache(scp);
2015 cm_ReleaseSCache(dscp);
2020 long cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid)
2025 static struct afsconf_cell info;
2026 struct rx_connection *serverconns[MAXSERVERS];
2027 struct rx_securityClass *sc[3];
2028 afs_int32 scIndex = 2; /* authenticated - we have a token */
2029 struct ubik_client *pruclient = NULL;
2030 struct afsconf_dir *tdir;
2034 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
2035 code = afsconf_GetCellInfo(tdir, ucellp->cellp->name, "afsprot", &info);
2036 afsconf_Close(tdir);
2042 /* we have the token that was given to us in the settoken
2043 * call. we just have to use it.
2045 scIndex = 2; /* kerberos ticket */
2046 sc[2] = rxkad_NewClientSecurityObject(rxkad_clear, &ucellp->sessionKey,
2047 ucellp->kvno, ucellp->ticketLen,
2050 memset(serverconns, 0, sizeof(serverconns)); /* terminate list!!! */
2051 for (i = 0; i < info.numServers; i++)
2053 rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
2054 info.hostAddr[i].sin_port, PRSRV, sc[scIndex],
2057 code = ubik_ClientInit(serverconns, &pruclient);
2062 code = rxs_Release(sc[scIndex]);
2064 lids.idlist_len = 0;
2065 lids.idlist_val = 0;
2066 lnames.namelist_len = 1;
2067 lnames.namelist_val = (prname *) malloc(PR_MAXNAMELEN);
2068 strncpy(lnames.namelist_val[0], uname, PR_MAXNAMELEN);
2069 lnames.namelist_val[0][PR_MAXNAMELEN-1] = '\0';
2070 for ( p=lnames.namelist_val[0], r=NULL; *p; p++ ) {
2076 if (r && !stricmp(r+1,ucellp->cellp->name))
2079 code = ubik_PR_NameToID(pruclient, 0, &lnames, &lids);
2080 if (lids.idlist_val) {
2081 *uid = *lids.idlist_val;
2082 free(lids.idlist_val);
2084 if (lnames.namelist_val)
2085 free(lnames.namelist_val);
2088 ubik_ClientDestroy(pruclient);
2094 #endif /* QUERY_AFSID */
2096 long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2103 struct ClearToken ct;
2113 int release_userp = 0;
2116 saveDataPtr = ioctlp->inDatap;
2118 cm_SkipIoctlPath(ioctlp);
2120 tp = ioctlp->inDatap;
2123 memcpy(&ticketLen, tp, sizeof(ticketLen));
2124 tp += sizeof(ticketLen);
2125 if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN)
2126 return CM_ERROR_INVAL;
2128 /* remember ticket and skip over it for now */
2132 /* clear token size */
2133 memcpy(&ctSize, tp, sizeof(ctSize));
2134 tp += sizeof(ctSize);
2135 if (ctSize != sizeof(struct ClearToken))
2136 return CM_ERROR_INVAL;
2139 memcpy(&ct, tp, ctSize);
2141 if (ct.AuthHandle == -1)
2142 ct.AuthHandle = 999; /* more rxvab compat stuff */
2144 /* more stuff, if any */
2145 if (ioctlp->inCopied > tp - saveDataPtr) {
2146 /* flags: logon flag */
2147 memcpy(&flags, tp, sizeof(int));
2151 cellp = cm_GetCell(tp, CM_FLAG_CREATE);
2153 return CM_ERROR_NOSUCHCELL;
2154 tp += strlen(tp) + 1;
2158 tp += strlen(tp) + 1;
2160 #ifndef AFSIFS /* no SMB username, so we cannot logon based on this */
2161 if (flags & PIOCTL_LOGON) {
2162 /* SMB user name with which to associate tokens */
2164 osi_Log2(smb_logp,"cm_IoctlSetToken for user [%s] smbname [%s]",
2165 osi_LogSaveString(smb_logp,uname), osi_LogSaveString(smb_logp,smbname));
2166 fprintf(stderr, "SMB name = %s\n", smbname);
2167 tp += strlen(tp) + 1;
2169 osi_Log1(smb_logp,"cm_IoctlSetToken for user [%s]",
2170 osi_LogSaveString(smb_logp, uname));
2175 memcpy(&uuid, tp, sizeof(uuid));
2176 if (!cm_FindTokenEvent(uuid, sessionKey))
2177 return CM_ERROR_INVAL;
2179 cellp = cm_data.rootCellp;
2180 osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
2184 if (flags & PIOCTL_LOGON) {
2185 userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname,
2186 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
2191 /* store the token */
2192 lock_ObtainMutex(&userp->mx);
2193 ucellp = cm_GetUCell(userp, cellp);
2194 osi_Log1(smb_logp,"cm_IoctlSetToken ucellp %lx", ucellp);
2195 ucellp->ticketLen = ticketLen;
2196 if (ucellp->ticketp)
2197 free(ucellp->ticketp); /* Discard old token if any */
2198 ucellp->ticketp = malloc(ticketLen);
2199 memcpy(ucellp->ticketp, ticket, ticketLen);
2201 * Get the session key from the RPC, rather than from the pioctl.
2204 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
2206 memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
2207 ucellp->kvno = ct.AuthHandle;
2208 ucellp->expirationTime = ct.EndTimestamp;
2211 ucellp->uid = ANONYMOUSID;
2214 StringCbCopyA(ucellp->userName, MAXKTCNAMELEN, uname);
2216 cm_UsernameToId(uname, ucellp, &ucellp->uid);
2219 ucellp->flags |= CM_UCELLFLAG_RXKAD;
2220 lock_ReleaseMutex(&userp->mx);
2222 if (flags & PIOCTL_LOGON) {
2223 ioctlp->flags |= SMB_IOCTLFLAG_LOGON;
2226 cm_ResetACLCache(userp);
2229 cm_ReleaseUser(userp);
2234 long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
2240 struct ClearToken ct;
2242 cm_SkipIoctlPath(ioctlp);
2244 tp = ioctlp->inDatap;
2245 cp = ioctlp->outDatap;
2248 memcpy(&iterator, tp, sizeof(iterator));
2249 tp += sizeof(iterator);
2251 lock_ObtainMutex(&userp->mx);
2253 /* look for token */
2254 for (;;iterator++) {
2255 ucellp = cm_FindUCell(userp, iterator);
2257 lock_ReleaseMutex(&userp->mx);
2258 return CM_ERROR_NOMORETOKENS;
2260 if (ucellp->flags & CM_UCELLFLAG_RXKAD)
2265 temp = ucellp->iterator + 1;
2266 memcpy(cp, &temp, sizeof(temp));
2270 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2271 cp += sizeof(ucellp->ticketLen);
2274 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2275 cp += ucellp->ticketLen;
2277 /* clear token size */
2279 memcpy(cp, &temp, sizeof(temp));
2283 ct.AuthHandle = ucellp->kvno;
2285 * Don't give out a real session key here
2288 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2290 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2291 ct.ViceId = 37; /* XXX */
2292 ct.BeginTimestamp = 0; /* XXX */
2293 ct.EndTimestamp = ucellp->expirationTime;
2294 memcpy(cp, &ct, sizeof(ct));
2297 /* Primary flag (unused) */
2299 memcpy(cp, &temp, sizeof(temp));
2303 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->cellp->name);
2304 cp += strlen(cp) + 1;
2307 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->userName);
2308 cp += strlen(cp) + 1;
2310 ioctlp->outDatap = cp;
2312 lock_ReleaseMutex(&userp->mx);
2317 long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2323 struct ClearToken ct;
2326 cm_SkipIoctlPath(ioctlp);
2328 tp = ioctlp->inDatap;
2330 cp = ioctlp->outDatap;
2332 /* cell name is right here */
2333 cellp = cm_GetCell(tp, 0);
2335 return CM_ERROR_NOSUCHCELL;
2336 tp += strlen(tp) + 1;
2339 memcpy(&uuid, tp, sizeof(uuid));
2341 lock_ObtainMutex(&userp->mx);
2343 ucellp = cm_GetUCell(userp, cellp);
2344 if (!ucellp || !(ucellp->flags & CM_UCELLFLAG_RXKAD)) {
2345 lock_ReleaseMutex(&userp->mx);
2346 return CM_ERROR_NOMORETOKENS;
2350 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2351 cp += sizeof(ucellp->ticketLen);
2354 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2355 cp += ucellp->ticketLen;
2357 /* clear token size */
2359 memcpy(cp, &temp, sizeof(temp));
2363 ct.AuthHandle = ucellp->kvno;
2365 * Don't give out a real session key here
2368 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2370 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2371 ct.ViceId = 37; /* XXX */
2372 ct.BeginTimestamp = 0; /* XXX */
2373 ct.EndTimestamp = ucellp->expirationTime;
2374 memcpy(cp, &ct, sizeof(ct));
2377 /* Primary flag (unused) */
2379 memcpy(cp, &temp, sizeof(temp));
2383 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->cellp->name);
2384 cp += strlen(cp) + 1;
2387 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->userName);
2388 cp += strlen(cp) + 1;
2390 ioctlp->outDatap = cp;
2392 lock_ReleaseMutex(&userp->mx);
2394 cm_RegisterNewTokenEvent(uuid, ucellp->sessionKey.data);
2399 long cm_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2405 cm_SkipIoctlPath(ioctlp);
2407 cp = ioctlp->outDatap;
2409 /* cell name is right here */
2410 cellp = cm_GetCell(ioctlp->inDatap, 0);
2412 return CM_ERROR_NOSUCHCELL;
2414 lock_ObtainMutex(&userp->mx);
2416 ucellp = cm_GetUCell(userp, cellp);
2418 lock_ReleaseMutex(&userp->mx);
2419 return CM_ERROR_NOMORETOKENS;
2422 osi_Log1(smb_logp,"cm_IoctlDelToken ucellp %lx", ucellp);
2424 if (ucellp->ticketp) {
2425 free(ucellp->ticketp);
2426 ucellp->ticketp = NULL;
2428 ucellp->ticketLen = 0;
2429 memset(ucellp->sessionKey.data, 0, 8);
2431 ucellp->expirationTime = 0;
2432 ucellp->userName[0] = '\0';
2433 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2436 lock_ReleaseMutex(&userp->mx);
2438 cm_ResetACLCache(userp);
2443 long cm_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2447 lock_ObtainMutex(&userp->mx);
2449 for (ucellp = userp->cellInfop; ucellp; ucellp = ucellp->nextp) {
2450 osi_Log1(smb_logp,"cm_IoctlDelAllToken ucellp %lx", ucellp);
2452 if (ucellp->ticketp) {
2453 free(ucellp->ticketp);
2454 ucellp->ticketp = NULL;
2456 ucellp->ticketLen = 0;
2457 memset(ucellp->sessionKey.data, 0, 8);
2459 ucellp->expirationTime = 0;
2460 ucellp->userName[0] = '\0';
2461 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2465 lock_ReleaseMutex(&userp->mx);
2467 cm_ResetACLCache(userp);
2472 long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
2474 char afspath[MAX_PATH];
2476 int nextAutoSubmount;
2478 DWORD dwType, dwSize;
2483 cm_SkipIoctlPath(ioctlp);
2485 /* Serialize this one, to prevent simultaneous mods
2488 lock_ObtainMutex(&cm_Afsdsbmt_Lock);
2490 /* Parse the input parameters--first the required afs path,
2491 * then the requested submount name (which may be "").
2493 cm_NormalizeAfsPath (afspath, sizeof(afspath), ioctlp->inDatap);
2494 submountreqp = ioctlp->inDatap + (strlen(ioctlp->inDatap)+1);
2496 /* If the caller supplied a suggested submount name, see if
2497 * that submount name is in use... if so, the submount's path
2498 * has to match our path.
2501 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
2502 AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
2505 REG_OPTION_NON_VOLATILE,
2506 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
2511 if (submountreqp && *submountreqp) {
2512 char submountPathNormalized[MAX_PATH];
2513 char submountPath[MAX_PATH];
2515 dwSize = sizeof(submountPath);
2516 status = RegQueryValueEx( hkSubmounts, submountreqp, 0,
2517 &dwType, submountPath, &dwSize);
2519 if (status != ERROR_SUCCESS) {
2521 /* The suggested submount name isn't in use now--
2522 * so we can safely map the requested submount name
2523 * to the supplied path. Remember not to write the
2524 * leading "/afs" when writing out the submount.
2526 RegSetValueEx( hkSubmounts, submountreqp, 0,
2528 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2529 &afspath[strlen(cm_mountRoot)]:"/",
2530 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2531 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2533 RegCloseKey( hkSubmounts );
2534 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountreqp);
2535 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2536 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2540 /* The suggested submount name is already in use--if the
2541 * supplied path matches the submount's path, we can still
2542 * use the suggested submount name.
2544 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2545 if (!strcmp (submountPathNormalized, afspath)) {
2546 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountreqp);
2547 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2548 RegCloseKey( hkSubmounts );
2549 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2554 RegQueryInfoKey( hkSubmounts,
2556 NULL, /* lpcClass */
2557 NULL, /* lpReserved */
2558 NULL, /* lpcSubKeys */
2559 NULL, /* lpcMaxSubKeyLen */
2560 NULL, /* lpcMaxClassLen */
2561 &dwSubmounts, /* lpcValues */
2562 NULL, /* lpcMaxValueNameLen */
2563 NULL, /* lpcMaxValueLen */
2564 NULL, /* lpcbSecurityDescriptor */
2565 NULL /* lpftLastWriteTime */
2569 /* Having obtained a list of all available submounts, start
2570 * searching that list for a path which matches the requested
2571 * AFS path. We'll also keep track of the highest "auto15"/"auto47"
2572 * submount, in case we need to add a new one later.
2575 nextAutoSubmount = 1;
2577 for ( dwIndex = 0; dwIndex < dwSubmounts; dwIndex ++ ) {
2578 char submountPathNormalized[MAX_PATH];
2579 char submountPath[MAX_PATH] = "";
2580 DWORD submountPathLen = sizeof(submountPath);
2581 char submountName[MAX_PATH];
2582 DWORD submountNameLen = sizeof(submountName);
2585 RegEnumValue( hkSubmounts, dwIndex, submountName, &submountNameLen, NULL,
2586 &dwType, submountPath, &submountPathLen);
2587 if (dwType == REG_EXPAND_SZ) {
2589 StringCbCopyA(buf, MAX_PATH, submountPath);
2590 submountPathLen = ExpandEnvironmentStrings(buf, submountPath, MAX_PATH);
2591 if (submountPathLen > MAX_PATH)
2595 /* If this is an Auto### submount, remember its ### value */
2596 if ((!strnicmp (submountName, "auto", 4)) &&
2597 (isdigit (submountName[strlen("auto")]))) {
2598 int thisAutoSubmount;
2599 thisAutoSubmount = atoi (&submountName[strlen("auto")]);
2600 nextAutoSubmount = max (nextAutoSubmount,
2601 thisAutoSubmount+1);
2604 if ((submountPathLen == 0) ||
2605 (submountPathLen == sizeof(submountPath) - 1)) {
2609 /* See if the path for this submount matches the path
2610 * that our caller specified. If so, we can return
2613 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2614 if (!strcmp (submountPathNormalized, afspath)) {
2615 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountName);
2616 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2617 RegCloseKey(hkSubmounts);
2618 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2624 /* We've been through the entire list of existing submounts, and
2625 * didn't find any which matched the specified path. So, we'll
2626 * just have to add one. Remember not to write the leading "/afs"
2627 * when writing out the submount.
2630 StringCbPrintfA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "auto%ld", nextAutoSubmount);
2632 RegSetValueEx( hkSubmounts,
2636 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2637 &afspath[strlen(cm_mountRoot)]:"/",
2638 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2639 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2641 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2642 RegCloseKey(hkSubmounts);
2643 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2647 long cm_IoctlGetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2649 memcpy(ioctlp->outDatap, &cryptall, sizeof(cryptall));
2650 ioctlp->outDatap += sizeof(cryptall);
2655 long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2657 afs_int32 c = cryptall;
2659 cm_SkipIoctlPath(ioctlp);
2661 memcpy(&cryptall, ioctlp->inDatap, sizeof(cryptall));
2663 if (c != cryptall) {
2665 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_ON);
2667 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_OFF);
2672 long cm_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp)
2677 cm_SkipIoctlPath(ioctlp);
2679 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2680 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2683 if (flags & AFSCALL_RXSTATS_ENABLE) {
2684 rx_enableProcessRPCStats();
2686 if (flags & AFSCALL_RXSTATS_DISABLE) {
2687 rx_disableProcessRPCStats();
2689 if (flags & AFSCALL_RXSTATS_CLEAR) {
2690 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
2695 long cm_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp)
2700 cm_SkipIoctlPath(ioctlp);
2702 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2703 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2706 if (flags & AFSCALL_RXSTATS_ENABLE) {
2707 rx_enablePeerRPCStats();
2709 if (flags & AFSCALL_RXSTATS_DISABLE) {
2710 rx_disablePeerRPCStats();
2712 if (flags & AFSCALL_RXSTATS_CLEAR) {
2713 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
2718 long cm_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp)
2720 smb_user_t *uidp = ioctlp->uidp;
2722 if (uidp && uidp->unp) {
2723 memcpy(ioctlp->outDatap, uidp->unp->name, strlen(uidp->unp->name));
2724 ioctlp->outDatap += strlen(uidp->unp->name);
2730 long cm_IoctlUUIDControl(struct smb_ioctl * ioctlp, struct cm_user *userp)
2735 memcpy(&cmd, ioctlp->inDatap, sizeof(long));
2737 if (cmd) { /* generate a new UUID */
2738 UuidCreate((UUID *) &uuid);
2739 cm_data.Uuid = uuid;
2740 cm_ForceNewConnectionsAllServers();
2743 memcpy(ioctlp->outDatap, &cm_data.Uuid, sizeof(cm_data.Uuid));
2744 ioctlp->outDatap += sizeof(cm_data.Uuid);
2750 * functions to dump contents of various structures.
2751 * In debug build (linked with crt debug library) will dump allocated but not freed memory
2753 extern int cm_DumpSCache(FILE *outputFile, char *cookie, int lock);
2754 extern int cm_DumpBufHashTable(FILE *outputFile, char *cookie, int lock);
2755 extern int smb_DumpVCP(FILE *outputFile, char *cookie, int lock);
2757 long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
2761 char logfileName[MAX_PATH+1];
2766 static _CrtMemState memstate;
2769 cm_SkipIoctlPath(ioctlp);
2770 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
2772 dwSize = GetEnvironmentVariable("TEMP", logfileName, sizeof(logfileName));
2773 if ( dwSize == 0 || dwSize > sizeof(logfileName) )
2775 GetWindowsDirectory(logfileName, sizeof(logfileName));
2777 strncat(logfileName, "\\afsd_alloc.log", sizeof(logfileName));
2779 hLogFile = CreateFile(logfileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2785 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2786 ioctlp->outDatap += sizeof(long);
2791 SetFilePointer(hLogFile, 0, NULL, FILE_END);
2793 cookie = inValue ? "b" : "e";
2799 _CrtMemCheckpoint(&memstate);
2803 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2804 _CrtSetReportFile(_CRT_WARN, hLogFile);
2805 _CrtMemDumpAllObjectsSince(&memstate);
2809 /* dump all interesting data */
2810 cm_MemDumpDirStats(hLogFile, cookie, 1);
2811 cm_MemDumpBPlusStats(hLogFile, cookie, 1);
2812 cm_DumpCells(hLogFile, cookie, 1);
2813 cm_DumpVolumes(hLogFile, cookie, 1);
2814 cm_DumpSCache(hLogFile, cookie, 1);
2815 cm_DumpBufHashTable(hLogFile, cookie, 1);
2816 smb_DumpVCP(hLogFile, cookie, 1);
2818 CloseHandle(hLogFile);
2820 inValue = 0; /* success */
2821 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2822 ioctlp->outDatap += sizeof(long);
2829 cm_CheckServersStatus(cm_serverRef_t *serversp)
2832 cm_serverRef_t *tsrp;
2834 int someBusy = 0, someOffline = 0, allOffline = 1, allBusy = 1, allDown = 1;
2836 if (serversp == NULL) {
2837 osi_Log1(afsd_logp, "cm_CheckServersStatus returning 0x%x", CM_ERROR_ALLDOWN);
2838 return CM_ERROR_ALLDOWN;
2841 lock_ObtainRead(&cm_serverLock);
2842 for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
2843 if (tsp = tsrp->server) {
2844 cm_GetServerNoLock(tsp);
2845 lock_ReleaseRead(&cm_serverLock);
2846 if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
2848 if (tsrp->status == srv_busy) {
2851 } else if (tsrp->status == srv_offline) {
2861 lock_ObtainRead(&cm_serverLock);
2862 cm_PutServerNoLock(tsp);
2865 lock_ReleaseRead(&cm_serverLock);
2868 code = CM_ERROR_ALLDOWN;
2870 code = CM_ERROR_ALLBUSY;
2871 else if (allOffline || (someBusy && someOffline))
2872 code = CM_ERROR_ALLOFFLINE;
2875 osi_Log1(afsd_logp, "cm_CheckServersStatus returning 0x%x", code);
2880 long cm_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp)
2886 cm_vol_state_t *statep;
2892 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
2896 #ifdef AFS_FREELANCE_CLIENT
2897 if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
2899 cm_ReleaseSCache(scp);
2903 volume = scp->fid.volume;
2905 cellp = cm_FindCellByID(scp->fid.cell);
2907 cm_ReleaseSCache(scp);
2910 return CM_ERROR_NOSUCHCELL;
2912 code = cm_GetVolumeByID(cellp, volume, userp, &req, CM_GETVOL_FLAG_CREATE, &tvp);
2916 if (volume == tvp->rw.ID)
2918 else if (volume == tvp->ro.ID)
2923 switch (statep->state) {
2929 code = CM_ERROR_ALLBUSY;
2932 code = CM_ERROR_ALLOFFLINE;
2935 code = CM_ERROR_ALLDOWN;