Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Manually parsed structures found in DNSP
5 :
6 : Copyright (C) Andrew Tridgell 2010
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "librpc/gen_ndr/ndr_dnsp.h"
24 :
25 : /*
26 : print a dnsp_name
27 : */
28 26 : _PUBLIC_ void ndr_print_dnsp_name(struct ndr_print *ndr, const char *name,
29 : const char *dns_name)
30 : {
31 26 : ndr->print(ndr, "%-25s: %s", name, dns_name);
32 26 : }
33 :
34 : /*
35 : pull a dnsp_name
36 : */
37 124998 : _PUBLIC_ enum ndr_err_code ndr_pull_dnsp_name(struct ndr_pull *ndr, int ndr_flags, const char **name)
38 : {
39 : uint8_t len, count, termination;
40 : int i;
41 : uint32_t total_len, raw_offset;
42 : char *ret;
43 :
44 124998 : NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &len));
45 124998 : NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &count));
46 :
47 124998 : raw_offset = ndr->offset;
48 :
49 124998 : ret = talloc_strdup(ndr->current_mem_ctx, "");
50 124998 : if (!ret) {
51 0 : return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name");
52 : }
53 124998 : total_len = 1;
54 :
55 1341882 : for (i=0; i<count; i++) {
56 : uint8_t sublen, newlen;
57 549780 : NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &sublen));
58 549780 : newlen = total_len + sublen;
59 549780 : if (newlen < total_len) {
60 0 : return ndr_pull_error(ndr, NDR_ERR_RANGE,
61 : "Failed to pull dnsp_name");
62 : }
63 549780 : if (i != count-1) {
64 425241 : if (newlen == UINT8_MAX) {
65 0 : return ndr_pull_error(
66 : ndr, NDR_ERR_RANGE,
67 : "Failed to pull dnsp_name");
68 : }
69 425241 : newlen++; /* for the '.' */
70 : }
71 549780 : ret = talloc_realloc(ndr->current_mem_ctx, ret, char, newlen);
72 549780 : if (!ret) {
73 0 : return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name");
74 : }
75 549780 : NDR_CHECK(ndr_pull_bytes(ndr, (uint8_t *)&ret[total_len-1], sublen));
76 549780 : if (i != count-1) {
77 425241 : ret[newlen-2] = '.';
78 : }
79 549780 : ret[newlen-1] = 0;
80 549780 : total_len = newlen;
81 : }
82 124998 : NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &termination));
83 124998 : if (termination != 0) {
84 0 : return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name - not NUL terminated");
85 : }
86 124998 : if (ndr->offset > raw_offset + len) {
87 0 : return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name - overrun by %u bytes",
88 : ndr->offset - (raw_offset + len));
89 : }
90 : /* there could be additional pad bytes */
91 248275 : while (ndr->offset < raw_offset + len) {
92 : uint8_t pad;
93 0 : NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &pad));
94 : }
95 124998 : (*name) = ret;
96 124998 : return NDR_ERR_SUCCESS;
97 : }
98 :
99 20982 : enum ndr_err_code ndr_push_dnsp_name(struct ndr_push *ndr, int ndr_flags, const char *name)
100 : {
101 : int count, total_len, i;
102 :
103 : /* count the dots */
104 586654 : for (count=i=0; name[i]; i++) {
105 565672 : if (name[i] == '.') count++;
106 : }
107 20982 : total_len = strlen(name) + 1;
108 :
109 : /*
110 : * cope with names ending in '.'
111 : */
112 20982 : if (name[0] == '\0') {
113 : /*
114 : * Don't access name[-1] for the "" input, which has
115 : * the same meaning as a lone '.'.
116 : *
117 : * This allows a round-trip of a dnsRecord from
118 : * Windows of a MX record of '.'
119 : */
120 20944 : } else if (name[strlen(name)-1] != '.') {
121 20918 : total_len++;
122 20918 : count++;
123 : }
124 20982 : if (total_len > 255 || count > 255) {
125 0 : return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
126 : "dns_name of length %d larger than 255", total_len);
127 : }
128 20982 : NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, (uint8_t)total_len));
129 20982 : NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, (uint8_t)count));
130 107240 : for (i=0; i<count; i++) {
131 86258 : const char *p = strchr(name, '.');
132 86258 : size_t sublen = p?(p-name):strlen(name);
133 86258 : NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, (uint8_t)sublen));
134 86258 : NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)name, sublen));
135 86258 : name += sublen + 1;
136 : }
137 20982 : NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, 0));
138 :
139 20982 : return NDR_ERR_SUCCESS;
140 : }
141 :
142 : /*
143 : print a dnsp_string
144 : */
145 0 : _PUBLIC_ void ndr_print_dnsp_string(struct ndr_print *ndr, const char *name,
146 : const char *dns_string)
147 : {
148 0 : ndr->print(ndr, "%-25s: %s", name, dns_string);
149 0 : }
150 :
151 : /*
152 : pull a dnsp_string
153 : */
154 10828 : _PUBLIC_ enum ndr_err_code ndr_pull_dnsp_string(struct ndr_pull *ndr, int ndr_flags, const char **string)
155 : {
156 : uint8_t len;
157 : char *ret;
158 :
159 10828 : NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &len));
160 :
161 10828 : ret = talloc_zero_array(ndr->current_mem_ctx, char, len + 1);
162 10828 : if (!ret) {
163 0 : return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_string");
164 : }
165 10828 : NDR_CHECK(ndr_pull_bytes(ndr, (uint8_t *)ret, len));
166 :
167 10828 : (*string) = ret;
168 10828 : NDR_PULL_ALIGN(ndr, 1);
169 10828 : return NDR_ERR_SUCCESS;
170 : }
171 :
172 8590 : enum ndr_err_code ndr_push_dnsp_string(struct ndr_push *ndr, int ndr_flags, const char *string)
173 : {
174 : int total_len;
175 8590 : total_len = strlen(string);
176 8590 : if (total_len > 255) {
177 0 : return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
178 : "dns_name of length %d larger than 255", total_len);
179 : }
180 8590 : NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, (uint8_t)total_len));
181 8590 : NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)string, total_len));
182 :
183 8590 : return NDR_ERR_SUCCESS;
184 : }
185 :
186 : /*
187 : * print a dnsp_string_list
188 : */
189 0 : _PUBLIC_ void ndr_print_dnsp_string_list(struct ndr_print *ndr, const char *name,
190 : const struct dnsp_string_list *list)
191 : {
192 : uint32_t i;
193 :
194 0 : ndr->no_newline = true;
195 0 : for (i=0; i<ndr->depth; i++) {
196 0 : ndr->print(ndr, " ");
197 : }
198 0 : ndr->print(ndr, "%-25s:", name);
199 0 : for (i=0; i<list->count; i++) {
200 0 : ndr->print(ndr, " \"%s\"", list->str[i]);
201 : }
202 0 : ndr->print(ndr, "\n");
203 0 : ndr->no_newline = false;
204 0 : }
205 :
206 : /*
207 : * pull a dnsp_string_list
208 : */
209 9194 : _PUBLIC_ enum ndr_err_code ndr_pull_dnsp_string_list(struct ndr_pull *ndr, int ndr_flags, struct dnsp_string_list *list)
210 : {
211 9194 : list->count = 0;
212 9194 : list->str = talloc_array(ndr->current_mem_ctx, const char *,
213 : list->count);
214 9194 : if (! list->str) {
215 0 : return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_string_list");
216 : }
217 :
218 24817 : while (ndr->offset < ndr->data_size) {
219 10828 : list->str = talloc_realloc(ndr->current_mem_ctx, list->str,
220 : const char *, list->count+1);
221 10828 : if (! list->str) {
222 0 : return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_string_list");
223 : }
224 10828 : NDR_CHECK(ndr_pull_dnsp_string(ndr, ndr_flags, &list->str[list->count]));
225 10828 : list->count++;
226 : }
227 :
228 9194 : return NDR_ERR_SUCCESS;
229 : }
230 :
231 7275 : enum ndr_err_code ndr_push_dnsp_string_list(struct ndr_push *ndr, int ndr_flags, const struct dnsp_string_list *list)
232 : {
233 : uint8_t i;
234 :
235 15865 : for (i=0; i<list->count; i++) {
236 8590 : NDR_CHECK(ndr_push_dnsp_string(ndr, ndr_flags, list->str[i]));
237 : }
238 7275 : return NDR_ERR_SUCCESS;
239 : }
240 :
241 1051 : enum ndr_err_code ndr_dnsp_string_list_copy(TALLOC_CTX *mem_ctx,
242 : const struct dnsp_string_list *src,
243 : struct dnsp_string_list *dst)
244 : {
245 : size_t i;
246 :
247 1051 : dst->count = 0;
248 1051 : dst->str = talloc_zero_array(mem_ctx, const char *, src->count);
249 1051 : if (dst->str == NULL) {
250 0 : return NDR_ERR_ALLOC;
251 : }
252 :
253 2261 : for (i = 0; i < src->count; i++) {
254 1210 : dst->str[i] = talloc_strdup(dst->str, src->str[i]);
255 1210 : if (dst->str[i] == NULL) {
256 0 : TALLOC_FREE(dst->str);
257 0 : return NDR_ERR_ALLOC;
258 : }
259 : }
260 :
261 1051 : dst->count = src->count;
262 1051 : return NDR_ERR_SUCCESS;
263 : }
|