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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 24 * Copyright 2017 Joyent, Inc. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/conf.h> 29 #include <sys/ddi.h> 30 #include <sys/modctl.h> 31 #include <sys/cred.h> 32 #include <sys/disp.h> 33 #include <sys/ioccom.h> 34 #include <sys/policy.h> 35 #include <sys/cmn_err.h> 36 #include <smbsrv/smb_kproto.h> 37 #include <smbsrv/smb_ioctl.h> 38 39 #ifdef _FAKE_KERNEL 40 #error "See libfksmbsrv" 41 #endif /* _FAKE_KERNEL */ 42 43 static int smb_drv_open(dev_t *, int, int, cred_t *); 44 static int smb_drv_close(dev_t, int, int, cred_t *); 45 static int smb_drv_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 46 static int smb_drv_attach(dev_info_t *, ddi_attach_cmd_t); 47 static int smb_drv_detach(dev_info_t *, ddi_detach_cmd_t); 48 static int smb_drv_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 49 50 /* 51 * ***************************************************************************** 52 * ****************************** Global Variables ***************************** 53 * ***************************************************************************** 54 * 55 * These variables can only be changed through the /etc/system file. 56 */ 57 58 /* 59 * Maximum buffer size for NT: configurable based on the client environment. 60 * IR104720 Experiments with Windows 2000 indicate that we achieve better 61 * SmbWriteX performance with a buffer size of 64KB instead of the 37KB used 62 * with Windows NT4.0. Previous experiments with NT4.0 resulted in directory 63 * listing problems so this buffer size is configurable based on the end-user 64 * environment. When in doubt use 37KB. 65 */ 66 int smb_maxbufsize = SMB_NT_MAXBUF; 67 int smb_oplock_levelII = 1; 68 int smb_oplock_timeout = OPLOCK_STD_TIMEOUT; 69 int smb_oplock_min_timeout = OPLOCK_MIN_TIMEOUT; 70 int smb_flush_required = 1; 71 int smb_dirsymlink_enable = 1; 72 int smb_sign_debug = 0; 73 int smb_shortnames = 1; 74 uint_t smb_audit_flags = 75 #ifdef DEBUG 76 SMB_AUDIT_NODE; 77 #else 78 0; 79 #endif 80 81 /* 82 * Maximum number of simultaneous authentication, share mapping, pipe open 83 * requests to be processed. 84 */ 85 int smb_ssetup_threshold = SMB_AUTHSVC_MAXTHREAD; 86 int smb_tcon_threshold = 1024; 87 int smb_opipe_threshold = 1024; 88 89 /* 90 * Number of milliseconds that a request will be stalled if it comes in after 91 * the maximum number of inflight operations are being proccessed. 92 */ 93 int smb_ssetup_timeout = (30 * 1000); 94 int smb_tcon_timeout = (30 * 1000); 95 int smb_opipe_timeout = (30 * 1000); 96 97 /* 98 * Thread priorities used in smbsrv. Our threads spend most of their time 99 * blocked on various conditions. However, if the system gets heavy load, 100 * the scheduler has to choose an order to run these. We want the order: 101 * (a) timers, (b) notifications, (c) workers, (d) receivers (and etc.) 102 * where notifications are oplock and change notify work. Aside from this 103 * relative ordering, smbsrv threads should run with a priority close to 104 * that of normal user-space threads (thus minclsyspri below), just like 105 * NFS and other "file service" kinds of processing. 106 */ 107 int smbsrv_base_pri = MINCLSYSPRI; 108 int smbsrv_listen_pri = MINCLSYSPRI; 109 int smbsrv_receive_pri = MINCLSYSPRI; 110 int smbsrv_worker_pri = MINCLSYSPRI + 1; 111 int smbsrv_notify_pri = MINCLSYSPRI + 2; 112 int smbsrv_timer_pri = MINCLSYSPRI + 5; 113 114 115 /* 116 * ***************************************************************************** 117 * ********************** Static Variables / Module Linkage ******************** 118 * ***************************************************************************** 119 */ 120 121 static struct cb_ops cbops = { 122 smb_drv_open, /* cb_open */ 123 smb_drv_close, /* cb_close */ 124 nodev, /* cb_strategy */ 125 nodev, /* cb_print */ 126 nodev, /* cb_dump */ 127 nodev, /* cb_read */ 128 nodev, /* cb_write */ 129 smb_drv_ioctl, /* cb_ioctl */ 130 nodev, /* cb_devmap */ 131 nodev, /* cb_mmap */ 132 nodev, /* cb_segmap */ 133 nochpoll, /* cb_chpoll */ 134 ddi_prop_op, /* cb_prop_op */ 135 NULL, /* cb_streamtab */ 136 D_MP, /* cb_flag */ 137 CB_REV, /* cb_rev */ 138 nodev, /* cb_aread */ 139 nodev, /* cb_awrite */ 140 }; 141 142 static struct dev_ops devops = { 143 DEVO_REV, /* devo_rev */ 144 0, /* devo_refcnt */ 145 smb_drv_getinfo, /* devo_getinfo */ 146 nulldev, /* devo_identify */ 147 nulldev, /* devo_probe */ 148 smb_drv_attach, /* devo_attach */ 149 smb_drv_detach, /* devo_detach */ 150 nodev, /* devo_reset */ 151 &cbops, /* devo_cb_ops */ 152 NULL, /* devo_bus_ops */ 153 NULL, /* devo_power */ 154 ddi_quiesce_not_needed, /* devo_quiesce */ 155 }; 156 157 static struct modldrv modldrv = { 158 &mod_driverops, /* drv_modops */ 159 "CIFS Server Protocol", /* drv_linkinfo */ 160 &devops, 161 }; 162 163 static struct modlinkage modlinkage = { 164 MODREV_1, /* revision of the module, must be: MODREV_1 */ 165 &modldrv, /* ptr to linkage structures */ 166 NULL, 167 }; 168 169 static dev_info_t *smb_drv_dip = NULL; 170 171 /* 172 * **************************************************************************** 173 * Module Interface 174 * **************************************************************************** 175 */ 176 177 int 178 _init(void) 179 { 180 int rc; 181 182 if ((rc = smb_server_g_init()) != 0) { 183 return (rc); 184 } 185 186 if ((rc = mod_install(&modlinkage)) != 0) { 187 smb_server_g_fini(); 188 } 189 190 return (rc); 191 } 192 193 int 194 _info(struct modinfo *modinfop) 195 { 196 return (mod_info(&modlinkage, modinfop)); 197 } 198 199 int 200 _fini(void) 201 { 202 int rc; 203 204 if (smb_server_get_count() != 0) 205 return (EBUSY); 206 207 if ((rc = mod_remove(&modlinkage)) == 0) { 208 smb_server_g_fini(); 209 } 210 211 return (rc); 212 } 213 214 /* 215 * **************************************************************************** 216 * Pseudo Device Entry Points 217 * **************************************************************************** 218 */ 219 /* ARGSUSED */ 220 static int 221 smb_drv_open(dev_t *devp, int flag, int otyp, cred_t *cr) 222 { 223 zoneid_t zid; 224 225 /* 226 * Check caller's privileges. 227 */ 228 if (secpolicy_smb(cr) != 0) 229 return (EPERM); 230 231 /* 232 * We need a unique minor per zone otherwise an smbd in any other 233 * zone will keep this minor open and we won't get a close call. 234 * The zone ID is good enough as a minor number. 235 */ 236 zid = crgetzoneid(cr); 237 if (zid < 0) 238 return (ENODEV); 239 *devp = makedevice(getmajor(*devp), zid); 240 241 /* 242 * Start SMB service state machine 243 */ 244 return (smb_server_create()); 245 } 246 247 /* ARGSUSED */ 248 static int 249 smb_drv_close(dev_t dev, int flag, int otyp, cred_t *credp) 250 { 251 return (smb_server_delete()); 252 } 253 254 /* ARGSUSED */ 255 static int 256 smb_drv_ioctl(dev_t drv, int cmd, intptr_t argp, int flags, cred_t *cred, 257 int *retval) 258 { 259 smb_ioc_t *ioc; 260 smb_ioc_header_t ioc_hdr; 261 uint32_t crc; 262 boolean_t copyout = B_FALSE; 263 int rc = 0; 264 size_t alloclen; 265 266 if (ddi_copyin((void *)argp, &ioc_hdr, sizeof (ioc_hdr), flags)) 267 return (EFAULT); 268 269 /* 270 * Check version and length. 271 * 272 * Note that some ioctls (i.e. SMB_IOC_SVCENUM) have payload 273 * data after the ioctl struct, in which case they specify a 274 * length much larger than sizeof smb_ioc_t. The theoretical 275 * largest ioctl data is therefore the size of the union plus 276 * the max size of the payload (which is SMB_IOC_DATA_SIZE). 277 */ 278 if (ioc_hdr.version != SMB_IOC_VERSION || 279 ioc_hdr.len < sizeof (ioc_hdr) || 280 ioc_hdr.len > (sizeof (*ioc) + SMB_IOC_DATA_SIZE)) 281 return (EINVAL); 282 283 crc = ioc_hdr.crc; 284 ioc_hdr.crc = 0; 285 if (smb_crc_gen((uint8_t *)&ioc_hdr, sizeof (ioc_hdr)) != crc) 286 return (EINVAL); 287 288 /* 289 * Note that smb_ioc_t is a union, and callers set ioc_hdr.len 290 * to the size of the actual union arm. If some caller were to 291 * set that size too small, we could end up passing under-sized 292 * memory to one of the type-specific handler functions. Avoid 293 * that problem by allocating at least the size of the union, 294 * (zeroed out) and then copy in the caller specified length. 295 */ 296 alloclen = MAX(ioc_hdr.len, sizeof (*ioc)); 297 ioc = kmem_zalloc(alloclen, KM_SLEEP); 298 if (ddi_copyin((void *)argp, ioc, ioc_hdr.len, flags)) { 299 kmem_free(ioc, alloclen); 300 return (EFAULT); 301 } 302 303 switch (cmd) { 304 case SMB_IOC_CONFIG: 305 rc = smb_server_configure(&ioc->ioc_cfg); 306 break; 307 case SMB_IOC_START: 308 rc = smb_server_start(&ioc->ioc_start); 309 break; 310 case SMB_IOC_STOP: 311 rc = smb_server_stop(); 312 break; 313 case SMB_IOC_EVENT: 314 rc = smb_server_notify_event(&ioc->ioc_event); 315 break; 316 case SMB_IOC_GMTOFF: 317 rc = smb_server_set_gmtoff(&ioc->ioc_gmt); 318 break; 319 case SMB_IOC_SHARE: 320 rc = smb_kshare_export_list(&ioc->ioc_share); 321 break; 322 case SMB_IOC_UNSHARE: 323 rc = smb_kshare_unexport_list(&ioc->ioc_share); 324 break; 325 case SMB_IOC_SHAREINFO: 326 rc = smb_kshare_info(&ioc->ioc_shareinfo); 327 copyout = B_TRUE; 328 break; 329 case SMB_IOC_NUMOPEN: 330 rc = smb_server_numopen(&ioc->ioc_opennum); 331 copyout = B_TRUE; 332 break; 333 case SMB_IOC_SVCENUM: 334 rc = smb_server_enum(&ioc->ioc_svcenum); 335 copyout = B_TRUE; 336 break; 337 case SMB_IOC_SESSION_CLOSE: 338 rc = smb_server_session_close(&ioc->ioc_session); 339 break; 340 case SMB_IOC_FILE_CLOSE: 341 rc = smb_server_file_close(&ioc->ioc_fileid); 342 break; 343 case SMB_IOC_SPOOLDOC: 344 rc = smb_server_spooldoc(&ioc->ioc_spooldoc); 345 copyout = B_TRUE; 346 break; 347 default: 348 rc = ENOTTY; 349 break; 350 } 351 if ((rc == 0) && copyout) { 352 if (ddi_copyout(ioc, (void *)argp, ioc_hdr.len, flags)) 353 rc = EFAULT; 354 } 355 kmem_free(ioc, alloclen); 356 return (rc); 357 } 358 359 /* 360 * **************************************************************************** 361 * Pseudo Device Operations 362 * **************************************************************************** 363 */ 364 static int 365 smb_drv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 366 { 367 if (cmd == DDI_ATTACH) { 368 /* we only allow instance 0 to attach */ 369 if (ddi_get_instance(dip) == 0) { 370 /* create the minor node */ 371 if (ddi_create_minor_node(dip, "smbsrv", S_IFCHR, 0, 372 DDI_PSEUDO, 0) == DDI_SUCCESS) { 373 smb_drv_dip = dip; 374 return (DDI_SUCCESS); 375 } else { 376 cmn_err(CE_WARN, "smb_drv_attach:" 377 " failed creating minor node"); 378 } 379 } 380 } 381 return (DDI_FAILURE); 382 } 383 384 static int 385 smb_drv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 386 { 387 if (cmd == DDI_DETACH) { 388 ASSERT(dip == smb_drv_dip); 389 ddi_remove_minor_node(dip, NULL); 390 smb_drv_dip = NULL; 391 return (DDI_SUCCESS); 392 } 393 return (DDI_FAILURE); 394 } 395 396 /* ARGSUSED */ 397 static int 398 smb_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 399 { 400 ulong_t instance = getminor((dev_t)arg); 401 402 switch (cmd) { 403 case DDI_INFO_DEVT2DEVINFO: 404 *result = smb_drv_dip; 405 return (DDI_SUCCESS); 406 407 case DDI_INFO_DEVT2INSTANCE: 408 *result = (void *)instance; 409 return (DDI_SUCCESS); 410 411 default: 412 break; 413 } 414 415 return (DDI_FAILURE); 416 } 417