ndr: added support for NDR64
authorAndrew Tridgell <tridge@samba.org>
Thu, 17 Sep 2009 16:08:47 +0000 (09:08 -0700)
committerAndrew Tridgell <tridge@samba.org>
Fri, 18 Sep 2009 04:52:24 +0000 (21:52 -0700)
This adds NDR64 support for the push functions in libndr

librpc/ndr/libndr.h
librpc/ndr/ndr.c
librpc/ndr/ndr_basic.c

index 1868af610446c2cb476d0cb233770f37e31699e2..16a1ff65d0c2b4e413e160ea1cd10bd0b8e5c59c 100644 (file)
@@ -165,7 +165,7 @@ struct ndr_print {
 #define NDR_PRINT_OUT_STRING(ctx, type, p) NDR_PRINT_FUNCTION_STRING(ctx, type, NDR_OUT, p)
 #define NDR_PRINT_IN_STRING(ctx, type, p) NDR_PRINT_FUNCTION_STRING(ctx, type, NDR_IN | NDR_SET_VALUES, p)
 
-#define NDR_BE(ndr) (((ndr)->flags & (LIBNDR_FLAG_BIGENDIAN|LIBNDR_FLAG_LITTLE_ENDIAN)) == LIBNDR_FLAG_BIGENDIAN)
+#define NDR_BE(ndr) (unlikely(((ndr)->flags & (LIBNDR_FLAG_BIGENDIAN|LIBNDR_FLAG_LITTLE_ENDIAN)) == LIBNDR_FLAG_BIGENDIAN))
 
 enum ndr_err_code {
        NDR_ERR_SUCCESS = 0,
@@ -185,7 +185,8 @@ enum ndr_err_code {
        NDR_ERR_TOKEN,
        NDR_ERR_IPV4ADDRESS,
        NDR_ERR_INVALID_POINTER,
-       NDR_ERR_UNREAD_BYTES
+       NDR_ERR_UNREAD_BYTES,
+       NDR_ERR_NDR64
 };
 
 #define NDR_ERR_CODE_IS_SUCCESS(x) (x == NDR_ERR_SUCCESS)
@@ -216,7 +217,7 @@ enum ndr_compression_alg {
 #define NDR_SET_VALUES 4
 
 #define NDR_PULL_NEED_BYTES(ndr, n) do { \
-       if ((n) > ndr->data_size || ndr->offset + (n) > ndr->data_size) { \
+       if (unlikely((n) > ndr->data_size || ndr->offset + (n) > ndr->data_size)) { \
                return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "Pull bytes %u (%s)", (unsigned)n, __location__); \
        } \
 } while(0)
@@ -226,13 +227,13 @@ enum ndr_compression_alg {
 #define NDR_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
 
 #define NDR_PULL_ALIGN(ndr, n) do { \
-       if (!(ndr->flags & LIBNDR_FLAG_NOALIGN)) { \
-               if (ndr->flags & LIBNDR_FLAG_PAD_CHECK) { \
+       if (unlikely(!(ndr->flags & LIBNDR_FLAG_NOALIGN))) {    \
+               if (unlikely(ndr->flags & LIBNDR_FLAG_PAD_CHECK)) {     \
                        ndr_check_padding(ndr, n); \
                } \
                ndr->offset = (ndr->offset + (n-1)) & ~(n-1); \
        } \
-       if (ndr->offset > ndr->data_size) { \
+       if (unlikely(ndr->offset > ndr->data_size)) {                   \
                return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "Pull align %u", (unsigned)n); \
        } \
 } while(0)
@@ -240,7 +241,7 @@ enum ndr_compression_alg {
 #define NDR_PUSH_NEED_BYTES(ndr, n) NDR_CHECK(ndr_push_expand(ndr, n))
 
 #define NDR_PUSH_ALIGN(ndr, n) do { \
-       if (!(ndr->flags & LIBNDR_FLAG_NOALIGN)) { \
+       if (likely(!(ndr->flags & LIBNDR_FLAG_NOALIGN))) {      \
                uint32_t _pad = ((ndr->offset + (n-1)) & ~(n-1)) - ndr->offset; \
                while (_pad--) NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, 0)); \
        } \
@@ -251,7 +252,7 @@ enum ndr_compression_alg {
 #define NDR_CHECK(call) do { \
        enum ndr_err_code _status; \
        _status = call; \
-       if (!NDR_ERR_CODE_IS_SUCCESS(_status)) { \
+       if (unlikely(!NDR_ERR_CODE_IS_SUCCESS(_status))) {      \
                return _status; \
        } \
 } while (0)
@@ -260,7 +261,7 @@ enum ndr_compression_alg {
 #define NDR_CHECK_FREE(call) do { \
        enum ndr_err_code _status; \
        _status = call; \
-       if (!NDR_ERR_CODE_IS_SUCCESS(_status)) { \
+       if (unlikely(!NDR_ERR_CODE_IS_SUCCESS(_status))) {      \
                talloc_free(ndr);                \
                return _status; \
        } \
@@ -289,24 +290,24 @@ enum ndr_compression_alg {
 #define NDR_PULL_ALLOC(ndr, s) do { \
        _NDR_PULL_FIX_CURRENT_MEM_CTX(ndr);\
        (s) = talloc_ptrtype(ndr->current_mem_ctx, (s)); \
-       if (!(s)) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Alloc %s failed: %s\n", # s, __location__); \
+       if (unlikely(!(s))) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Alloc %s failed: %s\n", # s, __location__); \
 } while (0)
 
 #define NDR_PULL_ALLOC_N(ndr, s, n) do { \
        _NDR_PULL_FIX_CURRENT_MEM_CTX(ndr);\
        (s) = talloc_array_ptrtype(ndr->current_mem_ctx, (s), n); \
-       if (!(s)) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Alloc %u * %s failed: %s\n", (unsigned)n, # s, __location__); \
+       if (unlikely(!(s))) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Alloc %u * %s failed: %s\n", (unsigned)n, # s, __location__); \
 } while (0)
 
 
 #define NDR_PUSH_ALLOC_SIZE(ndr, s, size) do { \
        (s) = talloc_array(ndr, uint8_t, size); \
-       if (!(s)) return ndr_push_error(ndr, NDR_ERR_ALLOC, "push alloc %u failed: %s\n", (unsigned)size, __location__); \
+       if (unlikely(!(s))) return ndr_push_error(ndr, NDR_ERR_ALLOC, "push alloc %u failed: %s\n", (unsigned)size, __location__); \
 } while (0)
 
 #define NDR_PUSH_ALLOC(ndr, s) do { \
        (s) = talloc_ptrtype(ndr, (s)); \
-       if (!(s)) return ndr_push_error(ndr, NDR_ERR_ALLOC, "push alloc %s failed: %s\n", # s, __location__); \
+       if (unlikely(!(s))) return ndr_push_error(ndr, NDR_ERR_ALLOC, "push alloc %s failed: %s\n", # s, __location__); \
 } while (0)
 
 /* these are used when generic fn pointers are needed for ndr push/pull fns */
index ef318d64d2a25cf0699d3253c496f6fe788cf836..d629d852e8dedb6286fb4624a96e9bfb5405d9e8 100644 (file)
@@ -355,9 +355,11 @@ _PUBLIC_ void ndr_set_flags(uint32_t *pflags, uint32_t new_flags)
        /* the big/little endian flags are inter-dependent */
        if (new_flags & LIBNDR_FLAG_LITTLE_ENDIAN) {
                (*pflags) &= ~LIBNDR_FLAG_BIGENDIAN;
+               (*pflags) &= ~LIBNDR_FLAG_NDR64;
        }
        if (new_flags & LIBNDR_FLAG_BIGENDIAN) {
                (*pflags) &= ~LIBNDR_FLAG_LITTLE_ENDIAN;
+               (*pflags) &= ~LIBNDR_FLAG_NDR64;
        }
        if (new_flags & LIBNDR_FLAG_REMAINING) {
                (*pflags) &= ~LIBNDR_ALIGN_FLAGS;
@@ -1168,6 +1170,7 @@ const static struct {
        { NDR_ERR_IPV4ADDRESS, "IPv4 Address Error" },
        { NDR_ERR_INVALID_POINTER, "Invalid Pointer" },
        { NDR_ERR_UNREAD_BYTES, "Unread Bytes" },
+       { NDR_ERR_NDR64, "NDR64 assertion error" },
        { 0, NULL }
 };
 
index 6781ccda2e6ef2742501d07516558426fc1f3d0f..efadb1e95e402580a63e7c4525a7967222b923e4 100644 (file)
@@ -132,14 +132,15 @@ _PUBLIC_ enum ndr_err_code ndr_pull_uint3264(struct ndr_pull *ndr, int ndr_flags
 {
        uint64_t v64;
        enum ndr_err_code err;
-       if (!(ndr->flags & LIBNDR_FLAG_NDR64)) {
+       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 (v64 != *v) {
+       if (unlikely(v64 != *v)) {
                DEBUG(0,(__location__ ": non-zero upper 32 bits 0x%016llx\n",
                         (unsigned long long)v64));
+               return NDR_ERR_NDR64;
        }
        return err;
 }
@@ -376,6 +377,21 @@ _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);
+       }
+       NDR_PUSH_ALIGN(ndr, 4);
+       NDR_PUSH_NEED_BYTES(ndr, 4);
+       NDR_SIVAL(ndr, ndr->offset, v);
+       ndr->offset += 4;
+       return NDR_ERR_SUCCESS;
+}
+
 /*
   push a udlong
 */
@@ -446,12 +462,28 @@ _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;
+               }
+       }
        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;
+               }
+       }
        NDR_PULL_ALIGN(ndr, size);
        return NDR_ERR_SUCCESS;
 }
@@ -500,7 +532,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);
 }
 
 /*
@@ -518,7 +550,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);
 }
 
 /*
@@ -526,7 +558,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);
 }