ndr: fix push/pull DATA_BLOB with NDR_NOALIGN
[mat/samba.git] / librpc / ndr / ndr_basic.c
index b4443003d0613b7ea273cf756c995ae81c45479f..1887838779d409941ec336c6ffb9a66682c3ad64 100644 (file)
@@ -61,6 +61,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;
@@ -72,6 +73,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;
@@ -83,6 +85,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);
@@ -95,6 +98,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);
@@ -107,6 +111,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_uint16(struct ndr_pull *ndr, int ndr_flags,
 */
 _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);
@@ -125,6 +130,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_uint1632(struct ndr_pull *ndr, int ndr_flags
 */
 _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);
@@ -137,6 +143,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);
@@ -151,6 +158,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);
        }
@@ -169,6 +177,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);
@@ -217,6 +226,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);
@@ -230,6 +240,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;
@@ -264,6 +275,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));
@@ -278,6 +290,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;
@@ -302,6 +315,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;
@@ -414,6 +428,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;
        }
@@ -425,6 +440,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;
@@ -436,6 +452,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;
@@ -447,6 +464,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);
@@ -459,6 +477,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);
@@ -482,6 +501,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_uint1632(struct ndr_push *ndr, int ndr_flags
 */
 _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);
@@ -494,6 +514,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);
@@ -517,6 +538,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));
@@ -530,6 +552,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));
@@ -563,6 +586,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);
@@ -576,6 +600,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));
@@ -686,6 +711,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;
        }
@@ -738,6 +764,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;
 }
@@ -747,6 +774,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;
 }
@@ -756,6 +784,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;
@@ -766,6 +795,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;
@@ -776,6 +806,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;
 }
@@ -785,6 +816,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;
 }
@@ -814,6 +846,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_time_t(struct ndr_pull *ndr, int ndr_flags,
 */
 _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);
 }
 
@@ -839,6 +872,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_uid_t(struct ndr_pull *ndr, int ndr_flags, u
 */
 _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);
 }
 
@@ -1213,16 +1247,21 @@ _PUBLIC_ void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_
 
 
 /*
-  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 uint32 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_FLAG_REMAINING) {
                /* nothing to do */
-       } else if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
-               if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
-                       blob.length = 0;
-               } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
+       } 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) {
                        blob.length = NDR_ALIGN(ndr, 4);
@@ -1239,18 +1278,23 @@ _PUBLIC_ enum ndr_err_code ndr_push_DATA_BLOB(struct ndr_push *ndr, int ndr_flag
 }
 
 /*
-  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 uint32 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_FLAG_REMAINING) {
                length = ndr->data_size - ndr->offset;
-       } else if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
-               if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
-                       length = 0;
-               } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
+       } 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) {
                        length = NDR_ALIGN(ndr, 4);
@@ -1304,3 +1348,90 @@ _PUBLIC_ NTSTATUS ndr_map_error2ntstatus(enum ndr_err_code ndr_err)
        /* 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);
+}