1 /*
2  * Copyright (c) 2015 Verisure Innovation AB
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25  * OF SUCH DAMAGE.
26  *
27  * This file is part of the lwIP TCP/IP stack.
28  *
29  * Author: Erik Ekman <erik@kryo.se>
30  *
31  */
32 
33 #include "test_mdns.h"
34 
35 #include "lwip/pbuf.h"
36 #include "lwip/apps/mdns.h"
37 #include "lwip/apps/mdns_domain.h"
38 #include "lwip/apps/mdns_priv.h"
39 
START_TEST(readname_basic)40 START_TEST(readname_basic)
41 {
42   static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 };
43   struct pbuf *p;
44   struct mdns_domain domain;
45   u16_t offset;
46   LWIP_UNUSED_ARG(_i);
47 
48   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
49   fail_if(p == NULL);
50   p->payload = (void *)(size_t)data;
51   offset = mdns_readname(p, 0, &domain);
52   pbuf_free(p);
53   fail_unless(offset == sizeof(data));
54   fail_unless(domain.length == sizeof(data));
55   fail_if(memcmp(&domain.name, data, sizeof(data)));
56 }
57 END_TEST
58 
START_TEST(readname_anydata)59 START_TEST(readname_anydata)
60 {
61   static const u8_t data[] = { 0x05, 0x00, 0xFF, 0x08, 0xc0, 0x0f, 0x04, 0x7f, 0x80, 0x82, 0x88, 0x00 };
62   struct pbuf *p;
63   struct mdns_domain domain;
64   u16_t offset;
65   LWIP_UNUSED_ARG(_i);
66 
67   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
68   fail_if(p == NULL);
69   p->payload = (void *)(size_t)data;
70   offset = mdns_readname(p, 0, &domain);
71   pbuf_free(p);
72   fail_unless(offset == sizeof(data));
73   fail_unless(domain.length == sizeof(data));
74   fail_if(memcmp(&domain.name, data, sizeof(data)));
75 }
76 END_TEST
77 
START_TEST(readname_short_buf)78 START_TEST(readname_short_buf)
79 {
80   static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a' };
81   struct pbuf *p;
82   struct mdns_domain domain;
83   u16_t offset;
84   LWIP_UNUSED_ARG(_i);
85 
86   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
87   fail_if(p == NULL);
88   p->payload = (void *)(size_t)data;
89   offset = mdns_readname(p, 0, &domain);
90   pbuf_free(p);
91   fail_unless(offset == MDNS_READNAME_ERROR);
92 }
93 END_TEST
94 
START_TEST(readname_long_label)95 START_TEST(readname_long_label)
96 {
97   static const u8_t data[] = {
98       0x05, 'm', 'u', 'l', 't', 'i',
99       0x52, 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
100       'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
101       'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
102       'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
103       'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
104       'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 0x00
105   };
106   struct pbuf *p;
107   struct mdns_domain domain;
108   u16_t offset;
109   LWIP_UNUSED_ARG(_i);
110 
111   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
112   fail_if(p == NULL);
113   p->payload = (void *)(size_t)data;
114   offset = mdns_readname(p, 0, &domain);
115   pbuf_free(p);
116   fail_unless(offset == MDNS_READNAME_ERROR);
117 }
118 END_TEST
119 
START_TEST(readname_overflow)120 START_TEST(readname_overflow)
121 {
122   static const u8_t data[] = {
123       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
124       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
125       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
126       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
127       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
128       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
129       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
130       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
131       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
132       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
133       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
134       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
135       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
136       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
137       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
138       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
139       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
140       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
141       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
142       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
143       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
144       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
145       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
146       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
147       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
148       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
149       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
150       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
151       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
152       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
153       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
154       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
155       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
156       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
157       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
158       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
159       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
160       0x00
161   };
162   struct pbuf *p;
163   struct mdns_domain domain;
164   u16_t offset;
165   LWIP_UNUSED_ARG(_i);
166 
167   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
168   fail_if(p == NULL);
169   p->payload = (void *)(size_t)data;
170   offset = mdns_readname(p, 0, &domain);
171   pbuf_free(p);
172   fail_unless(offset == MDNS_READNAME_ERROR);
173 }
174 END_TEST
175 
START_TEST(readname_jump_earlier)176 START_TEST(readname_jump_earlier)
177 {
178   static const u8_t data[] = {
179       /* Some padding needed, not supported to jump to bytes containing dns header */
180       /*  0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181       /* 10 */ 0x0f, 0x0e, 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xab,
182       /* 20 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x0c
183   };
184   static const u8_t fullname[] = {
185       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00
186   };
187   struct pbuf *p;
188   struct mdns_domain domain;
189   u16_t offset;
190   LWIP_UNUSED_ARG(_i);
191 
192   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
193   fail_if(p == NULL);
194   p->payload = (void *)(size_t)data;
195   offset = mdns_readname(p, 20, &domain);
196   pbuf_free(p);
197   fail_unless(offset == sizeof(data));
198   fail_unless(domain.length == sizeof(fullname));
199 
200   fail_if(memcmp(&domain.name, fullname, sizeof(fullname)));
201 }
202 END_TEST
203 
START_TEST(readname_jump_earlier_jump)204 START_TEST(readname_jump_earlier_jump)
205 {
206   static const u8_t data[] = {
207       /* Some padding needed, not supported to jump to bytes containing dns header */
208       /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209       /* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x03, 0x0b, 0x0a, 0xf2,
210       /* 0x10 */ 0x04, 'c', 'a', 's', 't', 0x00, 0xc0, 0x10,
211       /* 0x18 */ 0x05, 'm', 'u', 'l', 't', 'i', 0xc0, 0x16
212   };
213   static const u8_t fullname[] = {
214       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00
215   };
216   struct pbuf *p;
217   struct mdns_domain domain;
218   u16_t offset;
219   LWIP_UNUSED_ARG(_i);
220 
221   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
222   fail_if(p == NULL);
223   p->payload = (void *)(size_t)data;
224   offset = mdns_readname(p, 0x18, &domain);
225   pbuf_free(p);
226   fail_unless(offset == sizeof(data));
227   fail_unless(domain.length == sizeof(fullname));
228 
229   fail_if(memcmp(&domain.name, fullname, sizeof(fullname)));
230 }
231 END_TEST
232 
START_TEST(readname_jump_maxdepth)233 START_TEST(readname_jump_maxdepth)
234 {
235   static const u8_t data[] = {
236       /* Some padding needed, not supported to jump to bytes containing dns header */
237       /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238       /* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x03, 0x0b, 0x0a, 0xf2,
239       /* 0x10 */ 0x04, 'n', 'a', 'm', 'e', 0xc0, 0x27, 0x03,
240       /* 0x18 */ 0x03, 'd', 'n', 's', 0xc0, 0x10, 0xc0, 0x10,
241       /* 0x20 */ 0x04, 'd', 'e', 'e', 'p', 0xc0, 0x18, 0x00,
242       /* 0x28 */ 0x04, 'c', 'a', 's', 't', 0xc0, 0x20, 0xb0,
243       /* 0x30 */ 0x05, 'm', 'u', 'l', 't', 'i', 0xc0, 0x28
244   };
245   static const u8_t fullname[] = {
246       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
247       0x04, 'd', 'e', 'e', 'p', 0x03, 'd', 'n', 's',
248       0x04, 'n', 'a', 'm', 'e', 0x00
249   };
250   struct pbuf *p;
251   struct mdns_domain domain;
252   u16_t offset;
253   LWIP_UNUSED_ARG(_i);
254 
255   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
256   fail_if(p == NULL);
257   p->payload = (void *)(size_t)data;
258   offset = mdns_readname(p, 0x30, &domain);
259   pbuf_free(p);
260   fail_unless(offset == sizeof(data));
261   fail_unless(domain.length == sizeof(fullname));
262 
263   fail_if(memcmp(&domain.name, fullname, sizeof(fullname)));
264 }
265 END_TEST
266 
START_TEST(readname_jump_later)267 START_TEST(readname_jump_later)
268 {
269   static const u8_t data[] = {
270       /* 0x00 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x10, 0x00, 0x01, 0x40,
271       /* 0x10 */ 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xab
272   };
273   static const u8_t fullname[] = {
274       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00
275   };
276   struct pbuf *p;
277   struct mdns_domain domain;
278   u16_t offset;
279   LWIP_UNUSED_ARG(_i);
280 
281   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
282   fail_if(p == NULL);
283   p->payload = (void *)(size_t)data;
284   offset = mdns_readname(p, 0, &domain);
285   pbuf_free(p);
286   fail_unless(offset == 13);
287   fail_unless(domain.length == sizeof(fullname));
288 
289   fail_if(memcmp(&domain.name, fullname, sizeof(fullname)));
290 }
291 END_TEST
292 
START_TEST(readname_half_jump)293 START_TEST(readname_half_jump)
294 {
295   static const u8_t data[] = {
296       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0
297   };
298   struct pbuf *p;
299   struct mdns_domain domain;
300   u16_t offset;
301   LWIP_UNUSED_ARG(_i);
302 
303   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
304   fail_if(p == NULL);
305   p->payload = (void *)(size_t)data;
306   offset = mdns_readname(p, 0, &domain);
307   pbuf_free(p);
308   fail_unless(offset == MDNS_READNAME_ERROR);
309 }
310 END_TEST
311 
START_TEST(readname_jump_toolong)312 START_TEST(readname_jump_toolong)
313 {
314   static const u8_t data[] = {
315       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc2, 0x10, 0x00, 0x01, 0x40
316   };
317   struct pbuf *p;
318   struct mdns_domain domain;
319   u16_t offset;
320   LWIP_UNUSED_ARG(_i);
321 
322   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
323   fail_if(p == NULL);
324   p->payload = (void *)(size_t)data;
325   offset = mdns_readname(p, 0, &domain);
326   pbuf_free(p);
327   fail_unless(offset == MDNS_READNAME_ERROR);
328 }
329 END_TEST
330 
START_TEST(readname_jump_loop_label)331 START_TEST(readname_jump_loop_label)
332 {
333   static const u8_t data[] = {
334       /*  0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
335       /* 10 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x10
336   };
337   struct pbuf *p;
338   struct mdns_domain domain;
339   u16_t offset;
340   LWIP_UNUSED_ARG(_i);
341 
342   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
343   fail_if(p == NULL);
344   p->payload = (void *)(size_t)data;
345   offset = mdns_readname(p, 10, &domain);
346   pbuf_free(p);
347   fail_unless(offset == MDNS_READNAME_ERROR);
348 }
349 END_TEST
350 
START_TEST(readname_jump_loop_jump)351 START_TEST(readname_jump_loop_jump)
352 {
353   static const u8_t data[] = {
354       /*  0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
355       /* 10 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x15
356   };
357   struct pbuf *p;
358   struct mdns_domain domain;
359   u16_t offset;
360   LWIP_UNUSED_ARG(_i);
361 
362   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
363   fail_if(p == NULL);
364   p->payload = (void *)(size_t)data;
365   offset = mdns_readname(p, 10, &domain);
366   pbuf_free(p);
367   fail_unless(offset == MDNS_READNAME_ERROR);
368 }
369 END_TEST
370 
START_TEST(add_label_basic)371 START_TEST(add_label_basic)
372 {
373   static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 };
374   struct mdns_domain domain;
375   err_t res;
376   LWIP_UNUSED_ARG(_i);
377 
378   memset(&domain, 0, sizeof(domain));
379   res = mdns_domain_add_label(&domain, "multi", 5);
380   fail_unless(res == ERR_OK);
381   res = mdns_domain_add_label(&domain, "cast", 4);
382   fail_unless(res == ERR_OK);
383   res = mdns_domain_add_label(&domain, NULL, 0);
384   fail_unless(res == ERR_OK);
385   fail_unless(domain.length == sizeof(data));
386   fail_if(memcmp(&domain.name, data, sizeof(data)));
387 }
388 END_TEST
389 
START_TEST(add_label_long_label)390 START_TEST(add_label_long_label)
391 {
392   static const char *toolong = "abcdefghijklmnopqrstuvwxyz0123456789-abcdefghijklmnopqrstuvwxyz0123456789-abcdefghijklmnopqrstuvwxyz0123456789-";
393   struct mdns_domain domain;
394   err_t res;
395   LWIP_UNUSED_ARG(_i);
396 
397   memset(&domain, 0, sizeof(domain));
398   res = mdns_domain_add_label(&domain, "multi", 5);
399   fail_unless(res == ERR_OK);
400   res = mdns_domain_add_label(&domain, toolong, (u8_t)strlen(toolong));
401   fail_unless(res == ERR_VAL);
402 }
403 END_TEST
404 
START_TEST(add_label_full)405 START_TEST(add_label_full)
406 {
407   static const char *label = "0123456789abcdef0123456789abcdef";
408   struct mdns_domain domain;
409   err_t res;
410   LWIP_UNUSED_ARG(_i);
411 
412   memset(&domain, 0, sizeof(domain));
413   res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label));
414   fail_unless(res == ERR_OK);
415   fail_unless(domain.length == 33);
416   res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label));
417   fail_unless(res == ERR_OK);
418   fail_unless(domain.length == 66);
419   res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label));
420   fail_unless(res == ERR_OK);
421   fail_unless(domain.length == 99);
422   res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label));
423   fail_unless(res == ERR_OK);
424   fail_unless(domain.length == 132);
425   res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label));
426   fail_unless(res == ERR_OK);
427   fail_unless(domain.length == 165);
428   res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label));
429   fail_unless(res == ERR_OK);
430   fail_unless(domain.length == 198);
431   res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label));
432   fail_unless(res == ERR_OK);
433   fail_unless(domain.length == 231);
434   res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label));
435   fail_unless(res == ERR_VAL);
436   fail_unless(domain.length == 231);
437   res = mdns_domain_add_label(&domain, label, 25);
438   fail_unless(res == ERR_VAL);
439   fail_unless(domain.length == 231);
440   res = mdns_domain_add_label(&domain, label, 24);
441   fail_unless(res == ERR_VAL);
442   fail_unless(domain.length == 231);
443   res = mdns_domain_add_label(&domain, label, 23);
444   fail_unless(res == ERR_OK);
445   fail_unless(domain.length == 255);
446   res = mdns_domain_add_label(&domain, NULL, 0);
447   fail_unless(res == ERR_OK);
448   fail_unless(domain.length == 256);
449   res = mdns_domain_add_label(&domain, NULL, 0);
450   fail_unless(res == ERR_VAL);
451   fail_unless(domain.length == 256);
452 }
453 END_TEST
454 
START_TEST(domain_eq_basic)455 START_TEST(domain_eq_basic)
456 {
457   static const u8_t data[] = {
458       0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00
459   };
460   struct mdns_domain domain1, domain2;
461   err_t res;
462   LWIP_UNUSED_ARG(_i);
463 
464   memset(&domain1, 0, sizeof(domain1));
465   res = mdns_domain_add_label(&domain1, "multi", 5);
466   fail_unless(res == ERR_OK);
467   res = mdns_domain_add_label(&domain1, "cast", 4);
468   fail_unless(res == ERR_OK);
469   res = mdns_domain_add_label(&domain1, NULL, 0);
470   fail_unless(res == ERR_OK);
471   fail_unless(domain1.length == sizeof(data));
472 
473   memset(&domain2, 0, sizeof(domain2));
474   res = mdns_domain_add_label(&domain2, "multi", 5);
475   fail_unless(res == ERR_OK);
476   res = mdns_domain_add_label(&domain2, "cast", 4);
477   fail_unless(res == ERR_OK);
478   res = mdns_domain_add_label(&domain2, NULL, 0);
479   fail_unless(res == ERR_OK);
480 
481   fail_unless(mdns_domain_eq(&domain1, &domain2));
482 }
483 END_TEST
484 
START_TEST(domain_eq_diff)485 START_TEST(domain_eq_diff)
486 {
487   struct mdns_domain domain1, domain2;
488   err_t res;
489   LWIP_UNUSED_ARG(_i);
490 
491   memset(&domain1, 0, sizeof(domain1));
492   res = mdns_domain_add_label(&domain1, "multi", 5);
493   fail_unless(res == ERR_OK);
494   res = mdns_domain_add_label(&domain1, "base", 4);
495   fail_unless(res == ERR_OK);
496   res = mdns_domain_add_label(&domain1, NULL, 0);
497   fail_unless(res == ERR_OK);
498 
499   memset(&domain2, 0, sizeof(domain2));
500   res = mdns_domain_add_label(&domain2, "multi", 5);
501   fail_unless(res == ERR_OK);
502   res = mdns_domain_add_label(&domain2, "cast", 4);
503   fail_unless(res == ERR_OK);
504   res = mdns_domain_add_label(&domain2, NULL, 0);
505   fail_unless(res == ERR_OK);
506 
507   fail_if(mdns_domain_eq(&domain1, &domain2));
508 }
509 END_TEST
510 
START_TEST(domain_eq_case)511 START_TEST(domain_eq_case)
512 {
513   struct mdns_domain domain1, domain2;
514   err_t res;
515   LWIP_UNUSED_ARG(_i);
516 
517   memset(&domain1, 0, sizeof(domain1));
518   res = mdns_domain_add_label(&domain1, "multi", 5);
519   fail_unless(res == ERR_OK);
520   res = mdns_domain_add_label(&domain1, "cast", 4);
521   fail_unless(res == ERR_OK);
522   res = mdns_domain_add_label(&domain1, NULL, 0);
523   fail_unless(res == ERR_OK);
524 
525   memset(&domain2, 0, sizeof(domain2));
526   res = mdns_domain_add_label(&domain2, "MulTI", 5);
527   fail_unless(res == ERR_OK);
528   res = mdns_domain_add_label(&domain2, "casT", 4);
529   fail_unless(res == ERR_OK);
530   res = mdns_domain_add_label(&domain2, NULL, 0);
531   fail_unless(res == ERR_OK);
532 
533   fail_unless(mdns_domain_eq(&domain1, &domain2));
534 }
535 END_TEST
536 
START_TEST(domain_eq_anydata)537 START_TEST(domain_eq_anydata)
538 {
539   static const u8_t data1[] = { 0x05, 0xcc, 0xdc, 0x00, 0xa0 };
540   static const u8_t data2[] = { 0x7f, 0x8c, 0x01, 0xff, 0xcf };
541   struct mdns_domain domain1, domain2;
542   err_t res;
543   LWIP_UNUSED_ARG(_i);
544 
545   memset(&domain1, 0, sizeof(domain1));
546   res = mdns_domain_add_label(&domain1, (const char*)data1, sizeof(data1));
547   fail_unless(res == ERR_OK);
548   res = mdns_domain_add_label(&domain1, "cast", 4);
549   fail_unless(res == ERR_OK);
550   res = mdns_domain_add_label(&domain1, (const char*)data2, sizeof(data2));
551   fail_unless(res == ERR_OK);
552   res = mdns_domain_add_label(&domain1, NULL, 0);
553   fail_unless(res == ERR_OK);
554 
555   memset(&domain2, 0, sizeof(domain2));
556   res = mdns_domain_add_label(&domain2, (const char*)data1, sizeof(data1));
557   fail_unless(res == ERR_OK);
558   res = mdns_domain_add_label(&domain2, "casT", 4);
559   fail_unless(res == ERR_OK);
560   res = mdns_domain_add_label(&domain2, (const char*)data2, sizeof(data2));
561   fail_unless(res == ERR_OK);
562   res = mdns_domain_add_label(&domain2, NULL, 0);
563   fail_unless(res == ERR_OK);
564 
565   fail_unless(mdns_domain_eq(&domain1, &domain2));
566 }
567 END_TEST
568 
START_TEST(domain_eq_length)569 START_TEST(domain_eq_length)
570 {
571   struct mdns_domain domain1, domain2;
572   err_t res;
573   LWIP_UNUSED_ARG(_i);
574 
575   memset(&domain1, 0, sizeof(domain1));
576   memset(domain1.name, 0xAA, sizeof(MDNS_DOMAIN_MAXLEN));
577   res = mdns_domain_add_label(&domain1, "multi", 5);
578   fail_unless(res == ERR_OK);
579   res = mdns_domain_add_label(&domain1, "cast", 4);
580   fail_unless(res == ERR_OK);
581 
582   memset(&domain2, 0, sizeof(domain2));
583   memset(domain2.name, 0xBB, sizeof(MDNS_DOMAIN_MAXLEN));
584   res = mdns_domain_add_label(&domain2, "multi", 5);
585   fail_unless(res == ERR_OK);
586   res = mdns_domain_add_label(&domain2, "cast", 4);
587   fail_unless(res == ERR_OK);
588 
589   fail_unless(mdns_domain_eq(&domain1, &domain2));
590 }
591 END_TEST
592 
START_TEST(compress_full_match)593 START_TEST(compress_full_match)
594 {
595   static const u8_t data[] = {
596       0x00, 0x00,
597       0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00
598   };
599   struct pbuf *p;
600   struct mdns_domain domain;
601   u16_t offset;
602   u16_t length;
603   err_t res;
604   LWIP_UNUSED_ARG(_i);
605 
606   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
607   fail_if(p == NULL);
608   p->payload = (void *)(size_t)data;
609 
610   memset(&domain, 0, sizeof(domain));
611   res = mdns_domain_add_label(&domain, "foobar", 6);
612   fail_unless(res == ERR_OK);
613   res = mdns_domain_add_label(&domain, "local", 5);
614   fail_unless(res == ERR_OK);
615   res = mdns_domain_add_label(&domain, NULL, 0);
616   fail_unless(res == ERR_OK);
617 
618   offset = 2;
619   length = mdns_compress_domain(p, &offset, &domain);
620   /* Write 0 bytes, then a jump to addr 2 */
621   fail_unless(length == 0);
622   fail_unless(offset == 2);
623 
624   pbuf_free(p);
625 }
626 END_TEST
627 
START_TEST(compress_full_match_subset)628 START_TEST(compress_full_match_subset)
629 {
630   static const u8_t data[] = {
631       0x00, 0x00,
632       0x02, 'g', 'o', 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00
633   };
634   struct pbuf *p;
635   struct mdns_domain domain;
636   u16_t offset;
637   u16_t length;
638   err_t res;
639   LWIP_UNUSED_ARG(_i);
640 
641   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
642   fail_if(p == NULL);
643   p->payload = (void *)(size_t)data;
644 
645   memset(&domain, 0, sizeof(domain));
646   res = mdns_domain_add_label(&domain, "foobar", 6);
647   fail_unless(res == ERR_OK);
648   res = mdns_domain_add_label(&domain, "local", 5);
649   fail_unless(res == ERR_OK);
650   res = mdns_domain_add_label(&domain, NULL, 0);
651   fail_unless(res == ERR_OK);
652 
653   offset = 2;
654   length = mdns_compress_domain(p, &offset, &domain);
655   /* Write 0 bytes, then a jump to addr 5 */
656   fail_unless(length == 0);
657   fail_unless(offset == 5);
658 
659   pbuf_free(p);
660 }
661 END_TEST
662 
START_TEST(compress_full_match_jump)663 START_TEST(compress_full_match_jump)
664 {
665   static const u8_t data[] = {
666     /* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
667                0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
668     /* 0x10 */ 0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xc0, 0x00, 0x02, 0x00,
669     /* 0x20 */ 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0xc0, 0x15
670   };
671   struct pbuf *p;
672   struct mdns_domain domain;
673   u16_t offset;
674   u16_t length;
675   err_t res;
676   LWIP_UNUSED_ARG(_i);
677 
678   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
679   fail_if(p == NULL);
680   p->payload = (void *)(size_t)data;
681 
682   memset(&domain, 0, sizeof(domain));
683   res = mdns_domain_add_label(&domain, "foobar", 6);
684   fail_unless(res == ERR_OK);
685   res = mdns_domain_add_label(&domain, "local", 5);
686   fail_unless(res == ERR_OK);
687   res = mdns_domain_add_label(&domain, NULL, 0);
688   fail_unless(res == ERR_OK);
689 
690   offset = 0x20;
691   length = mdns_compress_domain(p, &offset, &domain);
692   /* Write 0 bytes, then a jump to addr 0x20 */
693   fail_unless(length == 0);
694   fail_unless(offset == 0x20);
695 
696   pbuf_free(p);
697 }
698 END_TEST
699 
START_TEST(compress_no_match)700 START_TEST(compress_no_match)
701 {
702   static const u8_t data[] = {
703       0x00, 0x00,
704       0x04, 'l', 'w', 'i', 'p', 0x05, 'w', 'i', 'k', 'i', 'a', 0x03, 'c', 'o', 'm', 0x00
705   };
706   struct pbuf *p;
707   struct mdns_domain domain;
708   u16_t offset;
709   u16_t length;
710   err_t res;
711   LWIP_UNUSED_ARG(_i);
712 
713   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
714   fail_if(p == NULL);
715   p->payload = (void *)(size_t)data;
716 
717   memset(&domain, 0, sizeof(domain));
718   res = mdns_domain_add_label(&domain, "foobar", 6);
719   fail_unless(res == ERR_OK);
720   res = mdns_domain_add_label(&domain, "local", 5);
721   fail_unless(res == ERR_OK);
722   res = mdns_domain_add_label(&domain, NULL, 0);
723   fail_unless(res == ERR_OK);
724 
725   offset = 2;
726   length = mdns_compress_domain(p, &offset, &domain);
727   /* Write all bytes, no jump */
728   fail_unless(length == domain.length);
729 
730   pbuf_free(p);
731 }
732 END_TEST
733 
START_TEST(compress_2nd_label)734 START_TEST(compress_2nd_label)
735 {
736   static const u8_t data[] = {
737       0x00, 0x00,
738       0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00
739   };
740   struct pbuf *p;
741   struct mdns_domain domain;
742   u16_t offset;
743   u16_t length;
744   err_t res;
745   LWIP_UNUSED_ARG(_i);
746 
747   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
748   fail_if(p == NULL);
749   p->payload = (void *)(size_t)data;
750 
751   memset(&domain, 0, sizeof(domain));
752   res = mdns_domain_add_label(&domain, "lwip", 4);
753   fail_unless(res == ERR_OK);
754   res = mdns_domain_add_label(&domain, "local", 5);
755   fail_unless(res == ERR_OK);
756   res = mdns_domain_add_label(&domain, NULL, 0);
757   fail_unless(res == ERR_OK);
758 
759   offset = 2;
760   length = mdns_compress_domain(p, &offset, &domain);
761   /* Write 5 bytes, then a jump to addr 9 */
762   fail_unless(length == 5);
763   fail_unless(offset == 9);
764 
765   pbuf_free(p);
766 }
767 END_TEST
768 
START_TEST(compress_2nd_label_short)769 START_TEST(compress_2nd_label_short)
770 {
771   static const u8_t data[] = {
772       0x00, 0x00,
773       0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00
774   };
775   struct pbuf *p;
776   struct mdns_domain domain;
777   u16_t offset;
778   u16_t length;
779   err_t res;
780   LWIP_UNUSED_ARG(_i);
781 
782   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
783   fail_if(p == NULL);
784   p->payload = (void *)(size_t)data;
785 
786   memset(&domain, 0, sizeof(domain));
787   res = mdns_domain_add_label(&domain, "foobar", 6);
788   fail_unless(res == ERR_OK);
789   res = mdns_domain_add_label(&domain, "local", 5);
790   fail_unless(res == ERR_OK);
791   res = mdns_domain_add_label(&domain, NULL, 0);
792   fail_unless(res == ERR_OK);
793 
794   offset = 2;
795   length = mdns_compress_domain(p, &offset, &domain);
796   /* Write 5 bytes, then a jump to addr 7 */
797   fail_unless(length == 7);
798   fail_unless(offset == 7);
799 
800   pbuf_free(p);
801 }
802 END_TEST
803 
START_TEST(compress_jump_to_jump)804 START_TEST(compress_jump_to_jump)
805 {
806   static const u8_t data[] = {
807       /* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
808                  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
809       /* 0x10 */ 0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xc0, 0x00, 0x02, 0x00,
810       /* 0x20 */ 0x07, 'b', 'a', 'n', 'a', 'n', 'a', 's', 0xc0, 0x15
811   };
812   struct pbuf *p;
813   struct mdns_domain domain;
814   u16_t offset;
815   u16_t length;
816   err_t res;
817   LWIP_UNUSED_ARG(_i);
818 
819   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
820   fail_if(p == NULL);
821   p->payload = (void *)(size_t)data;
822 
823   memset(&domain, 0, sizeof(domain));
824   res = mdns_domain_add_label(&domain, "foobar", 6);
825   fail_unless(res == ERR_OK);
826   res = mdns_domain_add_label(&domain, "local", 5);
827   fail_unless(res == ERR_OK);
828   res = mdns_domain_add_label(&domain, NULL, 0);
829   fail_unless(res == ERR_OK);
830 
831   offset = 0x20;
832   length = mdns_compress_domain(p, &offset, &domain);
833   /* Don't compress if jump would be to a jump */
834   fail_unless(length == domain.length);
835 
836   offset = 0x10;
837   length = mdns_compress_domain(p, &offset, &domain);
838   /* Write 7 bytes, then a jump to addr 0x15 */
839   fail_unless(length == 7);
840   fail_unless(offset == 0x15);
841 
842   pbuf_free(p);
843 }
844 END_TEST
845 
START_TEST(compress_long_match)846 START_TEST(compress_long_match)
847 {
848   static const u8_t data[] = {
849       0x00, 0x00,
850       0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x03, 'c', 'o', 'm', 0x00
851   };
852   struct pbuf *p;
853   struct mdns_domain domain;
854   u16_t offset;
855   u16_t length;
856   err_t res;
857   LWIP_UNUSED_ARG(_i);
858 
859   p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
860   fail_if(p == NULL);
861   p->payload = (void *)(size_t)data;
862 
863   memset(&domain, 0, sizeof(domain));
864   res = mdns_domain_add_label(&domain, "foobar", 6);
865   fail_unless(res == ERR_OK);
866   res = mdns_domain_add_label(&domain, "local", 5);
867   fail_unless(res == ERR_OK);
868   res = mdns_domain_add_label(&domain, NULL, 0);
869   fail_unless(res == ERR_OK);
870 
871   offset = 2;
872   length = mdns_compress_domain(p, &offset, &domain);
873   fail_unless(length == domain.length);
874 
875   pbuf_free(p);
876 }
877 END_TEST
878 
mdns_suite(void)879 Suite* mdns_suite(void)
880 {
881   testfunc tests[] = {
882     TESTFUNC(readname_basic),
883     TESTFUNC(readname_anydata),
884     TESTFUNC(readname_short_buf),
885     TESTFUNC(readname_long_label),
886     TESTFUNC(readname_overflow),
887     TESTFUNC(readname_jump_earlier),
888     TESTFUNC(readname_jump_earlier_jump),
889     TESTFUNC(readname_jump_maxdepth),
890     TESTFUNC(readname_jump_later),
891     TESTFUNC(readname_half_jump),
892     TESTFUNC(readname_jump_toolong),
893     TESTFUNC(readname_jump_loop_label),
894     TESTFUNC(readname_jump_loop_jump),
895 
896     TESTFUNC(add_label_basic),
897     TESTFUNC(add_label_long_label),
898     TESTFUNC(add_label_full),
899 
900     TESTFUNC(domain_eq_basic),
901     TESTFUNC(domain_eq_diff),
902     TESTFUNC(domain_eq_case),
903     TESTFUNC(domain_eq_anydata),
904     TESTFUNC(domain_eq_length),
905 
906     TESTFUNC(compress_full_match),
907     TESTFUNC(compress_full_match_subset),
908     TESTFUNC(compress_full_match_jump),
909     TESTFUNC(compress_no_match),
910     TESTFUNC(compress_2nd_label),
911     TESTFUNC(compress_2nd_label_short),
912     TESTFUNC(compress_jump_to_jump),
913     TESTFUNC(compress_long_match),
914   };
915   return create_suite("MDNS", tests, sizeof(tests)/sizeof(testfunc), NULL, NULL);
916 }
917