/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 | 186 | { |
39 | 186 | uint8_t len, count, termination; |
40 | 186 | int i; |
41 | 186 | uint32_t total_len, raw_offset; |
42 | 186 | char *ret; |
43 | | |
44 | 186 | NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &len)); |
45 | 178 | NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &count)); |
46 | | |
47 | 176 | raw_offset = ndr->offset; |
48 | | |
49 | 176 | ret = talloc_strdup(ndr->current_mem_ctx, ""); |
50 | 176 | if (!ret) { |
51 | 0 | return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name"); |
52 | 0 | } |
53 | 176 | total_len = 1; |
54 | | |
55 | 3.08k | for (i=0; i<count; i++) { |
56 | 2.96k | uint8_t sublen, newlen; |
57 | 2.96k | NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &sublen)); |
58 | 2.94k | newlen = total_len + sublen; |
59 | 2.94k | if (newlen < total_len) { |
60 | 10 | return ndr_pull_error(ndr, NDR_ERR_RANGE, |
61 | 10 | "Failed to pull dnsp_name"); |
62 | 10 | } |
63 | 2.93k | if (i != count-1) { |
64 | 2.86k | if (newlen == UINT8_MAX) { |
65 | 1 | return ndr_pull_error( |
66 | 1 | ndr, NDR_ERR_RANGE, |
67 | 1 | "Failed to pull dnsp_name"); |
68 | 1 | } |
69 | 2.86k | newlen++; /* for the '.' */ |
70 | 2.86k | } |
71 | 2.93k | ret = talloc_realloc(ndr->current_mem_ctx, ret, char, newlen); |
72 | 2.93k | if (!ret) { |
73 | 0 | return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name"); |
74 | 0 | } |
75 | 2.93k | NDR_CHECK(ndr_pull_bytes(ndr, (uint8_t *)&ret[total_len-1], sublen)); |
76 | 2.91k | if (i != count-1) { |
77 | 2.84k | ret[newlen-2] = '.'; |
78 | 2.84k | } |
79 | 2.91k | ret[newlen-1] = 0; |
80 | 2.91k | total_len = newlen; |
81 | 2.91k | } |
82 | 122 | NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &termination)); |
83 | 118 | if (termination != 0) { |
84 | 14 | return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name - not NUL terminated"); |
85 | 14 | } |
86 | 104 | if (ndr->offset > raw_offset + len) { |
87 | 16 | return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name - overrun by %"PRIu32" bytes", |
88 | 16 | ndr->offset - (raw_offset + len)); |
89 | 16 | } |
90 | | /* there could be additional pad bytes */ |
91 | 928 | while (ndr->offset < raw_offset + len) { |
92 | 858 | uint8_t pad; |
93 | 858 | NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &pad)); |
94 | 858 | } |
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.63k | for (count=i=0; name[i]; i++) { |
105 | 2.55k | if (name[i] == '.') count++; |
106 | 2.55k | } |
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 | 58 | } else if (name[strlen(name)-1] != '.') { |
121 | 29 | total_len++; |
122 | 29 | count++; |
123 | 29 | } |
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.42k | for (i=0; i<count; i++) { |
131 | 2.35k | const char *p = strchr(name, '.'); |
132 | 2.35k | size_t sublen = p?(p-name):strlen(name); |
133 | 2.35k | NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, (uint8_t)sublen)); |
134 | 2.35k | NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)name, sublen)); |
135 | 2.35k | name += sublen + 1; |
136 | 2.35k | } |
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.48k | { |
148 | 1.48k | ndr->print(ndr, "%-25s: %s", name, dns_string); |
149 | 1.48k | } |
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 | 5.92M | { |
156 | 5.92M | uint8_t len; |
157 | 5.92M | char *ret; |
158 | | |
159 | 5.92M | NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &len)); |
160 | | |
161 | 5.92M | ret = talloc_zero_array(ndr->current_mem_ctx, char, len + 1); |
162 | 5.92M | if (!ret) { |
163 | 0 | return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_string"); |
164 | 0 | } |
165 | 5.92M | NDR_CHECK(ndr_pull_bytes(ndr, (uint8_t *)ret, len)); |
166 | | |
167 | 5.92M | (*string) = ret; |
168 | 5.92M | NDR_PULL_ALIGN(ndr, 1); |
169 | 5.92M | return NDR_ERR_SUCCESS; |
170 | 5.92M | } |
171 | | |
172 | | enum ndr_err_code ndr_push_dnsp_string(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char *string) |
173 | 11.6k | { |
174 | 11.6k | size_t total_len; |
175 | 11.6k | total_len = strlen(string); |
176 | 11.6k | 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 | 11.6k | NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, (uint8_t)total_len)); |
182 | 11.6k | NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)string, total_len)); |
183 | | |
184 | 11.6k | return NDR_ERR_SUCCESS; |
185 | 11.6k | } |
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 | 1.16k | { |
193 | 1.16k | uint32_t i; |
194 | | |
195 | 1.16k | ndr->no_newline = true; |
196 | 1.16k | ndr->print(ndr, "%*.s%-25s:", 4 * ndr->depth, "", name); |
197 | 11.1k | for (i=0; i<list->count; i++) { |
198 | 9.98k | ndr->print(ndr, " \"%s\"", list->str[i]); |
199 | 9.98k | } |
200 | 1.16k | ndr->print(ndr, "\n"); |
201 | 1.16k | ndr->no_newline = false; |
202 | 1.16k | } |
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 | 2.29k | { |
209 | 2.29k | list->count = 0; |
210 | 2.29k | list->str = talloc_array(ndr->current_mem_ctx, const char *, |
211 | 2.29k | list->count); |
212 | 2.29k | if (! list->str) { |
213 | 0 | return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_string_list"); |
214 | 0 | } |
215 | | |
216 | 5.92M | while (ndr->offset < ndr->data_size) { |
217 | 5.92M | list->str = talloc_realloc(ndr->current_mem_ctx, list->str, |
218 | 5.92M | const char *, list->count+1); |
219 | 5.92M | if (! list->str) { |
220 | 0 | return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_string_list"); |
221 | 0 | } |
222 | 5.92M | NDR_CHECK(ndr_pull_dnsp_string(ndr, ndr_flags, &list->str[list->count])); |
223 | 5.91M | list->count++; |
224 | 5.91M | } |
225 | | |
226 | 2.17k | return NDR_ERR_SUCCESS; |
227 | 2.29k | } |
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 | 630 | { |
231 | 630 | uint8_t i; |
232 | | |
233 | 11.5k | for (i=0; i<list->count; i++) { |
234 | 10.9k | NDR_CHECK(ndr_push_dnsp_string(ndr, ndr_flags, list->str[i])); |
235 | 10.9k | } |
236 | 630 | return NDR_ERR_SUCCESS; |
237 | 630 | } |
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 | } |