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*8473SJose.Borrego@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 235331Samw * Use is subject to license terms. 245331Samw */ 255331Samw 265331Samw #include <sys/types.h> 275331Samw #include <sys/ddi.h> 285331Samw #include <sys/modctl.h> 295331Samw #include <sys/cred.h> 305331Samw #include <sys/ioccom.h> 315331Samw #include <sys/policy.h> 328167Samw@Sun.COM #include <sys/cmn_err.h> 335331Samw #include <smbsrv/smb_incl.h> 345331Samw #include <smbsrv/smb_door_svc.h> 355331Samw #include <smbsrv/smb_ioctl.h> 365331Samw #include <smbsrv/smb_kproto.h> 376139Sjb150015 386139Sjb150015 static int smb_drv_open(dev_t *, int, int, cred_t *); 396139Sjb150015 static int smb_drv_close(dev_t, int, int, cred_t *); 406139Sjb150015 static int smb_drv_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 415331Samw static int smb_drv_attach(dev_info_t *, ddi_attach_cmd_t); 425331Samw static int smb_drv_detach(dev_info_t *, ddi_detach_cmd_t); 435331Samw static int smb_drv_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 446139Sjb150015 456139Sjb150015 /* 466139Sjb150015 * ***************************************************************************** 476139Sjb150015 * ****************************** Global Variables ***************************** 486139Sjb150015 * ***************************************************************************** 496139Sjb150015 * 506139Sjb150015 * These variables can only be changed through the /etc/system file. 516139Sjb150015 */ 525331Samw 535331Samw /* 546139Sjb150015 * Maximum buffer size for NT: configurable based on the client environment. 556139Sjb150015 * IR104720 Experiments with Windows 2000 indicate that we achieve better 566139Sjb150015 * SmbWriteX performance with a buffer size of 64KB instead of the 37KB used 576139Sjb150015 * with Windows NT4.0. Previous experiments with NT4.0 resulted in directory 586139Sjb150015 * listing problems so this buffer size is configurable based on the end-user 596139Sjb150015 * environment. When in doubt use 37KB. 605331Samw */ 616139Sjb150015 int smb_maxbufsize = SMB_NT_MAXBUF; 626139Sjb150015 clock_t smb_oplock_timeout = OPLOCK_STD_TIMEOUT; 636139Sjb150015 int smb_flush_required = 1; 646139Sjb150015 int smb_dirsymlink_enable = 1; 656139Sjb150015 int smb_announce_quota = 0; 667348SJose.Borrego@Sun.COM int smb_sign_debug = 0; 676139Sjb150015 686139Sjb150015 /* 696139Sjb150015 * ***************************************************************************** 706139Sjb150015 * ********************** Static Variables / Module Linkage ******************** 716139Sjb150015 * ***************************************************************************** 726139Sjb150015 */ 736139Sjb150015 745331Samw static struct cb_ops cbops = { 755331Samw smb_drv_open, /* cb_open */ 765331Samw smb_drv_close, /* cb_close */ 775331Samw nodev, /* cb_strategy */ 785331Samw nodev, /* cb_print */ 795331Samw nodev, /* cb_dump */ 805331Samw nodev, /* cb_read */ 815331Samw nodev, /* cb_write */ 825331Samw smb_drv_ioctl, /* cb_ioctl */ 835331Samw nodev, /* cb_devmap */ 845331Samw nodev, /* cb_mmap */ 855331Samw nodev, /* cb_segmap */ 865331Samw nochpoll, /* cb_chpoll */ 875331Samw ddi_prop_op, /* cb_prop_op */ 885331Samw NULL, /* cb_streamtab */ 895331Samw D_MP, /* cb_flag */ 905331Samw CB_REV, /* cb_rev */ 915331Samw nodev, /* cb_aread */ 925331Samw nodev, /* cb_awrite */ 935331Samw }; 945331Samw 955331Samw static struct dev_ops devops = { 965331Samw DEVO_REV, /* devo_rev */ 975331Samw 0, /* devo_refcnt */ 985331Samw smb_drv_getinfo, /* devo_getinfo */ 995331Samw nulldev, /* devo_identify */ 1005331Samw nulldev, /* devo_probe */ 1015331Samw smb_drv_attach, /* devo_attach */ 1025331Samw smb_drv_detach, /* devo_detach */ 1035331Samw nodev, /* devo_reset */ 1045331Samw &cbops, /* devo_cb_ops */ 1055331Samw NULL, /* devo_bus_ops */ 1065331Samw NULL, /* devo_power */ 1077656SSherry.Moore@Sun.COM ddi_quiesce_not_needed, /* devo_quiesce */ 1085331Samw }; 1095331Samw 1105331Samw static struct modldrv modldrv = { 1115331Samw &mod_driverops, /* drv_modops */ 1127656SSherry.Moore@Sun.COM "CIFS Server Protocol", /* 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 /* 1256139Sjb150015 * **************************************************************************** 1266139Sjb150015 * Module Interface 1276139Sjb150015 * **************************************************************************** 1285331Samw */ 1295331Samw 1305331Samw int 1315331Samw _init(void) 1325331Samw { 133*8473SJose.Borrego@Sun.COM int rc; 134*8473SJose.Borrego@Sun.COM 135*8473SJose.Borrego@Sun.COM rc = smb_server_svc_init(); 136*8473SJose.Borrego@Sun.COM if (rc == 0) { 137*8473SJose.Borrego@Sun.COM rc = mod_install(&modlinkage); 138*8473SJose.Borrego@Sun.COM if (rc != 0) 139*8473SJose.Borrego@Sun.COM (void) smb_server_svc_fini(); 140*8473SJose.Borrego@Sun.COM } 141*8473SJose.Borrego@Sun.COM return (rc); 1425331Samw } 1435331Samw 1445331Samw int 1455331Samw _info(struct modinfo *modinfop) 1465331Samw { 1475331Samw return (mod_info(&modlinkage, modinfop)); 1485331Samw } 1495331Samw 1505331Samw int 1515331Samw _fini(void) 1525331Samw { 153*8473SJose.Borrego@Sun.COM int rc; 154*8473SJose.Borrego@Sun.COM 155*8473SJose.Borrego@Sun.COM rc = mod_remove(&modlinkage); 156*8473SJose.Borrego@Sun.COM if (rc == 0) 157*8473SJose.Borrego@Sun.COM rc = smb_server_svc_fini(); 158*8473SJose.Borrego@Sun.COM return (rc); 1596139Sjb150015 } 1606139Sjb150015 1616139Sjb150015 /* 1626139Sjb150015 * **************************************************************************** 1636139Sjb150015 * Pseudo Device Entry Points 1646139Sjb150015 * **************************************************************************** 1656139Sjb150015 */ 1666139Sjb150015 /* ARGSUSED */ 1676139Sjb150015 static int 1686139Sjb150015 smb_drv_open(dev_t *devp, int flag, int otyp, cred_t *credp) 1696139Sjb150015 { 1706139Sjb150015 /* 1716139Sjb150015 * Check caller's privileges. 1726139Sjb150015 */ 1736139Sjb150015 if (secpolicy_smb(credp) != 0) 1746139Sjb150015 return (EPERM); 1756139Sjb150015 1766139Sjb150015 /* 1776139Sjb150015 * Start SMB service state machine 1786139Sjb150015 */ 1796139Sjb150015 return (smb_server_create()); 1806139Sjb150015 } 1816139Sjb150015 1826139Sjb150015 /* ARGSUSED */ 1836139Sjb150015 static int 1846139Sjb150015 smb_drv_close(dev_t dev, int flag, int otyp, cred_t *credp) 1856139Sjb150015 { 1866139Sjb150015 return (smb_server_delete()); 1876139Sjb150015 } 1885331Samw 1896139Sjb150015 /* ARGSUSED */ 1906139Sjb150015 static int 1916139Sjb150015 smb_drv_ioctl(dev_t drv, int cmd, intptr_t argp, int flag, cred_t *cred, 1926139Sjb150015 int *retval) 1936139Sjb150015 { 1946139Sjb150015 int rc = 0; 1956139Sjb150015 smb_io_t smb_io; 1968167Samw@Sun.COM uint32_t crc1; 1978167Samw@Sun.COM uint32_t crc2; 1986139Sjb150015 1996139Sjb150015 if (ddi_copyin((smb_io_t *)argp, &smb_io, sizeof (smb_io), flag) || 2006139Sjb150015 (smb_io.sio_version != SMB_IOC_VERSION)) 2016139Sjb150015 return (EFAULT); 2026139Sjb150015 2038167Samw@Sun.COM crc1 = smb_io.sio_crc; 2048167Samw@Sun.COM smb_io.sio_crc = 0; 2058167Samw@Sun.COM crc2 = smb_crc_gen((uint8_t *)&smb_io, sizeof (smb_io_t)); 2068167Samw@Sun.COM 2078167Samw@Sun.COM if (crc1 != crc2) 2088167Samw@Sun.COM return (EFAULT); 2098167Samw@Sun.COM 2106139Sjb150015 switch (cmd) { 2116139Sjb150015 case SMB_IOC_CONFIG: 2126139Sjb150015 rc = smb_server_configure(&smb_io.sio_data.cfg); 2136139Sjb150015 break; 2146139Sjb150015 case SMB_IOC_START: 2156139Sjb150015 rc = smb_server_start(&smb_io.sio_data.start); 2166139Sjb150015 break; 2176139Sjb150015 case SMB_IOC_NBT_LISTEN: 2186139Sjb150015 rc = smb_server_nbt_listen(smb_io.sio_data.error); 2196139Sjb150015 break; 2206139Sjb150015 case SMB_IOC_TCP_LISTEN: 2216139Sjb150015 rc = smb_server_tcp_listen(smb_io.sio_data.error); 2226139Sjb150015 break; 2236139Sjb150015 case SMB_IOC_NBT_RECEIVE: 2246139Sjb150015 rc = smb_server_nbt_receive(); 2256139Sjb150015 break; 2266139Sjb150015 case SMB_IOC_TCP_RECEIVE: 2276139Sjb150015 rc = smb_server_tcp_receive(); 2286139Sjb150015 break; 2296139Sjb150015 case SMB_IOC_GMTOFF: 2306139Sjb150015 rc = smb_server_set_gmtoff(smb_io.sio_data.gmtoff); 2316139Sjb150015 break; 2326139Sjb150015 default: 2336139Sjb150015 rc = ENOTTY; 2346139Sjb150015 break; 2355331Samw } 2365331Samw 2375331Samw return (rc); 2385331Samw } 2395331Samw 2405331Samw /* 2416139Sjb150015 * **************************************************************************** 2426139Sjb150015 * Pseudo Device Operations 2436139Sjb150015 * **************************************************************************** 2445331Samw */ 2456139Sjb150015 static int 2466139Sjb150015 smb_drv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2476139Sjb150015 { 2486139Sjb150015 if (cmd == DDI_ATTACH) { 2496139Sjb150015 /* we only allow instance 0 to attach */ 2506139Sjb150015 if (ddi_get_instance(dip) == 0) { 2516139Sjb150015 /* create the minor node */ 2526139Sjb150015 if (ddi_create_minor_node(dip, "smbsrv", S_IFCHR, 0, 2536139Sjb150015 DDI_PSEUDO, 0) == DDI_SUCCESS) { 254*8473SJose.Borrego@Sun.COM smb_drv_dip = dip; 255*8473SJose.Borrego@Sun.COM return (DDI_SUCCESS); 2566139Sjb150015 } else { 2576139Sjb150015 cmn_err(CE_WARN, "smb_drv_attach:" 2586139Sjb150015 " failed creating minor node"); 2596139Sjb150015 } 2606139Sjb150015 } 2616139Sjb150015 } 2626139Sjb150015 return (DDI_FAILURE); 2636139Sjb150015 } 2646139Sjb150015 2656139Sjb150015 static int 2666139Sjb150015 smb_drv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2676139Sjb150015 { 2686139Sjb150015 if (cmd == DDI_DETACH) { 2696139Sjb150015 ASSERT(dip == smb_drv_dip); 270*8473SJose.Borrego@Sun.COM ddi_remove_minor_node(dip, NULL); 271*8473SJose.Borrego@Sun.COM smb_drv_dip = NULL; 272*8473SJose.Borrego@Sun.COM return (DDI_SUCCESS); 2736139Sjb150015 } 2746139Sjb150015 return (DDI_FAILURE); 2756139Sjb150015 } 2765331Samw 2775331Samw /* ARGSUSED */ 2785331Samw static int 2795331Samw smb_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 2805331Samw { 2815331Samw ulong_t instance = getminor((dev_t)arg); 2825331Samw 2835331Samw switch (cmd) { 2845331Samw case DDI_INFO_DEVT2DEVINFO: 2855331Samw *result = smb_drv_dip; 2865331Samw return (DDI_SUCCESS); 2875331Samw 2885331Samw case DDI_INFO_DEVT2INSTANCE: 2895331Samw *result = (void *)instance; 2905331Samw return (DDI_SUCCESS); 2915331Samw 2925331Samw default: 2935331Samw break; 2945331Samw } 2955331Samw 2965331Samw return (DDI_FAILURE); 2975331Samw } 298