Print this page
1575 untangle libmlrpc ... (libmlrpc)


   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  * Copyright 2012 Milan Jurik. All rights reserved.

  25  */
  26 
  27 /*
  28  * Network Data Representation (NDR) is a compatible subset of the DCE RPC
  29  * and MSRPC NDR.  NDR is used to move parameters consisting of
  30  * complicated trees of data constructs between an RPC client and server.
  31  */
  32 
  33 #include <sys/byteorder.h>
  34 #include <strings.h>
  35 #include <assert.h>
  36 #include <string.h>

  37 #include <stdlib.h>
  38 
  39 #include <smbsrv/libsmb.h>
  40 #include <smbsrv/string.h>
  41 #include <smbsrv/libmlrpc.h>
  42 
  43 #define NDR_STRING_MAX          4096
  44 
  45 #define NDR_IS_UNION(T) \
  46         (((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_UNION)
  47 #define NDR_IS_STRING(T)        \
  48         (((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_STRING)
  49 
  50 extern ndr_typeinfo_t ndt_s_wchar;
  51 
  52 /*
  53  * The following synopsis describes the terms TOP-MOST, OUTER and INNER.
  54  *
  55  * Each parameter (call arguments and return values) is a TOP-MOST item.
  56  * A TOP-MOST item consists of one or more OUTER items.  An OUTER item
  57  * consists of one or more INNER items.  There are important differences
  58  * between each kind, which, primarily, have to do with the allocation
  59  * of memory to contain data structures and the order of processing.
  60  *
  61  * This is most easily demonstrated with a short example.
  62  * Consider these structures:
  63  *
  64  *      struct top_param {


1193         n_fixed = 0;
1194 
1195         if (!ndr_outer_grow(outer_ref, n_hdr))
1196                 return (0);             /* error already set */
1197 
1198         switch (nds->m_op) {
1199         case NDR_M_OP_MARSHALL:
1200                 valp = outer_ref->datum;
1201                 if (!valp) {
1202                         NDR_SET_ERROR(outer_ref, NDR_ERR_OUTER_PARAMS_BAD);
1203                         return (0);
1204                 }
1205 
1206                 if (outer_ref->backptr)
1207                         assert(valp == *outer_ref->backptr);
1208 
1209                 if (ti == &ndt_s_wchar) {
1210                         /*
1211                          * size_is is the number of characters in the
1212                          * (multibyte) string, including the null.

1213                          */
1214                         size_is = smb_wcequiv_strlen(valp) /
1215                             sizeof (smb_wchar_t);
1216 
1217                         if (!(nds->flags & NDS_F_NONULL))
1218                                 ++size_is;
1219 
1220                         if (size_is > NDR_STRING_MAX) {
1221                                 NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
1222                                 return (0);
1223                         }







1224                 } else {
1225                         valp = outer_ref->datum;
1226                         n_zeroes = 0;
1227                         for (ix = 0; ix < NDR_STRING_MAX; ix++) {
1228                                 if (valp[ix] == 0) {
1229                                         n_zeroes++;
1230                                         if (n_zeroes >= is_varlen &&
1231                                             ix % is_varlen == 0) {
1232                                                 break;
1233                                         }
1234                                 } else {
1235                                         n_zeroes = 0;
1236                                 }
1237                         }
1238                         if (ix >= NDR_STRING_MAX) {
1239                                 NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
1240                                 return (0);
1241                         }
1242                         size_is = ix+1;
1243                 }


1271                  *      size_is   = 261 (0x105)
1272                  *      first_is  = 0
1273                  *      length_is = 53  (0x35)
1274                  *
1275                  * The length_is was correct (for the given path) but the
1276                  * size_is was the maximum path length rather than being
1277                  * related to length_is.
1278                  */
1279                 if (first_is != 0) {
1280                         NDR_SET_ERROR(outer_ref, NDR_ERR_STRING_SIZING);
1281                         return (0);
1282                 }
1283 
1284                 if (ti == &ndt_s_wchar) {
1285                         /*
1286                          * Decoding Unicode to UTF-8; we need to allow
1287                          * for the maximum possible char size. It would
1288                          * be nice to use mbequiv_strlen but the string
1289                          * may not be null terminated.
1290                          */
1291                         n_alloc = (size_is + 1) * MTS_MB_CHAR_MAX;
1292                 } else {
1293                         n_alloc = (size_is + 1) * is_varlen;
1294                 }
1295 
1296                 valp = NDS_MALLOC(nds, n_alloc, outer_ref);
1297                 if (!valp) {
1298                         NDR_SET_ERROR(outer_ref, NDR_ERR_MALLOC_FAILED);
1299                         return (0);
1300                 }
1301 
1302                 bzero(valp, (size_is+1) * is_varlen);
1303 
1304                 if (outer_ref->backptr)
1305                         *outer_ref->backptr = valp;
1306                 outer_ref->datum = valp;
1307                 break;
1308 
1309         default:
1310                 NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
1311                 return (0);


1724         char                    name[30];
1725 
1726         if (encl_ref->inner_flags & NDR_F_SIZE_IS) {
1727                 /* now is the time to check/set size */
1728                 if (!ndr_size_is(encl_ref))
1729                         return (0);     /* error already set */
1730                 n_elem = encl_ref->size_is;
1731         } else {
1732                 assert(encl_ref->inner_flags & NDR_F_DIMENSION_IS);
1733                 n_elem = encl_ref->dimension_is;
1734         }
1735 
1736         bzero(&myref, sizeof (myref));
1737         myref.enclosing = encl_ref;
1738         myref.stream = encl_ref->stream;
1739         myref.packed_alignment = 0;
1740         myref.ti = ti;
1741         myref.inner_flags = NDR_F_NONE;
1742 
1743         for (i = 0; i < n_elem; i++) {
1744                 (void) sprintf(name, "[%lu]", i);
1745                 myref.name = name;
1746                 myref.pdu_offset = pdu_offset + i * ti->pdu_size_fixed_part;
1747                 myref.datum = encl_ref->datum + i * ti->c_size_fixed_part;
1748 
1749                 if (!ndr_inner(&myref))
1750                         return (0);
1751         }
1752 
1753         return (1);
1754 }
1755 
1756 
1757 /*
1758  * BASIC TYPES
1759  */
1760 #define MAKE_BASIC_TYPE_BASE(TYPE, SIZE) \
1761     extern int ndr_##TYPE(struct ndr_reference *encl_ref); \
1762     ndr_typeinfo_t ndt_##TYPE = { \
1763         1,              /* NDR version */ \
1764         (SIZE)-1,       /* alignment */ \


1779         1,              /* NDR version */ \
1780         (SIZE)-1,       /* alignment */ \
1781         NDR_F_STRING,   /* flags */ \
1782         ndr_s##TYPE,    /* ndr_func */ \
1783         0,              /* pdu_size_fixed_part */ \
1784         SIZE,           /* pdu_size_variable_part */ \
1785         0,              /* c_size_fixed_part */ \
1786         SIZE,           /* c_size_variable_part */ \
1787         }; \
1788     int ndr_s##TYPE(struct ndr_reference *ref) { \
1789         return (ndr_string_basic_integer(ref, &ndt_##TYPE)); \
1790 }
1791 
1792 #define MAKE_BASIC_TYPE(TYPE, SIZE) \
1793         MAKE_BASIC_TYPE_BASE(TYPE, SIZE) \
1794         MAKE_BASIC_TYPE_STRING(TYPE, SIZE)
1795 
1796 int ndr_basic_integer(ndr_ref_t *, unsigned);
1797 int ndr_string_basic_integer(ndr_ref_t *, ndr_typeinfo_t *);
1798 







1799 
1800 MAKE_BASIC_TYPE(_char, 1)
1801 MAKE_BASIC_TYPE(_uchar, 1)
1802 MAKE_BASIC_TYPE(_short, 2)
1803 MAKE_BASIC_TYPE(_ushort, 2)
1804 MAKE_BASIC_TYPE(_long, 4)
1805 MAKE_BASIC_TYPE(_ulong, 4)
1806 
1807 MAKE_BASIC_TYPE_BASE(_wchar, 2)
1808 
1809 int
1810 ndr_basic_integer(ndr_ref_t *ref, unsigned size)
1811 {
1812         ndr_stream_t    *nds = ref->stream;
1813         char            *valp = (char *)ref->datum;
1814         int             rc;
1815 
1816         switch (nds->m_op) {
1817         case NDR_M_OP_MARSHALL:
1818                 rc = NDS_PUT_PDU(nds, ref->pdu_offset, size,
1819                     valp, nds->swap, ref);
1820                 break;
1821 
1822         case NDR_M_OP_UNMARSHALL:
1823                 rc = NDS_GET_PDU(nds, ref->pdu_offset, size,
1824                     valp, nds->swap, ref);
1825                 break;
1826 
1827         default:
1828                 NDR_SET_ERROR(ref, NDR_ERR_M_OP_INVALID);


1837 {
1838         unsigned long           pdu_offset = encl_ref->pdu_offset;
1839         unsigned                size = type_under->pdu_size_fixed_part;
1840         char                    *valp;
1841         ndr_ref_t               myref;
1842         unsigned long           i;
1843         long                    sense = 0;
1844         char                    name[30];
1845 
1846         assert(size != 0);
1847 
1848         bzero(&myref, sizeof (myref));
1849         myref.enclosing = encl_ref;
1850         myref.stream = encl_ref->stream;
1851         myref.packed_alignment = 0;
1852         myref.ti = type_under;
1853         myref.inner_flags = NDR_F_NONE;
1854         myref.name = name;
1855 
1856         for (i = 0; i < NDR_STRING_MAX; i++) {
1857                 (void) sprintf(name, "[%lu]", i);
1858                 myref.pdu_offset = pdu_offset + i * size;
1859                 valp = encl_ref->datum + i * size;
1860                 myref.datum = valp;
1861 
1862                 if (!ndr_inner(&myref))
1863                         return (0);
1864 
1865                 switch (size) {
1866                 case 1:         sense = *valp; break;
1867                 /*LINTED E_BAD_PTR_CAST_ALIGN*/
1868                 case 2:         sense = *(short *)valp; break;
1869                 /*LINTED E_BAD_PTR_CAST_ALIGN*/
1870                 case 4:         sense = *(long *)valp; break;
1871                 }
1872 
1873                 if (!sense)
1874                         break;
1875         }
1876 
1877         return (1);


1880 
1881 extern int ndr_s_wchar(ndr_ref_t *encl_ref);
1882 ndr_typeinfo_t ndt_s_wchar = {
1883         1,              /* NDR version */
1884         2-1,            /* alignment */
1885         NDR_F_STRING,   /* flags */
1886         ndr_s_wchar,    /* ndr_func */
1887         0,              /* pdu_size_fixed_part */
1888         2,              /* pdu_size_variable_part */
1889         0,              /* c_size_fixed_part */
1890         1,              /* c_size_variable_part */
1891 };
1892 
1893 
1894 /*
1895  * Hand coded wchar function because all strings are transported
1896  * as wide characters. During NDR_M_OP_MARSHALL, we convert from
1897  * multi-byte to wide characters. During NDR_M_OP_UNMARSHALL, we
1898  * convert from wide characters to multi-byte.
1899  *
1900  * It appeared that NT would sometimes leave a spurious character
1901  * in the data stream before the null wide_char, which would get
1902  * included in the string decode because we processed until the
1903  * null character. It now looks like NT does not always terminate
1904  * RPC Unicode strings and the terminating null is a side effect
1905  * of field alignment. So now we rely on the strlen_is (set up in
1906  * ndr_outer_string) of the enclosing reference. This may or may
1907  * not include the null but it doesn't matter, the algorithm will
1908  * get it right.
1909  */
1910 int
1911 ndr_s_wchar(ndr_ref_t *encl_ref)
1912 {
1913         ndr_stream_t            *nds = encl_ref->stream;
1914         unsigned short          wide_char;
1915         char                    *valp;
1916         ndr_ref_t               myref;
1917         unsigned long           i;
1918         char                    name[30];
1919         int                     count;
1920         int                     char_count = 0;
1921 



1922         if (nds->m_op == NDR_M_OP_UNMARSHALL) {
1923                 /*
1924                  * To avoid problems with zero length strings
1925                  * we can just null terminate here and be done.
1926                  */
1927                 if (encl_ref->strlen_is == 0) {
1928                         encl_ref->datum[0] = '\0';
1929                         return (1);
1930                 }
1931         }
1932 























1933         bzero(&myref, sizeof (myref));
1934         myref.enclosing = encl_ref;
1935         myref.stream = encl_ref->stream;
1936         myref.packed_alignment = 0;
1937         myref.ti = &ndt__wchar;
1938         myref.inner_flags = NDR_F_NONE;
1939         myref.datum = (char *)&wide_char;
1940         myref.name = name;
1941         myref.pdu_offset = encl_ref->pdu_offset;


1942 
1943         valp = encl_ref->datum;
1944         count = 0;
1945 
1946         for (i = 0; i < NDR_STRING_MAX; i++) {
1947                 (void) sprintf(name, "[%lu]", i);
1948 
1949                 if (nds->m_op == NDR_M_OP_MARSHALL) {
1950                         count = smb_mbtowc((smb_wchar_t *)&wide_char, valp,
1951                             MTS_MB_CHAR_MAX);
1952                         if (count < 0) {
1953                                 return (0);
1954                         } else if (count == 0) {
1955                                 if (encl_ref->strlen_is != encl_ref->size_is)
1956                                         break;
1957 
1958                                 /*
1959                                  * If the input char is 0, mbtowc
1960                                  * returns 0 without setting wide_char.
1961                                  * Set wide_char to 0 and a count of 1.

1962                                  */
1963                                 wide_char = *valp;
1964                                 count = 1;
1965                         }
1966                 }
1967 
1968                 if (!ndr_inner(&myref))
1969                         return (0);
1970 
1971                 if (nds->m_op == NDR_M_OP_UNMARSHALL) {
1972                         count = smb_wctomb(valp, wide_char);
1973 
1974                         if ((++char_count) == encl_ref->strlen_is) {
1975                                 valp += count;
1976                                 *valp = '\0';
1977                                 break;
1978                         }
1979                 }
1980 
1981                 if (!wide_char)
1982                         break;
1983 
1984                 myref.pdu_offset += sizeof (wide_char);
1985                 valp += count;
1986         }
1987 
1988         return (1);
1989 }
1990 
1991 /*
1992  * Converts a multibyte character string to a little-endian, wide-char
1993  * string.  No more than nwchars wide characters are stored.
1994  * A terminating null wide character is appended if there is room.
1995  *
1996  * Returns the number of wide characters converted, not counting
1997  * any terminating null wide character.  Returns -1 if an invalid
1998  * multibyte character is encountered.
1999  */

2000 size_t
2001 ndr_mbstowcs(ndr_stream_t *nds, smb_wchar_t *wcs, const char *mbs,
2002     size_t nwchars)
2003 {
2004         smb_wchar_t *start = wcs;
2005         int nbytes;
2006 
2007         while (nwchars--) {
2008                 nbytes = ndr_mbtowc(nds, wcs, mbs, MTS_MB_CHAR_MAX);
2009                 if (nbytes < 0) {
2010                         *wcs = 0;
2011                         return ((size_t)-1);
2012                 }
2013 
2014                 if (*mbs == 0)
2015                         break;
2016 
2017                 ++wcs;
2018                 mbs += nbytes;
2019         }
2020 
2021         return (wcs - start);
2022 }
2023 
2024 /*
2025  * Converts a multibyte character to a little-endian, wide-char, which
2026  * is stored in wcharp.  Up to nbytes bytes are examined.
2027  *
2028  * If mbchar is valid, returns the number of bytes processed in mbchar.
2029  * If mbchar is invalid, returns -1.  See also smb_mbtowc().
2030  */
2031 /*ARGSUSED*/
2032 int
2033 ndr_mbtowc(ndr_stream_t *nds, smb_wchar_t *wcharp, const char *mbchar,
2034     size_t nbytes)
2035 {
2036         int rc;
2037 
2038         if ((rc = smb_mbtowc(wcharp, mbchar, nbytes)) < 0)
2039                 return (rc);
2040 
2041 #ifdef _BIG_ENDIAN
2042         if (nds == NULL || NDR_MODE_MATCH(nds, NDR_MODE_RETURN_SEND))
2043                 *wcharp = BSWAP_16(*wcharp);


2044 #endif

2045 
2046         return (rc);
2047 }


   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  * Copyright 2012 Milan Jurik. All rights reserved.
  25  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  26  */
  27 
  28 /*
  29  * Network Data Representation (NDR) is a compatible subset of the DCE RPC
  30  * and MSRPC NDR.  NDR is used to move parameters consisting of
  31  * complicated trees of data constructs between an RPC client and server.
  32  */
  33 
  34 #include <sys/byteorder.h>
  35 #include <strings.h>
  36 #include <assert.h>
  37 #include <string.h>
  38 #include <stdio.h>
  39 #include <stdlib.h>
  40 
  41 #include <libmlrpc.h>
  42 #include <ndr_wchar.h>

  43 


  44 #define NDR_IS_UNION(T) \
  45         (((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_UNION)
  46 #define NDR_IS_STRING(T)        \
  47         (((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_STRING)
  48 
  49 extern ndr_typeinfo_t ndt_s_wchar;
  50 
  51 /*
  52  * The following synopsis describes the terms TOP-MOST, OUTER and INNER.
  53  *
  54  * Each parameter (call arguments and return values) is a TOP-MOST item.
  55  * A TOP-MOST item consists of one or more OUTER items.  An OUTER item
  56  * consists of one or more INNER items.  There are important differences
  57  * between each kind, which, primarily, have to do with the allocation
  58  * of memory to contain data structures and the order of processing.
  59  *
  60  * This is most easily demonstrated with a short example.
  61  * Consider these structures:
  62  *
  63  *      struct top_param {


1192         n_fixed = 0;
1193 
1194         if (!ndr_outer_grow(outer_ref, n_hdr))
1195                 return (0);             /* error already set */
1196 
1197         switch (nds->m_op) {
1198         case NDR_M_OP_MARSHALL:
1199                 valp = outer_ref->datum;
1200                 if (!valp) {
1201                         NDR_SET_ERROR(outer_ref, NDR_ERR_OUTER_PARAMS_BAD);
1202                         return (0);
1203                 }
1204 
1205                 if (outer_ref->backptr)
1206                         assert(valp == *outer_ref->backptr);
1207 
1208                 if (ti == &ndt_s_wchar) {
1209                         /*
1210                          * size_is is the number of characters in the
1211                          * (multibyte) string, including the null.
1212                          * In other words, symbols, not bytes.
1213                          */
1214                         size_t wlen;
1215                         wlen = ndr__mbstowcs(NULL, valp, NDR_STRING_MAX);
1216                         if (wlen == (size_t)-1) {
1217                                 /* illegal sequence error? */



1218                                 NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
1219                                 return (0);
1220                         }
1221                         if ((nds->flags & NDS_F_NONULL) == 0)
1222                                 wlen++;
1223                         if (wlen > NDR_STRING_MAX) {
1224                                 NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
1225                                 return (0);
1226                         }
1227                         size_is = wlen;
1228                 } else {
1229                         valp = outer_ref->datum;
1230                         n_zeroes = 0;
1231                         for (ix = 0; ix < NDR_STRING_MAX; ix++) {
1232                                 if (valp[ix] == 0) {
1233                                         n_zeroes++;
1234                                         if (n_zeroes >= is_varlen &&
1235                                             ix % is_varlen == 0) {
1236                                                 break;
1237                                         }
1238                                 } else {
1239                                         n_zeroes = 0;
1240                                 }
1241                         }
1242                         if (ix >= NDR_STRING_MAX) {
1243                                 NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
1244                                 return (0);
1245                         }
1246                         size_is = ix+1;
1247                 }


1275                  *      size_is   = 261 (0x105)
1276                  *      first_is  = 0
1277                  *      length_is = 53  (0x35)
1278                  *
1279                  * The length_is was correct (for the given path) but the
1280                  * size_is was the maximum path length rather than being
1281                  * related to length_is.
1282                  */
1283                 if (first_is != 0) {
1284                         NDR_SET_ERROR(outer_ref, NDR_ERR_STRING_SIZING);
1285                         return (0);
1286                 }
1287 
1288                 if (ti == &ndt_s_wchar) {
1289                         /*
1290                          * Decoding Unicode to UTF-8; we need to allow
1291                          * for the maximum possible char size. It would
1292                          * be nice to use mbequiv_strlen but the string
1293                          * may not be null terminated.
1294                          */
1295                         n_alloc = (size_is + 1) * NDR_MB_CHAR_MAX;
1296                 } else {
1297                         n_alloc = (size_is + 1) * is_varlen;
1298                 }
1299 
1300                 valp = NDS_MALLOC(nds, n_alloc, outer_ref);
1301                 if (!valp) {
1302                         NDR_SET_ERROR(outer_ref, NDR_ERR_MALLOC_FAILED);
1303                         return (0);
1304                 }
1305 
1306                 bzero(valp, (size_is+1) * is_varlen);
1307 
1308                 if (outer_ref->backptr)
1309                         *outer_ref->backptr = valp;
1310                 outer_ref->datum = valp;
1311                 break;
1312 
1313         default:
1314                 NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
1315                 return (0);


1728         char                    name[30];
1729 
1730         if (encl_ref->inner_flags & NDR_F_SIZE_IS) {
1731                 /* now is the time to check/set size */
1732                 if (!ndr_size_is(encl_ref))
1733                         return (0);     /* error already set */
1734                 n_elem = encl_ref->size_is;
1735         } else {
1736                 assert(encl_ref->inner_flags & NDR_F_DIMENSION_IS);
1737                 n_elem = encl_ref->dimension_is;
1738         }
1739 
1740         bzero(&myref, sizeof (myref));
1741         myref.enclosing = encl_ref;
1742         myref.stream = encl_ref->stream;
1743         myref.packed_alignment = 0;
1744         myref.ti = ti;
1745         myref.inner_flags = NDR_F_NONE;
1746 
1747         for (i = 0; i < n_elem; i++) {
1748                 (void) snprintf(name, sizeof (name), "[%lu]", i);
1749                 myref.name = name;
1750                 myref.pdu_offset = pdu_offset + i * ti->pdu_size_fixed_part;
1751                 myref.datum = encl_ref->datum + i * ti->c_size_fixed_part;
1752 
1753                 if (!ndr_inner(&myref))
1754                         return (0);
1755         }
1756 
1757         return (1);
1758 }
1759 
1760 
1761 /*
1762  * BASIC TYPES
1763  */
1764 #define MAKE_BASIC_TYPE_BASE(TYPE, SIZE) \
1765     extern int ndr_##TYPE(struct ndr_reference *encl_ref); \
1766     ndr_typeinfo_t ndt_##TYPE = { \
1767         1,              /* NDR version */ \
1768         (SIZE)-1,       /* alignment */ \


1783         1,              /* NDR version */ \
1784         (SIZE)-1,       /* alignment */ \
1785         NDR_F_STRING,   /* flags */ \
1786         ndr_s##TYPE,    /* ndr_func */ \
1787         0,              /* pdu_size_fixed_part */ \
1788         SIZE,           /* pdu_size_variable_part */ \
1789         0,              /* c_size_fixed_part */ \
1790         SIZE,           /* c_size_variable_part */ \
1791         }; \
1792     int ndr_s##TYPE(struct ndr_reference *ref) { \
1793         return (ndr_string_basic_integer(ref, &ndt_##TYPE)); \
1794 }
1795 
1796 #define MAKE_BASIC_TYPE(TYPE, SIZE) \
1797         MAKE_BASIC_TYPE_BASE(TYPE, SIZE) \
1798         MAKE_BASIC_TYPE_STRING(TYPE, SIZE)
1799 
1800 int ndr_basic_integer(ndr_ref_t *, unsigned);
1801 int ndr_string_basic_integer(ndr_ref_t *, ndr_typeinfo_t *);
1802 
1803 /* Comments to be nice to those searching for these types. */
1804 MAKE_BASIC_TYPE(_char, 1)       /* ndt__char,  ndt_s_char */
1805 MAKE_BASIC_TYPE(_uchar, 1)      /* ndt__uchar, ndt_s_uchar */
1806 MAKE_BASIC_TYPE(_short, 2)      /* ndt__short, ndt_s_short */
1807 MAKE_BASIC_TYPE(_ushort, 2)     /* ndt__ushort, ndt_s_ushort */
1808 MAKE_BASIC_TYPE(_long, 4)       /* ndt__long,  ndt_s_long */
1809 MAKE_BASIC_TYPE(_ulong, 4)      /* ndt__ulong, ndt_s_ulong */
1810 
1811 MAKE_BASIC_TYPE_BASE(_wchar, 2) /* ndt__wchar, ndt_s_wchar */





1812 


1813 int
1814 ndr_basic_integer(ndr_ref_t *ref, unsigned size)
1815 {
1816         ndr_stream_t    *nds = ref->stream;
1817         char            *valp = (char *)ref->datum;
1818         int             rc;
1819 
1820         switch (nds->m_op) {
1821         case NDR_M_OP_MARSHALL:
1822                 rc = NDS_PUT_PDU(nds, ref->pdu_offset, size,
1823                     valp, nds->swap, ref);
1824                 break;
1825 
1826         case NDR_M_OP_UNMARSHALL:
1827                 rc = NDS_GET_PDU(nds, ref->pdu_offset, size,
1828                     valp, nds->swap, ref);
1829                 break;
1830 
1831         default:
1832                 NDR_SET_ERROR(ref, NDR_ERR_M_OP_INVALID);


1841 {
1842         unsigned long           pdu_offset = encl_ref->pdu_offset;
1843         unsigned                size = type_under->pdu_size_fixed_part;
1844         char                    *valp;
1845         ndr_ref_t               myref;
1846         unsigned long           i;
1847         long                    sense = 0;
1848         char                    name[30];
1849 
1850         assert(size != 0);
1851 
1852         bzero(&myref, sizeof (myref));
1853         myref.enclosing = encl_ref;
1854         myref.stream = encl_ref->stream;
1855         myref.packed_alignment = 0;
1856         myref.ti = type_under;
1857         myref.inner_flags = NDR_F_NONE;
1858         myref.name = name;
1859 
1860         for (i = 0; i < NDR_STRING_MAX; i++) {
1861                 (void) snprintf(name, sizeof (name), "[%lu]", i);
1862                 myref.pdu_offset = pdu_offset + i * size;
1863                 valp = encl_ref->datum + i * size;
1864                 myref.datum = valp;
1865 
1866                 if (!ndr_inner(&myref))
1867                         return (0);
1868 
1869                 switch (size) {
1870                 case 1:         sense = *valp; break;
1871                 /*LINTED E_BAD_PTR_CAST_ALIGN*/
1872                 case 2:         sense = *(short *)valp; break;
1873                 /*LINTED E_BAD_PTR_CAST_ALIGN*/
1874                 case 4:         sense = *(long *)valp; break;
1875                 }
1876 
1877                 if (!sense)
1878                         break;
1879         }
1880 
1881         return (1);


1884 
1885 extern int ndr_s_wchar(ndr_ref_t *encl_ref);
1886 ndr_typeinfo_t ndt_s_wchar = {
1887         1,              /* NDR version */
1888         2-1,            /* alignment */
1889         NDR_F_STRING,   /* flags */
1890         ndr_s_wchar,    /* ndr_func */
1891         0,              /* pdu_size_fixed_part */
1892         2,              /* pdu_size_variable_part */
1893         0,              /* c_size_fixed_part */
1894         1,              /* c_size_variable_part */
1895 };
1896 
1897 
1898 /*
1899  * Hand coded wchar function because all strings are transported
1900  * as wide characters. During NDR_M_OP_MARSHALL, we convert from
1901  * multi-byte to wide characters. During NDR_M_OP_UNMARSHALL, we
1902  * convert from wide characters to multi-byte.
1903  *
1904  * The most critical thing to get right in this function is to
1905  * marshall or unmarshall _exactly_ the number of elements the
1906  * OtW length specifies, as saved by the caller in: strlen_is.
1907  * Doing otherwise would leave us positioned at the wrong place
1908  * in the data stream for whatever follows this.  Note that the
1909  * string data covered by strlen_is may or may not include any
1910  * null termination, but the converted string provided by the
1911  * caller or returned always has a null terminator.

1912  */
1913 int
1914 ndr_s_wchar(ndr_ref_t *encl_ref)
1915 {
1916         ndr_stream_t            *nds = encl_ref->stream;
1917         char                    *valp = encl_ref->datum;

1918         ndr_ref_t               myref;

1919         char                    name[30];
1920         ndr_wchar_t             wcs[NDR_STRING_MAX+1];
1921         size_t                  i, slen, wlen;
1922 
1923         /* This is enforced in ndr_outer_string() */
1924         assert(encl_ref->strlen_is <= NDR_STRING_MAX);
1925 
1926         if (nds->m_op == NDR_M_OP_UNMARSHALL) {
1927                 /*
1928                  * To avoid problems with zero length strings
1929                  * we can just null terminate here and be done.
1930                  */
1931                 if (encl_ref->strlen_is == 0) {
1932                         encl_ref->datum[0] = '\0';
1933                         return (1);
1934                 }
1935         }
1936 
1937         /*
1938          * If we're marshalling, convert the given string
1939          * from UTF-8 into a local UCS-2 string.
1940          */
1941         if (nds->m_op == NDR_M_OP_MARSHALL) {
1942                 wlen = ndr__mbstowcs(wcs, valp, NDR_STRING_MAX);
1943                 if (wlen == (size_t)-1)
1944                         return (0);
1945                 /*
1946                  * Add a nulls to make strlen_is.
1947                  * (always zero or one of them)
1948                  * Then null terminate at wlen,
1949                  * just for debug convenience.
1950                  */
1951                 while (wlen < encl_ref->strlen_is)
1952                         wcs[wlen++] = 0;
1953                 wcs[wlen] = 0;
1954         }
1955 
1956         /*
1957          * Copy wire data to or from the local wc string.
1958          * Always exactly strlen_is elements.
1959          */
1960         bzero(&myref, sizeof (myref));
1961         myref.enclosing = encl_ref;
1962         myref.stream = encl_ref->stream;
1963         myref.packed_alignment = 0;
1964         myref.ti = &ndt__wchar;
1965         myref.inner_flags = NDR_F_NONE;

1966         myref.name = name;
1967         myref.pdu_offset = encl_ref->pdu_offset;
1968         myref.datum = (char *)wcs;
1969         wlen = encl_ref->strlen_is;
1970 
1971         for (i = 0; i < wlen; i++) {
1972                 (void) snprintf(name, sizeof (name), "[%lu]", i);
1973                 if (!ndr_inner(&myref))







1974                         return (0);
1975                 myref.pdu_offset += sizeof (ndr_wchar_t);
1976                 myref.datum      += sizeof (ndr_wchar_t);
1977         }
1978 
1979         /*
1980          * If this is unmarshall, convert the local UCS-2 string
1981          * into a UTF-8 string in the caller's buffer.  The caller
1982          * previously determined the space required and provides a
1983          * buffer of sufficient size.
1984          */








1985         if (nds->m_op == NDR_M_OP_UNMARSHALL) {
1986                 wcs[wlen] = 0;
1987                 slen = ndr__wcstombs(valp, wcs, wlen);
1988                 if (slen == (size_t)-1)
1989                         return (0);
1990                 valp[slen] = '\0';

1991         }

1992 







1993         return (1);
1994 }
1995 
1996 /*
1997  * Converts a multibyte character string to a little-endian, wide-char
1998  * string.  No more than nwchars wide characters are stored.
1999  * A terminating null wide character is appended if there is room.
2000  *
2001  * Returns the number of wide characters converted, not counting
2002  * any terminating null wide character.  Returns -1 if an invalid
2003  * multibyte character is encountered.
2004  */
2005 /* ARGSUSED */
2006 size_t
2007 ndr_mbstowcs(ndr_stream_t *nds, ndr_wchar_t *wcs, const char *mbs,
2008     size_t nwchars)
2009 {
2010         size_t len;

2011 


































2012 #ifdef _BIG_ENDIAN
2013         if (nds == NULL || NDR_MODE_MATCH(nds, NDR_MODE_RETURN_SEND)) {
2014                 /* Make WC string in LE order. */
2015                 len = ndr__mbstowcs_le(wcs, mbs, nwchars);
2016         } else
2017 #endif
2018                 len = ndr__mbstowcs(wcs, mbs, nwchars);
2019 
2020         return (len);
2021 }