1/* $FreeBSD$ */
2
3#include <setjmp.h>
4#include <stdlib.h>
5
6#include "dhcpd.h"
7
8jmp_buf env;
9
10void	expand_domain_search(struct packet *packet);
11
12void
13no_option_present()
14{
15	int ret;
16	struct option_data option;
17	struct packet p;
18
19	option.data = NULL;
20	option.len  = 0;
21	p.options[DHO_DOMAIN_SEARCH] = option;
22
23	ret = setjmp(env);
24	if (ret == 0)
25		expand_domain_search(&p);
26
27	if (p.options[DHO_DOMAIN_SEARCH].len != 0 ||
28	    p.options[DHO_DOMAIN_SEARCH].data != NULL)
29		abort();
30}
31
32void
33one_domain_valid()
34{
35	int ret;
36	struct packet p;
37	struct option_data *option;
38
39	char *data     = "\007example\003org\0";
40	char *expected = "example.org.";
41
42	option = &p.options[DHO_DOMAIN_SEARCH];
43	option->len  = 13;
44	option->data = malloc(option->len);
45	memcpy(option->data, data, option->len);
46
47	ret = setjmp(env);
48	if (ret == 0)
49		expand_domain_search(&p);
50
51	if (option->len != strlen(expected) ||
52	    strcmp(option->data, expected) != 0)
53		abort();
54
55	free(option->data);
56}
57
58void
59one_domain_truncated1()
60{
61	int ret;
62	struct option_data *option;
63	struct packet p;
64
65	char *data = "\007example\003org";
66
67	option = &p.options[DHO_DOMAIN_SEARCH];
68	option->len  = 12;
69	option->data = malloc(option->len);
70	memcpy(option->data, data, option->len);
71
72	ret = setjmp(env);
73	if (ret == 0)
74		expand_domain_search(&p);
75
76	if (ret != 1)
77		abort();
78
79	free(option->data);
80}
81
82void
83one_domain_truncated2()
84{
85	int ret;
86	struct option_data *option;
87	struct packet p;
88
89	char *data = "\007ex";
90
91	option = &p.options[DHO_DOMAIN_SEARCH];
92	option->len  = 3;
93	option->data = malloc(option->len);
94	memcpy(option->data, data, option->len);
95
96	ret = setjmp(env);
97	if (ret == 0)
98		expand_domain_search(&p);
99
100	if (ret != 1)
101		abort();
102
103	free(option->data);
104}
105
106void
107two_domains_valid()
108{
109	int ret;
110	struct packet p;
111	struct option_data *option;
112
113	char *data     = "\007example\003org\0\007example\003com\0";
114	char *expected = "example.org. example.com.";
115
116	option = &p.options[DHO_DOMAIN_SEARCH];
117	option->len  = 26;
118	option->data = malloc(option->len);
119	memcpy(option->data, data, option->len);
120
121	ret = setjmp(env);
122	if (ret == 0)
123		expand_domain_search(&p);
124
125	if (option->len != strlen(expected) ||
126	    strcmp(option->data, expected) != 0)
127		abort();
128
129	free(option->data);
130}
131
132void
133two_domains_truncated1()
134{
135	int ret;
136	struct option_data *option;
137	struct packet p;
138
139	char *data = "\007example\003org\0\007example\003com";
140
141	option = &p.options[DHO_DOMAIN_SEARCH];
142	option->len  = 25;
143	option->data = malloc(option->len);
144	memcpy(option->data, data, option->len);
145
146	ret = setjmp(env);
147	if (ret == 0)
148		expand_domain_search(&p);
149
150	if (ret != 1)
151		abort();
152
153	free(option->data);
154}
155
156void
157two_domains_truncated2()
158{
159	int ret;
160	struct option_data *option;
161	struct packet p;
162
163	char *data = "\007example\003org\0\007ex";
164
165	option = &p.options[DHO_DOMAIN_SEARCH];
166	option->len  = 16;
167	option->data = malloc(option->len);
168	memcpy(option->data, data, option->len);
169
170	ret = setjmp(env);
171	if (ret == 0)
172		expand_domain_search(&p);
173
174	if (ret != 1)
175		abort();
176
177	free(option->data);
178}
179
180void
181two_domains_compressed()
182{
183	int ret;
184	struct packet p;
185	struct option_data *option;
186
187	char *data     = "\007example\003org\0\006foobar\xc0\x08";
188	char *expected = "example.org. foobar.org.";
189
190	option = &p.options[DHO_DOMAIN_SEARCH];
191	option->len  = 22;
192	option->data = malloc(option->len);
193	memcpy(option->data, data, option->len);
194
195	ret = setjmp(env);
196	if (ret == 0)
197		expand_domain_search(&p);
198
199	if (option->len != strlen(expected) ||
200	    strcmp(option->data, expected) != 0)
201		abort();
202
203	free(option->data);
204}
205
206void
207two_domains_infloop()
208{
209	int ret;
210	struct packet p;
211	struct option_data *option;
212
213	char *data = "\007example\003org\0\006foobar\xc0\x0d";
214
215	option = &p.options[DHO_DOMAIN_SEARCH];
216	option->len  = 22;
217	option->data = malloc(option->len);
218	memcpy(option->data, data, option->len);
219
220	ret = setjmp(env);
221	if (ret == 0)
222		expand_domain_search(&p);
223
224	if (ret != 1)
225		abort();
226
227	free(option->data);
228}
229
230void
231two_domains_forwardptr()
232{
233	int ret;
234	struct packet p;
235	struct option_data *option;
236
237	char *data = "\007example\003org\xc0\x0d\006foobar\0";
238
239	option = &p.options[DHO_DOMAIN_SEARCH];
240	option->len  = 22;
241	option->data = malloc(option->len);
242	memcpy(option->data, data, option->len);
243
244	ret = setjmp(env);
245	if (ret == 0)
246		expand_domain_search(&p);
247
248	if (ret != 1)
249		abort();
250
251	free(option->data);
252}
253
254void
255two_domains_truncatedptr()
256{
257	int ret;
258	struct packet p;
259	struct option_data *option;
260
261	char *data = "\007example\003org\0\006foobar\xc0";
262
263	option = &p.options[DHO_DOMAIN_SEARCH];
264	option->len  = 21;
265	option->data = malloc(option->len);
266	memcpy(option->data, data, option->len);
267
268	ret = setjmp(env);
269	if (ret == 0)
270		expand_domain_search(&p);
271
272	if (ret != 1)
273		abort();
274
275	free(option->data);
276}
277
278void
279multiple_domains_valid()
280{
281	int ret;
282	struct packet p;
283	struct option_data *option;
284
285	char *data =
286	    "\007example\003org\0\002cl\006foobar\003com\0\002fr\xc0\x10";
287
288	char *expected = "example.org. cl.foobar.com. fr.foobar.com.";
289
290	option = &p.options[DHO_DOMAIN_SEARCH];
291	option->len  = 33;
292	option->data = malloc(option->len);
293	memcpy(option->data, data, option->len);
294
295	ret = setjmp(env);
296	if (ret == 0)
297		expand_domain_search(&p);
298
299	if (option->len != strlen(expected) ||
300	    strcmp(option->data, expected) != 0)
301		abort();
302
303	free(option->data);
304}
305
306int
307main(int argc, char *argv[])
308{
309
310	no_option_present();
311
312	one_domain_valid();
313	one_domain_truncated1();
314	one_domain_truncated2();
315
316	two_domains_valid();
317	two_domains_truncated1();
318	two_domains_truncated2();
319
320	two_domains_compressed();
321	two_domains_infloop();
322	two_domains_forwardptr();
323	two_domains_truncatedptr();
324
325	multiple_domains_valid();
326
327	return (0);
328}
329