From ea923fb4a26f88664a1db36e1a93a2c96239a7a4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 21 Jan 2005 06:54:10 +0000 Subject: r4885: added a new NBT client library. Features include: - structures defined using IDL in nbt.idl - build around our events structure, and talloc - fully async - supports all NBT packet fields as per rfc1002 - easy interfaces for name query and status For the moment there are just a couple of test functions in namequery.c, test_name_query() and test_name_status(). These will be removed when we hook the new library into libcli/ fully The new library will also be a fairly good basis for a nbt server. Although it can't be a server as-is, I wrote it with the needs of a server in mind (for example, extremely scalable idtree based packet handling) (This used to be commit ae7e625bfa4b4a3ee32c64566064b6a4c84ee4b9) --- source4/librpc/config.mk | 9 ++- source4/librpc/idl/idl_types.h | 6 ++ source4/librpc/idl/nbt.idl | 166 +++++++++++++++++++++++++++++++++++++++++ source4/librpc/ndr/libndr.h | 3 +- source4/librpc/ndr/ndr.c | 21 ++++++ source4/librpc/ndr/ndr_basic.c | 34 ++++++--- 6 files changed, 226 insertions(+), 13 deletions(-) create mode 100644 source4/librpc/idl/nbt.idl (limited to 'source4/librpc') diff --git a/source4/librpc/config.mk b/source4/librpc/config.mk index 3fbd5dadbc..75582c2adc 100644 --- a/source4/librpc/config.mk +++ b/source4/librpc/config.mk @@ -287,6 +287,13 @@ INIT_OBJ_FILES = librpc/gen_ndr/ndr_schannel.o NOPROTO = YES REQUIRED_SUBSYSTEMS = LIBNDR +[SUBSYSTEM::NDR_NBT] +INIT_OBJ_FILES = librpc/gen_ndr/ndr_nbt.o +INIT_FUNCTION = dcerpc_nbt_init +NOPROTO = YES +REQUIRED_SUBSYSTEMS = LIBNDR + + [SUBSYSTEM::NDR_ALL] REQUIRED_SUBSYSTEMS = NDR_AUDIOSRV NDR_ECHO NDR_DCERPC NDR_EXCHANGE \ NDR_DSBACKUP NDR_EFS NDR_MISC NDR_LSA NDR_DFS NDR_DRSUAPI \ @@ -295,7 +302,7 @@ REQUIRED_SUBSYSTEMS = NDR_AUDIOSRV NDR_ECHO NDR_DCERPC NDR_EXCHANGE \ NDR_WINREG NDR_MGMT NDR_PROTECTED_STORAGE NDR_DCOM NDR_OXIDRESOLVER \ NDR_REMACT NDR_WZCSVC NDR_BROWSER NDR_W32TIME NDR_SCERPC NDR_NTSVCS \ NDR_NETLOGON NDR_TRKWKS NDR_KEYSVC NDR_KRB5PAC NDR_XATTR NDR_SCHANNEL \ - NDR_ROT NDR_DRSBLOBS NDR_SVCCTL LIB_SECURITY_NDR + NDR_ROT NDR_DRSBLOBS NDR_SVCCTL NDR_NBT LIB_SECURITY_NDR [SUBSYSTEM::RPC_NDR_ROT] ADD_OBJ_FILES = librpc/gen_ndr/ndr_rot_c.o diff --git a/source4/librpc/idl/idl_types.h b/source4/librpc/idl/idl_types.h index 9463fe0c47..1db778476c 100644 --- a/source4/librpc/idl/idl_types.h +++ b/source4/librpc/idl/idl_types.h @@ -6,6 +6,7 @@ #define STR_NULLTERM LIBNDR_FLAG_STR_NULLTERM #define STR_BYTESIZE LIBNDR_FLAG_STR_BYTESIZE #define STR_FIXLEN32 LIBNDR_FLAG_STR_FIXLEN32 +#define STR_FIXLEN15 LIBNDR_FLAG_STR_FIXLEN15 #define STR_CONFORMANT LIBNDR_FLAG_STR_CONFORMANT #define STR_CHARLEN LIBNDR_FLAG_STR_CHARLEN #define STR_UTF8 LIBNDR_FLAG_STR_UTF8 @@ -36,6 +37,11 @@ */ #define string32 [flag(STR_FIXLEN32)] string +/* + fixed length 16 character ascii string +*/ +#define astring15 [flag(STR_ASCII|STR_FIXLEN15)] string + /* an ascii string prefixed with [size] [offset] [length], all 32 bits null terminated diff --git a/source4/librpc/idl/nbt.idl b/source4/librpc/idl/nbt.idl new file mode 100644 index 0000000000..909ff502e8 --- /dev/null +++ b/source4/librpc/idl/nbt.idl @@ -0,0 +1,166 @@ +#include "idl_types.h" + +/* + IDL structures for NBT operations + + NBT is not traditionally encoded using IDL/NDR. This is a bit of an + experiment, and I may well switch us back to a more traditional + encoding if it doesn't work out +*/ + +interface nbt +{ + const int NBT_NAME_SERVICE_PORT = 137; + const int NBT_DGRAM_SERVICE_PORT = 138; + + typedef [bitmap16bit] bitmap { + NBT_RCODE = 0x000F, + NBT_FLAG_BROADCAST = 0x0010, + NBT_FLAG_RECURSION_AVAIL = 0x0080, + NBT_FLAG_RECURSION_DESIRED = 0x0100, + NBT_FLAG_TRUNCATION = 0x0200, + NBT_FLAG_AUTHORITIVE = 0x0400, + NBT_OPCODE = 0x7800, + NBT_FLAG_REPLY = 0x8000 + } nbt_operation; + + /* the opcodes are in the operation field, masked with + NBT_OPCODE */ + const int NBT_OPCODE_QUERY = (0<<11); + const int NBT_OPCODE_REGISTER = (5<<11); + const int NBT_OPCODE_RELEASE = (6<<11); + const int NBT_OPCODE_WACK = (7<<11); + const int NBT_OPCODE_REFRESH = (8<<11); + + /* rcode values */ + typedef enum { + NBT_RCODE_FMT = 0x1, + NBT_RCODE_SVR = 0x2, + NBT_RCODE_NAM = 0x3, + NBT_RCODE_IMP = 0x4, + NBT_RCODE_RFS = 0x5, + NBT_RCODE_ACT = 0x6, + NBT_RCODE_CFT = 0x7 + } nbt_rcode; + + /* we support any 8bit name type, but by defining the common + ones here we get better debug displays */ + typedef [enum8bit] enum { + NBT_NAME_CLIENT = 0x00, + NBT_NAME_MS = 0x01, + NBT_NAME_USER = 0x03, + NBT_NAME_SERVER = 0x20, + NBT_NAME_PDC = 0x1B, + NBT_NAME_LOGON = 0x1C, + NBT_NAME_MASTER = 0x1D, + NBT_NAME_BROWSER = 0x1E + } nbt_name_type; + + /* the ndr parser for nbt_name is separately defined in + nbtname.c */ + typedef [nopull,nopush] struct { + string name; + string scope; + nbt_name_type type; + } nbt_name; + + typedef [enum16bit] enum { + NBT_QCLASS_IP = 0x01 + } nbt_qclass; + + typedef [enum16bit] enum { + NBT_QTYPE_ADDRESS = 0x0001, + NBT_QTYPE_NAMESERVICE = 0x0002, + NBT_QTYPE_NULL = 0x000A, + NBT_QTYPE_NETBIOS = 0x0020, + NBT_QTYPE_STATUS = 0x0021 + } nbt_qtype; + + typedef struct { + nbt_name name; + nbt_qtype question_type; + nbt_qclass question_class; + } nbt_name_question; + + typedef [bitmap16bit] bitmap { + NBT_NM_PERMANENT = 0x0200, + NBT_NM_ACTIVE = 0x0400, + NBT_NM_CONFLICT = 0x0800, + NBT_NM_DEREGISTER = 0x1000, + NBT_NM_OWNER_TYPE = 0x6000, + NBT_NM_GROUP = 0x8000 + } nb_flags; + + typedef struct { + nb_flags nb_flags; + uint32 ipaddr; + } nbt_rdata_netbios; + + + typedef struct { + uint8 unit_id[6]; + uint8 jumpers; + uint8 test_result; + uint16 version_number; + uint16 period_of_statistics; + uint16 number_of_crcs; + uint16 number_alignment_errors; + uint16 number_of_collisions; + uint16 number_send_aborts; + uint32 number_good_sends; + uint32 number_good_receives; + uint16 number_retransmits; + uint16 number_no_resource_conditions; + uint16 number_free_command_blocks; + uint16 total_number_command_blocks; + uint16 max_total_number_command_blocks; + uint16 number_pending_sessions; + uint16 max_number_pending_sessions; + uint16 max_total_sessions_possible; + uint16 session_data_packet_size; + } nbt_statistics; + + typedef struct { + astring15 name; + nbt_name_type type; + nb_flags nb_flags; + } nbt_status_name; + + typedef struct { + uint8 num_names; + nbt_status_name names[num_names]; + nbt_statistics statistics; + } nbt_rdata_status; + + typedef struct { + nbt_operation operation; + } nbt_rdata_wack; + + typedef [nodiscriminant] union { + [case(NBT_QTYPE_NETBIOS)] nbt_rdata_netbios netbios; + [case(NBT_QTYPE_STATUS)] nbt_rdata_status status; + [case(NBT_QTYPE_NULL)] nbt_rdata_wack wack; + } nbt_rdata; + + typedef [flag(LIBNDR_PRINT_ARRAY_HEX)] struct { + nbt_name name; + nbt_qtype rr_type; + nbt_qclass rr_class; + uint32 ttl; + [subcontext(2),switch_is(rr_type)] nbt_rdata rdata; + } nbt_res_rec; + + typedef [flag(NDR_NOALIGN|NDR_BIG_ENDIAN|NDR_PAHEX),public] struct { + uint16 name_trn_id; + nbt_operation operation; + uint16 qdcount; + uint16 ancount; + uint16 nscount; + uint16 arcount; + nbt_name_question questions[qdcount]; + nbt_res_rec answers[ancount]; + nbt_res_rec nsrecs[nscount]; + nbt_res_rec additional[arcount]; + [flag(NDR_REMAINING)] DATA_BLOB padding; + } nbt_name_packet; +} diff --git a/source4/librpc/ndr/libndr.h b/source4/librpc/ndr/libndr.h index 288e753cca..b5a5573448 100644 --- a/source4/librpc/ndr/libndr.h +++ b/source4/librpc/ndr/libndr.h @@ -102,7 +102,8 @@ struct ndr_print { #define LIBNDR_FLAG_STR_CONFORMANT (1<<10) #define LIBNDR_FLAG_STR_CHARLEN (1<<11) #define LIBNDR_FLAG_STR_UTF8 (1<<12) -#define LIBNDR_STRING_FLAGS (0x1FFC) +#define LIBNDR_FLAG_STR_FIXLEN15 (1<<13) +#define LIBNDR_STRING_FLAGS (0x3FFC) #define LIBNDR_FLAG_REF_ALLOC (1<<20) diff --git a/source4/librpc/ndr/ndr.c b/source4/librpc/ndr/ndr.c index 7cc832c68e..8a25e27cc1 100644 --- a/source4/librpc/ndr/ndr.c +++ b/source4/librpc/ndr/ndr.c @@ -883,3 +883,24 @@ size_t ndr_size_struct(const void *p, int flags, ndr_push_flags_fn_t push) talloc_free(ndr); return ret; } + +/* + generic ndr_size_*() handler for unions +*/ +size_t ndr_size_union(const void *p, int flags, uint32_t level, ndr_push_union_fn_t push) +{ + struct ndr_push *ndr; + NTSTATUS status; + size_t ret; + + ndr = ndr_push_init_ctx(NULL); + if (!ndr) return 0; + ndr->flags |= flags; + status = push(ndr, NDR_SCALARS|NDR_BUFFERS, level, discard_const(p)); + if (!NT_STATUS_IS_OK(status)) { + return 0; + } + ret = ndr->offset; + talloc_free(ndr); + return ret; +} diff --git a/source4/librpc/ndr/ndr_basic.c b/source4/librpc/ndr/ndr_basic.c index 29a3009af6..6476f58764 100644 --- a/source4/librpc/ndr/ndr_basic.c +++ b/source4/librpc/ndr/ndr_basic.c @@ -718,8 +718,9 @@ NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s) *s = as; break; + case LIBNDR_FLAG_STR_FIXLEN15: case LIBNDR_FLAG_STR_FIXLEN32: - len1 = 32; + len1 = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15; NDR_PULL_NEED_BYTES(ndr, len1*byte_mul); ret = convert_string_talloc(ndr, chset, CH_UNIX, ndr->data+ndr->offset, @@ -733,7 +734,6 @@ NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s) *s = as; break; - default: return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n", ndr->flags & LIBNDR_STRING_FLAGS); @@ -748,7 +748,7 @@ NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s) */ NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s) { - ssize_t s_len, c_len; + ssize_t s_len, c_len, d_len; int ret; int chset = CH_UTF16; unsigned flags = ndr->flags; @@ -882,16 +882,18 @@ NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s) ndr->offset += c_len*byte_mul; break; + case LIBNDR_FLAG_STR_FIXLEN15: case LIBNDR_FLAG_STR_FIXLEN32: - NDR_PUSH_NEED_BYTES(ndr, byte_mul*32); + d_len = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15; + NDR_PUSH_NEED_BYTES(ndr, byte_mul*d_len); ret = convert_string(CH_UNIX, chset, s, s_len + 1, - ndr->data+ndr->offset, byte_mul*32); + ndr->data+ndr->offset, byte_mul*d_len); if (ret == -1) { return ndr_push_error(ndr, NDR_ERR_CHARCNV, "Bad character conversion"); } - ndr->offset += byte_mul*32; + ndr->offset += byte_mul*d_len; break; default: @@ -915,6 +917,9 @@ size_t ndr_string_array_size(struct ndr_push *ndr, const char *s) if (flags & LIBNDR_FLAG_STR_FIXLEN32) { return 32; } + if (flags & LIBNDR_FLAG_STR_FIXLEN15) { + return 15; + } c_len = s?strlen_m(s):0; @@ -1029,11 +1034,18 @@ void ndr_print_enum(struct ndr_print *ndr, const char *name, const char *type, void ndr_print_bitmap_flag(struct ndr_print *ndr, size_t size, const char *flag_name, uint_t flag, uint_t value) { - /* size can be later used to print something like: - * ...1.... .........: FLAG1_NAME - * .....0.. .........: FLAG2_NAME - */ - ndr->print(ndr, "%s: %-25s", (flag & value)?"1":"0", flag_name); + /* 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 { + ndr->print(ndr, "0x%02x: %-25s (%d)", value, flag_name, value); + } } void ndr_print_uint8(struct ndr_print *ndr, const char *name, uint8_t v) -- cgit