1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "@(#)smb_init.c 1.4 08/07/08 SMI" 27 28 #include <sys/types.h> 29 #include <sys/ddi.h> 30 #include <sys/modctl.h> 31 #include <sys/cred.h> 32 #include <sys/ioccom.h> 33 #include <sys/policy.h> 34 #include <smbsrv/smb_incl.h> 35 #include <smbsrv/mlsvc.h> 36 #include <smbsrv/smb_door_svc.h> 37 #include <smbsrv/smb_ioctl.h> 38 #include <smbsrv/smb_kproto.h> 39 40 static int smb_drv_open(dev_t *, int, int, cred_t *); 41 static int smb_drv_close(dev_t, int, int, cred_t *); 42 static int smb_drv_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 43 static int smb_drv_attach(dev_info_t *, ddi_attach_cmd_t); 44 static int smb_drv_detach(dev_info_t *, ddi_detach_cmd_t); 45 static int smb_drv_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 46 47 /* 48 * ***************************************************************************** 49 * ****************************** Global Variables ***************************** 50 * ***************************************************************************** 51 * 52 * These variables can only be changed through the /etc/system file. 53 */ 54 55 /* 56 * Maximum buffer size for NT: configurable based on the client environment. 57 * IR104720 Experiments with Windows 2000 indicate that we achieve better 58 * SmbWriteX performance with a buffer size of 64KB instead of the 37KB used 59 * with Windows NT4.0. Previous experiments with NT4.0 resulted in directory 60 * listing problems so this buffer size is configurable based on the end-user 61 * environment. When in doubt use 37KB. 62 */ 63 int smb_maxbufsize = SMB_NT_MAXBUF; 64 clock_t smb_oplock_timeout = OPLOCK_STD_TIMEOUT; 65 int smb_flush_required = 1; 66 int smb_dirsymlink_enable = 1; 67 int smb_announce_quota = 0; 68 int smb_sign_debug = 0; 69 70 /* 71 * ***************************************************************************** 72 * ********************** Static Variables / Module Linkage ******************** 73 * ***************************************************************************** 74 */ 75 76 static struct cb_ops cbops = { 77 smb_drv_open, /* cb_open */ 78 smb_drv_close, /* cb_close */ 79 nodev, /* cb_strategy */ 80 nodev, /* cb_print */ 81 nodev, /* cb_dump */ 82 nodev, /* cb_read */ 83 nodev, /* cb_write */ 84 smb_drv_ioctl, /* cb_ioctl */ 85 nodev, /* cb_devmap */ 86 nodev, /* cb_mmap */ 87 nodev, /* cb_segmap */ 88 nochpoll, /* cb_chpoll */ 89 ddi_prop_op, /* cb_prop_op */ 90 NULL, /* cb_streamtab */ 91 D_MP, /* cb_flag */ 92 CB_REV, /* cb_rev */ 93 nodev, /* cb_aread */ 94 nodev, /* cb_awrite */ 95 }; 96 97 static struct dev_ops devops = { 98 DEVO_REV, /* devo_rev */ 99 0, /* devo_refcnt */ 100 smb_drv_getinfo, /* devo_getinfo */ 101 nulldev, /* devo_identify */ 102 nulldev, /* devo_probe */ 103 smb_drv_attach, /* devo_attach */ 104 smb_drv_detach, /* devo_detach */ 105 nodev, /* devo_reset */ 106 &cbops, /* devo_cb_ops */ 107 NULL, /* devo_bus_ops */ 108 NULL, /* devo_power */ 109 }; 110 111 static struct modldrv modldrv = { 112 &mod_driverops, /* drv_modops */ 113 "CIFS Server Protocol 1.4", /* drv_linkinfo */ 114 &devops, 115 }; 116 117 static struct modlinkage modlinkage = { 118 MODREV_1, /* revision of the module, must be: MODREV_1 */ 119 &modldrv, /* ptr to linkage structures */ 120 NULL, 121 }; 122 123 static dev_info_t *smb_drv_dip = NULL; 124 125 /* 126 * **************************************************************************** 127 * Module Interface 128 * **************************************************************************** 129 */ 130 131 int 132 _init(void) 133 { 134 return (mod_install(&modlinkage)); 135 } 136 137 int 138 _info(struct modinfo *modinfop) 139 { 140 return (mod_info(&modlinkage, modinfop)); 141 } 142 143 int 144 _fini(void) 145 { 146 return (mod_remove(&modlinkage)); 147 } 148 149 /* 150 * **************************************************************************** 151 * Pseudo Device Entry Points 152 * **************************************************************************** 153 */ 154 /* ARGSUSED */ 155 static int 156 smb_drv_open(dev_t *devp, int flag, int otyp, cred_t *credp) 157 { 158 /* 159 * Check caller's privileges. 160 */ 161 if (secpolicy_smb(credp) != 0) 162 return (EPERM); 163 164 /* 165 * Start SMB service state machine 166 */ 167 return (smb_server_create()); 168 } 169 170 /* ARGSUSED */ 171 static int 172 smb_drv_close(dev_t dev, int flag, int otyp, cred_t *credp) 173 { 174 return (smb_server_delete()); 175 } 176 177 /* ARGSUSED */ 178 static int 179 smb_drv_ioctl(dev_t drv, int cmd, intptr_t argp, int flag, cred_t *cred, 180 int *retval) 181 { 182 int rc = 0; 183 smb_io_t smb_io; 184 185 if (ddi_copyin((smb_io_t *)argp, &smb_io, sizeof (smb_io), flag) || 186 (smb_io.sio_version != SMB_IOC_VERSION)) 187 return (EFAULT); 188 189 switch (cmd) { 190 case SMB_IOC_CONFIG: 191 rc = smb_server_configure(&smb_io.sio_data.cfg); 192 break; 193 case SMB_IOC_START: 194 rc = smb_server_start(&smb_io.sio_data.start); 195 break; 196 case SMB_IOC_NBT_LISTEN: 197 rc = smb_server_nbt_listen(smb_io.sio_data.error); 198 break; 199 case SMB_IOC_TCP_LISTEN: 200 rc = smb_server_tcp_listen(smb_io.sio_data.error); 201 break; 202 case SMB_IOC_NBT_RECEIVE: 203 rc = smb_server_nbt_receive(); 204 break; 205 case SMB_IOC_TCP_RECEIVE: 206 rc = smb_server_tcp_receive(); 207 break; 208 case SMB_IOC_GMTOFF: 209 rc = smb_server_set_gmtoff(smb_io.sio_data.gmtoff); 210 break; 211 default: 212 rc = ENOTTY; 213 break; 214 } 215 216 return (rc); 217 } 218 219 /* 220 * **************************************************************************** 221 * Pseudo Device Operations 222 * **************************************************************************** 223 */ 224 static int 225 smb_drv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 226 { 227 if (cmd == DDI_ATTACH) { 228 /* we only allow instance 0 to attach */ 229 if (ddi_get_instance(dip) == 0) { 230 /* create the minor node */ 231 if (ddi_create_minor_node(dip, "smbsrv", S_IFCHR, 0, 232 DDI_PSEUDO, 0) == DDI_SUCCESS) { 233 if (smb_server_svc_init() == 0) { 234 smb_drv_dip = dip; 235 return (DDI_SUCCESS); 236 } 237 ddi_remove_minor_node(dip, NULL); 238 } else { 239 cmn_err(CE_WARN, "smb_drv_attach:" 240 " failed creating minor node"); 241 } 242 } 243 } 244 return (DDI_FAILURE); 245 } 246 247 static int 248 smb_drv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 249 { 250 if (cmd == DDI_DETACH) { 251 ASSERT(dip == smb_drv_dip); 252 if (smb_server_svc_fini() == 0) { 253 ddi_remove_minor_node(dip, NULL); 254 smb_drv_dip = NULL; 255 return (DDI_SUCCESS); 256 } 257 } 258 return (DDI_FAILURE); 259 } 260 261 /* ARGSUSED */ 262 static int 263 smb_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 264 { 265 ulong_t instance = getminor((dev_t)arg); 266 267 switch (cmd) { 268 case DDI_INFO_DEVT2DEVINFO: 269 *result = smb_drv_dip; 270 return (DDI_SUCCESS); 271 272 case DDI_INFO_DEVT2INSTANCE: 273 *result = (void *)instance; 274 return (DDI_SUCCESS); 275 276 default: 277 break; 278 } 279 280 return (DDI_FAILURE); 281 } 282