s4: torture: Tweak the compound padding streamfile test to send 3 reads instead of...
[Samba.git] / librpc / ndr / ndr_dns_utils.c
blob325d9c68bea5c448b8f79b4228fe908465d6ad0d
1 #include "includes.h"
2 #include "../librpc/ndr/libndr.h"
3 #include "ndr_dns_utils.h"
6 /**
7 push a dns/nbt string list to the wire
8 */
9 enum ndr_err_code ndr_push_dns_string_list(struct ndr_push *ndr,
10 struct ndr_token_list *string_list,
11 int ndr_flags,
12 const char *s,
13 bool is_nbt)
15 const char *start = s;
16 bool use_compression;
17 size_t max_length;
18 if (is_nbt) {
19 use_compression = true;
21 * Max length is longer in NBT/Wins, because Windows counts
22 * the semi-decompressed size of the netbios name (16 bytes)
23 * rather than the wire size of 32, which is what you'd expect
24 * if it followed RFC1002 (it uses the short form in
25 * [MS-WINSRA]). In other words the maximum size of the
26 * "scope" is 237, not 221.
28 * We make the size limit slightly larger than 255 + 16,
29 * because the 237 scope limit is already enforced in the
30 * winsserver code with a specific return value; bailing out
31 * here would muck with that.
33 max_length = 274;
34 } else {
35 use_compression = !(ndr->flags & LIBNDR_FLAG_NO_COMPRESSION);
36 max_length = 255;
39 if (!(ndr_flags & NDR_SCALARS)) {
40 return NDR_ERR_SUCCESS;
43 while (s && *s) {
44 enum ndr_err_code ndr_err;
45 char *compname;
46 size_t complen;
47 uint32_t offset;
49 if (use_compression) {
50 /* see if we have pushed the remaining string already,
51 * if so we use a label pointer to this string
53 ndr_err = ndr_token_retrieve_cmp_fn(string_list, s,
54 &offset,
55 (comparison_fn_t)strcmp,
56 false);
57 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
58 uint8_t b[2];
60 if (offset > 0x3FFF) {
61 return ndr_push_error(ndr, NDR_ERR_STRING,
62 "offset for dns string " \
63 "label pointer " \
64 "%u[%08X] > 0x00003FFF",
65 offset, offset);
68 b[0] = 0xC0 | (offset>>8);
69 b[1] = (offset & 0xFF);
71 return ndr_push_bytes(ndr, b, 2);
75 complen = strcspn(s, ".");
77 /* the length must fit into 6 bits (i.e. <= 63) */
78 if (complen > 0x3F) {
79 return ndr_push_error(ndr, NDR_ERR_STRING,
80 "component length %u[%08X] > " \
81 "0x0000003F",
82 (unsigned)complen,
83 (unsigned)complen);
86 if (complen == 0 && s[complen] == '.') {
87 return ndr_push_error(ndr, NDR_ERR_STRING,
88 "component length is 0 "
89 "(consecutive dots)");
92 if (is_nbt && s[complen] == '.' && s[complen + 1] == '\0') {
93 /* nbt names are sometimes usernames, and we need to
94 * keep a trailing dot to ensure it is byte-identical,
95 * (not just semantically identical given DNS
96 * semantics). */
97 complen++;
100 compname = talloc_asprintf(ndr, "%c%*.*s",
101 (unsigned char)complen,
102 (unsigned char)complen,
103 (unsigned char)complen, s);
104 NDR_ERR_HAVE_NO_MEMORY(compname);
106 /* remember the current component + the rest of the string
107 * so it can be reused later
109 if (use_compression) {
110 NDR_CHECK(ndr_token_store(ndr, string_list, s,
111 ndr->offset));
114 /* push just this component into the blob */
115 NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)compname,
116 complen+1));
117 talloc_free(compname);
119 s += complen;
120 if (*s == '.') {
121 s++;
123 if (s - start > max_length) {
124 return ndr_push_error(ndr, NDR_ERR_STRING,
125 "name > %zu character long",
126 max_length);
130 /* if we reach the end of the string and have pushed the last component
131 * without using a label pointer, we need to terminate the string
133 return ndr_push_bytes(ndr, (const uint8_t *)"", 1);