From 08f16292a0cfab57c484661c1f05e1a49ec06942 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 29 Sep 2005 14:00:07 +0000 Subject: r10608: - fix hierachical memory handling in ndr_pull_nbt_name - add wrepl_nbt_name scalar type and do the pull/push in the ndr layer instead of the caller - give the flags and group_flag in the wrepl_name a meaning metze (This used to be commit b98efc2905e1147eb97111b46a877bdb9d8dd154) --- source4/libcli/nbt/nbtname.c | 126 ++++++++++++++++++++++++++++++-- source4/libcli/wrepl/winsrepl.c | 47 ++---------- source4/libcli/wrepl/winsrepl.h | 16 +++- source4/pidl/lib/Parse/Pidl/Typelist.pm | 11 ++- source4/torture/nbt/winsreplication.c | 7 +- 5 files changed, 152 insertions(+), 55 deletions(-) diff --git a/source4/libcli/nbt/nbtname.c b/source4/libcli/nbt/nbtname.c index ae6df8a18d..86309b7f6b 100644 --- a/source4/libcli/nbt/nbtname.c +++ b/source4/libcli/nbt/nbtname.c @@ -294,7 +294,7 @@ NTSTATUS ndr_pull_nbt_name(struct ndr_pull *ndr, int ndr_flags, struct nbt_name scope = strchr(s, '.'); if (scope) { *scope = 0; - r->scope = talloc_strdup(ndr, scope+1); + r->scope = talloc_strdup(ndr->current_mem_ctx, scope+1); NT_STATUS_HAVE_NO_MEMORY(r->scope); } else { r->scope = NULL; @@ -312,7 +312,7 @@ NTSTATUS ndr_pull_nbt_name(struct ndr_pull *ndr, int ndr_flags, struct nbt_name status = decompress_name(cname, &r->type); NT_STATUS_NOT_OK_RETURN(status); - r->name = talloc_strdup(ndr, cname); + r->name = talloc_strdup(ndr->current_mem_ctx, cname); NT_STATUS_HAVE_NO_MEMORY(r->name); talloc_free(cname); @@ -344,12 +344,7 @@ NTSTATUS ndr_push_nbt_name(struct ndr_push *ndr, int ndr_flags, const struct nbt } status = ndr_push_nbt_string(ndr, ndr_flags, fullname); -#if 0 - /* this free conflicts with the use of pointers into strings - in the ndr_token_store() calls above. Metze, can you look - at this? */ - talloc_free(fullname); -#endif + return status; } @@ -476,3 +471,118 @@ char *nbt_name_string(TALLOC_CTX *mem_ctx, const struct nbt_name *name) return ret; } +/* + pull a nbt name, WINS Replication uses another on wire format for nbt name +*/ +NTSTATUS ndr_pull_wrepl_nbt_name(struct ndr_pull *ndr, int ndr_flags, struct nbt_name *r) +{ + uint8_t *namebuf; + uint32_t namebuf_len; + + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + + NDR_CHECK(ndr_pull_align(ndr, 4)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &namebuf_len)); + if (namebuf_len < 1 || namebuf_len > 255) { + return ndr_pull_error(ndr, NDR_ERR_ALLOC, "value out of range"); + } + NDR_PULL_ALLOC_N(ndr, namebuf, namebuf_len); + NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, namebuf, namebuf_len)); + + /* oh wow, what a nasty bug in windows ... */ + if (namebuf[0] == 0x1b && namebuf_len >= 16) { + namebuf[0] = namebuf[15]; + namebuf[15] = 0x1b; + } + + if (namebuf_len < 17) { + r->type = 0x00; + + r->name = talloc_strndup(ndr->current_mem_ctx, (char *)namebuf, namebuf_len); + if (!r->name) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "out of memory"); + + r->scope= NULL; + + talloc_free(namebuf); + return NT_STATUS_OK; + } + + r->type = namebuf[15]; + + namebuf[15] = '\0'; + trim_string((char *)namebuf, NULL, " "); + r->name = talloc_strdup(ndr->current_mem_ctx, (char *)namebuf); + if (!r->name) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "out of memory"); + + if (namebuf_len > 18) { + r->scope = talloc_strndup(ndr->current_mem_ctx, (char *)(namebuf+17), namebuf_len-17); + if (!r->scope) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "out of memory"); + } else { + r->scope = NULL; + } + + talloc_free(namebuf); + return NT_STATUS_OK; +} + +/* + push a nbt name, WINS Replication uses another on wire format for nbt name +*/ +NTSTATUS ndr_push_wrepl_nbt_name(struct ndr_push *ndr, int ndr_flags, const struct nbt_name r) +{ + uint8_t *namebuf; + uint32_t namebuf_len; + uint32_t name_len; + uint32_t scope_len = 0; + + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + + name_len = strlen(r.name); + if (name_len > 15) { + return NT_STATUS_INVALID_PARAMETER_MIX; + } + + if (r.scope) { + scope_len = strlen(r.scope); + } + if (scope_len > 238) { + return NT_STATUS_INVALID_PARAMETER_MIX; + } + + namebuf = (uint8_t *)talloc_asprintf(ndr, "%-15s%c%s", + r.name, 'X', + (r.scope?r.scope:"")); + if (!namebuf) return ndr_push_error(ndr, NDR_ERR_ALLOC, "out of memory"); + + namebuf_len = strlen((char *)namebuf) + 1; + + /* + * we need to set the type here, and use a place-holder in the talloc_asprintf() + * as the type can be 0x00, and then the namebuf_len = strlen(namebuf); would give wrong results + */ + namebuf[15] = r.type; + + /* oh wow, what a nasty bug in windows ... */ + if (r.type == 0x1b) { + namebuf[15] = namebuf[0]; + namebuf[0] = 0x1b; + } + + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, namebuf_len)); + NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, namebuf, namebuf_len)); + + talloc_free(namebuf); + return NT_STATUS_OK; +} + +void ndr_print_wrepl_nbt_name(struct ndr_print *ndr, const char *name, const struct nbt_name r) +{ + char *s = nbt_name_string(ndr, &r); + ndr_print_string(ndr, name, s); + talloc_free(s); +} diff --git a/source4/libcli/wrepl/winsrepl.c b/source4/libcli/wrepl/winsrepl.c index 069ee29407..feeea321b1 100644 --- a/source4/libcli/wrepl/winsrepl.c +++ b/source4/libcli/wrepl/winsrepl.c @@ -671,40 +671,6 @@ struct wrepl_request *wrepl_pull_names_send(struct wrepl_socket *wrepl_socket, return req; } - -/* - extract a nbt_name from a WINS name buffer -*/ -static NTSTATUS wrepl_extract_name(struct nbt_name *name, - TALLOC_CTX *mem_ctx, - uint8_t *namebuf, uint32_t len) -{ - char *s; - - /* oh wow, what a nasty bug in windows ... */ - if (namebuf[0] == 0x1b && len >= 16) { - namebuf[0] = namebuf[15]; - namebuf[15] = 0x1b; - } - - if (len < 17) { - make_nbt_name_client(name, talloc_strndup(mem_ctx, (char *)namebuf, len)); - return NT_STATUS_OK; - } - - s = talloc_strndup(mem_ctx, (char *)namebuf, 15); - trim_string(s, NULL, " "); - name->name = s; - name->type = namebuf[15]; - if (len > 18) { - name->scope = talloc_strndup(mem_ctx, (char *)(namebuf+17), len-17); - } else { - name->scope = NULL; - } - - return NT_STATUS_OK; -} - /* fetch the names for a WINS partner - recv */ @@ -735,12 +701,15 @@ NTSTATUS wrepl_pull_names_recv(struct wrepl_request *req, for (i=0;iout.num_names;i++) { struct wrepl_wins_name *wname = &packet->message.replication.info.reply.names[i]; struct wrepl_name *name = &io->out.names[i]; - status = wrepl_extract_name(&name->name, io->out.names, - wname->name, wname->name_len); - if (!NT_STATUS_IS_OK(status)) goto failed; - name->flags = wname->flags; - name->group_flag= wname->group_flag; + name->name = wname->name; + talloc_steal(io->out.names, wname->name.name); + talloc_steal(io->out.names, wname->name.scope); + name->type = WREPL_NAME_TYPE(wname->flags); + name->state = WREPL_NAME_STATE(wname->flags); + name->node = WREPL_NBT_NODE(wname->flags); + name->is_static = WREPL_NAME_IS_STATIC(wname->flags); + name->raw_flags = wname->flags; name->version_id= wname->id; name->owner = talloc_strdup(io->out.names, io->in.partner.address); if (name->owner == NULL) goto nomem; diff --git a/source4/libcli/wrepl/winsrepl.h b/source4/libcli/wrepl/winsrepl.h index 2253fe181e..9b9362e4b3 100644 --- a/source4/libcli/wrepl/winsrepl.h +++ b/source4/libcli/wrepl/winsrepl.h @@ -104,6 +104,15 @@ struct wrepl_pull_table { } out; }; +#define WREPL_NAME_TYPE(flags) (flags & WREPL_FLAGS_RECORD_TYPE) +#define WREPL_NAME_STATE(flags) ((flags & WREPL_FLAGS_RECORD_STATE)>>2) +#define WREPL_NBT_NODE(flags) ((flags & WREPL_FLAGS_NODE_TYPE)<<8) +#define WREPL_NAME_IS_STATIC(flags) ((flags & WREPL_FLAGS_IS_STATIC)?True:False) + +#define WREPL_NAME_FLAGS(type, state, node, is_static) \ + (type | (state << 2) | (node>>8) | \ + (is_static ? WREPL_FLAGS_IS_STATIC : 0)) + /* a full pull replication */ @@ -116,8 +125,11 @@ struct wrepl_pull_names { uint32_t num_names; struct wrepl_name { struct nbt_name name; - uint32_t flags; - uint32_t group_flag; + enum wrepl_name_type type; + enum wrepl_name_state state; + enum nbt_node_type node; + BOOL is_static; + uint32_t raw_flags; uint64_t version_id; const char *owner; uint32_t num_addresses; diff --git a/source4/pidl/lib/Parse/Pidl/Typelist.pm b/source4/pidl/lib/Parse/Pidl/Typelist.pm index 7dfbe761de..d81fedf71e 100644 --- a/source4/pidl/lib/Parse/Pidl/Typelist.pm +++ b/source4/pidl/lib/Parse/Pidl/Typelist.pm @@ -140,9 +140,9 @@ my $scalars = { NDR_ALIGN => 4 }, "COMRESULT" => { - "C_TYPE" => "COMRESULT", - IS_REFERENCE => 0, - NDR_ALIGN => 4 + C_TYPE => "COMRESULT", + IS_REFERENCE => 0, + NDR_ALIGN => 4 }, # special types @@ -151,6 +151,11 @@ my $scalars = { IS_REFERENCE => 1, NDR_ALIGN => 4 #??? }, + "wrepl_nbt_name"=> { + C_TYPE => "struct nbt_name", + IS_REFERENCE => 0, + NDR_ALIGN => 4 + }, "ipv4address" => { C_TYPE => "const char *", IS_REFERENCE => 1, diff --git a/source4/torture/nbt/winsreplication.c b/source4/torture/nbt/winsreplication.c index cd60e12499..d3ec5e84d6 100644 --- a/source4/torture/nbt/winsreplication.c +++ b/source4/torture/nbt/winsreplication.c @@ -147,9 +147,10 @@ static void display_entry(TALLOC_CTX *mem_ctx, struct wrepl_name *name) int i; printf("%s\n", nbt_name_string(mem_ctx, &name->name)); - printf("\tFLAGS: 0x%08X G_FLAG: 0x%08X VERSION_ID: %llu\n", - name->flags, name->group_flag, name->version_id); - printf("\tOWNER: %-15s\n", name->owner); + printf("\tTYPE:%u STATE:%u NODE:0x%04X STATIC:%u VERSION_ID: %llu\n", + name->type, name->state, name->node, name->is_static, name->version_id); + printf("\tRAW_FLAGS:0x%08X OWNER: %-15s\n", + name->raw_flags, name->owner); for (i=0;inum_addresses;i++) { printf("\tADDR: %-15s OWNER: %-15s\n", name->addresses[i].address, name->addresses[i].owner); -- cgit