librpc/ndr: remember INCOMPLETE_BUFFER missing bytes in relative_highest_offset
[gd/samba-autobuild/.git] / librpc / ndr / ndr_basic.c
index d46590f0cb55e629c1a6b811d58b219660a835fc..a6cf607f3eb89ae4f37f4e9a00e9bfb472e3a73e 100644 (file)
@@ -1,20 +1,20 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
 
    routines for marshalling/unmarshalling basic types
 
    Copyright (C) Andrew Tridgell 2003
-   
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -22,6 +22,7 @@
 #include "includes.h"
 #include "system/network.h"
 #include "librpc/ndr/libndr.h"
+#include "lib/util/util_net.h"
 
 #define NDR_SVAL(ndr, ofs) (NDR_BE(ndr)?RSVAL(ndr->data,ofs):SVAL(ndr->data,ofs))
 #define NDR_IVAL(ndr, ofs) (NDR_BE(ndr)?RIVAL(ndr->data,ofs):IVAL(ndr->data,ofs))
@@ -31,6 +32,8 @@
 #define NDR_SIVALS(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSIVALS(ndr->data,ofs,v); } else SIVALS(ndr->data,ofs,v); } while (0)
 
 
+static void ndr_dump_data(struct ndr_print *ndr, const uint8_t *buf, int len);
+
 /*
   check for data leaks from the server by looking for non-zero pad bytes
   these could also indicate that real structure elements have been
@@ -60,6 +63,7 @@ _PUBLIC_ void ndr_check_padding(struct ndr_pull *ndr, size_t n)
 */
 _PUBLIC_ enum ndr_err_code ndr_pull_int8(struct ndr_pull *ndr, int ndr_flags, int8_t *v)
 {
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PULL_NEED_BYTES(ndr, 1);
        *v = (int8_t)CVAL(ndr->data, ndr->offset);
        ndr->offset += 1;
@@ -71,6 +75,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_int8(struct ndr_pull *ndr, int ndr_flags, in
 */
 _PUBLIC_ enum ndr_err_code ndr_pull_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *v)
 {
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PULL_NEED_BYTES(ndr, 1);
        *v = CVAL(ndr->data, ndr->offset);
        ndr->offset += 1;
@@ -82,6 +87,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_uint8(struct ndr_pull *ndr, int ndr_flags, u
 */
 _PUBLIC_ enum ndr_err_code ndr_pull_int16(struct ndr_pull *ndr, int ndr_flags, int16_t *v)
 {
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PULL_ALIGN(ndr, 2);
        NDR_PULL_NEED_BYTES(ndr, 2);
        *v = (uint16_t)NDR_SVAL(ndr, ndr->offset);
@@ -94,6 +100,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_int16(struct ndr_pull *ndr, int ndr_flags, i
 */
 _PUBLIC_ enum ndr_err_code ndr_pull_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
 {
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PULL_ALIGN(ndr, 2);
        NDR_PULL_NEED_BYTES(ndr, 2);
        *v = NDR_SVAL(ndr, ndr->offset);
@@ -101,11 +108,31 @@ _PUBLIC_ enum ndr_err_code ndr_pull_uint16(struct ndr_pull *ndr, int ndr_flags,
        return NDR_ERR_SUCCESS;
 }
 
+/*
+  parse a uint1632_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_uint1632(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
+{
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+       if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
+               uint32_t v32 = 0;
+               enum ndr_err_code err = ndr_pull_uint32(ndr, ndr_flags, &v32);
+               *v = v32;
+               if (unlikely(v32 != *v)) {
+                       DEBUG(0,(__location__ ": non-zero upper 16 bits 0x%08x\n", (unsigned)v32));
+                       return NDR_ERR_NDR64;
+               }
+               return err;
+       }
+       return ndr_pull_uint16(ndr, ndr_flags, v);
+}
+
 /*
   parse a int32_t
 */
 _PUBLIC_ enum ndr_err_code ndr_pull_int32(struct ndr_pull *ndr, int ndr_flags, int32_t *v)
 {
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PULL_ALIGN(ndr, 4);
        NDR_PULL_NEED_BYTES(ndr, 4);
        *v = NDR_IVALS(ndr, ndr->offset);
@@ -118,6 +145,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_int32(struct ndr_pull *ndr, int ndr_flags, i
 */
 _PUBLIC_ enum ndr_err_code ndr_pull_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
 {
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PULL_ALIGN(ndr, 4);
        NDR_PULL_NEED_BYTES(ndr, 4);
        *v = NDR_IVAL(ndr, ndr->offset);
@@ -125,11 +153,34 @@ _PUBLIC_ enum ndr_err_code ndr_pull_uint32(struct ndr_pull *ndr, int ndr_flags,
        return NDR_ERR_SUCCESS;
 }
 
+/*
+  parse a arch dependent uint32/uint64
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_uint3264(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
+{
+       uint64_t v64;
+       enum ndr_err_code err;
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+       if (likely(!(ndr->flags & LIBNDR_FLAG_NDR64))) {
+               return ndr_pull_uint32(ndr, ndr_flags, v);
+       }
+       err = ndr_pull_hyper(ndr, ndr_flags, &v64);
+       *v = (uint32_t)v64;
+       if (unlikely(v64 != *v)) {
+               DEBUG(0,(__location__ ": non-zero upper 32 bits 0x%016llx\n",
+                        (unsigned long long)v64));
+               return ndr_pull_error(ndr, NDR_ERR_NDR64, __location__ ": non-zero upper 32 bits 0x%016llx\n",
+                        (unsigned long long)v64);
+       }
+       return err;
+}
+
 /*
   parse a double
 */
 _PUBLIC_ enum ndr_err_code ndr_pull_double(struct ndr_pull *ndr, int ndr_flags, double *v)
 {
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PULL_ALIGN(ndr, 8);
        NDR_PULL_NEED_BYTES(ndr, 8);
        memcpy(v, ndr->data+ndr->offset, 8);
@@ -137,12 +188,25 @@ _PUBLIC_ enum ndr_err_code ndr_pull_double(struct ndr_pull *ndr, int ndr_flags,
        return NDR_ERR_SUCCESS;
 }
 
+/*
+  parse a pointer referent identifier stored in 2 bytes
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr_short(struct ndr_pull *ndr, uint16_t *v)
+{
+       NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, v));
+       if (*v != 0) {
+               ndr->ptr_count++;
+       }
+       *(v) -= ndr->relative_rap_convert;
+       return NDR_ERR_SUCCESS;
+}
+
 /*
   parse a pointer referent identifier
 */
 _PUBLIC_ enum ndr_err_code ndr_pull_generic_ptr(struct ndr_pull *ndr, uint32_t *v)
 {
-       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, v));
+       NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, v));
        if (*v != 0) {
                ndr->ptr_count++;
        }
@@ -154,7 +218,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_generic_ptr(struct ndr_pull *ndr, uint32_t *
 */
 _PUBLIC_ enum ndr_err_code ndr_pull_ref_ptr(struct ndr_pull *ndr, uint32_t *v)
 {
-       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, v));
+       NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, v));
        /* ref pointers always point to data */
        *v = 1;
        return NDR_ERR_SUCCESS;
@@ -165,6 +229,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_ref_ptr(struct ndr_pull *ndr, uint32_t *v)
 */
 _PUBLIC_ enum ndr_err_code ndr_pull_udlong(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
 {
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PULL_ALIGN(ndr, 4);
        NDR_PULL_NEED_BYTES(ndr, 8);
        *v = NDR_IVAL(ndr, ndr->offset);
@@ -178,6 +243,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_udlong(struct ndr_pull *ndr, int ndr_flags,
 */
 _PUBLIC_ enum ndr_err_code ndr_pull_udlongr(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
 {
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PULL_ALIGN(ndr, 4);
        NDR_PULL_NEED_BYTES(ndr, 8);
        *v = ((uint64_t)NDR_IVAL(ndr, ndr->offset)) << 32;
@@ -200,6 +266,9 @@ _PUBLIC_ enum ndr_err_code ndr_pull_dlong(struct ndr_pull *ndr, int ndr_flags, i
 _PUBLIC_ enum ndr_err_code ndr_pull_hyper(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
 {
        NDR_PULL_ALIGN(ndr, 8);
+       if (NDR_BE(ndr)) {
+               return ndr_pull_udlongr(ndr, ndr_flags, v);
+       }
        return ndr_pull_udlong(ndr, ndr_flags, v);
 }
 
@@ -209,6 +278,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_hyper(struct ndr_pull *ndr, int ndr_flags, u
 _PUBLIC_ enum ndr_err_code ndr_pull_pointer(struct ndr_pull *ndr, int ndr_flags, void* *v)
 {
        uintptr_t h;
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PULL_ALIGN(ndr, sizeof(h));
        NDR_PULL_NEED_BYTES(ndr, sizeof(h));
        memcpy(&h, ndr->data+ndr->offset, sizeof(h));
@@ -223,6 +293,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_pointer(struct ndr_pull *ndr, int ndr_flags,
 _PUBLIC_ enum ndr_err_code ndr_pull_NTSTATUS(struct ndr_pull *ndr, int ndr_flags, NTSTATUS *status)
 {
        uint32_t v;
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
        NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
        *status = NT_STATUS(v);
        return NDR_ERR_SUCCESS;
@@ -247,11 +318,90 @@ _PUBLIC_ void ndr_print_NTSTATUS(struct ndr_print *ndr, const char *name, NTSTAT
 _PUBLIC_ enum ndr_err_code ndr_pull_WERROR(struct ndr_pull *ndr, int ndr_flags, WERROR *status)
 {
        uint32_t v;
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
        NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
        *status = W_ERROR(v);
        return NDR_ERR_SUCCESS;
 }
 
+
+/*
+  parse a uint8_t enum
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_enum_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *v)
+{
+       return ndr_pull_uint8(ndr, ndr_flags, v);
+}
+
+/*
+  parse a uint16_t enum
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_enum_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
+{
+       return ndr_pull_uint16(ndr, ndr_flags, v);
+}
+
+/*
+  parse a uint1632_t enum (uint32_t on NDR64)
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_enum_uint1632(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
+{
+       if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
+               uint32_t v32;
+               NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &v32));
+               *v = v32;
+               if (v32 != *v) {
+                       DEBUG(0,(__location__ ": non-zero upper 16 bits 0x%08x\n", (unsigned)v32));
+                       return NDR_ERR_NDR64;
+               }
+               return NDR_ERR_SUCCESS;
+       }
+       return ndr_pull_uint16(ndr, ndr_flags, v);
+}
+
+/*
+  parse a uint32_t enum
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_enum_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
+{
+       return ndr_pull_uint32(ndr, ndr_flags, v);
+}
+
+/*
+  push a uint8_t enum
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_enum_uint8(struct ndr_push *ndr, int ndr_flags, uint8_t v)
+{
+       return ndr_push_uint8(ndr, ndr_flags, v);
+}
+
+/*
+  push a uint16_t enum
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_enum_uint16(struct ndr_push *ndr, int ndr_flags, uint16_t v)
+{
+       return ndr_push_uint16(ndr, ndr_flags, v);
+}
+
+/*
+  push a uint32_t enum
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_enum_uint32(struct ndr_push *ndr, int ndr_flags, uint32_t v)
+{
+       return ndr_push_uint32(ndr, ndr_flags, v);
+}
+
+/*
+  push a uint1632_t enum
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_enum_uint1632(struct ndr_push *ndr, int ndr_flags, uint16_t v)
+{
+       if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
+               return ndr_push_uint32(ndr, ndr_flags, v);
+       }
+       return ndr_push_uint16(ndr, ndr_flags, v);
+}
+
 /*
   push a WERROR
 */
@@ -281,6 +431,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_bytes(struct ndr_pull *ndr, uint8_t *data, u
 */
 _PUBLIC_ enum ndr_err_code ndr_pull_array_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *data, uint32_t n)
 {
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
        if (!(ndr_flags & NDR_SCALARS)) {
                return NDR_ERR_SUCCESS;
        }
@@ -292,6 +443,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_array_uint8(struct ndr_pull *ndr, int ndr_fl
 */
 _PUBLIC_ enum ndr_err_code ndr_push_int8(struct ndr_push *ndr, int ndr_flags, int8_t v)
 {
+       NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PUSH_NEED_BYTES(ndr, 1);
        SCVAL(ndr->data, ndr->offset, (uint8_t)v);
        ndr->offset += 1;
@@ -303,6 +455,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_int8(struct ndr_push *ndr, int ndr_flags, in
 */
 _PUBLIC_ enum ndr_err_code ndr_push_uint8(struct ndr_push *ndr, int ndr_flags, uint8_t v)
 {
+       NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PUSH_NEED_BYTES(ndr, 1);
        SCVAL(ndr->data, ndr->offset, v);
        ndr->offset += 1;
@@ -314,6 +467,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_uint8(struct ndr_push *ndr, int ndr_flags, u
 */
 _PUBLIC_ enum ndr_err_code ndr_push_int16(struct ndr_push *ndr, int ndr_flags, int16_t v)
 {
+       NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PUSH_ALIGN(ndr, 2);
        NDR_PUSH_NEED_BYTES(ndr, 2);
        NDR_SSVAL(ndr, ndr->offset, (uint16_t)v);
@@ -326,6 +480,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_int16(struct ndr_push *ndr, int ndr_flags, i
 */
 _PUBLIC_ enum ndr_err_code ndr_push_uint16(struct ndr_push *ndr, int ndr_flags, uint16_t v)
 {
+       NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PUSH_ALIGN(ndr, 2);
        NDR_PUSH_NEED_BYTES(ndr, 2);
        NDR_SSVAL(ndr, ndr->offset, v);
@@ -333,11 +488,23 @@ _PUBLIC_ enum ndr_err_code ndr_push_uint16(struct ndr_push *ndr, int ndr_flags,
        return NDR_ERR_SUCCESS;
 }
 
+/*
+  push a uint1632
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_uint1632(struct ndr_push *ndr, int ndr_flags, uint16_t v)
+{
+       if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
+               return ndr_push_uint32(ndr, ndr_flags, v);
+       }
+       return ndr_push_uint16(ndr, ndr_flags, v);
+}
+
 /*
   push a int32_t
 */
 _PUBLIC_ enum ndr_err_code ndr_push_int32(struct ndr_push *ndr, int ndr_flags, int32_t v)
 {
+       NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PUSH_ALIGN(ndr, 4);
        NDR_PUSH_NEED_BYTES(ndr, 4);
        NDR_SIVALS(ndr, ndr->offset, v);
@@ -350,6 +517,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_int32(struct ndr_push *ndr, int ndr_flags, i
 */
 _PUBLIC_ enum ndr_err_code ndr_push_uint32(struct ndr_push *ndr, int ndr_flags, uint32_t v)
 {
+       NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PUSH_ALIGN(ndr, 4);
        NDR_PUSH_NEED_BYTES(ndr, 4);
        NDR_SIVAL(ndr, ndr->offset, v);
@@ -357,11 +525,23 @@ _PUBLIC_ enum ndr_err_code ndr_push_uint32(struct ndr_push *ndr, int ndr_flags,
        return NDR_ERR_SUCCESS;
 }
 
+/*
+  push a uint3264
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_uint3264(struct ndr_push *ndr, int ndr_flags, uint32_t v)
+{
+       if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
+               return ndr_push_hyper(ndr, ndr_flags, v);
+       }
+       return ndr_push_uint32(ndr, ndr_flags, v);
+}
+
 /*
   push a udlong
 */
 _PUBLIC_ enum ndr_err_code ndr_push_udlong(struct ndr_push *ndr, int ndr_flags, uint64_t v)
 {
+       NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PUSH_ALIGN(ndr, 4);
        NDR_PUSH_NEED_BYTES(ndr, 8);
        NDR_SIVAL(ndr, ndr->offset, (v & 0xFFFFFFFF));
@@ -375,6 +555,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_udlong(struct ndr_push *ndr, int ndr_flags,
 */
 _PUBLIC_ enum ndr_err_code ndr_push_udlongr(struct ndr_push *ndr, int ndr_flags, uint64_t v)
 {
+       NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PUSH_ALIGN(ndr, 4);
        NDR_PUSH_NEED_BYTES(ndr, 8);
        NDR_SIVAL(ndr, ndr->offset, (v>>32));
@@ -397,6 +578,9 @@ _PUBLIC_ enum ndr_err_code ndr_push_dlong(struct ndr_push *ndr, int ndr_flags, i
 _PUBLIC_ enum ndr_err_code ndr_push_hyper(struct ndr_push *ndr, int ndr_flags, uint64_t v)
 {
        NDR_PUSH_ALIGN(ndr, 8);
+       if (NDR_BE(ndr)) {
+               return ndr_push_udlongr(ndr, NDR_SCALARS, v);
+       }
        return ndr_push_udlong(ndr, NDR_SCALARS, v);
 }
 
@@ -405,6 +589,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_hyper(struct ndr_push *ndr, int ndr_flags, u
 */
 _PUBLIC_ enum ndr_err_code ndr_push_double(struct ndr_push *ndr, int ndr_flags, double v)
 {
+       NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PUSH_ALIGN(ndr, 8);
        NDR_PUSH_NEED_BYTES(ndr, 8);
        memcpy(ndr->data+ndr->offset, &v, 8);
@@ -418,6 +603,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_double(struct ndr_push *ndr, int ndr_flags,
 _PUBLIC_ enum ndr_err_code ndr_push_pointer(struct ndr_push *ndr, int ndr_flags, void* v)
 {
        uintptr_t h = (intptr_t)v;
+       NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
        NDR_PUSH_ALIGN(ndr, sizeof(h));
        NDR_PUSH_NEED_BYTES(ndr, sizeof(h));
        memcpy(ndr->data+ndr->offset, &h, sizeof(h));
@@ -427,16 +613,80 @@ _PUBLIC_ enum ndr_err_code ndr_push_pointer(struct ndr_push *ndr, int ndr_flags,
 
 _PUBLIC_ enum ndr_err_code ndr_push_align(struct ndr_push *ndr, size_t size)
 {
+       /* this is a nasty hack to make pidl work with NDR64 */
+       if (size == 5) {
+               if (ndr->flags & LIBNDR_FLAG_NDR64) {
+                       size = 8;
+               } else {
+                       size = 4;
+               }
+       } else if (size == 3) {
+               if (ndr->flags & LIBNDR_FLAG_NDR64) {
+                       size = 4;
+               } else {
+                       size = 2;
+               }
+       }
        NDR_PUSH_ALIGN(ndr, size);
        return NDR_ERR_SUCCESS;
 }
 
 _PUBLIC_ enum ndr_err_code ndr_pull_align(struct ndr_pull *ndr, size_t size)
 {
+       /* this is a nasty hack to make pidl work with NDR64 */
+       if (size == 5) {
+               if (ndr->flags & LIBNDR_FLAG_NDR64) {
+                       size = 8;
+               } else {
+                       size = 4;
+               }
+       } else if (size == 3) {
+               if (ndr->flags & LIBNDR_FLAG_NDR64) {
+                       size = 4;
+               } else {
+                       size = 2;
+               }
+       }
        NDR_PULL_ALIGN(ndr, size);
        return NDR_ERR_SUCCESS;
 }
 
+_PUBLIC_ enum ndr_err_code ndr_push_union_align(struct ndr_push *ndr, size_t size)
+{
+       /* MS-RPCE section 2.2.5.3.4.4 */
+       if (ndr->flags & LIBNDR_FLAG_NDR64) {
+               return ndr_push_align(ndr, size);
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_union_align(struct ndr_pull *ndr, size_t size)
+{
+       /* MS-RPCE section 2.2.5.3.4.4 */
+       if (ndr->flags & LIBNDR_FLAG_NDR64) {
+               return ndr_pull_align(ndr, size);
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_trailer_align(struct ndr_push *ndr, size_t size)
+{
+       /* MS-RPCE section 2.2.5.3.4.1 */
+       if (ndr->flags & LIBNDR_FLAG_NDR64) {
+               return ndr_push_align(ndr, size);
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_trailer_align(struct ndr_pull *ndr, size_t size)
+{
+       /* MS-RPCE section 2.2.5.3.4.1 */
+       if (ndr->flags & LIBNDR_FLAG_NDR64) {
+               return ndr_pull_align(ndr, size);
+       }
+       return NDR_ERR_SUCCESS;
+}
+
 /*
   push some bytes
 */
@@ -464,6 +714,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_zero(struct ndr_push *ndr, uint32_t n)
 */
 _PUBLIC_ enum ndr_err_code ndr_push_array_uint8(struct ndr_push *ndr, int ndr_flags, const uint8_t *data, uint32_t n)
 {
+       NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
        if (!(ndr_flags & NDR_SCALARS)) {
                return NDR_ERR_SUCCESS;
        }
@@ -481,7 +732,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_unique_ptr(struct ndr_push *ndr, const void
                ptr |= 0x00020000;
                ndr->ptr_count++;
        }
-       return ndr_push_uint32(ndr, NDR_SCALARS, ptr);
+       return ndr_push_uint3264(ndr, NDR_SCALARS, ptr);
 }
 
 /*
@@ -499,7 +750,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_full_ptr(struct ndr_push *ndr, const void *p
                        ndr_token_store(ndr, &ndr->full_ptr_list, p, ptr);
                }
        }
-       return ndr_push_uint32(ndr, NDR_SCALARS, ptr);
+       return ndr_push_uint3264(ndr, NDR_SCALARS, ptr);
 }
 
 /*
@@ -507,7 +758,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_full_ptr(struct ndr_push *ndr, const void *p
 */
 _PUBLIC_ enum ndr_err_code ndr_push_ref_ptr(struct ndr_push *ndr)
 {
-       return ndr_push_uint32(ndr, NDR_SCALARS, 0xAEF1AEF1);
+       return ndr_push_uint3264(ndr, NDR_SCALARS, 0xAEF1AEF1);
 }
 
 
@@ -516,6 +767,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_ref_ptr(struct ndr_push *ndr)
 */
 _PUBLIC_ enum ndr_err_code ndr_push_NTTIME(struct ndr_push *ndr, int ndr_flags, NTTIME t)
 {
+       NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
        NDR_CHECK(ndr_push_udlong(ndr, ndr_flags, t));
        return NDR_ERR_SUCCESS;
 }
@@ -525,6 +777,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_NTTIME(struct ndr_push *ndr, int ndr_flags,
 */
 _PUBLIC_ enum ndr_err_code ndr_pull_NTTIME(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
 {
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
        NDR_CHECK(ndr_pull_udlong(ndr, ndr_flags, t));
        return NDR_ERR_SUCCESS;
 }
@@ -534,6 +787,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_NTTIME(struct ndr_pull *ndr, int ndr_flags,
 */
 _PUBLIC_ enum ndr_err_code ndr_push_NTTIME_1sec(struct ndr_push *ndr, int ndr_flags, NTTIME t)
 {
+       NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
        t /= 10000000;
        NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
        return NDR_ERR_SUCCESS;
@@ -544,6 +798,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_NTTIME_1sec(struct ndr_push *ndr, int ndr_fl
 */
 _PUBLIC_ enum ndr_err_code ndr_pull_NTTIME_1sec(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
 {
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
        NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
        (*t) *= 10000000;
        return NDR_ERR_SUCCESS;
@@ -554,6 +809,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_NTTIME_1sec(struct ndr_pull *ndr, int ndr_fl
 */
 _PUBLIC_ enum ndr_err_code ndr_pull_NTTIME_hyper(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
 {
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
        NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
        return NDR_ERR_SUCCESS;
 }
@@ -563,6 +819,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_NTTIME_hyper(struct ndr_pull *ndr, int ndr_f
 */
 _PUBLIC_ enum ndr_err_code ndr_push_NTTIME_hyper(struct ndr_push *ndr, int ndr_flags, NTTIME t)
 {
+       NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
        NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
        return NDR_ERR_SUCCESS;
 }
@@ -587,6 +844,58 @@ _PUBLIC_ enum ndr_err_code ndr_pull_time_t(struct ndr_pull *ndr, int ndr_flags,
 }
 
 
+/*
+  push a uid_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_uid_t(struct ndr_push *ndr, int ndr_flags, uid_t u)
+{
+       NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+       return ndr_push_hyper(ndr, NDR_SCALARS, (uint64_t)u);
+}
+
+/*
+  pull a uid_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_uid_t(struct ndr_pull *ndr, int ndr_flags, uid_t *u)
+{
+       uint64_t uu;
+       NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, &uu));
+       *u = (uid_t)uu;
+       if (unlikely(uu != *u)) {
+               DEBUG(0,(__location__ ": uid_t pull doesn't fit 0x%016llx\n",
+                        (unsigned long long)uu));
+               return NDR_ERR_NDR64;
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+
+/*
+  push a gid_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_gid_t(struct ndr_push *ndr, int ndr_flags, gid_t g)
+{
+       NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+       return ndr_push_hyper(ndr, NDR_SCALARS, (uint64_t)g);
+}
+
+/*
+  pull a gid_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_gid_t(struct ndr_pull *ndr, int ndr_flags, gid_t *g)
+{
+       uint64_t gg;
+       NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, &gg));
+       *g = (gid_t)gg;
+       if (unlikely(gg != *g)) {
+               DEBUG(0,(__location__ ": gid_t pull doesn't fit 0x%016llx\n",
+                        (unsigned long long)gg));
+               return NDR_ERR_NDR64;
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+
 /*
   pull a ipv4address
 */
@@ -609,7 +918,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_ipv4address(struct ndr_push *ndr, int ndr_fl
        uint32_t addr;
        if (!is_ipaddress(address)) {
                return ndr_push_error(ndr, NDR_ERR_IPV4ADDRESS,
-                                     "Invalid IPv4 address: '%s'", 
+                                     "Invalid IPv4 address: '%s'",
                                      address);
        }
        addr = inet_addr(address);
@@ -620,19 +929,83 @@ _PUBLIC_ enum ndr_err_code ndr_push_ipv4address(struct ndr_push *ndr, int ndr_fl
 /*
   print a ipv4address
 */
-_PUBLIC_ void ndr_print_ipv4address(struct ndr_print *ndr, const char *name, 
+_PUBLIC_ void ndr_print_ipv4address(struct ndr_print *ndr, const char *name,
                           const char *address)
 {
        ndr->print(ndr, "%-25s: %s", name, address);
 }
 
+/*
+  pull a ipv6address
+*/
+#define IPV6_BYTES 16
+#define IPV6_ADDR_STR_LEN 39
+_PUBLIC_ enum ndr_err_code ndr_pull_ipv6address(struct ndr_pull *ndr, int ndr_flags, const char **address)
+{
+       uint8_t addr[IPV6_BYTES];
+       char *addr_str = talloc_strdup(ndr->current_mem_ctx, "");
+       int i;
+       NDR_CHECK(ndr_pull_array_uint8(ndr, ndr_flags, addr, IPV6_BYTES));
+       for (i = 0; i < IPV6_BYTES; ++i) {
+               addr_str = talloc_asprintf_append(addr_str, "%02x", addr[i]);
+               /* We need a ':' every second byte but the last one */
+               if (i%2 == 1 && i != (IPV6_BYTES - 1)) {
+                       addr_str = talloc_strdup_append(addr_str, ":");
+               }
+       }
+       *address = addr_str;
+       NDR_ERR_HAVE_NO_MEMORY(*address);
+       return NDR_ERR_SUCCESS;
+}
+
+/*
+  push a ipv6address
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_ipv6address(struct ndr_push *ndr, int ndr_flags, const char *address)
+{
+#ifdef AF_INET6
+       uint8_t addr[IPV6_BYTES];
+       int ret;
+
+       if (!is_ipaddress(address)) {
+               return ndr_push_error(ndr, NDR_ERR_IPV6ADDRESS,
+                                     "Invalid IPv6 address: '%s'",
+                                     address);
+       }
+       ret = inet_pton(AF_INET6, address, addr);
+       if (ret <= 0) {
+               return NDR_ERR_IPV6ADDRESS;
+       }
+
+       NDR_CHECK(ndr_push_array_uint8(ndr, ndr_flags, addr, IPV6_BYTES));
+
+       return NDR_ERR_SUCCESS;
+#else
+       return NDR_ERR_IPV6ADDRESS;
+#endif
+}
+
+/*
+  print a ipv6address
+*/
+_PUBLIC_ void ndr_print_ipv6address(struct ndr_print *ndr, const char *name,
+                          const char *address)
+{
+       ndr->print(ndr, "%-25s: %s", name, address);
+}
+#undef IPV6_BYTES
 
 _PUBLIC_ void ndr_print_struct(struct ndr_print *ndr, const char *name, const char *type)
 {
        ndr->print(ndr, "%s: struct %s", name, type);
 }
 
-_PUBLIC_ void ndr_print_enum(struct ndr_print *ndr, const char *name, const char *type, 
+_PUBLIC_ void ndr_print_null(struct ndr_print *ndr)
+{
+       ndr->print(ndr, "UNEXPECTED NULL POINTER");
+}
+
+_PUBLIC_ void ndr_print_enum(struct ndr_print *ndr, const char *name, const char *type,
                    const char *val, uint32_t value)
 {
        if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
@@ -644,13 +1017,17 @@ _PUBLIC_ void ndr_print_enum(struct ndr_print *ndr, const char *name, const char
 
 _PUBLIC_ void ndr_print_bitmap_flag(struct ndr_print *ndr, size_t size, const char *flag_name, uint32_t flag, uint32_t value)
 {
+       if (flag == 0) {
+               return;
+       }
+
        /* this is an attempt to support multi-bit bitmap masks */
        value &= flag;
 
        while (!(flag & 1)) {
                flag >>= 1;
                value >>= 1;
-       }       
+       }
        if (flag == 1) {
                ndr->print(ndr, "   %d: %-25s", value, flag_name);
        } else {
@@ -688,6 +1065,16 @@ _PUBLIC_ void ndr_print_uint32(struct ndr_print *ndr, const char *name, uint32_t
        ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
 }
 
+_PUBLIC_ void ndr_print_int3264(struct ndr_print *ndr, const char *name, int32_t v)
+{
+       ndr->print(ndr, "%-25s: %d", name, v);
+}
+
+_PUBLIC_ void ndr_print_uint3264(struct ndr_print *ndr, const char *name, uint32_t v)
+{
+       ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
+}
+
 _PUBLIC_ void ndr_print_udlong(struct ndr_print *ndr, const char *name, uint64_t v)
 {
        ndr->print(ndr, "%-25s: 0x%016llx (%llu)", name, (unsigned long long)v, (unsigned long long)v);
@@ -754,6 +1141,16 @@ _PUBLIC_ void ndr_print_time_t(struct ndr_print *ndr, const char *name, time_t t
        }
 }
 
+_PUBLIC_ void ndr_print_uid_t(struct ndr_print *ndr, const char *name, uid_t u)
+{
+       ndr_print_dlong(ndr, name, u);
+}
+
+_PUBLIC_ void ndr_print_gid_t(struct ndr_print *ndr, const char *name, gid_t g)
+{
+       ndr_print_dlong(ndr, name, g);
+}
+
 _PUBLIC_ void ndr_print_union(struct ndr_print *ndr, const char *name, int level, const char *type)
 {
        if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
@@ -768,13 +1165,19 @@ _PUBLIC_ void ndr_print_bad_level(struct ndr_print *ndr, const char *name, uint1
        ndr->print(ndr, "UNKNOWN LEVEL %u", level);
 }
 
-_PUBLIC_ void ndr_print_array_uint8(struct ndr_print *ndr, const char *name, 
+_PUBLIC_ void ndr_print_array_uint8(struct ndr_print *ndr, const char *name,
                           const uint8_t *data, uint32_t count)
 {
        int i;
+#define _ONELINE_LIMIT 32
 
-       if (count <= 600 && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
-               char s[1202];
+       if (data == NULL) {
+               ndr->print(ndr, "%s: ARRAY(%d) : NULL", name, count);
+               return;
+       }
+
+       if (count <= _ONELINE_LIMIT && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
+               char s[(_ONELINE_LIMIT + 1) * 2];
                for (i=0;i<count;i++) {
                        snprintf(&s[i*2], 3, "%02x", data[i]);
                }
@@ -784,6 +1187,11 @@ _PUBLIC_ void ndr_print_array_uint8(struct ndr_print *ndr, const char *name,
        }
 
        ndr->print(ndr, "%s: ARRAY(%d)", name, count);
+       if (count > _ONELINE_LIMIT && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
+               ndr_dump_data(ndr, data, count);
+               return;
+       }
+
        ndr->depth++;
        for (i=0;i<count;i++) {
                char *idx=NULL;
@@ -792,24 +1200,81 @@ _PUBLIC_ void ndr_print_array_uint8(struct ndr_print *ndr, const char *name,
                        free(idx);
                }
        }
-       ndr->depth--;   
+       ndr->depth--;
+#undef _ONELINE_LIMIT
+}
+
+static void ndr_print_asc(struct ndr_print *ndr, const uint8_t *buf, int len)
+{
+       int i;
+       for (i=0;i<len;i++)
+               ndr->print(ndr, "%c", isprint(buf[i])?buf[i]:'.');
 }
 
+/*
+  ndr_print version of dump_data()
+ */
+static void ndr_dump_data(struct ndr_print *ndr, const uint8_t *buf, int len)
+{
+       int i=0;
+
+       ndr->no_newline = true;
+
+       for (i=0;i<len;) {
+               if (i%16 == 0 && i<len) {
+                       ndr->print(ndr, "[%04X] ",i);
+               }
+
+               ndr->print(ndr, "%02X ",(int)buf[i]);
+               i++;
+               if (i%8 == 0) ndr->print(ndr,"  ");
+               if (i%16 == 0) {
+                       ndr_print_asc(ndr,&buf[i-16],8); ndr->print(ndr," ");
+                       ndr_print_asc(ndr,&buf[i-8],8); ndr->print(ndr, "\n");
+               }
+       }
+
+       if (i%16) {
+               int n;
+               n = 16 - (i%16);
+               ndr->print(ndr, " ");
+               if (n>8) ndr->print(ndr," ");
+               while (n--) ndr->print(ndr,"   ");
+               n = MIN(8,i%16);
+               ndr_print_asc(ndr,&buf[i-(i%16)],n); ndr->print(ndr, " ");
+               n = (i%16) - n;
+               if (n>0) ndr_print_asc(ndr,&buf[i-n],n);
+               ndr->print(ndr,"\n");
+       }
+
+       ndr->no_newline = false;
+}
+
+
 _PUBLIC_ void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_BLOB r)
 {
        ndr->print(ndr, "%-25s: DATA_BLOB length=%u", name, (unsigned)r.length);
        if (r.length) {
-               dump_data(10, r.data, r.length);
+               ndr_dump_data(ndr, r.data, r.length);
        }
 }
 
 
 /*
-  push a DATA_BLOB onto the wire. 
-*/
+ * Push a DATA_BLOB onto the wire.
+ * 1) When called with LIBNDR_FLAG_ALIGN* alignment flags set, push padding
+ *    bytes _only_. The length is determined by the alignment required and the
+ *    current ndr offset.
+ * 2) When called with the LIBNDR_FLAG_REMAINING flag, push the byte array to
+ *    the ndr buffer.
+ * 3) Otherwise, push a uint3264 length _and_ a corresponding byte array to the
+ *    ndr buffer.
+ */
 _PUBLIC_ enum ndr_err_code ndr_push_DATA_BLOB(struct ndr_push *ndr, int ndr_flags, DATA_BLOB blob)
 {
-       if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
+       if (ndr->flags & LIBNDR_FLAG_REMAINING) {
+               /* nothing to do */
+       } else if (ndr->flags & (LIBNDR_ALIGN_FLAGS & ~LIBNDR_FLAG_NOALIGN)) {
                if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
                        blob.length = NDR_ALIGN(ndr, 2);
                } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
@@ -819,21 +1284,30 @@ _PUBLIC_ enum ndr_err_code ndr_push_DATA_BLOB(struct ndr_push *ndr, int ndr_flag
                }
                NDR_PUSH_ALLOC_SIZE(ndr, blob.data, blob.length);
                data_blob_clear(&blob);
-       } else if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
-               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, blob.length));
+       } else {
+               NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, blob.length));
        }
        NDR_CHECK(ndr_push_bytes(ndr, blob.data, blob.length));
        return NDR_ERR_SUCCESS;
 }
 
 /*
-  pull a DATA_BLOB from the wire. 
-*/
+ * Pull a DATA_BLOB from the wire.
+ * 1) when called with LIBNDR_FLAG_ALIGN* alignment flags set, pull padding
+ *    bytes _only_. The length is determined by the alignment required and the
+ *    current ndr offset.
+ * 2) When called with the LIBNDR_FLAG_REMAINING flag, pull all remaining bytes
+ *    from the ndr buffer.
+ * 3) Otherwise, pull a uint3264 length _and_ a corresponding byte array from the
+ *    ndr buffer.
+ */
 _PUBLIC_ enum ndr_err_code ndr_pull_DATA_BLOB(struct ndr_pull *ndr, int ndr_flags, DATA_BLOB *blob)
 {
        uint32_t length = 0;
 
-       if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
+       if (ndr->flags & LIBNDR_FLAG_REMAINING) {
+               length = ndr->data_size - ndr->offset;
+       } else if (ndr->flags & (LIBNDR_ALIGN_FLAGS & ~LIBNDR_FLAG_NOALIGN)) {
                if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
                        length = NDR_ALIGN(ndr, 2);
                } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
@@ -844,10 +1318,8 @@ _PUBLIC_ enum ndr_err_code ndr_pull_DATA_BLOB(struct ndr_pull *ndr, int ndr_flag
                if (ndr->data_size - ndr->offset < length) {
                        length = ndr->data_size - ndr->offset;
                }
-       } else if (ndr->flags & LIBNDR_FLAG_REMAINING) {
-               length = ndr->data_size - ndr->offset;
        } else {
-               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &length));
+               NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &length));
        }
        NDR_PULL_NEED_BYTES(ndr, length);
        *blob = data_blob_talloc(ndr->current_mem_ctx, ndr->data+ndr->offset, length);
@@ -860,3 +1332,120 @@ _PUBLIC_ uint32_t ndr_size_DATA_BLOB(int ret, const DATA_BLOB *data, int flags)
        if (!data) return ret;
        return ret + data->length;
 }
+
+_PUBLIC_ void ndr_print_bool(struct ndr_print *ndr, const char *name, const bool b)
+{
+       ndr->print(ndr, "%-25s: %s", name, b?"true":"false");
+}
+
+_PUBLIC_ NTSTATUS ndr_map_error2ntstatus(enum ndr_err_code ndr_err)
+{
+       switch (ndr_err) {
+       case NDR_ERR_SUCCESS:
+               return NT_STATUS_OK;
+       case NDR_ERR_BUFSIZE:
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       case NDR_ERR_TOKEN:
+               return NT_STATUS_INTERNAL_ERROR;
+       case NDR_ERR_ALLOC:
+               return NT_STATUS_NO_MEMORY;
+       case NDR_ERR_ARRAY_SIZE:
+               return NT_STATUS_ARRAY_BOUNDS_EXCEEDED;
+       case NDR_ERR_INVALID_POINTER:
+               return NT_STATUS_INVALID_PARAMETER_MIX;
+       case NDR_ERR_UNREAD_BYTES:
+               return NT_STATUS_PORT_MESSAGE_TOO_LONG;
+       default:
+               break;
+       }
+
+       /* we should map all error codes to different status codes */
+       return NT_STATUS_INVALID_PARAMETER;
+}
+
+_PUBLIC_ int ndr_map_error2errno(enum ndr_err_code ndr_err)
+{
+       switch (ndr_err) {
+       case NDR_ERR_SUCCESS:
+               return 0;
+       case NDR_ERR_BUFSIZE:
+               return ENOSPC;
+       case NDR_ERR_TOKEN:
+               return EINVAL;
+       case NDR_ERR_ALLOC:
+               return ENOMEM;
+       case NDR_ERR_ARRAY_SIZE:
+               return EMSGSIZE;
+       case NDR_ERR_INVALID_POINTER:
+               return EINVAL;
+       case NDR_ERR_UNREAD_BYTES:
+               return EOVERFLOW;
+       default:
+               break;
+       }
+
+       /* we should map all error codes to different status codes */
+       return EINVAL;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_timespec(struct ndr_push *ndr,
+                                            int ndr_flags,
+                                            const struct timespec *t)
+{
+       NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+       NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t->tv_sec));
+       NDR_CHECK(ndr_push_uint32(ndr, ndr_flags, t->tv_nsec));
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_timespec(struct ndr_pull *ndr,
+                                            int ndr_flags,
+                                            struct timespec *t)
+{
+       uint64_t secs;
+       uint32_t nsecs;
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+       NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, &secs));
+       NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &nsecs));
+       t->tv_sec = secs;
+       t->tv_nsec = nsecs;
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_timespec(struct ndr_print *ndr, const char *name,
+                                const struct timespec *t)
+{
+       ndr->print(ndr, "%-25s: %s.%ld", name, timestring(ndr, t->tv_sec),
+                  (long)t->tv_nsec);
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_timeval(struct ndr_push *ndr,
+                                           int ndr_flags,
+                                           const struct timeval *t)
+{
+       NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+       NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t->tv_sec));
+       NDR_CHECK(ndr_push_uint32(ndr, ndr_flags, t->tv_usec));
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_timeval(struct ndr_pull *ndr,
+                                           int ndr_flags,
+                                           struct timeval *t)
+{
+       uint64_t secs;
+       uint32_t usecs;
+       NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+       NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, &secs));
+       NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &usecs));
+       t->tv_sec = secs;
+       t->tv_usec = usecs;
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_timeval(struct ndr_print *ndr, const char *name,
+                               const struct timeval *t)
+{
+       ndr->print(ndr, "%-25s: %s.%ld", name, timestring(ndr, t->tv_sec),
+                  (long)t->tv_usec);
+}