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 /* 22*f9a15d2cSjose borrego * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23da6c28aaSamw * Use is subject to license terms. 24da6c28aaSamw */ 25da6c28aaSamw 26da6c28aaSamw #include <sys/types.h> 27da6c28aaSamw #include <sys/ddi.h> 28da6c28aaSamw #include <sys/modctl.h> 29da6c28aaSamw #include <sys/cred.h> 30da6c28aaSamw #include <sys/ioccom.h> 31da6c28aaSamw #include <sys/policy.h> 3294fff790SAlan Wright #include <sys/cmn_err.h> 33da6c28aaSamw #include <smbsrv/smb_incl.h> 34da6c28aaSamw #include <smbsrv/smb_door_svc.h> 35da6c28aaSamw #include <smbsrv/smb_ioctl.h> 36da6c28aaSamw #include <smbsrv/smb_kproto.h> 37faa1795aSjb150015 38faa1795aSjb150015 static int smb_drv_open(dev_t *, int, int, cred_t *); 39faa1795aSjb150015 static int smb_drv_close(dev_t, int, int, cred_t *); 40faa1795aSjb150015 static int smb_drv_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 41da6c28aaSamw static int smb_drv_attach(dev_info_t *, ddi_attach_cmd_t); 42da6c28aaSamw static int smb_drv_detach(dev_info_t *, ddi_detach_cmd_t); 43da6c28aaSamw static int smb_drv_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 44da6c28aaSamw 45da6c28aaSamw /* 46faa1795aSjb150015 * ***************************************************************************** 47faa1795aSjb150015 * ****************************** Global Variables ***************************** 48faa1795aSjb150015 * ***************************************************************************** 49faa1795aSjb150015 * 50faa1795aSjb150015 * These variables can only be changed through the /etc/system file. 51da6c28aaSamw */ 52faa1795aSjb150015 53faa1795aSjb150015 /* 54faa1795aSjb150015 * Maximum buffer size for NT: configurable based on the client environment. 55faa1795aSjb150015 * IR104720 Experiments with Windows 2000 indicate that we achieve better 56faa1795aSjb150015 * SmbWriteX performance with a buffer size of 64KB instead of the 37KB used 57faa1795aSjb150015 * with Windows NT4.0. Previous experiments with NT4.0 resulted in directory 58faa1795aSjb150015 * listing problems so this buffer size is configurable based on the end-user 59faa1795aSjb150015 * environment. When in doubt use 37KB. 60faa1795aSjb150015 */ 61faa1795aSjb150015 int smb_maxbufsize = SMB_NT_MAXBUF; 62faa1795aSjb150015 clock_t smb_oplock_timeout = OPLOCK_STD_TIMEOUT; 63faa1795aSjb150015 int smb_flush_required = 1; 64faa1795aSjb150015 int smb_dirsymlink_enable = 1; 65faa1795aSjb150015 int smb_announce_quota = 0; 66c8ec8eeaSjose borrego int smb_sign_debug = 0; 67faa1795aSjb150015 68faa1795aSjb150015 /* 69faa1795aSjb150015 * ***************************************************************************** 70faa1795aSjb150015 * ********************** Static Variables / Module Linkage ******************** 71faa1795aSjb150015 * ***************************************************************************** 72faa1795aSjb150015 */ 73faa1795aSjb150015 74da6c28aaSamw static struct cb_ops cbops = { 75da6c28aaSamw smb_drv_open, /* cb_open */ 76da6c28aaSamw smb_drv_close, /* cb_close */ 77da6c28aaSamw nodev, /* cb_strategy */ 78da6c28aaSamw nodev, /* cb_print */ 79da6c28aaSamw nodev, /* cb_dump */ 80da6c28aaSamw nodev, /* cb_read */ 81da6c28aaSamw nodev, /* cb_write */ 82da6c28aaSamw smb_drv_ioctl, /* cb_ioctl */ 83da6c28aaSamw nodev, /* cb_devmap */ 84da6c28aaSamw nodev, /* cb_mmap */ 85da6c28aaSamw nodev, /* cb_segmap */ 86da6c28aaSamw nochpoll, /* cb_chpoll */ 87da6c28aaSamw ddi_prop_op, /* cb_prop_op */ 88da6c28aaSamw NULL, /* cb_streamtab */ 89da6c28aaSamw D_MP, /* cb_flag */ 90da6c28aaSamw CB_REV, /* cb_rev */ 91da6c28aaSamw nodev, /* cb_aread */ 92da6c28aaSamw nodev, /* cb_awrite */ 93da6c28aaSamw }; 94da6c28aaSamw 95da6c28aaSamw static struct dev_ops devops = { 96da6c28aaSamw DEVO_REV, /* devo_rev */ 97da6c28aaSamw 0, /* devo_refcnt */ 98da6c28aaSamw smb_drv_getinfo, /* devo_getinfo */ 99da6c28aaSamw nulldev, /* devo_identify */ 100da6c28aaSamw nulldev, /* devo_probe */ 101da6c28aaSamw smb_drv_attach, /* devo_attach */ 102da6c28aaSamw smb_drv_detach, /* devo_detach */ 103da6c28aaSamw nodev, /* devo_reset */ 104da6c28aaSamw &cbops, /* devo_cb_ops */ 105da6c28aaSamw NULL, /* devo_bus_ops */ 106da6c28aaSamw NULL, /* devo_power */ 10719397407SSherry Moore ddi_quiesce_not_needed, /* devo_quiesce */ 108da6c28aaSamw }; 109da6c28aaSamw 110da6c28aaSamw static struct modldrv modldrv = { 111da6c28aaSamw &mod_driverops, /* drv_modops */ 11219397407SSherry Moore "CIFS Server Protocol", /* drv_linkinfo */ 113da6c28aaSamw &devops, 114da6c28aaSamw }; 115da6c28aaSamw 116da6c28aaSamw static struct modlinkage modlinkage = { 117da6c28aaSamw MODREV_1, /* revision of the module, must be: MODREV_1 */ 118da6c28aaSamw &modldrv, /* ptr to linkage structures */ 119da6c28aaSamw NULL, 120da6c28aaSamw }; 121da6c28aaSamw 122da6c28aaSamw static dev_info_t *smb_drv_dip = NULL; 123da6c28aaSamw 124da6c28aaSamw /* 125faa1795aSjb150015 * **************************************************************************** 126faa1795aSjb150015 * Module Interface 127faa1795aSjb150015 * **************************************************************************** 128da6c28aaSamw */ 129da6c28aaSamw 130da6c28aaSamw int 131da6c28aaSamw _init(void) 132da6c28aaSamw { 133*f9a15d2cSjose borrego int rc; 134*f9a15d2cSjose borrego 135*f9a15d2cSjose borrego rc = smb_server_svc_init(); 136*f9a15d2cSjose borrego if (rc == 0) { 137*f9a15d2cSjose borrego rc = mod_install(&modlinkage); 138*f9a15d2cSjose borrego if (rc != 0) 139*f9a15d2cSjose borrego (void) smb_server_svc_fini(); 140*f9a15d2cSjose borrego } 141*f9a15d2cSjose borrego return (rc); 142da6c28aaSamw } 143da6c28aaSamw 144da6c28aaSamw int 145da6c28aaSamw _info(struct modinfo *modinfop) 146da6c28aaSamw { 147da6c28aaSamw return (mod_info(&modlinkage, modinfop)); 148da6c28aaSamw } 149da6c28aaSamw 150da6c28aaSamw int 151da6c28aaSamw _fini(void) 152da6c28aaSamw { 153*f9a15d2cSjose borrego int rc; 154*f9a15d2cSjose borrego 155*f9a15d2cSjose borrego rc = mod_remove(&modlinkage); 156*f9a15d2cSjose borrego if (rc == 0) 157*f9a15d2cSjose borrego rc = smb_server_svc_fini(); 158*f9a15d2cSjose borrego return (rc); 159da6c28aaSamw } 160da6c28aaSamw 161faa1795aSjb150015 /* 162faa1795aSjb150015 * **************************************************************************** 163faa1795aSjb150015 * Pseudo Device Entry Points 164faa1795aSjb150015 * **************************************************************************** 165faa1795aSjb150015 */ 166faa1795aSjb150015 /* ARGSUSED */ 167faa1795aSjb150015 static int 168faa1795aSjb150015 smb_drv_open(dev_t *devp, int flag, int otyp, cred_t *credp) 169faa1795aSjb150015 { 170faa1795aSjb150015 /* 171faa1795aSjb150015 * Check caller's privileges. 172faa1795aSjb150015 */ 173faa1795aSjb150015 if (secpolicy_smb(credp) != 0) 174faa1795aSjb150015 return (EPERM); 175faa1795aSjb150015 176faa1795aSjb150015 /* 177faa1795aSjb150015 * Start SMB service state machine 178faa1795aSjb150015 */ 179faa1795aSjb150015 return (smb_server_create()); 180faa1795aSjb150015 } 181faa1795aSjb150015 182faa1795aSjb150015 /* ARGSUSED */ 183faa1795aSjb150015 static int 184faa1795aSjb150015 smb_drv_close(dev_t dev, int flag, int otyp, cred_t *credp) 185faa1795aSjb150015 { 186faa1795aSjb150015 return (smb_server_delete()); 187faa1795aSjb150015 } 188faa1795aSjb150015 189faa1795aSjb150015 /* ARGSUSED */ 190faa1795aSjb150015 static int 191faa1795aSjb150015 smb_drv_ioctl(dev_t drv, int cmd, intptr_t argp, int flag, cred_t *cred, 192faa1795aSjb150015 int *retval) 193faa1795aSjb150015 { 194faa1795aSjb150015 int rc = 0; 195faa1795aSjb150015 smb_io_t smb_io; 19694fff790SAlan Wright uint32_t crc1; 19794fff790SAlan Wright uint32_t crc2; 198faa1795aSjb150015 199faa1795aSjb150015 if (ddi_copyin((smb_io_t *)argp, &smb_io, sizeof (smb_io), flag) || 200faa1795aSjb150015 (smb_io.sio_version != SMB_IOC_VERSION)) 201faa1795aSjb150015 return (EFAULT); 202faa1795aSjb150015 20394fff790SAlan Wright crc1 = smb_io.sio_crc; 20494fff790SAlan Wright smb_io.sio_crc = 0; 20594fff790SAlan Wright crc2 = smb_crc_gen((uint8_t *)&smb_io, sizeof (smb_io_t)); 20694fff790SAlan Wright 20794fff790SAlan Wright if (crc1 != crc2) 20894fff790SAlan Wright return (EFAULT); 20994fff790SAlan Wright 210faa1795aSjb150015 switch (cmd) { 211faa1795aSjb150015 case SMB_IOC_CONFIG: 212faa1795aSjb150015 rc = smb_server_configure(&smb_io.sio_data.cfg); 213faa1795aSjb150015 break; 214faa1795aSjb150015 case SMB_IOC_START: 215faa1795aSjb150015 rc = smb_server_start(&smb_io.sio_data.start); 216faa1795aSjb150015 break; 217faa1795aSjb150015 case SMB_IOC_NBT_LISTEN: 218faa1795aSjb150015 rc = smb_server_nbt_listen(smb_io.sio_data.error); 219faa1795aSjb150015 break; 220faa1795aSjb150015 case SMB_IOC_TCP_LISTEN: 221faa1795aSjb150015 rc = smb_server_tcp_listen(smb_io.sio_data.error); 222faa1795aSjb150015 break; 223faa1795aSjb150015 case SMB_IOC_NBT_RECEIVE: 224faa1795aSjb150015 rc = smb_server_nbt_receive(); 225faa1795aSjb150015 break; 226faa1795aSjb150015 case SMB_IOC_TCP_RECEIVE: 227faa1795aSjb150015 rc = smb_server_tcp_receive(); 228faa1795aSjb150015 break; 229faa1795aSjb150015 case SMB_IOC_GMTOFF: 230faa1795aSjb150015 rc = smb_server_set_gmtoff(smb_io.sio_data.gmtoff); 231faa1795aSjb150015 break; 232faa1795aSjb150015 default: 233faa1795aSjb150015 rc = ENOTTY; 234faa1795aSjb150015 break; 235faa1795aSjb150015 } 236da6c28aaSamw 237da6c28aaSamw return (rc); 238da6c28aaSamw } 239da6c28aaSamw 240da6c28aaSamw /* 241faa1795aSjb150015 * **************************************************************************** 242faa1795aSjb150015 * Pseudo Device Operations 243faa1795aSjb150015 * **************************************************************************** 244da6c28aaSamw */ 245faa1795aSjb150015 static int 246faa1795aSjb150015 smb_drv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 247faa1795aSjb150015 { 248faa1795aSjb150015 if (cmd == DDI_ATTACH) { 249faa1795aSjb150015 /* we only allow instance 0 to attach */ 250faa1795aSjb150015 if (ddi_get_instance(dip) == 0) { 251faa1795aSjb150015 /* create the minor node */ 252faa1795aSjb150015 if (ddi_create_minor_node(dip, "smbsrv", S_IFCHR, 0, 253faa1795aSjb150015 DDI_PSEUDO, 0) == DDI_SUCCESS) { 254faa1795aSjb150015 smb_drv_dip = dip; 255faa1795aSjb150015 return (DDI_SUCCESS); 256faa1795aSjb150015 } else { 257faa1795aSjb150015 cmn_err(CE_WARN, "smb_drv_attach:" 258faa1795aSjb150015 " failed creating minor node"); 259faa1795aSjb150015 } 260faa1795aSjb150015 } 261faa1795aSjb150015 } 262faa1795aSjb150015 return (DDI_FAILURE); 263faa1795aSjb150015 } 264faa1795aSjb150015 265faa1795aSjb150015 static int 266faa1795aSjb150015 smb_drv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 267faa1795aSjb150015 { 268faa1795aSjb150015 if (cmd == DDI_DETACH) { 269faa1795aSjb150015 ASSERT(dip == smb_drv_dip); 270faa1795aSjb150015 ddi_remove_minor_node(dip, NULL); 271faa1795aSjb150015 smb_drv_dip = NULL; 272faa1795aSjb150015 return (DDI_SUCCESS); 273faa1795aSjb150015 } 274faa1795aSjb150015 return (DDI_FAILURE); 275faa1795aSjb150015 } 276da6c28aaSamw 277da6c28aaSamw /* ARGSUSED */ 278da6c28aaSamw static int 279da6c28aaSamw smb_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 280da6c28aaSamw { 281da6c28aaSamw ulong_t instance = getminor((dev_t)arg); 282da6c28aaSamw 283da6c28aaSamw switch (cmd) { 284da6c28aaSamw case DDI_INFO_DEVT2DEVINFO: 285da6c28aaSamw *result = smb_drv_dip; 286da6c28aaSamw return (DDI_SUCCESS); 287da6c28aaSamw 288da6c28aaSamw case DDI_INFO_DEVT2INSTANCE: 289da6c28aaSamw *result = (void *)instance; 290da6c28aaSamw return (DDI_SUCCESS); 291da6c28aaSamw 292da6c28aaSamw default: 293da6c28aaSamw break; 294da6c28aaSamw } 295da6c28aaSamw 296da6c28aaSamw return (DDI_FAILURE); 297da6c28aaSamw } 298