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;
203 char * relativePath = ioctlp->inDatap;
205 osi_Log1(afsd_logp, "cm_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,relativePath));
207 /* This is usually the file name, but for StatMountPoint it is the path. */
208 /* ioctlp->inDatap can be either of the form:
211 * \\netbios-name\submount\path\.
212 * \\netbios-name\submount\path\file
214 TranslateExtendedChars(relativePath);
217 /* we have passed the whole path, including the afs prefix.
218 when the pioctl call is made, we perform an ioctl to afsrdr
219 and it returns the correct (full) path. therefore, there is
220 no drive letter, and the path is absolute. */
221 code = cm_NameI(cm_data.rootSCachep, relativePath,
223 userp, "", reqp, scpp);
226 osi_Log1(afsd_logp,"cm_ParseIoctlPath code 0x%x", code);
230 if (relativePath[0] == relativePath[1] &&
231 relativePath[1] == '\\' &&
232 !_strnicmp(cm_NetbiosName,relativePath+2,strlen(cm_NetbiosName)))
238 /* We may have found a UNC path.
239 * If the first component is the NetbiosName,
240 * then throw out the second component (the submount)
241 * since it had better expand into the value of ioctl->tidPathp
244 p = relativePath + 2 + strlen(cm_NetbiosName) + 1; /* buffer overflow vuln.? */
245 if ( !_strnicmp("all", p, 3) )
248 for (i = 0; *p && *p != '\\'; i++,p++ ) {
251 p++; /* skip past trailing slash */
252 shareName[i] = 0; /* terminate string */
254 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
256 /* we found a sharename, therefore use the resulting path */
257 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
258 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
259 userp, sharePath, reqp, &substRootp);
262 osi_Log1(afsd_logp,"cm_ParseIoctlPath [1] code 0x%x", code);
266 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
267 userp, NULL, reqp, scpp);
268 cm_ReleaseSCache(substRootp);
270 osi_Log1(afsd_logp,"cm_ParseIoctlPath [2] code 0x%x", code);
274 /* otherwise, treat the name as a cellname mounted off the afs root.
275 * This requires that we reconstruct the shareName string with
276 * leading and trailing slashes.
278 p = relativePath + 2 + strlen(cm_NetbiosName) + 1;
279 if ( !_strnicmp("all", p, 3) )
283 for (i = 1; *p && *p != '\\'; i++,p++ ) {
286 p++; /* skip past trailing slash */
287 shareName[i++] = '/'; /* add trailing slash */
288 shareName[i] = 0; /* terminate string */
291 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
292 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
293 userp, shareName, reqp, &substRootp);
295 osi_Log1(afsd_logp,"cm_ParseIoctlPath [3] code 0x%x", code);
299 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
300 userp, NULL, reqp, scpp);
302 cm_ReleaseSCache(substRootp);
303 osi_Log1(afsd_logp,"cm_ParseIoctlPath code [4] 0x%x", code);
308 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
309 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
310 userp, ioctlp->tidPathp, reqp, &substRootp);
312 osi_Log1(afsd_logp,"cm_ParseIoctlPath [6] code 0x%x", code);
316 code = cm_NameI(substRootp, relativePath,
318 userp, NULL, reqp, scpp);
320 cm_ReleaseSCache(substRootp);
321 osi_Log1(afsd_logp,"cm_ParseIoctlPath [7] code 0x%x", code);
327 /* # of bytes of path */
328 code = (long)strlen(ioctlp->inDatap) + 1;
329 ioctlp->inDatap += code;
331 /* This is usually nothing, but for StatMountPoint it is the file name. */
332 TranslateExtendedChars(ioctlp->inDatap);
335 cm_ReleaseSCache(substRootp);
337 /* and return success */
338 osi_Log1(afsd_logp,"cm_ParseIoctlPath [8] code 0x%x", code);
342 void cm_SkipIoctlPath(smb_ioctl_t *ioctlp)
346 temp = (long) strlen(ioctlp->inDatap) + 1;
347 ioctlp->inDatap += temp;
351 /* format the specified path to look like "/afs/<cellname>/usr", by
352 * adding "/afs" (if necessary) in front, changing any \'s to /'s, and
353 * removing any trailing "/"'s. One weirdo caveat: "/afs" will be
354 * intentionally returned as "/afs/"--this makes submount manipulation
355 * easier (because we can always jump past the initial "/afs" to find
356 * the AFS path that should be written into afsdsbmt.ini).
358 void cm_NormalizeAfsPath(char *outpathp, long outlen, char *inpathp)
361 char bslash_mountRoot[256];
363 strncpy(bslash_mountRoot, cm_mountRoot, sizeof(bslash_mountRoot) - 1);
364 bslash_mountRoot[0] = '\\';
366 if (!strnicmp (inpathp, cm_mountRoot, strlen(cm_mountRoot)))
367 StringCbCopy(outpathp, outlen, inpathp);
368 else if (!strnicmp (inpathp, bslash_mountRoot, strlen(bslash_mountRoot)))
369 StringCbCopy(outpathp, outlen, inpathp);
370 else if ((inpathp[0] == '/') || (inpathp[0] == '\\'))
371 StringCbPrintfA(outpathp, outlen, "%s%s", cm_mountRoot, inpathp);
372 else // inpathp looks like "<cell>/usr"
373 StringCbPrintfA(outpathp, outlen, "%s/%s", cm_mountRoot, inpathp);
375 for (cp = outpathp; *cp != 0; ++cp) {
380 if (strlen(outpathp) && (outpathp[strlen(outpathp)-1] == '/')) {
381 outpathp[strlen(outpathp)-1] = 0;
384 if (!strcmpi (outpathp, cm_mountRoot)) {
385 StringCbCopy(outpathp, outlen, cm_mountRoot);
389 #define LEAF_SIZE 256
390 /* parse the passed-in file name and do a namei on its parent. If we fail,
391 * return an error code, otherwise return the vnode located in *scpp.
393 long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
394 cm_scache_t **scpp, char *leafp)
399 cm_scache_t *substRootp = NULL;
401 StringCbCopyA(tbuffer, sizeof(tbuffer), ioctlp->inDatap);
402 tp = strrchr(tbuffer, '\\');
403 jp = strrchr(tbuffer, '/');
406 else if (jp && (tp - tbuffer) < (jp - tbuffer))
409 StringCbCopyA(tbuffer, sizeof(tbuffer), "\\");
411 StringCbCopyA(leafp, LEAF_SIZE, ioctlp->inDatap);
416 StringCbCopyA(leafp, LEAF_SIZE, tp+1);
419 if (tbuffer[0] == tbuffer[1] &&
420 tbuffer[1] == '\\' &&
421 !_strnicmp(cm_NetbiosName,tbuffer+2,strlen(cm_NetbiosName)))
427 /* We may have found a UNC path.
428 * If the first component is the NetbiosName,
429 * then throw out the second component (the submount)
430 * since it had better expand into the value of ioctl->tidPathp
433 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
434 if ( !_strnicmp("all", p, 3) )
437 for (i = 0; *p && *p != '\\'; i++,p++ ) {
440 p++; /* skip past trailing slash */
441 shareName[i] = 0; /* terminate string */
443 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
445 /* we found a sharename, therefore use the resulting path */
446 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
447 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
448 userp, sharePath, reqp, &substRootp);
450 if (code) return code;
452 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
453 userp, NULL, reqp, scpp);
454 cm_ReleaseSCache(substRootp);
455 if (code) return code;
457 /* otherwise, treat the name as a cellname mounted off the afs root.
458 * This requires that we reconstruct the shareName string with
459 * leading and trailing slashes.
461 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
462 if ( !_strnicmp("all", p, 3) )
466 for (i = 1; *p && *p != '\\'; i++,p++ ) {
469 p++; /* skip past trailing slash */
470 shareName[i++] = '/'; /* add trailing slash */
471 shareName[i] = 0; /* terminate string */
473 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
474 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
475 userp, shareName, reqp, &substRootp);
476 if (code) return code;
478 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
479 userp, NULL, reqp, scpp);
480 cm_ReleaseSCache(substRootp);
481 if (code) return code;
484 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
485 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
486 userp, ioctlp->tidPathp, reqp, &substRootp);
487 if (code) return code;
489 code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
490 userp, NULL, reqp, scpp);
491 cm_ReleaseSCache(substRootp);
492 if (code) return code;
495 /* # of bytes of path */
496 code = (long)strlen(ioctlp->inDatap) + 1;
497 ioctlp->inDatap += code;
499 /* and return success */
503 long cm_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp)
508 AFSFetchStatus fileStatus;
514 struct rx_connection * callp;
518 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
519 if (code) return code;
521 /* now make the get acl call */
522 fid.Volume = scp->fid.volume;
523 fid.Vnode = scp->fid.vnode;
524 fid.Unique = scp->fid.unique;
526 acl.AFSOpaque_val = ioctlp->outDatap;
527 acl.AFSOpaque_len = 0;
528 code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
531 callp = cm_GetRxConn(connp);
532 code = RXAFS_FetchACL(callp, &fid, &acl, &fileStatus, &volSync);
533 rx_PutConnection(callp);
535 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
536 code = cm_MapRPCError(code, &req);
537 cm_ReleaseSCache(scp);
539 if (code) return code;
541 /* skip over return data */
542 tlen = (int)strlen(ioctlp->outDatap) + 1;
543 ioctlp->outDatap += tlen;
545 /* and return success */
549 long cm_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp)
558 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
559 if (code) return code;
561 #ifdef AFS_FREELANCE_CLIENT
562 if ( cm_freelanceEnabled &&
563 scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
564 scp->fid.volume==AFS_FAKE_ROOT_VOL_ID &&
565 scp->fid.vnode==0x1 && scp->fid.unique==0x1 ) {
566 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "Freelance.Local.Root");
567 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
570 #endif /* AFS_FREELANCE_CLIENT */
572 cellp = cm_FindCellByID(scp->fid.cell);
574 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), cellp->name);
575 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
579 code = CM_ERROR_NOSUCHCELL;
582 cm_ReleaseSCache(scp);
586 long cm_IoctlSetACL(struct smb_ioctl *ioctlp, struct cm_user *userp)
591 AFSFetchStatus fileStatus;
596 struct rx_connection * callp;
600 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
601 if (code) return code;
603 /* now make the get acl call */
604 fid.Volume = scp->fid.volume;
605 fid.Vnode = scp->fid.vnode;
606 fid.Unique = scp->fid.unique;
608 acl.AFSOpaque_val = ioctlp->inDatap;
609 acl.AFSOpaque_len = (u_int)strlen(ioctlp->inDatap)+1;
610 code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
613 callp = cm_GetRxConn(connp);
614 code = RXAFS_StoreACL(callp, &fid, &acl, &fileStatus, &volSync);
615 rx_PutConnection(callp);
617 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
618 code = cm_MapRPCError(code, &req);
620 /* invalidate cache info, since we just trashed the ACL cache */
621 lock_ObtainMutex(&scp->mx);
622 cm_DiscardSCache(scp);
623 lock_ReleaseMutex(&scp->mx);
625 cm_ReleaseSCache(scp);
632 long cm_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
641 lock_ObtainWrite(&cm_scacheLock);
642 for (i=0; i<cm_data.scacheHashTableSize; i++) {
643 for (scp = cm_data.scacheHashTablep[i]; scp; scp = scp->nextp) {
644 cm_HoldSCacheNoLock(scp);
645 lock_ReleaseWrite(&cm_scacheLock);
647 /* now flush the file */
648 code = cm_FlushFile(scp, userp, &req);
649 lock_ObtainWrite(&cm_scacheLock);
650 cm_ReleaseSCacheNoLock(scp);
653 lock_ReleaseWrite(&cm_scacheLock);
658 long cm_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp)
662 unsigned long volume;
668 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
669 if (code) return code;
671 volume = scp->fid.volume;
672 cell = scp->fid.cell;
673 cm_ReleaseSCache(scp);
675 code = cm_FlushVolume(userp, &req, cell, volume);
680 long cm_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp)
688 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
689 if (code) return code;
691 cm_FlushFile(scp, userp, &req);
692 cm_ReleaseSCache(scp);
697 long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
701 char offLineMsg[256];
705 AFSFetchVolumeStatus volStat;
706 AFSStoreVolumeStatus storeStat;
711 struct rx_connection * callp;
715 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
716 if (code) return code;
718 cellp = cm_FindCellByID(scp->fid.cell);
721 if (scp->flags & CM_SCACHEFLAG_RO) {
722 cm_ReleaseSCache(scp);
723 return CM_ERROR_READONLY;
726 code = cm_GetVolumeByID(cellp, scp->fid.volume, userp, &req,
727 CM_GETVOL_FLAG_CREATE, &tvp);
729 cm_ReleaseSCache(scp);
734 /* Copy the junk out, using cp as a roving pointer. */
735 cp = ioctlp->inDatap;
736 memcpy((char *)&volStat, cp, sizeof(AFSFetchVolumeStatus));
737 cp += sizeof(AFSFetchVolumeStatus);
738 StringCbCopyA(volName, sizeof(volName), cp);
739 cp += strlen(volName)+1;
740 StringCbCopyA(offLineMsg, sizeof(offLineMsg), cp);
741 cp += strlen(offLineMsg)+1;
742 StringCbCopyA(motd, sizeof(motd), cp);
744 if (volStat.MinQuota != -1) {
745 storeStat.MinQuota = volStat.MinQuota;
746 storeStat.Mask |= AFS_SETMINQUOTA;
748 if (volStat.MaxQuota != -1) {
749 storeStat.MaxQuota = volStat.MaxQuota;
750 storeStat.Mask |= AFS_SETMAXQUOTA;
754 code = cm_ConnFromFID(&scp->fid, userp, &req, &tcp);
757 callp = cm_GetRxConn(tcp);
758 code = RXAFS_SetVolumeStatus(callp, scp->fid.volume,
759 &storeStat, volName, offLineMsg, motd);
760 rx_PutConnection(callp);
762 } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
763 code = cm_MapRPCError(code, &req);
765 /* return on failure */
766 cm_ReleaseSCache(scp);
771 /* we are sending parms back to make compat. with prev system. should
772 * change interface later to not ask for current status, just set
775 cp = ioctlp->outDatap;
776 memcpy(cp, (char *)&volStat, sizeof(VolumeStatus));
777 cp += sizeof(VolumeStatus);
778 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), volName);
779 cp += strlen(volName)+1;
780 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), offLineMsg);
781 cp += strlen(offLineMsg)+1;
782 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), motd);
783 cp += strlen(motd)+1;
785 /* now return updated return data pointer */
786 ioctlp->outDatap = cp;
791 long cm_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
795 char offLineMsg[256];
799 AFSFetchVolumeStatus volStat;
805 struct rx_connection * callp;
809 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
810 if (code) return code;
813 OfflineMsg = offLineMsg;
816 code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
819 callp = cm_GetRxConn(connp);
820 code = RXAFS_GetVolumeStatus(callp, scp->fid.volume,
821 &volStat, &Name, &OfflineMsg, &MOTD);
822 rx_PutConnection(callp);
824 } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
825 code = cm_MapRPCError(code, &req);
827 cm_ReleaseSCache(scp);
828 if (code) return code;
830 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
831 cp = ioctlp->outDatap;
832 memcpy(cp, (char *)&volStat, sizeof(AFSFetchVolumeStatus));
833 cp += sizeof(AFSFetchVolumeStatus);
834 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), volName);
835 cp += strlen(volName)+1;
836 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), offLineMsg);
837 cp += strlen(offLineMsg)+1;
838 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), motd);
839 cp += strlen(motd)+1;
841 /* return new size */
842 ioctlp->outDatap = cp;
847 long cm_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp)
857 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
858 if (code) return code;
860 memset(&fid, 0, sizeof(cm_fid_t));
861 fid.volume = scp->fid.volume;
862 fid.vnode = scp->fid.vnode;
863 fid.unique = scp->fid.unique;
865 cm_ReleaseSCache(scp);
867 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
868 cp = ioctlp->outDatap;
869 memcpy(cp, (char *)&fid, sizeof(cm_fid_t));
870 cp += sizeof(cm_fid_t);
872 /* return new size */
873 ioctlp->outDatap = cp;
878 long cm_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp)
887 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
888 if (code) return code;
890 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
891 cp = ioctlp->outDatap;
892 memcpy(cp, (char *)&scp->owner, sizeof(afs_uint32));
893 cp += sizeof(afs_uint32);
894 memcpy(cp, (char *)&scp->group, sizeof(afs_uint32));
895 cp += sizeof(afs_uint32);
897 /* return new size */
898 ioctlp->outDatap = cp;
900 cm_ReleaseSCache(scp);
905 long cm_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp)
911 cm_serverRef_t **tsrpp, *current;
913 unsigned long volume;
919 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
920 if (code) return code;
922 volume = scp->fid.volume;
924 cellp = cm_FindCellByID(scp->fid.cell);
926 cm_ReleaseSCache(scp);
929 return CM_ERROR_NOSUCHCELL;
931 code = cm_GetVolumeByID(cellp, volume, userp, &req, CM_GETVOL_FLAG_CREATE, &tvp);
932 if (code) return code;
934 cp = ioctlp->outDatap;
936 lock_ObtainMutex(&tvp->mx);
937 tsrpp = cm_GetVolServers(tvp, volume);
938 lock_ObtainRead(&cm_serverLock);
939 for (current = *tsrpp; current; current = current->next) {
940 tsp = current->server;
941 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
944 lock_ReleaseRead(&cm_serverLock);
945 cm_FreeServerList(tsrpp, 0);
946 lock_ReleaseMutex(&tvp->mx);
948 /* still room for terminating NULL, add it on */
949 volume = 0; /* reuse vbl */
950 memcpy(cp, (char *)&volume, sizeof(long));
953 ioctlp->outDatap = cp;
958 long cm_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
968 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
969 if (code) return code;
971 cp = ioctlp->inDatap;
973 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
974 cm_ReleaseSCache(dscp);
975 if (code) return code;
977 lock_ObtainMutex(&scp->mx);
979 /* now check that this is a real mount point */
980 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
981 lock_ReleaseMutex(&scp->mx);
982 cm_ReleaseSCache(scp);
983 return CM_ERROR_INVAL;
986 code = cm_ReadMountPoint(scp, userp, &req);
988 cp = ioctlp->outDatap;
989 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), scp->mountPointStringp);
990 cp += strlen(cp) + 1;
991 ioctlp->outDatap = cp;
993 lock_ReleaseMutex(&scp->mx);
994 cm_ReleaseSCache(scp);
999 long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1009 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1010 if (code) return code;
1012 cp = ioctlp->inDatap;
1014 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1016 /* if something went wrong, bail out now */
1021 lock_ObtainMutex(&scp->mx);
1022 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1023 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1025 lock_ReleaseMutex(&scp->mx);
1026 cm_ReleaseSCache(scp);
1030 /* now check that this is a real mount point */
1031 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
1032 lock_ReleaseMutex(&scp->mx);
1033 cm_ReleaseSCache(scp);
1034 code = CM_ERROR_INVAL;
1038 /* time to make the RPC, so drop the lock */
1039 lock_ReleaseMutex(&scp->mx);
1040 cm_ReleaseSCache(scp);
1042 /* easier to do it this way */
1043 code = cm_Unlink(dscp, cp, userp, &req);
1044 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1045 smb_NotifyChange(FILE_ACTION_REMOVED,
1046 FILE_NOTIFY_CHANGE_DIR_NAME,
1047 dscp, cp, NULL, TRUE);
1050 lock_ObtainMutex(&scp->mx);
1051 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1052 lock_ReleaseMutex(&scp->mx);
1055 cm_ReleaseSCache(dscp);
1059 long cm_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp)
1069 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1070 tp = ioctlp->inDatap;
1073 memcpy(&temp, tp, sizeof(temp));
1074 if (temp == 0x12345678) { /* For afs3.3 version */
1075 memcpy(&csi, tp, sizeof(csi));
1076 if (csi.tinterval >= 0) {
1077 cp = ioctlp->outDatap;
1078 memcpy(cp, (char *)&cm_daemonCheckDownInterval, sizeof(long));
1079 ioctlp->outDatap += sizeof(long);
1080 if (csi.tinterval > 0) {
1081 if (!smb_SUser(userp))
1082 return CM_ERROR_NOACCESS;
1083 cm_daemonCheckDownInterval = csi.tinterval;
1091 } else { /* For pre afs3.3 versions */
1092 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
1093 ioctlp->inDatap = cp = ioctlp->inDatap + sizeof(long);
1094 if (cp - ioctlp->inAllocp < ioctlp->inCopied) /* still more data available */
1099 * 1: fast check, don't contact servers.
1100 * 2: local cell only.
1103 /* have cell name, too */
1104 cellp = cm_GetCell(cp, 0);
1105 if (!cellp) return CM_ERROR_NOSUCHCELL;
1107 else cellp = (cm_cell_t *) 0;
1108 if (!cellp && (temp & 2)) {
1109 /* use local cell */
1110 cellp = cm_FindCellByID(1);
1112 if (!(temp & 1)) { /* if not fast, call server checker routine */
1113 /* check down servers */
1114 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS | CM_FLAG_CHECKUPSERVERS,
1118 /* now return the current down server list */
1119 cp = ioctlp->outDatap;
1120 lock_ObtainRead(&cm_serverLock);
1121 for (tsp = cm_allServersp; tsp; tsp=tsp->allNextp) {
1122 if (cellp && tsp->cellp != cellp) continue; /* cell spec'd and wrong */
1123 if ((tsp->flags & CM_SERVERFLAG_DOWN)
1124 && tsp->type == CM_SERVER_FILE) {
1125 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
1129 lock_ReleaseRead(&cm_serverLock);
1131 ioctlp->outDatap = cp;
1135 long cm_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp)
1137 /* we don't print anything superfluous, so we don't support the gag call */
1138 return CM_ERROR_INVAL;
1141 long cm_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
1143 cm_RefreshVolumes();
1147 long cm_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp)
1152 cm_SkipIoctlPath(ioctlp);
1154 memcpy(&temp, ioctlp->inDatap, sizeof(temp));
1156 temp = cm_data.buf_nOrigBuffers;
1158 /* temp is in 1K units, convert to # of buffers */
1159 temp = temp / (cm_data.buf_blockSize / 1024);
1162 /* now adjust the cache size */
1163 code = buf_SetNBuffers(temp);
1168 long cm_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
1172 cm_SkipIoctlPath(ioctlp);
1174 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
1178 afsd_ForceTrace(FALSE);
1179 buf_ForceTrace(FALSE);
1183 /* set tracing value to low order bit */
1184 if ((inValue & 1) == 0) {
1185 /* disable tracing */
1186 osi_LogDisable(afsd_logp);
1187 rx_DebugOnOff(FALSE);
1190 /* enable tracing */
1191 osi_LogEnable(afsd_logp);
1192 rx_DebugOnOff(TRUE);
1196 /* see if we're supposed to do a reset, too */
1198 osi_LogReset(afsd_logp);
1201 /* and copy out tracing flag */
1202 inValue = afsd_logp->enabled; /* use as a temp vbl */
1203 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
1204 ioctlp->outDatap += sizeof(long);
1208 long cm_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp)
1210 cm_cacheParms_t parms;
1212 memset(&parms, 0, sizeof(parms));
1214 /* first we get, in 1K units, the cache size */
1215 parms.parms[0] = cm_data.buf_nbuffers * (cm_data.buf_blockSize / 1024);
1217 /* and then the actual # of buffers in use (not in the free list, I guess,
1218 * will be what we do).
1220 parms.parms[1] = (cm_data.buf_nbuffers - buf_CountFreeList()) * (cm_data.buf_blockSize / 1024);
1222 memcpy(ioctlp->outDatap, &parms, sizeof(parms));
1223 ioctlp->outDatap += sizeof(parms);
1228 long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1233 cm_serverRef_t *serverRefp;
1234 cm_server_t *serverp;
1240 cm_SkipIoctlPath(ioctlp);
1242 tp = ioctlp->inDatap;
1244 memcpy((char *)&whichCell, tp, sizeof(long));
1247 /* see if more than one long passed in, ignoring the null pathname (the -1) */
1248 if (ioctlp->inCopied-1 > sizeof(long)) {
1249 memcpy((char *)&magic, tp, sizeof(long));
1252 lock_ObtainRead(&cm_cellLock);
1253 for (tcellp = cm_data.allCellsp; tcellp; tcellp = tcellp->allNextp) {
1254 if (whichCell == 0) break;
1257 lock_ReleaseRead(&cm_cellLock);
1261 cp = ioctlp->outDatap;
1263 if (magic == 0x12345678) {
1264 memcpy(cp, (char *)&magic, sizeof(long));
1267 memset(cp, 0, max * sizeof(long));
1269 lock_ObtainRead(&cm_serverLock); /* for going down server list */
1270 /* jaltman - do the reference counts to serverRefp contents need to be increased? */
1271 serverRefp = tcellp->vlServersp;
1272 for (i=0; i<max; i++) {
1273 if (!serverRefp) break;
1274 serverp = serverRefp->server;
1275 memcpy(cp, &serverp->addr.sin_addr.s_addr, sizeof(long));
1277 serverRefp = serverRefp->next;
1279 lock_ReleaseRead(&cm_serverLock);
1280 cp = basep + max * sizeof(afs_int32);
1281 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), tcellp->name);
1282 cp += strlen(tcellp->name)+1;
1283 ioctlp->outDatap = cp;
1289 return CM_ERROR_NOMORETOKENS; /* mapped to EDOM */
1292 extern long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *namep);
1294 long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1296 /* NT cache manager will read cell information from CellServDB each time
1297 * cell is accessed. So, this call is necessary only if list of server for a cell
1298 * changes (or IP addresses of cell servers changes).
1299 * All that needs to be done is to refresh server information for all cells that
1300 * are already loaded.
1302 * cell list will be cm_CellLock and cm_ServerLock will be held for write.
1307 cm_SkipIoctlPath(ioctlp);
1308 lock_ObtainWrite(&cm_cellLock);
1310 for (cp = cm_data.allCellsp; cp; cp=cp->allNextp)
1313 lock_ObtainMutex(&cp->mx);
1314 /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
1315 cm_FreeServerList(&cp->vlServersp, CM_FREESERVERLIST_DELETE);
1316 cp->vlServersp = NULL;
1317 code = cm_SearchCellFile(cp->name, cp->name, cm_AddCellProc, cp);
1318 #ifdef AFS_AFSDB_ENV
1320 if (cm_dnsEnabled) {
1322 code = cm_SearchCellByDNS(cp->name, cp->name, &ttl, cm_AddCellProc, cp);
1323 if ( code == 0 ) { /* got cell from DNS */
1324 cp->flags |= CM_CELLFLAG_DNS;
1325 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1326 cp->timeout = time(0) + ttl;
1331 cp->flags &= ~CM_CELLFLAG_DNS;
1333 #endif /* AFS_AFSDB_ENV */
1335 cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
1338 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1339 cm_RandomizeServer(&cp->vlServersp);
1341 lock_ReleaseMutex(&cp->mx);
1344 lock_ReleaseWrite(&cm_cellLock);
1348 long cm_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
1352 if (cm_freelanceEnabled) {
1353 if (cm_GetRootCellName(ioctlp->outDatap))
1354 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "Freelance.Local.Root");
1355 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1356 } else if (cm_data.rootCellp) {
1357 /* return the default cellname to the caller */
1358 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), cm_data.rootCellp->name);
1359 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1361 /* if we don't know our default cell, return failure */
1362 code = CM_ERROR_NOSUCHCELL;
1368 long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp)
1370 long setSysName, foundname = 0;
1371 char *cp, *cp2, inname[MAXSYSNAME], outname[MAXSYSNAME];
1372 int t, count, num = 0;
1373 char **sysnamelist[MAXSYSNAME];
1375 cm_SkipIoctlPath(ioctlp);
1377 memcpy(&setSysName, ioctlp->inDatap, sizeof(long));
1378 ioctlp->inDatap += sizeof(long);
1382 if ( setSysName < 0 || setSysName > MAXNUMSYSNAMES )
1384 cp2 = ioctlp->inDatap;
1385 for ( cp=ioctlp->inDatap, count = 0; count < setSysName; count++ ) {
1386 /* won't go past end of ioctlp->inDatap since maxsysname*num < ioctlp->inDatap length */
1387 t = (int)strlen(cp);
1388 if (t >= MAXSYSNAME || t <= 0)
1390 /* check for names that can shoot us in the foot */
1391 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
1397 /* inname gets first entry in case we're being a translator */
1398 /* (we are never a translator) */
1399 t = (int)strlen(ioctlp->inDatap);
1400 memcpy(inname, ioctlp->inDatap, t + 1);
1401 ioctlp->inDatap += t + 1;
1405 /* Not xlating, so local case */
1407 osi_panic("cm_IoctlSysName: !cm_sysName\n", __FILE__, __LINE__);
1409 if (!setSysName) { /* user just wants the info */
1410 StringCbCopyA(outname, sizeof(outname), cm_sysName);
1411 foundname = cm_sysNameCount;
1412 *sysnamelist = cm_sysNameList;
1414 /* Local guy; only root can change sysname */
1415 /* clear @sys entries from the dnlc, once afs_lookup can
1416 * do lookups of @sys entries and thinks it can trust them */
1417 /* privs ok, store the entry, ... */
1418 StringCbCopyA(cm_sysName, sizeof(cm_sysName), inname);
1419 StringCbCopyA(cm_sysNameList[0], MAXSYSNAME, inname);
1420 if (setSysName > 1) { /* ... or list */
1421 cp = ioctlp->inDatap;
1422 for (count = 1; count < setSysName; ++count) {
1423 if (!cm_sysNameList[count])
1424 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to write\n",
1425 __FILE__, __LINE__);
1426 t = (int)strlen(cp);
1427 StringCbCopyA(cm_sysNameList[count], MAXSYSNAME, cp);
1431 cm_sysNameCount = setSysName;
1435 /* return the sysname to the caller */
1436 cp = ioctlp->outDatap;
1437 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
1438 cp += sizeof(afs_int32); /* skip found flag */
1440 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), outname);
1441 cp += strlen(outname) + 1; /* skip name and terminating null char */
1442 for ( count=1; count < foundname ; ++count) { /* ... or list */
1443 if ( !(*sysnamelist)[count] )
1444 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to read\n",
1445 __FILE__, __LINE__);
1446 t = (int)strlen((*sysnamelist)[count]);
1447 if (t >= MAXSYSNAME)
1448 osi_panic("cm_IoctlSysName: sysname entry garbled\n",
1449 __FILE__, __LINE__);
1450 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), (*sysnamelist)[count]);
1454 ioctlp->outDatap = cp;
1461 long cm_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1466 cm_SkipIoctlPath(ioctlp);
1468 cellp = cm_GetCell(ioctlp->inDatap, 0);
1470 return CM_ERROR_NOSUCHCELL;
1473 lock_ObtainMutex(&cellp->mx);
1474 if (cellp->flags & CM_CELLFLAG_SUID)
1475 temp |= CM_SETCELLFLAG_SUID;
1476 lock_ReleaseMutex(&cellp->mx);
1478 /* now copy out parm */
1479 memcpy(ioctlp->outDatap, &temp, sizeof(long));
1480 ioctlp->outDatap += sizeof(long);
1485 long cm_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1490 cm_SkipIoctlPath(ioctlp);
1492 cellp = cm_GetCell(ioctlp->inDatap + 2*sizeof(long), 0);
1494 return CM_ERROR_NOSUCHCELL;
1496 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
1498 lock_ObtainMutex(&cellp->mx);
1499 if (temp & CM_SETCELLFLAG_SUID)
1500 cellp->flags |= CM_CELLFLAG_SUID;
1502 cellp->flags &= ~CM_CELLFLAG_SUID;
1503 lock_ReleaseMutex(&cellp->mx);
1508 long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1510 cm_SSetPref_t *spin; /* input */
1511 cm_SPref_t *srvin; /* one input component */
1513 int i, vlonly, noServers, type;
1514 struct sockaddr_in tmp;
1515 unsigned short rank;
1517 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1519 spin = (cm_SSetPref_t *)ioctlp->inDatap;
1520 noServers = spin->num_servers;
1521 vlonly = spin->flags;
1523 type = CM_SERVER_VLDB;
1525 type = CM_SERVER_FILE;
1527 for ( i=0; i < noServers; i++)
1529 srvin = &(spin->servers[i]);
1530 rank = srvin->rank + (rand() & 0x000f);
1531 tmp.sin_addr = srvin->host;
1532 tmp.sin_family = AF_INET;
1534 tsp = cm_FindServer(&tmp, type);
1535 if ( tsp ) /* an existing server - ref count increased */
1537 tsp->ipRank = rank; /* no need to protect by mutex*/
1539 if (type == CM_SERVER_FILE)
1541 /* find volumes which might have RO copy
1542 /* on server and change the ordering of
1545 cm_ChangeRankVolume(tsp);
1549 /* set preferences for an existing vlserver */
1550 cm_ChangeRankCellVLServer(tsp);
1553 else /* add a new server without a cell */
1555 tsp = cm_NewServer(&tmp, type, NULL); /* refcount = 1 */
1558 lock_ObtainMutex(&tsp->mx);
1559 tsp->flags |= CM_SERVERFLAG_PREF_SET;
1560 lock_ReleaseMutex(&tsp->mx);
1561 cm_PutServer(tsp); /* decrease refcount */
1566 long cm_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1568 cm_SPrefRequest_t *spin; /* input */
1569 cm_SPrefInfo_t *spout; /* output */
1570 cm_SPref_t *srvout; /* one output component */
1572 int i, vlonly, noServers;
1574 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1576 spin = (cm_SPrefRequest_t *)ioctlp->inDatap;
1577 spout = (cm_SPrefInfo_t *) ioctlp->outDatap;
1578 srvout = spout->servers;
1579 noServers = spin->num_servers;
1580 vlonly = spin->flags & CM_SPREF_VLONLY;
1581 spout->num_servers = 0;
1583 lock_ObtainRead(&cm_serverLock); /* get server lock */
1585 for (tsp=cm_allServersp, i=0; tsp && noServers; tsp=tsp->allNextp,i++){
1586 if (spin->offset > i) {
1587 continue; /* catch up to where we left off */
1590 if ( vlonly && (tsp->type == CM_SERVER_FILE) )
1591 continue; /* ignore fileserver for -vlserver option*/
1592 if ( !vlonly && (tsp->type == CM_SERVER_VLDB) )
1593 continue; /* ignore vlservers */
1595 srvout->host = tsp->addr.sin_addr;
1596 srvout->rank = tsp->ipRank;
1598 spout->num_servers++;
1601 lock_ReleaseRead(&cm_serverLock); /* release server lock */
1603 if ( tsp ) /* we ran out of space in the output buffer */
1604 spout->next_offset = i;
1606 spout->next_offset = 0;
1607 ioctlp->outDatap += sizeof(cm_SPrefInfo_t) +
1608 (spout->num_servers -1 ) * sizeof(cm_SPref_t) ;
1612 long cm_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp)
1614 /* we ignore default asynchrony since we only have one way
1615 * of doing this today.
1620 long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1622 char leaf[LEAF_SIZE];
1636 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1637 if (code) return code;
1639 /* Translate chars for the mount point name */
1640 TranslateExtendedChars(leaf);
1643 * The fs command allows the user to specify partial cell names on NT. These must
1644 * be expanded to the full cell name for mount points so that the mount points will
1645 * work on UNIX clients.
1648 /* Extract the possibly partial cell name */
1649 StringCbCopyA(cell, sizeof(cell), ioctlp->inDatap + 1); /* Skip the mp type character */
1651 if (cp = strchr(cell, ':')) {
1652 /* Extract the volume name */
1654 StringCbCopyA(volume, sizeof(volume), cp + 1);
1656 /* Get the full name for this cell */
1657 code = cm_SearchCellFile(cell, fullCell, 0, 0);
1658 #ifdef AFS_AFSDB_ENV
1659 if (code && cm_dnsEnabled)
1660 code = cm_SearchCellByDNS(cell, fullCell, &ttl, 0, 0);
1663 return CM_ERROR_NOSUCHCELL;
1665 StringCbPrintfA(mpInfo, sizeof(mpInfo), "%c%s:%s", *ioctlp->inDatap, fullCell, volume);
1667 /* No cell name specified */
1668 StringCbCopyA(mpInfo, sizeof(mpInfo), ioctlp->inDatap);
1671 #ifdef AFS_FREELANCE_CLIENT
1672 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1673 /* we are adding the mount point to the root dir., so call
1674 * the freelance code to do the add. */
1675 osi_Log0(afsd_logp,"IoctlCreateMountPoint within Freelance root dir");
1676 code = cm_FreelanceAddMount(leaf, fullCell, volume,
1677 *ioctlp->inDatap == '%', NULL);
1678 cm_ReleaseSCache(dscp);
1682 /* create the symlink with mode 644. The lack of X bits tells
1683 * us that it is a mount point.
1685 tattr.mask = CM_ATTRMASK_UNIXMODEBITS | CM_ATTRMASK_CLIENTMODTIME;
1686 tattr.unixModeBits = 0644;
1687 tattr.clientModTime = time(NULL);
1689 code = cm_SymLink(dscp, leaf, mpInfo, 0, &tattr, userp, &req);
1690 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1691 smb_NotifyChange(FILE_ACTION_ADDED,
1692 FILE_NOTIFY_CHANGE_DIR_NAME,
1693 dscp, leaf, NULL, TRUE);
1695 cm_ReleaseSCache(dscp);
1699 long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1701 char leaf[LEAF_SIZE];
1710 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1711 if (code) return code;
1713 /* Translate chars for the link name */
1714 TranslateExtendedChars(leaf);
1716 /* Translate chars for the linked to name */
1717 TranslateExtendedChars(ioctlp->inDatap);
1719 cp = ioctlp->inDatap; /* contents of link */
1721 #ifdef AFS_FREELANCE_CLIENT
1722 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1723 /* we are adding the symlink to the root dir., so call
1724 * the freelance code to do the add. */
1725 if (cp[0] == cp[1] && cp[1] == '\\' &&
1726 !_strnicmp(cm_NetbiosName,cp+2,strlen(cm_NetbiosName)))
1728 /* skip \\AFS\ or \\AFS\all\ */
1730 p = cp + 2 + strlen(cm_NetbiosName) + 1;
1731 if ( !_strnicmp("all", p, 3) )
1735 osi_Log0(afsd_logp,"IoctlCreateSymlink within Freelance root dir");
1736 code = cm_FreelanceAddSymlink(leaf, cp, NULL);
1737 cm_ReleaseSCache(dscp);
1742 /* Create symlink with mode 0755. */
1743 tattr.mask = CM_ATTRMASK_UNIXMODEBITS;
1744 tattr.unixModeBits = 0755;
1746 code = cm_SymLink(dscp, leaf, cp, 0, &tattr, userp, &req);
1747 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1748 smb_NotifyChange(FILE_ACTION_ADDED,
1749 FILE_NOTIFY_CHANGE_FILE_NAME
1750 | FILE_NOTIFY_CHANGE_DIR_NAME,
1751 dscp, leaf, NULL, TRUE);
1753 cm_ReleaseSCache(dscp);
1759 long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1766 cm_scache_t *newRootScp;
1771 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1772 if (code) return code;
1774 cp = ioctlp->inDatap;
1776 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1777 cm_ReleaseSCache(dscp);
1778 if (code) return code;
1780 /* Check that it's a real symlink */
1781 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1782 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1783 scp->fileType != CM_SCACHETYPE_INVALID) {
1784 cm_ReleaseSCache(scp);
1785 return CM_ERROR_INVAL;
1788 code = cm_AssembleLink(scp, "", &newRootScp, &spacep, userp, &req);
1789 cm_ReleaseSCache(scp);
1791 cp = ioctlp->outDatap;
1792 if (newRootScp != NULL) {
1793 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), cm_mountRoot);
1794 StringCbCatA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), "/");
1797 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), spacep->data);
1798 cp += strlen(cp) + 1;
1799 ioctlp->outDatap = cp;
1800 cm_FreeSpace(spacep);
1801 if (newRootScp != NULL)
1802 cm_ReleaseSCache(newRootScp);
1804 } else if (code == CM_ERROR_PATH_NOT_COVERED &&
1805 scp->fileType == CM_SCACHETYPE_DFSLINK ||
1806 code == CM_ERROR_NOSUCHPATH &&
1807 scp->fileType == CM_SCACHETYPE_INVALID) {
1808 cp = ioctlp->outDatap;
1809 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), spacep->data);
1810 cp += strlen(cp) + 1;
1811 ioctlp->outDatap = cp;
1812 cm_FreeSpace(spacep);
1813 if (newRootScp != NULL)
1814 cm_ReleaseSCache(newRootScp);
1821 long cm_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1822 {/*CHECK FOR VALID SYMLINK*/
1831 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1832 if (code) return code;
1834 cp = ioctlp->inDatap;
1835 osi_LogEvent("cm_IoctlListlink",NULL," name[%s]",cp);
1837 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1838 cm_ReleaseSCache(dscp);
1839 if (code) return code;
1841 /* Check that it's a real symlink */
1842 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1843 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1844 scp->fileType != CM_SCACHETYPE_INVALID)
1845 code = CM_ERROR_INVAL;
1846 cm_ReleaseSCache(scp);
1850 long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1860 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1861 if (code) return code;
1863 cp = ioctlp->inDatap;
1865 #ifdef AFS_FREELANCE_CLIENT
1866 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1867 /* we are adding the mount point to the root dir., so call
1868 * the freelance code to do the add. */
1869 osi_Log0(afsd_logp,"IoctlDeletelink from Freelance root dir");
1870 code = cm_FreelanceRemoveSymlink(cp);
1871 cm_ReleaseSCache(dscp);
1876 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1878 /* if something went wrong, bail out now */
1882 lock_ObtainMutex(&scp->mx);
1883 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1884 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1888 /* now check that this is a real symlink */
1889 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1890 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1891 scp->fileType != CM_SCACHETYPE_INVALID) {
1892 code = CM_ERROR_INVAL;
1896 /* time to make the RPC, so drop the lock */
1897 lock_ReleaseMutex(&scp->mx);
1899 /* easier to do it this way */
1900 code = cm_Unlink(dscp, cp, userp, &req);
1901 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1902 smb_NotifyChange(FILE_ACTION_REMOVED,
1903 FILE_NOTIFY_CHANGE_FILE_NAME
1904 | FILE_NOTIFY_CHANGE_DIR_NAME,
1905 dscp, cp, NULL, TRUE);
1907 lock_ObtainMutex(&scp->mx);
1909 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1912 lock_ReleaseMutex(&scp->mx);
1913 cm_ReleaseSCache(scp);
1916 cm_ReleaseSCache(dscp);
1921 long cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid)
1926 static struct afsconf_cell info;
1927 struct rx_connection *serverconns[MAXSERVERS];
1928 struct rx_securityClass *sc[3];
1929 afs_int32 scIndex = 2; /* authenticated - we have a token */
1930 struct ubik_client *pruclient = NULL;
1931 struct afsconf_dir *tdir;
1935 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
1936 code = afsconf_GetCellInfo(tdir, ucellp->cellp->name, "afsprot", &info);
1937 afsconf_Close(tdir);
1943 /* we have the token that was given to us in the settoken
1944 * call. we just have to use it.
1946 scIndex = 2; /* kerberos ticket */
1947 sc[2] = rxkad_NewClientSecurityObject(rxkad_clear, &ucellp->sessionKey,
1948 ucellp->kvno, ucellp->ticketLen,
1951 memset(serverconns, 0, sizeof(serverconns)); /* terminate list!!! */
1952 for (i = 0; i < info.numServers; i++)
1954 rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
1955 info.hostAddr[i].sin_port, PRSRV, sc[scIndex],
1958 code = ubik_ClientInit(serverconns, &pruclient);
1963 code = rxs_Release(sc[scIndex]);
1965 lids.idlist_len = 0;
1966 lids.idlist_val = 0;
1967 lnames.namelist_len = 1;
1968 lnames.namelist_val = (prname *) malloc(PR_MAXNAMELEN);
1969 strncpy(lnames.namelist_val[0], uname, PR_MAXNAMELEN);
1970 lnames.namelist_val[0][PR_MAXNAMELEN-1] = '\0';
1971 for ( p=lnames.namelist_val[0], r=NULL; *p; p++ ) {
1977 if (r && !stricmp(r+1,ucellp->cellp->name))
1980 code = ubik_PR_NameToID(pruclient, 0, &lnames, &lids);
1981 if (lids.idlist_val) {
1982 *uid = *lids.idlist_val;
1983 free(lids.idlist_val);
1985 if (lnames.namelist_val)
1986 free(lnames.namelist_val);
1989 ubik_ClientDestroy(pruclient);
1995 #endif /* QUERY_AFSID */
1997 long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2004 struct ClearToken ct;
2014 int release_userp = 0;
2017 saveDataPtr = ioctlp->inDatap;
2019 cm_SkipIoctlPath(ioctlp);
2021 tp = ioctlp->inDatap;
2024 memcpy(&ticketLen, tp, sizeof(ticketLen));
2025 tp += sizeof(ticketLen);
2026 if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN)
2027 return CM_ERROR_INVAL;
2029 /* remember ticket and skip over it for now */
2033 /* clear token size */
2034 memcpy(&ctSize, tp, sizeof(ctSize));
2035 tp += sizeof(ctSize);
2036 if (ctSize != sizeof(struct ClearToken))
2037 return CM_ERROR_INVAL;
2040 memcpy(&ct, tp, ctSize);
2042 if (ct.AuthHandle == -1)
2043 ct.AuthHandle = 999; /* more rxvab compat stuff */
2045 /* more stuff, if any */
2046 if (ioctlp->inCopied > tp - saveDataPtr) {
2047 /* flags: logon flag */
2048 memcpy(&flags, tp, sizeof(int));
2052 cellp = cm_GetCell(tp, CM_FLAG_CREATE);
2053 if (!cellp) return CM_ERROR_NOSUCHCELL;
2054 tp += strlen(tp) + 1;
2058 tp += strlen(tp) + 1;
2060 #ifndef AFSIFS /* no SMB username, so we cannot logon based on this */
2061 if (flags & PIOCTL_LOGON) {
2062 /* SMB user name with which to associate tokens */
2064 osi_Log2(smb_logp,"cm_IoctlSetToken for user [%s] smbname [%s]",
2065 osi_LogSaveString(smb_logp,uname), osi_LogSaveString(smb_logp,smbname));
2066 fprintf(stderr, "SMB name = %s\n", smbname);
2067 tp += strlen(tp) + 1;
2069 osi_Log1(smb_logp,"cm_IoctlSetToken for user [%s]",
2070 osi_LogSaveString(smb_logp, uname));
2075 memcpy(&uuid, tp, sizeof(uuid));
2076 if (!cm_FindTokenEvent(uuid, sessionKey))
2077 return CM_ERROR_INVAL;
2079 cellp = cm_data.rootCellp;
2080 osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
2084 if (flags & PIOCTL_LOGON) {
2085 userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname,
2086 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
2091 /* store the token */
2092 lock_ObtainMutex(&userp->mx);
2093 ucellp = cm_GetUCell(userp, cellp);
2094 osi_Log1(smb_logp,"cm_IoctlSetToken ucellp %lx", ucellp);
2095 ucellp->ticketLen = ticketLen;
2096 if (ucellp->ticketp)
2097 free(ucellp->ticketp); /* Discard old token if any */
2098 ucellp->ticketp = malloc(ticketLen);
2099 memcpy(ucellp->ticketp, ticket, ticketLen);
2101 * Get the session key from the RPC, rather than from the pioctl.
2104 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
2106 memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
2107 ucellp->kvno = ct.AuthHandle;
2108 ucellp->expirationTime = ct.EndTimestamp;
2111 ucellp->uid = ANONYMOUSID;
2114 StringCbCopyA(ucellp->userName, MAXKTCNAMELEN, uname);
2116 cm_UsernameToId(uname, ucellp, &ucellp->uid);
2119 ucellp->flags |= CM_UCELLFLAG_RXKAD;
2120 lock_ReleaseMutex(&userp->mx);
2122 if (flags & PIOCTL_LOGON) {
2123 ioctlp->flags |= SMB_IOCTLFLAG_LOGON;
2126 cm_ResetACLCache(userp);
2129 cm_ReleaseUser(userp);
2134 long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
2140 struct ClearToken ct;
2142 cm_SkipIoctlPath(ioctlp);
2144 tp = ioctlp->inDatap;
2145 cp = ioctlp->outDatap;
2148 memcpy(&iterator, tp, sizeof(iterator));
2149 tp += sizeof(iterator);
2151 lock_ObtainMutex(&userp->mx);
2153 /* look for token */
2154 for (;;iterator++) {
2155 ucellp = cm_FindUCell(userp, iterator);
2157 lock_ReleaseMutex(&userp->mx);
2158 return CM_ERROR_NOMORETOKENS;
2160 if (ucellp->flags & CM_UCELLFLAG_RXKAD)
2165 temp = ucellp->iterator + 1;
2166 memcpy(cp, &temp, sizeof(temp));
2170 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2171 cp += sizeof(ucellp->ticketLen);
2174 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2175 cp += ucellp->ticketLen;
2177 /* clear token size */
2179 memcpy(cp, &temp, sizeof(temp));
2183 ct.AuthHandle = ucellp->kvno;
2185 * Don't give out a real session key here
2188 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2190 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2191 ct.ViceId = 37; /* XXX */
2192 ct.BeginTimestamp = 0; /* XXX */
2193 ct.EndTimestamp = ucellp->expirationTime;
2194 memcpy(cp, &ct, sizeof(ct));
2197 /* Primary flag (unused) */
2199 memcpy(cp, &temp, sizeof(temp));
2203 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->cellp->name);
2204 cp += strlen(cp) + 1;
2207 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->userName);
2208 cp += strlen(cp) + 1;
2210 ioctlp->outDatap = cp;
2212 lock_ReleaseMutex(&userp->mx);
2217 long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2223 struct ClearToken ct;
2226 cm_SkipIoctlPath(ioctlp);
2228 tp = ioctlp->inDatap;
2230 cp = ioctlp->outDatap;
2232 /* cell name is right here */
2233 cellp = cm_GetCell(tp, 0);
2235 return CM_ERROR_NOSUCHCELL;
2236 tp += strlen(tp) + 1;
2239 memcpy(&uuid, tp, sizeof(uuid));
2241 lock_ObtainMutex(&userp->mx);
2243 ucellp = cm_GetUCell(userp, cellp);
2244 if (!ucellp || !(ucellp->flags & CM_UCELLFLAG_RXKAD)) {
2245 lock_ReleaseMutex(&userp->mx);
2246 return CM_ERROR_NOMORETOKENS;
2250 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2251 cp += sizeof(ucellp->ticketLen);
2254 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2255 cp += ucellp->ticketLen;
2257 /* clear token size */
2259 memcpy(cp, &temp, sizeof(temp));
2263 ct.AuthHandle = ucellp->kvno;
2265 * Don't give out a real session key here
2268 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2270 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2271 ct.ViceId = 37; /* XXX */
2272 ct.BeginTimestamp = 0; /* XXX */
2273 ct.EndTimestamp = ucellp->expirationTime;
2274 memcpy(cp, &ct, sizeof(ct));
2277 /* Primary flag (unused) */
2279 memcpy(cp, &temp, sizeof(temp));
2283 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->cellp->name);
2284 cp += strlen(cp) + 1;
2287 StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->userName);
2288 cp += strlen(cp) + 1;
2290 ioctlp->outDatap = cp;
2292 lock_ReleaseMutex(&userp->mx);
2294 cm_RegisterNewTokenEvent(uuid, ucellp->sessionKey.data);
2299 long cm_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2305 cm_SkipIoctlPath(ioctlp);
2307 cp = ioctlp->outDatap;
2309 /* cell name is right here */
2310 cellp = cm_GetCell(ioctlp->inDatap, 0);
2311 if (!cellp) return CM_ERROR_NOSUCHCELL;
2313 lock_ObtainMutex(&userp->mx);
2315 ucellp = cm_GetUCell(userp, cellp);
2317 lock_ReleaseMutex(&userp->mx);
2318 return CM_ERROR_NOMORETOKENS;
2321 osi_Log1(smb_logp,"cm_IoctlDelToken ucellp %lx", ucellp);
2323 if (ucellp->ticketp) {
2324 free(ucellp->ticketp);
2325 ucellp->ticketp = NULL;
2327 ucellp->ticketLen = 0;
2328 memset(ucellp->sessionKey.data, 0, 8);
2330 ucellp->expirationTime = 0;
2331 ucellp->userName[0] = '\0';
2332 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2335 lock_ReleaseMutex(&userp->mx);
2337 cm_ResetACLCache(userp);
2342 long cm_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2346 lock_ObtainMutex(&userp->mx);
2348 for (ucellp = userp->cellInfop; ucellp; ucellp = ucellp->nextp) {
2349 osi_Log1(smb_logp,"cm_IoctlDelAllToken ucellp %lx", ucellp);
2351 if (ucellp->ticketp) {
2352 free(ucellp->ticketp);
2353 ucellp->ticketp = NULL;
2355 ucellp->ticketLen = 0;
2356 memset(ucellp->sessionKey.data, 0, 8);
2358 ucellp->expirationTime = 0;
2359 ucellp->userName[0] = '\0';
2360 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2364 lock_ReleaseMutex(&userp->mx);
2366 cm_ResetACLCache(userp);
2371 long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
2373 char afspath[MAX_PATH];
2375 int nextAutoSubmount;
2377 DWORD dwType, dwSize;
2382 cm_SkipIoctlPath(ioctlp);
2384 /* Serialize this one, to prevent simultaneous mods
2387 lock_ObtainMutex(&cm_Afsdsbmt_Lock);
2389 /* Parse the input parameters--first the required afs path,
2390 * then the requested submount name (which may be "").
2392 cm_NormalizeAfsPath (afspath, sizeof(afspath), ioctlp->inDatap);
2393 submountreqp = ioctlp->inDatap + (strlen(ioctlp->inDatap)+1);
2395 /* If the caller supplied a suggested submount name, see if
2396 * that submount name is in use... if so, the submount's path
2397 * has to match our path.
2400 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
2401 AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
2404 REG_OPTION_NON_VOLATILE,
2405 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
2410 if (submountreqp && *submountreqp) {
2411 char submountPathNormalized[MAX_PATH];
2412 char submountPath[MAX_PATH];
2414 dwSize = sizeof(submountPath);
2415 status = RegQueryValueEx( hkSubmounts, submountreqp, 0,
2416 &dwType, submountPath, &dwSize);
2418 if (status != ERROR_SUCCESS) {
2420 /* The suggested submount name isn't in use now--
2421 * so we can safely map the requested submount name
2422 * to the supplied path. Remember not to write the
2423 * leading "/afs" when writing out the submount.
2425 RegSetValueEx( hkSubmounts, submountreqp, 0,
2427 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2428 &afspath[strlen(cm_mountRoot)]:"/",
2429 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2430 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2432 RegCloseKey( hkSubmounts );
2433 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountreqp);
2434 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2435 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2439 /* The suggested submount name is already in use--if the
2440 * supplied path matches the submount's path, we can still
2441 * use the suggested submount name.
2443 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2444 if (!strcmp (submountPathNormalized, afspath)) {
2445 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountreqp);
2446 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2447 RegCloseKey( hkSubmounts );
2448 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2453 RegQueryInfoKey( hkSubmounts,
2455 NULL, /* lpcClass */
2456 NULL, /* lpReserved */
2457 NULL, /* lpcSubKeys */
2458 NULL, /* lpcMaxSubKeyLen */
2459 NULL, /* lpcMaxClassLen */
2460 &dwSubmounts, /* lpcValues */
2461 NULL, /* lpcMaxValueNameLen */
2462 NULL, /* lpcMaxValueLen */
2463 NULL, /* lpcbSecurityDescriptor */
2464 NULL /* lpftLastWriteTime */
2468 /* Having obtained a list of all available submounts, start
2469 * searching that list for a path which matches the requested
2470 * AFS path. We'll also keep track of the highest "auto15"/"auto47"
2471 * submount, in case we need to add a new one later.
2474 nextAutoSubmount = 1;
2476 for ( dwIndex = 0; dwIndex < dwSubmounts; dwIndex ++ ) {
2477 char submountPathNormalized[MAX_PATH];
2478 char submountPath[MAX_PATH] = "";
2479 DWORD submountPathLen = sizeof(submountPath);
2480 char submountName[MAX_PATH];
2481 DWORD submountNameLen = sizeof(submountName);
2484 RegEnumValue( hkSubmounts, dwIndex, submountName, &submountNameLen, NULL,
2485 &dwType, submountPath, &submountPathLen);
2486 if (dwType == REG_EXPAND_SZ) {
2488 StringCbCopyA(buf, MAX_PATH, submountPath);
2489 submountPathLen = ExpandEnvironmentStrings(buf, submountPath, MAX_PATH);
2490 if (submountPathLen > MAX_PATH)
2494 /* If this is an Auto### submount, remember its ### value */
2495 if ((!strnicmp (submountName, "auto", 4)) &&
2496 (isdigit (submountName[strlen("auto")]))) {
2497 int thisAutoSubmount;
2498 thisAutoSubmount = atoi (&submountName[strlen("auto")]);
2499 nextAutoSubmount = max (nextAutoSubmount,
2500 thisAutoSubmount+1);
2503 if ((submountPathLen == 0) ||
2504 (submountPathLen == sizeof(submountPath) - 1)) {
2508 /* See if the path for this submount matches the path
2509 * that our caller specified. If so, we can return
2512 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2513 if (!strcmp (submountPathNormalized, afspath)) {
2514 StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountName);
2515 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2516 RegCloseKey(hkSubmounts);
2517 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2523 /* We've been through the entire list of existing submounts, and
2524 * didn't find any which matched the specified path. So, we'll
2525 * just have to add one. Remember not to write the leading "/afs"
2526 * when writing out the submount.
2529 StringCbPrintfA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "auto%ld", nextAutoSubmount);
2531 RegSetValueEx( hkSubmounts,
2535 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2536 &afspath[strlen(cm_mountRoot)]:"/",
2537 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2538 (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2540 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2541 RegCloseKey(hkSubmounts);
2542 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2546 long cm_IoctlGetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2548 memcpy(ioctlp->outDatap, &cryptall, sizeof(cryptall));
2549 ioctlp->outDatap += sizeof(cryptall);
2554 long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2556 afs_int32 c = cryptall;
2558 cm_SkipIoctlPath(ioctlp);
2560 memcpy(&cryptall, ioctlp->inDatap, sizeof(cryptall));
2562 if (c != cryptall) {
2564 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_ON);
2566 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_OFF);
2571 long cm_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp)
2576 cm_SkipIoctlPath(ioctlp);
2578 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2579 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2582 if (flags & AFSCALL_RXSTATS_ENABLE) {
2583 rx_enableProcessRPCStats();
2585 if (flags & AFSCALL_RXSTATS_DISABLE) {
2586 rx_disableProcessRPCStats();
2588 if (flags & AFSCALL_RXSTATS_CLEAR) {
2589 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
2594 long cm_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp)
2599 cm_SkipIoctlPath(ioctlp);
2601 memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
2602 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
2605 if (flags & AFSCALL_RXSTATS_ENABLE) {
2606 rx_enablePeerRPCStats();
2608 if (flags & AFSCALL_RXSTATS_DISABLE) {
2609 rx_disablePeerRPCStats();
2611 if (flags & AFSCALL_RXSTATS_CLEAR) {
2612 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
2617 long cm_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp)
2619 smb_user_t *uidp = ioctlp->uidp;
2621 if (uidp && uidp->unp) {
2622 memcpy(ioctlp->outDatap, uidp->unp->name, strlen(uidp->unp->name));
2623 ioctlp->outDatap += strlen(uidp->unp->name);
2629 long cm_IoctlUUIDControl(struct smb_ioctl * ioctlp, struct cm_user *userp)
2634 memcpy(&cmd, ioctlp->inDatap, sizeof(long));
2636 if (cmd) { /* generate a new UUID */
2637 UuidCreate((UUID *) &uuid);
2638 cm_data.Uuid = uuid;
2639 cm_ForceNewConnectionsAllServers();
2642 memcpy(ioctlp->outDatap, &cm_data.Uuid, sizeof(cm_data.Uuid));
2643 ioctlp->outDatap += sizeof(cm_data.Uuid);
2649 * functions to dump contents of various structures.
2650 * In debug build (linked with crt debug library) will dump allocated but not freed memory
2652 extern int cm_DumpSCache(FILE *outputFile, char *cookie, int lock);
2653 extern int cm_DumpBufHashTable(FILE *outputFile, char *cookie, int lock);
2654 extern int smb_DumpVCP(FILE *outputFile, char *cookie, int lock);
2656 long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
2660 char logfileName[MAX_PATH+1];
2665 static _CrtMemState memstate;
2668 cm_SkipIoctlPath(ioctlp);
2669 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
2671 dwSize = GetEnvironmentVariable("TEMP", logfileName, sizeof(logfileName));
2672 if ( dwSize == 0 || dwSize > sizeof(logfileName) )
2674 GetWindowsDirectory(logfileName, sizeof(logfileName));
2676 strncat(logfileName, "\\afsd_alloc.log", sizeof(logfileName));
2678 hLogFile = CreateFile(logfileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2684 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2685 ioctlp->outDatap += sizeof(long);
2690 SetFilePointer(hLogFile, 0, NULL, FILE_END);
2692 cookie = inValue ? "b" : "e";
2698 _CrtMemCheckpoint(&memstate);
2702 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2703 _CrtSetReportFile(_CRT_WARN, hLogFile);
2704 _CrtMemDumpAllObjectsSince(&memstate);
2708 /* dump all interesting data */
2709 cm_DumpCells(hLogFile, cookie, 1);
2710 cm_DumpVolumes(hLogFile, cookie, 1);
2711 cm_DumpSCache(hLogFile, cookie, 1);
2712 cm_DumpBufHashTable(hLogFile, cookie, 1);
2713 smb_DumpVCP(hLogFile, cookie, 1);
2715 CloseHandle(hLogFile);
2717 inValue = 0; /* success */
2718 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2719 ioctlp->outDatap += sizeof(long);
2726 cm_CheckServersStatus(cm_serverRef_t *serversp)
2729 cm_serverRef_t *tsrp;
2731 int someBusy = 0, someOffline = 0, allOffline = 1, allBusy = 1, allDown = 1;
2733 if (serversp == NULL) {
2734 osi_Log1(afsd_logp, "cm_CheckServersStatus returning 0x%x", CM_ERROR_ALLDOWN);
2735 return CM_ERROR_ALLDOWN;
2738 lock_ObtainRead(&cm_serverLock);
2739 for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
2740 if (tsp = tsrp->server) {
2741 cm_GetServerNoLock(tsp);
2742 lock_ReleaseRead(&cm_serverLock);
2743 if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
2745 if (tsrp->status == srv_busy) {
2748 } else if (tsrp->status == srv_offline) {
2758 lock_ObtainRead(&cm_serverLock);
2759 cm_PutServerNoLock(tsp);
2762 lock_ReleaseRead(&cm_serverLock);
2765 code = CM_ERROR_ALLDOWN;
2767 code = CM_ERROR_ALLBUSY;
2768 else if (allOffline || (someBusy && someOffline))
2769 code = CM_ERROR_ALLOFFLINE;
2772 osi_Log1(afsd_logp, "cm_CheckServersStatus returning 0x%x", code);
2777 long cm_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp)
2783 cm_vol_state_t *statep;
2789 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
2793 volume = scp->fid.volume;
2795 cellp = cm_FindCellByID(scp->fid.cell);
2797 cm_ReleaseSCache(scp);
2800 return CM_ERROR_NOSUCHCELL;
2802 code = cm_GetVolumeByID(cellp, volume, userp, &req, CM_GETVOL_FLAG_CREATE, &tvp);
2806 if (volume == tvp->rw.ID)
2808 else if (volume == tvp->ro.ID)
2813 switch (statep->state) {
2819 code = CM_ERROR_ALLBUSY;
2822 code = CM_ERROR_ALLOFFLINE;
2825 code = CM_ERROR_ALLDOWN;