/* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* * These replace NODIRECT functions of the same name in * $SRC/lib/smbsrv/libsmb/common/smb_kmod.c including: * smb_kmod_bind, smb_kmod_ioctl, smb_kmod_isbound, * smb_kmod_start, smb_kmod_stop, smb_kmod_unbind. * * For all the other smb_kmod_... functions, we can just use the * libsmb code because those all call smb_kmod_ioctl, for which * we have an override here. * * The replacment functions here just call the libfksmbsrv code * directly where the real (in-kernel) versions would be entered * via the driver framework (open, close, ioctl). Aside from that, * the call sequences are intentionally the same (where possible). * In particular, that makes it possible to debug startup/teardown * problems in the user-space version of this code. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "smbd.h" boolean_t smbdrv_opened = B_FALSE; /* * We want to adjust a few things in the standard configuration * passed to the "fake" version of the smbsrv kernel module. * * Reduce the maximum number of connections and workers, just for * convenience while debugging. (Don't want hundreds of threads.) */ static void fksmbd_adjust_config(smb_ioc_header_t *ioc_hdr) { smb_ioc_cfg_t *ioc = (smb_ioc_cfg_t *)ioc_hdr; char *s; ioc->maxconnections = 10; ioc->maxworkers = 20; smbd_report("maxconnections=%d, maxworkers=%d", ioc->maxconnections, ioc->maxworkers); if ((s = getenv("SMB_MAX_PROTOCOL")) != NULL) { ioc->max_protocol = strtol(s, NULL, 16); smbd_report("max_protocol=0x%x", ioc->max_protocol); } if ((s = getenv("SMB_MIN_PROTOCOL")) != NULL) { ioc->min_protocol = strtol(s, NULL, 16); smbd_report("min_protocol=0x%x", ioc->min_protocol); } if ((s = getenv("SMB_SIGNING")) != NULL) { ioc->signing_enable = 0; ioc->signing_required = 0; switch (s[0]) { case 'e': ioc->signing_enable = 1; break; case 'r': ioc->signing_enable = 1; ioc->signing_required = 1; break; default: smbd_report("env SMB_SIGNING invalid"); break; } } smbd_report("signing: enable=%d, required=%d", ioc->signing_enable, ioc->signing_required); } boolean_t smb_kmod_isbound(void) { return (smbdrv_opened); } int smb_kmod_bind(boolean_t smbd) { int rc; if (!smbd) return (ENXIO); if (smbdrv_opened) { smbdrv_opened = B_FALSE; (void) fksmbsrv_drv_close(); } rc = fksmbsrv_drv_open(); if (rc == 0) smbdrv_opened = B_TRUE; return (rc); } void smb_kmod_unbind(void) { if (smbdrv_opened) { smbdrv_opened = B_FALSE; (void) fksmbsrv_drv_close(); } } int smb_kmod_ioctl(int cmd, smb_ioc_header_t *ioc, uint32_t len) { int rc; _NOTE(ARGUNUSED(len)); if (!smbdrv_opened) return (EBADF); if (cmd == SMB_IOC_CONFIG) fksmbd_adjust_config(ioc); rc = fksmbsrv_drv_ioctl(cmd, ioc); return (rc); } /* ARGSUSED */ int smb_kmod_start(int opipe, int lmshr, int udoor) { smb_ioc_start_t ioc; int rc; bzero(&ioc, sizeof (ioc)); /* These three are unused */ ioc.opipe = -1; ioc.lmshrd = -1; ioc.udoor = -1; /* These are the "door" dispatch callbacks */ ioc.lmshr_func = NULL; /* not used */ ioc.opipe_func = NULL; /* not used */ ioc.udoor_func = (void *)fksmbd_door_dispatch; rc = smb_kmod_ioctl(SMB_IOC_START, &ioc.hdr, sizeof (ioc)); return (rc); } void smb_kmod_stop(void) { smb_ioc_header_t ioc; bzero(&ioc, sizeof (ioc)); (void) smb_kmod_ioctl(SMB_IOC_STOP, &ioc, sizeof (ioc)); }