summaryrefslogtreecommitdiff
path: root/librpc
diff options
context:
space:
mode:
authorKai Blin <kai@samba.org>2010-09-29 17:24:53 -0700
committerKai Blin <kai@samba.org>2010-10-23 10:17:05 +0000
commita7b833ec7e19bc3251ade69af101631013d60419 (patch)
tree6d0c44eb1e889f4168667107efd16f4602fafeda /librpc
parent719a6bbfede5b124c96f7c84d27e68ac285b073a (diff)
downloadsamba-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.idl43
-rw-r--r--librpc/ndr/ndr_dns.c98
-rw-r--r--librpc/ndr/ndr_dns.h2
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);