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
@@ -20,11 +20,11 @@
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
- * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
*/
/*
* SMB mbuf marshaling encode/decode.
*/
@@ -37,18 +37,17 @@
#define DECODE_NO_ERROR 0
#define DECODE_NO_MORE_DATA 1
#define DECODE_ALLOCATION_ERROR 2
#define DECODE_CONVERSION_ERROR 3
-static int mbc_marshal_cstou8(char *, char *, size_t, char *, size_t);
static int mbc_marshal_make_room(mbuf_chain_t *, int32_t);
static void mbc_marshal_store_byte(mbuf_chain_t *, uint8_t);
static int mbc_marshal_put_char(mbuf_chain_t *mbc, uint8_t);
static int mbc_marshal_put_short(mbuf_chain_t *mbc, uint16_t);
static int mbc_marshal_put_long(mbuf_chain_t *mbc, uint32_t);
static int mbc_marshal_put_long_long(mbuf_chain_t *mbc, uint64_t);
-static int mbc_marshal_put_ascii_string(mbuf_chain_t *, char *, int);
+static int mbc_marshal_put_oem_string(mbuf_chain_t *, char *, int);
static int mbc_marshal_put_unicode_string(mbuf_chain_t *, char *, int);
static int mbc_marshal_put_uio(mbuf_chain_t *, struct uio *);
static int mbc_marshal_put_mbufs(mbuf_chain_t *mbc, mbuf_t *m);
static int mbc_marshal_put_mbuf_chain(mbuf_chain_t *mbc, mbuf_chain_t *nmbc);
static uint8_t mbc_marshal_fetch_byte(mbuf_chain_t *mbc);
@@ -56,14 +55,14 @@
static int mbc_marshal_get_short(mbuf_chain_t *mbc, uint16_t *data);
static int mbc_marshal_get_long(mbuf_chain_t *mbc, uint32_t *data);
static uint64_t qswap(uint64_t ll);
static int mbc_marshal_get_odd_long_long(mbuf_chain_t *mbc, uint64_t *data);
static int mbc_marshal_get_long_long(mbuf_chain_t *mbc, uint64_t *data);
-static int mbc_marshal_get_ascii_string(smb_request_t *, mbuf_chain_t *,
- uint8_t **ascii, int);
+static int mbc_marshal_get_oem_string(smb_request_t *, mbuf_chain_t *,
+ char **, int);
static int mbc_marshal_get_unicode_string(smb_request_t *, mbuf_chain_t *,
- uint8_t **, int);
+ char **, int);
static int mbc_marshal_get_mbufs(mbuf_chain_t *, int32_t, mbuf_t **);
static int mbc_marshal_get_mbuf_chain(mbuf_chain_t *, int32_t, mbuf_chain_t *);
static int mbc_marshal_get_uio(mbuf_chain_t *, struct uio *);
static int mbc_marshal_get_skip(mbuf_chain_t *, uint_t);
@@ -150,11 +149,11 @@
smb_mbc_vdecodef(mbuf_chain_t *mbc, const char *fmt, va_list ap)
{
uint8_t c;
uint8_t cval;
uint8_t *cvalp;
- uint8_t **cvalpp;
+ char **charpp;
uint16_t wval;
uint16_t *wvalp;
uint32_t *lvalp;
uint64_t *llvalp;
smb_vdb_t *vdp;
@@ -292,11 +291,11 @@
case 'L':
if (mbc_marshal_get_char(mbc, &cval) != 0)
return (-1);
if (cval != 2)
return (-1);
- goto ascii_conversion;
+ goto oem_conversion;
case 'A':
case 'S':
if (mbc_marshal_get_char(mbc, &cval) != 0)
return (-1);
@@ -308,31 +307,29 @@
case 'u': /* Convert from unicode if flags are set */
if (unicode)
goto unicode_translation;
/* FALLTHROUGH */
- case 's':
-ascii_conversion:
+ case 's': /* get OEM string */
+oem_conversion:
ASSERT(sr != NULL);
- cvalpp = va_arg(ap, uint8_t **);
+ charpp = va_arg(ap, char **);
if (!repc_specified)
repc = 0;
- if (mbc_marshal_get_ascii_string(sr,
- mbc, cvalpp, repc) != 0)
+ if (mbc_marshal_get_oem_string(sr,
+ mbc, charpp, repc) != 0)
return (-1);
break;
- case 'U': /* Convert from unicode */
+ case 'U': /* get UTF-16 string */
unicode_translation:
ASSERT(sr != 0);
- cvalpp = va_arg(ap, uint8_t **);
+ charpp = va_arg(ap, char **);
if (!repc_specified)
repc = 0;
- if (mbc->chain_offset & 1)
- mbc->chain_offset++;
if (mbc_marshal_get_unicode_string(sr,
- mbc, cvalpp, repc) != 0)
+ mbc, charpp, repc) != 0)
return (-1);
break;
case 'Y': /* dos time to unix time tt/dd */
lvalp = va_arg(ap, uint32_t *);
@@ -517,10 +514,11 @@
* U Align the offset of the mbuf chain on a 16bit boundary.
*/
int
smb_mbc_vencodef(mbuf_chain_t *mbc, const char *fmt, va_list ap)
{
+ char *charp;
uint8_t *cvalp;
timestruc_t *tvp;
smb_vdb_t *vdp;
smb_request_t *sr = NULL;
uint64_t llval;
@@ -547,11 +545,10 @@
repc_specified = B_TRUE;
} else if (c == '#') {
repc = va_arg(ap, int);
c = *fmt++;
repc_specified = B_TRUE;
-
}
switch (c) {
case '%':
sr = va_arg(ap, struct smb_request *);
@@ -657,11 +654,11 @@
break;
case 'L':
tag = 2;
- goto ascii_conversion;
+ goto oem_conversion;
case 'S':
case 'A':
tag = 4;
goto tagged_str;
@@ -678,19 +675,30 @@
case 'u': /* Convert from unicode if flags are set */
if (unicode)
goto unicode_translation;
/* FALLTHROUGH */
- case 's': /* ASCII/multibyte string */
-ascii_conversion: cvalp = va_arg(ap, uint8_t *);
+ case 's': /* put OEM string */
+oem_conversion:
+ charp = va_arg(ap, char *);
if (!repc_specified)
repc = 0;
- if (mbc_marshal_put_ascii_string(mbc,
- (char *)cvalp, repc) != 0)
+ if (mbc_marshal_put_oem_string(mbc,
+ charp, repc) != 0)
return (DECODE_NO_MORE_DATA);
break;
+ case 'U': /* put UTF-16 string */
+unicode_translation:
+ charp = va_arg(ap, char *);
+ if (!repc_specified)
+ repc = 0;
+ if (mbc_marshal_put_unicode_string(mbc,
+ charp, repc) != 0)
+ return (DECODE_NO_MORE_DATA);
+ break;
+
case 'Y': /* int32_t, encode dos date/time */
while (repc-- > 0) {
uint16_t d, t;
lval = va_arg(ap, uint32_t);
@@ -726,22 +734,10 @@
while (repc-- > 0)
if (mbc_marshal_put_char(mbc, 0) != 0)
return (DECODE_NO_MORE_DATA);
break;
- case 'U': /* Convert to unicode, align to word boundary */
-unicode_translation:
- if (mbc->chain_offset & 1)
- mbc->chain_offset++;
- cvalp = va_arg(ap, uint8_t *);
- if (!repc_specified)
- repc = 0;
- if (mbc_marshal_put_unicode_string(mbc,
- (char *)cvalp, repc) != 0)
- return (DECODE_NO_MORE_DATA);
- break;
-
default:
ASSERT(0);
return (-1);
}
}
@@ -918,10 +914,27 @@
return (0);
}
/*
+ * Put padding sufficient to align to A, where
+ * A is some power of 2 greater than zero.
+ */
+int
+smb_mbc_put_align(mbuf_chain_t *mbc, int align)
+{
+ int mask = align - 1;
+ int padsz;
+
+ ASSERT(align > 0 && (align & mask) == 0);
+ if ((mbc->chain_offset & mask) == 0)
+ return (0);
+ padsz = align - (mbc->chain_offset & mask);
+ return (smb_mbc_encodef(mbc, "#.", padsz));
+}
+
+/*
* Put data into mbuf chain allocating as needed.
* Adds room to end of mbuf chain if needed.
*/
static int
mbc_marshal_make_room(mbuf_chain_t *mbc, int32_t bytes_needed)
@@ -1066,83 +1079,153 @@
mbc_marshal_store_byte(mbc, data >> 56);
return (0);
}
/*
- * When need to convert from UTF-8 (internal format) to a single
- * byte string (external format ) when marshalling a string.
+ * Marshal a UTF-8 string (str) into mbc, converting to OEM codeset.
+ * Also write a null unless the repc count limits the length we put.
+ * When (repc > 0) the length we marshal must be exactly repc, and
+ * truncate or pad the mbc data as necessary.
+ * See also: msgbuf_put_oem_string
*/
static int
-mbc_marshal_put_ascii_string(mbuf_chain_t *mbc, char *mbs, int repc)
+mbc_marshal_put_oem_string(mbuf_chain_t *mbc, char *mbs, int repc)
{
- smb_wchar_t wide_char;
- int nbytes;
- int length;
+ uint8_t *oembuf = NULL;
+ uint8_t *s;
+ int oemlen;
+ int rlen;
+ int rc;
- if ((length = smb_sbequiv_strlen(mbs)) == -1)
+ /*
+ * Compute length of converted OEM string,
+ * NOT including null terminator
+ */
+ if ((oemlen = smb_sbequiv_strlen(mbs)) == -1)
return (DECODE_NO_MORE_DATA);
- length += sizeof (char);
-
- if ((repc > 0) && (repc < length))
- length = repc;
- if (mbc_marshal_make_room(mbc, length))
+ /*
+ * If repc not specified, put whole string + NULL,
+ * otherwise will truncate or pad as needed.
+ */
+ if (repc <= 0)
+ repc = oemlen + 1;
+ if (mbc_marshal_make_room(mbc, repc))
return (DECODE_NO_MORE_DATA);
- while (*mbs) {
/*
- * We should restore oem chars here.
+ * Convert into a temporary buffer
+ * Free oembuf before return.
*/
- nbytes = smb_mbtowc(&wide_char, mbs, MTS_MB_CHAR_MAX);
- if (nbytes == -1)
- return (DECODE_NO_MORE_DATA);
+ oembuf = smb_mem_zalloc(oemlen + 1);
+ ASSERT(oembuf != NULL);
+ rlen = smb_mbstooem(oembuf, mbs, oemlen);
+ if (rlen < 0) {
+ rc = DECODE_NO_MORE_DATA;
+ goto out;
+ }
+ if (rlen > oemlen)
+ rlen = oemlen;
+ oembuf[rlen] = '\0';
- mbc_marshal_store_byte(mbc, (uint8_t)wide_char);
-
- if (wide_char & 0xFF00)
- mbc_marshal_store_byte(mbc, wide_char >> 8);
-
- mbs += nbytes;
+ /*
+ * Copy the converted string into the message,
+ * truncated or paded as required.
+ */
+ s = oembuf;
+ while (repc > 0) {
+ mbc_marshal_store_byte(mbc, *s);
+ if (*s != '\0')
+ s++;
+ repc--;
}
+ rc = 0;
- mbc_marshal_store_byte(mbc, 0);
- return (0);
+out:
+ if (oembuf != NULL)
+ smb_mem_free(oembuf);
+ return (rc);
}
+/*
+ * Marshal a UTF-8 string (str) into mbc, converting to UTF-16.
+ * Also write a null unless the repc count limits the length.
+ * When (repc > 0) the length we marshal must be exactly repc,
+ * and truncate or pad the mbc data as necessary.
+ * See also: msgbuf_put_unicode_string
+ */
static int
-mbc_marshal_put_unicode_string(mbuf_chain_t *mbc, char *ascii, int repc)
+mbc_marshal_put_unicode_string(mbuf_chain_t *mbc, char *mbs, int repc)
{
- smb_wchar_t wchar;
- int consumed;
- int length;
+ smb_wchar_t *wcsbuf = NULL;
+ smb_wchar_t *wp;
+ size_t wcslen, wcsbytes;
+ size_t rlen;
+ int rc;
- if ((length = smb_wcequiv_strlen(ascii)) == -1)
+ /* align to word boundary */
+ if (mbc->chain_offset & 1) {
+ if (mbc_marshal_make_room(mbc, 1))
return (DECODE_NO_MORE_DATA);
+ mbc_marshal_store_byte(mbc, 0);
+ }
- length += sizeof (smb_wchar_t);
+ /*
+ * Compute length of converted UTF-16 string,
+ * NOT including null terminator (in bytes).
+ */
+ wcsbytes = smb_wcequiv_strlen(mbs);
+ if (wcsbytes == (size_t)-1)
+ return (DECODE_NO_MORE_DATA);
- if ((repc > 0) && (repc < length))
- length = repc;
-
- if (mbc_marshal_make_room(mbc, length))
+ /*
+ * If repc not specified, put whole string + NULL,
+ * otherwise will truncate or pad as needed.
+ */
+ if (repc <= 0)
+ repc = wcsbytes + 2;
+ if (mbc_marshal_make_room(mbc, repc))
return (DECODE_NO_MORE_DATA);
- while (length > 0) {
- consumed = smb_mbtowc(&wchar, ascii, MTS_MB_CHAR_MAX);
- if (consumed == -1)
- break; /* Invalid sequence */
+
/*
- * Note that consumed will be 0 when the null terminator
- * is encountered and ascii will not be advanced beyond
- * that point. Length will continue to be decremented so
- * we won't get stuck here.
+ * Convert into a temporary buffer
+ * Free wcsbuf before return.
*/
- ascii += consumed;
+ wcslen = wcsbytes / 2;
+ wcsbuf = smb_mem_zalloc(wcsbytes + 2);
+ ASSERT(wcsbuf != NULL);
+ rlen = smb_mbstowcs(wcsbuf, mbs, wcslen);
+ if (rlen == (size_t)-1) {
+ rc = DECODE_NO_MORE_DATA;
+ goto out;
+ }
+ if (rlen > wcslen)
+ rlen = wcslen;
+ wcsbuf[rlen] = 0;
+
+ /*
+ * Copy the converted string into the message,
+ * truncated or paded as required. Preserve
+ * little-endian order while copying.
+ */
+ wp = wcsbuf;
+ while (repc > 1) {
+ smb_wchar_t wchar = LE_IN16(wp);
mbc_marshal_store_byte(mbc, wchar);
mbc_marshal_store_byte(mbc, wchar >> 8);
- length -= sizeof (smb_wchar_t);
+ if (wchar != 0)
+ wp++;
+ repc -= sizeof (smb_wchar_t);
}
- return (0);
+ if (repc > 0)
+ mbc_marshal_store_byte(mbc, 0);
+
+ rc = 0;
+out:
+ if (wcsbuf != NULL)
+ smb_mem_free(wcsbuf);
+ return (rc);
}
static int /*ARGSUSED*/
uiorefnoop(caddr_t p, int size, int adj)
{
@@ -1373,105 +1456,163 @@
}
return (0);
}
/*
- * mbc_marshal_get_ascii_string
+ * mbc_marshal_get_oem_string
*
- * The ascii string in smb includes oem chars. Since the
- * system needs utf8 encodes unicode char, conversion is
- * required to convert the oem char to unicode and then
- * to encode the converted wchars to utf8 format.
- * Therefore, the **ascii returned will be in such format
- * instead of the real ASCII format.
+ * Decode an OEM string, returning its UTF-8 form in strpp,
+ * allocated using smb_srm_zalloc (automatically freed).
+ * If max_bytes != 0, consume at most max_bytes of the mbc.
+ * See also: msgbuf_get_oem_string
*/
static int
-mbc_marshal_get_ascii_string(
- smb_request_t *sr,
- mbuf_chain_t *mbc,
- uint8_t **ascii,
- int max_ascii)
+mbc_marshal_get_oem_string(smb_request_t *sr,
+ mbuf_chain_t *mbc, char **strpp, int max_bytes)
{
- char *rcvbuf;
- char *ch;
- int max;
- int length = 0;
+ char *mbs;
+ uint8_t *oembuf = NULL;
+ int oemlen, oemmax;
+ int mbsmax;
+ int rlen;
+ int rc;
- max = MALLOC_QUANTUM;
- rcvbuf = smb_srm_zalloc(sr, max);
+ if (max_bytes == 0)
+ max_bytes = 0xffff;
- if (max_ascii == 0)
- max_ascii = 0xffff;
-
- ch = rcvbuf;
+ /*
+ * Get the OtW data into a temporary buffer.
+ * Free oembuf before return.
+ */
+ oemlen = 0;
+ oemmax = MALLOC_QUANTUM;
+ oembuf = smb_mem_alloc(oemmax);
for (;;) {
- while (length < max) {
- if (max_ascii-- <= 0) {
- *ch++ = 0;
- goto multibyte_encode;
+ uint8_t ch;
+
+ if (oemlen >= max_bytes)
+ break;
+ if ((oemlen + 2) >= oemmax) {
+ oemmax += MALLOC_QUANTUM;
+ oembuf = smb_mem_realloc(oembuf, oemmax);
}
- if (MBC_ROOM_FOR(mbc, sizeof (char)) == 0) {
- /* Data will never be available */
- return (DECODE_NO_MORE_DATA);
+ if (mbc_marshal_get_char(mbc, &ch) != 0) {
+ rc = DECODE_NO_MORE_DATA;
+ goto out;
}
- if ((*ch++ = mbc_marshal_fetch_byte(mbc)) == 0)
- goto multibyte_encode;
- length++;
+ if (ch == 0)
+ break;
+ oembuf[oemlen++] = ch;
}
- max += MALLOC_QUANTUM;
- rcvbuf = smb_srm_rezalloc(sr, rcvbuf, max);
- ch = rcvbuf + length;
- }
+ oembuf[oemlen] = '\0';
-multibyte_encode:
/*
- * UTF-8 encode the string for internal system use.
+ * Get the buffer we'll return and convert to UTF-8.
+ * May take as much as double the space.
*/
- length = strlen(rcvbuf) + 1;
- *ascii = smb_srm_zalloc(sr, length * MTS_MB_CHAR_MAX);
- return (mbc_marshal_cstou8("CP850", (char *)*ascii,
- (size_t)length * MTS_MB_CHAR_MAX, rcvbuf, (size_t)length));
+ mbsmax = oemlen * 2;
+ mbs = smb_srm_zalloc(sr, mbsmax + 1);
+ ASSERT(mbs != NULL);
+ rlen = smb_oemtombs(mbs, oembuf, mbsmax);
+ if (rlen < 0) {
+ rc = DECODE_NO_MORE_DATA;
+ goto out;
+ }
+ if (rlen > mbsmax)
+ rlen = mbsmax;
+ mbs[rlen] = '\0';
+ *strpp = mbs;
+ rc = 0;
+
+out:
+ if (oembuf != NULL)
+ smb_mem_free(oembuf);
+ return (rc);
}
+/*
+ * mbc_marshal_get_unicode_string
+ *
+ * Decode a UTF-16 string, returning its UTF-8 form in strpp,
+ * allocated using smb_srm_zalloc (automatically freed).
+ * If max_bytes != 0, consume at most max_bytes of the mbc.
+ * See also: msgbuf_get_unicode_string
+ */
static int
mbc_marshal_get_unicode_string(smb_request_t *sr,
- mbuf_chain_t *mbc, uint8_t **ascii, int max_unicode)
+ mbuf_chain_t *mbc, char **strpp, int max_bytes)
{
- int max;
- uint16_t wchar;
- char *ch;
- int emitted;
- int length = 0;
+ char *mbs;
+ uint16_t *wcsbuf = NULL;
+ int wcslen; // wchar count
+ int wcsmax; // byte count
+ size_t mbsmax;
+ size_t rlen;
+ int rc;
- if (max_unicode == 0)
- max_unicode = 0xffff;
+ if (max_bytes == 0)
+ max_bytes = 0xffff;
- max = MALLOC_QUANTUM;
- *ascii = smb_srm_zalloc(sr, max);
+ /*
+ * Unicode strings are always word aligned.
+ */
+ if (mbc->chain_offset & 1) {
+ if (MBC_ROOM_FOR(mbc, sizeof (char)) == 0)
+ return (DECODE_NO_MORE_DATA);
+ mbc->chain_offset++;
+ }
- ch = (char *)*ascii;
+ /*
+ * Get the OtW data into a temporary buffer.
+ * Free wcsbuf before return.
+ */
+ wcslen = 0;
+ wcsmax = MALLOC_QUANTUM;
+ wcsbuf = smb_mem_alloc(wcsmax);
for (;;) {
- while ((length + MTS_MB_CHAR_MAX) < max) {
- if (max_unicode <= 0)
- goto done;
- max_unicode -= 2;
+ uint16_t wchar;
- if (mbc_marshal_get_short(mbc, &wchar) != 0)
- return (DECODE_NO_MORE_DATA);
-
- if (wchar == 0) goto done;
-
- emitted = smb_wctomb(ch, wchar);
- length += emitted;
- ch += emitted;
+ if ((wcslen * 2) >= max_bytes)
+ break;
+ if (((wcslen * 2) + 4) >= wcsmax) {
+ wcsmax += MALLOC_QUANTUM;
+ wcsbuf = smb_mem_realloc(wcsbuf, wcsmax);
}
- max += MALLOC_QUANTUM;
- *ascii = smb_srm_rezalloc(sr, *ascii, max);
- ch = (char *)*ascii + length;
+ if (mbc_marshal_get_short(mbc, &wchar) != 0) {
+ rc = DECODE_NO_MORE_DATA;
+ goto out;
}
-done: *ch = 0;
- return (0);
+ if (wchar == 0)
+ break;
+ /* Keep in little-endian form. */
+ LE_OUT16(wcsbuf + wcslen, wchar);
+ wcslen++;
+ }
+ wcsbuf[wcslen] = 0;
+
+ /*
+ * Get the buffer we'll return and convert to UTF-8.
+ * May take as much 4X number of wide chars.
+ */
+ mbsmax = wcslen * MTS_MB_CUR_MAX;
+ mbs = smb_srm_zalloc(sr, mbsmax + 1);
+ ASSERT(mbs != NULL);
+ rlen = smb_wcstombs(mbs, wcsbuf, mbsmax);
+ if (rlen == (size_t)-1) {
+ rc = DECODE_NO_MORE_DATA;
+ goto out;
+ }
+ if (rlen > mbsmax)
+ rlen = mbsmax;
+ mbs[rlen] = '\0';
+ *strpp = mbs;
+ rc = 0;
+
+out:
+ if (wcsbuf != NULL)
+ smb_mem_free(wcsbuf);
+ return (rc);
}
static int /*ARGSUSED*/
mbc_marshal_get_mbufs(mbuf_chain_t *mbc, int32_t bytes, mbuf_t **m)
{
@@ -1568,32 +1709,6 @@
{
if (MBC_ROOM_FOR(mbc, skip) == 0)
return (DECODE_NO_MORE_DATA);
mbc->chain_offset += skip;
return (0);
-}
-
-/*
- * Converts oem string to UTF-8 string with an output string of max
- * maxconv bytes. The string may be truncated or not null-terminated if
- * there is not enough room.
- *
- * returns -1, cnt (partial conversion) or 0 (success)
- */
-
-static int
-mbc_marshal_cstou8(char *cs, char *outbuf, size_t maxconv,
- char *inbuf, size_t srcbytes)
-{
- kiconv_t t2u;
- size_t inlen = srcbytes;
- size_t outlen = maxconv;
- int err = 0;
- size_t rc;
-
- if ((t2u = kiconv_open("UTF-8", cs)) == (kiconv_t)-1)
- return (-1);
-
- rc = kiconv(t2u, &inbuf, &inlen, &outbuf, &outlen, &err);
- (void) kiconv_close(t2u);
- return ((int)rc);
}