2 #include "../librpc/ndr/libndr.h"
3 #include "ndr_dns_utils.h"
7 push a dns/nbt string list to the wire
9 enum ndr_err_code
ndr_push_dns_string_list(struct ndr_push
*ndr
,
10 struct ndr_token_list
*string_list
,
11 ndr_flags_type ndr_flags
,
15 const char *start
= s
;
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.
35 use_compression
= !(ndr
->flags
& LIBNDR_FLAG_NO_COMPRESSION
);
39 if (!(ndr_flags
& NDR_SCALARS
)) {
40 return NDR_ERR_SUCCESS
;
44 enum ndr_err_code ndr_err
;
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_peek_cmp_fn(string_list
,
58 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
61 if (offset
> 0x3FFF) {
62 return ndr_push_error(ndr
, NDR_ERR_STRING
,
63 "offset for dns string " \
65 "%"PRIu32
"[%08"PRIX32
"] > 0x00003FFF",
69 b
[0] = 0xC0 | (offset
>>8);
70 b
[1] = (offset
& 0xFF);
72 return ndr_push_bytes(ndr
, b
, 2);
76 complen
= strcspn(s
, ".");
78 /* the length must fit into 6 bits (i.e. <= 63) */
80 return ndr_push_error(ndr
, NDR_ERR_STRING
,
81 "component length %zu[%08zX] > " \
87 if (complen
== 0 && s
[complen
] == '.') {
88 return ndr_push_error(ndr
, NDR_ERR_STRING
,
89 "component length is 0 "
90 "(consecutive dots)");
93 if (is_nbt
&& s
[complen
] == '.' && s
[complen
+ 1] == '\0') {
94 /* nbt names are sometimes usernames, and we need to
95 * keep a trailing dot to ensure it is byte-identical,
96 * (not just semantically identical given DNS
101 compname
= talloc_asprintf(ndr
, "%c%*.*s",
102 (unsigned char)complen
,
103 (unsigned char)complen
,
104 (unsigned char)complen
, s
);
105 NDR_ERR_HAVE_NO_MEMORY(compname
);
107 /* remember the current component + the rest of the string
108 * so it can be reused later
110 if (use_compression
) {
111 NDR_CHECK(ndr_token_store(ndr
, string_list
, s
,
115 /* push just this component into the blob */
116 NDR_CHECK(ndr_push_bytes(ndr
, (const uint8_t *)compname
,
118 talloc_free(compname
);
124 if (s
- start
> max_length
) {
125 return ndr_push_error(ndr
, NDR_ERR_STRING
,
126 "name > %zu characters long",
131 /* if we reach the end of the string and have pushed the last component
132 * without using a label pointer, we need to terminate the string
134 return ndr_push_bytes(ndr
, (const uint8_t *)"", 1);