Print this page
NEX-19025 CIFS gets confused with filenames containing enhanced Unicode
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
and: (fix build, check-rtime)
NEX-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-4458 Incorrect directory listing response for non-UNICODE clients
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-4029 Hang listing directory with fksmbd
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-3738 Should support SMB2_CAP_LARGE_MTU
Reviewed by: Alek Pinchuk <alek@nexenta.com>
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-3611 CLONE NEX-3550 Replace smb2_enable with max_protocol
Reviewed by: Yuri Pankov <Yuri.Pankov@nexenta.com>
NEX-2353 Codenomicon: SMB2 TC # 448950 - PANIC in SMB2.Compounded-commands...
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-56 extended security NTLMSSP, inbound
SMB-48 Panic with smbtorture raw.scan-eamax
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c
+++ new/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.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 *
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.
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
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 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 *
25 - * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
25 + * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
26 26 */
27 27
28 28 /*
29 29 * SMB mbuf marshaling encode/decode.
30 30 */
31 31
32 32 #include <smbsrv/smb_kproto.h>
33 33
34 34
35 35 #define MALLOC_QUANTUM 80
36 36
37 37 #define DECODE_NO_ERROR 0
38 38 #define DECODE_NO_MORE_DATA 1
39 39 #define DECODE_ALLOCATION_ERROR 2
40 40 #define DECODE_CONVERSION_ERROR 3
41 41
42 -static int mbc_marshal_cstou8(char *, char *, size_t, char *, size_t);
43 42 static int mbc_marshal_make_room(mbuf_chain_t *, int32_t);
44 43 static void mbc_marshal_store_byte(mbuf_chain_t *, uint8_t);
45 44 static int mbc_marshal_put_char(mbuf_chain_t *mbc, uint8_t);
46 45 static int mbc_marshal_put_short(mbuf_chain_t *mbc, uint16_t);
47 46 static int mbc_marshal_put_long(mbuf_chain_t *mbc, uint32_t);
48 47 static int mbc_marshal_put_long_long(mbuf_chain_t *mbc, uint64_t);
49 -static int mbc_marshal_put_ascii_string(mbuf_chain_t *, char *, int);
48 +static int mbc_marshal_put_oem_string(mbuf_chain_t *, char *, int);
50 49 static int mbc_marshal_put_unicode_string(mbuf_chain_t *, char *, int);
51 50 static int mbc_marshal_put_uio(mbuf_chain_t *, struct uio *);
52 51 static int mbc_marshal_put_mbufs(mbuf_chain_t *mbc, mbuf_t *m);
53 52 static int mbc_marshal_put_mbuf_chain(mbuf_chain_t *mbc, mbuf_chain_t *nmbc);
54 53 static uint8_t mbc_marshal_fetch_byte(mbuf_chain_t *mbc);
55 54 static int mbc_marshal_get_char(mbuf_chain_t *mbc, uint8_t *data);
56 55 static int mbc_marshal_get_short(mbuf_chain_t *mbc, uint16_t *data);
57 56 static int mbc_marshal_get_long(mbuf_chain_t *mbc, uint32_t *data);
58 57 static uint64_t qswap(uint64_t ll);
59 58 static int mbc_marshal_get_odd_long_long(mbuf_chain_t *mbc, uint64_t *data);
60 59 static int mbc_marshal_get_long_long(mbuf_chain_t *mbc, uint64_t *data);
61 -static int mbc_marshal_get_ascii_string(smb_request_t *, mbuf_chain_t *,
62 - uint8_t **ascii, int);
60 +static int mbc_marshal_get_oem_string(smb_request_t *, mbuf_chain_t *,
61 + char **, int);
63 62 static int mbc_marshal_get_unicode_string(smb_request_t *, mbuf_chain_t *,
64 - uint8_t **, int);
63 + char **, int);
65 64 static int mbc_marshal_get_mbufs(mbuf_chain_t *, int32_t, mbuf_t **);
66 65 static int mbc_marshal_get_mbuf_chain(mbuf_chain_t *, int32_t, mbuf_chain_t *);
67 66 static int mbc_marshal_get_uio(mbuf_chain_t *, struct uio *);
68 67 static int mbc_marshal_get_skip(mbuf_chain_t *, uint_t);
69 68
70 69 /*
71 70 * smb_mbc_vdecodef
72 71 *
73 72 * This function reads the contents of the mbc chain passed in under the list
74 73 * of arguments passed in.
75 74 *
76 75 * The format string provides a description of the parameters passed in as well
77 76 * as an action to be taken by smb_mbc_vdecodef().
78 77 *
79 78 * % Pointer to an SMB request structure (smb_request_t *). There
80 79 * should be only one of these in the string.
81 80 *
82 81 * C Pointer to an mbuf chain. Copy to that mbuf chain the number of
83 82 * bytes specified (number preceding C).
84 83 *
85 84 * m Pointer to an mbuf. Copy to that mbuf the number of bytes
86 85 * specified (number preceding m).
87 86 *
88 87 * M Read the 32 bit value at the current location of the mbuf chain
89 88 * and check if it matches the signature of an SMB1 request (SMBx).
90 89 *
91 90 * N Read the 32 bit value at the current location of the mbuf chain
92 91 * and check if it matches the signature of an SMB2 request (SMBx).
93 92 *
94 93 * b Pointer to a buffer. Copy to that buffer the number of bytes
95 94 * specified (number preceding b).
96 95 *
97 96 * c Same as 'b'.
98 97 *
99 98 * w Pointer to a word (16bit value). Copy the next 16bit value into
100 99 * that location.
101 100 *
102 101 * l Pointer to a long (32bit value). Copy the next 32bit value into
103 102 * that location.
104 103 *
105 104 * q Pointer to a quad (64bit value). Copy the next 64bit value into
106 105 * that location.
107 106 *
108 107 * Q Same as above with a call to qswap().
109 108 *
110 109 * B Pointer to a vardata_block structure. That structure is used to
111 110 * retrieve data from the mbuf chain (an iovec type structure is
112 111 * embedded in a vardata_block).
113 112 *
114 113 * D Pointer to a vardata_block structure. That structure is used to
115 114 * retrieve data from the mbuf chain, however, two fields of the
116 115 * vardata_block structure (tag and len) are first initialized
117 116 * using the mbuf chain itself.
118 117 *
119 118 * V Same as 'D'.
120 119 *
121 120 * L
122 121 *
123 122 * A
124 123 *
125 124 * P Same as 'A'
126 125 *
127 126 * S Same as 'A'
128 127 *
129 128 * u Pointer to a string pointer. Allocate memory and retrieve the
130 129 * string at the current location in the mbuf chain. Store the
131 130 * address to the buffer allocated at the address specified by
132 131 * the pointer. In addition if an sr was passed and it indicates
133 132 * that the string is an unicode string, convert it.
134 133 *
135 134 * s Same as 'u' without convertion.
136 135 *
137 136 * U Same as 'u'. The string to retrieve is unicode.
138 137 *
139 138 * y Pointer to a 32bit value. Read the dos time at the current mbuf
140 139 * chain location, convert it to unix time and store it at the
141 140 * location indicated by the pointer.
142 141 *
143 142 * Y Same as 'y' bt the dos time coded in the mbuf chain is inverted.
144 143 *
|
↓ open down ↓ |
70 lines elided |
↑ open up ↑ |
145 144 * . Skip the number of bytes indicated by the number preceding '.'.
146 145 *
147 146 * , Same as '.' but take in account it is an unicode string.
148 147 */
149 148 int
150 149 smb_mbc_vdecodef(mbuf_chain_t *mbc, const char *fmt, va_list ap)
151 150 {
152 151 uint8_t c;
153 152 uint8_t cval;
154 153 uint8_t *cvalp;
155 - uint8_t **cvalpp;
154 + char **charpp;
156 155 uint16_t wval;
157 156 uint16_t *wvalp;
158 157 uint32_t *lvalp;
159 158 uint64_t *llvalp;
160 159 smb_vdb_t *vdp;
161 160 smb_request_t *sr = NULL;
162 161 uint32_t lval;
163 162 int unicode = 0;
164 163 int repc;
165 164 boolean_t repc_specified;
166 165
167 166 while ((c = *fmt++) != 0) {
168 167 repc_specified = B_FALSE;
169 168 repc = 1;
170 169
171 170 if ('0' <= c && c <= '9') {
172 171 repc = 0;
173 172 do {
174 173 repc = repc * 10 + c - '0';
175 174 c = *fmt++;
176 175 } while ('0' <= c && c <= '9');
177 176 repc_specified = B_TRUE;
178 177 } else if (c == '#') {
179 178 repc = va_arg(ap, int);
180 179 c = *fmt++;
181 180 repc_specified = B_TRUE;
182 181 }
183 182
184 183 switch (c) {
185 184 case '%':
186 185 sr = va_arg(ap, struct smb_request *);
187 186 if (sr->session->dialect >= SMB_VERS_2_BASE) {
188 187 unicode = 1;
189 188 break;
190 189 }
191 190 unicode = sr->smb_flg2 & SMB_FLAGS2_UNICODE;
192 191 break;
193 192
194 193 case 'C': /* Mbuf_chain */
195 194 if (mbc_marshal_get_mbuf_chain(mbc, repc,
196 195 va_arg(ap, mbuf_chain_t *)) != 0)
197 196 return (-1);
198 197 break;
199 198
200 199 case 'm': /* struct_mbuf */
201 200 if (mbc_marshal_get_mbufs(mbc, repc,
202 201 va_arg(ap, mbuf_t **)) != 0)
203 202 return (-1);
204 203 break;
205 204
206 205 case 'M':
207 206 if (mbc_marshal_get_long(mbc, &lval) != 0)
208 207 return (-1);
209 208 if (lval != 0x424D53FF) /* 0xFF S M B */
210 209 return (-1);
211 210 break;
212 211
213 212 case 'N':
214 213 if (mbc_marshal_get_long(mbc, &lval) != 0)
215 214 return (-1);
216 215 if (lval != 0x424D53FE) /* 0xFE S M B */
217 216 return (-1);
218 217 break;
219 218
220 219 case 'b':
221 220 case 'c':
222 221 cvalp = va_arg(ap, uint8_t *);
223 222 if (MBC_ROOM_FOR(mbc, repc) == 0)
224 223 /* Data will never be available */
225 224 return (-1);
226 225
227 226 while (repc-- > 0)
228 227 *cvalp++ = mbc_marshal_fetch_byte(mbc);
229 228 break;
230 229
231 230 case 'w':
232 231 wvalp = va_arg(ap, uint16_t *);
233 232 while (repc-- > 0)
234 233 if (mbc_marshal_get_short(mbc, wvalp++) != 0)
235 234 return (-1);
236 235 break;
237 236
238 237 case 'l':
239 238 lvalp = va_arg(ap, uint32_t *);
240 239 while (repc-- > 0)
241 240 if (mbc_marshal_get_long(mbc, lvalp++) != 0)
242 241 return (-1);
243 242 break;
244 243
245 244 case 'q':
246 245 llvalp = va_arg(ap, uint64_t *);
247 246 while (repc-- > 0)
248 247 if (mbc_marshal_get_long_long(
249 248 mbc, llvalp++) != 0)
250 249 return (-1);
251 250 break;
252 251
253 252 case 'Q':
254 253 llvalp = va_arg(ap, uint64_t *);
255 254 while (repc-- > 0)
256 255 if (mbc_marshal_get_odd_long_long(
257 256 mbc, llvalp++) != 0)
258 257 return (-1);
259 258 break;
260 259
261 260 case 'B':
262 261 vdp = va_arg(ap, struct vardata_block *);
263 262 vdp->vdb_tag = 0;
264 263 vdp->vdb_len = repc;
265 264 vdp->vdb_uio.uio_iov = &vdp->vdb_iovec[0];
266 265 vdp->vdb_uio.uio_iovcnt = MAX_IOVEC;
267 266 vdp->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
268 267 vdp->vdb_uio.uio_resid = repc;
269 268 if (mbc_marshal_get_uio(mbc, &vdp->vdb_uio) != 0)
270 269 return (-1);
271 270 break;
272 271
273 272 case 'D':
274 273 case 'V':
275 274 vdp = va_arg(ap, struct vardata_block *);
276 275 if (mbc_marshal_get_char(mbc, &vdp->vdb_tag) != 0)
277 276 return (-1);
278 277 if (mbc_marshal_get_short(mbc, &wval) != 0)
279 278 return (-1);
280 279 vdp->vdb_len = (uint32_t)wval;
281 280 vdp->vdb_uio.uio_iov = &vdp->vdb_iovec[0];
282 281 vdp->vdb_uio.uio_iovcnt = MAX_IOVEC;
283 282 vdp->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
284 283 vdp->vdb_uio.uio_resid = vdp->vdb_len;
285 284 if (vdp->vdb_len != 0) {
286 285 if (mbc_marshal_get_uio(mbc,
|
↓ open down ↓ |
121 lines elided |
↑ open up ↑ |
287 286 &vdp->vdb_uio) != 0)
288 287 return (-1);
289 288 }
290 289 break;
291 290
292 291 case 'L':
293 292 if (mbc_marshal_get_char(mbc, &cval) != 0)
294 293 return (-1);
295 294 if (cval != 2)
296 295 return (-1);
297 - goto ascii_conversion;
296 + goto oem_conversion;
298 297
299 298 case 'A':
300 299 case 'S':
301 300 if (mbc_marshal_get_char(mbc, &cval) != 0)
302 301 return (-1);
303 302 if (((c == 'A' || c == 'S') && cval != 4) ||
304 303 (c == 'L' && cval != 2))
305 304 return (-1);
306 305 /* FALLTHROUGH */
307 306
308 307 case 'u': /* Convert from unicode if flags are set */
309 308 if (unicode)
310 309 goto unicode_translation;
311 310 /* FALLTHROUGH */
312 311
313 - case 's':
314 -ascii_conversion:
312 + case 's': /* get OEM string */
313 +oem_conversion:
315 314 ASSERT(sr != NULL);
316 - cvalpp = va_arg(ap, uint8_t **);
315 + charpp = va_arg(ap, char **);
317 316 if (!repc_specified)
318 317 repc = 0;
319 - if (mbc_marshal_get_ascii_string(sr,
320 - mbc, cvalpp, repc) != 0)
318 + if (mbc_marshal_get_oem_string(sr,
319 + mbc, charpp, repc) != 0)
321 320 return (-1);
322 321 break;
323 322
324 - case 'U': /* Convert from unicode */
323 + case 'U': /* get UTF-16 string */
325 324 unicode_translation:
326 325 ASSERT(sr != 0);
327 - cvalpp = va_arg(ap, uint8_t **);
326 + charpp = va_arg(ap, char **);
328 327 if (!repc_specified)
329 328 repc = 0;
330 - if (mbc->chain_offset & 1)
331 - mbc->chain_offset++;
332 329 if (mbc_marshal_get_unicode_string(sr,
333 - mbc, cvalpp, repc) != 0)
330 + mbc, charpp, repc) != 0)
334 331 return (-1);
335 332 break;
336 333
337 334 case 'Y': /* dos time to unix time tt/dd */
338 335 lvalp = va_arg(ap, uint32_t *);
339 336 while (repc-- > 0) {
340 337 short d, t;
341 338
342 339 if (mbc_marshal_get_short(mbc,
343 340 (uint16_t *)&t) != 0)
344 341 return (-1);
345 342 if (mbc_marshal_get_short(mbc,
346 343 (uint16_t *)&d) != 0)
347 344 return (-1);
348 345 *lvalp++ = smb_time_dos_to_unix(d, t);
349 346 }
350 347 break;
351 348
352 349 case 'y': /* dos time to unix time dd/tt */
353 350 lvalp = va_arg(ap, uint32_t *);
354 351 while (repc-- > 0) {
355 352 short d, t;
356 353
357 354 if (mbc_marshal_get_short(mbc,
358 355 (uint16_t *)&d) != 0)
359 356 return (-1);
360 357 if (mbc_marshal_get_short(mbc,
361 358 (uint16_t *)&t) != 0)
362 359 return (-1);
363 360 *lvalp++ = smb_time_dos_to_unix(d, t);
364 361 }
365 362 break;
366 363
367 364 case ',':
368 365 if (unicode)
369 366 repc *= 2;
370 367 /* FALLTHROUGH */
371 368
372 369 case '.':
373 370 if (mbc_marshal_get_skip(mbc, repc) != 0)
374 371 return (-1);
375 372 break;
376 373
377 374 default:
378 375 ASSERT(0);
379 376 return (-1);
380 377 }
381 378 }
382 379 return (0);
383 380 }
384 381
385 382 /*
386 383 * smb_mbc_decodef
387 384 *
388 385 * This function reads the contents of the mbc chain passed in under the
389 386 * control of the format fmt.
390 387 *
391 388 * (for a description of the format string see smb_mbc_vencodef()).
392 389 */
393 390 int
394 391 smb_mbc_decodef(mbuf_chain_t *mbc, const char *fmt, ...)
395 392 {
396 393 int xx;
397 394 va_list ap;
398 395
399 396 va_start(ap, fmt);
400 397 xx = smb_mbc_vdecodef(mbc, fmt, ap);
401 398 va_end(ap);
402 399 return (xx);
403 400 }
404 401
405 402 /*
406 403 * smb_mbc_peek
407 404 *
408 405 * This function reads the contents of the mbc passed in at the specified offset
409 406 * under the control of the format fmt. The offset of the chain passed in is not
410 407 * modified.
411 408 *
412 409 * (for a description of the format string see smb_mbc_vdecodef()).
413 410 */
414 411 int
415 412 smb_mbc_peek(mbuf_chain_t *mbc, int offset, const char *fmt, ...)
416 413 {
417 414 mbuf_chain_t tmp;
418 415 va_list ap;
419 416 int xx;
420 417
421 418 va_start(ap, fmt);
422 419
423 420 (void) MBC_SHADOW_CHAIN(&tmp, mbc, offset, mbc->max_bytes - offset);
424 421 xx = smb_mbc_vdecodef(&tmp, fmt, ap);
425 422 va_end(ap);
426 423 return (xx);
427 424 }
428 425
429 426 /*
430 427 * smb_mbc_vencodef
431 428 *
432 429 * This function builds a stream of bytes in the mbc chain passed in under the
433 430 * control of the list of arguments passed in.
434 431 *
435 432 * The format string provides a description of the parameters passed in as well
436 433 * as an action to be taken by smb_mbc_vencodef().
437 434 *
438 435 * \b Restore the mbuf chain offset to its initial value.
439 436 *
440 437 * % Pointer to an SMB request structure (smb_request_t *). There
441 438 * should be only one of these in the string. If an sr in present
442 439 * it will be used to determine if unicode conversion should be
443 440 * applied to the strings.
444 441 *
445 442 * C Pointer to an mbuf chain. Copy that mbuf chain into the
446 443 * destination mbuf chain.
447 444 *
448 445 * D Pointer to a vardata_block structure. Copy the data described
449 446 * by that structure into the mbuf chain. The tag field is hard
450 447 * coded to '1'.
451 448 *
452 449 * M Write the SMB1 request signature ('SMBX') into the mbuf chain.
453 450 *
454 451 * N Write the SMB2 request signature ('SMBX') into the mbuf chain.
455 452 *
456 453 * T Pointer to a timestruc_t. Convert the content of the structure
457 454 * into NT time and store the result of the conversion in the
458 455 * mbuf chain.
459 456 *
460 457 * V Same as 'D' but the tag field is hard coded to '5'.
461 458 *
462 459 * b Byte. Store the byte or the nymber of bytes specified into the
463 460 * the mbuf chain. A format string like this "2b" would require 2
464 461 * bytes to be passed in.
465 462 *
466 463 * m Pointer to an mbuf. Copy the contents of the mbuf into the mbuf
467 464 * chain.
468 465 *
469 466 * c Pointer to a buffer. Copy the buffer into the mbuf chain. The
470 467 * size of the buffer is indicated by the number preceding 'c'.
471 468 *
472 469 * w Word (16bit value). Store the word or the number of words
473 470 * specified into the the mbuf chain. A format string like this
474 471 * "2w" would require 2 words to be passed in.
475 472 *
476 473 * l Long (32bit value). Store the long or the number of longs
477 474 * specified into the the mbuf chain. A format string like this
478 475 * "2l" would require 2 longs to be passed in.
479 476 *
480 477 * q Quad (64bit value). Store the quad or the number of quads
481 478 * specified into the the mbuf chain. A format string like this
482 479 * "2q" would require 2 quads to be passed in.
483 480 *
484 481 * L Pointer to a string. Store the string passed in into the mbuf
485 482 * chain preceded with a tag value of '2'.
486 483 *
487 484 * S Pointer to a string. Store the string passed in into the mbuf
488 485 * chain preceded with a tag value of '4'. Applied a unicode
489 486 * conversion is appropriate.
490 487 *
491 488 * A Same as 'S'
492 489 *
493 490 * P Pointer to a string. Store the string passed in into the mbuf
494 491 * chain preceded with a tag value of '5'. Applied a unicode
495 492 * conversion is appropriate.
496 493 *
497 494 * u Pointer to a string. Store the string passed in into the mbuf
498 495 * chain. Applied a unicode conversion is appropriate.
499 496 *
500 497 * s Pointer to a string. Store the string passed in into the mbuf
501 498 * chain.
502 499 *
503 500 * Y Date/Time. Store the Date/Time or the number of Date/Time(s)
504 501 * specified into the the mbuf chain. A format string like this
505 502 * "2Y" would require 2 Date/Time values. The Date/Time is
506 503 * converted to DOS before storing.
507 504 *
508 505 * y Same as 'Y'. The order of Date and Time is reversed.
509 506 *
510 507 * , Character. Store the character or number of character specified
511 508 * into the mbuf chain. A format string like this "2c" would
|
↓ open down ↓ |
168 lines elided |
↑ open up ↑ |
512 509 * require 2 characters to be passed in. A unicode conversion is
513 510 * applied if appropriate.
514 511 *
515 512 * . Same as '`' without unicode conversion.
516 513 *
517 514 * U Align the offset of the mbuf chain on a 16bit boundary.
518 515 */
519 516 int
520 517 smb_mbc_vencodef(mbuf_chain_t *mbc, const char *fmt, va_list ap)
521 518 {
519 + char *charp;
522 520 uint8_t *cvalp;
523 521 timestruc_t *tvp;
524 522 smb_vdb_t *vdp;
525 523 smb_request_t *sr = NULL;
526 524 uint64_t llval;
527 525 int64_t nt_time;
528 526 uint32_t lval;
529 527 uint_t tag;
530 528 int unicode = 0;
531 529 int repc;
532 530 boolean_t repc_specified;
533 531 uint16_t wval;
534 532 uint8_t cval;
535 533 uint8_t c;
536 534
537 535 while ((c = *fmt++) != 0) {
538 536 repc_specified = B_FALSE;
539 537 repc = 1;
540 538
541 539 if ('0' <= c && c <= '9') {
|
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
542 540 repc = 0;
543 541 do {
544 542 repc = repc * 10 + c - '0';
545 543 c = *fmt++;
546 544 } while ('0' <= c && c <= '9');
547 545 repc_specified = B_TRUE;
548 546 } else if (c == '#') {
549 547 repc = va_arg(ap, int);
550 548 c = *fmt++;
551 549 repc_specified = B_TRUE;
552 -
553 550 }
554 551
555 552 switch (c) {
556 553 case '%':
557 554 sr = va_arg(ap, struct smb_request *);
558 555 if (sr->session->dialect >= SMB_VERS_2_BASE) {
559 556 unicode = 1;
560 557 break;
561 558 }
562 559 unicode = sr->smb_flg2 & SMB_FLAGS2_UNICODE;
563 560 break;
564 561
565 562 case 'C': /* Mbuf_chain */
566 563 if (mbc_marshal_put_mbuf_chain(mbc,
567 564 va_arg(ap, mbuf_chain_t *)) != 0)
568 565 return (DECODE_NO_MORE_DATA);
569 566 break;
570 567
571 568 case 'D':
572 569 vdp = va_arg(ap, struct vardata_block *);
573 570
574 571 if (mbc_marshal_put_char(mbc, 1) != 0)
575 572 return (DECODE_NO_MORE_DATA);
576 573 if (mbc_marshal_put_short(mbc, vdp->vdb_len) != 0)
577 574 return (DECODE_NO_MORE_DATA);
578 575 if (mbc_marshal_put_uio(mbc, &vdp->vdb_uio) != 0)
579 576 return (DECODE_NO_MORE_DATA);
580 577 break;
581 578
582 579 case 'M':
583 580 /* 0xFF S M B */
584 581 if (mbc_marshal_put_long(mbc, 0x424D53FF))
585 582 return (DECODE_NO_MORE_DATA);
586 583 break;
587 584
588 585 case 'N':
589 586 /* 0xFE S M B */
590 587 if (mbc_marshal_put_long(mbc, 0x424D53FE))
591 588 return (DECODE_NO_MORE_DATA);
592 589 break;
593 590
594 591 case 'T':
595 592 tvp = va_arg(ap, timestruc_t *);
596 593 nt_time = smb_time_unix_to_nt(tvp);
597 594 if (mbc_marshal_put_long_long(mbc, nt_time) != 0)
598 595 return (DECODE_NO_MORE_DATA);
599 596 break;
600 597
601 598 case 'V':
602 599 vdp = va_arg(ap, struct vardata_block *);
603 600
604 601 if (mbc_marshal_put_char(mbc, 5) != 0)
605 602 return (DECODE_NO_MORE_DATA);
606 603 if (mbc_marshal_put_short(mbc, vdp->vdb_len) != 0)
607 604 return (DECODE_NO_MORE_DATA);
608 605 if (mbc_marshal_put_uio(mbc, &vdp->vdb_uio) != 0)
609 606 return (DECODE_NO_MORE_DATA);
610 607 break;
611 608
612 609 case 'b':
613 610 while (repc-- > 0) {
614 611 cval = va_arg(ap, int);
615 612 if (mbc_marshal_put_char(mbc, cval) != 0)
616 613 return (DECODE_NO_MORE_DATA);
617 614 }
618 615 break;
619 616
620 617 case 'm': /* struct_mbuf */
621 618 if (mbc_marshal_put_mbufs(mbc,
622 619 va_arg(ap, mbuf_t *)) != 0)
623 620 return (DECODE_NO_MORE_DATA);
624 621 break;
625 622
626 623 case 'c':
627 624 cvalp = va_arg(ap, uint8_t *);
628 625 while (repc-- > 0) {
629 626 if (mbc_marshal_put_char(mbc,
630 627 *cvalp++) != 0)
631 628 return (DECODE_NO_MORE_DATA);
632 629 }
633 630 break;
634 631
635 632 case 'w':
636 633 while (repc-- > 0) {
637 634 wval = va_arg(ap, int);
638 635 if (mbc_marshal_put_short(mbc, wval) != 0)
639 636 return (DECODE_NO_MORE_DATA);
640 637 }
641 638 break;
642 639
643 640 case 'l':
644 641 while (repc-- > 0) {
645 642 lval = va_arg(ap, uint32_t);
646 643 if (mbc_marshal_put_long(mbc, lval) != 0)
647 644 return (DECODE_NO_MORE_DATA);
648 645 }
649 646 break;
650 647
651 648 case 'q':
|
↓ open down ↓ |
89 lines elided |
↑ open up ↑ |
652 649 while (repc-- > 0) {
653 650 llval = va_arg(ap, uint64_t);
654 651 if (mbc_marshal_put_long_long(mbc, llval) != 0)
655 652 return (DECODE_NO_MORE_DATA);
656 653 }
657 654 break;
658 655
659 656
660 657 case 'L':
661 658 tag = 2;
662 - goto ascii_conversion;
659 + goto oem_conversion;
663 660
664 661 case 'S':
665 662 case 'A':
666 663 tag = 4;
667 664 goto tagged_str;
668 665
669 666 case 'P':
670 667 tag = 3;
671 668 goto tagged_str;
672 669
673 670 tagged_str:
674 671 if (mbc_marshal_put_char(mbc, tag) != 0)
675 672 return (DECODE_NO_MORE_DATA);
676 673 /* FALLTHROUGH */
677 674
678 675 case 'u': /* Convert from unicode if flags are set */
679 676 if (unicode)
680 677 goto unicode_translation;
681 678 /* FALLTHROUGH */
682 679
683 - case 's': /* ASCII/multibyte string */
684 -ascii_conversion: cvalp = va_arg(ap, uint8_t *);
680 + case 's': /* put OEM string */
681 +oem_conversion:
682 + charp = va_arg(ap, char *);
685 683 if (!repc_specified)
686 684 repc = 0;
687 - if (mbc_marshal_put_ascii_string(mbc,
688 - (char *)cvalp, repc) != 0)
685 + if (mbc_marshal_put_oem_string(mbc,
686 + charp, repc) != 0)
689 687 return (DECODE_NO_MORE_DATA);
690 688 break;
691 689
690 + case 'U': /* put UTF-16 string */
691 +unicode_translation:
692 + charp = va_arg(ap, char *);
693 + if (!repc_specified)
694 + repc = 0;
695 + if (mbc_marshal_put_unicode_string(mbc,
696 + charp, repc) != 0)
697 + return (DECODE_NO_MORE_DATA);
698 + break;
699 +
692 700 case 'Y': /* int32_t, encode dos date/time */
693 701 while (repc-- > 0) {
694 702 uint16_t d, t;
695 703
696 704 lval = va_arg(ap, uint32_t);
697 705 smb_time_unix_to_dos(lval,
698 706 (short *)&d, (short *)&t);
699 707 if (mbc_marshal_put_short(mbc, t) != 0)
700 708 return (DECODE_NO_MORE_DATA);
701 709 if (mbc_marshal_put_short(mbc, d) != 0)
702 710 return (DECODE_NO_MORE_DATA);
703 711 }
704 712 break;
705 713
706 714 case 'y': /* int32_t, encode dos date/time */
707 715 while (repc-- > 0) {
708 716 uint16_t d, t;
709 717
710 718 lval = va_arg(ap, uint32_t);
711 719 smb_time_unix_to_dos(lval,
712 720 (short *)&d, (short *)&t);
713 721 if (mbc_marshal_put_short(mbc, d) != 0)
714 722 return (DECODE_NO_MORE_DATA);
715 723 if (mbc_marshal_put_short(mbc, t) != 0)
716 724 return (DECODE_NO_MORE_DATA);
717 725 }
718 726 break;
719 727
720 728 case ',':
|
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
721 729 if (unicode)
722 730 repc *= 2;
723 731 /* FALLTHROUGH */
724 732
725 733 case '.':
726 734 while (repc-- > 0)
727 735 if (mbc_marshal_put_char(mbc, 0) != 0)
728 736 return (DECODE_NO_MORE_DATA);
729 737 break;
730 738
731 - case 'U': /* Convert to unicode, align to word boundary */
732 -unicode_translation:
733 - if (mbc->chain_offset & 1)
734 - mbc->chain_offset++;
735 - cvalp = va_arg(ap, uint8_t *);
736 - if (!repc_specified)
737 - repc = 0;
738 - if (mbc_marshal_put_unicode_string(mbc,
739 - (char *)cvalp, repc) != 0)
740 - return (DECODE_NO_MORE_DATA);
741 - break;
742 -
743 739 default:
744 740 ASSERT(0);
745 741 return (-1);
746 742 }
747 743 }
748 744 return (0);
749 745 }
750 746
751 747 /*
752 748 * smb_mbc_encodef
753 749 *
754 750 * This function builds a stream of bytes in the mbc chain passed in under the
755 751 * control of the format fmt.
756 752 *
757 753 * (for a description of the format string see smb_mbc_vencodef()).
758 754 */
759 755 int
760 756 smb_mbc_encodef(mbuf_chain_t *mbc, const char *fmt, ...)
761 757 {
762 758 int rc;
763 759 va_list ap;
764 760
765 761 va_start(ap, fmt);
766 762 rc = smb_mbc_vencodef(mbc, fmt, ap);
767 763 va_end(ap);
768 764 return (rc);
769 765 }
770 766
771 767 /*
772 768 * smb_mbc_poke
773 769 *
774 770 * This function writes a stream of bytes in the mbc passed in at the specified
775 771 * offset under the control of the format fmt. The offset of the chain passed in
776 772 * is not modified.
777 773 *
778 774 * (for a description of the format string see smb_mbc_vencodef()).
779 775 */
780 776 int
781 777 smb_mbc_poke(mbuf_chain_t *mbc, int offset, const char *fmt, ...)
782 778 {
783 779 int len, rc;
784 780 mbuf_chain_t tmp;
785 781 va_list ap;
786 782
787 783 if ((len = mbc->max_bytes - offset) < 0)
788 784 return (DECODE_NO_MORE_DATA);
789 785 rc = MBC_SHADOW_CHAIN(&tmp, mbc, offset, len);
790 786 if (rc)
791 787 return (DECODE_NO_MORE_DATA);
792 788
793 789 va_start(ap, fmt);
794 790 rc = smb_mbc_vencodef(&tmp, fmt, ap);
795 791 va_end(ap);
796 792
797 793 return (rc);
798 794 }
799 795
800 796 /*
801 797 * Copy data from the src mbuf chain to the dst mbuf chain,
802 798 * at the given offset in the src and current offset in dst,
803 799 * for copy_len bytes. Does NOT update src->chain_offset.
804 800 */
805 801 int
806 802 smb_mbc_copy(mbuf_chain_t *dst_mbc, const mbuf_chain_t *src_mbc,
807 803 int copy_offset, int copy_len)
808 804 {
809 805 mbuf_t *src_m;
810 806 int offset, len;
811 807 int rc;
812 808
813 809 if (copy_len <= 0)
814 810 return (0);
815 811 if (copy_offset < 0)
816 812 return (EINVAL);
817 813 if ((copy_offset + copy_len) > src_mbc->max_bytes)
818 814 return (EMSGSIZE);
819 815
820 816 /*
821 817 * Advance to the src mbuf where we start copying.
822 818 */
823 819 offset = copy_offset;
824 820 src_m = src_mbc->chain;
825 821 while (src_m && offset >= src_m->m_len) {
826 822 offset -= src_m->m_len;
827 823 src_m = src_m->m_next;
828 824 }
829 825 if (src_m == NULL)
830 826 return (EFAULT);
831 827
832 828 /*
833 829 * Copy the first part, which may start somewhere past
834 830 * the beginning of the current mbuf.
835 831 */
836 832 len = src_m->m_len - offset;
837 833 if (len > copy_len)
838 834 len = copy_len;
839 835 rc = smb_mbc_put_mem(dst_mbc, src_m->m_data + offset, len);
840 836 if (rc != 0)
841 837 return (rc);
842 838 copy_len -= len;
843 839
844 840 /*
845 841 * Copy remaining mbufs...
846 842 */
847 843 while (copy_len > 0) {
848 844 src_m = src_m->m_next;
849 845 if (src_m == NULL)
850 846 break;
851 847 len = src_m->m_len;
852 848 if (len > copy_len)
853 849 len = copy_len;
854 850 rc = smb_mbc_put_mem(dst_mbc, src_m->m_data, len);
855 851 copy_len -= len;
856 852 }
857 853
858 854 return (0);
859 855 }
860 856
861 857 /*
862 858 * Copy data from the passed memory buffer into the mbuf chain
863 859 * at the current offset.
864 860 */
865 861 int
866 862 smb_mbc_put_mem(mbuf_chain_t *mbc, void *vmem, int mem_len)
867 863 {
868 864 caddr_t mem = vmem;
869 865 mbuf_t *m;
870 866 int32_t offset, tlen;
871 867 int rc;
872 868
873 869 if (mem_len <= 0)
874 870 return (0);
875 871
876 872 if ((rc = mbc_marshal_make_room(mbc, mem_len)) != 0)
877 873 return (rc);
878 874
879 875 /*
880 876 * Advance to the dst mbuf where we start copying.
881 877 * Allocations were done by _make_room().
882 878 */
883 879 offset = mbc->chain_offset;
884 880 m = mbc->chain;
885 881 while (offset >= m->m_len) {
886 882 ASSERT(m->m_len > 0);
887 883 offset -= m->m_len;
888 884 m = m->m_next;
889 885 }
890 886
891 887 /*
892 888 * Copy the first part, which may start somewhere past
893 889 * the beginning of the current mbuf.
894 890 */
895 891 tlen = m->m_len - offset;
896 892 if (tlen > mem_len)
897 893 tlen = mem_len;
898 894 bcopy(mem, m->m_data + offset, tlen);
899 895 mbc->chain_offset += tlen;
900 896 mem += tlen;
901 897 mem_len -= tlen;
902 898
903 899 /*
904 900 * Copy remaining mem into mbufs. These all start
905 901 * at the beginning of each mbuf, and the last may
906 902 * end somewhere short of m_len.
907 903 */
908 904 while (mem_len > 0) {
909 905 m = m->m_next;
910 906 tlen = m->m_len;
911 907 if (tlen > mem_len)
912 908 tlen = mem_len;
|
↓ open down ↓ |
160 lines elided |
↑ open up ↑ |
913 909 bcopy(mem, m->m_data, tlen);
914 910 mbc->chain_offset += tlen;
915 911 mem += tlen;
916 912 mem_len -= tlen;
917 913 }
918 914
919 915 return (0);
920 916 }
921 917
922 918 /*
919 + * Put padding sufficient to align to A, where
920 + * A is some power of 2 greater than zero.
921 + */
922 +int
923 +smb_mbc_put_align(mbuf_chain_t *mbc, int align)
924 +{
925 + int mask = align - 1;
926 + int padsz;
927 +
928 + ASSERT(align > 0 && (align & mask) == 0);
929 + if ((mbc->chain_offset & mask) == 0)
930 + return (0);
931 + padsz = align - (mbc->chain_offset & mask);
932 + return (smb_mbc_encodef(mbc, "#.", padsz));
933 +}
934 +
935 +/*
923 936 * Put data into mbuf chain allocating as needed.
924 937 * Adds room to end of mbuf chain if needed.
925 938 */
926 939 static int
927 940 mbc_marshal_make_room(mbuf_chain_t *mbc, int32_t bytes_needed)
928 941 {
929 942 mbuf_t *m;
930 943 mbuf_t *l;
931 944 int32_t bytes_available;
932 945
933 946 bytes_needed += mbc->chain_offset;
934 947 if (bytes_needed > mbc->max_bytes)
935 948 return (EMSGSIZE);
936 949
937 950 if ((m = mbc->chain) == 0) {
938 951 MGET(m, M_WAIT, MT_DATA);
939 952 m->m_len = 0;
940 953 MCLGET(m, M_WAIT);
941 954 mbc->chain = m;
942 955 /* xxxx */
943 956 /* ^ */
944 957 }
945 958
946 959 /* ---- ----- --xx ---xxx */
947 960 /* ^ */
948 961
949 962 l = 0;
950 963 while ((m != 0) && (bytes_needed >= m->m_len)) {
951 964 l = m;
952 965 bytes_needed -= m->m_len;
953 966 m = m->m_next;
954 967 }
955 968
956 969 if ((bytes_needed == 0) || (m != 0)) {
957 970 /* We have enough room already */
958 971 return (0);
959 972 }
960 973
961 974 /* ---- ----- --xx ---xxx */
962 975 /* ^ */
963 976 /* Back up to start of last mbuf */
964 977 m = l;
965 978 bytes_needed += m->m_len;
966 979
967 980 /* ---- ----- --xx ---xxx */
968 981 /* ^ */
969 982
970 983 bytes_available = (m->m_flags & M_EXT) ?
971 984 m->m_ext.ext_size : MLEN;
972 985
973 986 /* ---- ----- --xx ---xxx */
974 987 /* ^ */
975 988 while ((bytes_needed != 0) && (bytes_needed > bytes_available)) {
976 989 m->m_len = bytes_available;
977 990 bytes_needed -= m->m_len;
978 991 /* ---- ----- --xx ------ */
979 992 /* ^ */
980 993
981 994 MGET(m->m_next, M_WAIT, MT_DATA);
982 995 m = m->m_next;
983 996 m->m_len = 0;
984 997 MCLGET(m, M_WAIT);
985 998
986 999 ASSERT((m->m_flags & M_EXT) != 0);
987 1000 bytes_available = m->m_ext.ext_size;
988 1001
989 1002 /* ---- ----- --xx ------ xxxx */
990 1003 /* ^ */
991 1004 }
992 1005
993 1006 /* ---- ----- --xx ------ xxxx */
994 1007 /* ^ */
995 1008 /* Expand last tail as needed */
996 1009 if (m->m_len <= bytes_needed) {
997 1010 m->m_len = bytes_needed;
998 1011 /* ---- ----- --xx ------ --xx */
999 1012 /* ^ */
1000 1013 }
1001 1014
1002 1015 return (0);
1003 1016 }
1004 1017
1005 1018 static void
1006 1019 mbc_marshal_store_byte(mbuf_chain_t *mbc, uint8_t data)
1007 1020 {
1008 1021 mbuf_t *m = mbc->chain;
1009 1022 int32_t cur_offset = mbc->chain_offset;
1010 1023
1011 1024 /*
1012 1025 * Scan forward looking for the last data currently in chain.
1013 1026 */
1014 1027 while (cur_offset >= m->m_len) {
1015 1028 cur_offset -= m->m_len;
1016 1029 m = m->m_next;
1017 1030 }
1018 1031 ((char *)m->m_data)[cur_offset] = data;
1019 1032 mbc->chain_offset++;
1020 1033 }
1021 1034
1022 1035 static int
1023 1036 mbc_marshal_put_char(mbuf_chain_t *mbc, uint8_t data)
1024 1037 {
1025 1038 if (mbc_marshal_make_room(mbc, sizeof (char)) != 0)
1026 1039 return (DECODE_NO_MORE_DATA);
1027 1040 mbc_marshal_store_byte(mbc, data);
1028 1041 return (0);
1029 1042 }
1030 1043
1031 1044 static int
1032 1045 mbc_marshal_put_short(mbuf_chain_t *mbc, uint16_t data)
1033 1046 {
1034 1047 if (mbc_marshal_make_room(mbc, sizeof (short)))
1035 1048 return (DECODE_NO_MORE_DATA);
1036 1049 mbc_marshal_store_byte(mbc, data);
1037 1050 mbc_marshal_store_byte(mbc, data >> 8);
1038 1051 return (0);
1039 1052 }
1040 1053
1041 1054 static int
1042 1055 mbc_marshal_put_long(mbuf_chain_t *mbc, uint32_t data)
1043 1056 {
1044 1057 if (mbc_marshal_make_room(mbc, sizeof (int32_t)))
1045 1058 return (DECODE_NO_MORE_DATA);
1046 1059 mbc_marshal_store_byte(mbc, data);
1047 1060 mbc_marshal_store_byte(mbc, data >> 8);
1048 1061 mbc_marshal_store_byte(mbc, data >> 16);
1049 1062 mbc_marshal_store_byte(mbc, data >> 24);
1050 1063 return (0);
1051 1064 }
1052 1065
1053 1066 static int
1054 1067 mbc_marshal_put_long_long(mbuf_chain_t *mbc, uint64_t data)
1055 1068 {
1056 1069 if (mbc_marshal_make_room(mbc, sizeof (int64_t)))
1057 1070 return (DECODE_NO_MORE_DATA);
1058 1071
1059 1072 mbc_marshal_store_byte(mbc, data);
1060 1073 mbc_marshal_store_byte(mbc, data >> 8);
|
↓ open down ↓ |
128 lines elided |
↑ open up ↑ |
1061 1074 mbc_marshal_store_byte(mbc, data >> 16);
1062 1075 mbc_marshal_store_byte(mbc, data >> 24);
1063 1076 mbc_marshal_store_byte(mbc, data >> 32);
1064 1077 mbc_marshal_store_byte(mbc, data >> 40);
1065 1078 mbc_marshal_store_byte(mbc, data >> 48);
1066 1079 mbc_marshal_store_byte(mbc, data >> 56);
1067 1080 return (0);
1068 1081 }
1069 1082
1070 1083 /*
1071 - * When need to convert from UTF-8 (internal format) to a single
1072 - * byte string (external format ) when marshalling a string.
1084 + * Marshal a UTF-8 string (str) into mbc, converting to OEM codeset.
1085 + * Also write a null unless the repc count limits the length we put.
1086 + * When (repc > 0) the length we marshal must be exactly repc, and
1087 + * truncate or pad the mbc data as necessary.
1088 + * See also: msgbuf_put_oem_string
1073 1089 */
1074 1090 static int
1075 -mbc_marshal_put_ascii_string(mbuf_chain_t *mbc, char *mbs, int repc)
1091 +mbc_marshal_put_oem_string(mbuf_chain_t *mbc, char *mbs, int repc)
1076 1092 {
1077 - smb_wchar_t wide_char;
1078 - int nbytes;
1079 - int length;
1093 + uint8_t *oembuf = NULL;
1094 + uint8_t *s;
1095 + int oemlen;
1096 + int rlen;
1097 + int rc;
1080 1098
1081 - if ((length = smb_sbequiv_strlen(mbs)) == -1)
1099 + /*
1100 + * Compute length of converted OEM string,
1101 + * NOT including null terminator
1102 + */
1103 + if ((oemlen = smb_sbequiv_strlen(mbs)) == -1)
1082 1104 return (DECODE_NO_MORE_DATA);
1083 1105
1084 - length += sizeof (char);
1085 -
1086 - if ((repc > 0) && (repc < length))
1087 - length = repc;
1088 - if (mbc_marshal_make_room(mbc, length))
1106 + /*
1107 + * If repc not specified, put whole string + NULL,
1108 + * otherwise will truncate or pad as needed.
1109 + */
1110 + if (repc <= 0)
1111 + repc = oemlen + 1;
1112 + if (mbc_marshal_make_room(mbc, repc))
1089 1113 return (DECODE_NO_MORE_DATA);
1090 1114
1091 - while (*mbs) {
1092 - /*
1093 - * We should restore oem chars here.
1094 - */
1095 - nbytes = smb_mbtowc(&wide_char, mbs, MTS_MB_CHAR_MAX);
1096 - if (nbytes == -1)
1097 - return (DECODE_NO_MORE_DATA);
1115 + /*
1116 + * Convert into a temporary buffer
1117 + * Free oembuf before return.
1118 + */
1119 + oembuf = smb_mem_zalloc(oemlen + 1);
1120 + ASSERT(oembuf != NULL);
1121 + rlen = smb_mbstooem(oembuf, mbs, oemlen);
1122 + if (rlen < 0) {
1123 + rc = DECODE_NO_MORE_DATA;
1124 + goto out;
1125 + }
1126 + if (rlen > oemlen)
1127 + rlen = oemlen;
1128 + oembuf[rlen] = '\0';
1098 1129
1099 - mbc_marshal_store_byte(mbc, (uint8_t)wide_char);
1100 -
1101 - if (wide_char & 0xFF00)
1102 - mbc_marshal_store_byte(mbc, wide_char >> 8);
1103 -
1104 - mbs += nbytes;
1130 + /*
1131 + * Copy the converted string into the message,
1132 + * truncated or paded as required.
1133 + */
1134 + s = oembuf;
1135 + while (repc > 0) {
1136 + mbc_marshal_store_byte(mbc, *s);
1137 + if (*s != '\0')
1138 + s++;
1139 + repc--;
1105 1140 }
1141 + rc = 0;
1106 1142
1107 - mbc_marshal_store_byte(mbc, 0);
1108 - return (0);
1143 +out:
1144 + if (oembuf != NULL)
1145 + smb_mem_free(oembuf);
1146 + return (rc);
1109 1147 }
1110 1148
1149 +/*
1150 + * Marshal a UTF-8 string (str) into mbc, converting to UTF-16.
1151 + * Also write a null unless the repc count limits the length.
1152 + * When (repc > 0) the length we marshal must be exactly repc,
1153 + * and truncate or pad the mbc data as necessary.
1154 + * See also: msgbuf_put_unicode_string
1155 + */
1111 1156 static int
1112 -mbc_marshal_put_unicode_string(mbuf_chain_t *mbc, char *ascii, int repc)
1157 +mbc_marshal_put_unicode_string(mbuf_chain_t *mbc, char *mbs, int repc)
1113 1158 {
1114 - smb_wchar_t wchar;
1115 - int consumed;
1116 - int length;
1159 + smb_wchar_t *wcsbuf = NULL;
1160 + smb_wchar_t *wp;
1161 + size_t wcslen, wcsbytes;
1162 + size_t rlen;
1163 + int rc;
1117 1164
1118 - if ((length = smb_wcequiv_strlen(ascii)) == -1)
1165 + /* align to word boundary */
1166 + if (mbc->chain_offset & 1) {
1167 + if (mbc_marshal_make_room(mbc, 1))
1168 + return (DECODE_NO_MORE_DATA);
1169 + mbc_marshal_store_byte(mbc, 0);
1170 + }
1171 +
1172 + /*
1173 + * Compute length of converted UTF-16 string,
1174 + * NOT including null terminator (in bytes).
1175 + */
1176 + wcsbytes = smb_wcequiv_strlen(mbs);
1177 + if (wcsbytes == (size_t)-1)
1119 1178 return (DECODE_NO_MORE_DATA);
1120 1179
1121 - length += sizeof (smb_wchar_t);
1180 + /*
1181 + * If repc not specified, put whole string + NULL,
1182 + * otherwise will truncate or pad as needed.
1183 + */
1184 + if (repc <= 0)
1185 + repc = wcsbytes + 2;
1186 + if (mbc_marshal_make_room(mbc, repc))
1187 + return (DECODE_NO_MORE_DATA);
1122 1188
1123 - if ((repc > 0) && (repc < length))
1124 - length = repc;
1189 + /*
1190 + * Convert into a temporary buffer
1191 + * Free wcsbuf before return.
1192 + */
1193 + wcslen = wcsbytes / 2;
1194 + wcsbuf = smb_mem_zalloc(wcsbytes + 2);
1195 + ASSERT(wcsbuf != NULL);
1196 + rlen = smb_mbstowcs(wcsbuf, mbs, wcslen);
1197 + if (rlen == (size_t)-1) {
1198 + rc = DECODE_NO_MORE_DATA;
1199 + goto out;
1200 + }
1201 + if (rlen > wcslen)
1202 + rlen = wcslen;
1203 + wcsbuf[rlen] = 0;
1125 1204
1126 - if (mbc_marshal_make_room(mbc, length))
1127 - return (DECODE_NO_MORE_DATA);
1128 - while (length > 0) {
1129 - consumed = smb_mbtowc(&wchar, ascii, MTS_MB_CHAR_MAX);
1130 - if (consumed == -1)
1131 - break; /* Invalid sequence */
1132 - /*
1133 - * Note that consumed will be 0 when the null terminator
1134 - * is encountered and ascii will not be advanced beyond
1135 - * that point. Length will continue to be decremented so
1136 - * we won't get stuck here.
1137 - */
1138 - ascii += consumed;
1205 + /*
1206 + * Copy the converted string into the message,
1207 + * truncated or paded as required. Preserve
1208 + * little-endian order while copying.
1209 + */
1210 + wp = wcsbuf;
1211 + while (repc > 1) {
1212 + smb_wchar_t wchar = LE_IN16(wp);
1139 1213 mbc_marshal_store_byte(mbc, wchar);
1140 1214 mbc_marshal_store_byte(mbc, wchar >> 8);
1141 - length -= sizeof (smb_wchar_t);
1215 + if (wchar != 0)
1216 + wp++;
1217 + repc -= sizeof (smb_wchar_t);
1142 1218 }
1143 - return (0);
1219 + if (repc > 0)
1220 + mbc_marshal_store_byte(mbc, 0);
1221 +
1222 + rc = 0;
1223 +out:
1224 + if (wcsbuf != NULL)
1225 + smb_mem_free(wcsbuf);
1226 + return (rc);
1144 1227 }
1145 1228
1146 1229 static int /*ARGSUSED*/
1147 1230 uiorefnoop(caddr_t p, int size, int adj)
1148 1231 {
1149 1232 return (0);
1150 1233 }
1151 1234
1152 1235 static int
1153 1236 mbc_marshal_put_uio(mbuf_chain_t *mbc, struct uio *uio)
1154 1237 {
1155 1238 mbuf_t **t;
1156 1239 mbuf_t *m = NULL;
1157 1240 struct iovec *iov = uio->uio_iov;
1158 1241 int32_t i, iov_cnt = uio->uio_iovcnt;
1159 1242
1160 1243 iov = uio->uio_iov;
1161 1244 t = &mbc->chain;
1162 1245 for (i = 0; i < iov_cnt; i++) {
1163 1246 MGET(m, M_WAIT, MT_DATA);
1164 1247 m->m_ext.ext_buf = iov->iov_base;
1165 1248 m->m_ext.ext_ref = uiorefnoop;
1166 1249 m->m_data = m->m_ext.ext_buf;
1167 1250 m->m_flags |= M_EXT;
1168 1251 m->m_len = m->m_ext.ext_size = iov->iov_len;
1169 1252 mbc->max_bytes += m->m_len;
1170 1253 m->m_next = 0;
1171 1254 *t = m;
1172 1255 t = &m->m_next;
1173 1256 iov++;
1174 1257 }
1175 1258 return (0);
1176 1259 }
1177 1260
1178 1261 static int
1179 1262 mbc_marshal_put_mbufs(mbuf_chain_t *mbc, mbuf_t *m)
1180 1263 {
1181 1264 mbuf_t *mt;
1182 1265 mbuf_t **t;
1183 1266 int bytes;
1184 1267
1185 1268 if (m != NULL) {
1186 1269 mt = m;
1187 1270 bytes = mt->m_len;
1188 1271 while (mt->m_next != 0) {
1189 1272 mt = mt->m_next;
1190 1273 bytes += mt->m_len;
1191 1274 }
1192 1275 if (bytes != 0) {
1193 1276 t = &mbc->chain;
1194 1277 while (*t != 0) {
1195 1278 bytes += (*t)->m_len;
1196 1279 t = &(*t)->m_next;
1197 1280 }
1198 1281 *t = m;
1199 1282 mbc->chain_offset = bytes;
1200 1283 } else {
1201 1284 m_freem(m);
1202 1285 }
1203 1286 }
1204 1287 return (0);
1205 1288 }
1206 1289
1207 1290 static int
1208 1291 mbc_marshal_put_mbuf_chain(mbuf_chain_t *mbc, mbuf_chain_t *nmbc)
1209 1292 {
1210 1293 if (nmbc->chain != 0) {
1211 1294 if (mbc_marshal_put_mbufs(mbc, nmbc->chain))
1212 1295 return (DECODE_NO_MORE_DATA);
1213 1296 MBC_SETUP(nmbc, nmbc->max_bytes);
1214 1297 }
1215 1298 return (0);
1216 1299 }
1217 1300
1218 1301 static uint8_t
1219 1302 mbc_marshal_fetch_byte(mbuf_chain_t *mbc)
1220 1303 {
1221 1304 uint8_t data;
1222 1305 mbuf_t *m = mbc->chain;
1223 1306 int32_t offset = mbc->chain_offset;
1224 1307
1225 1308 while (offset >= m->m_len) {
1226 1309 offset -= m->m_len;
1227 1310 m = m->m_next;
1228 1311 }
1229 1312 data = ((uint8_t *)m->m_data)[offset];
1230 1313 mbc->chain_offset++;
1231 1314 return (data);
1232 1315 }
1233 1316
1234 1317 static int
1235 1318 mbc_marshal_get_char(mbuf_chain_t *mbc, uint8_t *data)
1236 1319 {
1237 1320 if (MBC_ROOM_FOR(mbc, sizeof (char)) == 0) {
1238 1321 /* Data will never be available */
1239 1322 return (DECODE_NO_MORE_DATA);
1240 1323 }
1241 1324 *data = mbc_marshal_fetch_byte(mbc);
1242 1325 return (0);
1243 1326 }
1244 1327
1245 1328 static int
1246 1329 mbc_marshal_get_short(mbuf_chain_t *mbc, uint16_t *data)
1247 1330 {
1248 1331 uint16_t tmp;
1249 1332 mbuf_t *m = mbc->chain;
1250 1333 int32_t offset = mbc->chain_offset;
1251 1334
1252 1335 if (MBC_ROOM_FOR(mbc, sizeof (short)) == 0) {
1253 1336 /* Data will never be available */
1254 1337 return (DECODE_NO_MORE_DATA);
1255 1338 }
1256 1339
1257 1340 while (offset >= m->m_len) {
1258 1341 offset -= m->m_len;
1259 1342 m = m->m_next;
1260 1343 }
1261 1344 if ((m->m_len - offset) >= sizeof (short)) {
1262 1345 *data = LE_IN16(m->m_data + offset);
1263 1346 mbc->chain_offset += sizeof (short);
1264 1347 } else {
1265 1348 tmp = (uint16_t)mbc_marshal_fetch_byte(mbc);
1266 1349 tmp |= ((uint16_t)mbc_marshal_fetch_byte(mbc)) << 8;
1267 1350 *data = tmp;
1268 1351 }
1269 1352 return (0);
1270 1353 }
1271 1354
1272 1355 static int
1273 1356 mbc_marshal_get_long(mbuf_chain_t *mbc, uint32_t *data)
1274 1357 {
1275 1358 uint32_t tmp;
1276 1359 mbuf_t *m = mbc->chain;
1277 1360 int32_t offset = mbc->chain_offset;
1278 1361
1279 1362 if (MBC_ROOM_FOR(mbc, sizeof (int32_t)) == 0) {
1280 1363 /* Data will never be available */
1281 1364 return (DECODE_NO_MORE_DATA);
1282 1365 }
1283 1366 while (offset >= m->m_len) {
1284 1367 offset -= m->m_len;
1285 1368 m = m->m_next;
1286 1369 }
1287 1370 if ((m->m_len - offset) >= sizeof (int32_t)) {
1288 1371 *data = LE_IN32(m->m_data + offset);
1289 1372 mbc->chain_offset += sizeof (int32_t);
1290 1373 } else {
1291 1374 tmp = (uint32_t)mbc_marshal_fetch_byte(mbc);
1292 1375 tmp |= ((uint32_t)mbc_marshal_fetch_byte(mbc)) << 8;
1293 1376 tmp |= ((uint32_t)mbc_marshal_fetch_byte(mbc)) << 16;
1294 1377 tmp |= ((uint32_t)mbc_marshal_fetch_byte(mbc)) << 24;
1295 1378 *data = tmp;
1296 1379 }
1297 1380 return (0);
1298 1381 }
1299 1382
1300 1383 static uint64_t
1301 1384 qswap(uint64_t ll)
1302 1385 {
1303 1386 uint64_t v;
1304 1387
1305 1388 v = ll >> 32;
1306 1389 v |= ll << 32;
1307 1390
1308 1391 return (v);
1309 1392 }
1310 1393
1311 1394 static int
1312 1395 mbc_marshal_get_odd_long_long(mbuf_chain_t *mbc, uint64_t *data)
1313 1396 {
1314 1397 uint64_t tmp;
1315 1398 mbuf_t *m = mbc->chain;
1316 1399 int32_t offset = mbc->chain_offset;
1317 1400
1318 1401 if (MBC_ROOM_FOR(mbc, sizeof (int64_t)) == 0) {
1319 1402 /* Data will never be available */
1320 1403 return (DECODE_NO_MORE_DATA);
1321 1404 }
1322 1405 while (offset >= m->m_len) {
1323 1406 offset -= m->m_len;
1324 1407 m = m->m_next;
1325 1408 }
1326 1409
1327 1410 if ((m->m_len - offset) >= sizeof (int64_t)) {
1328 1411 *data = qswap(LE_IN64(m->m_data + offset));
1329 1412 mbc->chain_offset += sizeof (int64_t);
1330 1413 } else {
1331 1414 tmp = (uint64_t)mbc_marshal_fetch_byte(mbc) << 32;
1332 1415 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 40;
1333 1416 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 48;
1334 1417 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 56;
1335 1418 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc);
1336 1419 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 8;
1337 1420 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 16;
1338 1421 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 24;
1339 1422
1340 1423 *(uint64_t *)data = tmp;
1341 1424 }
1342 1425 return (0);
1343 1426 }
1344 1427
1345 1428 static int
1346 1429 mbc_marshal_get_long_long(mbuf_chain_t *mbc, uint64_t *data)
1347 1430 {
1348 1431 uint64_t tmp;
1349 1432 mbuf_t *m = mbc->chain;
1350 1433 int32_t offset = mbc->chain_offset;
1351 1434
1352 1435 if (MBC_ROOM_FOR(mbc, sizeof (int64_t)) == 0) {
1353 1436 /* Data will never be available */
1354 1437 return (DECODE_NO_MORE_DATA);
1355 1438 }
1356 1439 while (offset >= m->m_len) {
1357 1440 offset -= m->m_len;
1358 1441 m = m->m_next;
1359 1442 }
1360 1443 if ((m->m_len - offset) >= sizeof (int64_t)) {
1361 1444 *data = LE_IN64(m->m_data + offset);
1362 1445 mbc->chain_offset += sizeof (int64_t);
1363 1446 } else {
1364 1447 tmp = (uint32_t)mbc_marshal_fetch_byte(mbc);
1365 1448 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 8;
1366 1449 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 16;
1367 1450 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 24;
|
↓ open down ↓ |
214 lines elided |
↑ open up ↑ |
1368 1451 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 32;
1369 1452 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 40;
1370 1453 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 48;
1371 1454 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 56;
1372 1455 *(uint64_t *)data = tmp;
1373 1456 }
1374 1457 return (0);
1375 1458 }
1376 1459
1377 1460 /*
1378 - * mbc_marshal_get_ascii_string
1461 + * mbc_marshal_get_oem_string
1379 1462 *
1380 - * The ascii string in smb includes oem chars. Since the
1381 - * system needs utf8 encodes unicode char, conversion is
1382 - * required to convert the oem char to unicode and then
1383 - * to encode the converted wchars to utf8 format.
1384 - * Therefore, the **ascii returned will be in such format
1385 - * instead of the real ASCII format.
1463 + * Decode an OEM string, returning its UTF-8 form in strpp,
1464 + * allocated using smb_srm_zalloc (automatically freed).
1465 + * If max_bytes != 0, consume at most max_bytes of the mbc.
1466 + * See also: msgbuf_get_oem_string
1386 1467 */
1387 1468 static int
1388 -mbc_marshal_get_ascii_string(
1389 - smb_request_t *sr,
1390 - mbuf_chain_t *mbc,
1391 - uint8_t **ascii,
1392 - int max_ascii)
1469 +mbc_marshal_get_oem_string(smb_request_t *sr,
1470 + mbuf_chain_t *mbc, char **strpp, int max_bytes)
1393 1471 {
1394 - char *rcvbuf;
1395 - char *ch;
1396 - int max;
1397 - int length = 0;
1472 + char *mbs;
1473 + uint8_t *oembuf = NULL;
1474 + int oemlen, oemmax;
1475 + int mbsmax;
1476 + int rlen;
1477 + int rc;
1398 1478
1399 - max = MALLOC_QUANTUM;
1400 - rcvbuf = smb_srm_zalloc(sr, max);
1479 + if (max_bytes == 0)
1480 + max_bytes = 0xffff;
1401 1481
1402 - if (max_ascii == 0)
1403 - max_ascii = 0xffff;
1404 -
1405 - ch = rcvbuf;
1482 + /*
1483 + * Get the OtW data into a temporary buffer.
1484 + * Free oembuf before return.
1485 + */
1486 + oemlen = 0;
1487 + oemmax = MALLOC_QUANTUM;
1488 + oembuf = smb_mem_alloc(oemmax);
1406 1489 for (;;) {
1407 - while (length < max) {
1408 - if (max_ascii-- <= 0) {
1409 - *ch++ = 0;
1410 - goto multibyte_encode;
1411 - }
1412 - if (MBC_ROOM_FOR(mbc, sizeof (char)) == 0) {
1413 - /* Data will never be available */
1414 - return (DECODE_NO_MORE_DATA);
1415 - }
1416 - if ((*ch++ = mbc_marshal_fetch_byte(mbc)) == 0)
1417 - goto multibyte_encode;
1418 - length++;
1490 + uint8_t ch;
1491 +
1492 + if (oemlen >= max_bytes)
1493 + break;
1494 + if ((oemlen + 2) >= oemmax) {
1495 + oemmax += MALLOC_QUANTUM;
1496 + oembuf = smb_mem_realloc(oembuf, oemmax);
1419 1497 }
1420 - max += MALLOC_QUANTUM;
1421 - rcvbuf = smb_srm_rezalloc(sr, rcvbuf, max);
1422 - ch = rcvbuf + length;
1498 + if (mbc_marshal_get_char(mbc, &ch) != 0) {
1499 + rc = DECODE_NO_MORE_DATA;
1500 + goto out;
1501 + }
1502 + if (ch == 0)
1503 + break;
1504 + oembuf[oemlen++] = ch;
1423 1505 }
1506 + oembuf[oemlen] = '\0';
1424 1507
1425 -multibyte_encode:
1426 1508 /*
1427 - * UTF-8 encode the string for internal system use.
1509 + * Get the buffer we'll return and convert to UTF-8.
1510 + * May take as much as double the space.
1428 1511 */
1429 - length = strlen(rcvbuf) + 1;
1430 - *ascii = smb_srm_zalloc(sr, length * MTS_MB_CHAR_MAX);
1431 - return (mbc_marshal_cstou8("CP850", (char *)*ascii,
1432 - (size_t)length * MTS_MB_CHAR_MAX, rcvbuf, (size_t)length));
1512 + mbsmax = oemlen * 2;
1513 + mbs = smb_srm_zalloc(sr, mbsmax + 1);
1514 + ASSERT(mbs != NULL);
1515 + rlen = smb_oemtombs(mbs, oembuf, mbsmax);
1516 + if (rlen < 0) {
1517 + rc = DECODE_NO_MORE_DATA;
1518 + goto out;
1519 + }
1520 + if (rlen > mbsmax)
1521 + rlen = mbsmax;
1522 + mbs[rlen] = '\0';
1523 + *strpp = mbs;
1524 + rc = 0;
1525 +
1526 +out:
1527 + if (oembuf != NULL)
1528 + smb_mem_free(oembuf);
1529 + return (rc);
1433 1530 }
1434 1531
1532 +/*
1533 + * mbc_marshal_get_unicode_string
1534 + *
1535 + * Decode a UTF-16 string, returning its UTF-8 form in strpp,
1536 + * allocated using smb_srm_zalloc (automatically freed).
1537 + * If max_bytes != 0, consume at most max_bytes of the mbc.
1538 + * See also: msgbuf_get_unicode_string
1539 + */
1435 1540 static int
1436 1541 mbc_marshal_get_unicode_string(smb_request_t *sr,
1437 - mbuf_chain_t *mbc, uint8_t **ascii, int max_unicode)
1542 + mbuf_chain_t *mbc, char **strpp, int max_bytes)
1438 1543 {
1439 - int max;
1440 - uint16_t wchar;
1441 - char *ch;
1442 - int emitted;
1443 - int length = 0;
1544 + char *mbs;
1545 + uint16_t *wcsbuf = NULL;
1546 + int wcslen; // wchar count
1547 + int wcsmax; // byte count
1548 + size_t mbsmax;
1549 + size_t rlen;
1550 + int rc;
1444 1551
1445 - if (max_unicode == 0)
1446 - max_unicode = 0xffff;
1552 + if (max_bytes == 0)
1553 + max_bytes = 0xffff;
1447 1554
1448 - max = MALLOC_QUANTUM;
1449 - *ascii = smb_srm_zalloc(sr, max);
1555 + /*
1556 + * Unicode strings are always word aligned.
1557 + */
1558 + if (mbc->chain_offset & 1) {
1559 + if (MBC_ROOM_FOR(mbc, sizeof (char)) == 0)
1560 + return (DECODE_NO_MORE_DATA);
1561 + mbc->chain_offset++;
1562 + }
1450 1563
1451 - ch = (char *)*ascii;
1564 + /*
1565 + * Get the OtW data into a temporary buffer.
1566 + * Free wcsbuf before return.
1567 + */
1568 + wcslen = 0;
1569 + wcsmax = MALLOC_QUANTUM;
1570 + wcsbuf = smb_mem_alloc(wcsmax);
1452 1571 for (;;) {
1453 - while ((length + MTS_MB_CHAR_MAX) < max) {
1454 - if (max_unicode <= 0)
1455 - goto done;
1456 - max_unicode -= 2;
1572 + uint16_t wchar;
1457 1573
1458 - if (mbc_marshal_get_short(mbc, &wchar) != 0)
1459 - return (DECODE_NO_MORE_DATA);
1460 -
1461 - if (wchar == 0) goto done;
1462 -
1463 - emitted = smb_wctomb(ch, wchar);
1464 - length += emitted;
1465 - ch += emitted;
1574 + if ((wcslen * 2) >= max_bytes)
1575 + break;
1576 + if (((wcslen * 2) + 4) >= wcsmax) {
1577 + wcsmax += MALLOC_QUANTUM;
1578 + wcsbuf = smb_mem_realloc(wcsbuf, wcsmax);
1466 1579 }
1467 - max += MALLOC_QUANTUM;
1468 - *ascii = smb_srm_rezalloc(sr, *ascii, max);
1469 - ch = (char *)*ascii + length;
1580 + if (mbc_marshal_get_short(mbc, &wchar) != 0) {
1581 + rc = DECODE_NO_MORE_DATA;
1582 + goto out;
1583 + }
1584 + if (wchar == 0)
1585 + break;
1586 + /* Keep in little-endian form. */
1587 + LE_OUT16(wcsbuf + wcslen, wchar);
1588 + wcslen++;
1470 1589 }
1471 -done: *ch = 0;
1472 - return (0);
1590 + wcsbuf[wcslen] = 0;
1591 +
1592 + /*
1593 + * Get the buffer we'll return and convert to UTF-8.
1594 + * May take as much 4X number of wide chars.
1595 + */
1596 + mbsmax = wcslen * MTS_MB_CUR_MAX;
1597 + mbs = smb_srm_zalloc(sr, mbsmax + 1);
1598 + ASSERT(mbs != NULL);
1599 + rlen = smb_wcstombs(mbs, wcsbuf, mbsmax);
1600 + if (rlen == (size_t)-1) {
1601 + rc = DECODE_NO_MORE_DATA;
1602 + goto out;
1603 + }
1604 + if (rlen > mbsmax)
1605 + rlen = mbsmax;
1606 + mbs[rlen] = '\0';
1607 + *strpp = mbs;
1608 + rc = 0;
1609 +
1610 +out:
1611 + if (wcsbuf != NULL)
1612 + smb_mem_free(wcsbuf);
1613 + return (rc);
1473 1614 }
1474 1615
1475 1616 static int /*ARGSUSED*/
1476 1617 mbc_marshal_get_mbufs(mbuf_chain_t *mbc, int32_t bytes, mbuf_t **m)
1477 1618 {
1478 1619 *m = NULL;
1479 1620 if (MBC_ROOM_FOR(mbc, bytes) == 0) {
1480 1621 /* Data will never be available */
1481 1622 return (DECODE_NO_MORE_DATA);
1482 1623 }
1483 1624 /* not yet implemented */
1484 1625 return (-1);
1485 1626 }
1486 1627
1487 1628 static int
1488 1629 mbc_marshal_get_mbuf_chain(mbuf_chain_t *mbc, int32_t bytes, mbuf_chain_t *nmbc)
1489 1630 {
1490 1631 int rc;
1491 1632 mbuf_t *m;
1492 1633
1493 1634 if (bytes == 0) {
1494 1635 /* Get all the rest */
1495 1636 bytes = mbc->max_bytes - mbc->chain_offset;
1496 1637 }
1497 1638
1498 1639 MBC_SETUP(nmbc, mbc->max_bytes);
1499 1640 if ((rc = mbc_marshal_get_mbufs(mbc, bytes, &m)) != 0) {
1500 1641 if (m)
1501 1642 m_freem(m);
1502 1643 return (rc);
1503 1644 }
1504 1645 nmbc->chain = m;
1505 1646 while (m != 0) {
1506 1647 bytes += m->m_len;
1507 1648 m = m->m_next;
1508 1649 }
1509 1650 nmbc->max_bytes = bytes;
1510 1651 return (0);
1511 1652 }
1512 1653
1513 1654 static int
1514 1655 mbc_marshal_get_uio(mbuf_chain_t *mbc, struct uio *uio)
1515 1656 {
1516 1657 int i, offset;
1517 1658 int32_t bytes = uio->uio_resid;
1518 1659 int32_t remainder;
1519 1660 struct iovec *iov;
1520 1661 mbuf_t *m;
1521 1662
1522 1663 /*
1523 1664 * The residual count is tested because in the case of write requests
1524 1665 * with no data (smbtorture RAW-WRITE test will generate that type of
1525 1666 * request) this function is called with a residual count of zero
1526 1667 * bytes.
1527 1668 */
1528 1669 if (bytes != 0) {
1529 1670 iov = uio->uio_iov;
1530 1671 uio->uio_segflg = UIO_SYSSPACE;
1531 1672 uio->uio_extflg = UIO_COPY_DEFAULT;
1532 1673
1533 1674 if (MBC_ROOM_FOR(mbc, bytes) == 0) {
1534 1675 /* Data will never be available */
1535 1676 return (DECODE_NO_MORE_DATA);
1536 1677 }
1537 1678
1538 1679 m = mbc->chain;
1539 1680 offset = mbc->chain_offset;
1540 1681 while (offset >= m->m_len) {
1541 1682 offset -= m->m_len;
1542 1683 m = m->m_next;
1543 1684 ASSERT((offset == 0) || (offset && m));
1544 1685 }
1545 1686
1546 1687 for (i = 0; (bytes > 0) && (i < uio->uio_iovcnt); i++) {
1547 1688 iov[i].iov_base = &m->m_data[offset];
1548 1689 remainder = m->m_len - offset;
1549 1690 if (remainder >= bytes) {
1550 1691 iov[i].iov_len = bytes;
1551 1692 mbc->chain_offset += bytes;
1552 1693 uio->uio_iovcnt = i + 1;
1553 1694 return (0);
1554 1695 }
1555 1696 iov[i].iov_len = remainder;
1556 1697 mbc->chain_offset += remainder;
1557 1698 bytes -= remainder;
1558 1699 m = m->m_next;
1559 1700 offset = 0;
1560 1701 }
1561 1702 return (DECODE_NO_MORE_DATA);
1562 1703 }
|
↓ open down ↓ |
80 lines elided |
↑ open up ↑ |
1563 1704 return (0);
1564 1705 }
1565 1706
1566 1707 static int
1567 1708 mbc_marshal_get_skip(mbuf_chain_t *mbc, uint_t skip)
1568 1709 {
1569 1710 if (MBC_ROOM_FOR(mbc, skip) == 0)
1570 1711 return (DECODE_NO_MORE_DATA);
1571 1712 mbc->chain_offset += skip;
1572 1713 return (0);
1573 -}
1574 -
1575 -/*
1576 - * Converts oem string to UTF-8 string with an output string of max
1577 - * maxconv bytes. The string may be truncated or not null-terminated if
1578 - * there is not enough room.
1579 - *
1580 - * returns -1, cnt (partial conversion) or 0 (success)
1581 - */
1582 -
1583 -static int
1584 -mbc_marshal_cstou8(char *cs, char *outbuf, size_t maxconv,
1585 - char *inbuf, size_t srcbytes)
1586 -{
1587 - kiconv_t t2u;
1588 - size_t inlen = srcbytes;
1589 - size_t outlen = maxconv;
1590 - int err = 0;
1591 - size_t rc;
1592 -
1593 - if ((t2u = kiconv_open("UTF-8", cs)) == (kiconv_t)-1)
1594 - return (-1);
1595 -
1596 - rc = kiconv(t2u, &inbuf, &inlen, &outbuf, &outlen, &err);
1597 - (void) kiconv_close(t2u);
1598 - return ((int)rc);
1599 1714 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX