1/* 2 * Copyright (c) 2000-2001, Boris Popov 3 * All rights reserved. 4 * 5 * Portions Copyright (C) 2001 - 2013 Apple Inc. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Boris Popov. 18 * 4. Neither the name of the author nor the names of any co-contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 */ 35 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/proc.h> 39#include <sys/kernel.h> 40#include <sys/sysctl.h> 41#include <sys/vnode.h> 42#include <sys/mount.h> 43#include <sys/stat.h> 44#include <sys/malloc.h> 45#include <sys/sysctl.h> 46#include <libkern/OSAtomic.h> 47 48#include <sys/kauth.h> 49 50#include <sys/syslog.h> 51#include <sys/smb_apple.h> 52#include <sys/mchain.h> 53 54#include <netsmb/smb.h> 55#include <netsmb/smb_2.h> 56#include <netsmb/smb_conn.h> 57#include <netsmb/smb_subr.h> 58#include <netsmb/smb_dev.h> 59#include <netsmb/smb_sleephandler.h> 60#include <netsmb/smb_rq.h> 61 62#include <smbfs/smbfs.h> 63#include <smbfs/smbfs_node.h> 64#include <smbfs/smbfs_subr.h> 65#include <smbfs/smbfs_subr_2.h> 66#include <smbclient/smbclient_internal.h> 67#include "smbfs_security.h" 68#include <Triggers/triggers.h> 69 70#include <sys/buf.h> 71 72int smbfs_module_start(kmod_info_t *ki, void *data); 73int smbfs_module_stop(kmod_info_t *ki, void *data); 74static int smbfs_root(struct mount *, vnode_t *, vfs_context_t); 75 76#define SMB_FSYNC_TIMO 30 77 78#ifdef SMB_DEBUG 79__attribute__((visibility("hidden"))) int smbfs_loglevel = SMB_LOW_LOG_LEVEL; 80#else // SMB_DEBUG 81__attribute__((visibility("hidden"))) int smbfs_loglevel = SMB_NO_LOG_LEVEL; 82#endif // SMB_DEBUG 83 84__attribute__((visibility("hidden"))) uint32_t smbfs_deadtimer = DEAD_TIMEOUT; 85__attribute__((visibility("hidden"))) uint32_t smbfs_hard_deadtimer = HARD_DEAD_TIMER; 86__attribute__((visibility("hidden"))) uint32_t smbfs_trigger_deadtimer = TRIGGER_DEAD_TIMEOUT; 87 88static int smbfs_version = SMBFS_VERSION; 89static int mount_cnt = 0; 90int dev_open_cnt = 0; 91int unloadInProgress = FALSE; 92 93lck_grp_attr_t *smbfs_group_attr; 94lck_attr_t *smbfs_lock_attr; 95lck_grp_t *smbfs_mutex_group; 96lck_grp_t *smbfs_rwlock_group; 97 98lck_grp_attr_t *co_grp_attr; 99lck_grp_t *co_lck_group; 100lck_attr_t *co_lck_attr; 101 102lck_grp_attr_t *vc_credits_grp_attr; 103lck_grp_t *vc_credits_lck_group; 104lck_attr_t *vc_credits_lck_attr; 105 106lck_grp_attr_t *vcst_grp_attr; 107lck_grp_t *vcst_lck_group; 108lck_attr_t *vcst_lck_attr; 109 110lck_grp_attr_t *ssst_grp_attr; 111lck_grp_t *ssst_lck_group; 112lck_attr_t *ssst_lck_attr; 113 114lck_grp_attr_t *fid_lck_grp_attr; 115lck_grp_t *fid_lck_grp; 116lck_attr_t *fid_lck_attr; 117 118lck_grp_attr_t *iodflags_grp_attr; 119lck_grp_t *iodflags_lck_group; 120lck_attr_t *iodflags_lck_attr; 121 122lck_grp_attr_t *iodrq_grp_attr; 123lck_grp_t *iodrq_lck_group; 124lck_attr_t *iodrq_lck_attr; 125 126lck_grp_attr_t *iodev_grp_attr; 127lck_grp_t *iodev_lck_group; 128lck_attr_t *iodev_lck_attr; 129 130lck_grp_attr_t *srs_grp_attr; 131lck_grp_t *srs_lck_group; 132lck_attr_t *srs_lck_attr; 133 134lck_grp_attr_t *nbp_grp_attr; 135lck_grp_t *nbp_lck_group; 136lck_attr_t *nbp_lck_attr; 137 138lck_grp_attr_t *dev_lck_grp_attr; 139lck_grp_t *dev_lck_grp; 140lck_attr_t *dev_lck_attr; 141lck_rw_t *dev_rw_lck; 142 143lck_grp_attr_t *hash_lck_grp_attr; 144lck_grp_t *hash_lck_grp; 145lck_attr_t *hash_lck_attr; 146 147struct smbmnt_carg { 148 vfs_context_t context; 149 struct mount *mp; 150 int found; 151}; 152 153static uint32_t smb_maxsegreadsize = 1024 * 1024 * 2; 154static uint32_t smb_maxsegwritesize = 1024 * 1024 * 2; 155 156SYSCTL_DECL(_net_smb); 157SYSCTL_NODE(_net_smb, OID_AUTO, fs, CTLFLAG_RW, 0, "SMB/CIFS file system"); 158SYSCTL_INT(_net_smb_fs, OID_AUTO, version, CTLFLAG_RD, &smbfs_version, 0, ""); 159SYSCTL_INT(_net_smb_fs, OID_AUTO, loglevel, CTLFLAG_RW, &smbfs_loglevel, 0, ""); 160SYSCTL_INT(_net_smb_fs, OID_AUTO, kern_deadtimer, CTLFLAG_RW, &smbfs_deadtimer, DEAD_TIMEOUT, ""); 161SYSCTL_INT(_net_smb_fs, OID_AUTO, kern_hard_deadtimer, CTLFLAG_RW, &smbfs_hard_deadtimer, HARD_DEAD_TIMER, ""); 162SYSCTL_INT(_net_smb_fs, OID_AUTO, kern_soft_deadtimer, CTLFLAG_RW, &smbfs_trigger_deadtimer, TRIGGER_DEAD_TIMEOUT, ""); 163SYSCTL_INT(_net_smb_fs, OID_AUTO, maxsegreadsize, CTLFLAG_RW, &smb_maxsegreadsize, 0, ""); 164SYSCTL_INT(_net_smb_fs, OID_AUTO, maxsegwritesize, CTLFLAG_RW, &smb_maxsegwritesize, 0, ""); 165 166 167extern struct sysctl_oid sysctl__net_smb; 168extern struct sysctl_oid sysctl__net_smb_fs_version; 169extern struct sysctl_oid sysctl__net_smb_fs_loglevel; 170extern struct sysctl_oid sysctl__net_smb_fs_kern_deadtimer; 171extern struct sysctl_oid sysctl__net_smb_fs_kern_hard_deadtimer; 172extern struct sysctl_oid sysctl__net_smb_fs_kern_soft_deadtimer; 173extern struct sysctl_oid sysctl__net_smb_fs_tcpsndbuf; 174extern struct sysctl_oid sysctl__net_smb_fs_tcprcvbuf; 175extern struct sysctl_oid sysctl__net_smb_fs_maxwrite; 176extern struct sysctl_oid sysctl__net_smb_fs_maxread; 177extern struct sysctl_oid sysctl__net_smb_fs_maxsegreadsize; 178extern struct sysctl_oid sysctl__net_smb_fs_maxsegwritesize; 179 180 181MALLOC_DEFINE(M_SMBFSHASH, "SMBFS hash", "SMBFS hash table"); 182 183#ifndef VFS_CTL_DISC 184#define VFS_CTL_DISC 0x00010008 /* Server is disconnected */ 185#endif 186 187static void 188smbfs_lock_init() 189{ 190 hash_lck_attr = lck_attr_alloc_init(); 191 hash_lck_grp_attr = lck_grp_attr_alloc_init(); 192 hash_lck_grp = lck_grp_alloc_init("smb-hash", hash_lck_grp_attr); 193 194 smbfs_lock_attr = lck_attr_alloc_init(); 195 smbfs_group_attr = lck_grp_attr_alloc_init(); 196 smbfs_mutex_group = lck_grp_alloc_init("smb-mutex", smbfs_group_attr); 197 smbfs_rwlock_group = lck_grp_alloc_init("smbfs-rwlock", smbfs_group_attr); 198} 199 200static void 201smbfs_lock_uninit() 202{ 203 lck_grp_free(smbfs_mutex_group); 204 lck_grp_free(smbfs_rwlock_group); 205 lck_grp_attr_free(smbfs_group_attr); 206 lck_attr_free(smbfs_lock_attr); 207 208 lck_grp_free(hash_lck_grp); 209 lck_grp_attr_free(hash_lck_grp_attr); 210 lck_attr_free(hash_lck_attr); 211} 212 213static void 214smbnet_lock_init() 215{ 216 co_lck_attr = lck_attr_alloc_init(); 217 co_grp_attr = lck_grp_attr_alloc_init(); 218 co_lck_group = lck_grp_alloc_init("smb-co", co_grp_attr); 219 220 vc_credits_lck_attr = lck_attr_alloc_init(); 221 vc_credits_grp_attr = lck_grp_attr_alloc_init(); 222 vc_credits_lck_group = lck_grp_alloc_init("smb-vc_credits", vc_credits_grp_attr); 223 224 vcst_lck_attr = lck_attr_alloc_init(); 225 vcst_grp_attr = lck_grp_attr_alloc_init(); 226 vcst_lck_group = lck_grp_alloc_init("smb-vcst", vcst_grp_attr); 227 228 ssst_lck_attr = lck_attr_alloc_init(); 229 ssst_grp_attr = lck_grp_attr_alloc_init(); 230 ssst_lck_group = lck_grp_alloc_init("smb-ssst", ssst_grp_attr); 231 232 fid_lck_attr = lck_attr_alloc_init(); 233 fid_lck_grp_attr = lck_grp_attr_alloc_init(); 234 fid_lck_grp = lck_grp_alloc_init("smb-fid", fid_lck_grp_attr); 235 236 iodflags_lck_attr = lck_attr_alloc_init(); 237 iodflags_grp_attr = lck_grp_attr_alloc_init(); 238 iodflags_lck_group = lck_grp_alloc_init("smb-iodflags", iodflags_grp_attr); 239 240 iodrq_lck_attr = lck_attr_alloc_init(); 241 iodrq_grp_attr = lck_grp_attr_alloc_init(); 242 iodrq_lck_group = lck_grp_alloc_init("smb-iodrq", iodrq_grp_attr); 243 244 iodev_lck_attr = lck_attr_alloc_init(); 245 iodev_grp_attr = lck_grp_attr_alloc_init(); 246 iodev_lck_group = lck_grp_alloc_init("smb-iodev", iodev_grp_attr); 247 248 srs_lck_attr = lck_attr_alloc_init(); 249 srs_grp_attr = lck_grp_attr_alloc_init(); 250 srs_lck_group = lck_grp_alloc_init("smb-srs", srs_grp_attr); 251 252 nbp_lck_attr = lck_attr_alloc_init(); 253 nbp_grp_attr = lck_grp_attr_alloc_init(); 254 nbp_lck_group = lck_grp_alloc_init("smb-nbp", nbp_grp_attr); 255 256 dev_lck_attr = lck_attr_alloc_init(); 257 dev_lck_grp_attr = lck_grp_attr_alloc_init(); 258 dev_lck_grp = lck_grp_alloc_init("smb-dev", dev_lck_grp_attr); 259 dev_rw_lck = lck_rw_alloc_init(dev_lck_grp, dev_lck_attr); 260} 261 262static void 263smbnet_lock_uninit() 264{ 265 lck_grp_free(dev_lck_grp); 266 lck_grp_attr_free(dev_lck_grp_attr); 267 lck_attr_free(dev_lck_attr); 268 269 lck_grp_free(nbp_lck_group); 270 lck_grp_attr_free(nbp_grp_attr); 271 lck_attr_free(nbp_lck_attr); 272 273 lck_grp_free(srs_lck_group); 274 lck_grp_attr_free(srs_grp_attr); 275 lck_attr_free(srs_lck_attr); 276 277 lck_grp_free(iodev_lck_group); 278 lck_grp_attr_free(iodev_grp_attr); 279 lck_attr_free(iodev_lck_attr); 280 281 lck_grp_free(iodrq_lck_group); 282 lck_grp_attr_free(iodrq_grp_attr); 283 lck_attr_free(iodrq_lck_attr); 284 285 lck_grp_free(iodflags_lck_group); 286 lck_grp_attr_free(iodflags_grp_attr); 287 lck_attr_free(iodflags_lck_attr); 288 289 lck_grp_free(ssst_lck_group); 290 lck_grp_attr_free(ssst_grp_attr); 291 lck_attr_free(ssst_lck_attr); 292 293 lck_grp_free(fid_lck_grp); 294 lck_grp_attr_free(fid_lck_grp_attr); 295 lck_attr_free(fid_lck_attr); 296 297 lck_grp_free(vc_credits_lck_group); 298 lck_grp_attr_free(vc_credits_grp_attr); 299 lck_attr_free(vc_credits_lck_attr); 300 301 lck_grp_free(vcst_lck_group); 302 lck_grp_attr_free(vcst_grp_attr); 303 lck_attr_free(vcst_lck_attr); 304 305 lck_grp_free(co_lck_group); 306 lck_grp_attr_free(co_grp_attr); 307 lck_attr_free(co_lck_attr); 308} 309 310/* 311 * Need to check and make sure the server is in the same domain, if not 312 * then we need to turn off ACL support. 313 */ 314static void 315isServerInSameDomian(struct smb_share *share, struct smbmount *smp) 316{ 317 /* Just to be safe */ 318 if (smp->ntwrk_sids) { 319 SMB_FREE(smp->ntwrk_sids, M_TEMP); 320 } 321 322 smp->ntwrk_sids_cnt = 0; 323 if (SSTOVC(share)->vc_flags & SMBV_NETWORK_SID) { 324 /* See if the VC network SID is known by Directory Service */ 325 if ((smp->sm_args.altflags & SMBFS_MNT_DEBUG_ACL_ON) || 326 (smp->sm_args.altflags & SMBFS_MNT_TIME_MACHINE) || 327 (smbfs_is_sid_known(&SSTOVC(share)->vc_ntwrk_sid))) { 328 SMB_MALLOC(smp->ntwrk_sids, ntsid_t *, sizeof(ntsid_t), M_TEMP, M_WAITOK); 329 memcpy(smp->ntwrk_sids, &SSTOVC(share)->vc_ntwrk_sid, sizeof(ntsid_t)); 330 smp->ntwrk_sids_cnt = 1; 331 return; 332 } 333 } 334 SMBWARNING("%s: can't determine if server is in the same domain, turning off ACLs support.\n", 335 vfs_statfs(smp->sm_mp)->f_mntfromname); 336 share->ss_attributes &= ~FILE_PERSISTENT_ACLS; 337} 338 339/* 340 * The share needs to be locked before calling this rouitne! 341 * 342 * smbfs_down is called when we have a message that timeout or we are 343 * starting a reconnect. It uses vfs_event_signal() to tell interested parties 344 * the connection with the server is "down". 345 */ 346static int 347smbfs_down(struct smb_share *share, int timeToNotify) 348{ 349 struct smbmount *smp; 350 int treenct = 1; 351 352 smp = share->ss_mount; 353 /* We have already unmounted or we are being force unmount, we are done */ 354 if ((smp == NULL) || (vfs_isforce(smp->sm_mp))) { 355 return 0; 356 } 357 358 /* 359 * They are attempted to unmount it so don't count this one. 360 * Still notify them they may want to force unmount it. 361 */ 362 if (vfs_isunmount(smp->sm_mp)) { 363 treenct = 0; 364 } 365 366 /* Attempt to remount the Dfs volume */ 367 if (treenct && (smp->sm_args.altflags & SMBFS_MNT_DFS_SHARE) && 368 !(smp->sm_status & SM_STATUS_REMOUNT)) { 369 smp->sm_status |= SM_STATUS_REMOUNT; 370 /* Never do Dfs failover if the share is FAT or doing Unix Extensions */ 371 if ((IPC_PORT_VALID(SSTOVC(share)->vc_gss.gss_mp)) && 372 (share->ss_fstype != SMB_FS_FAT) && !(UNIX_CAPS(share))) { 373 374 /* Call autofs with the fsid to start the remount */ 375 SMBERROR("Remounting %s/%s\n", SSTOVC(share)->vc_srvname, 376 share->ss_name); 377 if (SMBRemountServer(&(vfs_statfs(smp->sm_mp))->f_fsid, 378 sizeof(vfs_statfs(smp->sm_mp)->f_fsid), 379 SSTOVC(share)->vc_gss.gss_asid)) { 380 /* Something went wrong try again next time */ 381 SMBERROR("Something went wrong with remounting %s/%s\n", 382 SSTOVC(share)->vc_srvname, share->ss_name); 383 smp->sm_status &= ~SM_STATUS_REMOUNT; 384 } 385 } else { 386 SMBWARNING("Skipping remounting %s/%s, file system type mismatch\n", 387 SSTOVC(share)->vc_srvname, share->ss_name); 388 } 389 } 390 391 /* We need to notify and we haven't notified before then notify */ 392 if (timeToNotify && !(smp->sm_status & SM_STATUS_DOWN)) { 393 int dontNotify = ((smp->sm_args.altflags & SMBFS_MNT_SOFT) && 394 (vfs_flags(smp->sm_mp) & MNT_DONTBROWSE)); 395 396 SMBWARNING("Share %s not responding\n", share->ss_name); 397 /* Never notify on soft-mounted nobrowse volumes */ 398 if (!dontNotify) { 399 vfs_event_signal(&(vfs_statfs(smp->sm_mp))->f_fsid, VQ_NOTRESP, 0); 400 } 401 smp->sm_status |= SM_STATUS_DOWN; 402 } 403 return treenct; 404} 405 406/* 407 * The share needs to be locked before calling this rouitne! 408 * 409 * smbfs_up is called when we receive a successful response to a message or we have 410 * successfully reconnect. It uses vfs_event_signal() to tell interested parties 411 * the connection is OK again if the connection was having problems. 412 */ 413static void 414smbfs_up(struct smb_share *share, int reconnect) 415{ 416 struct smbmount *smp; 417 418 smp = share->ss_mount; 419 420 /* We have already unmounted or we are being force unmount, we are done */ 421 if ((smp == NULL) || (vfs_isforce(smp->sm_mp))) { 422 return; 423 } 424 425 if (reconnect) { 426 smbfs_reconnect(smp); 427 } 428 429 /* We are done remounting, either we reconnect or the remount worked */ 430 smp->sm_status &= ~SM_STATUS_REMOUNT; 431 432 if (smp->sm_status & SM_STATUS_DOWN) { 433 int dontNotify = ((smp->sm_args.altflags & SMBFS_MNT_SOFT) && 434 (vfs_flags(smp->sm_mp) & MNT_DONTBROWSE)); 435 436 smp->sm_status &= ~SM_STATUS_DOWN; 437 SMBWARNING("Share %s responding\n", share->ss_name); 438 /* Never notify on soft-mounted nobrowse volumes */ 439 if (!dontNotify) { 440 vfs_event_signal(&(vfs_statfs(smp->sm_mp))->f_fsid, VQ_NOTRESP, 1); 441 } 442 } 443} 444 445/* 446 * The share needs to be locked before calling this rouitne! 447 * 448 * smbfs_dead is called when the share is no longer reachable and the dead timer 449 * has gone off. It uses vfs_event_signal() to tell interested parties 450 * the connection is gone. This should cause the mount to get forced unmounted. 451 */ 452static void 453smbfs_dead(struct smb_share *share) 454{ 455 struct smbmount *smp; 456 457 smp = share->ss_mount; 458 if (smp && !(smp->sm_status & SM_STATUS_DEAD)) { 459 /* If we have a ss_mount then we have a sm_mp */ 460 SMBWARNING("Share %s has gone away, unmounting the volume\n", 461 share->ss_name); 462 vfs_event_signal(&(vfs_statfs(smp->sm_mp))->f_fsid, VQ_DEAD, 0); 463 smp->sm_status |= SM_STATUS_DEAD; 464 } 465} 466 467/* 468 * The share needs to be locked before calling this rouitne! 469 * 470 * See if the volume is being forced unmounted. In the future we will also 471 * check for the share getting changed out because of Dfs trigger remounts. 472 */ 473static int 474smbfs_is_going_away(struct smb_share* share) 475{ 476 struct smbmount *smp; 477 478 if (share->ss_flags & SMBS_GOING_AWAY) { 479 /* Once marked as going away, always going away */ 480 return TRUE; 481 } 482 483 smp = share->ss_mount; 484 485 /* If we have a ss_mount then we have a sm_mp */ 486 if (smp && (vfs_isforce(smp->sm_mp))) { 487 share->ss_flags |= SMBS_GOING_AWAY; 488 return TRUE; 489 } 490 491 return FALSE; 492} 493 494/* 495 * Fill in the smb_remount_info structure with all the information that user 496 * land needs to remount the volume. 497 */ 498static int 499smbfs_remountInfo(struct mount *mp, struct smb_share *share, 500 struct smb_remount_info *info) 501{ 502#ifdef SMBDEBUG_REMOUNT 503 /* Used for testing only, pretend we are in reconnect. */ 504 share->ss_flags |= SMBS_RECONNECTING; 505#endif // SMBDEBUG_REMOUNT 506 SMB_ASSERT(SSTOVC(share)->vc_gss.gss_cpn_len < sizeof(info->mntClientPrincipalName)); 507 bzero(info, sizeof(*info)); 508 info->version = REMOUNT_INFO_VERSION; 509 info->mntAuthFlags = SSTOVC(share)->vc_flags & SMBV_USER_LAND_MASK; 510 info->mntOwner = VFSTOSMBFS(mp)->sm_args.uid; 511 info->mntGroup = VFSTOSMBFS(mp)->sm_args.gid; 512 /* 513 * The default is 30 seconds, but this is setable with a sysctl. The timer 514 * has already started, but normally it takes only a couple of seconds to get 515 * to this point. 516 */ 517 info->mntDeadTimer = share->ss_dead_timer; 518 if (!info->mntDeadTimer) { 519 /* Never wait less than one second */ 520 info->mntDeadTimer = 1; 521 } 522 523 strlcpy(info->mntURL, vfs_statfs(mp)->f_mntfromname, sizeof(info->mntURL)); 524 strlcpy(info->mntClientPrincipalName, (char *)SSTOVC(share)->vc_gss.gss_cpn, 525 SSTOVC(share)->vc_gss.gss_cpn_len); 526 info->mntClientPrincipalNameType = SSTOVC(share)->vc_gss.gss_client_nt; 527 return 0; 528} 529 530/* 531 * Remount the volume by replacing the old share with the new share that was 532 * obtained using the device id. 533 */ 534 535static int 536smbfs_remount(int32_t dev, struct mount *mp, struct smbmount *smp, 537 vfs_context_t context) 538{ 539 int error = 0; 540 struct smb_share *share = NULL; 541 struct smb_share *new_share = NULL; 542 543 error = smb_dev2share(dev, &new_share); 544 if (error || !new_share) { 545 return (error) ? error : ENOMEM; 546 } 547 /* 548 * Can't completely protect from throwing away a perfectly good connection, 549 * but we can make the window pretty short. So if the old share is not in 550 * reconnect mode, we should just get out, nothing for us to do here. If 551 * for some strange reason the new share is the same as the old share 552 * just get out. We could have reconnected, found the same share and then 553 * the connection went down again. 554 */ 555 share = smb_get_share_with_reference(smp); 556 if (!(share->ss_flags & SMBS_RECONNECTING) || (new_share == share)) { 557 /* Done with the new share release the reference */ 558 smb_share_rele(new_share, context); 559 /* Mark that the remount completed, so it can be used again. */ 560 smp->sm_status &= ~SM_STATUS_REMOUNT; 561 smb_share_rele(share, context); 562 return EEXIST; 563 } 564 smb_share_rele(share, context); 565 566 /* 567 * We now lock the VFS from accessing either share until we are done here. 568 * All new VFS operations will be blocked, any old operation will continue 569 * until they need to access the smp or share again. 570 */ 571 lck_rw_lock_exclusive(&smp->sm_rw_sharelock); 572 /* 573 * Now block any calls to the new share, since nothing is really happening 574 * on the share this should be safe. But it could block other access on the 575 * new vc until we are done, but we never sleep here so that should be ok. 576 */ 577 lck_mtx_lock(&new_share->ss_shlock); 578 /* 579 * Finally lock the old share, This could block the vc reconnect code, but 580 * not much we can do about that here. Remember the mount holds a reference 581 * on the old share and we are under the lock now so we can access it 582 * directly without any issues. 583 */ 584 share = smp->sm_share; 585 lck_mtx_lock(&share->ss_shlock); 586 if (SSTOVC(new_share)->throttle_info) { 587 /* Taking a reference here will release the old reference */ 588 throttle_info_mount_ref(mp, SSTOVC(new_share)->throttle_info); 589 } else if (SSTOVC(share)->throttle_info) { 590 /* 591 * The new vc doesn't have any throttle info, but we have one on the 592 * old VC, release the reference. 593 */ 594 throttle_info_mount_rel(mp); 595 } 596 /* Take a volume count, since this share has a mount now */ 597 (void)OSAddAtomic(1, &SSTOVC(new_share)->vc_volume_cnt); 598 /* 599 * We support allowing information to changes on the VC and the share, except 600 * for information obtained from the smbfs_qfsattr, smbfs_unix_qfsattr, 601 * isServerInSameDomian, and smbfs_unix_whoami routines. Once ACLs are turned 602 * on they stay on, Better be in the same domain, nothing we can do about 603 * this one. So we have really only two issues here: 604 * 1. The file system types of the two shares don't match, FAT vs NTFS, need 605 * to prevent this from happening. We just can't support switching between 606 * dot underbar files and named streams, so we should never allow FAT 607 * file system to failover and we should never remount a FAT Share. 608 * 2. One of the shares supports UNIX Extensions and the other doesn't. If 609 * the old share is doing UNIX Extensions then never failover. If the new 610 * share does UNIX Extensions, ignore those and treat the server like any 611 * other Windows system. 612 */ 613 new_share->ss_fstype = share->ss_fstype; /* Always the same file system type */ 614 new_share->ss_attributes = share->ss_attributes; 615 new_share->ss_maxfilenamelen = share->ss_maxfilenamelen; 616 new_share->ss_unix_caps = share->ss_unix_caps; 617 new_share->ss_going_away = smbfs_is_going_away; 618 new_share->ss_down = smbfs_down; 619 new_share->ss_up = smbfs_up; 620 new_share->ss_dead = smbfs_dead; 621 new_share->ss_dead_timer = share->ss_dead_timer; 622 /* Now remove the mount point from the old share */ 623 share->ss_mount = NULL; 624 /* Now add the mount point to the new share */ 625 new_share->ss_mount = smp; 626 /* Now add the new share to the mount point */ 627 smp->sm_share = new_share; 628 smp->sm_status |= SM_STATUS_UPDATED; 629 SMBERROR("replacing %s/%s with %s/%s\n", SSTOVC(share)->vc_srvname, 630 share->ss_name, SSTOVC(new_share)->vc_srvname, new_share->ss_name); 631 /* Now unlock in reverse order */ 632 lck_mtx_unlock(&share->ss_shlock); 633 lck_mtx_unlock(&new_share->ss_shlock); 634 lck_rw_unlock_exclusive(&smp->sm_rw_sharelock); 635 smb_iod_errorout_share_request(share, ETIMEDOUT); 636 /* Remove the old share's volume count, since it no longer has a mount */ 637 (void)OSAddAtomic(-1, &SSTOVC(share)->vc_volume_cnt); 638 /* Release the old share */ 639 smb_share_rele(share, context); 640 /* Now get the new share and notify everyone we are up */ 641 share = smb_get_share_with_reference(smp); 642 smbfs_up(share, TRUE); 643 smb_share_rele(share, context); 644 return 0; 645} 646 647static int 648smbfs_mount(struct mount *mp, vnode_t devvp, user_addr_t data, vfs_context_t context) 649{ 650#pragma unused (devvp) 651 struct smb_mount_args *args = NULL; /* will hold data from mount request */ 652 struct smbmount *smp = NULL; 653 struct smb_share *share = NULL; 654 struct vfsioattr smbIOAttr; 655 vnode_t vp; 656 int error; 657 uint32_t stream_flags = 0; 658 659 SMB_LOG_KTRACE(SMB_DBG_MOUNT | DBG_FUNC_START, 0, 0, 0, 0, 0); 660 661 if (data == USER_ADDR_NULL) { 662 SMBDEBUG("missing data argument\n"); 663 error = EINVAL; 664 goto bad; 665 } 666 667 SMB_MALLOC(args, struct smb_mount_args *, sizeof(*args), M_SMBFSDATA, 668 M_WAITOK | M_ZERO); 669 if (!args) { 670 SMBDEBUG("Couldn't malloc the mount arguments!"); 671 error = ENOMEM; 672 goto bad; 673 } 674 error = copyin(data, (caddr_t)args, sizeof(*args)); 675 if (error) { 676 SMBDEBUG("Couldn't copyin the mount arguments!"); 677 goto bad; 678 } 679 680 if (args->version != SMB_IOC_STRUCT_VERSION) { 681 SMBERROR("Mount structure version mismatch: kernel=%d, mount=%d\n", 682 SMB_IOC_STRUCT_VERSION, args->version); 683 error = EINVAL; 684 goto bad; 685 } 686 687 /* Set the debug level, if set to us. */ 688 if (args->KernelLogLevel) { 689 smbfs_loglevel = args->KernelLogLevel; 690 } 691 /* 692 * Get the share and retain a reference count until we unmount or complete 693 * a mount update. The smb vfs policy requires that the share can only be 694 * passed into a routine if an extra reference has been taken on the share. 695 * Any routine require accessing the share from the mount point must call 696 * smb_get_share_with_reference to get a pointer to the share. No routine 697 * except mount and unmount should every access the mount points share 698 * directly. 699 */ 700 error = smb_dev2share(args->dev, &share); 701 if (error) { 702 SMBDEBUG("invalid device handle %d (%d)\n", args->dev, error); 703 goto bad; 704 } 705 706 /* Need to deal with the mount update here */ 707 if (vfs_isupdate(mp)) { 708 SMBERROR("MNT_UPDATE not supported!"); 709 error = ENOTSUP; 710 goto bad; 711 } 712 713 SMB_MALLOC(smp, struct smbmount*, sizeof(*smp), M_SMBFSDATA, M_WAITOK | M_ZERO); 714 if (smp == NULL) { 715 SMBDEBUG("Couldn't malloc the smb mount structure!"); 716 error = ENOMEM; 717 goto bad; 718 } 719 720 smp->sm_mp = mp; 721 vfs_setfsprivate(mp, (void *)smp); 722 723 /* alloc hash stuff */ 724 smp->sm_hash = hashinit(desiredvnodes, M_SMBFSHASH, &smp->sm_hashlen); 725 if (smp->sm_hash == NULL) 726 goto bad; 727 smp->sm_hashlock = lck_mtx_alloc_init(hash_lck_grp, hash_lck_attr); 728 729 lck_rw_init(&smp->sm_rw_sharelock, smbfs_rwlock_group, smbfs_lock_attr); 730 lck_mtx_init(&smp->sm_statfslock, smbfs_mutex_group, smbfs_lock_attr); 731 lck_mtx_init(&smp->sm_reclaim_lock, smbfs_mutex_group, smbfs_lock_attr); 732 lck_mtx_init(&smp->sm_svrmsg_lock, smbfs_mutex_group, smbfs_lock_attr); 733 734 lck_rw_lock_exclusive(&smp->sm_rw_sharelock); 735 smp->sm_share = share; 736 lck_rw_unlock_exclusive(&smp->sm_rw_sharelock); 737 smp->sm_rvp = NULL; 738 /* Save any passed in arguments that we may need */ 739 smp->sm_args.altflags = args->altflags; 740 smp->sm_args.uid = args->uid; 741 smp->sm_args.gid = args->gid; 742 error = kauth_cred_uid2guid(smp->sm_args.uid, &smp->sm_args.uuid); 743 if (error) { 744 SMBERROR("Couldn't get the mounted users UUID, uid = %d error = %d\n", 745 smp->sm_args.uid, error); 746 goto bad; 747 } 748 smp->sm_args.file_mode = args->file_mode & ACCESSPERMS; 749 smp->sm_args.dir_mode = args->dir_mode & ACCESSPERMS; 750 if (args->volume_name[0]) { 751 smp->sm_args.volume_name = smb_strndup(args->volume_name, 752 sizeof(args->volume_name)); 753 } else { 754 smp->sm_args.volume_name = NULL; 755 } 756 757 /* 758 * See if they sent use a submount path to use. 759 * This function also checks/cleans up the args->path and args->path_len 760 */ 761 if (args->path_len) { 762 smbfs_create_start_path(smp, args, SMB_UNICODE_STRINGS(SSTOVC(share))); 763 } 764 765 /* 766 * Validate the negotiate if SMB 2/3. smb2fs_smb_validate_neg_info will 767 * check for whether the session needs to be validated or not. 768 */ 769 if (!(smp->sm_args.altflags & SMBFS_MNT_VALIDATE_NEG_OFF)) { 770 if (SSTOVC(share)->vc_flags & SMBV_SMB2) { 771 error = smb2fs_smb_validate_neg_info(share, context); 772 if (error) { 773 SMBERROR("smb2fs_smb_validate_neg_info failed %d \n", error); 774 goto bad; 775 } 776 } 777 } 778 else { 779 SMBWARNING("Validate Negotiate is off in preferences\n"); 780 } 781 782 /* 783 * This call should be done from mount() in vfs layer. Not sure why each 784 * file system has to do it here, but go ahead and make an internal call to 785 * fill in the default values. 786 */ 787 error = smbfs_smb_statfs(smp, vfs_statfs(mp), context); 788 if (error) { 789 SMBDEBUG("smbfs_smb_statfs failed %d\n", error); 790 goto bad; 791 } 792 793 /* Copy in the from name, used for reconnects and other things */ 794 strlcpy(vfs_statfs(mp)->f_mntfromname, args->url_fromname, MAXPATHLEN); 795 796 /* Now get the mounted volumes unique id */ 797 smp->sm_args.unique_id_len = args->unique_id_len; 798 SMB_MALLOC(smp->sm_args.unique_id, unsigned char *, smp->sm_args.unique_id_len, 799 M_SMBFSDATA, M_WAITOK); 800 if (smp->sm_args.unique_id) { 801 bcopy(args->unique_id, smp->sm_args.unique_id, smp->sm_args.unique_id_len); 802 } else { 803 smp->sm_args.unique_id_len = 0; 804 } 805 SMB_FREE(args, M_SMBFSDATA); /* Done with the args free them */ 806 807 if (smp->sm_args.altflags & SMBFS_MNT_TIME_MACHINE) { 808 SMBWARNING("%s mounted using tm flag\n", vfs_statfs(mp)->f_mntfromname); 809 } 810 811 vfs_getnewfsid(mp); 812 813 if (SSTOVC(share)->vc_flags & SMBV_SMB2) { 814 /* Only SMB 2/3 uses File IDs or AAPL create context */ 815 if (smp->sm_args.altflags & SMBFS_MNT_FILE_IDS_OFF) { 816 /* Turn off File IDs */ 817 SMBWARNING("File IDs has been turned off for %s volume\n", 818 (smp->sm_args.volume_name) ? smp->sm_args.volume_name : ""); 819 SSTOVC(share)->vc_misc_flags &= ~SMBV_HAS_FILEIDS; 820 } 821 822 if (smp->sm_args.altflags & SMBFS_MNT_AAPL_OFF) { 823 /* Turn off AAPL */ 824 SMBWARNING("AAPL has been turned off for %s volume\n", 825 (smp->sm_args.volume_name) ? smp->sm_args.volume_name : ""); 826 SSTOVC(share)->vc_misc_flags |= SMBV_OTHER_SERVER; 827 } 828 } 829 830 /* 831 * Need to get the remote server's file system information 832 * here before we do anything else. Make sure we have the servers or 833 * the default value for ss_maxfilenamelen. NOTE: We use it in strnlen. 834 */ 835 smbfs_smb_qfsattr(smp, context); 836 837 /* Its a unix server see if it supports any of the UNIX extensions */ 838 if (UNIX_SERVER(SSTOVC(share))) { 839 smbfs_unix_qfsattr(share, context); 840 } 841 842 /* 843 * This volume was mounted as guest, turn off ACLs and set the mount point to 844 * ignore ownership. We will always return an owner of 99, and group of 99. 845 */ 846 if (SMBV_HAS_GUEST_ACCESS(SSTOVC(share))) { 847 if (share->ss_attributes & FILE_PERSISTENT_ACLS) { 848 SMB_LOG_ACCESS("%s was mounted as guest turning off ACLs support.\n", 849 vfs_statfs(mp)->f_mntfromname); 850 } 851 share->ss_attributes &= ~FILE_PERSISTENT_ACLS; 852 vfs_setflags(mp, MNT_IGNORE_OWNERSHIP); 853 } 854 855 /* Make sure the server is in the same domain, if not turn off acls */ 856 if (share->ss_attributes & FILE_PERSISTENT_ACLS) { 857 isServerInSameDomian(share, smp); 858 } 859 860 /* See if the server supports the who am I operation */ 861 if (UNIX_CAPS(share) & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP) { 862 smbfs_unix_whoami(share, smp, context); 863 } 864 865 error = smbfs_root(mp, &vp, context); 866 if (error) { 867 SMBDEBUG("The smbfs_root failed %d\n", error); 868 goto bad; 869 } 870 /* 871 * This UNIX Server says it supports the UNIX Extensions, but it doesn't 872 * support all the options we require. Turn off the UNIX Extensions that 873 * they don't support. 874 */ 875 if ((UNIX_CAPS(share) & UNIX_QFILEINFO_UNIX_INFO2_CAP) && 876 ((VTOSMB(vp)->n_flags_mask & EXT_REQUIRED_BY_MAC) != EXT_REQUIRED_BY_MAC)) { 877 /* Turn off the UNIX Info2 */ 878 UNIX_CAPS(share) &= ~(UNIX_SFILEINFO_UNIX_INFO2_CAP); 879 /* Must be Linux, turn on the unlink call so we can delete symlink files */ 880 UNIX_CAPS(share) |= UNIX_SFILEINFO_POSIX_UNLINK_CAP; 881 /* Force the root vnode to forget any UNIX Extensions Info */ 882 VTOSMB(vp)->attribute_cache_timer = 0; 883 VTOSMB(vp)->n_uid = KAUTH_UID_NONE; 884 VTOSMB(vp)->n_gid = KAUTH_GID_NONE; 885 } 886 vfs_setauthopaque (mp); 887 /* we can always answer access questions better than local VFS */ 888 vfs_setauthopaqueaccess (mp); 889 890 if (share->ss_attributes & FILE_PERSISTENT_ACLS) { 891 guid_t ntwrk_uuid = kauth_null_guid; 892 893 DBG_ASSERT(smp->ntwrk_sids); /* We should always have a network SID */ 894 SMB_LOG_ACCESS("%s support ACLs\n", vfs_statfs(mp)->f_mntfromname); 895 vfs_setextendedsecurity(mp); 896 /* Now test to see if we should be mapping the local user to the nework user */ 897 if (kauth_cred_ntsid2guid(smp->ntwrk_sids, &ntwrk_uuid)) { 898 smp->sm_flags |= MNT_MAPS_NETWORK_LOCAL_USER; 899 } else if (!kauth_guid_equal(&smp->sm_args.uuid, &ntwrk_uuid)) { 900 smp->sm_flags |= MNT_MAPS_NETWORK_LOCAL_USER; 901 } 902 } 903 else { 904 SMB_LOG_ACCESS("%s doesn't support ACLs\n", vfs_statfs(mp)->f_mntfromname); 905 vfs_clearextendedsecurity (mp); 906 } 907 908 if (SSTOVC(share)->vc_flags & SMBV_SMB2) { 909 if (share->ss_attributes & FILE_SUPPORTS_REPARSE_POINTS) { 910 smp->sm_flags |= MNT_SUPPORTS_REPARSE_SYMLINKS; 911 } 912 913 if (!(SSTOVC(share)->vc_misc_flags & SMBV_HAS_COPYCHUNK)) { 914 /* Check for CopyChunk support */ 915 if (!smb2fs_smb_cmpd_check_copyfile(share, VTOSMB(vp), context)) { 916 SSTOVC(share)->vc_misc_flags |= SMBV_HAS_COPYCHUNK; 917 } 918 } 919 } 920 else { 921 if ((share->ss_attributes & FILE_SUPPORTS_REPARSE_POINTS) && 922 (((!UNIX_CAPS(share)) || (SSTOVC(share)->vc_flags & SMBV_DARWIN)))) { 923 smp->sm_flags |= MNT_SUPPORTS_REPARSE_SYMLINKS; 924 } 925 } 926 927 /* 928 * This is a read-only volume, so change the mount flags so 929 * the finder will show it as a read-only volume. 930 */ 931 if (share->ss_attributes & FILE_READ_ONLY_VOLUME) { 932 vfs_setflags(mp, MNT_RDONLY); 933 } else if ((share->maxAccessRights & FILE_FULL_WRITE_ACCESS) == 0) { 934 SMB_LOG_ACCESS("Share ACL doesn't allow write access, maxAccessRights are 0x%x\n", 935 share->maxAccessRights); 936 vfs_setflags(mp, MNT_RDONLY); 937 } 938 939 /* 940 * We now default to have named streams on if the server supports named 941 * streams. The user can turn off named streams by setting the correct 942 * option in the nsmb.conf file. The "nsmb.conf" allows the user to turn 943 * off named streams per share. So now we only check for turning off named 944 * streams since the default is to have them on. 945 */ 946 if (share->ss_attributes & FILE_NAMED_STREAMS) { 947 if (!(smp->sm_args.altflags & SMBFS_MNT_STREAMS_ON)) { 948 share->ss_attributes &= ~FILE_NAMED_STREAMS; 949 } 950 } 951 952 if (!(SSTOVC(share)->vc_flags & SMBV_SMB2)) { 953 /* 954 * SMB 1 Only 955 * 956 * We now default to have named streams on if the server supports named 957 * streams. The user can turn off named streams by creating a file on 958 * the top level of the share called ".com.apple.smb.streams.off". 959 * 960 * .com.apple.smb.streams.off - If exist on top level of share means 961 * turn off streams. 962 */ 963 if (share->ss_attributes & FILE_NAMED_STREAMS) { 964 if (smbfs_smb_query_info(share, VTOSMB(vp), VREG, 965 SMB_STREAMS_OFF, sizeof(SMB_STREAMS_OFF) - 1, 966 NULL, context) == 0) { 967 share->ss_attributes &= ~FILE_NAMED_STREAMS; 968 } else if (! UNIX_SERVER(SSTOVC(share)) && 969 (smbfs_smb_qstreaminfo(share, VTOSMB(vp), VDIR, 970 NULL, 0, 971 SFM_DESKTOP_NAME, 972 NULL, NULL, 973 NULL, NULL, 974 &stream_flags, NULL, 975 context) == 0)) { 976 /* 977 * We would like to know if this is a really old Windows server 978 * with Services For Mac (SFM Volume), we skip this check for 979 * unix servers. 980 */ 981 smp->sm_flags |= MNT_IS_SFM_VOLUME; 982 } 983 } 984 } 985 986 /* 987 * The AFP code sets io_devblocksize to one, which is used by the Cluster IO 988 * code to decide what to do when writing past the eof. ClusterIO code uses 989 * the io_devblocksize to decided what size block to use when writing pass 990 * the eof. So a io_devblocksize of one means only write to the eof. Seems 991 * like a hack, but not sure what else to do at this point. Talk this over 992 * with Joe and he wants to get back to it later. 993 */ 994 vfs_ioattr(mp, &smbIOAttr); /* get the current settings */ 995 smbIOAttr.io_devblocksize = 1; 996 997 /* 998 * io_maxreadcnt/io_maxwritecnt is the IO size that we want passed to us 999 * from UBC. 1000 * 1001 * io_maxsegreadsize/io_maxsegwritesize is the hardware limited max size, 1002 * but we are not limited so set to be same as io_maxreadcnt/io_maxwritecnt. 1003 * 1004 * io_segreadcnt/io_segwritecnt is just the segment size / page size. Again, 1005 * no real meaning to us. VM requires they must be evenly divisible by 4. 1006 * See <rdar://problem/14266574>. 1007 * 1008 */ 1009 1010 if (SSTOVC(share)->vc_flags & SMBV_SMB2) { 1011 /* Never allow more than 4 MB */ 1012 if (smb_maxsegreadsize > SMB_IOMAXCACHE) { 1013 smb_maxsegreadsize = SMB_IOMAXCACHE; 1014 } 1015 smbIOAttr.io_segwritecnt = smb_maxsegreadsize / PAGE_SIZE; 1016 /* Never allow more than 4 MB */ 1017 if (smb_maxsegwritesize > SMB_IOMAXCACHE) { 1018 smb_maxsegwritesize = SMB_IOMAXCACHE; 1019 } 1020 smbIOAttr.io_segreadcnt = smb_maxsegwritesize / PAGE_SIZE; 1021 1022 } else { 1023 size_t f_iosize = vfs_statfs(mp)->f_iosize; 1024 if (f_iosize < (PAGE_SIZE * 4)) { 1025 f_iosize = PAGE_SIZE * 4; /* Bad Server */ 1026 } 1027 smbIOAttr.io_segreadcnt = (uint32_t)(f_iosize / (PAGE_SIZE * 4)) * 4; 1028 smbIOAttr.io_segwritecnt = smbIOAttr.io_segreadcnt; 1029 } 1030 1031 smbIOAttr.io_maxsegreadsize = smbIOAttr.io_segreadcnt * PAGE_SIZE; 1032 smbIOAttr.io_maxsegwritesize = smbIOAttr.io_segwritecnt * PAGE_SIZE; 1033 1034 smbIOAttr.io_maxreadcnt = smbIOAttr.io_maxsegreadsize; 1035 smbIOAttr.io_maxwritecnt = smbIOAttr.io_maxsegwritesize; 1036 1037 SMBWARNING("io_maxsegreadsize = %d io_maxsegwritesize = %d f_iosize = %ld vc_rxmax = %d vc_wxmax = %d\n", 1038 smbIOAttr.io_maxsegreadsize, smbIOAttr.io_maxsegwritesize, 1039 vfs_statfs(mp)->f_iosize, 1040 SSTOVC(share)->vc_rxmax, SSTOVC(share)->vc_wxmax); 1041 1042 vfs_setioattr(mp, &smbIOAttr); 1043 1044 1045 /* smbfs_root did a vnode_get and a vnode_ref, so keep the ref but release the get */ 1046 vnode_put(vp); 1047 /* We now have everyting we need to setup the dead/up/down routines */ 1048 lck_mtx_lock(&share->ss_shlock); 1049 /* Use to tell the VC that the share is going away, so just timeout messages */ 1050 share->ss_going_away = smbfs_is_going_away; 1051 /* Routines to call when the mount is having problems */ 1052 share->ss_down = smbfs_down; 1053 share->ss_up = smbfs_up; 1054 share->ss_dead = smbfs_dead; 1055 if (smp->sm_args.altflags & SMBFS_MNT_SOFT) { 1056 if (smp->sm_args.altflags & SMBFS_MNT_DFS_SHARE) { 1057 /* 1058 * Dfs Trigger node, set the dead timer to something smaller and 1059 * never soft mount time out the operations 1060 */ 1061 share->ss_dead_timer = smbfs_trigger_deadtimer; 1062 } else { 1063 /* Timeout the operations */ 1064 share->ss_soft_timer = SOFTMOUNT_TIMEOUT; 1065 /* Soft mounts use the default timer value */ 1066 share->ss_dead_timer = smbfs_deadtimer; 1067 } 1068 } else { 1069 share->ss_dead_timer = smbfs_hard_deadtimer; 1070 } 1071 /* All done add the mount point to the share so we can access these routines */ 1072 share->ss_mount = smp; 1073 lck_mtx_unlock(&share->ss_shlock); 1074 SMBDEBUG("%s dead timer = %d\n", share->ss_name, share->ss_dead_timer); 1075 1076 OSAddAtomic(1, &SSTOVC(share)->vc_volume_cnt); 1077 if (SSTOVC(share)->throttle_info) { 1078 throttle_info_mount_ref(mp, SSTOVC(share)->throttle_info); 1079 } 1080 1081 smbfs_notify_change_create_thread(smp); 1082 if (smp->sm_args.altflags & SMBFS_MNT_COMPOUND_ON) { 1083 vfs_setcompoundopen(mp); 1084 } 1085 else { 1086 SMBWARNING("compound off in preferences\n"); 1087 } 1088 1089 if ((SSTOVC(share)->vc_flags & SMBV_SMB2) && 1090 (SSTOVC(share)->vc_misc_flags & SMBV_OSX_SERVER)) { 1091 1092 /* Mac OS X SMB 2/3 server */ 1093 share->ss_fstype = SMB_FS_MAC_OS_X; 1094 1095 /* Enable server message notification */ 1096 smbfs_start_svrmsg_notify(smp); 1097 } 1098 1099 mount_cnt++; 1100 1101 SMB_LOG_KTRACE(SMB_DBG_MOUNT | DBG_FUNC_END, 0, 0, 0, 0, 0); 1102 return (0); 1103bad: 1104 if (share) { 1105 lck_mtx_lock(&share->ss_shlock); 1106 share->ss_mount = NULL; /* share->ss_mount is smp which we free below */ 1107 lck_mtx_unlock(&share->ss_shlock); 1108 smb_share_rele(share, context); 1109 } 1110 if (smp) { 1111 vfs_setfsprivate(mp, (void *)0); 1112 1113 /* Was malloced by hashinit */ 1114 if (smp->sm_hash) 1115 SMB_FREE(smp->sm_hash, M_SMBFSHASH); 1116 lck_mtx_free(smp->sm_hashlock, hash_lck_grp); 1117 1118 lck_mtx_destroy(&smp->sm_statfslock, smbfs_mutex_group); 1119 lck_mtx_destroy(&smp->sm_reclaim_lock, smbfs_mutex_group); 1120 lck_rw_destroy(&smp->sm_rw_sharelock, smbfs_rwlock_group); 1121 lck_mtx_destroy(&smp->sm_svrmsg_lock, smbfs_mutex_group); 1122 SMB_FREE(smp->sm_args.volume_name, M_SMBSTR); 1123 SMB_FREE(smp->sm_args.path, M_SMBFSDATA); 1124 SMB_FREE(smp->sm_args.unique_id, M_SMBFSDATA); 1125 SMB_FREE(smp->ntwrk_gids, M_TEMP); 1126 SMB_FREE(smp->ntwrk_sids, M_TEMP); 1127 SMB_FREE(smp, M_SMBFSDATA); 1128 } 1129 SMB_FREE(args, M_SMBFSDATA); /* Done with the args free them */ 1130 1131 SMB_LOG_KTRACE(SMB_DBG_MOUNT | DBG_FUNC_END, error, 0, 0, 0, 0); 1132 return (error); 1133} 1134 1135/* Unmount the filesystem described by mp. */ 1136static int 1137smbfs_unmount(struct mount *mp, int mntflags, vfs_context_t context) 1138{ 1139 struct smbmount *smp = VFSTOSMBFS(mp); 1140 struct smb_share *share = smp->sm_share; 1141 vnode_t vp; 1142 int error = 0; 1143 1144 SMB_LOG_KTRACE(SMB_DBG_UNMOUNT | DBG_FUNC_START, mntflags, 0, 0, 0, 0); 1145 1146 SMBVDEBUG("smbfs_unmount: flags=%04x\n", mntflags); 1147 1148 /* Force unmount shutdown all outstanding I/O requests on this share. */ 1149 if (mntflags & MNT_FORCE) { 1150 smb_iod_errorout_share_request(share, ENXIO); 1151 } 1152 1153 error = smbfs_root(mp, &vp, context); 1154 if (error) { 1155 goto done; 1156 } 1157 1158 error = vflush(mp, vp, (mntflags & MNT_FORCE) ? FORCECLOSE : 0); 1159 if (error) { 1160 vnode_put(vp); 1161 goto done; 1162 } 1163 1164 if (vnode_isinuse(vp, 1) && !(mntflags & MNT_FORCE)) { 1165 SMBDEBUG("smbfs_unmount: usecnt\n"); 1166 vnode_put(vp); 1167 error = EBUSY; 1168 goto done; 1169 } 1170 1171 smp->sm_rvp = NULL; /* We no longer have a reference so clear it out */ 1172 vnode_rele(vp); /* to drop ref taken by smbfs_mount */ 1173 vnode_put(vp); /* to drop ref taken by VFS_ROOT above */ 1174 1175 (void)vflush(mp, NULLVP, FORCECLOSE); 1176 1177 /* Cancel outstanding svrmsg notify request */ 1178 if ((SSTOVC(share)->vc_flags & SMBV_SMB2) && 1179 (SSTOVC(share)->vc_misc_flags & SMBV_OSX_SERVER)) { 1180 smbfs_stop_svrmsg_notify(smp); 1181 } 1182 1183 /* We are done with this share shutdown all outstanding I/O requests. */ 1184 smb_iod_errorout_share_request(share, ENXIO); 1185 1186 OSAddAtomic(-1, &SSTOVC(share)->vc_volume_cnt); 1187 smbfs_notify_change_destroy_thread(smp); 1188 1189 if (SSTOVC(share)->throttle_info) 1190 throttle_info_mount_rel(mp); 1191 1192 /* Make sure SMB 2/3 fid table is empty */ 1193 if (SSTOVC(share)->vc_flags & SMBV_SMB2) { 1194 smb_fid_delete_all(share); 1195 } 1196 1197 /* Remove the smb mount pointer from the share before freeing it */ 1198 lck_mtx_lock(&share->ss_shlock); 1199 share->ss_mount = NULL; 1200 share->ss_dead = NULL; 1201 share->ss_up = NULL; 1202 share->ss_down = NULL; 1203 lck_mtx_unlock(&share->ss_shlock); 1204 1205 smb_share_rele(share, context); 1206 vfs_setfsprivate(mp, (void *)0); 1207 1208 if (smp->sm_hash) { 1209 SMB_FREE(smp->sm_hash, M_SMBFSHASH); 1210 smp->sm_hash = (void *)0xDEAD5AB0; 1211 } 1212 lck_mtx_free(smp->sm_hashlock, hash_lck_grp); 1213 1214 lck_mtx_destroy(&smp->sm_statfslock, smbfs_mutex_group); 1215 lck_mtx_destroy(&smp->sm_reclaim_lock, smbfs_mutex_group); 1216 lck_mtx_destroy(&smp->sm_svrmsg_lock, smbfs_mutex_group); 1217 lck_rw_destroy(&smp->sm_rw_sharelock, smbfs_rwlock_group); 1218 1219 if (smp->sm_args.volume_name) { 1220 SMB_FREE(smp->sm_args.volume_name, M_SMBSTR); 1221 } 1222 if (smp->sm_args.path) { 1223 SMB_FREE(smp->sm_args.path, M_SMBSTR); 1224 } 1225 if (smp->sm_args.unique_id) { 1226 SMB_FREE(smp->sm_args.unique_id, M_SMBSTR); 1227 } 1228 if (smp->ntwrk_gids) { 1229 SMB_FREE(smp->ntwrk_gids, M_SMBSTR); 1230 } 1231 if (smp->ntwrk_sids) { 1232 SMB_FREE(smp->ntwrk_sids, M_SMBSTR); 1233 } 1234 if (smp) { 1235 SMB_FREE(smp, M_SMBSTR); 1236 } 1237 1238 vfs_clearflags(mp, MNT_LOCAL); 1239 mount_cnt--; 1240 1241 error = 0; 1242 1243done: 1244 SMB_LOG_KTRACE(SMB_DBG_UNMOUNT | DBG_FUNC_END, error, 0, 0, 0, 0); 1245 return (error); 1246} 1247 1248/* 1249 * Return locked root vnode of a filesystem 1250 */ 1251static int 1252smbfs_root(struct mount *mp, vnode_t *vpp, vfs_context_t context) 1253{ 1254 struct smbmount *smp = VFSTOSMBFS(mp); 1255 struct smb_share *share = NULL; 1256 vnode_t vp; 1257 struct smbfattr fattr; 1258 int error = 0; 1259 1260 SMB_LOG_KTRACE(SMB_DBG_ROOT | DBG_FUNC_START, 0, 0, 0, 0, 0); 1261 1262 if (smp == NULL) { 1263 SMBERROR("smp == NULL (bug in umount)\n"); 1264 error = EINVAL; 1265 goto done; 1266 } 1267 1268 if (smp->sm_rvp) { 1269 /* just get the saved root vnode as its much faster */ 1270 *vpp = smp->sm_rvp; 1271 error = vnode_get(*vpp); 1272 goto done; 1273 } 1274 1275 /* Fill in the default values that we already know about the root vnode */ 1276 bzero(&fattr, sizeof(fattr)); 1277 nanouptime(&fattr.fa_reqtime); 1278 fattr.fa_valid_mask |= FA_VTYPE_VALID; 1279 fattr.fa_attr = SMB_EFA_DIRECTORY; 1280 fattr.fa_vtype = VDIR; 1281 1282 if (smp->sm_root_ino == 0) { 1283 /* 1284 * Must be at mount time and we dont know what the root File ID is. 1285 * Assume its 2 to start with 1286 */ 1287 smp->sm_root_ino = SMBFS_ROOT_INO; 1288 fattr.fa_ino = SMBFS_ROOT_INO; 1289 } 1290 else { 1291 /* Recreating root vnode and we know what its ID was */ 1292 fattr.fa_ino = smp->sm_root_ino; 1293 } 1294 1295 /* 1296 * First time to get the root vnode, smbfs_nget will create it and check 1297 * with the network to make sure all is well with the root node. Could get 1298 * an error if the device is not ready are we have no access. 1299 */ 1300 share = smb_get_share_with_reference(smp); 1301 error = smbfs_nget(share, mp, 1302 NULL, "TheRooT", 7, 1303 &fattr, &vp, 1304 0, SMBFS_NGET_CREATE_VNODE, 1305 context); 1306 smb_share_rele(share, context); 1307 if (error) { 1308 goto done; 1309 } 1310 1311 /* 1312 * Since root vnode has an exclusive lock, I know only one process can be 1313 * here at this time. Check once more while I still have the lock that 1314 * sm_rvp is still NULL before taking a ref and saving it. 1315 */ 1316 if (smp->sm_rvp == NULL) { 1317 smp->sm_rvp = vp; /* this will be released in the unmount code */ 1318 smbnode_unlock(VTOSMB(vp)); /* Release the smbnode lock */ 1319 /* 1320 * Now save a ref to this vnode so that we can quickly retrieve in 1321 * subsequent calls and make sure it doesn't go away until we unmount. 1322 */ 1323 error = vnode_ref(vp); 1324 /* It would be very rare for vnode_ref to fail, but be paranoid anyways */ 1325 if (error) { 1326 SMBERROR("vnode_ref on rootvp failed error %d\n", error); 1327 smp->sm_rvp = NULL; 1328 vnode_put(vp); 1329 goto done; 1330 } 1331 } else { 1332 /* 1333 * Must have had two or more processes running at same time, other process 1334 * saved the root vnode, so just unlock this one and return 1335 */ 1336 smbnode_unlock(VTOSMB(vp)); /* Release the smbnode lock */ 1337 } 1338 1339 *vpp = vp; 1340 error = 0; 1341 1342done: 1343 SMB_LOG_KTRACE(SMB_DBG_ROOT | DBG_FUNC_END, error, 0, 0, 0, 0); 1344 return (error); 1345} 1346 1347/* 1348 * Vfs start routine, a no-op. 1349 */ 1350/* ARGSUSED */ 1351static int 1352smbfs_start(struct mount *mp, int flags, vfs_context_t context) 1353{ 1354#pragma unused(mp, flags, context) 1355 return 0; 1356} 1357 1358/*ARGSUSED*/ 1359static int 1360smbfs_init(struct vfsconf *vfsp) 1361{ 1362#pragma unused(vfsp) 1363 static int32_t done = 0; 1364 1365 if (done == 1) 1366 return (0); 1367 done = 1; 1368 smbfs_lock_init(); 1369 1370 return 0; 1371} 1372 1373/* 1374 * smbfs_vfs_getattr call 1375 */ 1376static int 1377smbfs_vfs_getattr(struct mount *mp, struct vfs_attr *fsap, vfs_context_t context) 1378{ 1379 struct smbmount *smp = VFSTOSMBFS(mp); 1380 struct smb_share *share = NULL; 1381 struct vfsstatfs cachedstatfs; 1382 struct timespec ts; 1383 int error = 0; 1384 struct smb_vc *vcp = NULL; 1385 1386 SMB_LOG_KTRACE(SMB_DBG_VFS_GETATTR | DBG_FUNC_START, 0, 0, 0, 0, 0); 1387 1388 if ((smp->sm_rvp == NULL) || (VTOSMB(smp->sm_rvp) == NULL)) { 1389 error = EINVAL; 1390 goto done; 1391 } 1392 1393 share = smb_get_share_with_reference(smp); 1394 vcp = SSTOVC(share); 1395 1396 lck_mtx_lock(&smp->sm_statfslock); 1397 cachedstatfs = smp->sm_statfsbuf; 1398 if (smp->sm_status & SM_STATUS_STATFS) 1399 lck_mtx_unlock(&smp->sm_statfslock); 1400 else { 1401 smp->sm_status |= SM_STATUS_STATFS; 1402 lck_mtx_unlock(&smp->sm_statfslock); 1403 nanouptime(&ts); 1404 /* We always check the first time otherwise only if the cache is stale. */ 1405 if ((smp->sm_statfstime == 0) || 1406 (((ts.tv_sec - smp->sm_statfstime) > SM_MAX_STATFSTIME) && 1407 (VFSATTR_IS_ACTIVE(fsap, f_bsize) || VFSATTR_IS_ACTIVE(fsap, f_blocks) || 1408 VFSATTR_IS_ACTIVE(fsap, f_bfree) || VFSATTR_IS_ACTIVE(fsap, f_bavail) || 1409 VFSATTR_IS_ACTIVE(fsap, f_files) || VFSATTR_IS_ACTIVE(fsap, f_ffree)))) { 1410 /* update cached from-the-server data */ 1411 error = smbfs_smb_statfs(smp, &cachedstatfs, context); 1412 if (error == 0) { 1413 nanouptime(&ts); 1414 smp->sm_statfstime = ts.tv_sec; 1415 lck_mtx_lock(&smp->sm_statfslock); 1416 smp->sm_statfsbuf = cachedstatfs; 1417 lck_mtx_unlock(&smp->sm_statfslock); 1418 } 1419 else { 1420 error = 0; 1421 } 1422 } 1423 lck_mtx_lock(&smp->sm_statfslock); 1424 smp->sm_status &= ~SM_STATUS_STATFS; 1425 lck_mtx_unlock(&smp->sm_statfslock); 1426 } 1427 1428 /* 1429 * Not sure what to do about these items, seems we get call for them and 1430 * if they are not filled in an error gets return. We tell them in the 1431 * capibilities that we do not support these items. Notice AFP fills them 1432 * in and the values they using are the same as below. The AFP code does have 1433 * these items but they never get updated and always end with these same 1434 * values. 1435 */ 1436 VFSATTR_RETURN (fsap, f_objcount, (uint64_t) 0 + (uint64_t)0); 1437 /* We do not support setting filecount. */ 1438 VFSATTR_RETURN (fsap, f_filecount, (uint64_t) 0); 1439 /* We do not support setting dircount. */ 1440 VFSATTR_RETURN (fsap, f_dircount, (uint64_t) 0); 1441 /* We do not support setting maxobjcount. */ 1442 VFSATTR_RETURN (fsap, f_maxobjcount, (uint64_t) 0xFFFFFFFF); 1443 1444 /* copy results from cached statfs */ 1445 VFSATTR_RETURN(fsap, f_bsize, cachedstatfs.f_bsize); 1446 VFSATTR_RETURN(fsap, f_iosize, cachedstatfs.f_iosize); 1447 VFSATTR_RETURN(fsap, f_blocks, cachedstatfs.f_blocks); 1448 VFSATTR_RETURN(fsap, f_bfree, cachedstatfs.f_bfree); 1449 VFSATTR_RETURN(fsap, f_bavail, cachedstatfs.f_bavail); 1450 VFSATTR_RETURN (fsap, f_bused, cachedstatfs.f_blocks - cachedstatfs.f_bavail); 1451 VFSATTR_RETURN(fsap, f_files, cachedstatfs.f_files); 1452 VFSATTR_RETURN(fsap, f_ffree, cachedstatfs.f_ffree); 1453 1454 fsap->f_fsid.val[0] = vfs_statfs(mp)->f_fsid.val[0]; 1455 fsap->f_fsid.val[1] = vfs_typenum(mp); 1456 VFSATTR_SET_SUPPORTED(fsap, f_fsid); 1457 1458 /* The VFS layer handles f_owner. */ 1459 1460 /* 1461 * NOTE: the valid field indicates whether your VFS knows whether a 1462 * capability is supported or not. So, if you know FOR SURE that a capability 1463 * is support or not, then set that bit in the valid part. Then, in the 1464 * capabilities field, you either set it if supported or leave it clear if 1465 * not supported 1466 */ 1467 if (VFSATTR_IS_ACTIVE(fsap, f_capabilities)) { 1468 vol_capabilities_attr_t *cap = &fsap->f_capabilities; 1469 1470 cap->capabilities[VOL_CAPABILITIES_FORMAT] = 1471 VOL_CAP_FMT_SYMBOLICLINKS | 1472 VOL_CAP_FMT_FAST_STATFS | 1473 VOL_CAP_FMT_OPENDENYMODES | 1474 VOL_CAP_FMT_HIDDEN_FILES | 1475 VOL_CAP_FMT_64BIT_OBJECT_IDS | 1476 0; 1477 1478 /* 1479 * Only say we support large files if the server supports it. 1480 * FAT shares can not handle large files either. 1481 */ 1482 if ((VC_CAPS(vcp) & SMB_CAP_LARGE_FILES) && 1483 (share->ss_fstype != SMB_FS_FAT)) { 1484 cap->capabilities[VOL_CAPABILITIES_FORMAT] |= VOL_CAP_FMT_2TB_FILESIZE; 1485 } 1486 1487 /* Must be FAT so don't trust the modify times */ 1488 if (share->ss_fstype == SMB_FS_FAT) 1489 cap->capabilities[VOL_CAPABILITIES_FORMAT] |= VOL_CAP_FMT_NO_ROOT_TIMES; 1490 1491 if (share->ss_attributes & FILE_CASE_PRESERVED_NAMES) 1492 cap->capabilities[VOL_CAPABILITIES_FORMAT] |= VOL_CAP_FMT_CASE_PRESERVING; 1493 1494 if (vcp->vc_misc_flags & SMBV_OSX_SERVER) { 1495 /* Its OS X Server so we know for sure */ 1496 if (vcp->vc_volume_caps & kAAPL_CASE_SENSITIVE) { 1497 cap->capabilities[VOL_CAPABILITIES_FORMAT] |= VOL_CAP_FMT_CASE_SENSITIVE; 1498 } 1499 1500 if ((vcp->vc_volume_caps & kAAPL_SUPPORT_RESOLVE_ID) && 1501 (vcp->vc_misc_flags & SMBV_HAS_FILEIDS)) { 1502 /* Supports Resolve ID */ 1503 cap->capabilities[VOL_CAPABILITIES_FORMAT] |= VOL_CAP_FMT_PATH_FROM_ID | 1504 VOL_CAP_FMT_PERSISTENTOBJECTIDS; 1505 } 1506 } 1507 else { 1508 /* 1509 * Not a OS X Server, so we have to guess. 1510 * 1511 * This SMB file system is case INSENSITIVE and case preserving, 1512 * but servers vary, depending on the underlying volume. In 1513 * pathconf we have to give a yes or no answer. We need to return a 1514 * consistent answer in both cases. We do not know the real answer 1515 * for case sensitive, but lets default to what 90% of the servers 1516 * have set. Also remember this fixes Radar 4057391 and 3530751. 1517 */ 1518 } 1519 1520 if (share->ss_attributes & FILE_SUPPORTS_SPARSE_FILES) 1521 cap->capabilities[VOL_CAPABILITIES_FORMAT] |= VOL_CAP_FMT_SPARSE_FILES; 1522 1523 cap->capabilities[VOL_CAPABILITIES_INTERFACES] = 1524 VOL_CAP_INT_ATTRLIST | 1525 VOL_CAP_INT_FLOCK | 1526 VOL_CAP_INT_MANLOCK | 1527 0; 1528 1529 /* 1530 * If its a FAT filesystem, then named streams are not supported. 1531 * If named streams are not supported, then the attribute enumeration 1532 * calls wont work as we can not Max Access or Resource Fork info. 1533 * Thus named streams and non FAT is required for the attribute 1534 * enumeration calls. 1535 */ 1536 if ((share->ss_fstype != SMB_FS_FAT) && 1537 (share->ss_attributes & FILE_NAMED_STREAMS) && 1538 !(smp->sm_args.altflags & SMBFS_MNT_READDIRATTR_OFF)) { 1539 /* vnop_readdirattr allowed */ 1540 cap->capabilities[VOL_CAPABILITIES_INTERFACES] |= VOL_CAP_INT_READDIRATTR; 1541 } 1542 else { 1543 if (share->ss_fstype == SMB_FS_FAT) { 1544 SMBWARNING("FAT filesystem so smbfs_vnop_readdirattr is disabled for %s volume\n", 1545 (smp->sm_args.volume_name) ? smp->sm_args.volume_name : ""); 1546 } 1547 1548 if (!(share->ss_attributes & FILE_NAMED_STREAMS)) { 1549 SMBWARNING("No named streams so smbfs_vnop_readdirattr is disabled for %s volume\n", 1550 (smp->sm_args.volume_name) ? smp->sm_args.volume_name : ""); 1551 } 1552 1553 if (smp->sm_args.altflags & SMBFS_MNT_READDIRATTR_OFF) { 1554 SMBWARNING("smbfs_vnop_readdirattr has been turned off for %s volume\n", 1555 (smp->sm_args.volume_name) ? smp->sm_args.volume_name : ""); 1556 } 1557 } 1558 1559 if (UNIX_CAPS(share) & CIFS_UNIX_FCNTL_LOCKS_CAP) 1560 cap->capabilities[VOL_CAPABILITIES_INTERFACES] |= VOL_CAP_INT_ADVLOCK; 1561 1562 if (share->ss_attributes & FILE_NAMED_STREAMS) 1563 cap->capabilities[VOL_CAPABILITIES_INTERFACES] |= VOL_CAP_INT_NAMEDSTREAMS | VOL_CAP_INT_EXTENDED_ATTR; 1564 1565 if ((smp->sm_args.altflags & SMBFS_MNT_NOTIFY_OFF) == SMBFS_MNT_NOTIFY_OFF) { 1566 SMBWARNING("Notifications have been turned off for %s volume\n", 1567 (smp->sm_args.volume_name) ? smp->sm_args.volume_name : ""); 1568 } 1569 else { 1570 if (!(vcp->vc_flags & SMBV_SMB2) && 1571 (vcp->vc_maxmux < SMB_NOTIFY_MIN_MUX)) { 1572 /* SMB 1 */ 1573 SMBWARNING("Notifications are not support on %s volume\n", 1574 (smp->sm_args.volume_name) ? smp->sm_args.volume_name : ""); 1575 } 1576 else { 1577 cap->capabilities[VOL_CAPABILITIES_INTERFACES] |= VOL_CAP_INT_REMOTE_EVENT; 1578 } 1579 } 1580 1581 /* 1582 * We only turn on VOL_CAP_INT_COPYFILE if it's an SMB 2/3 connection 1583 * AND we know it supports FSCTL_SRV_COPY_CHUNK IOCTL. 1584 */ 1585 if ((SSTOVC(share)->vc_flags & SMBV_SMB2) && 1586 (SSTOVC(share)->vc_misc_flags & SMBV_HAS_COPYCHUNK)) { 1587 cap->capabilities[VOL_CAPABILITIES_INTERFACES] |= VOL_CAP_INT_COPYFILE; 1588 } 1589 1590 cap->capabilities[VOL_CAPABILITIES_RESERVED1] = 0; 1591 cap->capabilities[VOL_CAPABILITIES_RESERVED2] = 0; 1592 1593 cap->valid[VOL_CAPABILITIES_FORMAT] = 1594 VOL_CAP_FMT_PERSISTENTOBJECTIDS | 1595 VOL_CAP_FMT_NO_ROOT_TIMES | 1596 VOL_CAP_FMT_SYMBOLICLINKS | 1597 VOL_CAP_FMT_HARDLINKS | 1598 VOL_CAP_FMT_JOURNAL | 1599 VOL_CAP_FMT_JOURNAL_ACTIVE | 1600 VOL_CAP_FMT_SPARSE_FILES | 1601 VOL_CAP_FMT_ZERO_RUNS | 1602 VOL_CAP_FMT_2TB_FILESIZE | 1603 VOL_CAP_FMT_CASE_PRESERVING | 1604 VOL_CAP_FMT_CASE_SENSITIVE | 1605 VOL_CAP_FMT_FAST_STATFS | 1606 VOL_CAP_FMT_OPENDENYMODES | 1607 VOL_CAP_FMT_HIDDEN_FILES | 1608 VOL_CAP_FMT_64BIT_OBJECT_IDS | 1609 0; 1610 1611 if (vcp->vc_misc_flags & SMBV_OSX_SERVER) { 1612 /* Its OS X Server so we know for sure */ 1613 if ((vcp->vc_volume_caps & kAAPL_SUPPORT_RESOLVE_ID) && 1614 (vcp->vc_misc_flags & SMBV_HAS_FILEIDS)) { 1615 /* Supports Resolve ID */ 1616 cap->valid[VOL_CAPABILITIES_FORMAT] |= VOL_CAP_FMT_PATH_FROM_ID; 1617 } 1618 } 1619 1620 cap->valid[VOL_CAPABILITIES_INTERFACES] = 1621 VOL_CAP_INT_SEARCHFS | 1622 VOL_CAP_INT_ATTRLIST | 1623 VOL_CAP_INT_NFSEXPORT | 1624 VOL_CAP_INT_READDIRATTR | 1625 VOL_CAP_INT_EXCHANGEDATA | 1626 VOL_CAP_INT_COPYFILE | 1627 VOL_CAP_INT_ALLOCATE | 1628 VOL_CAP_INT_VOL_RENAME | 1629 VOL_CAP_INT_ADVLOCK | 1630 VOL_CAP_INT_FLOCK | 1631 VOL_CAP_INT_MANLOCK | 1632 VOL_CAP_INT_NAMEDSTREAMS | 1633 VOL_CAP_INT_EXTENDED_ATTR | 1634 VOL_CAP_INT_REMOTE_EVENT | 1635 0; 1636 1637 cap->valid[VOL_CAPABILITIES_RESERVED1] = 0; 1638 cap->valid[VOL_CAPABILITIES_RESERVED2] = 0; 1639 VFSATTR_SET_SUPPORTED(fsap, f_capabilities); 1640 } 1641 1642 /* 1643 * NOTE: the valid field indicates whether your VFS knows whether a 1644 * attribute is supported or not. So, if you know FOR SURE that a capability 1645 * is support or not, then set that bit in the valid part. 1646 */ 1647 if (VFSATTR_IS_ACTIVE(fsap, f_attributes)) { 1648 fsap->f_attributes.validattr.commonattr = 1649 ATTR_CMN_NAME | 1650 ATTR_CMN_DEVID | 1651 ATTR_CMN_FSID | 1652 ATTR_CMN_OBJTYPE | 1653 ATTR_CMN_OBJTAG | 1654 ATTR_CMN_OBJID | 1655 /* ATTR_CMN_OBJPERMANENTID | */ 1656 ATTR_CMN_PAROBJID | 1657 /* ATTR_CMN_SCRIPT | */ 1658 ATTR_CMN_CRTIME | 1659 ATTR_CMN_MODTIME | 1660 ATTR_CMN_CHGTIME | 1661 ATTR_CMN_ACCTIME | 1662 /* ATTR_CMN_BKUPTIME | */ 1663 /* Just not sure about the following: */ 1664 ATTR_CMN_FNDRINFO | 1665 ATTR_CMN_OWNERID | 1666 ATTR_CMN_GRPID | 1667 ATTR_CMN_ACCESSMASK | 1668 ATTR_CMN_FLAGS | 1669 ATTR_CMN_USERACCESS | 1670 ATTR_CMN_EXTENDED_SECURITY | 1671 ATTR_CMN_UUID | 1672 ATTR_CMN_GRPUUID | 1673 0; 1674 fsap->f_attributes.validattr.volattr = 1675 ATTR_VOL_FSTYPE | 1676 /* ATTR_VOL_SIGNATURE */ 1677 ATTR_VOL_SIZE | 1678 ATTR_VOL_SPACEFREE | 1679 ATTR_VOL_SPACEAVAIL | 1680 ATTR_VOL_MINALLOCATION | 1681 ATTR_VOL_ALLOCATIONCLUMP | 1682 ATTR_VOL_IOBLOCKSIZE | 1683 /* ATTR_VOL_OBJCOUNT */ 1684 /* ATTR_VOL_FILECOUNT */ 1685 /* ATTR_VOL_DIRCOUNT */ 1686 /* ATTR_VOL_MAXOBJCOUNT */ 1687 ATTR_VOL_MOUNTPOINT | 1688 ATTR_VOL_NAME | 1689 ATTR_VOL_MOUNTFLAGS | 1690 ATTR_VOL_MOUNTEDDEVICE | 1691 /* ATTR_VOL_ENCODINGSUSED */ 1692 ATTR_VOL_CAPABILITIES | 1693 ATTR_VOL_ATTRIBUTES | 1694 0; 1695 fsap->f_attributes.validattr.dirattr = 1696 ATTR_DIR_LINKCOUNT | 1697 ATTR_DIR_MOUNTSTATUS | 1698 0; 1699 fsap->f_attributes.validattr.fileattr = 1700 ATTR_FILE_LINKCOUNT | 1701 ATTR_FILE_TOTALSIZE | 1702 ATTR_FILE_ALLOCSIZE | 1703 /* ATTR_FILE_IOBLOCKSIZE */ 1704 ATTR_FILE_DEVTYPE | 1705 /* ATTR_FILE_FORKCOUNT */ 1706 /* ATTR_FILE_FORKLIST */ 1707 ATTR_FILE_DATALENGTH | 1708 ATTR_FILE_DATAALLOCSIZE | 1709 ATTR_FILE_RSRCLENGTH | 1710 ATTR_FILE_RSRCALLOCSIZE | 1711 0; 1712 fsap->f_attributes.validattr.forkattr = 0; 1713 1714 fsap->f_attributes.nativeattr.commonattr = 1715 ATTR_CMN_NAME | 1716 ATTR_CMN_DEVID | 1717 ATTR_CMN_FSID | 1718 ATTR_CMN_OBJTYPE | 1719 ATTR_CMN_OBJTAG | 1720 ATTR_CMN_OBJID | 1721 /* ATTR_CMN_OBJPERMANENTID | */ 1722 ATTR_CMN_PAROBJID | 1723 /* ATTR_CMN_SCRIPT | */ 1724 ATTR_CMN_CRTIME | 1725 ATTR_CMN_MODTIME | 1726 ATTR_CMN_ACCTIME | 1727 /* ATTR_CMN_BKUPTIME | */ 1728 /* ATTR_CMN_OWNERID | */ /* Supported but not native */ 1729 /* ATTR_CMN_GRPID | */ /* Supported but not native */ 1730 /* ATTR_CMN_ACCESSMASK | */ /* Supported but not native */ 1731 ATTR_CMN_FLAGS | 1732 /* ATTR_CMN_USERACCESS | */ /* Supported but not native */ 1733 0; 1734 /* FAT does not support change time */ 1735 if (share->ss_fstype != SMB_FS_FAT) { 1736 fsap->f_attributes.nativeattr.commonattr |= ATTR_CMN_CHGTIME; 1737 } 1738 /* Named Streams knows about Finder Info */ 1739 if (share->ss_attributes & FILE_NAMED_STREAMS) { 1740 fsap->f_attributes.nativeattr.commonattr |= ATTR_CMN_FNDRINFO; 1741 } 1742 1743 if (share->ss_attributes & FILE_PERSISTENT_ACLS) { 1744 fsap->f_attributes.nativeattr.commonattr |= ATTR_CMN_EXTENDED_SECURITY | ATTR_CMN_UUID | ATTR_CMN_GRPUUID; 1745 } 1746 1747 fsap->f_attributes.nativeattr.volattr = 1748 ATTR_VOL_FSTYPE | 1749 /* ATTR_VOL_SIGNATURE */ 1750 ATTR_VOL_SIZE | 1751 ATTR_VOL_SPACEFREE | 1752 ATTR_VOL_SPACEAVAIL | 1753 ATTR_VOL_MINALLOCATION | 1754 ATTR_VOL_ALLOCATIONCLUMP | 1755 ATTR_VOL_IOBLOCKSIZE | 1756 /* ATTR_VOL_OBJCOUNT */ 1757 /* ATTR_VOL_FILECOUNT */ 1758 /* ATTR_VOL_DIRCOUNT */ 1759 /* ATTR_VOL_MAXOBJCOUNT */ 1760 ATTR_VOL_MOUNTPOINT | 1761 ATTR_VOL_NAME | 1762 ATTR_VOL_MOUNTFLAGS | 1763 ATTR_VOL_MOUNTEDDEVICE | 1764 /* ATTR_VOL_ENCODINGSUSED */ 1765 ATTR_VOL_CAPABILITIES | 1766 ATTR_VOL_ATTRIBUTES | 1767 0; 1768 fsap->f_attributes.nativeattr.dirattr = 0; 1769 fsap->f_attributes.nativeattr.fileattr = 1770 /* ATTR_FILE_LINKCOUNT | */ /* Supported but not native */ 1771 /* ATTR_FILE_IOBLOCKSIZE */ 1772 ATTR_FILE_DEVTYPE | 1773 /* ATTR_FILE_FORKCOUNT */ 1774 /* ATTR_FILE_FORKLIST */ 1775 ATTR_FILE_DATALENGTH | 1776 ATTR_FILE_DATAALLOCSIZE | 1777 0; 1778 /* 1779 * Once we added streams support we should add this code. Radar 2899967 1780 */ 1781 if (share->ss_attributes & FILE_NAMED_STREAMS) 1782 fsap->f_attributes.nativeattr.fileattr |= ATTR_FILE_TOTALSIZE | 1783 ATTR_FILE_ALLOCSIZE | 1784 ATTR_FILE_RSRCLENGTH | 1785 ATTR_FILE_RSRCALLOCSIZE; 1786 1787 fsap->f_attributes.nativeattr.forkattr = 0; 1788 VFSATTR_SET_SUPPORTED(fsap, f_attributes); 1789 } 1790 /* 1791 * Our filesystem doesn't support volume dates. Let the VFS layer handle 1792 * these if requested. 1793 */ 1794 1795 /* 1796 * Could be one of the following: 1797 * SMB_FS_FAT, SMB_FS_CDFS, SMB_FS_UDF, 1798 * SMB_FS_NTFS_UNKNOWN, SMB_FS_NTFS, SMB_FS_NTFS_UNIX, 1799 * SMB_FS_MAC_OS_X 1800 */ 1801 VFSATTR_RETURN(fsap, f_fssubtype, share->ss_fstype); 1802 1803 if (VFSATTR_IS_ACTIVE(fsap, f_vol_name) && fsap->f_vol_name) { 1804 if (smp->sm_args.volume_name) { 1805 strlcpy(fsap->f_vol_name, smp->sm_args.volume_name, MAXPATHLEN); 1806 } else { 1807 /* 1808 * ref 3984574. Returning null here keeps vfs from returning 1809 * f_mntonname, and causes CarbonCore (File Mgr) to use the 1810 * f_mntfromname, as it did (& still does) when an error is returned. 1811 */ 1812 *fsap->f_vol_name = '\0'; 1813 } 1814 VFSATTR_SET_SUPPORTED(fsap, f_vol_name); 1815 } 1816 1817 /* Let the vfs layer handle f_signature */ 1818 /* We never set f_carbon_fsid, see <rdar://problem/4470282> depricated */ 1819 1820 smb_share_rele(share, context); 1821 1822done: 1823 SMB_LOG_KTRACE(SMB_DBG_VFS_GETATTR | DBG_FUNC_END, error, 0, 0, 0, 0); 1824 return (error); 1825} 1826 1827struct smbfs_sync_cargs { 1828 vfs_context_t context; 1829 int waitfor; 1830 int error; 1831}; 1832 1833 1834static int 1835smbfs_sync_callback(vnode_t vp, void *args) 1836{ 1837 int error; 1838 struct smbfs_sync_cargs *cargs; 1839 struct smbnode *np = NULL; 1840 struct smb_share *share = NULL; 1841 struct timespec ts; 1842 struct timespec waittime; 1843 int dirty = 0; 1844 1845 cargs = (struct smbfs_sync_cargs *)args; 1846 1847 if (smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK) != 0) { 1848 return (VNODE_RETURNED); 1849 } 1850 1851 np = VTOSMB(vp); 1852 np->n_lastvop = smbfs_sync_callback; 1853 1854 share = smb_get_share_with_reference(VTOSMBFS(vp)); 1855 /* 1856 * Must have gone into reconnect mode while interating the vnodes. Nothing for 1857 * us to do until reconnect is done. Just get out and wait for the next time. 1858 */ 1859 if (share->ss_flags & SMBS_RECONNECTING) { 1860 goto done; 1861 } 1862 1863 if (vnode_isreg(vp)) { 1864 /* 1865 * See if the file needs to be reopened. Ignore the error if being 1866 * revoke it will get caught below 1867 */ 1868 (void)smbfs_smb_reopen_file(share, np, cargs->context); 1869 1870 lck_mtx_lock(&np->f_openStateLock); 1871 if (np->f_openState & kNeedRevoke) { 1872 lck_mtx_unlock(&np->f_openStateLock); 1873 1874 SMBWARNING_LOCK(np, "revoking %s\n", np->n_name); 1875 1876 smbnode_unlock(np); 1877 np = NULL; /* Already unlocked */ 1878 vn_revoke(vp, REVOKEALL, cargs->context); 1879 goto done; 1880 } 1881 lck_mtx_unlock(&np->f_openStateLock); 1882 } 1883 /* 1884 * We have dirty data or we have a set eof pending in either case 1885 * deal with it in smbfs_fsync. 1886 */ 1887 dirty = vnode_hasdirtyblks(vp); 1888 if (dirty || 1889 (vnode_isreg(vp) && (np->n_flag & (NNEEDS_EOF_SET | NNEEDS_FLUSH)))) { 1890 1891 if (!(dirty) && 1892 !(np->n_flag & NNEEDS_EOF_SET) && 1893 (SSTOVC(share)->vc_server_caps & kAAPL_UNIX_BASED)) { 1894 /* 1895 * If its only needs a flush and the server is unix based, skip 1896 * doing this flush because the server OS is already doing a sync 1897 * with flush every 30 seconds or so. 1898 */ 1899 np->n_flag &= ~NNEEDS_FLUSH; 1900 } 1901 else { 1902 /* 1903 * Only send flush to server if its been longer than 30 secs since when 1904 * the last write was done. A flush can take a while and thus it can 1905 * hammer performance if you are doing a flush in the middle of a long 1906 * set of writes. 1907 */ 1908 nanouptime(&ts); 1909 waittime.tv_sec = SMB_FSYNC_TIMO; 1910 waittime.tv_nsec = 0; 1911 timespecsub(&ts, &waittime); 1912 1913 if (timespeccmp(&ts, &np->n_last_write_time, >)) { 1914 error = smbfs_fsync(share, vp, cargs->waitfor, 0, cargs->context); 1915 if (error) 1916 cargs->error = error; 1917 } 1918 } 1919 } 1920 1921 /* Someone is monitoring this node see if we have any work */ 1922 if (vnode_ismonitored(vp)) { 1923 int updateNotifyNode = FALSE; 1924 1925 if (vnode_isdir(vp) && !(np->n_flag & N_POLLNOTIFY)) { 1926 /* 1927 * The smbfs_restart_change_notify will now handle not only reopening 1928 * of notifcation, but also the closing of notifications. This is 1929 * done to force items into polling when we have too many items. 1930 */ 1931 smbfs_restart_change_notify(share, np, cargs->context); 1932 updateNotifyNode = np->d_needsUpdate; 1933 } else 1934 updateNotifyNode = TRUE; 1935 /* Looks like something change udate the notify routines and our cache */ 1936 if (updateNotifyNode) 1937 (void)smbfs_update_cache(share, vp, NULL, cargs->context); 1938 } 1939done: 1940 if (np) { 1941 smbnode_unlock(np); 1942 } 1943 /* We only have a share if we took a reference, release it */ 1944 if (share) { 1945 smb_share_rele(share, cargs->context); 1946 } 1947 1948 return (VNODE_RETURNED); 1949} 1950 1951/* 1952 * Flush out the buffer cache 1953 */ 1954static int 1955smbfs_sync(struct mount *mp, int waitfor, vfs_context_t context) 1956{ 1957 struct smbfs_sync_cargs args; 1958 1959 SMB_LOG_KTRACE(SMB_DBG_SYNC | DBG_FUNC_START, 0, 0, 0, 0, 0); 1960 1961 args.context = context; 1962 args.waitfor = waitfor; 1963 args.error = 0; 1964 /* 1965 * Force stale buffer cache information to be flushed. 1966 * 1967 * sbmfs_sync_callback will be called for each vnode 1968 * hung off of this mount point... the vnode will be 1969 * properly referenced and unreferenced around the callback 1970 */ 1971 vnode_iterate(mp, VNODE_ITERATE_ACTIVE, smbfs_sync_callback, (void *)&args); 1972 1973 SMB_LOG_KTRACE(SMB_DBG_SYNC | DBG_FUNC_END, args.error, 0, 0, 0, 0); 1974 return (args.error); 1975} 1976 1977/* 1978 * smbfs_vget - Equivalent of AFP Resolve ID 1979 * Returns an unlocked vnode 1980 */ 1981static int 1982smbfs_vget(struct mount *mp, ino64_t ino, vnode_t *vpp, vfs_context_t context) 1983{ 1984 int error; 1985 struct smbmount *smp = VFSTOSMBFS(mp); 1986 struct smb_share *share = NULL; 1987 struct smb_vc *vcp = NULL; 1988 char *path = NULL; 1989 size_t path_max = MAXPATHLEN; 1990 struct smbfattr *fap = NULL; 1991 uint32_t resolve_error = 0; 1992 char *server_path = NULL; 1993 vnode_t root_vp = NULL; 1994 struct smbnode *root_np = NULL; 1995 1996 SMB_LOG_KTRACE(SMB_DBG_VGET | DBG_FUNC_START, ino, 0, 0, 0, 0); 1997 1998 if (smp == NULL) { 1999 SMBERROR("smp == NULL\n"); 2000 error = EINVAL; 2001 goto done; 2002 } 2003 2004 SMB_MALLOC(path, 2005 char *, 2006 MAXPATHLEN, 2007 M_SMBTEMP, 2008 M_WAITOK | M_ZERO); 2009 if (path == NULL) { 2010 SMBERROR("SMB_MALLOC failed\n"); 2011 error = ENOMEM; 2012 goto done; 2013 } 2014 2015 SMB_MALLOC(fap, 2016 struct smbfattr *, 2017 sizeof(struct smbfattr), 2018 M_SMBTEMP, 2019 M_WAITOK | M_ZERO); 2020 if (fap == NULL) { 2021 SMBERROR("SMB_MALLOC failed\n"); 2022 error = ENOMEM; 2023 goto done; 2024 } 2025 2026 share = smb_get_share_with_reference(smp); 2027 vcp = SSTOVC(share); 2028 2029 if ((vcp->vc_misc_flags & SMBV_OSX_SERVER) && 2030 (vcp->vc_volume_caps & kAAPL_SUPPORT_RESOLVE_ID) && 2031 (vcp->vc_misc_flags & SMBV_HAS_FILEIDS)) { 2032 /* 2033 * Supports Resolve ID. 2034 * First check to see if we already have the vnode 2035 */ 2036 if ((ino == SMBFS_ROOT_INO) || (ino == SMBFS_ROOT_PAR_INO)) { 2037 /* Get the root vnode */ 2038 error = smbfs_root(mp, vpp, context); 2039 goto done; 2040 } 2041 else { 2042 /* 2043 * Some other vnode 2044 */ 2045 fap->fa_ino = ino; 2046 2047 /* 2048 * Since we only have the ino in the fap, if we do find an existing 2049 * vnode, dont update its meta data 2050 */ 2051 if (smbfs_nget(share, mp, 2052 NULL, NULL, 0, 2053 fap, vpp, 2054 0, (SMBFS_NGET_LOOKUP_ONLY | SMBFS_NGET_NO_CACHE_UPDATE), 2055 context) == 0) { 2056 /* 2057 * Found one in our hash table. Unlock it and return it 2058 */ 2059 error = 0; 2060 smbnode_unlock(VTOSMB(*vpp)); 2061 goto done; 2062 } 2063 } 2064 2065 /* 2066 * Not already in our hash table. 2067 * Do Resolve ID to server to see if server can find the item. If so 2068 * it will return the path from the share to the item. 2069 * 2070 * Need root vnode to do the Resolve ID call on 2071 */ 2072 error = smbfs_root(mp, &root_vp, context); 2073 if (error) { 2074 SMBDEBUG("smbfs_root failed %d\n", error); 2075 goto done; 2076 } 2077 root_np = VTOSMB(root_vp); 2078 2079 error = smb2fs_smb_cmpd_resolve_id(share, root_np, 2080 ino, &resolve_error, &server_path, 2081 context); 2082 if (error) { 2083 goto done; 2084 } 2085 2086 if (resolve_error) { 2087 error = resolve_error; 2088 goto done; 2089 } 2090 2091 if (server_path == NULL) { 2092 error = ENOENT; 2093 goto done; 2094 } 2095 2096 /* 2097 * Build the local path to the item starting with mount point 2098 */ 2099 if (strlcpy(path, vfs_statfs(mp)->f_mntonname, path_max) >= path_max) { 2100 /* Should not happen */ 2101 SMBDEBUG("path too long <%s>\n", vfs_statfs(mp)->f_mntonname); 2102 error = ENAMETOOLONG; 2103 goto done; 2104 } 2105 path_max = MAXPATHLEN - strlen(path); 2106 2107 if (strlcat(path, "/", path_max) >= path_max) { 2108 /* Should not happen */ 2109 SMBDEBUG("path too long <%s> + <%s>\n", path, "/"); 2110 error = ENAMETOOLONG; 2111 goto done; 2112 } 2113 path_max = MAXPATHLEN - strlen(path); 2114 2115 if (strlcat(path, server_path, path_max) >= path_max) { 2116 SMBDEBUG("path too long <%s> + <%s>\n", path, server_path); 2117 error = ENAMETOOLONG; 2118 goto done; 2119 } 2120 2121 /* 2122 * Follow that path to find the vnode 2123 */ 2124 error = vnode_lookup (path, 0, vpp, context); 2125 if (error) { 2126 SMBDEBUG("vnode_lookup failed %d\n", error); 2127 goto done; 2128 } 2129 2130 /* make sure it is one of my vnodes */ 2131 if (vnode_tag(*vpp) != VT_CIFS) { 2132 SMBDEBUG("vnode_lookup found non SMB vnode???\n"); 2133 error = ENOENT; 2134 goto done; 2135 } 2136 } 2137 else { 2138 error = ENOTSUP; 2139 } 2140 2141done: 2142 if (root_vp) { 2143 vnode_put(root_vp); 2144 } 2145 2146 if (server_path) { 2147 SMB_FREE(server_path, M_SMBTEMP); 2148 } 2149 2150 if (fap) { 2151 SMB_FREE(fap, M_SMBTEMP); 2152 } 2153 2154 if (path) { 2155 SMB_FREE(path, M_SMBTEMP); 2156 } 2157 2158 /* We only have a share if we took a reference, release it */ 2159 if (share) { 2160 smb_share_rele(share, context); 2161 } 2162 2163 SMB_LOG_KTRACE(SMB_DBG_VGET | DBG_FUNC_END, error, 0, 0, 0, 0); 2164 return (error); 2165} 2166 2167static int 2168smbfs_fhtovp(struct mount *mp, int fhlen, unsigned char *fhp, vnode_t *vpp, 2169 vfs_context_t context) 2170{ 2171#pragma unused(mp, fhlen, fhp, vpp, context) 2172 return (EINVAL); 2173} 2174 2175/* 2176 * Vnode pointer to File handle, should never happen either 2177 */ 2178static int 2179smbfs_vptofh(vnode_t vp, int *fhlen, unsigned char *fhp, vfs_context_t context) 2180{ 2181#pragma unused(vp, fhlen, fhp, context) 2182 return (EINVAL); 2183} 2184 2185/* 2186 * smbfs_sysctl handles the VFS_CTL_QUERY request which tells interested 2187 * parties if the connection with the remote server is up or down. 2188 */ 2189static int 2190smbfs_sysctl(int * name, unsigned namelen, user_addr_t oldp, size_t * oldlenp, 2191 user_addr_t newp, size_t newlen, vfs_context_t context) 2192{ 2193#pragma unused(oldlenp, newp, newlen) 2194 int error = 0; 2195 struct sysctl_req *req; 2196 struct mount *mp = NULL; 2197 struct smbmount *smp = NULL; 2198 struct vfsquery vq; 2199 int32_t dev = 0; 2200 struct smb_remount_info info; 2201 struct smb_share *share; 2202 struct vfs_server v_server; 2203 uint count; 2204 uint totlen; 2205 uint numThreads; 2206 struct netfs_status *nsp = NULL; 2207 struct smb_vc *vcp = NULL; 2208 struct smb_rq *rqp, *trqp; 2209 2210 SMB_LOG_KTRACE(SMB_DBG_SYSCTL | DBG_FUNC_START, name[0], 0, 0, 0, 0); 2211 2212 /* 2213 * All names at this level are terminal. 2214 */ 2215 if (namelen > 1) { 2216 error = ENOTDIR; /* overloaded */ 2217 goto done; 2218 } 2219 2220 switch (name[0]) { 2221 case VFS_CTL_STATFS: 2222 case VFS_CTL_UMOUNT: 2223 case VFS_CTL_NEWADDR: 2224 case VFS_CTL_TIMEO: 2225 case VFS_CTL_NOLOCKS: 2226 /* Force the VFS layer to handle these */ 2227 error = ENOTSUP; 2228 goto done; 2229 break; 2230 case SMBFS_SYSCTL_GET_SERVER_SHARE: 2231 case SMBFS_SYSCTL_REMOUNT_INFO: 2232 case SMBFS_SYSCTL_REMOUNT: 2233 case VFS_CTL_QUERY: 2234 case VFS_CTL_SADDR: 2235 case VFS_CTL_DISC: 2236 case VFS_CTL_SERVERINFO: 2237 case VFS_CTL_NSTATUS: 2238 { 2239 boolean_t is_64_bit = vfs_context_is64bit(context); 2240 union union_vfsidctl vc; 2241 2242 req = CAST_DOWN(struct sysctl_req *, oldp); 2243 error = SYSCTL_IN(req, &vc, is_64_bit ? sizeof(vc.vc64) : sizeof(vc.vc32)); 2244 if (error) { 2245 break; 2246 } 2247 mp = vfs_getvfs(&vc.vc32.vc_fsid); /* works for 32 and 64 */ 2248 /* 2249 * The sysctl_vfs_ctlbyfsid grabs a reference on the mount before 2250 * calling us, so we know the mount point can't go away while we 2251 * are working on it here. Just to be safe we make sure it can be 2252 * found by vfs_getvfs. Also if its being forced unmounted there 2253 * is nothing for us to do here just get out. 2254 */ 2255 if (mp && !(vfs_isforce(mp))) { 2256 smp = VFSTOSMBFS(mp); 2257 } 2258 if (!smp) { 2259 error = ENOENT; 2260 break; 2261 } 2262 req->newidx = 0; 2263 if (is_64_bit) { 2264 req->newptr = vc.vc64.vc_ptr; 2265 req->newlen = (size_t)vc.vc64.vc_len; 2266 } else { 2267 req->newptr = CAST_USER_ADDR_T(vc.vc32.vc_ptr); 2268 req->newlen = vc.vc32.vc_len; 2269 } 2270 break; 2271 } 2272 default: 2273 error = ENOTSUP; 2274 break; 2275 } 2276 if (error) { 2277 goto done; 2278 } 2279 2280 /* We only support new style vfs sysctl. */ 2281 switch (name[0]) { 2282 case SMBFS_SYSCTL_GET_SERVER_SHARE: 2283 { 2284 size_t len; 2285 char *serverShareStr; 2286 2287 share = smb_get_share_with_reference(smp); 2288 len = strnlen(SSTOVC(share)->vc_srvname, SMB_MAX_DNS_SRVNAMELEN); 2289 len += 1; /* Slash */ 2290 len += strnlen(share->ss_name, SMB_MAXSHARENAMELEN); 2291 len += 1; /* null byte */ 2292 SMB_MALLOC(serverShareStr, char *, len, M_TEMP, M_WAITOK | M_ZERO); 2293 strlcpy(serverShareStr, SSTOVC(share)->vc_srvname, len); 2294 strlcat(serverShareStr, "/", len); 2295 strlcat(serverShareStr, share->ss_name, len); 2296 smb_share_rele(share, context); 2297 error = SYSCTL_OUT(req, serverShareStr, len); 2298 SMB_FREE(serverShareStr, M_TEMP); 2299 break; 2300 } 2301 case SMBFS_SYSCTL_REMOUNT_INFO: 2302 share = smb_get_share_with_reference(smp); 2303 smbfs_remountInfo(mp, share, &info); 2304 smb_share_rele(share, context); 2305 error = SYSCTL_OUT(req, &info, sizeof(info)); 2306 break; 2307 case SMBFS_SYSCTL_REMOUNT: 2308 error = SYSCTL_IN(req, &dev, sizeof(dev)); 2309 if (!error) { 2310 error = smbfs_remount(dev, mp, smp, context); 2311 } 2312 break; 2313 case VFS_CTL_QUERY: 2314 bzero(&vq, sizeof(vq)); 2315 if (smp && (smp->sm_status & SM_STATUS_DEAD)) { 2316 vq.vq_flags |= VQ_DEAD; 2317 } else if (smp) { 2318 int dontNotify = ((smp->sm_args.altflags & SMBFS_MNT_SOFT) && 2319 (vfs_flags(smp->sm_mp) & MNT_DONTBROWSE)); 2320 2321 if ((smp->sm_status & SM_STATUS_DOWN) && !dontNotify) { 2322 vq.vq_flags |= VQ_NOTRESP; 2323 } 2324 if (smp->sm_status & SM_STATUS_REMOUNT) { 2325 vq.vq_flags |= VQ_ASSIST; 2326 } else if (smp->sm_status & SM_STATUS_UPDATED) { 2327 vq.vq_flags |= VQ_UPDATE; 2328 /* report back only once */ 2329 smp->sm_status &= ~SM_STATUS_UPDATED; 2330 } 2331 2332 /* Check if we have any pending svrmsg replies */ 2333 if (smp->sm_svrmsg_pending) { 2334 vq.vq_flags |= VQ_SERVEREVENT; 2335 } 2336 } 2337 2338 SMB_LOG_KTRACE(SMB_DBG_SYSCTL | DBG_FUNC_NONE, 2339 0xabc001, vq.vq_flags, 0, 0, 0); 2340 2341 SMBDEBUG("vq.vq_flags = 0x%x\n", vq.vq_flags); 2342 error = SYSCTL_OUT(req, &vq, sizeof(vq)); 2343 break; 2344 2345 case VFS_CTL_SADDR: 2346 if (smp->sm_args.altflags & SMBFS_MNT_DFS_SHARE) { 2347 /* Never let them unmount a dfs share */ 2348 error = ENOTSUP; 2349 } 2350 else { 2351 struct sockaddr_storage storage; 2352 struct sockaddr *saddr; 2353 size_t len; 2354 2355 memset(&storage, 0, sizeof(storage)); 2356 2357 /* Get a reference on the share */ 2358 share = smb_get_share_with_reference(smp); 2359 2360 if (SSTOVC(share)->vc_saddr->sa_family == AF_NETBIOS) { 2361 /* NetBIOS sockaddr get the real IPv4 sockaddr */ 2362 saddr = (struct sockaddr *) 2363 &((struct sockaddr_nb *) SSTOVC(share)->vc_saddr)->snb_addrin; 2364 } 2365 else { 2366 /* IPv4 or IPv6 sockaddr */ 2367 saddr = SSTOVC(share)->vc_saddr; 2368 } 2369 2370 /* Just to be safe, make sure we have a safe length */ 2371 len = (saddr->sa_len > sizeof(storage)) ? sizeof(storage) : saddr->sa_len; 2372 memcpy(&storage, saddr, len); 2373 smb_share_rele(share, context); 2374 error = SYSCTL_OUT(req, &storage, len); 2375 } 2376 break; 2377 2378 case VFS_CTL_DISC: 2379 if (smp->sm_args.altflags & SMBFS_MNT_DFS_SHARE) { 2380 /* Never let them unmount a dfs share */ 2381 error = ENOTSUP; 2382 } 2383 else { 2384 /* 2385 * Server is not responding. KEA will now request an unmount. 2386 * If there are no files opened for write AND there are no files 2387 * sitting in UBC with dirty data, then return 0 and signal KEA 2388 * to unmount us right now. KEA will not display this share in 2389 * the dialog since we should be unmounting immediately. 2390 * Otherwise, return EBUSY and let the dialog be displayed so 2391 * the user can decide what to do 2392 */ 2393 error = 0; /* assume can be immediately unmounted */ 2394 2395 /* Get a reference on the share */ 2396 share = smb_get_share_with_reference(smp); 2397 2398 if (!vfs_isrdonly(mp)) { 2399 /* only check for "busy" files if not read only */ 2400 lck_mtx_lock(&share->ss_shlock); 2401 2402 error = smbfs_IObusy(smp); 2403 SMBDEBUG("VFS_CTL_DISC - smbfs_IObusy returned %d\n", error); 2404 2405 lck_mtx_unlock(&share->ss_shlock); 2406 } 2407 2408 SMB_LOG_KTRACE(SMB_DBG_SYSCTL | DBG_FUNC_NONE, 2409 0xabc002, error, 0, 0, 0); 2410 2411 if (error != EBUSY) { 2412 SMBDEBUG("VFS_CTL_DISC unmounting\n"); 2413 /* ok to immediately be unmounted */ 2414 share->ss_dead(share); 2415 } 2416 2417 smb_share_rele(share, context); 2418 } 2419 2420 break; 2421 2422 case VFS_CTL_SERVERINFO: 2423 { 2424 /* Fill in the server name */ 2425 size_t len; 2426 share = smb_get_share_with_reference(smp); 2427 len = strnlen(SSTOVC(share)->vc_srvname, SMB_MAX_DNS_SRVNAMELEN); 2428 strlcpy((char *)v_server.vs_server_name, SSTOVC(share)->vc_srvname, len + 1); 2429 2430 if (smp->sm_svrmsg_pending) { 2431 /* Fill in shutdown delay */ 2432 if (smp->sm_svrmsg_pending & SVRMSG_RCVD_GOING_DOWN) { 2433 /* Set the delay (in minutes) we received from the server */ 2434 v_server.vs_minutes = smp->sm_svrmsg_shutdown_delay / 60; 2435 2436 smp->sm_svrmsg_pending &= ~SVRMSG_RCVD_GOING_DOWN; 2437 } else if (smp->sm_svrmsg_pending & SVRMSG_RCVD_SHUTDOWN_CANCEL) { 2438 /* Delay = 0xfff means server is staying up */ 2439 v_server.vs_minutes = 0xfff; 2440 smp->sm_svrmsg_pending &= ~SVRMSG_RCVD_SHUTDOWN_CANCEL; 2441 } 2442 } else { 2443 /* 2444 * No server events to report. 2445 * Don't return an error, otherwise nothing gets passed back. 2446 * Use -1 for v_minutes to indicate an error. 2447 */ 2448 v_server.vs_minutes = -1; 2449 } 2450 smb_share_rele(share, context); 2451 2452 error = SYSCTL_OUT(req, &v_server, sizeof(v_server)); 2453 2454 break; 2455 } 2456 2457 case VFS_CTL_NSTATUS: 2458 /* grab a reference until we're done with the share */ 2459 share = smb_get_share_with_reference(smp); 2460 2461 /* Get access to the vc underneath */ 2462 vcp = SSTOVC(share); 2463 2464 /* Round up the threads */ 2465 numThreads = 0; 2466 SMB_IOD_RQLOCK(vcp->vc_iod); 2467 TAILQ_FOREACH_SAFE(rqp, &(vcp->vc_iod)->iod_rqlist, sr_link, trqp) { 2468 /* Only count threads for this share and 2469 * they're not internal or async threads */ 2470 if ((rqp->sr_share == share) && 2471 !(rqp->sr_flags & (SMBR_ASYNC | SMBR_INTERNAL))) { 2472 numThreads++; 2473 } 2474 } 2475 SMB_IOD_RQUNLOCK(vcp->vc_iod); 2476 2477 /* Calculate total size of result buffer */ 2478 totlen = sizeof(struct netfs_status) + (numThreads * sizeof(uint64_t)); 2479 2480 if (req->oldptr == USER_ADDR_NULL) { // Caller is querying buffer size 2481 smb_share_rele(share, context); 2482 return SYSCTL_OUT(req, NULL, totlen); 2483 } 2484 2485 MALLOC(nsp, struct netfs_status *, totlen, M_TEMP, M_WAITOK|M_ZERO); 2486 if (nsp == NULL) { 2487 smb_share_rele(share, context); 2488 return ENOMEM; 2489 } 2490 2491 if (smp->sm_status & SM_STATUS_DOWN) { 2492 nsp->ns_status |= VQ_NOTRESP; 2493 } 2494 if (smp->sm_status & SM_STATUS_DEAD) { 2495 nsp->ns_status |= VQ_DEAD; 2496 } 2497 2498 /* Return some significant mount options as a string 2499 * e.g. "rw,soft,vers=0x0302,sec=kerberos,timeout=20 */ 2500 snprintf(nsp->ns_mountopts, sizeof(nsp->ns_mountopts), 2501 "%s,%s,vers=0x%X,sec=%s,timeout=%d", 2502 (vfs_flags(mp) & MNT_RDONLY) ? "ro" : "rw", 2503 (smp->sm_args.altflags & SMBFS_MNT_SOFT) ? "soft" : "hard", 2504 vcp->vc_sopt.sv_dialect ? vcp->vc_sopt.sv_dialect : 0x01, 2505 (vcp->vc_flags & SMBV_GUEST_ACCESS) ? "guest" : 2506 (vcp->vc_flags & SMBV_PRIV_GUEST_ACCESS) ? "privguest" : 2507 (vcp->vc_flags & SMBV_ANONYMOUS_ACCESS) ? "anonymous" : 2508 (vcp->vc_flags & SMBV_KERBEROS_ACCESS) ? "kerberos" : 2509 (vcp->vc_sopt.sv_caps & SMB_CAP_EXT_SECURITY) ? "gss" : "unknown", 2510 (smp->sm_args.altflags & SMBFS_MNT_SOFT) ? share->ss_soft_timer : (share->ss_dead_timer + vcp->vc_resp_wait_timeout)); 2511 2512 nsp->ns_threadcount = numThreads; 2513 2514 /* 2515 * Get the thread ids of threads waiting for a reply 2516 * and find the longest wait time. 2517 */ 2518 if (numThreads > 0) { 2519 struct timespec now; 2520 time_t sendtime; 2521 2522 nanouptime(&now); 2523 count = 0; 2524 sendtime = now.tv_sec; 2525 SMB_IOD_RQLOCK(vcp->vc_iod); 2526 TAILQ_FOREACH_SAFE(rqp, &(vcp->vc_iod)->iod_rqlist, sr_link, trqp) { 2527 /* Only count threads for this share if they're not internal threads */ 2528 if ((rqp->sr_share == share) && 2529 !(rqp->sr_flags & (SMBR_ASYNC | SMBR_INTERNAL))) { 2530 if ((rqp->sr_state & ~SMBRQ_NOTSENT) && rqp->sr_timesent.tv_sec < sendtime) { 2531 sendtime = rqp->sr_timesent.tv_sec; 2532 } 2533 nsp->ns_threadids[count] = rqp->sr_threadId; 2534 if (++count >= numThreads) 2535 break; 2536 } 2537 } 2538 nsp->ns_waittime = (uint32_t)(now.tv_sec - sendtime); 2539 SMB_IOD_RQUNLOCK(vcp->vc_iod); 2540 } 2541 2542 smb_share_rele(share, context); 2543 2544 error = SYSCTL_OUT(req, nsp, totlen); 2545 break; 2546 2547 default: 2548 error = ENOTSUP; 2549 break; 2550 } 2551 2552done: 2553 if (error) { 2554 SMBWARNING("name[0] = %d error = %d\n", name[0], error); 2555 } 2556 2557 SMB_LOG_KTRACE(SMB_DBG_SYSCTL | DBG_FUNC_END, error, 0, 0, 0, 0); 2558 return (error); 2559} 2560 2561static char smbfs_name[MFSNAMELEN] = "smbfs"; 2562 2563kmod_info_t *smbfs_kmod_infop; 2564 2565typedef int (*PFI)(); 2566 2567extern struct vnodeopv_desc smbfs_vnodeop_opv_desc; 2568static struct vnodeopv_desc *smbfs_vnodeop_opv_desc_list[1] = 2569{ 2570 &smbfs_vnodeop_opv_desc 2571}; 2572 2573 2574extern int version_major; 2575extern int version_minor; 2576 2577static vfstable_t smbfs_vfsconf; 2578 2579static struct vfsops smbfs_vfsops = { 2580 smbfs_mount, 2581 smbfs_start, 2582 smbfs_unmount, 2583 smbfs_root, 2584 NULL, /* quotactl */ 2585 smbfs_vfs_getattr, 2586 smbfs_sync, 2587 smbfs_vget, 2588 smbfs_fhtovp, 2589 smbfs_vptofh, 2590 smbfs_init, 2591 smbfs_sysctl, 2592 NULL, 2593 {0} 2594}; 2595 2596int smbfs_module_start(kmod_info_t *ki, void *data) 2597{ 2598#pragma unused(data) 2599 struct vfs_fsentry vfe; 2600 int error; 2601 2602 smbfs_kmod_infop = ki; 2603 2604 vfe.vfe_vfsops = &smbfs_vfsops; 2605 /* We just have vnode operations for regular files and directories */ 2606 vfe.vfe_vopcnt = 1; 2607 vfe.vfe_opvdescs = smbfs_vnodeop_opv_desc_list; 2608 strlcpy(vfe.vfe_fsname, smbfs_name, sizeof(vfe.vfe_fsname)); 2609 vfe.vfe_flags = VFS_TBLTHREADSAFE | VFS_TBLFSNODELOCK | VFS_TBLNOTYPENUM | 2610 VFS_TBL64BITREADY | VFS_TBLREADDIR_EXTENDED | 2611 VFS_TBLUNMOUNT_PREFLIGHT; 2612 2613 vfe.vfe_reserv[0] = 0; 2614 vfe.vfe_reserv[1] = 0; 2615 2616 error = vfs_fsadd(&vfe, &smbfs_vfsconf); 2617 if (error) 2618 goto out; 2619 2620 smbnet_lock_init(); /* Initialize the network locks */ 2621 2622 /* This just calls nsmb_dev_load */ 2623 SEND_EVENT(dev_netsmb, MOD_LOAD); 2624 2625 sysctl_register_oid(&sysctl__net_smb); 2626 sysctl_register_oid(&sysctl__net_smb_fs); 2627 2628 sysctl_register_oid(&sysctl__net_smb_fs_version); 2629 sysctl_register_oid(&sysctl__net_smb_fs_loglevel); 2630 2631 sysctl_register_oid(&sysctl__net_smb_fs_kern_deadtimer); 2632 sysctl_register_oid(&sysctl__net_smb_fs_kern_hard_deadtimer); 2633 sysctl_register_oid(&sysctl__net_smb_fs_kern_soft_deadtimer); 2634 2635 sysctl_register_oid(&sysctl__net_smb_fs_tcpsndbuf); 2636 sysctl_register_oid(&sysctl__net_smb_fs_tcprcvbuf); 2637 2638 sysctl_register_oid(&sysctl__net_smb_fs_maxwrite); 2639 sysctl_register_oid(&sysctl__net_smb_fs_maxread); 2640 2641 sysctl_register_oid(&sysctl__net_smb_fs_maxsegreadsize); 2642 sysctl_register_oid(&sysctl__net_smb_fs_maxsegwritesize); 2643 2644 smbfs_install_sleep_wake_notifier(); 2645 2646out: 2647 return (error ? KERN_FAILURE : KERN_SUCCESS); 2648} 2649 2650 2651int smbfs_module_stop(kmod_info_t *ki, void *data) 2652{ 2653#pragma unused(ki) 2654#pragma unused(data) 2655 int error; 2656 2657 /* 2658 * The dev_rw_lck lock is global value and protects the dev_open_cnt, 2659 * unloadInProgress flag, the device opens, closes, loads and unloads. All device 2660 * opens and close are serialize, so we only have one happening at any time. 2661 */ 2662 lck_rw_lock_exclusive(dev_rw_lck); 2663 unloadInProgress = TRUE; 2664 /* We are still in use, don't unload. */ 2665 if (mount_cnt || dev_open_cnt) { 2666 SMBWARNING("Still in use, we have %d volumes mounted and %d devices opened\n", 2667 mount_cnt, dev_open_cnt); 2668 unloadInProgress = FALSE; 2669 lck_rw_unlock_exclusive(dev_rw_lck); 2670 return KERN_NO_ACCESS; 2671 } 2672 lck_rw_unlock_exclusive(dev_rw_lck); 2673 error = vfs_fsremove(smbfs_vfsconf); 2674 if (error) { 2675 /* Should never happen */ 2676 SMBERROR("vfs_fsremove failed with %d, may want to reboot!\n", error); 2677 goto out; 2678 } 2679 sysctl_unregister_oid(&sysctl__net_smb_fs_maxsegreadsize); 2680 sysctl_unregister_oid(&sysctl__net_smb_fs_maxsegwritesize); 2681 2682 sysctl_unregister_oid(&sysctl__net_smb_fs_maxwrite); 2683 sysctl_unregister_oid(&sysctl__net_smb_fs_maxread); 2684 2685 sysctl_unregister_oid(&sysctl__net_smb_fs_tcpsndbuf); 2686 sysctl_unregister_oid(&sysctl__net_smb_fs_tcprcvbuf); 2687 2688 sysctl_unregister_oid(&sysctl__net_smb_fs_kern_deadtimer); 2689 sysctl_unregister_oid(&sysctl__net_smb_fs_kern_hard_deadtimer); 2690 sysctl_unregister_oid(&sysctl__net_smb_fs_kern_soft_deadtimer); 2691 2692 sysctl_unregister_oid(&sysctl__net_smb_fs_version); 2693 sysctl_unregister_oid(&sysctl__net_smb_fs_loglevel); 2694 2695 sysctl_unregister_oid(&sysctl__net_smb_fs); 2696 sysctl_unregister_oid(&sysctl__net_smb); 2697 2698 /* This just calls nsmb_dev_load */ 2699 SEND_EVENT(dev_netsmb, MOD_UNLOAD); 2700 2701 smbfs_remove_sleep_wake_notifier(); 2702 2703 lck_rw_free(dev_rw_lck, dev_lck_grp); 2704 smbfs_lock_uninit(); /* Free up the file system locks */ 2705 smbnet_lock_uninit(); /* Free up the network locks */ 2706 2707out: 2708 return (error ? KERN_FAILURE : KERN_SUCCESS); 2709} 2710