15331Samw /* 25331Samw * CDDL HEADER START 35331Samw * 45331Samw * The contents of this file are subject to the terms of the 55331Samw * Common Development and Distribution License (the "License"). 65331Samw * You may not use this file except in compliance with the License. 75331Samw * 85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95331Samw * or http://www.opensolaris.org/os/licensing. 105331Samw * See the License for the specific language governing permissions 115331Samw * and limitations under the License. 125331Samw * 135331Samw * When distributing Covered Code, include this CDDL HEADER in each 145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155331Samw * If applicable, add the following below this CDDL HEADER, with the 165331Samw * fields enclosed by brackets "[]" replaced with your own identifying 175331Samw * information: Portions Copyright [yyyy] [name of copyright owner] 185331Samw * 195331Samw * CDDL HEADER END 205331Samw */ 215331Samw /* 22*6139Sjb150015 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 235331Samw * Use is subject to license terms. 245331Samw */ 255331Samw 265331Samw #pragma ident "%Z%%M% %I% %E% SMI" 275331Samw 285331Samw #include <sys/types.h> 295331Samw #include <sys/ddi.h> 305331Samw #include <sys/modctl.h> 315331Samw #include <sys/cred.h> 325331Samw #include <sys/ioccom.h> 335331Samw #include <sys/policy.h> 345331Samw #include <smbsrv/smb_incl.h> 355331Samw #include <smbsrv/mlsvc.h> 365331Samw #include <smbsrv/smb_door_svc.h> 375331Samw #include <smbsrv/smb_ioctl.h> 385331Samw #include <smbsrv/smb_kproto.h> 39*6139Sjb150015 40*6139Sjb150015 static int smb_drv_open(dev_t *, int, int, cred_t *); 41*6139Sjb150015 static int smb_drv_close(dev_t, int, int, cred_t *); 42*6139Sjb150015 static int smb_drv_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 435331Samw static int smb_drv_attach(dev_info_t *, ddi_attach_cmd_t); 445331Samw static int smb_drv_detach(dev_info_t *, ddi_detach_cmd_t); 455331Samw static int smb_drv_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 46*6139Sjb150015 47*6139Sjb150015 /* 48*6139Sjb150015 * ***************************************************************************** 49*6139Sjb150015 * ****************************** Global Variables ***************************** 50*6139Sjb150015 * ***************************************************************************** 51*6139Sjb150015 * 52*6139Sjb150015 * These variables can only be changed through the /etc/system file. 53*6139Sjb150015 */ 545331Samw 555331Samw /* 56*6139Sjb150015 * Maximum buffer size for NT: configurable based on the client environment. 57*6139Sjb150015 * IR104720 Experiments with Windows 2000 indicate that we achieve better 58*6139Sjb150015 * SmbWriteX performance with a buffer size of 64KB instead of the 37KB used 59*6139Sjb150015 * with Windows NT4.0. Previous experiments with NT4.0 resulted in directory 60*6139Sjb150015 * listing problems so this buffer size is configurable based on the end-user 61*6139Sjb150015 * environment. When in doubt use 37KB. 625331Samw */ 63*6139Sjb150015 int smb_maxbufsize = SMB_NT_MAXBUF; 64*6139Sjb150015 clock_t smb_oplock_timeout = OPLOCK_STD_TIMEOUT; 65*6139Sjb150015 int smb_flush_required = 1; 66*6139Sjb150015 int smb_dirsymlink_enable = 1; 67*6139Sjb150015 int smb_announce_quota = 0; 68*6139Sjb150015 69*6139Sjb150015 /* 70*6139Sjb150015 * ***************************************************************************** 71*6139Sjb150015 * ********************** Static Variables / Module Linkage ******************** 72*6139Sjb150015 * ***************************************************************************** 73*6139Sjb150015 */ 74*6139Sjb150015 755331Samw static struct cb_ops cbops = { 765331Samw smb_drv_open, /* cb_open */ 775331Samw smb_drv_close, /* cb_close */ 785331Samw nodev, /* cb_strategy */ 795331Samw nodev, /* cb_print */ 805331Samw nodev, /* cb_dump */ 815331Samw nodev, /* cb_read */ 825331Samw nodev, /* cb_write */ 835331Samw smb_drv_ioctl, /* cb_ioctl */ 845331Samw nodev, /* cb_devmap */ 855331Samw nodev, /* cb_mmap */ 865331Samw nodev, /* cb_segmap */ 875331Samw nochpoll, /* cb_chpoll */ 885331Samw ddi_prop_op, /* cb_prop_op */ 895331Samw NULL, /* cb_streamtab */ 905331Samw D_MP, /* cb_flag */ 915331Samw CB_REV, /* cb_rev */ 925331Samw nodev, /* cb_aread */ 935331Samw nodev, /* cb_awrite */ 945331Samw }; 955331Samw 965331Samw static struct dev_ops devops = { 975331Samw DEVO_REV, /* devo_rev */ 985331Samw 0, /* devo_refcnt */ 995331Samw smb_drv_getinfo, /* devo_getinfo */ 1005331Samw nulldev, /* devo_identify */ 1015331Samw nulldev, /* devo_probe */ 1025331Samw smb_drv_attach, /* devo_attach */ 1035331Samw smb_drv_detach, /* devo_detach */ 1045331Samw nodev, /* devo_reset */ 1055331Samw &cbops, /* devo_cb_ops */ 1065331Samw NULL, /* devo_bus_ops */ 1075331Samw NULL, /* devo_power */ 1085331Samw }; 1095331Samw 1105331Samw static struct modldrv modldrv = { 1115331Samw &mod_driverops, /* drv_modops */ 1125331Samw "CIFS Server Protocol %I%", /* drv_linkinfo */ 1135331Samw &devops, 1145331Samw }; 1155331Samw 1165331Samw static struct modlinkage modlinkage = { 1175331Samw MODREV_1, /* revision of the module, must be: MODREV_1 */ 1185331Samw &modldrv, /* ptr to linkage structures */ 1195331Samw NULL, 1205331Samw }; 1215331Samw 1225331Samw static dev_info_t *smb_drv_dip = NULL; 1235331Samw 1245331Samw /* 125*6139Sjb150015 * **************************************************************************** 126*6139Sjb150015 * Module Interface 127*6139Sjb150015 * **************************************************************************** 1285331Samw */ 1295331Samw 1305331Samw int 1315331Samw _init(void) 1325331Samw { 133*6139Sjb150015 return (mod_install(&modlinkage)); 1345331Samw } 1355331Samw 1365331Samw int 1375331Samw _info(struct modinfo *modinfop) 1385331Samw { 1395331Samw return (mod_info(&modlinkage, modinfop)); 1405331Samw } 1415331Samw 1425331Samw int 1435331Samw _fini(void) 1445331Samw { 145*6139Sjb150015 return (mod_remove(&modlinkage)); 146*6139Sjb150015 } 147*6139Sjb150015 148*6139Sjb150015 /* 149*6139Sjb150015 * **************************************************************************** 150*6139Sjb150015 * Pseudo Device Entry Points 151*6139Sjb150015 * **************************************************************************** 152*6139Sjb150015 */ 153*6139Sjb150015 /* ARGSUSED */ 154*6139Sjb150015 static int 155*6139Sjb150015 smb_drv_open(dev_t *devp, int flag, int otyp, cred_t *credp) 156*6139Sjb150015 { 157*6139Sjb150015 /* 158*6139Sjb150015 * Check caller's privileges. 159*6139Sjb150015 */ 160*6139Sjb150015 if (secpolicy_smb(credp) != 0) 161*6139Sjb150015 return (EPERM); 162*6139Sjb150015 163*6139Sjb150015 /* 164*6139Sjb150015 * Start SMB service state machine 165*6139Sjb150015 */ 166*6139Sjb150015 return (smb_server_create()); 167*6139Sjb150015 } 168*6139Sjb150015 169*6139Sjb150015 /* ARGSUSED */ 170*6139Sjb150015 static int 171*6139Sjb150015 smb_drv_close(dev_t dev, int flag, int otyp, cred_t *credp) 172*6139Sjb150015 { 173*6139Sjb150015 return (smb_server_delete()); 174*6139Sjb150015 } 1755331Samw 176*6139Sjb150015 /* ARGSUSED */ 177*6139Sjb150015 static int 178*6139Sjb150015 smb_drv_ioctl(dev_t drv, int cmd, intptr_t argp, int flag, cred_t *cred, 179*6139Sjb150015 int *retval) 180*6139Sjb150015 { 181*6139Sjb150015 int rc = 0; 182*6139Sjb150015 smb_io_t smb_io; 183*6139Sjb150015 184*6139Sjb150015 if (ddi_copyin((smb_io_t *)argp, &smb_io, sizeof (smb_io), flag) || 185*6139Sjb150015 (smb_io.sio_version != SMB_IOC_VERSION)) 186*6139Sjb150015 return (EFAULT); 187*6139Sjb150015 188*6139Sjb150015 switch (cmd) { 189*6139Sjb150015 case SMB_IOC_CONFIG: 190*6139Sjb150015 rc = smb_server_configure(&smb_io.sio_data.cfg); 191*6139Sjb150015 break; 192*6139Sjb150015 case SMB_IOC_START: 193*6139Sjb150015 rc = smb_server_start(&smb_io.sio_data.start); 194*6139Sjb150015 break; 195*6139Sjb150015 case SMB_IOC_NBT_LISTEN: 196*6139Sjb150015 rc = smb_server_nbt_listen(smb_io.sio_data.error); 197*6139Sjb150015 break; 198*6139Sjb150015 case SMB_IOC_TCP_LISTEN: 199*6139Sjb150015 rc = smb_server_tcp_listen(smb_io.sio_data.error); 200*6139Sjb150015 break; 201*6139Sjb150015 case SMB_IOC_NBT_RECEIVE: 202*6139Sjb150015 rc = smb_server_nbt_receive(); 203*6139Sjb150015 break; 204*6139Sjb150015 case SMB_IOC_TCP_RECEIVE: 205*6139Sjb150015 rc = smb_server_tcp_receive(); 206*6139Sjb150015 break; 207*6139Sjb150015 case SMB_IOC_GMTOFF: 208*6139Sjb150015 rc = smb_server_set_gmtoff(smb_io.sio_data.gmtoff); 209*6139Sjb150015 break; 210*6139Sjb150015 default: 211*6139Sjb150015 rc = ENOTTY; 212*6139Sjb150015 break; 2135331Samw } 2145331Samw 2155331Samw return (rc); 2165331Samw } 2175331Samw 2185331Samw /* 219*6139Sjb150015 * **************************************************************************** 220*6139Sjb150015 * Pseudo Device Operations 221*6139Sjb150015 * **************************************************************************** 2225331Samw */ 223*6139Sjb150015 static int 224*6139Sjb150015 smb_drv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 225*6139Sjb150015 { 226*6139Sjb150015 if (cmd == DDI_ATTACH) { 227*6139Sjb150015 /* we only allow instance 0 to attach */ 228*6139Sjb150015 if (ddi_get_instance(dip) == 0) { 229*6139Sjb150015 /* create the minor node */ 230*6139Sjb150015 if (ddi_create_minor_node(dip, "smbsrv", S_IFCHR, 0, 231*6139Sjb150015 DDI_PSEUDO, 0) == DDI_SUCCESS) { 232*6139Sjb150015 if (smb_server_svc_init() == 0) { 233*6139Sjb150015 smb_drv_dip = dip; 234*6139Sjb150015 return (DDI_SUCCESS); 235*6139Sjb150015 } 236*6139Sjb150015 ddi_remove_minor_node(dip, NULL); 237*6139Sjb150015 } else { 238*6139Sjb150015 cmn_err(CE_WARN, "smb_drv_attach:" 239*6139Sjb150015 " failed creating minor node"); 240*6139Sjb150015 } 241*6139Sjb150015 } 242*6139Sjb150015 } 243*6139Sjb150015 return (DDI_FAILURE); 244*6139Sjb150015 } 245*6139Sjb150015 246*6139Sjb150015 static int 247*6139Sjb150015 smb_drv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 248*6139Sjb150015 { 249*6139Sjb150015 if (cmd == DDI_DETACH) { 250*6139Sjb150015 ASSERT(dip == smb_drv_dip); 251*6139Sjb150015 if (smb_server_svc_fini() == 0) { 252*6139Sjb150015 ddi_remove_minor_node(dip, NULL); 253*6139Sjb150015 smb_drv_dip = NULL; 254*6139Sjb150015 return (DDI_SUCCESS); 255*6139Sjb150015 } 256*6139Sjb150015 } 257*6139Sjb150015 return (DDI_FAILURE); 258*6139Sjb150015 } 2595331Samw 2605331Samw /* ARGSUSED */ 2615331Samw static int 2625331Samw smb_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 2635331Samw { 2645331Samw ulong_t instance = getminor((dev_t)arg); 2655331Samw 2665331Samw switch (cmd) { 2675331Samw case DDI_INFO_DEVT2DEVINFO: 2685331Samw *result = smb_drv_dip; 2695331Samw return (DDI_SUCCESS); 2705331Samw 2715331Samw case DDI_INFO_DEVT2INSTANCE: 2725331Samw *result = (void *)instance; 2735331Samw return (DDI_SUCCESS); 2745331Samw 2755331Samw default: 2765331Samw break; 2775331Samw } 2785331Samw 2795331Samw return (DDI_FAILURE); 2805331Samw } 281