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 2018-2021 Tintri by DDN, Inc. All rights reserved.
14  */
15 
16 /*
17  * Test putting/getting unicode strings in mbchains.
18  */
19 
20 #include <sys/types.h>
21 #include <sys/debug.h>
22 #include <sys/varargs.h>
23 #include <smbsrv/smb_kproto.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <strings.h>
27 
28 #include "test_defs.h"
29 
30 static char mbsa[] = "A\xef\xbc\xa1.";		// A fwA . (5)
31 static char mbsp[] = "P\xf0\x9f\x92\xa9.";	// P poop . (6)
32 static smb_wchar_t wcsa[] = { 'A', 0xff21, '.', 0 };	// (3)
33 static smb_wchar_t wcsp[] = { 'P', 0xd83d, 0xdca9, '.', 0 }; // (4)
34 
35 smb_session_t test_ssn;
36 smb_request_t test_sr;
37 
38 /*
39  * Put ASCII string with NULL
40  */
41 static void
mbm_put_a0()42 mbm_put_a0()
43 {
44 	uint8_t wire[] = { 'o', 'n', 'e', 0, 42, 0 };
45 	mbuf_chain_t *mbc;
46 	int rc;
47 
48 	mbc = smb_mbc_alloc(100);
49 
50 	rc = smb_mbc_encodef(mbc, "sw", "one", 42);
51 	if (rc != 0) {
52 		printf("Fail: mbm_put_a0 encode\n");
53 		goto out;
54 	}
55 	if (mbc->chain->m_len != 6) {
56 		printf("Fail: mbm_put_a0 len=%d\n",
57 		    mbc->chain->m_len);
58 		return;
59 	}
60 
61 	if (memcmp(mbc->chain->m_data, wire, 6)) {
62 		printf("Fail: mbm_put_a0 cmp:\n");
63 		hexdump((uchar_t *)mbc->chain->m_data, 6);
64 		return;
65 	}
66 
67 	printf("Pass: mbm_put_a0\n");
68 
69 out:
70 	smb_mbc_free(mbc);
71 }
72 
73 /*
74  * Put ASCII string, no NULL
75  */
76 static void
mbm_put_a1()77 mbm_put_a1()
78 {
79 	uint8_t wire[] = { 'o', 'n', 'e', '.', 42, 0 };
80 	mbuf_chain_t *mbc;
81 	int rc;
82 
83 	mbc = smb_mbc_alloc(100);
84 
85 	rc = smb_mbc_encodef(mbc, "4sw", "one.", 42);
86 	if (rc != 0) {
87 		printf("Fail: mbm_put_a1 encode\n");
88 		goto out;
89 	}
90 	if (mbc->chain->m_len != 6) {
91 		printf("Fail: mbm_put_a1 len=%d\n",
92 		    mbc->chain->m_len);
93 		return;
94 	}
95 
96 	if (memcmp(mbc->chain->m_data, wire, 6)) {
97 		printf("Fail: mbm_put_a1 cmp:\n");
98 		hexdump((uchar_t *)mbc->chain->m_data, 6);
99 		return;
100 	}
101 
102 	printf("Pass: mbm_put_a1\n");
103 
104 out:
105 	smb_mbc_free(mbc);
106 }
107 
108 static void
mbm_put_apad()109 mbm_put_apad()
110 {
111 	uint8_t wire[] = { 'o', 'n', 'e', 0, 0 };
112 	mbuf_chain_t *mbc;
113 	int rc;
114 
115 	mbc = smb_mbc_alloc(100);
116 
117 	/* Encode with wire length > strlen */
118 	rc = smb_mbc_encodef(mbc, "5s", "one");
119 	if (rc != 0) {
120 		printf("Fail: mbm_put_apad encode\n");
121 		goto out;
122 	}
123 	if (mbc->chain->m_len != 5) {
124 		printf("Fail: mbm_put_apad len=%d\n",
125 		    mbc->chain->m_len);
126 		return;
127 	}
128 
129 	if (memcmp(mbc->chain->m_data, wire, 5)) {
130 		printf("Fail: mbm_put_apad cmp:\n");
131 		hexdump((uchar_t *)mbc->chain->m_data, 5);
132 		return;
133 	}
134 
135 	printf("Pass: mbm_put_apad\n");
136 
137 out:
138 	smb_mbc_free(mbc);
139 }
140 
141 static void
mbm_put_atrunc1()142 mbm_put_atrunc1()
143 {
144 	uint8_t wire[] = { 'o', 'n', 'e', 't', };
145 	mbuf_chain_t *mbc;
146 	int rc;
147 
148 	mbc = smb_mbc_alloc(100);
149 
150 	/* Encode with wire length < strlen */
151 	rc = smb_mbc_encodef(mbc, "4s", "onetwo");
152 	if (rc != 0) {
153 		printf("Fail: mbm_put_atrunc1 encode\n");
154 		goto out;
155 	}
156 	/* Trunc should put exactly 4 */
157 	if (mbc->chain->m_len != 4) {
158 		printf("Fail: mbm_put_atrunc1 len=%d\n",
159 		    mbc->chain->m_len);
160 		return;
161 	}
162 
163 	if (memcmp(mbc->chain->m_data, wire, 4)) {
164 		printf("Fail: mbm_put_atrunc1 cmp:\n");
165 		hexdump((uchar_t *)mbc->chain->m_data, 4);
166 		return;
167 	}
168 
169 	printf("Pass: mbm_put_atrunc1\n");
170 
171 out:
172 	smb_mbc_free(mbc);
173 }
174 
175 static void
mbm_put_atrunc2()176 mbm_put_atrunc2()
177 {
178 	uint8_t wire[] = { 'o', 'n', 'e', 't', 0 };
179 	mbuf_chain_t *mbc;
180 	int rc;
181 
182 	mbc = smb_mbc_alloc(4);
183 
184 	/* Encode with wire length < strlen */
185 	rc = smb_mbc_encodef(mbc, "s", "onetwo");
186 	if (rc != 1) {
187 		printf("Fail: mbm_put_atrunc2 encode rc=%d\n", rc);
188 		goto out;
189 	}
190 	/* Trunc should put exactly 4 */
191 	if (mbc->chain->m_len != 4) {
192 		printf("Fail: mbm_put_atrunc2 len=%d\n",
193 		    mbc->chain->m_len);
194 		return;
195 	}
196 
197 	if (memcmp(mbc->chain->m_data, wire, 5)) {
198 		printf("Fail: mbm_put_atrunc2 cmp:\n");
199 		hexdump((uchar_t *)mbc->chain->m_data, 4);
200 		return;
201 	}
202 
203 	printf("Pass: mbm_put_atrunc2\n");
204 
205 out:
206 	smb_mbc_free(mbc);
207 }
208 
209 /*
210  * Put unicode string with NULL
211  */
212 static void
mbm_put_u0()213 mbm_put_u0()
214 {
215 	uint16_t wire[] = { 'o', 'n', 'e', 0, 42, 0 };
216 	mbuf_chain_t *mbc;
217 	int rc;
218 
219 	mbc = smb_mbc_alloc(100);
220 
221 	rc = smb_mbc_encodef(mbc, "Uw", "one", 42);
222 	if (rc != 0) {
223 		printf("Fail: mbm_put_u0 encode\n");
224 		goto out;
225 	}
226 	if (mbc->chain->m_len != 10) {
227 		printf("Fail: mbm_put_u0 len=%d\n",
228 		    mbc->chain->m_len);
229 		return;
230 	}
231 
232 	if (memcmp(mbc->chain->m_data, wire, 10)) {
233 		printf("Fail: mbm_put_u0 cmp:\n");
234 		hexdump((uchar_t *)mbc->chain->m_data, 10);
235 		return;
236 	}
237 
238 	printf("Pass: mbm_put_u0\n");
239 
240 out:
241 	smb_mbc_free(mbc);
242 }
243 
244 /*
245  * Put unicode string, no NULL
246  */
247 static void
mbm_put_u1()248 mbm_put_u1()
249 {
250 	uint16_t wire[] = { 'o', 'n', 'e', '.', 42, 0 };
251 	mbuf_chain_t *mbc;
252 	int rc;
253 
254 	mbc = smb_mbc_alloc(100);
255 
256 	rc = smb_mbc_encodef(mbc, "8Uw", "one.", 42);
257 	if (rc != 0) {
258 		printf("Fail: mbm_put_u1 encode\n");
259 		goto out;
260 	}
261 	if (mbc->chain->m_len != 10) {
262 		printf("Fail: mbm_put_u1 len=%d\n",
263 		    mbc->chain->m_len);
264 		return;
265 	}
266 
267 	if (memcmp(mbc->chain->m_data, wire, 10)) {
268 		printf("Fail: mbm_put_u1 cmp:\n");
269 		hexdump((uchar_t *)mbc->chain->m_data, 10);
270 		return;
271 	}
272 
273 	printf("Pass: mbm_put_u1\n");
274 
275 out:
276 	smb_mbc_free(mbc);
277 }
278 
279 static void
mbm_put_u3()280 mbm_put_u3()
281 {
282 	mbuf_chain_t *mbc;
283 	int rc;
284 
285 	mbc = smb_mbc_alloc(100);
286 
287 	rc = smb_mbc_encodef(mbc, "U", mbsa);
288 	if (rc != 0) {
289 		printf("Fail: mbm_put_u3 encode\n");
290 		goto out;
291 	}
292 	if (mbc->chain->m_len != 8) {
293 		printf("Fail: mbm_put_u3 len=%d\n",
294 		    mbc->chain->m_len);
295 		return;
296 	}
297 
298 	if (memcmp(mbc->chain->m_data, wcsa, 8)) {
299 		printf("Fail: mbm_put_u3 cmp:\n");
300 		hexdump((uchar_t *)mbc->chain->m_data, 8);
301 		return;
302 	}
303 
304 	printf("Pass: mbm_put_u3\n");
305 
306 out:
307 	smb_mbc_free(mbc);
308 }
309 
310 static void
mbm_put_u4()311 mbm_put_u4()
312 {
313 	mbuf_chain_t *mbc;
314 	int rc;
315 
316 	mbc = smb_mbc_alloc(100);
317 
318 	rc = smb_mbc_encodef(mbc, "U", mbsp);
319 	if (rc != 0) {
320 		printf("Fail: mbm_put_u4 encode\n");
321 		goto out;
322 	}
323 	if (mbc->chain->m_len != 10) {
324 		printf("Fail: mbm_put_u4 len=%d\n",
325 		    mbc->chain->m_len);
326 		return;
327 	}
328 
329 	if (memcmp(mbc->chain->m_data, wcsp, 10)) {
330 		printf("Fail: mbm_put_u4 cmp:\n");
331 		hexdump((uchar_t *)mbc->chain->m_data, 10);
332 		return;
333 	}
334 
335 	printf("Pass: mbm_put_u4\n");
336 
337 out:
338 	smb_mbc_free(mbc);
339 }
340 
341 static void
mbm_put_upad()342 mbm_put_upad()
343 {
344 	uint16_t wire[] = { 'o', 'n', 'e', 0, 0 };
345 	mbuf_chain_t *mbc;
346 	int rc;
347 
348 	mbc = smb_mbc_alloc(100);
349 
350 	/* Encode with wire length > strlen */
351 	rc = smb_mbc_encodef(mbc, "10U", "one");
352 	if (rc != 0) {
353 		printf("Fail: mbm_put_upad encode\n");
354 		goto out;
355 	}
356 	if (mbc->chain->m_len != 10) {
357 		printf("Fail: mbm_put_upad len=%d\n",
358 		    mbc->chain->m_len);
359 		return;
360 	}
361 
362 	if (memcmp(mbc->chain->m_data, wire, 10)) {
363 		printf("Fail: mbm_put_upad cmp:\n");
364 		hexdump((uchar_t *)mbc->chain->m_data, 10);
365 		return;
366 	}
367 
368 	printf("Pass: mbm_put_upad\n");
369 
370 out:
371 	smb_mbc_free(mbc);
372 }
373 
374 static void
mbm_put_utrunc1()375 mbm_put_utrunc1()
376 {
377 	uint16_t wire[] = { 'o', 'n', 'e', 't' };
378 	mbuf_chain_t *mbc;
379 	int rc;
380 
381 	mbc = smb_mbc_alloc(100);
382 
383 	/* Encode with wire length < strlen */
384 	rc = smb_mbc_encodef(mbc, "8U", "onetwo");
385 	if (rc != 0) {
386 		printf("Fail: mbm_put_utrunc1 encode\n");
387 		goto out;
388 	}
389 	/* Trunc should put exactly 8 */
390 	if (mbc->chain->m_len != 8) {
391 		printf("Fail: mbm_put_utrunc1 len=%d\n",
392 		    mbc->chain->m_len);
393 		return;
394 	}
395 
396 	if (memcmp(mbc->chain->m_data, wire, 8)) {
397 		printf("Fail: mbm_put_utrunc1 cmp:\n");
398 		hexdump((uchar_t *)mbc->chain->m_data, 8);
399 		return;
400 	}
401 
402 	printf("Pass: mbm_put_utrunc1\n");
403 
404 out:
405 	smb_mbc_free(mbc);
406 }
407 
408 static void
mbm_put_utrunc2()409 mbm_put_utrunc2()
410 {
411 	uint16_t wire[] = { 'o', 'n', 'e', 't', 0 };
412 	mbuf_chain_t *mbc;
413 	int rc;
414 
415 	mbc = smb_mbc_alloc(8);
416 
417 	/* Encode with wire length < strlen */
418 	rc = smb_mbc_encodef(mbc, "U", "onetwo");
419 	if (rc != 1) {
420 		printf("Fail: mbm_put_utrunc2 encode rc=%d\n", rc);
421 		goto out;
422 	}
423 	/* Trunc should put exactly 8 */
424 	if (mbc->chain->m_len != 8) {
425 		printf("Fail: mbm_put_utrunc2 len=%d\n",
426 		    mbc->chain->m_len);
427 		return;
428 	}
429 
430 	if (memcmp(mbc->chain->m_data, wire, 10)) {
431 		printf("Fail: mbm_put_utrunc2 cmp:\n");
432 		hexdump((uchar_t *)mbc->chain->m_data, 8);
433 		return;
434 	}
435 
436 	printf("Pass: mbm_put_utrunc2\n");
437 
438 out:
439 	smb_mbc_free(mbc);
440 }
441 
442 static void
mbm_put_mbuf1()443 mbm_put_mbuf1()
444 {
445 	uint8_t wire[] = "onetwo";
446 	mbuf_chain_t mbc, mbc2;
447 	int rc;
448 
449 	MBC_INIT(&mbc, 16);
450 	MBC_INIT(&mbc2, 8);
451 
452 	rc = smb_mbc_encodef(&mbc, "3s", "one");
453 	if (rc != 0) {
454 		printf("Fail: mbm_put_mbuf1 encode 1 rc=%d\n", rc);
455 		goto out;
456 	}
457 	if (mbc.chain_offset != 3) {
458 		printf("Fail: mbm_put_mbuf1 encode 1 len=%d\n",
459 		    mbc.chain_offset);
460 		goto out;
461 	}
462 
463 	rc = smb_mbc_encodef(&mbc2, "s", "two");
464 	if (rc != 0) {
465 		printf("Fail: mbm_put_mbuf1 encode 2 rc=%d\n", rc);
466 		goto out;
467 	}
468 	if (mbc2.chain_offset != 4) {
469 		printf("Fail: mbm_put_mbuf1 encode 2 len=%d\n",
470 		    mbc.chain_offset);
471 		goto out;
472 	}
473 
474 	/* Append */
475 	rc = smb_mbc_encodef(&mbc, "m", mbc2.chain);
476 	mbc2.chain = NULL;
477 	if (rc != 0) {
478 		printf("Fail: mbm_put_mbuf1 encode 3 rc=%d\n", rc);
479 		goto out;
480 	}
481 	if (mbc.chain_offset != 7) {
482 		printf("Fail: mbm_put_mbuf1 encode 3 len=%d\n",
483 		    mbc.chain_offset);
484 		goto out;
485 	}
486 
487 	if (memcmp(mbc.chain->m_data, wire, 7)) {
488 		printf("Fail: mbm_put_mbuf1 cmp:\n");
489 		hexdump((uchar_t *)mbc.chain->m_data, 7);
490 		goto out;
491 	}
492 
493 	printf("Pass: mbm_put_mbuf1\n");
494 
495 out:
496 	MBC_FLUSH(&mbc);
497 	MBC_FLUSH(&mbc2);
498 }
499 
500 /*
501  * Verify m_prepend works
502  */
503 static void
mbm_put_mbuf2()504 mbm_put_mbuf2()
505 {
506 	uint8_t wire[] = "one.two";
507 	mbuf_chain_t mbc;
508 	mbuf_t *m;
509 	int len, rc;
510 
511 	MBC_INIT(&mbc, 512);
512 
513 	rc = smb_mbc_encodef(&mbc, "s", "two");
514 	if (rc != 0) {
515 		printf("Fail: mbm_put_mbuf2 encode 1 rc=%d\n", rc);
516 		goto out;
517 	}
518 	if (mbc.chain_offset != 4) {
519 		printf("Fail: mbm_put_mbuf2 encode 1 len=%d\n",
520 		    mbc.chain_offset);
521 		goto out;
522 	}
523 
524 	/* Prepend.  Should use prepend space, not allocate. */
525 	m = m_prepend(mbc.chain, 4, M_WAIT);
526 	if (m != mbc.chain) {
527 		(void) m_free(m);
528 		printf("Fail: mbm_put_mbuf2 m_prepend error\n", rc);
529 		goto out;
530 	}
531 
532 	/* Now write into the prepend space. */
533 	bcopy("one.", m->m_data, 4);
534 
535 	/* Verify length and content */
536 	len = MBC_LENGTH(&mbc);
537 	if (len != 8) {
538 		printf("Fail: mbm_put_mbuf2 encode 2 len=%d\n",
539 		    mbc.chain_offset);
540 		goto out;
541 	}
542 
543 	if (memcmp(mbc.chain->m_data, wire, 7)) {
544 		printf("Fail: mbm_put_mbuf2 cmp:\n");
545 		hexdump((uchar_t *)mbc.chain->m_data, 7);
546 		goto out;
547 	}
548 
549 	printf("Pass: mbm_put_mbuf2\n");
550 
551 out:
552 	MBC_FLUSH(&mbc);
553 }
554 
555 /*
556  * Check how mbc_marshal_make_room crosses a message boundary
557  */
558 static void
mbm_put_mbuf3()559 mbm_put_mbuf3()
560 {
561 	mbuf_chain_t mbc;
562 	mbuf_t *m;
563 	char *p;
564 	int rc;
565 
566 	MBC_INIT(&mbc, 16384);
567 
568 	/*
569 	 * Encode near the end of the first mbuf
570 	 * running over into the second.
571 	 */
572 	m = mbc.chain;
573 	mbc.chain_offset = M_TRAILINGSPACE(m) - 4;
574 	rc = smb_mbc_encodef(&mbc, "s", "one.two");
575 	if (rc != 0) {
576 		printf("Fail: mbm_put_mbuf3 encode 1 rc=%d\n", rc);
577 		goto out;
578 	}
579 
580 	/* Verify first segment */
581 	p = m->m_data + m->m_len - 4;
582 	if (memcmp(p, "one.", 4)) {
583 		printf("Fail: mbm_put_mbuf3 cmp1:\n");
584 		hexdump((uchar_t *)p, 4);
585 		goto out;
586 	}
587 
588 	/* Verify second segment */
589 	p = m->m_next->m_data;
590 	if (memcmp(p, "two", 4)) {
591 		printf("Fail: mbm_put_mbuf3 cmp2:\n");
592 		hexdump((uchar_t *)p, 4);
593 		goto out;
594 	}
595 
596 	printf("Pass: mbm_put_mbuf3\n");
597 
598 out:
599 	MBC_FLUSH(&mbc);
600 }
601 
602 /*
603  * Parse an ascii string.
604  */
605 static void
mbm_get_a0()606 mbm_get_a0()
607 {
608 	uint8_t wire[] = { 'o', 'n', 'e', 0, 42, 0 };
609 	mbuf_chain_t mbc;
610 	char *s;
611 	int rc;
612 	uint16_t w;
613 
614 	bzero(&mbc, sizeof (mbc));
615 	MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire));
616 
617 	rc = smb_mbc_decodef(&mbc, "%sw", &test_sr, &s, &w);
618 	if (rc != 0) {
619 		printf("Fail: mbm_get_a0 decode\n");
620 		goto out;
621 	}
622 	/*
623 	 * Decode a word after the string to make sure we
624 	 * end up positioned correctly after the string.
625 	 */
626 	if (w != 42) {
627 		printf("Fail: mbm_get_a0 w=%d\n", w);
628 		return;
629 	}
630 	if (strcmp(s, "one") != 0) {
631 		printf("Fail: mbm_get_a0 cmp: <%s>\n", s);
632 		return;
633 	}
634 
635 	printf("Pass: mbm_get_a0\n");
636 
637 out:
638 	MBC_FLUSH(&mbc);
639 }
640 
641 /*
642  * Parse an ascii string, no NULL
643  */
644 static void
mbm_get_a1()645 mbm_get_a1()
646 {
647 	uint8_t wire[] = { 'o', 'n', 'e', '.', 42, 0 };
648 	mbuf_chain_t mbc;
649 	char *s;
650 	int rc;
651 	uint16_t w;
652 
653 	bzero(&mbc, sizeof (mbc));
654 	MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire));
655 
656 	rc = smb_mbc_decodef(&mbc, "%3s.w", &test_sr, &s, &w);
657 	if (rc != 0) {
658 		printf("Fail: mbm_get_a1 decode\n");
659 		goto out;
660 	}
661 	/*
662 	 * Decode a word after the string to make sure we
663 	 * end up positioned correctly after the string.
664 	 */
665 	if (w != 42) {
666 		printf("Fail: mbm_get_a1 w=%d\n", w);
667 		return;
668 	}
669 	if (strcmp(s, "one") != 0) {
670 		printf("Fail: mbm_get_a1 cmp: <%s>\n", s);
671 		return;
672 	}
673 
674 	printf("Pass: mbm_get_a1\n");
675 
676 out:
677 	MBC_FLUSH(&mbc);
678 }
679 
680 /* parse exactly to end of data */
681 static void
mbm_get_a2()682 mbm_get_a2()
683 {
684 	uint8_t wire[] = { 'o', 'n', 'e' };
685 	mbuf_chain_t mbc;
686 	char *s;
687 	int rc;
688 
689 	bzero(&mbc, sizeof (mbc));
690 	MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire));
691 
692 	rc = smb_mbc_decodef(&mbc, "%3s", &test_sr, &s);
693 	if (rc != 0) {
694 		printf("Fail: mbm_get_a2 decode\n");
695 		goto out;
696 	}
697 	if (mbc.chain_offset != 3) {
698 		printf("Fail: mbm_get_a2 wrong pos\n");
699 		return;
700 	}
701 	if (strcmp(s, "one") != 0) {
702 		printf("Fail: mbm_get_a2 cmp: <%s>\n", s);
703 		return;
704 	}
705 
706 	printf("Pass: mbm_get_a2\n");
707 
708 out:
709 	MBC_FLUSH(&mbc);
710 }
711 
712 /*
713  * Parse a unicode string.
714  */
715 static void
mbm_get_u0()716 mbm_get_u0()
717 {
718 	uint16_t wire[] = { 'o', 'n', 'e', 0, 42, 0 };
719 	mbuf_chain_t mbc;
720 	char *s;
721 	int rc;
722 	uint16_t w;
723 
724 	bzero(&mbc, sizeof (mbc));
725 	MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire));
726 
727 	rc = smb_mbc_decodef(&mbc, "%Uw", &test_sr, &s, &w);
728 	if (rc != 0) {
729 		printf("Fail: mbm_get_u0 decode\n");
730 		goto out;
731 	}
732 	/*
733 	 * Decode a word after the string to make sure we
734 	 * end up positioned correctly after the string.
735 	 */
736 	if (w != 42) {
737 		printf("Fail: mbm_get_u0 w=%d\n", w);
738 		return;
739 	}
740 	if (strcmp(s, "one") != 0) {
741 		printf("Fail: mbm_get_u0 cmp: <%s>\n", s);
742 		return;
743 	}
744 
745 	printf("Pass: mbm_get_u0\n");
746 
747 out:
748 	MBC_FLUSH(&mbc);
749 }
750 
751 /*
752  * Parse a string that's NOT null terminated.
753  */
754 static void
mbm_get_u1()755 mbm_get_u1()
756 {
757 	uint16_t wire[] = { 'o', 'n', 'e', '.', 42, 0 };
758 	mbuf_chain_t mbc;
759 	char *s;
760 	int rc;
761 	uint16_t w;
762 
763 	bzero(&mbc, sizeof (mbc));
764 	MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire));
765 
766 	rc = smb_mbc_decodef(&mbc, "%6U..w", &test_sr, &s, &w);
767 	if (rc != 0) {
768 		printf("Fail: mbm_get_u1 decode\n");
769 		goto out;
770 	}
771 	/*
772 	 * Decode a word after the string to make sure we
773 	 * end up positioned correctly after the string.
774 	 */
775 	if (w != 42) {
776 		printf("Fail: mbm_get_u1 w=%d\n", w);
777 		return;
778 	}
779 	if (strcmp(s, "one") != 0) {
780 		printf("Fail: mbm_get_u1 cmp: <%s>\n", s);
781 		return;
782 	}
783 
784 	printf("Pass: mbm_get_u1\n");
785 
786 out:
787 	MBC_FLUSH(&mbc);
788 }
789 
790 /* parse exactly to end of data */
791 static void
mbm_get_u2()792 mbm_get_u2()
793 {
794 	uint16_t wire[] = { 't', 'w', 'o' };
795 	mbuf_chain_t mbc;
796 	char *s;
797 	int rc;
798 
799 	bzero(&mbc, sizeof (mbc));
800 	MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire));
801 
802 	rc = smb_mbc_decodef(&mbc, "%6U", &test_sr, &s);
803 	if (rc != 0) {
804 		printf("Fail: mbm_get_u2 decode\n");
805 		goto out;
806 	}
807 	if (mbc.chain_offset != 6) {
808 		printf("Fail: mbm_get_u2 wrong pos\n");
809 		return;
810 	}
811 	if (strcmp(s, "two") != 0) {
812 		printf("Fail: mbm_get_u2 cmp: <%s>\n", s);
813 		return;
814 	}
815 
816 	printf("Pass: mbm_get_a2\n");
817 
818 out:
819 	MBC_FLUSH(&mbc);
820 }
821 
822 static void
mbm_get_u3()823 mbm_get_u3()
824 {
825 	mbuf_chain_t mbc;
826 	char *s;
827 	int rc;
828 
829 	bzero(&mbc, sizeof (mbc));
830 	MBC_ATTACH_BUF(&mbc, (uchar_t *)wcsa, sizeof (wcsa));
831 
832 	rc = smb_mbc_decodef(&mbc, "%#U", &test_sr, sizeof (wcsa), &s);
833 	if (rc != 0) {
834 		printf("Fail: mbm_get_u3 decode\n");
835 		goto out;
836 	}
837 	if (strcmp(s, mbsa) != 0) {
838 		printf("Fail: mbm_get_u3 cmp: <%s>\n", s);
839 		return;
840 	}
841 
842 	printf("Pass: mbm_get_u3\n");
843 
844 out:
845 	MBC_FLUSH(&mbc);
846 }
847 
848 static void
mbm_get_u4()849 mbm_get_u4()
850 {
851 	mbuf_chain_t mbc;
852 	char *s;
853 	int rc;
854 
855 	bzero(&mbc, sizeof (mbc));
856 	MBC_ATTACH_BUF(&mbc, (uchar_t *)wcsp, sizeof (wcsp));
857 
858 	rc = smb_mbc_decodef(&mbc, "%#U", &test_sr, sizeof (wcsp), &s);
859 	if (rc != 0) {
860 		printf("Fail: mbm_get_u4 decode\n");
861 		goto out;
862 	}
863 	if (strcmp(s, mbsp) != 0) {
864 		printf("Fail: mbm_get_u4 cmp: <%s>\n", s);
865 		return;
866 	}
867 
868 	printf("Pass: mbm_get_u4\n");
869 
870 out:
871 	MBC_FLUSH(&mbc);
872 }
873 
874 void
test_mbmarshal()875 test_mbmarshal()
876 {
877 
878 	smb_mbc_init();
879 
880 	test_ssn.dialect = 0x210;	// SMB 2.1
881 	test_sr.session = &test_ssn;
882 	test_sr.sr_magic = SMB_REQ_MAGIC;
883 	smb_srm_init(&test_sr);
884 
885 	mbm_put_a0();
886 	mbm_put_a1();
887 	mbm_put_apad();
888 	mbm_put_atrunc1();
889 	mbm_put_atrunc2();
890 
891 	mbm_put_u0();
892 	mbm_put_u1();
893 	mbm_put_u3();
894 	mbm_put_u4();
895 	mbm_put_upad();
896 	mbm_put_utrunc1();
897 	mbm_put_utrunc2();
898 
899 	mbm_put_mbuf1();
900 	mbm_put_mbuf2();
901 	mbm_put_mbuf3();
902 
903 	mbm_get_a0();
904 	mbm_get_a1();
905 	mbm_get_a2();
906 	mbm_get_u0();
907 	mbm_get_u1();
908 	mbm_get_u2();
909 	mbm_get_u3();
910 	mbm_get_u4();
911 
912 	smb_srm_fini(&test_sr);
913 	smb_mbc_fini();
914 }
915