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 2015 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_SIGNING")) != NULL) {
  73                 ioc->signing_enable = 0;
  74                 ioc->signing_required = 0;
  75                 switch (s[0]) {
  76                 case 'e':
  77                         ioc->signing_enable = 1;
  78                         break;
  79                 case 'r':
  80                         ioc->signing_enable = 1;
  81                         ioc->signing_required = 1;
  82                         break;
  83                 default:
  84                         smbd_report("env SMB_SIGNING invalid");
  85                         break;
  86                 }
  87         }
  88         smbd_report("signing: enable=%d, required=%d",
  89             ioc->signing_enable, ioc->signing_required);
  90 }
  91 
  92 boolean_t
  93 smb_kmod_isbound(void)
  94 {
  95         return (smbdrv_opened);
  96 }
  97 
  98 int
  99 smb_kmod_bind(void)
 100 {
 101         int rc;
 102 
 103         if (smbdrv_opened) {
 104                 smbdrv_opened = B_FALSE;
 105                 (void) fksmbsrv_drv_close();
 106         }
 107 
 108         rc = fksmbsrv_drv_open();
 109         if (rc == 0)
 110                 smbdrv_opened = B_TRUE;
 111 
 112         return (rc);
 113 }
 114 
 115 void
 116 smb_kmod_unbind(void)
 117 {
 118         if (smbdrv_opened) {
 119                 smbdrv_opened = B_FALSE;
 120                 (void) fksmbsrv_drv_close();
 121         }
 122 }
 123 
 124 int
 125 smb_kmod_ioctl(int cmd, smb_ioc_header_t *ioc, uint32_t len)
 126 {
 127         int rc;
 128 
 129         _NOTE(ARGUNUSED(len));
 130 
 131         if (!smbdrv_opened)
 132                 return (EBADF);
 133 
 134         if (cmd == SMB_IOC_CONFIG)
 135                 fksmbd_adjust_config(ioc);
 136 
 137         rc = fksmbsrv_drv_ioctl(cmd, ioc);
 138         return (rc);
 139 }
 140 
 141 /* ARGSUSED */
 142 int
 143 smb_kmod_start(int opipe, int lmshr, int udoor)
 144 {
 145         smb_ioc_start_t ioc;
 146         int rc;
 147 
 148         bzero(&ioc, sizeof (ioc));
 149 
 150         /* These three are unused */
 151         ioc.opipe = -1;
 152         ioc.lmshrd = -1;
 153         ioc.udoor = -1;
 154 
 155         /* These are the "door" dispatch callbacks */
 156         ioc.lmshr_func = NULL; /* not used */
 157         ioc.opipe_func = NULL; /* not used */
 158         ioc.udoor_func = (void *)fksmbd_door_dispatch;
 159 
 160         rc = smb_kmod_ioctl(SMB_IOC_START, &ioc.hdr, sizeof (ioc));
 161         return (rc);
 162 }
 163 
 164 void
 165 smb_kmod_stop(void)
 166 {
 167         smb_ioc_header_t ioc;
 168 
 169         bzero(&ioc, sizeof (ioc));
 170         (void) smb_kmod_ioctl(SMB_IOC_STOP, &ioc, sizeof (ioc));
 171 }