1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  14  */
  15 
  16 /*
  17  * These replace NODIRECT functions of the same name in
  18  * $SRC/lib/smbsrv/libsmb/common/smb_kmod.c including:
  19  *      smb_kmod_bind, smb_kmod_ioctl, smb_kmod_isbound,
  20  *      smb_kmod_start, smb_kmod_stop, smb_kmod_unbind.
  21  *
  22  * For all the other smb_kmod_... functions, we can just use the
  23  * libsmb code because those all call smb_kmod_ioctl, for which
  24  * we have an override here.
  25  *
  26  * The replacment functions here just call the libfksmbsrv code
  27  * directly where the real (in-kernel) versions would be entered
  28  * via the driver framework (open, close, ioctl).  Aside from that,
  29  * the call sequences are intentionally the same (where possible).
  30  * In particular, that makes it possible to debug startup/teardown
  31  * problems in the user-space version of this code.
  32  */
  33 
  34 #include <sys/types.h>
  35 #include <sys/stat.h>
  36 #include <sys/ioccom.h>
  37 #include <sys/param.h>
  38 #include <stddef.h>
  39 #include <stdio.h>
  40 #include <string.h>
  41 #include <strings.h>
  42 #include <stdlib.h>
  43 #include <unistd.h>
  44 #include <fcntl.h>
  45 #include <errno.h>
  46 #include <note.h>
  47 
  48 #include <smbsrv/smbinfo.h>
  49 #include <smbsrv/smb_ioctl.h>
  50 #include "smbd.h"
  51 
  52 boolean_t smbdrv_opened = B_FALSE;
  53 
  54 /*
  55  * We want to adjust a few things in the standard configuration
  56  * passed to the "fake" version of the smbsrv kernel module.
  57  *
  58  * Reduce the maximum number of connections and workers, just for
  59  * convenience while debugging.  (Don't want hundreds of threads.)
  60  */
  61 static void
  62 fksmbd_adjust_config(smb_ioc_header_t *ioc_hdr)
  63 {
  64         smb_ioc_cfg_t *ioc = (smb_ioc_cfg_t *)ioc_hdr;
  65         char *s;
  66 
  67         ioc->maxconnections = 10;
  68         ioc->maxworkers = 20;
  69         smbd_report("maxconnections=%d, maxworkers=%d",
  70             ioc->maxconnections, ioc->maxworkers);
  71 
  72         if ((s = getenv("SMB_MAX_PROTOCOL")) != NULL) {
  73                 ioc->max_protocol = strtol(s, NULL, 16);
  74                 smbd_report("max_protocol=0x%x", ioc->max_protocol);
  75         }
  76 
  77         if ((s = getenv("SMB_MIN_PROTOCOL")) != NULL) {
  78                 ioc->min_protocol = strtol(s, NULL, 16);
  79                 smbd_report("min_protocol=0x%x", ioc->min_protocol);
  80         }
  81 
  82         if ((s = getenv("SMB_SIGNING")) != NULL) {
  83                 ioc->signing_enable = 0;
  84                 ioc->signing_required = 0;
  85                 switch (s[0]) {
  86                 case 'e':
  87                         ioc->signing_enable = 1;
  88                         break;
  89                 case 'r':
  90                         ioc->signing_enable = 1;
  91                         ioc->signing_required = 1;
  92                         break;
  93                 default:
  94                         smbd_report("env SMB_SIGNING invalid");
  95                         break;
  96                 }
  97         }
  98         smbd_report("signing: enable=%d, required=%d",
  99             ioc->signing_enable, ioc->signing_required);
 100 }
 101 
 102 boolean_t
 103 smb_kmod_isbound(void)
 104 {
 105         return (smbdrv_opened);
 106 }
 107 
 108 int
 109 smb_kmod_bind(void)
 110 {
 111         int rc;
 112 
 113         if (smbdrv_opened) {
 114                 smbdrv_opened = B_FALSE;
 115                 (void) fksmbsrv_drv_close();
 116         }
 117 
 118         rc = fksmbsrv_drv_open();
 119         if (rc == 0)
 120                 smbdrv_opened = B_TRUE;
 121 
 122         return (rc);
 123 }
 124 
 125 void
 126 smb_kmod_unbind(void)
 127 {
 128         if (smbdrv_opened) {
 129                 smbdrv_opened = B_FALSE;
 130                 (void) fksmbsrv_drv_close();
 131         }
 132 }
 133 
 134 int
 135 smb_kmod_ioctl(int cmd, smb_ioc_header_t *ioc, uint32_t len)
 136 {
 137         int rc;
 138 
 139         _NOTE(ARGUNUSED(len));
 140 
 141         if (!smbdrv_opened)
 142                 return (EBADF);
 143 
 144         if (cmd == SMB_IOC_CONFIG)
 145                 fksmbd_adjust_config(ioc);
 146 
 147         rc = fksmbsrv_drv_ioctl(cmd, ioc);
 148         return (rc);
 149 }
 150 
 151 /* ARGSUSED */
 152 int
 153 smb_kmod_start(int opipe, int lmshr, int udoor)
 154 {
 155         smb_ioc_start_t ioc;
 156         int rc;
 157 
 158         bzero(&ioc, sizeof (ioc));
 159 
 160         /* These three are unused */
 161         ioc.opipe = -1;
 162         ioc.lmshrd = -1;
 163         ioc.udoor = -1;
 164 
 165         /* These are the "door" dispatch callbacks */
 166         ioc.lmshr_func = NULL; /* not used */
 167         ioc.opipe_func = NULL; /* not used */
 168         ioc.udoor_func = (void *)fksmbd_door_dispatch;
 169 
 170         rc = smb_kmod_ioctl(SMB_IOC_START, &ioc.hdr, sizeof (ioc));
 171         return (rc);
 172 }
 173 
 174 void
 175 smb_kmod_stop(void)
 176 {
 177         smb_ioc_header_t ioc;
 178 
 179         bzero(&ioc, sizeof (ioc));
 180         (void) smb_kmod_ioctl(SMB_IOC_STOP, &ioc, sizeof (ioc));
 181 }