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