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 /* 2212508Samw@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 235331Samw */ 245331Samw 255331Samw #include <sys/types.h> 265331Samw #include <sys/ddi.h> 275331Samw #include <sys/modctl.h> 285331Samw #include <sys/cred.h> 295331Samw #include <sys/ioccom.h> 305331Samw #include <sys/policy.h> 318167Samw@Sun.COM #include <sys/cmn_err.h> 3210966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h> 335331Samw #include <smbsrv/smb_ioctl.h> 346139Sjb150015 356139Sjb150015 static int smb_drv_open(dev_t *, int, int, cred_t *); 366139Sjb150015 static int smb_drv_close(dev_t, int, int, cred_t *); 376139Sjb150015 static int smb_drv_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 385331Samw static int smb_drv_attach(dev_info_t *, ddi_attach_cmd_t); 395331Samw static int smb_drv_detach(dev_info_t *, ddi_detach_cmd_t); 405331Samw static int smb_drv_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 416139Sjb150015 426139Sjb150015 /* 436139Sjb150015 * ***************************************************************************** 446139Sjb150015 * ****************************** Global Variables ***************************** 456139Sjb150015 * ***************************************************************************** 466139Sjb150015 * 476139Sjb150015 * These variables can only be changed through the /etc/system file. 486139Sjb150015 */ 495331Samw 505331Samw /* 516139Sjb150015 * Maximum buffer size for NT: configurable based on the client environment. 526139Sjb150015 * IR104720 Experiments with Windows 2000 indicate that we achieve better 536139Sjb150015 * SmbWriteX performance with a buffer size of 64KB instead of the 37KB used 546139Sjb150015 * with Windows NT4.0. Previous experiments with NT4.0 resulted in directory 556139Sjb150015 * listing problems so this buffer size is configurable based on the end-user 566139Sjb150015 * environment. When in doubt use 37KB. 57*12890SJoyce.McIntosh@Sun.COM * 58*12890SJoyce.McIntosh@Sun.COM * smb_raw_mode: read_raw and write_raw supported (1) or NOT supported (0). 595331Samw */ 606139Sjb150015 int smb_maxbufsize = SMB_NT_MAXBUF; 61*12890SJoyce.McIntosh@Sun.COM int smb_oplock_levelII = 1; 628934SJose.Borrego@Sun.COM int smb_oplock_timeout = OPLOCK_STD_TIMEOUT; 63*12890SJoyce.McIntosh@Sun.COM int smb_oplock_min_timeout = OPLOCK_MIN_TIMEOUT; 646139Sjb150015 int smb_flush_required = 1; 656139Sjb150015 int smb_dirsymlink_enable = 1; 667348SJose.Borrego@Sun.COM int smb_sign_debug = 0; 67*12890SJoyce.McIntosh@Sun.COM int smb_raw_mode = 1; 68*12890SJoyce.McIntosh@Sun.COM int smb_shortnames = 1; 698934SJose.Borrego@Sun.COM uint_t smb_audit_flags = 708934SJose.Borrego@Sun.COM #ifdef DEBUG 718934SJose.Borrego@Sun.COM SMB_AUDIT_NODE; 728934SJose.Borrego@Sun.COM #else 738934SJose.Borrego@Sun.COM 0; 748934SJose.Borrego@Sun.COM #endif 756139Sjb150015 766139Sjb150015 /* 77*12890SJoyce.McIntosh@Sun.COM * Maximum number of simultaneous authentication, share mapping, pipe open 78*12890SJoyce.McIntosh@Sun.COM * requests to be processed. 79*12890SJoyce.McIntosh@Sun.COM */ 80*12890SJoyce.McIntosh@Sun.COM int smb_ssetup_threshold = 256; 81*12890SJoyce.McIntosh@Sun.COM int smb_tcon_threshold = 1024; 82*12890SJoyce.McIntosh@Sun.COM int smb_opipe_threshold = 1024; 83*12890SJoyce.McIntosh@Sun.COM 84*12890SJoyce.McIntosh@Sun.COM /* 85*12890SJoyce.McIntosh@Sun.COM * Number of milliseconds that a request will be stalled if it comes in after 86*12890SJoyce.McIntosh@Sun.COM * the maximum number of inflight operations are being proccessed. 87*12890SJoyce.McIntosh@Sun.COM */ 88*12890SJoyce.McIntosh@Sun.COM int smb_ssetup_timeout = (30 * 1000); 89*12890SJoyce.McIntosh@Sun.COM int smb_tcon_timeout = (30 * 1000); 90*12890SJoyce.McIntosh@Sun.COM int smb_opipe_timeout = (30 * 1000); 91*12890SJoyce.McIntosh@Sun.COM 92*12890SJoyce.McIntosh@Sun.COM int smb_threshold_debug = 0; 93*12890SJoyce.McIntosh@Sun.COM 94*12890SJoyce.McIntosh@Sun.COM 95*12890SJoyce.McIntosh@Sun.COM /* 966139Sjb150015 * ***************************************************************************** 976139Sjb150015 * ********************** Static Variables / Module Linkage ******************** 986139Sjb150015 * ***************************************************************************** 996139Sjb150015 */ 1006139Sjb150015 1015331Samw static struct cb_ops cbops = { 1025331Samw smb_drv_open, /* cb_open */ 1035331Samw smb_drv_close, /* cb_close */ 1045331Samw nodev, /* cb_strategy */ 1055331Samw nodev, /* cb_print */ 1065331Samw nodev, /* cb_dump */ 1075331Samw nodev, /* cb_read */ 1085331Samw nodev, /* cb_write */ 1095331Samw smb_drv_ioctl, /* cb_ioctl */ 1105331Samw nodev, /* cb_devmap */ 1115331Samw nodev, /* cb_mmap */ 1125331Samw nodev, /* cb_segmap */ 1135331Samw nochpoll, /* cb_chpoll */ 1145331Samw ddi_prop_op, /* cb_prop_op */ 1155331Samw NULL, /* cb_streamtab */ 1165331Samw D_MP, /* cb_flag */ 1175331Samw CB_REV, /* cb_rev */ 1185331Samw nodev, /* cb_aread */ 1195331Samw nodev, /* cb_awrite */ 1205331Samw }; 1215331Samw 1225331Samw static struct dev_ops devops = { 1235331Samw DEVO_REV, /* devo_rev */ 1245331Samw 0, /* devo_refcnt */ 1255331Samw smb_drv_getinfo, /* devo_getinfo */ 1265331Samw nulldev, /* devo_identify */ 1275331Samw nulldev, /* devo_probe */ 1285331Samw smb_drv_attach, /* devo_attach */ 1295331Samw smb_drv_detach, /* devo_detach */ 1305331Samw nodev, /* devo_reset */ 1315331Samw &cbops, /* devo_cb_ops */ 1325331Samw NULL, /* devo_bus_ops */ 1335331Samw NULL, /* devo_power */ 1347656SSherry.Moore@Sun.COM ddi_quiesce_not_needed, /* devo_quiesce */ 1355331Samw }; 1365331Samw 1375331Samw static struct modldrv modldrv = { 1385331Samw &mod_driverops, /* drv_modops */ 1397656SSherry.Moore@Sun.COM "CIFS Server Protocol", /* drv_linkinfo */ 1405331Samw &devops, 1415331Samw }; 1425331Samw 1435331Samw static struct modlinkage modlinkage = { 1445331Samw MODREV_1, /* revision of the module, must be: MODREV_1 */ 1455331Samw &modldrv, /* ptr to linkage structures */ 1465331Samw NULL, 1475331Samw }; 1485331Samw 1495331Samw static dev_info_t *smb_drv_dip = NULL; 1505331Samw 1515331Samw /* 1526139Sjb150015 * **************************************************************************** 1536139Sjb150015 * Module Interface 1546139Sjb150015 * **************************************************************************** 1555331Samw */ 1565331Samw 1575331Samw int 1585331Samw _init(void) 1595331Samw { 16012508Samw@Sun.COM int rc; 16112508Samw@Sun.COM 16212508Samw@Sun.COM if ((rc = smb_kshare_init()) != 0) 16312508Samw@Sun.COM return (rc); 1648473SJose.Borrego@Sun.COM 16512508Samw@Sun.COM if ((rc = smb_server_svc_init()) != 0) { 16612508Samw@Sun.COM smb_kshare_fini(); 16712508Samw@Sun.COM return (rc); 1688473SJose.Borrego@Sun.COM } 16912508Samw@Sun.COM 17012508Samw@Sun.COM if ((rc = mod_install(&modlinkage)) != 0) { 17112508Samw@Sun.COM smb_kshare_fini(); 17212508Samw@Sun.COM (void) smb_server_svc_fini(); 17312508Samw@Sun.COM } 17412508Samw@Sun.COM 1758473SJose.Borrego@Sun.COM return (rc); 1765331Samw } 1775331Samw 1785331Samw int 1795331Samw _info(struct modinfo *modinfop) 1805331Samw { 1815331Samw return (mod_info(&modlinkage, modinfop)); 1825331Samw } 1835331Samw 1845331Samw int 1855331Samw _fini(void) 1865331Samw { 1878473SJose.Borrego@Sun.COM int rc; 1888473SJose.Borrego@Sun.COM 18912508Samw@Sun.COM if ((rc = mod_remove(&modlinkage)) == 0) { 1908473SJose.Borrego@Sun.COM rc = smb_server_svc_fini(); 19112508Samw@Sun.COM smb_kshare_fini(); 19212508Samw@Sun.COM } 19312508Samw@Sun.COM 1948473SJose.Borrego@Sun.COM return (rc); 1956139Sjb150015 } 1966139Sjb150015 1976139Sjb150015 /* 1986139Sjb150015 * **************************************************************************** 1996139Sjb150015 * Pseudo Device Entry Points 2006139Sjb150015 * **************************************************************************** 2016139Sjb150015 */ 2026139Sjb150015 /* ARGSUSED */ 2036139Sjb150015 static int 2046139Sjb150015 smb_drv_open(dev_t *devp, int flag, int otyp, cred_t *credp) 2056139Sjb150015 { 2066139Sjb150015 /* 2076139Sjb150015 * Check caller's privileges. 2086139Sjb150015 */ 2096139Sjb150015 if (secpolicy_smb(credp) != 0) 2106139Sjb150015 return (EPERM); 2116139Sjb150015 2126139Sjb150015 /* 2136139Sjb150015 * Start SMB service state machine 2146139Sjb150015 */ 2156139Sjb150015 return (smb_server_create()); 2166139Sjb150015 } 2176139Sjb150015 2186139Sjb150015 /* ARGSUSED */ 2196139Sjb150015 static int 2206139Sjb150015 smb_drv_close(dev_t dev, int flag, int otyp, cred_t *credp) 2216139Sjb150015 { 2226139Sjb150015 return (smb_server_delete()); 2236139Sjb150015 } 2245331Samw 2256139Sjb150015 /* ARGSUSED */ 2266139Sjb150015 static int 2279832Samw@Sun.COM smb_drv_ioctl(dev_t drv, int cmd, intptr_t argp, int flags, cred_t *cred, 2286139Sjb150015 int *retval) 2296139Sjb150015 { 2309832Samw@Sun.COM smb_ioc_t *ioc; 2319832Samw@Sun.COM smb_ioc_header_t ioc_hdr; 2329832Samw@Sun.COM uint32_t crc; 2339832Samw@Sun.COM boolean_t copyout = B_FALSE; 2346139Sjb150015 int rc = 0; 2356139Sjb150015 2369832Samw@Sun.COM if (ddi_copyin((const void *)argp, &ioc_hdr, sizeof (smb_ioc_header_t), 2379832Samw@Sun.COM flags) || (ioc_hdr.version != SMB_IOC_VERSION)) 2386139Sjb150015 return (EFAULT); 2396139Sjb150015 2409832Samw@Sun.COM crc = ioc_hdr.crc; 2419832Samw@Sun.COM ioc_hdr.crc = 0; 2429832Samw@Sun.COM if (smb_crc_gen((uint8_t *)&ioc_hdr, sizeof (ioc_hdr)) != crc) 2439832Samw@Sun.COM return (EFAULT); 2448167Samw@Sun.COM 2459832Samw@Sun.COM ioc = kmem_alloc(ioc_hdr.len, KM_SLEEP); 2469832Samw@Sun.COM if (ddi_copyin((const void *)argp, ioc, ioc_hdr.len, flags)) { 2479832Samw@Sun.COM kmem_free(ioc, ioc_hdr.len); 2488167Samw@Sun.COM return (EFAULT); 2499832Samw@Sun.COM } 2508167Samw@Sun.COM 2516139Sjb150015 switch (cmd) { 2526139Sjb150015 case SMB_IOC_CONFIG: 2539832Samw@Sun.COM rc = smb_server_configure(&ioc->ioc_cfg); 2546139Sjb150015 break; 2556139Sjb150015 case SMB_IOC_START: 2569832Samw@Sun.COM rc = smb_server_start(&ioc->ioc_start); 2576139Sjb150015 break; 25811963SAfshin.Ardakani@Sun.COM case SMB_IOC_STOP: 25911963SAfshin.Ardakani@Sun.COM rc = smb_server_stop(); 26011963SAfshin.Ardakani@Sun.COM break; 26111963SAfshin.Ardakani@Sun.COM case SMB_IOC_EVENT: 26211963SAfshin.Ardakani@Sun.COM rc = smb_server_notify_event(&ioc->ioc_event); 26311963SAfshin.Ardakani@Sun.COM break; 2646139Sjb150015 case SMB_IOC_NBT_LISTEN: 2659832Samw@Sun.COM rc = smb_server_nbt_listen(&ioc->ioc_listen); 2666139Sjb150015 break; 2676139Sjb150015 case SMB_IOC_TCP_LISTEN: 2689832Samw@Sun.COM rc = smb_server_tcp_listen(&ioc->ioc_listen); 2696139Sjb150015 break; 2706139Sjb150015 case SMB_IOC_NBT_RECEIVE: 2716139Sjb150015 rc = smb_server_nbt_receive(); 2726139Sjb150015 break; 2736139Sjb150015 case SMB_IOC_TCP_RECEIVE: 2746139Sjb150015 rc = smb_server_tcp_receive(); 2756139Sjb150015 break; 2766139Sjb150015 case SMB_IOC_GMTOFF: 2779832Samw@Sun.COM rc = smb_server_set_gmtoff(&ioc->ioc_gmt); 2789832Samw@Sun.COM break; 2799832Samw@Sun.COM case SMB_IOC_SHARE: 28012508Samw@Sun.COM rc = smb_kshare_export_list(&ioc->ioc_share); 2819832Samw@Sun.COM break; 2829832Samw@Sun.COM case SMB_IOC_UNSHARE: 28312508Samw@Sun.COM rc = smb_kshare_unexport_list(&ioc->ioc_share); 2849832Samw@Sun.COM break; 285*12890SJoyce.McIntosh@Sun.COM case SMB_IOC_SHAREINFO: 286*12890SJoyce.McIntosh@Sun.COM rc = smb_kshare_info(&ioc->ioc_shareinfo); 287*12890SJoyce.McIntosh@Sun.COM copyout = B_TRUE; 288*12890SJoyce.McIntosh@Sun.COM break; 28910122SJordan.Brown@Sun.COM case SMB_IOC_NUMOPEN: 29010122SJordan.Brown@Sun.COM rc = smb_server_numopen(&ioc->ioc_opennum); 2919832Samw@Sun.COM copyout = B_TRUE; 2929832Samw@Sun.COM break; 29310122SJordan.Brown@Sun.COM case SMB_IOC_SVCENUM: 29410122SJordan.Brown@Sun.COM rc = smb_server_enum(&ioc->ioc_svcenum); 2959832Samw@Sun.COM copyout = B_TRUE; 2966139Sjb150015 break; 29710122SJordan.Brown@Sun.COM case SMB_IOC_SESSION_CLOSE: 29810122SJordan.Brown@Sun.COM rc = smb_server_session_close(&ioc->ioc_session); 29910122SJordan.Brown@Sun.COM break; 30010122SJordan.Brown@Sun.COM case SMB_IOC_FILE_CLOSE: 30110122SJordan.Brown@Sun.COM rc = smb_server_file_close(&ioc->ioc_fileid); 30210122SJordan.Brown@Sun.COM break; 303*12890SJoyce.McIntosh@Sun.COM case SMB_IOC_SPOOLDOC: 304*12890SJoyce.McIntosh@Sun.COM rc = smb_server_spooldoc(&ioc->ioc_spooldoc); 305*12890SJoyce.McIntosh@Sun.COM copyout = B_TRUE; 306*12890SJoyce.McIntosh@Sun.COM break; 3076139Sjb150015 default: 3086139Sjb150015 rc = ENOTTY; 3096139Sjb150015 break; 3105331Samw } 3119832Samw@Sun.COM if ((rc == 0) && copyout) { 3129832Samw@Sun.COM if (ddi_copyout((const void *)ioc, (void *)argp, ioc_hdr.len, 3139832Samw@Sun.COM flags)) 3149832Samw@Sun.COM rc = EFAULT; 3159832Samw@Sun.COM } 3169832Samw@Sun.COM kmem_free(ioc, ioc_hdr.len); 3175331Samw return (rc); 3185331Samw } 3195331Samw 3205331Samw /* 3216139Sjb150015 * **************************************************************************** 3226139Sjb150015 * Pseudo Device Operations 3236139Sjb150015 * **************************************************************************** 3245331Samw */ 3256139Sjb150015 static int 3266139Sjb150015 smb_drv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 3276139Sjb150015 { 3286139Sjb150015 if (cmd == DDI_ATTACH) { 3296139Sjb150015 /* we only allow instance 0 to attach */ 3306139Sjb150015 if (ddi_get_instance(dip) == 0) { 3316139Sjb150015 /* create the minor node */ 3326139Sjb150015 if (ddi_create_minor_node(dip, "smbsrv", S_IFCHR, 0, 3336139Sjb150015 DDI_PSEUDO, 0) == DDI_SUCCESS) { 3348473SJose.Borrego@Sun.COM smb_drv_dip = dip; 3358473SJose.Borrego@Sun.COM return (DDI_SUCCESS); 3366139Sjb150015 } else { 3376139Sjb150015 cmn_err(CE_WARN, "smb_drv_attach:" 3386139Sjb150015 " failed creating minor node"); 3396139Sjb150015 } 3406139Sjb150015 } 3416139Sjb150015 } 3426139Sjb150015 return (DDI_FAILURE); 3436139Sjb150015 } 3446139Sjb150015 3456139Sjb150015 static int 3466139Sjb150015 smb_drv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 3476139Sjb150015 { 3486139Sjb150015 if (cmd == DDI_DETACH) { 3496139Sjb150015 ASSERT(dip == smb_drv_dip); 3508473SJose.Borrego@Sun.COM ddi_remove_minor_node(dip, NULL); 3518473SJose.Borrego@Sun.COM smb_drv_dip = NULL; 3528473SJose.Borrego@Sun.COM return (DDI_SUCCESS); 3536139Sjb150015 } 3546139Sjb150015 return (DDI_FAILURE); 3556139Sjb150015 } 3565331Samw 3575331Samw /* ARGSUSED */ 3585331Samw static int 3595331Samw smb_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 3605331Samw { 3615331Samw ulong_t instance = getminor((dev_t)arg); 3625331Samw 3635331Samw switch (cmd) { 3645331Samw case DDI_INFO_DEVT2DEVINFO: 3655331Samw *result = smb_drv_dip; 3665331Samw return (DDI_SUCCESS); 3675331Samw 3685331Samw case DDI_INFO_DEVT2INSTANCE: 3695331Samw *result = (void *)instance; 3705331Samw return (DDI_SUCCESS); 3715331Samw 3725331Samw default: 3735331Samw break; 3745331Samw } 3755331Samw 3765331Samw return (DDI_FAILURE); 3775331Samw } 378