diff options
author | Kai Blin <kai@samba.org> | 2010-09-29 17:24:53 -0700 |
---|---|---|
committer | Kai Blin <kai@samba.org> | 2010-10-23 10:17:05 +0000 |
commit | a7b833ec7e19bc3251ade69af101631013d60419 (patch) | |
tree | 6d0c44eb1e889f4168667107efd16f4602fafeda /librpc | |
parent | 719a6bbfede5b124c96f7c84d27e68ac285b073a (diff) | |
download | samba-a7b833ec7e19bc3251ade69af101631013d60419.tar.gz samba-a7b833ec7e19bc3251ade69af101631013d60419.tar.bz2 samba-a7b833ec7e19bc3251ade69af101631013d60419.zip |
s4 dns: Reply to a name request with an A record.
The first real answer to a DNS request. Still uses hardcoded reply.
Diffstat (limited to 'librpc')
-rw-r--r-- | librpc/idl/dns.idl | 43 | ||||
-rw-r--r-- | librpc/ndr/ndr_dns.c | 98 | ||||
-rw-r--r-- | librpc/ndr/ndr_dns.h | 2 |
3 files changed, 131 insertions, 12 deletions
diff --git a/librpc/idl/dns.idl b/librpc/idl/dns.idl index 16dcf52929..b4075365ab 100644 --- a/librpc/idl/dns.idl +++ b/librpc/idl/dns.idl @@ -119,18 +119,48 @@ interface dns uint8 data[length]; } dns_rdata_data; - typedef [nodiscriminant,public] union { - [case(DNS_QTYPE_A),subcontext(2)] ipv4address ipv4_address; - [case(DNS_QTYPE_AAAA),subcontext(2)] ipv6address ipv6_address; - [default] dns_rdata_data data; + typedef struct { + dns_string mname; + dns_string rname; + uint32 serial; + uint32 refresh; + uint32 retry; + uint32 expire; + uint32 minimum; + } dns_soa_record; + + typedef [public] struct { + uint16 priority; + uint16 weight; + uint16 port; + dns_string target; + } dns_srv_record; + + typedef [public] struct { + uint16 preference; + dns_string exchange; + } dns_mx_record; + + typedef [nodiscriminant,public,flag(NDR_NOALIGN)] union { + [case(DNS_QTYPE_A)] ipv4address ipv4_record; + [case(DNS_QTYPE_NS)] dns_string ns_record; + [case(DNS_QTYPE_CNAME)] dns_string cname_record; + [case(DNS_QTYPE_SOA)] dns_soa_record soa_record; + [case(DNS_QTYPE_PTR)] dns_string ptr_record; + [case(DNS_QTYPE_MX)] dns_mx_record mx_record; + [case(DNS_QTYPE_AAAA)] ipv6address ipv6_record; + [case(DNS_QTYPE_SRV)] dns_srv_record srv_record; + [default]; } dns_rdata; - typedef [flag(LIBNDR_PRINT_ARRAY_HEX),public] struct { - dns_string name; + typedef [flag(LIBNDR_PRINT_ARRAY_HEX|NDR_NOALIGN),nopush,nopull] struct { + dns_string name; dns_qtype rr_type; dns_qclass rr_class; uint32 ttl; + uint16 length; [switch_is(rr_type)] dns_rdata rdata; + DATA_BLOB unexpected; } dns_res_rec; typedef [flag(NDR_NOALIGN|NDR_BIG_ENDIAN|NDR_PAHEX),public] struct { @@ -144,7 +174,6 @@ interface dns dns_res_rec answers[ancount]; dns_res_rec nsrecs[nscount]; dns_res_rec additional[arcount]; - [flag(NDR_REMAINING)] DATA_BLOB padding; } dns_name_packet; /* diff --git a/librpc/ndr/ndr_dns.c b/librpc/ndr/ndr_dns.c index 18dde2bd1a..638220af4e 100644 --- a/librpc/ndr/ndr_dns.c +++ b/librpc/ndr/ndr_dns.c @@ -57,7 +57,7 @@ static enum ndr_err_code ndr_pull_component(struct ndr_pull *ndr, while (loops < 5) { if (*offset >= ndr->data_size) { return ndr_pull_error(ndr, NDR_ERR_STRING, - "BAD DNS NAME component"); + "BAD DNS NAME component, bad offset"); } len = ndr->data[*offset]; if (len == 0) { @@ -70,7 +70,7 @@ static enum ndr_err_code ndr_pull_component(struct ndr_pull *ndr, /* its a label pointer */ if (1 + *offset >= ndr->data_size) { return ndr_pull_error(ndr, NDR_ERR_STRING, - "BAD DNS NAME component"); + "BAD DNS NAME component, bad label offset"); } *max_offset = MAX(*max_offset, *offset + 2); *offset = ((len&0x3F)<<8) | ndr->data[1 + *offset]; @@ -81,11 +81,11 @@ static enum ndr_err_code ndr_pull_component(struct ndr_pull *ndr, if ((len & 0xC0) != 0) { /* its a reserved length field */ return ndr_pull_error(ndr, NDR_ERR_STRING, - "BAD DNS NAME component"); + "BAD DNS NAME component, reserved lenght field: 0x%02x", (len &0xC)); } if (*offset + len + 2 > ndr->data_size) { return ndr_pull_error(ndr, NDR_ERR_STRING, - "BAD DNS NAME component"); + "BAD DNS NAME component, length too long"); } *component = (uint8_t*)talloc_strndup(ndr, (const char *)&ndr->data[1 + *offset], len); NDR_ERR_HAVE_NO_MEMORY(*component); @@ -95,7 +95,7 @@ static enum ndr_err_code ndr_pull_component(struct ndr_pull *ndr, } /* too many pointers */ - return ndr_pull_error(ndr, NDR_ERR_STRING, "BAD DNS NAME component"); + return ndr_pull_error(ndr, NDR_ERR_STRING, "BAD DNS NAME component, too many pointers"); } /** @@ -208,3 +208,91 @@ _PUBLIC_ enum ndr_err_code ndr_push_dns_string(struct ndr_push *ndr, int ndr_fla */ return ndr_push_bytes(ndr, (const uint8_t *)"", 1); } + +_PUBLIC_ enum ndr_err_code ndr_push_dns_res_rec(struct ndr_push *ndr, int ndr_flags, const struct dns_res_rec *r) +{ + { + uint32_t _flags_save_STRUCT = ndr->flags; + uint32_t _saved_offset1, _saved_offset2; + uint16_t length; + ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX|LIBNDR_FLAG_NOALIGN); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_dns_string(ndr, NDR_SCALARS, r->name)); + NDR_CHECK(ndr_push_dns_qtype(ndr, NDR_SCALARS, r->rr_type)); + NDR_CHECK(ndr_push_dns_qclass(ndr, NDR_SCALARS, r->rr_class)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->ttl)); + _saved_offset1 = ndr->offset; + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 0)); + NDR_CHECK(ndr_push_set_switch_value(ndr, &r->rdata, r->rr_type)); + NDR_CHECK(ndr_push_dns_rdata(ndr, NDR_SCALARS, &r->rdata)); + + if (r->unexpected.length > UINT16_MAX) { + return ndr_push_error(ndr, NDR_ERR_LENGTH, + "Unexpected blob lenght is too large"); + } + + NDR_CHECK(ndr_push_bytes(ndr, r->unexpected.data, r->unexpected.length)); + NDR_CHECK(ndr_push_trailer_align(ndr, 4)); + length = ndr->offset - (_saved_offset1 + 2); + _saved_offset2 = ndr->offset; + ndr->offset = _saved_offset1; + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, length)); + ndr->offset = _saved_offset2; + } + if (ndr_flags & NDR_BUFFERS) { + NDR_CHECK(ndr_push_dns_rdata(ndr, NDR_BUFFERS, &r->rdata)); + } + ndr->flags = _flags_save_STRUCT; + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_dns_res_rec(struct ndr_pull *ndr, int ndr_flags, struct dns_res_rec *r) +{ + { + uint32_t _flags_save_STRUCT = ndr->flags; + uint32_t _saved_offset1; + uint32_t pad, length; + + ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX|LIBNDR_FLAG_NOALIGN); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_pull_align(ndr, 4)); + NDR_CHECK(ndr_pull_dns_string(ndr, NDR_SCALARS, &r->name)); + NDR_CHECK(ndr_pull_dns_qtype(ndr, NDR_SCALARS, &r->rr_type)); + NDR_CHECK(ndr_pull_dns_qclass(ndr, NDR_SCALARS, &r->rr_class)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->ttl)); + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->length)); + _saved_offset1 = ndr->offset; + NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->rdata, r->rr_type)); + NDR_CHECK(ndr_pull_dns_rdata(ndr, NDR_SCALARS, &r->rdata)); + length = ndr->offset - _saved_offset1; + if (length > r->length) { + return ndr_pull_error(ndr, NDR_ERR_LENGTH, + "TODO"); + } + + r->unexpected = data_blob_null; + pad = r->length - length; + if (pad > 0) { + NDR_PULL_NEED_BYTES(ndr, pad); + r->unexpected = data_blob_talloc(ndr->current_mem_ctx, + ndr->data + ndr->offset, + pad); + if (r->unexpected.data == NULL) { + return ndr_pull_error(ndr, NDR_ERR_ALLOC, + "Failed to allocate a data blob"); + } + ndr->offset += pad; + } + + + NDR_CHECK(ndr_pull_trailer_align(ndr, 4)); + } + if (ndr_flags & NDR_BUFFERS) { + NDR_CHECK(ndr_pull_dns_rdata(ndr, NDR_BUFFERS, &r->rdata)); + } + ndr->flags = _flags_save_STRUCT; + } + return NDR_ERR_SUCCESS; +} diff --git a/librpc/ndr/ndr_dns.h b/librpc/ndr/ndr_dns.h index d0b6ab36f3..acdb7bb03a 100644 --- a/librpc/ndr/ndr_dns.h +++ b/librpc/ndr/ndr_dns.h @@ -1,3 +1,5 @@ _PUBLIC_ void ndr_print_dns_string(struct ndr_print *ndr, const char *name, const char *s); _PUBLIC_ enum ndr_err_code ndr_pull_dns_string(struct ndr_pull *ndr, int ndr_flags, const char **s); _PUBLIC_ enum ndr_err_code ndr_push_dns_string(struct ndr_push *ndr, int ndr_flags, const char *s); +_PUBLIC_ enum ndr_err_code ndr_push_dns_res_rec(struct ndr_push *ndr, int ndr_flags, const struct dns_res_rec *r); +_PUBLIC_ enum ndr_err_code ndr_pull_dns_res_rec(struct ndr_pull *ndr, int ndr_flags, struct dns_res_rec *r); |