1da6c28aaSamw /* 2da6c28aaSamw * CDDL HEADER START 3da6c28aaSamw * 4da6c28aaSamw * The contents of this file are subject to the terms of the 5da6c28aaSamw * Common Development and Distribution License (the "License"). 6da6c28aaSamw * You may not use this file except in compliance with the License. 7da6c28aaSamw * 8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10da6c28aaSamw * See the License for the specific language governing permissions 11da6c28aaSamw * and limitations under the License. 12da6c28aaSamw * 13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18da6c28aaSamw * 19da6c28aaSamw * CDDL HEADER END 20da6c28aaSamw */ 21da6c28aaSamw /* 22148c5f43SAlan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23da6c28aaSamw */ 24da6c28aaSamw 25da6c28aaSamw #include <sys/types.h> 26da6c28aaSamw #include <sys/ddi.h> 27da6c28aaSamw #include <sys/modctl.h> 28da6c28aaSamw #include <sys/cred.h> 29da6c28aaSamw #include <sys/ioccom.h> 30da6c28aaSamw #include <sys/policy.h> 3194fff790SAlan Wright #include <sys/cmn_err.h> 32bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h> 33da6c28aaSamw #include <smbsrv/smb_ioctl.h> 34faa1795aSjb150015 35faa1795aSjb150015 static int smb_drv_open(dev_t *, int, int, cred_t *); 36faa1795aSjb150015 static int smb_drv_close(dev_t, int, int, cred_t *); 37faa1795aSjb150015 static int smb_drv_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 38da6c28aaSamw static int smb_drv_attach(dev_info_t *, ddi_attach_cmd_t); 39da6c28aaSamw static int smb_drv_detach(dev_info_t *, ddi_detach_cmd_t); 40da6c28aaSamw static int smb_drv_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 41da6c28aaSamw 42da6c28aaSamw /* 43faa1795aSjb150015 * ***************************************************************************** 44faa1795aSjb150015 * ****************************** Global Variables ***************************** 45faa1795aSjb150015 * ***************************************************************************** 46faa1795aSjb150015 * 47faa1795aSjb150015 * These variables can only be changed through the /etc/system file. 48da6c28aaSamw */ 49faa1795aSjb150015 50faa1795aSjb150015 /* 51faa1795aSjb150015 * Maximum buffer size for NT: configurable based on the client environment. 52faa1795aSjb150015 * IR104720 Experiments with Windows 2000 indicate that we achieve better 53faa1795aSjb150015 * SmbWriteX performance with a buffer size of 64KB instead of the 37KB used 54faa1795aSjb150015 * with Windows NT4.0. Previous experiments with NT4.0 resulted in directory 55faa1795aSjb150015 * listing problems so this buffer size is configurable based on the end-user 56faa1795aSjb150015 * environment. When in doubt use 37KB. 57*cb174861Sjoyce mcintosh * 58*cb174861Sjoyce mcintosh * smb_raw_mode: read_raw and write_raw supported (1) or NOT supported (0). 59faa1795aSjb150015 */ 60faa1795aSjb150015 int smb_maxbufsize = SMB_NT_MAXBUF; 61*cb174861Sjoyce mcintosh int smb_oplock_levelII = 1; 622c2961f8Sjose borrego int smb_oplock_timeout = OPLOCK_STD_TIMEOUT; 63*cb174861Sjoyce mcintosh int smb_oplock_min_timeout = OPLOCK_MIN_TIMEOUT; 64faa1795aSjb150015 int smb_flush_required = 1; 65faa1795aSjb150015 int smb_dirsymlink_enable = 1; 66c8ec8eeaSjose borrego int smb_sign_debug = 0; 67*cb174861Sjoyce mcintosh int smb_raw_mode = 1; 68*cb174861Sjoyce mcintosh int smb_shortnames = 1; 692c2961f8Sjose borrego uint_t smb_audit_flags = 702c2961f8Sjose borrego #ifdef DEBUG 712c2961f8Sjose borrego SMB_AUDIT_NODE; 722c2961f8Sjose borrego #else 732c2961f8Sjose borrego 0; 742c2961f8Sjose borrego #endif 75faa1795aSjb150015 76faa1795aSjb150015 /* 77*cb174861Sjoyce mcintosh * Maximum number of simultaneous authentication, share mapping, pipe open 78*cb174861Sjoyce mcintosh * requests to be processed. 79*cb174861Sjoyce mcintosh */ 80*cb174861Sjoyce mcintosh int smb_ssetup_threshold = 256; 81*cb174861Sjoyce mcintosh int smb_tcon_threshold = 1024; 82*cb174861Sjoyce mcintosh int smb_opipe_threshold = 1024; 83*cb174861Sjoyce mcintosh 84*cb174861Sjoyce mcintosh /* 85*cb174861Sjoyce mcintosh * Number of milliseconds that a request will be stalled if it comes in after 86*cb174861Sjoyce mcintosh * the maximum number of inflight operations are being proccessed. 87*cb174861Sjoyce mcintosh */ 88*cb174861Sjoyce mcintosh int smb_ssetup_timeout = (30 * 1000); 89*cb174861Sjoyce mcintosh int smb_tcon_timeout = (30 * 1000); 90*cb174861Sjoyce mcintosh int smb_opipe_timeout = (30 * 1000); 91*cb174861Sjoyce mcintosh 92*cb174861Sjoyce mcintosh int smb_threshold_debug = 0; 93*cb174861Sjoyce mcintosh 94*cb174861Sjoyce mcintosh 95*cb174861Sjoyce mcintosh /* 96faa1795aSjb150015 * ***************************************************************************** 97faa1795aSjb150015 * ********************** Static Variables / Module Linkage ******************** 98faa1795aSjb150015 * ***************************************************************************** 99faa1795aSjb150015 */ 100faa1795aSjb150015 101da6c28aaSamw static struct cb_ops cbops = { 102da6c28aaSamw smb_drv_open, /* cb_open */ 103da6c28aaSamw smb_drv_close, /* cb_close */ 104da6c28aaSamw nodev, /* cb_strategy */ 105da6c28aaSamw nodev, /* cb_print */ 106da6c28aaSamw nodev, /* cb_dump */ 107da6c28aaSamw nodev, /* cb_read */ 108da6c28aaSamw nodev, /* cb_write */ 109da6c28aaSamw smb_drv_ioctl, /* cb_ioctl */ 110da6c28aaSamw nodev, /* cb_devmap */ 111da6c28aaSamw nodev, /* cb_mmap */ 112da6c28aaSamw nodev, /* cb_segmap */ 113da6c28aaSamw nochpoll, /* cb_chpoll */ 114da6c28aaSamw ddi_prop_op, /* cb_prop_op */ 115da6c28aaSamw NULL, /* cb_streamtab */ 116da6c28aaSamw D_MP, /* cb_flag */ 117da6c28aaSamw CB_REV, /* cb_rev */ 118da6c28aaSamw nodev, /* cb_aread */ 119da6c28aaSamw nodev, /* cb_awrite */ 120da6c28aaSamw }; 121da6c28aaSamw 122da6c28aaSamw static struct dev_ops devops = { 123da6c28aaSamw DEVO_REV, /* devo_rev */ 124da6c28aaSamw 0, /* devo_refcnt */ 125da6c28aaSamw smb_drv_getinfo, /* devo_getinfo */ 126da6c28aaSamw nulldev, /* devo_identify */ 127da6c28aaSamw nulldev, /* devo_probe */ 128da6c28aaSamw smb_drv_attach, /* devo_attach */ 129da6c28aaSamw smb_drv_detach, /* devo_detach */ 130da6c28aaSamw nodev, /* devo_reset */ 131da6c28aaSamw &cbops, /* devo_cb_ops */ 132da6c28aaSamw NULL, /* devo_bus_ops */ 133da6c28aaSamw NULL, /* devo_power */ 13419397407SSherry Moore ddi_quiesce_not_needed, /* devo_quiesce */ 135da6c28aaSamw }; 136da6c28aaSamw 137da6c28aaSamw static struct modldrv modldrv = { 138da6c28aaSamw &mod_driverops, /* drv_modops */ 13919397407SSherry Moore "CIFS Server Protocol", /* drv_linkinfo */ 140da6c28aaSamw &devops, 141da6c28aaSamw }; 142da6c28aaSamw 143da6c28aaSamw static struct modlinkage modlinkage = { 144da6c28aaSamw MODREV_1, /* revision of the module, must be: MODREV_1 */ 145da6c28aaSamw &modldrv, /* ptr to linkage structures */ 146da6c28aaSamw NULL, 147da6c28aaSamw }; 148da6c28aaSamw 149da6c28aaSamw static dev_info_t *smb_drv_dip = NULL; 150da6c28aaSamw 151da6c28aaSamw /* 152faa1795aSjb150015 * **************************************************************************** 153faa1795aSjb150015 * Module Interface 154faa1795aSjb150015 * **************************************************************************** 155da6c28aaSamw */ 156da6c28aaSamw 157da6c28aaSamw int 158da6c28aaSamw _init(void) 159da6c28aaSamw { 160f9a15d2cSjose borrego int rc; 161f9a15d2cSjose borrego 162148c5f43SAlan Wright if ((rc = smb_kshare_init()) != 0) 163148c5f43SAlan Wright return (rc); 164148c5f43SAlan Wright 165148c5f43SAlan Wright if ((rc = smb_server_svc_init()) != 0) { 166148c5f43SAlan Wright smb_kshare_fini(); 167148c5f43SAlan Wright return (rc); 168148c5f43SAlan Wright } 169148c5f43SAlan Wright 170148c5f43SAlan Wright if ((rc = mod_install(&modlinkage)) != 0) { 171148c5f43SAlan Wright smb_kshare_fini(); 172f9a15d2cSjose borrego (void) smb_server_svc_fini(); 173f9a15d2cSjose borrego } 174148c5f43SAlan Wright 175f9a15d2cSjose borrego return (rc); 176da6c28aaSamw } 177da6c28aaSamw 178da6c28aaSamw int 179da6c28aaSamw _info(struct modinfo *modinfop) 180da6c28aaSamw { 181da6c28aaSamw return (mod_info(&modlinkage, modinfop)); 182da6c28aaSamw } 183da6c28aaSamw 184da6c28aaSamw int 185da6c28aaSamw _fini(void) 186da6c28aaSamw { 187f9a15d2cSjose borrego int rc; 188f9a15d2cSjose borrego 189148c5f43SAlan Wright if ((rc = mod_remove(&modlinkage)) == 0) { 190f9a15d2cSjose borrego rc = smb_server_svc_fini(); 191148c5f43SAlan Wright smb_kshare_fini(); 192148c5f43SAlan Wright } 193148c5f43SAlan Wright 194f9a15d2cSjose borrego return (rc); 195da6c28aaSamw } 196da6c28aaSamw 197faa1795aSjb150015 /* 198faa1795aSjb150015 * **************************************************************************** 199faa1795aSjb150015 * Pseudo Device Entry Points 200faa1795aSjb150015 * **************************************************************************** 201faa1795aSjb150015 */ 202faa1795aSjb150015 /* ARGSUSED */ 203faa1795aSjb150015 static int 204faa1795aSjb150015 smb_drv_open(dev_t *devp, int flag, int otyp, cred_t *credp) 205faa1795aSjb150015 { 206faa1795aSjb150015 /* 207faa1795aSjb150015 * Check caller's privileges. 208faa1795aSjb150015 */ 209faa1795aSjb150015 if (secpolicy_smb(credp) != 0) 210faa1795aSjb150015 return (EPERM); 211faa1795aSjb150015 212faa1795aSjb150015 /* 213faa1795aSjb150015 * Start SMB service state machine 214faa1795aSjb150015 */ 215faa1795aSjb150015 return (smb_server_create()); 216faa1795aSjb150015 } 217faa1795aSjb150015 218faa1795aSjb150015 /* ARGSUSED */ 219faa1795aSjb150015 static int 220faa1795aSjb150015 smb_drv_close(dev_t dev, int flag, int otyp, cred_t *credp) 221faa1795aSjb150015 { 222faa1795aSjb150015 return (smb_server_delete()); 223faa1795aSjb150015 } 224faa1795aSjb150015 225faa1795aSjb150015 /* ARGSUSED */ 226faa1795aSjb150015 static int 22729bd2886SAlan Wright smb_drv_ioctl(dev_t drv, int cmd, intptr_t argp, int flags, cred_t *cred, 228faa1795aSjb150015 int *retval) 229faa1795aSjb150015 { 23029bd2886SAlan Wright smb_ioc_t *ioc; 23129bd2886SAlan Wright smb_ioc_header_t ioc_hdr; 23229bd2886SAlan Wright uint32_t crc; 23329bd2886SAlan Wright boolean_t copyout = B_FALSE; 234faa1795aSjb150015 int rc = 0; 235faa1795aSjb150015 23629bd2886SAlan Wright if (ddi_copyin((const void *)argp, &ioc_hdr, sizeof (smb_ioc_header_t), 23729bd2886SAlan Wright flags) || (ioc_hdr.version != SMB_IOC_VERSION)) 238faa1795aSjb150015 return (EFAULT); 239faa1795aSjb150015 24029bd2886SAlan Wright crc = ioc_hdr.crc; 24129bd2886SAlan Wright ioc_hdr.crc = 0; 24229bd2886SAlan Wright if (smb_crc_gen((uint8_t *)&ioc_hdr, sizeof (ioc_hdr)) != crc) 24394fff790SAlan Wright return (EFAULT); 24494fff790SAlan Wright 24529bd2886SAlan Wright ioc = kmem_alloc(ioc_hdr.len, KM_SLEEP); 24629bd2886SAlan Wright if (ddi_copyin((const void *)argp, ioc, ioc_hdr.len, flags)) { 24729bd2886SAlan Wright kmem_free(ioc, ioc_hdr.len); 24829bd2886SAlan Wright return (EFAULT); 24929bd2886SAlan Wright } 25029bd2886SAlan Wright 251faa1795aSjb150015 switch (cmd) { 252faa1795aSjb150015 case SMB_IOC_CONFIG: 25329bd2886SAlan Wright rc = smb_server_configure(&ioc->ioc_cfg); 254faa1795aSjb150015 break; 255faa1795aSjb150015 case SMB_IOC_START: 25629bd2886SAlan Wright rc = smb_server_start(&ioc->ioc_start); 257faa1795aSjb150015 break; 2589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case SMB_IOC_STOP: 2599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_server_stop(); 2609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break; 2619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case SMB_IOC_EVENT: 2629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_server_notify_event(&ioc->ioc_event); 2639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break; 264faa1795aSjb150015 case SMB_IOC_NBT_LISTEN: 26529bd2886SAlan Wright rc = smb_server_nbt_listen(&ioc->ioc_listen); 266faa1795aSjb150015 break; 267faa1795aSjb150015 case SMB_IOC_TCP_LISTEN: 26829bd2886SAlan Wright rc = smb_server_tcp_listen(&ioc->ioc_listen); 269faa1795aSjb150015 break; 270faa1795aSjb150015 case SMB_IOC_NBT_RECEIVE: 271faa1795aSjb150015 rc = smb_server_nbt_receive(); 272faa1795aSjb150015 break; 273faa1795aSjb150015 case SMB_IOC_TCP_RECEIVE: 274faa1795aSjb150015 rc = smb_server_tcp_receive(); 275faa1795aSjb150015 break; 276faa1795aSjb150015 case SMB_IOC_GMTOFF: 27729bd2886SAlan Wright rc = smb_server_set_gmtoff(&ioc->ioc_gmt); 27829bd2886SAlan Wright break; 27929bd2886SAlan Wright case SMB_IOC_SHARE: 280148c5f43SAlan Wright rc = smb_kshare_export_list(&ioc->ioc_share); 28129bd2886SAlan Wright break; 28229bd2886SAlan Wright case SMB_IOC_UNSHARE: 283148c5f43SAlan Wright rc = smb_kshare_unexport_list(&ioc->ioc_share); 28429bd2886SAlan Wright break; 285*cb174861Sjoyce mcintosh case SMB_IOC_SHAREINFO: 286*cb174861Sjoyce mcintosh rc = smb_kshare_info(&ioc->ioc_shareinfo); 287*cb174861Sjoyce mcintosh copyout = B_TRUE; 288*cb174861Sjoyce mcintosh break; 2891fcced4cSJordan Brown case SMB_IOC_NUMOPEN: 2901fcced4cSJordan Brown rc = smb_server_numopen(&ioc->ioc_opennum); 29129bd2886SAlan Wright copyout = B_TRUE; 29229bd2886SAlan Wright break; 2931fcced4cSJordan Brown case SMB_IOC_SVCENUM: 2941fcced4cSJordan Brown rc = smb_server_enum(&ioc->ioc_svcenum); 29529bd2886SAlan Wright copyout = B_TRUE; 296faa1795aSjb150015 break; 2971fcced4cSJordan Brown case SMB_IOC_SESSION_CLOSE: 2981fcced4cSJordan Brown rc = smb_server_session_close(&ioc->ioc_session); 2991fcced4cSJordan Brown break; 3001fcced4cSJordan Brown case SMB_IOC_FILE_CLOSE: 3011fcced4cSJordan Brown rc = smb_server_file_close(&ioc->ioc_fileid); 3021fcced4cSJordan Brown break; 303*cb174861Sjoyce mcintosh case SMB_IOC_SPOOLDOC: 304*cb174861Sjoyce mcintosh rc = smb_server_spooldoc(&ioc->ioc_spooldoc); 305*cb174861Sjoyce mcintosh copyout = B_TRUE; 306*cb174861Sjoyce mcintosh break; 307faa1795aSjb150015 default: 308faa1795aSjb150015 rc = ENOTTY; 309faa1795aSjb150015 break; 310faa1795aSjb150015 } 31129bd2886SAlan Wright if ((rc == 0) && copyout) { 31229bd2886SAlan Wright if (ddi_copyout((const void *)ioc, (void *)argp, ioc_hdr.len, 31329bd2886SAlan Wright flags)) 31429bd2886SAlan Wright rc = EFAULT; 31529bd2886SAlan Wright } 31629bd2886SAlan Wright kmem_free(ioc, ioc_hdr.len); 317da6c28aaSamw return (rc); 318da6c28aaSamw } 319da6c28aaSamw 320da6c28aaSamw /* 321faa1795aSjb150015 * **************************************************************************** 322faa1795aSjb150015 * Pseudo Device Operations 323faa1795aSjb150015 * **************************************************************************** 324da6c28aaSamw */ 325faa1795aSjb150015 static int 326faa1795aSjb150015 smb_drv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 327faa1795aSjb150015 { 328faa1795aSjb150015 if (cmd == DDI_ATTACH) { 329faa1795aSjb150015 /* we only allow instance 0 to attach */ 330faa1795aSjb150015 if (ddi_get_instance(dip) == 0) { 331faa1795aSjb150015 /* create the minor node */ 332faa1795aSjb150015 if (ddi_create_minor_node(dip, "smbsrv", S_IFCHR, 0, 333faa1795aSjb150015 DDI_PSEUDO, 0) == DDI_SUCCESS) { 334faa1795aSjb150015 smb_drv_dip = dip; 335faa1795aSjb150015 return (DDI_SUCCESS); 336faa1795aSjb150015 } else { 337faa1795aSjb150015 cmn_err(CE_WARN, "smb_drv_attach:" 338faa1795aSjb150015 " failed creating minor node"); 339faa1795aSjb150015 } 340faa1795aSjb150015 } 341faa1795aSjb150015 } 342faa1795aSjb150015 return (DDI_FAILURE); 343faa1795aSjb150015 } 344faa1795aSjb150015 345faa1795aSjb150015 static int 346faa1795aSjb150015 smb_drv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 347faa1795aSjb150015 { 348faa1795aSjb150015 if (cmd == DDI_DETACH) { 349faa1795aSjb150015 ASSERT(dip == smb_drv_dip); 350faa1795aSjb150015 ddi_remove_minor_node(dip, NULL); 351faa1795aSjb150015 smb_drv_dip = NULL; 352faa1795aSjb150015 return (DDI_SUCCESS); 353faa1795aSjb150015 } 354faa1795aSjb150015 return (DDI_FAILURE); 355faa1795aSjb150015 } 356da6c28aaSamw 357da6c28aaSamw /* ARGSUSED */ 358da6c28aaSamw static int 359da6c28aaSamw smb_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 360da6c28aaSamw { 361da6c28aaSamw ulong_t instance = getminor((dev_t)arg); 362da6c28aaSamw 363da6c28aaSamw switch (cmd) { 364da6c28aaSamw case DDI_INFO_DEVT2DEVINFO: 365da6c28aaSamw *result = smb_drv_dip; 366da6c28aaSamw return (DDI_SUCCESS); 367da6c28aaSamw 368da6c28aaSamw case DDI_INFO_DEVT2INSTANCE: 369da6c28aaSamw *result = (void *)instance; 370da6c28aaSamw return (DDI_SUCCESS); 371da6c28aaSamw 372da6c28aaSamw default: 373da6c28aaSamw break; 374da6c28aaSamw } 375da6c28aaSamw 376da6c28aaSamw return (DDI_FAILURE); 377da6c28aaSamw } 378