/*
* 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 2015 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 <sys/types.h>
#include <sys/stat.h>
#include <sys/ioccom.h>
#include <sys/param.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <note.h>
#include <smbsrv/smbinfo.h>
#include <smbsrv/smb_ioctl.h>
#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_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(void)
{
int rc;
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));
}