libndr: Fix ndr_print_bitmap_flag for value=0
[mat/samba.git] / librpc / ndr / ndr_basic.c
index 807db59995c31c72ea9b532b2d147c882030c4aa..113745ce978ecdad33c5e3c4864871323caee6ac 100644 (file)
@@ -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);
@@ -132,6 +160,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_uint3264(struct ndr_pull *ndr, int ndr_flags
 {
        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);
        }
@@ -140,7 +169,8 @@ _PUBLIC_ enum ndr_err_code ndr_pull_uint3264(struct ndr_pull *ndr, int ndr_flags
        if (unlikely(v64 != *v)) {
                DEBUG(0,(__location__ ": non-zero upper 32 bits 0x%016llx\n",
                         (unsigned long long)v64));
-               return NDR_ERR_NDR64;
+               return ndr_pull_error(ndr, NDR_ERR_NDR64, __location__ ": non-zero upper 32 bits 0x%016llx\n",
+                        (unsigned long long)v64);
        }
        return err;
 }
@@ -150,6 +180,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_uint3264(struct ndr_pull *ndr, int ndr_flags
 */
 _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);
@@ -157,6 +188,19 @@ _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
 */
@@ -185,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);
@@ -198,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;
@@ -220,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);
 }
 
@@ -229,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));
@@ -243,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;
@@ -267,6 +318,7 @@ _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;
@@ -282,9 +334,17 @@ _PUBLIC_ enum ndr_err_code ndr_pull_enum_uint8(struct ndr_pull *ndr, int ndr_fla
 }
 
 /*
-  parse a uint16_t enum (uint32_t on NDR64)
+  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;
@@ -296,11 +356,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_enum_uint16(struct ndr_pull *ndr, int ndr_fl
                }
                return NDR_ERR_SUCCESS;
        }
-       NDR_PULL_ALIGN(ndr, 2);
-       NDR_PULL_NEED_BYTES(ndr, 2);
-       *v = NDR_SVAL(ndr, ndr->offset);
-       ndr->offset += 2;
-       return NDR_ERR_SUCCESS;
+       return ndr_pull_uint16(ndr, ndr_flags, v);
 }
 
 /*
@@ -320,13 +376,10 @@ _PUBLIC_ enum ndr_err_code ndr_push_enum_uint8(struct ndr_push *ndr, int ndr_fla
 }
 
 /*
-  push a uint16_t enum (uint32_t on NDR64)
+  push a uint16_t enum
 */
 _PUBLIC_ enum ndr_err_code ndr_push_enum_uint16(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);
 }
 
@@ -338,6 +391,16 @@ _PUBLIC_ enum ndr_err_code ndr_push_enum_uint32(struct ndr_push *ndr, int ndr_fl
        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
@@ -368,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;
        }
@@ -379,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;
@@ -390,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;
@@ -401,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);
@@ -413,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);
@@ -420,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);
@@ -437,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);
@@ -452,11 +533,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_uint3264(struct ndr_push *ndr, int ndr_flags
        if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
                return ndr_push_hyper(ndr, ndr_flags, v);
        }
-       NDR_PUSH_ALIGN(ndr, 4);
-       NDR_PUSH_NEED_BYTES(ndr, 4);
-       NDR_SIVAL(ndr, ndr->offset, v);
-       ndr->offset += 4;
-       return NDR_ERR_SUCCESS;
+       return ndr_push_uint32(ndr, ndr_flags, v);
 }
 
 /*
@@ -464,6 +541,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_uint3264(struct ndr_push *ndr, int ndr_flags
 */
 _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));
@@ -477,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));
@@ -499,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);
 }
 
@@ -507,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);
@@ -520,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));
@@ -536,6 +620,12 @@ _PUBLIC_ enum ndr_err_code ndr_push_align(struct ndr_push *ndr, size_t size)
                } 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;
@@ -550,6 +640,12 @@ _PUBLIC_ enum ndr_err_code ndr_pull_align(struct ndr_pull *ndr, size_t size)
                } 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;
@@ -618,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;
        }
@@ -670,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;
 }
@@ -679,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;
 }
@@ -688,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;
@@ -698,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;
@@ -708,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;
 }
@@ -717,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;
 }
@@ -741,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
 */
@@ -763,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);
@@ -774,18 +929,82 @@ _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_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)
 {
@@ -801,6 +1020,10 @@ _PUBLIC_ void ndr_print_bitmap_flag(struct ndr_print *ndr, size_t size, const ch
        /* this is an attempt to support multi-bit bitmap masks */
        value &= flag;
 
+       if (value == 0) {
+               return;
+       }
+
        while (!(flag & 1)) {
                flag >>= 1;
                value >>= 1;
@@ -842,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);
@@ -908,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) {
@@ -926,9 +1169,15 @@ _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 (data == NULL) {
+               ndr->print(ndr, "%s: ARRAY(%d) : NULL", name, count);
+               return;
+       }
 
-       if (count <= 600 && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
-               char s[1202];
+       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]);
                }
@@ -938,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;
@@ -947,23 +1201,80 @@ _PUBLIC_ void ndr_print_array_uint8(struct ndr_print *ndr, const char *name,
                }
        }
        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) {
@@ -973,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) {
@@ -998,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);
@@ -1014,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);
+}