# # This file and its contents are supplied under the terms of the # Common Development and Distribution License ("CDDL"), version 1.0. # You may only use this file in accordance with the terms of version # 1.0 of the CDDL. # # A full copy of the text of the CDDL should have accompanied this # source. A copy of the CDDL is also available via the Internet at # http://www.illumos.org/license/CDDL. # # # Copyright 2018 Nexenta Systems, Inc. All rights reserved. # set -o emacs setenv ROOT ${CODEMGR_WS}/proto/root_i386 setenv LD_LIBRARY_PATH ${ROOT}/usr/lib/smbsrv:${ROOT}/usr/lib:${ROOT}/lib echo debug ${ROOT}/usr/lib/smbsrv/test-msgbuf # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright 2018 Nexenta Systems, Inc. All rights reserved. # PROG= test-msgbuf OBJS_LOCAL= test_main.o test_misc.o test_conv.o \ test_mbmarshal.o test_msgbuf.o OBJS_SMBSRV= smb_mbuf_marshaling.o smb_mbuf_util.o smb_alloc.o OBJS_SMBCMN= smb_msgbuf.o smb_string.o smb_utf8.o OBJS= ${OBJS_LOCAL} ${OBJS_SMBSRV} ${OBJS_SMBCMN} SMBSRV_SRCDIR=../../../uts/common/fs/smbsrv SMBSRV_CMNDIR=../../../common/smbsrv SRCS= ${OBJS_LOCAL:.o=.c} \ ${OBJS_SMBSRV:%.o=${SMBSRV_SRCDIR}/%.c} \ ${OBJS_SMBCMN:%.o=${SMBSRV_CMNDIR}/%.c} include ../../Makefile.cmd include ../../Makefile.ctf # Note: need our sys includes _before_ ENVCPPFLAGS, proto etc. CPPFLAGS.first += -I. CPPFLAGS.first += -I../../../lib/libfakekernel/common CPPFLAGS.first += -I../../../lib/smbsrv/libfksmbsrv/common INCS += -I../../../uts/common INCS += -I../../../uts/common/smbsrv INCS += -I../../../common/smbsrv CSTD= $(CSTD_GNU99) CFLAGS += $(CCVERBOSE) CFLAGS64 += $(CCVERBOSE) CERRWARN += -Wno-parentheses CPPFLAGS += -D_REENTRANT CPPFLAGS += -DTESTJIG CPPFLAGS += -Dsyslog=smb_syslog CPPFLAGS += -D_LARGEFILE64_SOURCE=1 # Always debug here CPPFLAGS += -DDEBUG CPPFLAGS += $(INCS) LDFLAGS += $(ZNOLAZYLOAD) LDFLAGS += '-R$$ORIGIN/..' LDLIBS += -lfakekernel -lcmdutils ROOTSMBDDIR = $(ROOTLIB)/smbsrv ROOTSMBDFILE = $(PROG:%=$(ROOTSMBDDIR)/%) .KEEP_STATE: all: $(PROG) $(PROG): $(OBJS) $(LINK.c) -o $(PROG) $(OBJS) $(LDLIBS) $(POST_PROCESS) clean: -$(RM) $(OBJS) include ../../Makefile.targ install: all $(ROOTSMBDFILE) test_main.o : test_main.c $(CC) $(CFLAGS) $(CPPFLAGS) -D_KMEMUSER -c test_main.c $(POST_PROCESS_O) test_misc.o : test_misc.c $(CC) $(CFLAGS) $(CPPFLAGS) -D_FAKE_KERNEL \ -I../../../uts/common/smbsrv \ -I../../../common/smbsrv -c test_misc.c $(POST_PROCESS_O) # OBJS_SMBSRV %.o: ../../../uts/common/fs/smbsrv/%.c $(CC) $(CFLAGS) $(CPPFLAGS) -D_FAKE_KERNEL \ -I../../../uts/common/smbsrv \ -I../../../common/smbsrv -c $< $(POST_PROCESS_O) # OBJS_SMBCMN %.o: ../../../common/smbsrv/%.c $(CC) $(CFLAGS) $(CPPFLAGS) -D_FAKE_KERNEL \ -I../../../uts/common/smbsrv \ -I../../../common/smbsrv -c $< $(POST_PROCESS_O) $(ROOTSMBDDIR)/%: % $(INS.file) #!/bin/sh # # This file and its contents are supplied under the terms of the # Common Development and Distribution License ("CDDL"), version 1.0. # You may only use this file in accordance with the terms of version # 1.0 of the CDDL. # # A full copy of the text of the CDDL should have accompanied this # source. A copy of the CDDL is also available via the Internet at # http://www.illumos.org/license/CDDL. # # # Copyright 2018 Nexenta Systems, Inc. All rights reserved. # # Helper program to run test-msgbuf (unit test program) # using binaries from the proto area. [ -n "$CODEMGR_WS" ] || { echo "Need a buildenv to set CODEMGR_WS=..." exit 1; } ROOT=${CODEMGR_WS}/proto/root_i386 LD_LIBRARY_PATH=$ROOT/usr/lib/smbsrv:$ROOT/usr/lib:$ROOT/lib export LD_LIBRARY_PATH export UMEM_DEBUG=default # run with the passed options exec $ROOT/usr/lib/smbsrv/test-msgbuf "$@" /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. * Copyright 2017-2021 Tintri by DDN, Inc. All rights reserved. */ #ifndef _SYS_SDT_H #define _SYS_SDT_H #ifdef __cplusplus extern "C" { #endif /* * For this test program define any dtrace probes out of existence. */ #define DTRACE_PROBE(a) ((void)0) #define DTRACE_PROBE1(a, ...) ((void)0) #define DTRACE_PROBE2(a, ...) ((void)0) #define DTRACE_PROBE3(a, ...) ((void)0) #define SET_ERROR(err) (void)0) #ifdef __cplusplus } #endif #endif /* _SYS_SDT_H */ /* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ /* * Test conversion of strings UTF-8 to/from UTF-16 etc. * * This tests both 16-bit unicode symbols (UCS-2) and so called * "enhanced" unicode symbols such as the "poop emoji" that are * above 65535 and encode to four bytes as UTF-8. */ #include #include #include #include #include #include #include "test_defs.h" #define U_FW_A 0xff21 // full-width A (A) static const char fwA[4] = "\xef\xbc\xa1"; #define U_POOP 0x1f4a9 // poop emoji (💩) static const char poop[5] = "\xf0\x9f\x92\xa9"; static char mbsa[] = "A\xef\xbc\xa1."; // A fwA . (5) static char mbsp[] = "P\xf0\x9f\x92\xa9."; // P poop . (6) static smb_wchar_t wcsa[] = { 'A', U_FW_A, '.', 0 }; // (3) static smb_wchar_t wcsp[] = { 'P', 0xd83d, 0xdca9, '.', 0 }; // (4) static void conv_wctomb() { char mbs[8]; int len; len = smb_wctomb(mbs, U_FW_A); if (len != 3) { printf("Fail: conv_wctomb fwA ret=%d\n", len); return; } mbs[len] = '\0'; if (strcmp(mbs, fwA)) { printf("Fail: conv_wctomb fwA cmp:\n"); hexdump((uchar_t *)mbs, len+1); return; } len = smb_wctomb(mbs, U_POOP); if (len != 4) { printf("Fail: conv_wctomb poop ret=%d\n", len); return; } mbs[len] = '\0'; if (strcmp(mbs, poop)) { printf("Fail: conv_wctomb poop cmp:\n"); hexdump((uchar_t *)mbs, len+1); return; } /* null wc to mbs should return 1 and put a null */ len = smb_wctomb(mbs, 0); if (len != 1) { printf("Fail: conv_wctomb null ret=%d\n", len); return; } if (mbs[0] != '\0') { printf("Fail: conv_wctomb null cmp:\n"); hexdump((uchar_t *)mbs, len+1); return; } printf("Pass: conv_wctomb\n"); } static void conv_mbtowc() { uint32_t wch = 0; int len; /* * The (void *) cast here is to let this build both * before and after an interface change in smb_mbtowc * (uint16_t vs uint32_t) */ len = smb_mbtowc((void *)&wch, fwA, 4); if (len != 3) { printf("Fail: conv_mbtowc fwA ret=%d\n", len); return; } if (wch != U_FW_A) { printf("Fail: conv_mbtowc fwA cmp: 0x%x\n", wch); return; } len = smb_mbtowc((void *)&wch, poop, 4); // poop emoji if (len != 4) { printf("Fail: conv_mbtowc poop ret=%d\n", len); return; } if (wch != U_POOP) { printf("Fail: conv_mbtowc poop cmp: 0x%x\n", wch); return; } /* null mbs to wc should return 0 (and set wch=0) */ len = smb_mbtowc((void *)&wch, "", 4); if (len != 0) { printf("Fail: conv_mbtowc null ret=%d\n", len); return; } if (wch != 0) { printf("Fail: conv_mbtowc null cmp: 0x%x\n", wch); return; } printf("Pass: conv_mbtowc\n"); } static void conv_wcstombs() { char tmbs[16]; int len; len = smb_wcstombs(tmbs, wcsa, sizeof (tmbs)); if (len != 5) { printf("Fail: conv_wcstombs A ret=%d\n", len); return; } if (strcmp(tmbs, mbsa)) { printf("Fail: conv_wcstombs A cmp:\n"); hexdump((uchar_t *)tmbs, len+2); return; } len = smb_wcstombs(tmbs, wcsp, sizeof (tmbs)); if (len != 6) { printf("Fail: conv_wcstombs f ret=%d\n", len); return; } if (strcmp(tmbs, mbsp)) { printf("Fail: conv_wcstombs f cmp:\n"); hexdump((uchar_t *)tmbs, len+2); return; } printf("Pass: conv_wcstombs\n"); } static void conv_mbstowcs() { smb_wchar_t twcs[8]; uint32_t wch = 0; int len; len = smb_mbstowcs(twcs, mbsa, sizeof (twcs)); if (len != 3) { printf("Fail: conv_mbstowcs A ret=%d\n", len); return; } if (memcmp(twcs, wcsa, len+2)) { printf("Fail: conv_mbstowcs A cmp: 0x%x\n", wch); hexdump((uchar_t *)twcs, len+2); return; } len = smb_mbstowcs(twcs, mbsp, sizeof (twcs)); if (len != 4) { printf("Fail: conv_mbstowcs P ret=%d\n", len); return; } if (memcmp(twcs, wcsp, len+2)) { printf("Fail: conv_mbstowcs P cmp: 0x%x\n", wch); hexdump((uchar_t *)twcs, len+2); return; } printf("Pass: conv_mbstowcs\n"); } /* * An OEM string that will require iconv. */ static uchar_t fubar_oem[] = "F\201bar"; // CP850 x81 (ü) static char fubar_mbs[] = "F\303\274bar"; // UTF8 xC3 xBC static void conv_oemtombs() { char tmbs[16]; int len; len = smb_oemtombs(tmbs, (uchar_t *)"foo", 4); if (len != 3) { printf("Fail: conv_wctomb foo ret=%d\n", len); return; } if (strcmp(tmbs, "foo")) { printf("Fail: conv_wctomb foo cmp:\n"); hexdump((uchar_t *)tmbs, len+1); return; } len = smb_oemtombs(tmbs, fubar_oem, 7); if (len != 6) { printf("Fail: conv_oemtombs fubar ret=%d\n", len); return; } if (strcmp(tmbs, fubar_mbs)) { printf("Fail: conv_oemtombs fubar cmp:\n"); hexdump((uchar_t *)tmbs, len+1); return; } printf("Pass: conv_oemtombs\n"); } static void conv_mbstooem() { uint8_t oemcs[8]; uint32_t wch = 0; int len; len = smb_mbstooem(oemcs, "foo", 8); if (len != 3) { printf("Fail: conv_mbstooem foo ret=%d\n", len); return; } if (memcmp(oemcs, "foo", len+1)) { printf("Fail: conv_mbstooem P cmp: 0x%x\n", wch); hexdump((uchar_t *)oemcs, len+1); return; } len = smb_mbstooem(oemcs, fubar_mbs, 8); if (len != 5) { printf("Fail: conv_mbstooem fubar ret=%d\n", len); return; } if (memcmp(oemcs, (char *)fubar_oem, len+1)) { printf("Fail: conv_mbstooem fubar cmp: 0x%x\n", wch); hexdump((uchar_t *)oemcs, len+1); return; } len = smb_mbstooem(oemcs, mbsp, 8); if (len != 3) { printf("Fail: conv_mbstooem poop ret=%d\n", len); return; } if (memcmp(oemcs, "P?.", len+1)) { printf("Fail: conv_mbstooem poop cmp: 0x%x\n", wch); hexdump((uchar_t *)oemcs, len+1); return; } printf("Pass: conv_mbstooem\n"); } static void conv_sbequiv_strlen() { int len; len = (int)smb_sbequiv_strlen("a"); if (len != 1) { printf("Fail: conv_sbequiv_strlen (a) len=%d\n", len); return; } len = (int)smb_sbequiv_strlen(fubar_mbs); if (len != strlen((char *)fubar_oem)) { printf("Fail: conv_sbequiv_strlen (fubar) len=%d\n", len); return; } len = (int)smb_sbequiv_strlen(mbsp); if (len != 3) { // "P?." printf("Fail: conv_sbequiv_strlen (poop) len=%d\n", len); return; } printf("Pass: conv_sbequiv_strlen\n"); } static void conv_wcequiv_strlen() { int len; len = (int)smb_wcequiv_strlen("a"); if (len != 2) { printf("Fail: conv_wcequiv_strlen (a) len=%d\n", len); return; } len = (int)smb_wcequiv_strlen(fwA); if (len != 2) { printf("Fail: conv_wcequiv_strlen (fwA) len=%d\n", len); return; } len = (int)smb_wcequiv_strlen(poop); if (len != 4) { printf("Fail: conv_wcequiv_strlen (poop) len=%d\n", len); return; } printf("Pass: conv_wcequiv_strlen\n"); } void test_conv() { conv_wctomb(); conv_mbtowc(); conv_wcstombs(); conv_mbstowcs(); conv_oemtombs(); conv_mbstooem(); conv_sbequiv_strlen(); conv_wcequiv_strlen(); } /* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ #ifndef _TEST_DEFS_H #define _TEST_DEFS_H /* * Describe the purpose of the file here. */ #ifdef __cplusplus extern "C" { #endif extern void hexdump(const uchar_t *buf, int len); extern void test_conv(void); extern void test_mbmarshal(void); extern void test_msgbuf(void); #ifdef __cplusplus } #endif #endif /* _TEST_DEFS_H */ /* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2018 Nexenta Systems, Inc. All rights reserved. * Copyright 2019 Joyent, Inc. */ /* * Test & debug program for smb_msgbuf.c and smb_mbuf_marshaling.c */ #include #include #include #include #include #include #include #include "test_defs.h" int main(int argc, char *argv[]) { test_conv(); test_mbmarshal(); test_msgbuf(); return (0); } void hexdump(const uchar_t *buf, int len) { int idx; char ascii[24]; char *pa = ascii; memset(ascii, '\0', sizeof (ascii)); idx = 0; while (len--) { if ((idx & 15) == 0) { printf("%04X: ", idx); pa = ascii; } if (*buf > ' ' && *buf <= '~') *pa++ = *buf; else *pa++ = '.'; printf("%02x ", *buf++); idx++; if ((idx & 3) == 0) { *pa++ = ' '; (void) putchar(' '); } if ((idx & 15) == 0) { *pa = '\0'; printf("%s\n", ascii); } } if ((idx & 15) != 0) { *pa = '\0'; /* column align the last ascii row */ while ((idx & 15) != 0) { if ((idx & 3) == 0) (void) putchar(' '); printf(" "); idx++; } printf("%s\n", ascii); } } /* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2018-2021 Tintri by DDN, Inc. All rights reserved. */ /* * Test putting/getting unicode strings in mbchains. */ #include #include #include #include #include #include #include #include "test_defs.h" static char mbsa[] = "A\xef\xbc\xa1."; // A fwA . (5) static char mbsp[] = "P\xf0\x9f\x92\xa9."; // P poop . (6) static smb_wchar_t wcsa[] = { 'A', 0xff21, '.', 0 }; // (3) static smb_wchar_t wcsp[] = { 'P', 0xd83d, 0xdca9, '.', 0 }; // (4) smb_session_t test_ssn; smb_request_t test_sr; /* * Put ASCII string with NULL */ static void mbm_put_a0() { uint8_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; mbuf_chain_t *mbc; int rc; mbc = smb_mbc_alloc(100); rc = smb_mbc_encodef(mbc, "sw", "one", 42); if (rc != 0) { printf("Fail: mbm_put_a0 encode\n"); goto out; } if (mbc->chain->m_len != 6) { printf("Fail: mbm_put_a0 len=%d\n", mbc->chain->m_len); return; } if (memcmp(mbc->chain->m_data, wire, 6)) { printf("Fail: mbm_put_a0 cmp:\n"); hexdump((uchar_t *)mbc->chain->m_data, 6); return; } printf("Pass: mbm_put_a0\n"); out: smb_mbc_free(mbc); } /* * Put ASCII string, no NULL */ static void mbm_put_a1() { uint8_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; mbuf_chain_t *mbc; int rc; mbc = smb_mbc_alloc(100); rc = smb_mbc_encodef(mbc, "4sw", "one.", 42); if (rc != 0) { printf("Fail: mbm_put_a1 encode\n"); goto out; } if (mbc->chain->m_len != 6) { printf("Fail: mbm_put_a1 len=%d\n", mbc->chain->m_len); return; } if (memcmp(mbc->chain->m_data, wire, 6)) { printf("Fail: mbm_put_a1 cmp:\n"); hexdump((uchar_t *)mbc->chain->m_data, 6); return; } printf("Pass: mbm_put_a1\n"); out: smb_mbc_free(mbc); } static void mbm_put_apad() { uint8_t wire[] = { 'o', 'n', 'e', 0, 0 }; mbuf_chain_t *mbc; int rc; mbc = smb_mbc_alloc(100); /* Encode with wire length > strlen */ rc = smb_mbc_encodef(mbc, "5s", "one"); if (rc != 0) { printf("Fail: mbm_put_apad encode\n"); goto out; } if (mbc->chain->m_len != 5) { printf("Fail: mbm_put_apad len=%d\n", mbc->chain->m_len); return; } if (memcmp(mbc->chain->m_data, wire, 5)) { printf("Fail: mbm_put_apad cmp:\n"); hexdump((uchar_t *)mbc->chain->m_data, 5); return; } printf("Pass: mbm_put_apad\n"); out: smb_mbc_free(mbc); } static void mbm_put_atrunc1() { uint8_t wire[] = { 'o', 'n', 'e', 't', }; mbuf_chain_t *mbc; int rc; mbc = smb_mbc_alloc(100); /* Encode with wire length < strlen */ rc = smb_mbc_encodef(mbc, "4s", "onetwo"); if (rc != 0) { printf("Fail: mbm_put_atrunc1 encode\n"); goto out; } /* Trunc should put exactly 4 */ if (mbc->chain->m_len != 4) { printf("Fail: mbm_put_atrunc1 len=%d\n", mbc->chain->m_len); return; } if (memcmp(mbc->chain->m_data, wire, 4)) { printf("Fail: mbm_put_atrunc1 cmp:\n"); hexdump((uchar_t *)mbc->chain->m_data, 4); return; } printf("Pass: mbm_put_atrunc1\n"); out: smb_mbc_free(mbc); } static void mbm_put_atrunc2() { uint8_t wire[] = { 'o', 'n', 'e', 't', 0 }; mbuf_chain_t *mbc; int rc; mbc = smb_mbc_alloc(4); /* Encode with wire length < strlen */ rc = smb_mbc_encodef(mbc, "s", "onetwo"); if (rc != 1) { printf("Fail: mbm_put_atrunc2 encode rc=%d\n", rc); goto out; } /* Trunc should put exactly 4 */ if (mbc->chain->m_len != 4) { printf("Fail: mbm_put_atrunc2 len=%d\n", mbc->chain->m_len); return; } if (memcmp(mbc->chain->m_data, wire, 5)) { printf("Fail: mbm_put_atrunc2 cmp:\n"); hexdump((uchar_t *)mbc->chain->m_data, 4); return; } printf("Pass: mbm_put_atrunc2\n"); out: smb_mbc_free(mbc); } /* * Put unicode string with NULL */ static void mbm_put_u0() { uint16_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; mbuf_chain_t *mbc; int rc; mbc = smb_mbc_alloc(100); rc = smb_mbc_encodef(mbc, "Uw", "one", 42); if (rc != 0) { printf("Fail: mbm_put_u0 encode\n"); goto out; } if (mbc->chain->m_len != 10) { printf("Fail: mbm_put_u0 len=%d\n", mbc->chain->m_len); return; } if (memcmp(mbc->chain->m_data, wire, 10)) { printf("Fail: mbm_put_u0 cmp:\n"); hexdump((uchar_t *)mbc->chain->m_data, 10); return; } printf("Pass: mbm_put_u0\n"); out: smb_mbc_free(mbc); } /* * Put unicode string, no NULL */ static void mbm_put_u1() { uint16_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; mbuf_chain_t *mbc; int rc; mbc = smb_mbc_alloc(100); rc = smb_mbc_encodef(mbc, "8Uw", "one.", 42); if (rc != 0) { printf("Fail: mbm_put_u1 encode\n"); goto out; } if (mbc->chain->m_len != 10) { printf("Fail: mbm_put_u1 len=%d\n", mbc->chain->m_len); return; } if (memcmp(mbc->chain->m_data, wire, 10)) { printf("Fail: mbm_put_u1 cmp:\n"); hexdump((uchar_t *)mbc->chain->m_data, 10); return; } printf("Pass: mbm_put_u1\n"); out: smb_mbc_free(mbc); } static void mbm_put_u3() { mbuf_chain_t *mbc; int rc; mbc = smb_mbc_alloc(100); rc = smb_mbc_encodef(mbc, "U", mbsa); if (rc != 0) { printf("Fail: mbm_put_u3 encode\n"); goto out; } if (mbc->chain->m_len != 8) { printf("Fail: mbm_put_u3 len=%d\n", mbc->chain->m_len); return; } if (memcmp(mbc->chain->m_data, wcsa, 8)) { printf("Fail: mbm_put_u3 cmp:\n"); hexdump((uchar_t *)mbc->chain->m_data, 8); return; } printf("Pass: mbm_put_u3\n"); out: smb_mbc_free(mbc); } static void mbm_put_u4() { mbuf_chain_t *mbc; int rc; mbc = smb_mbc_alloc(100); rc = smb_mbc_encodef(mbc, "U", mbsp); if (rc != 0) { printf("Fail: mbm_put_u4 encode\n"); goto out; } if (mbc->chain->m_len != 10) { printf("Fail: mbm_put_u4 len=%d\n", mbc->chain->m_len); return; } if (memcmp(mbc->chain->m_data, wcsp, 10)) { printf("Fail: mbm_put_u4 cmp:\n"); hexdump((uchar_t *)mbc->chain->m_data, 10); return; } printf("Pass: mbm_put_u4\n"); out: smb_mbc_free(mbc); } static void mbm_put_upad() { uint16_t wire[] = { 'o', 'n', 'e', 0, 0 }; mbuf_chain_t *mbc; int rc; mbc = smb_mbc_alloc(100); /* Encode with wire length > strlen */ rc = smb_mbc_encodef(mbc, "10U", "one"); if (rc != 0) { printf("Fail: mbm_put_upad encode\n"); goto out; } if (mbc->chain->m_len != 10) { printf("Fail: mbm_put_upad len=%d\n", mbc->chain->m_len); return; } if (memcmp(mbc->chain->m_data, wire, 10)) { printf("Fail: mbm_put_upad cmp:\n"); hexdump((uchar_t *)mbc->chain->m_data, 10); return; } printf("Pass: mbm_put_upad\n"); out: smb_mbc_free(mbc); } static void mbm_put_utrunc1() { uint16_t wire[] = { 'o', 'n', 'e', 't' }; mbuf_chain_t *mbc; int rc; mbc = smb_mbc_alloc(100); /* Encode with wire length < strlen */ rc = smb_mbc_encodef(mbc, "8U", "onetwo"); if (rc != 0) { printf("Fail: mbm_put_utrunc1 encode\n"); goto out; } /* Trunc should put exactly 8 */ if (mbc->chain->m_len != 8) { printf("Fail: mbm_put_utrunc1 len=%d\n", mbc->chain->m_len); return; } if (memcmp(mbc->chain->m_data, wire, 8)) { printf("Fail: mbm_put_utrunc1 cmp:\n"); hexdump((uchar_t *)mbc->chain->m_data, 8); return; } printf("Pass: mbm_put_utrunc1\n"); out: smb_mbc_free(mbc); } static void mbm_put_utrunc2() { uint16_t wire[] = { 'o', 'n', 'e', 't', 0 }; mbuf_chain_t *mbc; int rc; mbc = smb_mbc_alloc(8); /* Encode with wire length < strlen */ rc = smb_mbc_encodef(mbc, "U", "onetwo"); if (rc != 1) { printf("Fail: mbm_put_utrunc2 encode rc=%d\n", rc); goto out; } /* Trunc should put exactly 8 */ if (mbc->chain->m_len != 8) { printf("Fail: mbm_put_utrunc2 len=%d\n", mbc->chain->m_len); return; } if (memcmp(mbc->chain->m_data, wire, 10)) { printf("Fail: mbm_put_utrunc2 cmp:\n"); hexdump((uchar_t *)mbc->chain->m_data, 8); return; } printf("Pass: mbm_put_utrunc2\n"); out: smb_mbc_free(mbc); } static void mbm_put_mbuf1() { uint8_t wire[] = "onetwo"; mbuf_chain_t mbc, mbc2; int rc; MBC_INIT(&mbc, 16); MBC_INIT(&mbc2, 8); rc = smb_mbc_encodef(&mbc, "3s", "one"); if (rc != 0) { printf("Fail: mbm_put_mbuf1 encode 1 rc=%d\n", rc); goto out; } if (mbc.chain_offset != 3) { printf("Fail: mbm_put_mbuf1 encode 1 len=%d\n", mbc.chain_offset); goto out; } rc = smb_mbc_encodef(&mbc2, "s", "two"); if (rc != 0) { printf("Fail: mbm_put_mbuf1 encode 2 rc=%d\n", rc); goto out; } if (mbc2.chain_offset != 4) { printf("Fail: mbm_put_mbuf1 encode 2 len=%d\n", mbc.chain_offset); goto out; } /* Append */ rc = smb_mbc_encodef(&mbc, "m", mbc2.chain); mbc2.chain = NULL; if (rc != 0) { printf("Fail: mbm_put_mbuf1 encode 3 rc=%d\n", rc); goto out; } if (mbc.chain_offset != 7) { printf("Fail: mbm_put_mbuf1 encode 3 len=%d\n", mbc.chain_offset); goto out; } if (memcmp(mbc.chain->m_data, wire, 7)) { printf("Fail: mbm_put_mbuf1 cmp:\n"); hexdump((uchar_t *)mbc.chain->m_data, 7); goto out; } printf("Pass: mbm_put_mbuf1\n"); out: MBC_FLUSH(&mbc); MBC_FLUSH(&mbc2); } /* * Verify m_prepend works */ static void mbm_put_mbuf2() { uint8_t wire[] = "one.two"; mbuf_chain_t mbc; mbuf_t *m; int len, rc; MBC_INIT(&mbc, 512); rc = smb_mbc_encodef(&mbc, "s", "two"); if (rc != 0) { printf("Fail: mbm_put_mbuf2 encode 1 rc=%d\n", rc); goto out; } if (mbc.chain_offset != 4) { printf("Fail: mbm_put_mbuf2 encode 1 len=%d\n", mbc.chain_offset); goto out; } /* Prepend. Should use prepend space, not allocate. */ m = m_prepend(mbc.chain, 4, M_WAIT); if (m != mbc.chain) { (void) m_free(m); printf("Fail: mbm_put_mbuf2 m_prepend error\n", rc); goto out; } /* Now write into the prepend space. */ bcopy("one.", m->m_data, 4); /* Verify length and content */ len = MBC_LENGTH(&mbc); if (len != 8) { printf("Fail: mbm_put_mbuf2 encode 2 len=%d\n", mbc.chain_offset); goto out; } if (memcmp(mbc.chain->m_data, wire, 7)) { printf("Fail: mbm_put_mbuf2 cmp:\n"); hexdump((uchar_t *)mbc.chain->m_data, 7); goto out; } printf("Pass: mbm_put_mbuf2\n"); out: MBC_FLUSH(&mbc); } /* * Check how mbc_marshal_make_room crosses a message boundary */ static void mbm_put_mbuf3() { mbuf_chain_t mbc; mbuf_t *m; char *p; int rc; MBC_INIT(&mbc, 16384); /* * Encode near the end of the first mbuf * running over into the second. */ m = mbc.chain; mbc.chain_offset = M_TRAILINGSPACE(m) - 4; rc = smb_mbc_encodef(&mbc, "s", "one.two"); if (rc != 0) { printf("Fail: mbm_put_mbuf3 encode 1 rc=%d\n", rc); goto out; } /* Verify first segment */ p = m->m_data + m->m_len - 4; if (memcmp(p, "one.", 4)) { printf("Fail: mbm_put_mbuf3 cmp1:\n"); hexdump((uchar_t *)p, 4); goto out; } /* Verify second segment */ p = m->m_next->m_data; if (memcmp(p, "two", 4)) { printf("Fail: mbm_put_mbuf3 cmp2:\n"); hexdump((uchar_t *)p, 4); goto out; } printf("Pass: mbm_put_mbuf3\n"); out: MBC_FLUSH(&mbc); } /* * Parse an ascii string. */ static void mbm_get_a0() { uint8_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; mbuf_chain_t mbc; char *s; int rc; uint16_t w; bzero(&mbc, sizeof (mbc)); MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); rc = smb_mbc_decodef(&mbc, "%sw", &test_sr, &s, &w); if (rc != 0) { printf("Fail: mbm_get_a0 decode\n"); goto out; } /* * Decode a word after the string to make sure we * end up positioned correctly after the string. */ if (w != 42) { printf("Fail: mbm_get_a0 w=%d\n", w); return; } if (strcmp(s, "one") != 0) { printf("Fail: mbm_get_a0 cmp: <%s>\n", s); return; } printf("Pass: mbm_get_a0\n"); out: MBC_FLUSH(&mbc); } /* * Parse an ascii string, no NULL */ static void mbm_get_a1() { uint8_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; mbuf_chain_t mbc; char *s; int rc; uint16_t w; bzero(&mbc, sizeof (mbc)); MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); rc = smb_mbc_decodef(&mbc, "%3s.w", &test_sr, &s, &w); if (rc != 0) { printf("Fail: mbm_get_a1 decode\n"); goto out; } /* * Decode a word after the string to make sure we * end up positioned correctly after the string. */ if (w != 42) { printf("Fail: mbm_get_a1 w=%d\n", w); return; } if (strcmp(s, "one") != 0) { printf("Fail: mbm_get_a1 cmp: <%s>\n", s); return; } printf("Pass: mbm_get_a1\n"); out: MBC_FLUSH(&mbc); } /* parse exactly to end of data */ static void mbm_get_a2() { uint8_t wire[] = { 'o', 'n', 'e' }; mbuf_chain_t mbc; char *s; int rc; bzero(&mbc, sizeof (mbc)); MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); rc = smb_mbc_decodef(&mbc, "%3s", &test_sr, &s); if (rc != 0) { printf("Fail: mbm_get_a2 decode\n"); goto out; } if (mbc.chain_offset != 3) { printf("Fail: mbm_get_a2 wrong pos\n"); return; } if (strcmp(s, "one") != 0) { printf("Fail: mbm_get_a2 cmp: <%s>\n", s); return; } printf("Pass: mbm_get_a2\n"); out: MBC_FLUSH(&mbc); } /* * Parse a unicode string. */ static void mbm_get_u0() { uint16_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; mbuf_chain_t mbc; char *s; int rc; uint16_t w; bzero(&mbc, sizeof (mbc)); MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); rc = smb_mbc_decodef(&mbc, "%Uw", &test_sr, &s, &w); if (rc != 0) { printf("Fail: mbm_get_u0 decode\n"); goto out; } /* * Decode a word after the string to make sure we * end up positioned correctly after the string. */ if (w != 42) { printf("Fail: mbm_get_u0 w=%d\n", w); return; } if (strcmp(s, "one") != 0) { printf("Fail: mbm_get_u0 cmp: <%s>\n", s); return; } printf("Pass: mbm_get_u0\n"); out: MBC_FLUSH(&mbc); } /* * Parse a string that's NOT null terminated. */ static void mbm_get_u1() { uint16_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; mbuf_chain_t mbc; char *s; int rc; uint16_t w; bzero(&mbc, sizeof (mbc)); MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); rc = smb_mbc_decodef(&mbc, "%6U..w", &test_sr, &s, &w); if (rc != 0) { printf("Fail: mbm_get_u1 decode\n"); goto out; } /* * Decode a word after the string to make sure we * end up positioned correctly after the string. */ if (w != 42) { printf("Fail: mbm_get_u1 w=%d\n", w); return; } if (strcmp(s, "one") != 0) { printf("Fail: mbm_get_u1 cmp: <%s>\n", s); return; } printf("Pass: mbm_get_u1\n"); out: MBC_FLUSH(&mbc); } /* parse exactly to end of data */ static void mbm_get_u2() { uint16_t wire[] = { 't', 'w', 'o' }; mbuf_chain_t mbc; char *s; int rc; bzero(&mbc, sizeof (mbc)); MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); rc = smb_mbc_decodef(&mbc, "%6U", &test_sr, &s); if (rc != 0) { printf("Fail: mbm_get_u2 decode\n"); goto out; } if (mbc.chain_offset != 6) { printf("Fail: mbm_get_u2 wrong pos\n"); return; } if (strcmp(s, "two") != 0) { printf("Fail: mbm_get_u2 cmp: <%s>\n", s); return; } printf("Pass: mbm_get_a2\n"); out: MBC_FLUSH(&mbc); } static void mbm_get_u3() { mbuf_chain_t mbc; char *s; int rc; bzero(&mbc, sizeof (mbc)); MBC_ATTACH_BUF(&mbc, (uchar_t *)wcsa, sizeof (wcsa)); rc = smb_mbc_decodef(&mbc, "%#U", &test_sr, sizeof (wcsa), &s); if (rc != 0) { printf("Fail: mbm_get_u3 decode\n"); goto out; } if (strcmp(s, mbsa) != 0) { printf("Fail: mbm_get_u3 cmp: <%s>\n", s); return; } printf("Pass: mbm_get_u3\n"); out: MBC_FLUSH(&mbc); } static void mbm_get_u4() { mbuf_chain_t mbc; char *s; int rc; bzero(&mbc, sizeof (mbc)); MBC_ATTACH_BUF(&mbc, (uchar_t *)wcsp, sizeof (wcsp)); rc = smb_mbc_decodef(&mbc, "%#U", &test_sr, sizeof (wcsp), &s); if (rc != 0) { printf("Fail: mbm_get_u4 decode\n"); goto out; } if (strcmp(s, mbsp) != 0) { printf("Fail: mbm_get_u4 cmp: <%s>\n", s); return; } printf("Pass: mbm_get_u4\n"); out: MBC_FLUSH(&mbc); } void test_mbmarshal() { smb_mbc_init(); test_ssn.dialect = 0x210; // SMB 2.1 test_sr.session = &test_ssn; test_sr.sr_magic = SMB_REQ_MAGIC; smb_srm_init(&test_sr); mbm_put_a0(); mbm_put_a1(); mbm_put_apad(); mbm_put_atrunc1(); mbm_put_atrunc2(); mbm_put_u0(); mbm_put_u1(); mbm_put_u3(); mbm_put_u4(); mbm_put_upad(); mbm_put_utrunc1(); mbm_put_utrunc2(); mbm_put_mbuf1(); mbm_put_mbuf2(); mbm_put_mbuf3(); mbm_get_a0(); mbm_get_a1(); mbm_get_a2(); mbm_get_u0(); mbm_get_u1(); mbm_get_u2(); mbm_get_u3(); mbm_get_u4(); smb_srm_fini(&test_sr); smb_mbc_fini(); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ /* * A few excerpts from smb_kutil.c */ #include #include #include #include #include #include #include time_t tzh_leapcnt = 0; struct tm *smb_gmtime_r(time_t *clock, struct tm *result); time_t smb_timegm(struct tm *tm); struct tm { int tm_sec; int tm_min; int tm_hour; int tm_mday; int tm_mon; int tm_year; int tm_wday; int tm_yday; int tm_isdst; }; static const int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; uint64_t smb_time_unix_to_nt(timestruc_t *unix_time) { uint64_t nt_time; if ((unix_time->tv_sec == 0) && (unix_time->tv_nsec == 0)) return (0); nt_time = unix_time->tv_sec; nt_time *= 10000000; /* seconds to 100ns */ nt_time += unix_time->tv_nsec / 100; return (nt_time + NT_TIME_BIAS); } void smb_time_nt_to_unix(uint64_t nt_time, timestruc_t *unix_time) { uint32_t seconds; ASSERT(unix_time); if ((nt_time == 0) || (nt_time == -1)) { unix_time->tv_sec = 0; unix_time->tv_nsec = 0; return; } /* * Can't represent times less than or equal NT_TIME_BIAS, * so convert them to the oldest date we can store. * Note that time zero is "special" being converted * both directions as 0:0 (unix-to-nt, nt-to-unix). */ if (nt_time <= NT_TIME_BIAS) { unix_time->tv_sec = 0; unix_time->tv_nsec = 100; return; } nt_time -= NT_TIME_BIAS; seconds = nt_time / 10000000; unix_time->tv_sec = seconds; unix_time->tv_nsec = (nt_time % 10000000) * 100; } /* * smb_time_dos_to_unix * * Convert SMB_DATE & SMB_TIME values to a unix timestamp. * * A date/time field of 0 means that that server file system * assigned value need not be changed. The behaviour when the * date/time field is set to -1 is not documented but is * generally treated like 0. * If date or time is 0 or -1 the unix time is returned as 0 * so that the caller can identify and handle this special case. */ int32_t smb_time_dos_to_unix(int16_t date, int16_t time) { struct tm atm; if (((date == 0) || (time == 0)) || ((date == -1) || (time == -1))) { return (0); } atm.tm_year = ((date >> 9) & 0x3F) + 80; atm.tm_mon = ((date >> 5) & 0x0F) - 1; atm.tm_mday = ((date >> 0) & 0x1F); atm.tm_hour = ((time >> 11) & 0x1F); atm.tm_min = ((time >> 5) & 0x3F); atm.tm_sec = ((time >> 0) & 0x1F) << 1; return (smb_timegm(&atm)); } void smb_time_unix_to_dos(int32_t ux_time, int16_t *date_p, int16_t *time_p) { struct tm atm; int i; time_t tmp_time; if (ux_time == 0) { *date_p = 0; *time_p = 0; return; } tmp_time = (time_t)ux_time; (void) smb_gmtime_r(&tmp_time, &atm); if (date_p) { i = 0; i += atm.tm_year - 80; i <<= 4; i += atm.tm_mon + 1; i <<= 5; i += atm.tm_mday; *date_p = (short)i; } if (time_p) { i = 0; i += atm.tm_hour; i <<= 6; i += atm.tm_min; i <<= 5; i += atm.tm_sec >> 1; *time_p = (short)i; } } /* * smb_gmtime_r * * Thread-safe version of smb_gmtime. Returns a null pointer if either * input parameter is a null pointer. Otherwise returns a pointer * to result. * * Day of the week calculation: the Epoch was a thursday. * * There are no timezone corrections so tm_isdst and tm_gmtoff are * always zero, and the zone is always WET. */ struct tm * smb_gmtime_r(time_t *clock, struct tm *result) { time_t tsec; int year; int month; int sec_per_month; if (clock == 0 || result == 0) return (0); bzero(result, sizeof (struct tm)); tsec = *clock; tsec -= tzh_leapcnt; result->tm_wday = tsec / SECSPERDAY; result->tm_wday = (result->tm_wday + TM_THURSDAY) % DAYSPERWEEK; year = EPOCH_YEAR; while (tsec >= (isleap(year) ? (SECSPERDAY * DAYSPERLYEAR) : (SECSPERDAY * DAYSPERNYEAR))) { if (isleap(year)) tsec -= SECSPERDAY * DAYSPERLYEAR; else tsec -= SECSPERDAY * DAYSPERNYEAR; ++year; } result->tm_year = year - TM_YEAR_BASE; result->tm_yday = tsec / SECSPERDAY; for (month = TM_JANUARY; month <= TM_DECEMBER; ++month) { sec_per_month = days_in_month[month] * SECSPERDAY; if (month == TM_FEBRUARY && isleap(year)) sec_per_month += SECSPERDAY; if (tsec < sec_per_month) break; tsec -= sec_per_month; } result->tm_mon = month; result->tm_mday = (tsec / SECSPERDAY) + 1; tsec %= SECSPERDAY; result->tm_sec = tsec % 60; tsec /= 60; result->tm_min = tsec % 60; tsec /= 60; result->tm_hour = (int)tsec; return (result); } /* * smb_timegm * * Converts the broken-down time in tm to a time value, i.e. the number * of seconds since the Epoch (00:00:00 UTC, January 1, 1970). This is * not a POSIX or ANSI function. Per the man page, the input values of * tm_wday and tm_yday are ignored and, as the input data is assumed to * represent GMT, we force tm_isdst and tm_gmtoff to 0. * * Before returning the clock time, we use smb_gmtime_r to set up tm_wday * and tm_yday, and bring the other fields within normal range. I don't * think this is really how it should be done but it's convenient for * now. */ time_t smb_timegm(struct tm *tm) { time_t tsec; int dd; int mm; int yy; int year; if (tm == 0) return (-1); year = tm->tm_year + TM_YEAR_BASE; tsec = tzh_leapcnt; for (yy = EPOCH_YEAR; yy < year; ++yy) { if (isleap(yy)) tsec += SECSPERDAY * DAYSPERLYEAR; else tsec += SECSPERDAY * DAYSPERNYEAR; } for (mm = TM_JANUARY; mm < tm->tm_mon; ++mm) { dd = days_in_month[mm] * SECSPERDAY; if (mm == TM_FEBRUARY && isleap(year)) dd += SECSPERDAY; tsec += dd; } tsec += (tm->tm_mday - 1) * SECSPERDAY; tsec += tm->tm_sec; tsec += tm->tm_min * SECSPERMIN; tsec += tm->tm_hour * SECSPERHOUR; tm->tm_isdst = 0; (void) smb_gmtime_r(&tsec, tm); return (tsec); } /* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2019 Nexenta by DDN, Inc. All rights reserved. */ /* * Test putting/getting unicode strings in mbchains. */ #include #include #include #include #include #include #include #include "test_defs.h" static char mbsa[] = "A\xef\xbc\xa1."; // A fwA . (5) static char mbsp[] = "P\xf0\x9f\x92\xa9."; // P poop . (6) static smb_wchar_t wcsa[] = { 'A', 0xff21, '.', 0 }; // (3) static smb_wchar_t wcsp[] = { 'P', 0xd83d, 0xdca9, '.', 0 }; // (4) /* * Put ASCII string with NULL */ static void msg_put_a0() { uint8_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; uint8_t temp[32]; smb_msgbuf_t mb; int mbflags = 0; int rc; smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); rc = smb_msgbuf_encode(&mb, "sw", "one", 42); if (rc != 6) { printf("Fail: msg_put_a0 encode\n"); goto out; } if (memcmp(temp, wire, 6)) { printf("Fail: msg_put_a0 cmp:\n"); hexdump((uchar_t *)temp, 6); return; } printf("Pass: msg_put_a0\n"); out: smb_msgbuf_term(&mb); } /* * Put ASCII string, no NULL */ static void msg_put_a1() { uint8_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; uint8_t temp[32]; smb_msgbuf_t mb; int mbflags = 0; int rc; smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); rc = smb_msgbuf_encode(&mb, "4sw", "one.", 42); if (rc != 6) { printf("Fail: msg_put_a1 encode\n"); goto out; } if (memcmp(temp, wire, 6)) { printf("Fail: msg_put_a1 cmp:\n"); hexdump((uchar_t *)temp, 6); return; } printf("Pass: msg_put_a1\n"); out: smb_msgbuf_term(&mb); } static void msg_put_apad() { uint8_t wire[] = { 'o', 'n', 'e', 0, 0 }; uint8_t temp[32]; smb_msgbuf_t mb; int mbflags = 0; int rc; smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); /* Encode with wire length > strlen */ rc = smb_msgbuf_encode(&mb, "5s", "one"); if (rc != 5) { printf("Fail: msg_put_apad encode\n"); goto out; } if (memcmp(temp, wire, 5)) { printf("Fail: msg_put_apad cmp:\n"); hexdump((uchar_t *)temp, 5); return; } printf("Pass: msg_put_apad\n"); out: smb_msgbuf_term(&mb); } static void msg_put_atrunc1() { uint8_t wire[] = { 'o', 'n', 'e', 't', }; uint8_t temp[32]; smb_msgbuf_t mb; int mbflags = 0; int rc; smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); /* Encode with wire length < strlen */ rc = smb_msgbuf_encode(&mb, "4s", "onetwo"); /* Trunc should put exactly 4 */ if (rc != 4) { printf("Fail: msg_put_atrunc1 encode\n"); goto out; } if (memcmp(temp, wire, 4)) { printf("Fail: msg_put_atrunc1 cmp:\n"); hexdump((uchar_t *)temp, 4); return; } printf("Pass: msg_put_atrunc1\n"); out: smb_msgbuf_term(&mb); } static void msg_put_atrunc2() { uint8_t wire[] = { 'o', 'n', 'e', 't', 0}; uint8_t temp[32]; smb_msgbuf_t mb; int mbflags = 0; int rc; (void) memset(temp, 0, sizeof (temp)); smb_msgbuf_init(&mb, temp, 4, mbflags); /* Encode with wire length < strlen */ rc = smb_msgbuf_encode(&mb, "s", "onetwo"); /* Trunc should return "overflow" */ if (rc != -1) { printf("Fail: msg_put_atrunc2 encode rc=%d\n", rc); goto out; } if (memcmp(temp, wire, 5)) { printf("Fail: msg_put_atrunc2 cmp:\n"); hexdump((uchar_t *)temp, 5); return; } printf("Pass: msg_put_atrunc2\n"); out: smb_msgbuf_term(&mb); } /* * Put unicode string with NULL */ static void msg_put_u0() { uint16_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; uint8_t temp[32]; smb_msgbuf_t mb; int mbflags = 0; int rc; smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); rc = smb_msgbuf_encode(&mb, "Uw", "one", 42); if (rc != 10) { printf("Fail: msg_put_u0 encode\n"); goto out; } if (memcmp(temp, wire, 10)) { printf("Fail: msg_put_u0 cmp:\n"); hexdump((uchar_t *)temp, 10); return; } printf("Pass: msg_put_u0\n"); out: smb_msgbuf_term(&mb); } /* * Put unicode string, no NULL */ static void msg_put_u1() { uint16_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; uint8_t temp[32]; smb_msgbuf_t mb; int mbflags = 0; int rc; smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); rc = smb_msgbuf_encode(&mb, "8Uw", "one.", 42); if (rc != 10) { printf("Fail: msg_put_u1 encode\n"); goto out; } if (memcmp(temp, wire, 10)) { printf("Fail: msg_put_u1 cmp:\n"); hexdump((uchar_t *)temp, 10); return; } printf("Pass: msg_put_u1\n"); out: smb_msgbuf_term(&mb); } static void msg_put_u3() { uint8_t temp[32]; smb_msgbuf_t mb; int mbflags = 0; int rc; smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); rc = smb_msgbuf_encode(&mb, "U", mbsa); if (rc != 8) { printf("Fail: msg_put_u3 encode\n"); goto out; } if (memcmp(temp, wcsa, 8)) { printf("Fail: msg_put_u3 cmp:\n"); hexdump((uchar_t *)temp, 8); return; } printf("Pass: msg_put_u3\n"); out: smb_msgbuf_term(&mb); } static void msg_put_u4() { uint8_t temp[32]; smb_msgbuf_t mb; int mbflags = 0; int rc; smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); rc = smb_msgbuf_encode(&mb, "U", mbsp); if (rc != 10) { printf("Fail: msg_put_u4 encode\n"); goto out; } if (memcmp(temp, wcsp, 10)) { printf("Fail: msg_put_u4 cmp:\n"); hexdump((uchar_t *)temp, 10); return; } printf("Pass: msg_put_u4\n"); out: smb_msgbuf_term(&mb); } static void msg_put_upad() { uint16_t wire[] = { 'o', 'n', 'e', 0, 0 }; uint8_t temp[32]; smb_msgbuf_t mb; int mbflags = 0; int rc; smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); /* Encode with wire length > strlen */ rc = smb_msgbuf_encode(&mb, "10U", "one"); if (rc != 10) { printf("Fail: msg_put_upad encode\n"); goto out; } if (memcmp(temp, wire, 10)) { printf("Fail: msg_put_upad cmp:\n"); hexdump((uchar_t *)temp, 10); return; } printf("Pass: msg_put_upad\n"); out: smb_msgbuf_term(&mb); } static void msg_put_utrunc1() { uint16_t wire[] = { 'o', 'n', 'e', 't' }; uint8_t temp[32]; smb_msgbuf_t mb; int mbflags = 0; int rc; smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); /* Encode with wire length < strlen */ rc = smb_msgbuf_encode(&mb, "8U", "onetwo"); /* Trunc should put exactly 8 */ if (rc != 8) { printf("Fail: msg_put_utrunc1 encode\n"); goto out; } if (memcmp(temp, wire, 8)) { printf("Fail: msg_put_utrunc1 cmp:\n"); hexdump((uchar_t *)temp, 8); return; } printf("Pass: msg_put_utrunc1\n"); out: smb_msgbuf_term(&mb); } static void msg_put_utrunc2() { uint16_t wire[] = { 'o', 'n', 'e', 't', 0 }; uint8_t temp[32]; smb_msgbuf_t mb; int mbflags = 0; int rc; (void) memset(temp, 0, sizeof (temp)); smb_msgbuf_init(&mb, temp, 8, mbflags); /* Encode with wire length < strlen */ rc = smb_msgbuf_encode(&mb, "U", "onetwo"); /* Trunc should return "overflow" */ if (rc != -1) { printf("Fail: msg_put_utrunc2 encode rc=%d\n", rc); goto out; } if (memcmp(temp, wire, 10)) { printf("Fail: msg_put_utrunc2 cmp:\n"); hexdump((uchar_t *)temp, 10); return; } printf("Pass: msg_put_utrunc2\n"); out: smb_msgbuf_term(&mb); } /* * Parse an ascii string. */ static void msg_get_a0() { uint8_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; smb_msgbuf_t mb; int mbflags = 0; char *s; int rc; uint16_t w; smb_msgbuf_init(&mb, wire, sizeof (wire), mbflags); rc = smb_msgbuf_decode(&mb, "sw", &s, &w); if (rc != 6) { printf("Fail: msg_get_a0 decode\n"); goto out; } /* * Decode a word after the string to make sure we * end up positioned correctly after the string. */ if (w != 42) { printf("Fail: msg_get_a0 w=%d\n", w); return; } if (strcmp(s, "one") != 0) { printf("Fail: msg_get_a0 cmp: <%s>\n", s); return; } printf("Pass: msg_get_a0\n"); out: smb_msgbuf_term(&mb); } /* * Parse an ascii string, no NULL */ static void msg_get_a1() { uint8_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; smb_msgbuf_t mb; int mbflags = 0; char *s; int rc; uint16_t w; smb_msgbuf_init(&mb, wire, sizeof (wire), mbflags); rc = smb_msgbuf_decode(&mb, "3s.w", &s, &w); if (rc != 6) { printf("Fail: msg_get_a1 decode\n"); goto out; } /* * Decode a word after the string to make sure we * end up positioned correctly after the string. */ if (w != 42) { printf("Fail: msg_get_a1 w=%d\n", w); return; } if (strcmp(s, "one") != 0) { printf("Fail: msg_get_a1 cmp: <%s>\n", s); return; } printf("Pass: msg_get_a1\n"); out: smb_msgbuf_term(&mb); } /* parse exactly to end of data */ static void msg_get_a2() { uint8_t wire[] = { 'o', 'n', 'e' }; smb_msgbuf_t mb; int mbflags = 0; char *s; int rc; smb_msgbuf_init(&mb, wire, sizeof (wire), mbflags); rc = smb_msgbuf_decode(&mb, "3s", &s); if (rc != 3) { printf("Fail: msg_get_a2 decode\n"); goto out; } if (mb.scan != mb.end) { printf("Fail: msg_get_a2 wrong pos\n"); return; } if (strcmp(s, "one") != 0) { printf("Fail: msg_get_a2 cmp: <%s>\n", s); return; } printf("Pass: msg_get_a2\n"); out: smb_msgbuf_term(&mb); } /* * Parse a unicode string. */ static void msg_get_u0() { uint16_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; smb_msgbuf_t mb; int mbflags = 0; char *s; int rc; uint16_t w; smb_msgbuf_init(&mb, (uint8_t *)wire, sizeof (wire), mbflags); rc = smb_msgbuf_decode(&mb, "Uw", &s, &w); if (rc != 10) { printf("Fail: msg_get_u0 decode\n"); goto out; } /* * Decode a word after the string to make sure we * end up positioned correctly after the string. */ if (w != 42) { printf("Fail: msg_get_u0 w=%d\n", w); return; } if (strcmp(s, "one") != 0) { printf("Fail: msg_get_u0 cmp: <%s>\n", s); return; } printf("Pass: msg_get_u0\n"); out: smb_msgbuf_term(&mb); } /* * Parse a string that's NOT null terminated. */ static void msg_get_u1() { uint16_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; smb_msgbuf_t mb; int mbflags = 0; char *s; int rc; uint16_t w; smb_msgbuf_init(&mb, (uint8_t *)wire, sizeof (wire), mbflags); rc = smb_msgbuf_decode(&mb, "6U..w", &s, &w); if (rc != 10) { printf("Fail: msg_get_u1 decode\n"); goto out; } /* * Decode a word after the string to make sure we * end up positioned correctly after the string. */ if (w != 42) { printf("Fail: msg_get_u1 w=%d\n", w); return; } if (strcmp(s, "one") != 0) { printf("Fail: msg_get_u1 cmp: <%s>\n", s); return; } printf("Pass: msg_get_u1\n"); out: smb_msgbuf_term(&mb); } /* parse exactly to end of data */ static void msg_get_u2() { uint16_t wire[] = { 'o', 'n', 'e' }; smb_msgbuf_t mb; int mbflags = 0; char *s; int rc; smb_msgbuf_init(&mb, (uint8_t *)wire, sizeof (wire), mbflags); rc = smb_msgbuf_decode(&mb, "6U", &s); if (rc != 6) { printf("Fail: msg_get_u2 decode\n"); goto out; } if (mb.scan != mb.end) { printf("Fail: msg_get_u2 wrong pos\n"); return; } if (strcmp(s, "one") != 0) { printf("Fail: msg_get_u2 cmp: <%s>\n", s); return; } printf("Pass: msg_get_u2\n"); out: smb_msgbuf_term(&mb); } static void msg_get_u3() { smb_msgbuf_t mb; int mbflags = 0; char *s; int rc; smb_msgbuf_init(&mb, (uint8_t *)wcsa, sizeof (wcsa), mbflags); rc = smb_msgbuf_decode(&mb, "#U", sizeof (wcsa), &s); if (rc != 8) { printf("Fail: msg_get_u3 decode\n"); goto out; } if (strcmp(s, mbsa) != 0) { printf("Fail: msg_get_u3 cmp: <%s>\n", s); return; } printf("Pass: msg_get_u3\n"); out: smb_msgbuf_term(&mb); } static void msg_get_u4() { smb_msgbuf_t mb; int mbflags = 0; char *s; int rc; smb_msgbuf_init(&mb, (uint8_t *)wcsp, sizeof (wcsp), mbflags); rc = smb_msgbuf_decode(&mb, "#U", sizeof (wcsp), &s); if (rc != 10) { printf("Fail: msg_get_u4 decode\n"); goto out; } if (strcmp(s, mbsp) != 0) { printf("Fail: msg_get_u4 cmp: <%s>\n", s); return; } printf("Pass: msg_get_u4\n"); out: smb_msgbuf_term(&mb); } void test_msgbuf() { msg_put_a0(); msg_put_a1(); msg_put_apad(); msg_put_atrunc1(); msg_put_atrunc2(); msg_put_u0(); msg_put_u1(); msg_put_u3(); msg_put_u4(); msg_put_upad(); msg_put_utrunc1(); msg_put_utrunc2(); msg_get_a0(); msg_get_a1(); msg_get_a2(); msg_get_u0(); msg_get_u1(); msg_get_u2(); msg_get_u3(); msg_get_u4(); }