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