/src/samba/librpc/ndr/ndr_dnsp.c
Line | Count | Source |
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 | | _PUBLIC_ void ndr_print_dnsp_name(struct ndr_print *ndr, const char *name, |
29 | | const char *dns_name) |
30 | 62 | { |
31 | 62 | ndr->print(ndr, "%-25s: %s", name, dns_name); |
32 | 62 | } |
33 | | |
34 | | /* |
35 | | pull a dnsp_name |
36 | | */ |
37 | | _PUBLIC_ enum ndr_err_code ndr_pull_dnsp_name(struct ndr_pull *ndr, ndr_flags_type ndr_flags, const char **name) |
38 | 188 | { |
39 | 188 | uint8_t len, count, termination; |
40 | 188 | int i; |
41 | 188 | uint32_t total_len, raw_offset; |
42 | 188 | char *ret; |
43 | | |
44 | 188 | NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &len)); |
45 | 179 | NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &count)); |
46 | | |
47 | 178 | raw_offset = ndr->offset; |
48 | | |
49 | 178 | ret = talloc_strdup(ndr->current_mem_ctx, ""); |
50 | 178 | if (!ret) { |
51 | 0 | return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name"); |
52 | 0 | } |
53 | 178 | total_len = 1; |
54 | | |
55 | 3.18k | for (i=0; i<count; i++) { |
56 | 3.06k | uint8_t sublen, newlen; |
57 | 3.06k | NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &sublen)); |
58 | 3.04k | newlen = total_len + sublen; |
59 | 3.04k | if (newlen < total_len) { |
60 | 10 | return ndr_pull_error(ndr, NDR_ERR_RANGE, |
61 | 10 | "Failed to pull dnsp_name"); |
62 | 10 | } |
63 | 3.03k | if (i != count-1) { |
64 | 2.96k | if (newlen == UINT8_MAX) { |
65 | 2 | return ndr_pull_error( |
66 | 2 | ndr, NDR_ERR_RANGE, |
67 | 2 | "Failed to pull dnsp_name"); |
68 | 2 | } |
69 | 2.96k | newlen++; /* for the '.' */ |
70 | 2.96k | } |
71 | 3.03k | ret = talloc_realloc(ndr->current_mem_ctx, ret, char, newlen); |
72 | 3.03k | if (!ret) { |
73 | 0 | return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name"); |
74 | 0 | } |
75 | 3.03k | NDR_CHECK(ndr_pull_bytes(ndr, (uint8_t *)&ret[total_len-1], sublen)); |
76 | 3.01k | if (i != count-1) { |
77 | 2.94k | ret[newlen-2] = '.'; |
78 | 2.94k | } |
79 | 3.01k | ret[newlen-1] = 0; |
80 | 3.01k | total_len = newlen; |
81 | 3.01k | } |
82 | 121 | NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &termination)); |
83 | 117 | if (termination != 0) { |
84 | 14 | return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name - not NUL terminated"); |
85 | 14 | } |
86 | 103 | if (ndr->offset > raw_offset + len) { |
87 | 15 | return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name - overrun by %"PRIu32" bytes", |
88 | 15 | ndr->offset - (raw_offset + len)); |
89 | 15 | } |
90 | | /* there could be additional pad bytes */ |
91 | 807 | while (ndr->offset < raw_offset + len) { |
92 | 737 | uint8_t pad; |
93 | 737 | NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &pad)); |
94 | 737 | } |
95 | 70 | (*name) = ret; |
96 | 70 | return NDR_ERR_SUCCESS; |
97 | 88 | } |
98 | | |
99 | | enum ndr_err_code ndr_push_dnsp_name(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char *name) |
100 | 77 | { |
101 | 77 | int count, total_len, i; |
102 | | |
103 | | /* count the dots */ |
104 | 2.85k | for (count=i=0; name[i]; i++) { |
105 | 2.77k | if (name[i] == '.') count++; |
106 | 2.77k | } |
107 | 77 | total_len = strlen(name) + 1; |
108 | | |
109 | | /* |
110 | | * cope with names ending in '.' |
111 | | */ |
112 | 77 | 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 | 59 | } else if (name[strlen(name)-1] != '.') { |
121 | 28 | total_len++; |
122 | 28 | count++; |
123 | 28 | } |
124 | 77 | if (total_len > 255 || count > 255) { |
125 | 0 | return ndr_push_error(ndr, NDR_ERR_BUFSIZE, |
126 | 0 | "dns_name of length %d larger than 255", total_len); |
127 | 0 | } |
128 | 77 | NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, (uint8_t)total_len)); |
129 | 77 | NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, (uint8_t)count)); |
130 | 2.44k | for (i=0; i<count; i++) { |
131 | 2.36k | const char *p = strchr(name, '.'); |
132 | 2.36k | size_t sublen = p?(p-name):strlen(name); |
133 | 2.36k | NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, (uint8_t)sublen)); |
134 | 2.36k | NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)name, sublen)); |
135 | 2.36k | name += sublen + 1; |
136 | 2.36k | } |
137 | 77 | NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, 0)); |
138 | | |
139 | 77 | return NDR_ERR_SUCCESS; |
140 | 77 | } |
141 | | |
142 | | /* |
143 | | print a dnsp_string |
144 | | */ |
145 | | _PUBLIC_ void ndr_print_dnsp_string(struct ndr_print *ndr, const char *name, |
146 | | const char *dns_string) |
147 | 1.21k | { |
148 | 1.21k | ndr->print(ndr, "%-25s: %s", name, dns_string); |
149 | 1.21k | } |
150 | | |
151 | | /* |
152 | | pull a dnsp_string |
153 | | */ |
154 | | _PUBLIC_ enum ndr_err_code ndr_pull_dnsp_string(struct ndr_pull *ndr, ndr_flags_type ndr_flags, const char **string) |
155 | 6.39M | { |
156 | 6.39M | uint8_t len; |
157 | 6.39M | char *ret; |
158 | | |
159 | 6.39M | NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &len)); |
160 | | |
161 | 6.39M | ret = talloc_zero_array(ndr->current_mem_ctx, char, len + 1); |
162 | 6.39M | if (!ret) { |
163 | 0 | return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_string"); |
164 | 0 | } |
165 | 6.39M | NDR_CHECK(ndr_pull_bytes(ndr, (uint8_t *)ret, len)); |
166 | | |
167 | 6.39M | (*string) = ret; |
168 | 6.39M | NDR_PULL_ALIGN(ndr, 1); |
169 | 6.39M | return NDR_ERR_SUCCESS; |
170 | 6.39M | } |
171 | | |
172 | | enum ndr_err_code ndr_push_dnsp_string(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char *string) |
173 | 12.3k | { |
174 | 12.3k | size_t total_len; |
175 | 12.3k | total_len = strlen(string); |
176 | 12.3k | if (total_len > 255) { |
177 | 0 | return ndr_push_error(ndr, NDR_ERR_BUFSIZE, |
178 | 0 | "dns_name of length %zu larger than 255", |
179 | 0 | total_len); |
180 | 0 | } |
181 | 12.3k | NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, (uint8_t)total_len)); |
182 | 12.3k | NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)string, total_len)); |
183 | | |
184 | 12.3k | return NDR_ERR_SUCCESS; |
185 | 12.3k | } |
186 | | |
187 | | /* |
188 | | * print a dnsp_string_list |
189 | | */ |
190 | | _PUBLIC_ void ndr_print_dnsp_string_list(struct ndr_print *ndr, const char *name, |
191 | | const struct dnsp_string_list *list) |
192 | 858 | { |
193 | 858 | uint32_t i; |
194 | | |
195 | 858 | ndr->no_newline = true; |
196 | 858 | ndr->print(ndr, "%*.s%-25s:", 4 * ndr->depth, "", name); |
197 | 12.1k | for (i=0; i<list->count; i++) { |
198 | 11.2k | ndr->print(ndr, " \"%s\"", list->str[i]); |
199 | 11.2k | } |
200 | 858 | ndr->print(ndr, "\n"); |
201 | 858 | ndr->no_newline = false; |
202 | 858 | } |
203 | | |
204 | | /* |
205 | | * pull a dnsp_string_list |
206 | | */ |
207 | | _PUBLIC_ enum ndr_err_code ndr_pull_dnsp_string_list(struct ndr_pull *ndr, ndr_flags_type ndr_flags, struct dnsp_string_list *list) |
208 | 1.46k | { |
209 | 1.46k | list->count = 0; |
210 | 1.46k | list->str = talloc_array(ndr->current_mem_ctx, const char *, |
211 | 1.46k | list->count); |
212 | 1.46k | if (! list->str) { |
213 | 0 | return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_string_list"); |
214 | 0 | } |
215 | | |
216 | 6.39M | while (ndr->offset < ndr->data_size) { |
217 | 6.39M | list->str = talloc_realloc(ndr->current_mem_ctx, list->str, |
218 | 6.39M | const char *, list->count+1); |
219 | 6.39M | if (! list->str) { |
220 | 0 | return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_string_list"); |
221 | 0 | } |
222 | 6.39M | NDR_CHECK(ndr_pull_dnsp_string(ndr, ndr_flags, &list->str[list->count])); |
223 | 6.39M | list->count++; |
224 | 6.39M | } |
225 | | |
226 | 1.34k | return NDR_ERR_SUCCESS; |
227 | 1.46k | } |
228 | | |
229 | | enum ndr_err_code ndr_push_dnsp_string_list(struct ndr_push *ndr, ndr_flags_type ndr_flags, const struct dnsp_string_list *list) |
230 | 673 | { |
231 | 673 | uint8_t i; |
232 | | |
233 | 12.3k | for (i=0; i<list->count; i++) { |
234 | 11.6k | NDR_CHECK(ndr_push_dnsp_string(ndr, ndr_flags, list->str[i])); |
235 | 11.6k | } |
236 | 673 | return NDR_ERR_SUCCESS; |
237 | 673 | } |
238 | | |
239 | | enum ndr_err_code ndr_dnsp_string_list_copy(TALLOC_CTX *mem_ctx, |
240 | | const struct dnsp_string_list *src, |
241 | | struct dnsp_string_list *dst) |
242 | 0 | { |
243 | 0 | size_t i; |
244 | |
|
245 | 0 | dst->count = 0; |
246 | 0 | dst->str = talloc_zero_array(mem_ctx, const char *, src->count); |
247 | 0 | if (dst->str == NULL) { |
248 | 0 | return NDR_ERR_ALLOC; |
249 | 0 | } |
250 | | |
251 | 0 | for (i = 0; i < src->count; i++) { |
252 | 0 | dst->str[i] = talloc_strdup(dst->str, src->str[i]); |
253 | 0 | if (dst->str[i] == NULL) { |
254 | 0 | TALLOC_FREE(dst->str); |
255 | 0 | return NDR_ERR_ALLOC; |
256 | 0 | } |
257 | 0 | } |
258 | | |
259 | 0 | dst->count = src->count; |
260 | 0 | return NDR_ERR_SUCCESS; |
261 | 0 | } |