Print this page
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)
NEX-15578 SMB2 durable handle redesign
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-15578 SMB2 durable handle redesign
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-5844 want SMB2 ioctl FSCTL_SRV_COPYCHUNK
NEX-6124 smb_fsop_read/write should allow file != sr->fid_ofile
NEX-6125 smbtorture invalid response with smb2.ioctl
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-4538 SMB1 create file should support extended_response format (2)
NEX-6116 Failures in smbtorture raw.open
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Include this commit if upstreaming/backporting any of:
NEX-4540 SMB server declines EA support incorrectly
NEX-4239 smbtorture create failures re. allocation size
(illumos) 6398 SMB should support path names longer than 1024
NEX-4538 SMB1 create file should support extended_response format
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
NEX-2522 svcadm disable network/smb/server may hang
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-3662 Backport illumos 1501: taskq_create_proc ... TQ_DYNAMIC puts tasks in p0 (take 2)
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Marcel Telka <marcel.telka@nexenta.com>
NEX-3576 RPC error when displaying open files via Windows MMC
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-2188 Browsing top level share produces RPC error 1728
SMB-119 Text file contains garbage when re-opened
SMB-120 Share enumeration fails with Windows 8
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
SMB-39 Use AF_UNIX pipes for RPC
SMB-50 User-mode SMB server
Includes work by these authors:
Thomas Keiser <thomas.keiser@nexenta.com>
Albert Lee <trisk@nexenta.com>
SMB-65 SMB server in non-global zones (data structure changes)
Many things move to the smb_server_t object, and
many functions gain an sv arg (which server).
SMB-65 SMB server in non-global zones (kmem_caches)
common kmem_cache instances across zones
separate GZ-only init from NGZ init
SMB-63 taskq_create_proc ... TQ_DYNAMIC puts tasks in p0
re #11974 CIFS Share - Tree connect fails from Windows 7 Clients
re #6812 rb1753 backport illumos 1604 smbd print_enable doesn't really work
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb_opipe.c
+++ new/usr/src/uts/common/fs/smbsrv/smb_opipe.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 - * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
23 + * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
24 24 */
25 25
26 26 /*
27 27 * This module provides the interface to NDR RPC.
28 28 */
29 29
30 30 #include <sys/stat.h>
31 31 #include <sys/uio.h>
32 32 #include <sys/ksynch.h>
33 33 #include <sys/stropts.h>
34 34 #include <sys/socket.h>
35 35 #include <sys/filio.h>
36 36 #include <smbsrv/smb_kproto.h>
37 37 #include <smbsrv/smb_xdr.h>
38 -#include <smbsrv/winioctl.h>
38 +#include <smb/winioctl.h>
39 39
40 -static uint32_t smb_opipe_transceive(smb_request_t *, smb_fsctl_t *);
41 -
42 40 /*
43 41 * Allocate a new opipe and return it, or NULL, in which case
44 42 * the caller will report "internal error".
45 43 */
46 44 static smb_opipe_t *
47 45 smb_opipe_alloc(smb_request_t *sr)
48 46 {
49 47 smb_server_t *sv = sr->sr_server;
50 48 smb_opipe_t *opipe;
51 49 ksocket_t sock;
52 50
53 51 if (ksocket_socket(&sock, AF_UNIX, SOCK_STREAM, 0,
54 52 KSOCKET_SLEEP, sr->user_cr) != 0)
55 53 return (NULL);
56 54
57 55 opipe = kmem_cache_alloc(smb_cache_opipe, KM_SLEEP);
58 56
59 57 bzero(opipe, sizeof (smb_opipe_t));
60 58 mutex_init(&opipe->p_mutex, NULL, MUTEX_DEFAULT, NULL);
61 59 cv_init(&opipe->p_cv, NULL, CV_DEFAULT, NULL);
62 60 opipe->p_magic = SMB_OPIPE_MAGIC;
63 61 opipe->p_server = sv;
64 62 opipe->p_refcnt = 1;
65 63 opipe->p_socket = sock;
66 64
67 65 return (opipe);
68 66 }
69 67
70 68 /*
71 69 * Destroy an opipe. This is normally called from smb_ofile_delete
72 70 * when the ofile has no more references and is about to be free'd.
73 71 * This is also called here in error handling code paths, before
74 72 * the opipe is installed under an ofile.
75 73 */
76 74 void
77 75 smb_opipe_dealloc(smb_opipe_t *opipe)
78 76 {
79 77 smb_server_t *sv;
80 78
81 79 SMB_OPIPE_VALID(opipe);
82 80 sv = opipe->p_server;
83 81 SMB_SERVER_VALID(sv);
84 82
85 83 /*
86 84 * This is called in the error path when opening,
87 85 * in which case we close the socket here.
88 86 */
89 87 if (opipe->p_socket != NULL)
|
↓ open down ↓ |
38 lines elided |
↑ open up ↑ |
90 88 (void) ksocket_close(opipe->p_socket, zone_kcred());
91 89
92 90 opipe->p_magic = (uint32_t)~SMB_OPIPE_MAGIC;
93 91 cv_destroy(&opipe->p_cv);
94 92 mutex_destroy(&opipe->p_mutex);
95 93
96 94 kmem_cache_free(smb_cache_opipe, opipe);
97 95 }
98 96
99 97 /*
98 + * Unblock a request that might be blocked reading some
99 + * pipe (AF_UNIX socket). We don't have an easy way to
100 + * interrupt just the thread servicing this request, so
101 + * we shutdown(3socket) the socket, waking all readers.
102 + * That's a bit heavy-handed, making the socket unusable
103 + * after this, so we do this only when disconnecting a
104 + * session (i.e. stopping the SMB service), and not when
105 + * handling an SMB2_cancel or SMB_nt_cancel request.
106 + */
107 +static void
108 +smb_opipe_cancel(smb_request_t *sr)
109 +{
110 + ksocket_t so;
111 +
112 + switch (sr->session->s_state) {
113 + case SMB_SESSION_STATE_DISCONNECTED:
114 + case SMB_SESSION_STATE_TERMINATED:
115 + if ((so = sr->cancel_arg2) != NULL)
116 + (void) ksocket_shutdown(so, SHUT_RDWR, sr->user_cr);
117 + break;
118 + }
119 +}
120 +
121 +/*
100 122 * Helper for open: build pipe name and connect.
101 123 */
102 124 static int
103 125 smb_opipe_connect(smb_request_t *sr, smb_opipe_t *opipe)
104 126 {
105 127 struct sockaddr_un saddr;
106 128 smb_arg_open_t *op = &sr->sr_open;
107 129 const char *name;
108 130 int rc;
109 131
110 132 name = op->fqi.fq_path.pn_path;
111 133 name += strspn(name, "\\");
112 134 if (smb_strcasecmp(name, "PIPE", 4) == 0) {
113 135 name += 4;
114 136 name += strspn(name, "\\");
115 137 }
116 138 (void) strlcpy(opipe->p_name, name, SMB_OPIPE_MAXNAME);
117 139 (void) smb_strlwr(opipe->p_name);
118 140
119 141 bzero(&saddr, sizeof (saddr));
120 142 saddr.sun_family = AF_UNIX;
121 143 (void) snprintf(saddr.sun_path, sizeof (saddr.sun_path),
122 144 "%s/%s", SMB_PIPE_DIR, opipe->p_name);
123 145 rc = ksocket_connect(opipe->p_socket, (struct sockaddr *)&saddr,
124 146 sizeof (saddr), sr->user_cr);
125 147
126 148 return (rc);
127 149 }
128 150
129 151 /*
130 152 * Helper for open: encode and send the user info.
131 153 *
132 154 * We send information about this client + user to the
133 155 * pipe service so it can use it for access checks.
134 156 * The service MAY deny the open based on this info,
135 157 * (i.e. anonymous session trying to open a pipe that
136 158 * requires authentication) in which case we will read
137 159 * an error status from the service and return that.
138 160 */
139 161 static void
140 162 smb_opipe_send_userinfo(smb_request_t *sr, smb_opipe_t *opipe,
141 163 smb_error_t *errp)
142 164 {
143 165 XDR xdrs;
144 166 smb_netuserinfo_t nui;
145 167 smb_pipehdr_t phdr;
146 168 char *buf;
147 169 uint32_t buflen;
148 170 uint32_t status;
149 171 size_t iocnt = 0;
150 172 int rc;
151 173
152 174 /*
153 175 * Any errors building the XDR message etc.
154 176 */
155 177 errp->status = NT_STATUS_INTERNAL_ERROR;
156 178
157 179 smb_user_netinfo_init(sr->uid_user, &nui);
158 180 phdr.ph_magic = SMB_PIPE_HDR_MAGIC;
159 181 phdr.ph_uilen = xdr_sizeof(smb_netuserinfo_xdr, &nui);
|
↓ open down ↓ |
50 lines elided |
↑ open up ↑ |
160 182
161 183 buflen = sizeof (phdr) + phdr.ph_uilen;
162 184 buf = kmem_alloc(buflen, KM_SLEEP);
163 185
164 186 bcopy(&phdr, buf, sizeof (phdr));
165 187 xdrmem_create(&xdrs, buf + sizeof (phdr),
166 188 buflen - (sizeof (phdr)), XDR_ENCODE);
167 189 if (!smb_netuserinfo_xdr(&xdrs, &nui))
168 190 goto out;
169 191
170 - /*
171 - * If we fail sending the netuserinfo or recv'ing the
172 - * status reponse, we have probably run into the limit
173 - * on the number of open pipes. That's this status:
174 - */
175 - errp->status = NT_STATUS_PIPE_NOT_AVAILABLE;
192 + mutex_enter(&sr->sr_mutex);
193 + if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
194 + mutex_exit(&sr->sr_mutex);
195 + errp->status = NT_STATUS_CANCELLED;
196 + goto out;
197 + }
198 + sr->sr_state = SMB_REQ_STATE_WAITING_PIPE;
199 + sr->cancel_method = smb_opipe_cancel;
200 + sr->cancel_arg2 = opipe->p_socket;
201 + mutex_exit(&sr->sr_mutex);
176 202
177 203 rc = ksocket_send(opipe->p_socket, buf, buflen, 0,
178 204 &iocnt, sr->user_cr);
179 205 if (rc == 0 && iocnt != buflen)
180 206 rc = EIO;
181 - if (rc != 0)
182 - goto out;
207 + if (rc == 0)
208 + rc = ksocket_recv(opipe->p_socket, &status, sizeof (status),
209 + 0, &iocnt, sr->user_cr);
210 + if (rc == 0 && iocnt != sizeof (status))
211 + rc = EIO;
183 212
184 - rc = ksocket_recv(opipe->p_socket, &status, sizeof (status), 0,
185 - &iocnt, sr->user_cr);
186 - if (rc != 0 || iocnt != sizeof (status))
187 - goto out;
213 + mutex_enter(&sr->sr_mutex);
214 + sr->cancel_method = NULL;
215 + sr->cancel_arg2 = NULL;
216 + switch (sr->sr_state) {
217 + case SMB_REQ_STATE_WAITING_PIPE:
218 + sr->sr_state = SMB_REQ_STATE_ACTIVE;
219 + break;
220 + case SMB_REQ_STATE_CANCEL_PENDING:
221 + sr->sr_state = SMB_REQ_STATE_CANCELLED;
222 + rc = EINTR;
223 + break;
224 + default:
225 + /* keep rc from above */
226 + break;
227 + }
228 + mutex_exit(&sr->sr_mutex);
188 229
230 +
189 231 /*
190 232 * Return the status we read from the pipe service,
191 233 * normally NT_STATUS_SUCCESS, but could be something
192 234 * else like NT_STATUS_ACCESS_DENIED.
193 235 */
194 - errp->status = status;
236 + switch (rc) {
237 + case 0:
238 + errp->status = status;
239 + break;
240 + case EINTR:
241 + errp->status = NT_STATUS_CANCELLED;
242 + break;
243 + /*
244 + * If we fail sending the netuserinfo or recv'ing the
245 + * status reponse, we have probably run into the limit
246 + * on the number of open pipes. That's this status:
247 + */
248 + default:
249 + errp->status = NT_STATUS_PIPE_NOT_AVAILABLE;
250 + break;
251 + }
195 252
196 253 out:
197 254 xdr_destroy(&xdrs);
198 255 kmem_free(buf, buflen);
199 256 smb_user_netinfo_fini(&nui);
200 257 }
201 258
202 259 /*
203 260 * smb_opipe_open
204 261 *
205 262 * Open an RPC named pipe. This routine should be called if
206 263 * a file open is requested on a share of type STYPE_IPC.
207 264 * If we recognize the pipe, we setup a new ofile.
208 265 *
209 266 * Returns 0 on success, Otherwise an NT status code.
210 267 */
211 268 int
212 -smb_opipe_open(smb_request_t *sr, uint32_t uniqid)
269 +smb_opipe_open(smb_request_t *sr, smb_ofile_t *ofile)
213 270 {
214 271 smb_arg_open_t *op = &sr->sr_open;
215 - smb_ofile_t *ofile;
272 + smb_attr_t *ap = &op->fqi.fq_fattr;
216 273 smb_opipe_t *opipe;
217 274 smb_error_t err;
218 275
219 276 opipe = smb_opipe_alloc(sr);
220 277 if (opipe == NULL)
221 278 return (NT_STATUS_INTERNAL_ERROR);
222 279
223 280 if (smb_opipe_connect(sr, opipe) != 0) {
224 281 smb_opipe_dealloc(opipe);
225 282 return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
226 283 }
227 284
228 285 smb_opipe_send_userinfo(sr, opipe, &err);
229 286 if (err.status != 0) {
230 287 smb_opipe_dealloc(opipe);
231 288 return (err.status);
232 289 }
233 290
234 291 /*
235 - * Note: If smb_ofile_open succeeds, the new ofile is
236 - * in the FID lists can can be used by I/O requests.
292 + * We might have blocked in smb_opipe_connect long enough so
293 + * a tree disconnect might have happened. In that case, we
294 + * would be adding an ofile to a tree that's disconnecting,
295 + * which would interfere with tear-down.
237 296 */
238 - op->create_options = 0;
239 - op->pipe = opipe;
240 - ofile = smb_ofile_open(sr, NULL, op,
241 - SMB_FTYPE_MESG_PIPE, uniqid, &err);
242 - op->pipe = NULL;
243 - if (ofile == NULL) {
297 + if (!smb_tree_is_connected(sr->tid_tree)) {
244 298 smb_opipe_dealloc(opipe);
245 - return (err.status);
299 + return (NT_STATUS_NETWORK_NAME_DELETED);
246 300 }
247 301
302 + /*
303 + * Note: The new opipe is given to smb_ofile_open
304 + * via op->pipe
305 + */
306 + op->pipe = opipe;
307 + smb_ofile_open(sr, op, ofile);
308 + op->pipe = NULL;
309 +
248 310 /* An "up" pointer, for debug. */
249 311 opipe->p_ofile = ofile;
250 312
251 - op->dsize = 0x01000;
252 - op->dattr = FILE_ATTRIBUTE_NORMAL;
313 + /*
314 + * Caller expects attributes in op->fqi
315 + */
316 + (void) smb_opipe_getattr(ofile, &op->fqi.fq_fattr);
317 +
318 + op->dsize = 0;
319 + op->dattr = ap->sa_dosattr;
320 + op->fileid = ap->sa_vattr.va_nodeid;
253 321 op->ftype = SMB_FTYPE_MESG_PIPE;
254 - op->action_taken = SMB_OACT_LOCK | SMB_OACT_OPENED; /* 0x8001 */
322 + op->action_taken = SMB_OACT_OPLOCK | SMB_OACT_OPENED;
255 323 op->devstate = SMB_PIPE_READMODE_MESSAGE
256 324 | SMB_PIPE_TYPE_MESSAGE
257 325 | SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */
258 - op->fileid = ofile->f_fid;
259 326
260 327 sr->smb_fid = ofile->f_fid;
261 328 sr->fid_ofile = ofile;
262 329
263 330 return (NT_STATUS_SUCCESS);
264 331 }
265 332
266 333 /*
267 334 * smb_opipe_close
268 335 *
269 336 * Called by smb_ofile_close for pipes.
270 337 *
271 338 * Note: ksocket_close may block while waiting for
272 339 * any I/O threads with a hold to get out.
273 340 */
274 341 void
275 342 smb_opipe_close(smb_ofile_t *of)
276 343 {
277 344 smb_opipe_t *opipe;
278 345 ksocket_t sock;
279 346
280 347 ASSERT(of->f_state == SMB_OFILE_STATE_CLOSING);
281 348 ASSERT(of->f_ftype == SMB_FTYPE_MESG_PIPE);
282 349 opipe = of->f_pipe;
283 350 SMB_OPIPE_VALID(opipe);
284 351
285 352 mutex_enter(&opipe->p_mutex);
286 353 sock = opipe->p_socket;
287 354 opipe->p_socket = NULL;
288 355 mutex_exit(&opipe->p_mutex);
289 356
290 357 (void) ksocket_shutdown(sock, SHUT_RDWR, of->f_cr);
291 358 (void) ksocket_close(sock, of->f_cr);
292 359 }
293 360
294 361 /*
295 362 * smb_opipe_write
296 363 *
297 364 * Write RPC request data to the pipe. The client should call smb_opipe_read
298 365 * to complete the exchange and obtain the RPC response.
299 366 *
300 367 * Returns 0 on success or an errno on failure.
301 368 */
302 369 int
303 370 smb_opipe_write(smb_request_t *sr, struct uio *uio)
304 371 {
305 372 struct nmsghdr msghdr;
306 373 smb_ofile_t *ofile;
307 374 smb_opipe_t *opipe;
308 375 ksocket_t sock;
309 376 size_t sent = 0;
310 377 int rc = 0;
311 378
312 379 ofile = sr->fid_ofile;
313 380 ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
314 381 opipe = ofile->f_pipe;
315 382 SMB_OPIPE_VALID(opipe);
316 383
317 384 mutex_enter(&opipe->p_mutex);
318 385 sock = opipe->p_socket;
319 386 if (sock != NULL)
320 387 ksocket_hold(sock);
321 388 mutex_exit(&opipe->p_mutex);
322 389 if (sock == NULL)
323 390 return (EBADF);
324 391
325 392 bzero(&msghdr, sizeof (msghdr));
326 393 msghdr.msg_iov = uio->uio_iov;
327 394 msghdr.msg_iovlen = uio->uio_iovcnt;
328 395
329 396 /*
330 397 * This should block until we've sent it all,
331 398 * or given up due to errors (pipe closed).
332 399 */
333 400 while (uio->uio_resid > 0) {
334 401 rc = ksocket_sendmsg(sock, &msghdr, 0, &sent, ofile->f_cr);
335 402 if (rc != 0)
336 403 break;
337 404 uio->uio_resid -= sent;
338 405 }
339 406
340 407 ksocket_rele(sock);
341 408
342 409 return (rc);
343 410 }
344 411
345 412 /*
346 413 * smb_opipe_read
347 414 *
348 415 * This interface may be called from smb_opipe_transact (write, read)
349 416 * or from smb_read / smb2_read to get the rest of an RPC response.
350 417 * The response data (and length) are returned via the uio.
351 418 */
352 419 int
353 420 smb_opipe_read(smb_request_t *sr, struct uio *uio)
354 421 {
355 422 struct nmsghdr msghdr;
356 423 smb_ofile_t *ofile;
357 424 smb_opipe_t *opipe;
358 425 ksocket_t sock;
359 426 size_t recvcnt = 0;
360 427 int rc;
361 428
362 429 ofile = sr->fid_ofile;
363 430 ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
364 431 opipe = ofile->f_pipe;
|
↓ open down ↓ |
96 lines elided |
↑ open up ↑ |
365 432 SMB_OPIPE_VALID(opipe);
366 433
367 434 mutex_enter(&opipe->p_mutex);
368 435 sock = opipe->p_socket;
369 436 if (sock != NULL)
370 437 ksocket_hold(sock);
371 438 mutex_exit(&opipe->p_mutex);
372 439 if (sock == NULL)
373 440 return (EBADF);
374 441
375 - bzero(&msghdr, sizeof (msghdr));
376 - msghdr.msg_iov = uio->uio_iov;
377 - msghdr.msg_iovlen = uio->uio_iovcnt;
442 + mutex_enter(&sr->sr_mutex);
443 + if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
444 + mutex_exit(&sr->sr_mutex);
445 + rc = EINTR;
446 + goto out;
447 + }
448 + sr->sr_state = SMB_REQ_STATE_WAITING_PIPE;
449 + sr->cancel_method = smb_opipe_cancel;
450 + sr->cancel_arg2 = sock;
451 + mutex_exit(&sr->sr_mutex);
378 452
379 453 /*
380 454 * This should block only if there's no data.
381 455 * A single call to recvmsg does just that.
382 456 * (Intentionaly no recv loop here.)
383 457 */
458 + bzero(&msghdr, sizeof (msghdr));
459 + msghdr.msg_iov = uio->uio_iov;
460 + msghdr.msg_iovlen = uio->uio_iovcnt;
384 461 rc = ksocket_recvmsg(sock, &msghdr, 0,
385 462 &recvcnt, ofile->f_cr);
463 +
464 + mutex_enter(&sr->sr_mutex);
465 + sr->cancel_method = NULL;
466 + sr->cancel_arg2 = NULL;
467 + switch (sr->sr_state) {
468 + case SMB_REQ_STATE_WAITING_PIPE:
469 + sr->sr_state = SMB_REQ_STATE_ACTIVE;
470 + break;
471 + case SMB_REQ_STATE_CANCEL_PENDING:
472 + sr->sr_state = SMB_REQ_STATE_CANCELLED;
473 + rc = EINTR;
474 + break;
475 + default:
476 + /* keep rc from above */
477 + break;
478 + }
479 + mutex_exit(&sr->sr_mutex);
480 +
386 481 if (rc != 0)
387 482 goto out;
388 483
389 484 if (recvcnt == 0) {
390 485 /* Other side closed. */
391 486 rc = EPIPE;
392 487 goto out;
393 488 }
394 489 uio->uio_resid -= recvcnt;
395 490
396 491 out:
397 492 ksocket_rele(sock);
398 493
399 494 return (rc);
400 495 }
401 496
402 497 int
403 498 smb_opipe_ioctl(smb_request_t *sr, int cmd, void *arg, int *rvalp)
404 499 {
405 500 smb_ofile_t *ofile;
406 501 smb_opipe_t *opipe;
407 502 ksocket_t sock;
408 503 int rc;
409 504
410 505 ofile = sr->fid_ofile;
411 506 ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
412 507 opipe = ofile->f_pipe;
413 508 SMB_OPIPE_VALID(opipe);
414 509
415 510 mutex_enter(&opipe->p_mutex);
416 511 sock = opipe->p_socket;
417 512 if (sock != NULL)
418 513 ksocket_hold(sock);
419 514 mutex_exit(&opipe->p_mutex);
420 515 if (sock == NULL)
421 516 return (EBADF);
422 517
423 518 rc = ksocket_ioctl(sock, cmd, (intptr_t)arg, rvalp, ofile->f_cr);
424 519
425 520 ksocket_rele(sock);
426 521
427 522 return (rc);
428 523 }
429 524
430 525 /*
431 526 * Get the smb_attr_t for a named pipe.
432 527 * Caller has already cleared to zero.
|
↓ open down ↓ |
37 lines elided |
↑ open up ↑ |
433 528 */
434 529 int
435 530 smb_opipe_getattr(smb_ofile_t *of, smb_attr_t *ap)
436 531 {
437 532
438 533 if (of->f_pipe == NULL)
439 534 return (EINVAL);
440 535
441 536 ap->sa_vattr.va_type = VFIFO;
442 537 ap->sa_vattr.va_nlink = 1;
538 + ap->sa_vattr.va_nodeid = (uintptr_t)of->f_pipe;
443 539 ap->sa_dosattr = FILE_ATTRIBUTE_NORMAL;
444 - ap->sa_allocsz = 0x1000LL;
540 + ap->sa_allocsz = SMB_PIPE_MAX_MSGSIZE;
445 541
446 542 return (0);
447 543 }
448 544
449 545 int
450 546 smb_opipe_getname(smb_ofile_t *of, char *buf, size_t buflen)
451 547 {
452 548 smb_opipe_t *opipe;
453 549
454 550 if ((opipe = of->f_pipe) == NULL)
455 551 return (EINVAL);
456 552
457 553 (void) snprintf(buf, buflen, "\\%s", opipe->p_name);
458 554 return (0);
459 555 }
460 556
461 557 /*
462 - * Handler for smb2_ioctl
558 + * Handle device type FILE_DEVICE_NAMED_PIPE
559 + * for smb2_ioctl
463 560 */
464 561 /* ARGSUSED */
465 562 uint32_t
466 563 smb_opipe_fsctl(smb_request_t *sr, smb_fsctl_t *fsctl)
467 564 {
468 565 uint32_t status;
469 566
567 + if (!STYPE_ISIPC(sr->tid_tree->t_res_type))
568 + return (NT_STATUS_INVALID_DEVICE_REQUEST);
569 +
470 570 switch (fsctl->CtlCode) {
471 571 case FSCTL_PIPE_TRANSCEIVE:
472 572 status = smb_opipe_transceive(sr, fsctl);
473 573 break;
474 574
475 575 case FSCTL_PIPE_PEEK:
476 576 case FSCTL_PIPE_WAIT:
477 577 /* XXX todo */
478 578 status = NT_STATUS_NOT_SUPPORTED;
479 579 break;
480 580
481 581 default:
482 582 ASSERT(!"CtlCode");
483 583 status = NT_STATUS_INTERNAL_ERROR;
484 584 break;
485 585 }
486 586
487 587 return (status);
488 588 }
489 589
490 -static uint32_t
590 +uint32_t
491 591 smb_opipe_transceive(smb_request_t *sr, smb_fsctl_t *fsctl)
492 592 {
493 593 smb_vdb_t vdb;
494 594 smb_ofile_t *ofile;
495 595 struct mbuf *mb;
496 596 uint32_t status;
497 597 int len, rc;
498 598
499 599 /*
500 600 * Caller checked that this is the IPC$ share,
501 601 * and that this call has a valid open handle.
502 602 * Just check the type.
503 603 */
504 604 ofile = sr->fid_ofile;
505 605 if (ofile->f_ftype != SMB_FTYPE_MESG_PIPE)
506 606 return (NT_STATUS_INVALID_HANDLE);
507 607
508 608 rc = smb_mbc_decodef(fsctl->in_mbc, "#B",
509 609 fsctl->InputCount, &vdb);
510 610 if (rc != 0) {
511 611 /* Not enough data sent. */
512 612 return (NT_STATUS_INVALID_PARAMETER);
513 613 }
514 614
515 615 rc = smb_opipe_write(sr, &vdb.vdb_uio);
516 616 if (rc != 0)
517 617 return (smb_errno2status(rc));
518 618
519 619 vdb.vdb_tag = 0;
520 620 vdb.vdb_uio.uio_iov = &vdb.vdb_iovec[0];
521 621 vdb.vdb_uio.uio_iovcnt = MAX_IOVEC;
522 622 vdb.vdb_uio.uio_segflg = UIO_SYSSPACE;
523 623 vdb.vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
524 624 vdb.vdb_uio.uio_loffset = (offset_t)0;
525 625 vdb.vdb_uio.uio_resid = fsctl->MaxOutputResp;
526 626 mb = smb_mbuf_allocate(&vdb.vdb_uio);
527 627
528 628 rc = smb_opipe_read(sr, &vdb.vdb_uio);
529 629 if (rc != 0) {
530 630 m_freem(mb);
531 631 return (smb_errno2status(rc));
532 632 }
533 633
534 634 len = fsctl->MaxOutputResp - vdb.vdb_uio.uio_resid;
535 635 smb_mbuf_trim(mb, len);
536 636 MBC_ATTACH_MBUF(fsctl->out_mbc, mb);
537 637
538 638 /*
539 639 * If the output buffer holds a partial pipe message,
540 640 * we're supposed to return NT_STATUS_BUFFER_OVERFLOW.
541 641 * As we don't have message boundary markers, the best
542 642 * we can do is return that status when we have ALL of:
543 643 * Output buffer was < SMB_PIPE_MAX_MSGSIZE
544 644 * We filled the output buffer (resid==0)
545 645 * There's more data (ioctl FIONREAD)
546 646 */
547 647 status = NT_STATUS_SUCCESS;
548 648 if (fsctl->MaxOutputResp < SMB_PIPE_MAX_MSGSIZE &&
549 649 vdb.vdb_uio.uio_resid == 0) {
550 650 int nread = 0, trval;
551 651 rc = smb_opipe_ioctl(sr, FIONREAD, &nread, &trval);
552 652 if (rc == 0 && nread != 0)
553 653 status = NT_STATUS_BUFFER_OVERFLOW;
554 654 }
555 655
556 656 return (status);
557 657 }
|
↓ open down ↓ |
57 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX