mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2025-01-26 09:35:23 +00:00
Apply patch #8755: Multicast DNS responder support from Erik Ekman
This commit is contained in:
parent
4af297fc20
commit
4919932c49
1
README
1
README
@ -28,6 +28,7 @@ FEATURES
|
||||
* raw/native API for enhanced performance
|
||||
* Optional Berkeley-like socket API
|
||||
* DNS (Domain names resolver)
|
||||
* MDNS (Multicast DNS) responder
|
||||
|
||||
|
||||
APPLICATIONS
|
||||
|
109
doc/mdns.txt
Normal file
109
doc/mdns.txt
Normal file
@ -0,0 +1,109 @@
|
||||
Multicast DNS for lwIP
|
||||
|
||||
Author: Erik Ekman
|
||||
|
||||
|
||||
Note! The MDNS responder does not have all features required by the standards.
|
||||
See notes in src/core/mdns.c for what is left. It is however usable in normal
|
||||
cases - but watch out if many devices on the same network try to use the same
|
||||
host/service instance names.
|
||||
|
||||
|
||||
How to enable:
|
||||
==============
|
||||
|
||||
MDNS support does not depend on DNS.
|
||||
MDNS supports using IPv4 only, v6 only, or v4+v6.
|
||||
|
||||
To enable MDNS responder, set
|
||||
LWIP_MDNS = 1
|
||||
in lwipopts.h and add src/core/mdns.c to your list of files to build.
|
||||
|
||||
The max number of services supported per netif is defined by MDNS_MAX_SERVICES,
|
||||
default is 1.
|
||||
|
||||
Increase MEMP_NUM_UDP_PCB. MDNS needs one PCB for IPv4 and one for IPv6.
|
||||
|
||||
MDNS with IPv4 requires LWIP_IGMP = 1, and preferably LWIP_AUTOIP = 1.
|
||||
MDNS with IPv6 requires LWIP_IPV6_MLD = 1, and that a link-local address is
|
||||
generated.
|
||||
|
||||
The MDNS code puts its structs on the stack where suitable to reduce dynamic
|
||||
memory allocation. It may use up to 1kB of stack.
|
||||
|
||||
MDNS needs a strncasecmp() implementation. If you have one, define
|
||||
LWIP_MDNS_STRNCASECMP to it. Otherwise the code will provide an implementation
|
||||
for you.
|
||||
|
||||
|
||||
How to use:
|
||||
===========
|
||||
|
||||
Call mdns_resp_init() during system initialization.
|
||||
This opens UDP sockets on port 5353 for IPv4 and IPv6.
|
||||
|
||||
|
||||
To start responding on a netif, run
|
||||
mdns_resp_add_netif(struct netif *netif, char *hostname, u32_t dns_ttl)
|
||||
|
||||
The hostname will be copied. If this returns successfully, the netif will join
|
||||
the multicast groups and any MDNS/legacy DNS requests sent unicast or multicast
|
||||
to port 5353 will be handled:
|
||||
- <hostname>.local type A, AAAA or ANY returns relevant IP addresses
|
||||
- Reverse lookups (PTR in-addr.arpa, ip6.arpa) of netif addresses
|
||||
returns <hostname>.local
|
||||
Answers will use the supplied TTL (in seconds)
|
||||
MDNS allows UTF-8 names, but it is recommended to stay within ASCII,
|
||||
since the default case-insensitive comparison assumes this.
|
||||
|
||||
It is recommended to call this function after an IPv4 address has been set,
|
||||
since there is currently no check if the v4 address is valid.
|
||||
|
||||
To stop responding on a netif, run
|
||||
mdns_resp_remove_netif(struct netif *netif)
|
||||
|
||||
|
||||
Adding services:
|
||||
================
|
||||
|
||||
The netif first needs to be registered. Then run
|
||||
mdns_resp_add_service(struct netif *netif, char *name, char *service,
|
||||
u16_t proto, u16_t port, u32_t dns_ttl,
|
||||
service_get_txt_fn_t txt_fn, void *txt_userdata);
|
||||
|
||||
The name and service pointers will be copied. Name refers to the name of the
|
||||
service instance, and service is the type of service, like _http
|
||||
proto can be DNSSD_PROTO_UDP or DNSSD_PROTO_TCP which represent _udp and _tcp.
|
||||
If this call returns successfully, the following queries will be answered:
|
||||
- _services._dns-sd._udp.local type PTR returns <service>.<proto>.local
|
||||
- <service>.<proto>.local type PTR returns <name>.<service>.<proto>.local
|
||||
- <name>.<service>.<proto>.local type SRV returns hostname and port of service
|
||||
- <name>.<service>.<proto>.local type TXT builds text strings by calling txt_fn
|
||||
with the supplied userdata. The callback adds strings to the reply by calling
|
||||
mdns_resp_add_service_txtitem(struct mdns_service *service, char *txt,
|
||||
int txt_len). Example callback method:
|
||||
|
||||
static void srv_txt(struct mdns_service *service, void *txt_userdata)
|
||||
{
|
||||
res = mdns_resp_add_service_txtitem(service, "path=/", 6);
|
||||
LWIP_ERROR("mdns add service txt failed\n", (res == ERR_OK), return);
|
||||
}
|
||||
|
||||
Since a hostname struct is used for TXT storage each single item can be max
|
||||
63 bytes long, and the total max length (including length bytes for each
|
||||
item) is 255 bytes.
|
||||
|
||||
If your device runs a webserver on port 80, an example call might be:
|
||||
|
||||
mdns_resp_add_service(netif, "myweb", "_http"
|
||||
DNSSD_PROTO_TCP, 80, 3600, srv_txt, NULL);
|
||||
|
||||
which will publish myweb._http._tcp.local for any hosts looking for web servers,
|
||||
and point them to <hostname>.local:80
|
||||
|
||||
Relevant information will be sent as additional records to reduce number of
|
||||
requests required from a client.
|
||||
|
||||
Removing services is currently not supported. Services are removed when the
|
||||
netif is removed.
|
||||
|
@ -158,6 +158,9 @@ LWIPERFFILES=$(LWIPDIR)/apps/lwiperf/lwiperf.c
|
||||
# SNTPFILES: SNTP client
|
||||
SNTPFILES=$(LWIPDIR)/apps/sntp/sntp.c
|
||||
|
||||
# MDNSFILES: MDNS responder
|
||||
MDNSFILES=$(LWIPDIR)/apps/mdns/mdns.c
|
||||
|
||||
# NETBIOSNSFILES: NetBIOS name server
|
||||
NETBIOSNSFILES=$(LWIPDIR)/apps/netbiosns/netbiosns.c
|
||||
|
||||
@ -166,4 +169,5 @@ LWIPAPPFILES=$(SNMPFILES) \
|
||||
$(HTTPDFILES) \
|
||||
$(LWIPERFFILES) \
|
||||
$(SNTPFILES) \
|
||||
$(MDNSFILES) \
|
||||
$(NETBIOSNSFILES)
|
||||
|
2044
src/apps/mdns/mdns.c
Normal file
2044
src/apps/mdns/mdns.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -247,6 +247,10 @@ netif_add(struct netif *netif,
|
||||
/* netif not under AutoIP control by default */
|
||||
netif->autoip = NULL;
|
||||
#endif /* LWIP_AUTOIP */
|
||||
#if LWIP_MDNS
|
||||
/* netif not using MDNS by default */
|
||||
netif->mdns = NULL;
|
||||
#endif /* LWIP_MDNS */
|
||||
#if LWIP_IPV6_AUTOCONFIG
|
||||
/* IPv6 address autoconfiguration not enabled by default */
|
||||
netif->ip6_autoconfig_enabled = 0;
|
||||
|
78
src/include/lwip/apps/mdns.h
Normal file
78
src/include/lwip/apps/mdns.h
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Verisure Innovation AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Erik Ekman <erik.ekman@verisure.com>
|
||||
*
|
||||
*/
|
||||
#ifndef LWIP_HDR_MDNS_H
|
||||
#define LWIP_HDR_MDNS_H
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#if LWIP_MDNS
|
||||
|
||||
#define DNSSD_PROTO_UDP 0
|
||||
#define DNSSD_PROTO_TCP 1
|
||||
|
||||
#define MDNS_LABEL_MAXLEN 63
|
||||
|
||||
struct mdns_host;
|
||||
struct mdns_service;
|
||||
|
||||
void mdns_resp_init(void);
|
||||
|
||||
err_t mdns_resp_add_netif(struct netif *netif, char *hostname, u32_t dns_ttl);
|
||||
err_t mdns_resp_remove_netif(struct netif *netif);
|
||||
|
||||
typedef void (*service_get_txt_fn_t)(struct mdns_service *service, void *txt_userdata);
|
||||
err_t mdns_resp_add_service(struct netif *netif, char *name, char *service, u16_t proto, u16_t port, u32_t dns_ttl, service_get_txt_fn_t txt_fn, void *txt_userdata);
|
||||
err_t mdns_resp_add_service_txtitem(struct mdns_service *service, char *txt, int txt_len);
|
||||
|
||||
|
||||
/* Domain struct and methods - visible for unit tests */
|
||||
#define MDNS_DOMAIN_MAXLEN 256
|
||||
#define MDNS_READNAME_ERROR 0xFFFF
|
||||
|
||||
struct mdns_domain {
|
||||
/* Encoded domain name */
|
||||
u8_t name[MDNS_DOMAIN_MAXLEN];
|
||||
/* Total length of domain name, including zero */
|
||||
u16_t length;
|
||||
/* Set if compression of this domain is not allowed */
|
||||
u8_t skip_compression;
|
||||
};
|
||||
|
||||
err_t mdns_domain_add_label(struct mdns_domain *domain, const char *label, unsigned len);
|
||||
u16_t mdns_readname(struct pbuf *p, u16_t offset, struct mdns_domain *domain);
|
||||
int mdns_domain_eq(struct mdns_domain *a, struct mdns_domain *b);
|
||||
u8_t mdns_compress_domain(struct pbuf *pbuf, u16_t *offset, struct mdns_domain *domain);
|
||||
|
||||
#endif /* LWIP_MDNS */
|
||||
|
||||
#endif /* LWIP_HDR_MDNS_H */
|
41
src/include/lwip/apps/mdns_opts.h
Normal file
41
src/include/lwip/apps/mdns_opts.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* File: mdns_opts.h
|
||||
* Author: dziegel
|
||||
*
|
||||
* Created on 13. August 2016, 09:17
|
||||
*/
|
||||
|
||||
#ifndef LWIP_HDR_APPS_MDNS_OPTS_H
|
||||
#define LWIP_HDR_APPS_MDNS_OPTS_H
|
||||
/**
|
||||
* @defgroup mdns_opts Options
|
||||
* @ingroup mdns
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* LWIP_MDNS==1: Turn on multicast DNS module. UDP must be available for MDNS
|
||||
* transport. IGMP is needed for IPv4 multicast.
|
||||
*/
|
||||
#ifndef LWIP_MDNS
|
||||
#define LWIP_MDNS 0
|
||||
#endif /* LWIP_MDNS */
|
||||
|
||||
/** The maximum number of services per netif */
|
||||
#ifndef MDNS_MAX_SERVICES
|
||||
#define MDNS_MAX_SERVICES 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MDNS_DEBUG: Enable debugging for multicast DNS.
|
||||
*/
|
||||
#ifndef MDNS_DEBUG
|
||||
#define MDNS_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* LWIP_HDR_APPS_MDNS_OPTS_H */
|
||||
|
@ -38,6 +38,7 @@
|
||||
#define LWIP_HDR_NETIF_H
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/apps/mdns_opts.h"
|
||||
|
||||
#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF)
|
||||
|
||||
@ -58,6 +59,9 @@ struct autoip;
|
||||
#if LWIP_IPV6_DHCP6
|
||||
struct dhcp6;
|
||||
#endif /* LWIP_IPV6_DHCP6 */
|
||||
#if LWIP_MDNS
|
||||
struct mdns_host;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -255,6 +259,10 @@ struct netif {
|
||||
/** the AutoIP client state information for this netif */
|
||||
struct autoip *autoip;
|
||||
#endif
|
||||
#if LWIP_MDNS
|
||||
/** Interface-specific info for multicast DNS */
|
||||
struct mdns_host *mdns;
|
||||
#endif /* LWIP_MDNS */
|
||||
#if LWIP_IPV6_AUTOCONFIG
|
||||
/** is this netif enabled for IPv6 autoconfiguration */
|
||||
u8_t ip6_autoconfig_enabled;
|
||||
|
@ -69,12 +69,15 @@ extern "C" {
|
||||
#define DNS_RRTYPE_MX 15 /* mail exchange */
|
||||
#define DNS_RRTYPE_TXT 16 /* text strings */
|
||||
#define DNS_RRTYPE_AAAA 28 /* IPv6 address */
|
||||
#define DNS_RRTYPE_SRV 33 /* service location */
|
||||
#define DNS_RRTYPE_ANY 255 /* any type */
|
||||
|
||||
/* DNS field CLASS used for "Resource Records" */
|
||||
#define DNS_RRCLASS_IN 1 /* the Internet */
|
||||
#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */
|
||||
#define DNS_RRCLASS_CH 3 /* the CHAOS class */
|
||||
#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */
|
||||
#define DNS_RRCLASS_ANY 255 /* any class */
|
||||
#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */
|
||||
|
||||
/* DNS protocol flags */
|
||||
@ -90,6 +93,8 @@ extern "C" {
|
||||
#define DNS_FLAG2_ERR_NONE 0x00
|
||||
#define DNS_FLAG2_ERR_NAME 0x03
|
||||
|
||||
#define DNS_HDR_GET_OPCODE(hdr) ((((hdr)->flags1) >> 3) & 0xF)
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
@ -122,5 +127,5 @@ typedef enum {
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DNS_H */
|
||||
#endif /* LWIP_HDR_PROT_DNS_H */
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "core/test_pbuf.h"
|
||||
#include "etharp/test_etharp.h"
|
||||
#include "dhcp/test_dhcp.h"
|
||||
#include "mdns/test_mdns.h"
|
||||
|
||||
#include "lwip/init.h"
|
||||
|
||||
@ -42,7 +43,8 @@ int main(void)
|
||||
mem_suite,
|
||||
pbuf_suite,
|
||||
etharp_suite,
|
||||
dhcp_suite
|
||||
dhcp_suite,
|
||||
mdns_suite
|
||||
};
|
||||
size_t num = sizeof(suites)/sizeof(void*);
|
||||
LWIP_ASSERT("No suites defined", num > 0);
|
||||
|
@ -51,6 +51,10 @@
|
||||
#define TCP_RCV_SCALE 0
|
||||
#define PBUF_POOL_SIZE 400 /* pbuf tests need ~200KByte */
|
||||
|
||||
/* Enable IGMP and MDNS for MDNS tests */
|
||||
#define LWIP_IGMP 1
|
||||
#define LWIP_MDNS 1
|
||||
|
||||
/* Minimal changes to opt.h required for etharp unit tests: */
|
||||
#define ETHARP_SUPPORT_STATIC_ENTRIES 1
|
||||
|
||||
|
887
test/unit/mdns/test_mdns.c
Normal file
887
test/unit/mdns/test_mdns.c
Normal file
@ -0,0 +1,887 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Verisure Innovation AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Erik Ekman <erik.ekman@verisure.com>
|
||||
*
|
||||
* Please coordinate changes and requests with Erik Ekman
|
||||
* <erik.ekman@verisure.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "test_mdns.h"
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/apps/mdns.h"
|
||||
|
||||
START_TEST(readname_basic)
|
||||
{
|
||||
static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 };
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
offset = mdns_readname(p, 0, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == sizeof(data));
|
||||
fail_unless(domain.length == sizeof(data));
|
||||
fail_if(memcmp(&domain.name, data, sizeof(data)));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_anydata)
|
||||
{
|
||||
static const u8_t data[] = { 0x05, 0x00, 0xFF, 0x08, 0xc0, 0x0f, 0x04, 0x7f, 0x80, 0x82, 0x88, 0x00 };
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
offset = mdns_readname(p, 0, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == sizeof(data));
|
||||
fail_unless(domain.length == sizeof(data));
|
||||
fail_if(memcmp(&domain.name, data, sizeof(data)));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_short_buf)
|
||||
{
|
||||
static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a' };
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
offset = mdns_readname(p, 0, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == MDNS_READNAME_ERROR);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_long_label)
|
||||
{ static const u8_t data[] = {
|
||||
0x05, 'm', 'u', 'l', 't', 'i',
|
||||
0x52, 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
|
||||
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
|
||||
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
|
||||
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
|
||||
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
|
||||
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 0x00,
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
offset = mdns_readname(p, 0, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == MDNS_READNAME_ERROR);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_overflow)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x00,
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
offset = mdns_readname(p, 0, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == MDNS_READNAME_ERROR);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_jump_earlier)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
/* Some padding needed, not supported to jump to bytes containing dns header */
|
||||
/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 10 */ 0x0f, 0x0e, 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xab,
|
||||
/* 20 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x0c,
|
||||
};
|
||||
static const u8_t fullname[] = {
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00,
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
offset = mdns_readname(p, 20, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == sizeof(data));
|
||||
fail_unless(domain.length == sizeof(fullname));
|
||||
|
||||
fail_if(memcmp(&domain.name, fullname, sizeof(fullname)));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_jump_earlier_jump)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
/* Some padding needed, not supported to jump to bytes containing dns header */
|
||||
/* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x03, 0x0b, 0x0a, 0xf2,
|
||||
/* 0x10 */ 0x04, 'c', 'a', 's', 't', 0x00, 0xc0, 0x10,
|
||||
/* 0x18 */ 0x05, 'm', 'u', 'l', 't', 'i', 0xc0, 0x16,
|
||||
};
|
||||
static const u8_t fullname[] = {
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00,
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
offset = mdns_readname(p, 0x18, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == sizeof(data));
|
||||
fail_unless(domain.length == sizeof(fullname));
|
||||
|
||||
fail_if(memcmp(&domain.name, fullname, sizeof(fullname)));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_jump_maxdepth)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
/* Some padding needed, not supported to jump to bytes containing dns header */
|
||||
/* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x03, 0x0b, 0x0a, 0xf2,
|
||||
/* 0x10 */ 0x04, 'n', 'a', 'm', 'e', 0xc0, 0x27, 0x03,
|
||||
/* 0x18 */ 0x03, 'd', 'n', 's', 0xc0, 0x10, 0xc0, 0x10,
|
||||
/* 0x20 */ 0x04, 'd', 'e', 'e', 'p', 0xc0, 0x18, 0x00,
|
||||
/* 0x28 */ 0x04, 'c', 'a', 's', 't', 0xc0, 0x20, 0xb0,
|
||||
/* 0x30 */ 0x05, 'm', 'u', 'l', 't', 'i', 0xc0, 0x28,
|
||||
};
|
||||
static const u8_t fullname[] = {
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x04, 'd', 'e', 'e', 'p', 0x03, 'd', 'n', 's',
|
||||
0x04, 'n', 'a', 'm', 'e', 0x00,
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
offset = mdns_readname(p, 0x30, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == sizeof(data));
|
||||
fail_unless(domain.length == sizeof(fullname));
|
||||
|
||||
fail_if(memcmp(&domain.name, fullname, sizeof(fullname)));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_jump_later)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
/* 0x00 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x10, 0x00, 0x01, 0x40,
|
||||
/* 0x10 */ 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xab,
|
||||
};
|
||||
static const u8_t fullname[] = {
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00,
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
offset = mdns_readname(p, 0, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == 13);
|
||||
fail_unless(domain.length == sizeof(fullname));
|
||||
|
||||
fail_if(memcmp(&domain.name, fullname, sizeof(fullname)));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_half_jump)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0,
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
offset = mdns_readname(p, 0, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == MDNS_READNAME_ERROR);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_jump_toolong)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc2, 0x10, 0x00, 0x01, 0x40,
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
offset = mdns_readname(p, 0, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == MDNS_READNAME_ERROR);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_jump_loop_label)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 10 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x10,
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
offset = mdns_readname(p, 10, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == MDNS_READNAME_ERROR);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_jump_loop_jump)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 10 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x15,
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
offset = mdns_readname(p, 10, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == MDNS_READNAME_ERROR);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(add_label_basic)
|
||||
{
|
||||
static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 };
|
||||
struct mdns_domain domain;
|
||||
err_t res;
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "multi", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, "cast", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == sizeof(data));
|
||||
fail_if(memcmp(&domain.name, data, sizeof(data)));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(add_label_long_label)
|
||||
{
|
||||
static const char *toolong = "abcdefghijklmnopqrstuvwxyz0123456789-abcdefghijklmnopqrstuvwxyz0123456789-abcdefghijklmnopqrstuvwxyz0123456789-";
|
||||
struct mdns_domain domain;
|
||||
err_t res;
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "multi", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, toolong, strlen(toolong));
|
||||
fail_unless(res == ERR_VAL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(add_label_full)
|
||||
{
|
||||
static const char *label = "0123456789abcdef0123456789abcdef";
|
||||
struct mdns_domain domain;
|
||||
err_t res;
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, label, strlen(label));
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == 33);
|
||||
res = mdns_domain_add_label(&domain, label, strlen(label));
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == 66);
|
||||
res = mdns_domain_add_label(&domain, label, strlen(label));
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == 99);
|
||||
res = mdns_domain_add_label(&domain, label, strlen(label));
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == 132);
|
||||
res = mdns_domain_add_label(&domain, label, strlen(label));
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == 165);
|
||||
res = mdns_domain_add_label(&domain, label, strlen(label));
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == 198);
|
||||
res = mdns_domain_add_label(&domain, label, strlen(label));
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == 231);
|
||||
res = mdns_domain_add_label(&domain, label, strlen(label));
|
||||
fail_unless(res == ERR_VAL);
|
||||
fail_unless(domain.length == 231);
|
||||
res = mdns_domain_add_label(&domain, label, 25);
|
||||
fail_unless(res == ERR_VAL);
|
||||
fail_unless(domain.length == 231);
|
||||
res = mdns_domain_add_label(&domain, label, 24);
|
||||
fail_unless(res == ERR_VAL);
|
||||
fail_unless(domain.length == 231);
|
||||
res = mdns_domain_add_label(&domain, label, 23);
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == 255);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == 256);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_VAL);
|
||||
fail_unless(domain.length == 256);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(domain_eq_basic)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00,
|
||||
};
|
||||
struct mdns_domain domain1, domain2;
|
||||
err_t res;
|
||||
|
||||
memset(&domain1, 0, sizeof(domain1));
|
||||
res = mdns_domain_add_label(&domain1, "multi", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, "cast", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain1.length == sizeof(data));
|
||||
|
||||
memset(&domain2, 0, sizeof(domain2));
|
||||
res = mdns_domain_add_label(&domain2, "multi", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, "cast", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
fail_unless(mdns_domain_eq(&domain1, &domain2));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(domain_eq_diff)
|
||||
{
|
||||
struct mdns_domain domain1, domain2;
|
||||
err_t res;
|
||||
|
||||
memset(&domain1, 0, sizeof(domain1));
|
||||
res = mdns_domain_add_label(&domain1, "multi", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, "base", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
memset(&domain2, 0, sizeof(domain2));
|
||||
res = mdns_domain_add_label(&domain2, "multi", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, "cast", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
fail_if(mdns_domain_eq(&domain1, &domain2));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(domain_eq_case)
|
||||
{
|
||||
struct mdns_domain domain1, domain2;
|
||||
err_t res;
|
||||
|
||||
memset(&domain1, 0, sizeof(domain1));
|
||||
res = mdns_domain_add_label(&domain1, "multi", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, "cast", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
memset(&domain2, 0, sizeof(domain2));
|
||||
res = mdns_domain_add_label(&domain2, "MulTI", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, "casT", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
fail_unless(mdns_domain_eq(&domain1, &domain2));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(domain_eq_anydata)
|
||||
{
|
||||
static const char data1[] = { 0x05, (char)0xcc, (char)0xdc, 0x00, (char)0xa0 };
|
||||
static const char data2[] = { 0x7f, (char)0x8c, 0x01, (char)0xff, (char)0xcf };
|
||||
struct mdns_domain domain1, domain2;
|
||||
err_t res;
|
||||
|
||||
memset(&domain1, 0, sizeof(domain1));
|
||||
res = mdns_domain_add_label(&domain1, data1, sizeof(data1));
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, "cast", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, data2, sizeof(data2));
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
memset(&domain2, 0, sizeof(domain2));
|
||||
res = mdns_domain_add_label(&domain2, data1, sizeof(data1));
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, "casT", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, data2, sizeof(data2));
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
fail_unless(mdns_domain_eq(&domain1, &domain2));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(domain_eq_length)
|
||||
{
|
||||
struct mdns_domain domain1, domain2;
|
||||
err_t res;
|
||||
|
||||
memset(&domain1, 0, sizeof(domain1));
|
||||
memset(domain1.name, 0xAA, sizeof(MDNS_DOMAIN_MAXLEN));
|
||||
res = mdns_domain_add_label(&domain1, "multi", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, "cast", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
memset(&domain2, 0, sizeof(domain2));
|
||||
memset(domain2.name, 0xBB, sizeof(MDNS_DOMAIN_MAXLEN));
|
||||
res = mdns_domain_add_label(&domain2, "multi", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, "cast", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
fail_unless(mdns_domain_eq(&domain1, &domain2));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(compress_full_match)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x00, 0x00,
|
||||
0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
u8_t length;
|
||||
err_t res;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "foobar", 6);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, "local", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
offset = 2;
|
||||
length = mdns_compress_domain(p, &offset, &domain);
|
||||
/* Write 0 bytes, then a jump to addr 2 */
|
||||
fail_unless(length == 0);
|
||||
fail_unless(offset == 2);
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(compress_full_match_subset)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x00, 0x00,
|
||||
0x02, 'g', 'o', 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
u8_t length;
|
||||
err_t res;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "foobar", 6);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, "local", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
offset = 2;
|
||||
length = mdns_compress_domain(p, &offset, &domain);
|
||||
/* Write 0 bytes, then a jump to addr 5 */
|
||||
fail_unless(length == 0);
|
||||
fail_unless(offset == 5);
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(compress_full_match_jump)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
/* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
/* 0x10 */ 0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xc0, 0x00, 0x02, 0x00,
|
||||
/* 0x20 */ 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0xc0, 0x15,
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
u8_t length;
|
||||
err_t res;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "foobar", 6);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, "local", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
offset = 0x20;
|
||||
length = mdns_compress_domain(p, &offset, &domain);
|
||||
/* Write 0 bytes, then a jump to addr 0x20 */
|
||||
fail_unless(length == 0);
|
||||
fail_unless(offset == 0x20);
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(compress_no_match)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x00, 0x00,
|
||||
0x04, 'l', 'w', 'i', 'p', 0x05, 'w', 'i', 'k', 'i', 'a', 0x03, 'c', 'o', 'm', 0x00
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
u8_t length;
|
||||
err_t res;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "foobar", 6);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, "local", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
offset = 2;
|
||||
length = mdns_compress_domain(p, &offset, &domain);
|
||||
/* Write all bytes, no jump */
|
||||
fail_unless(length == domain.length);
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(compress_2nd_label)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x00, 0x00,
|
||||
0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
u8_t length;
|
||||
err_t res;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "lwip", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, "local", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
offset = 2;
|
||||
length = mdns_compress_domain(p, &offset, &domain);
|
||||
/* Write 5 bytes, then a jump to addr 9 */
|
||||
fail_unless(length == 5);
|
||||
fail_unless(offset == 9);
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(compress_2nd_label_short)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x00, 0x00,
|
||||
0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
u8_t length;
|
||||
err_t res;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "foobar", 6);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, "local", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
offset = 2;
|
||||
length = mdns_compress_domain(p, &offset, &domain);
|
||||
/* Write 5 bytes, then a jump to addr 7 */
|
||||
fail_unless(length == 7);
|
||||
fail_unless(offset == 7);
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(compress_jump_to_jump)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
/* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
/* 0x10 */ 0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xc0, 0x00, 0x02, 0x00,
|
||||
/* 0x20 */ 0x07, 'b', 'a', 'n', 'a', 'n', 'a', 's', 0xc0, 0x15,
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
u8_t length;
|
||||
err_t res;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "foobar", 6);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, "local", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
offset = 0x20;
|
||||
length = mdns_compress_domain(p, &offset, &domain);
|
||||
/* Dont compress if jump would be to a jump */
|
||||
fail_unless(length == domain.length);
|
||||
|
||||
offset = 0x10;
|
||||
length = mdns_compress_domain(p, &offset, &domain);
|
||||
/* Write 7 bytes, then a jump to addr 0x15 */
|
||||
fail_unless(length == 7);
|
||||
fail_unless(offset == 0x15);
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(compress_long_match)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x00, 0x00,
|
||||
0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x03, 'c', 'o', 'm', 0x00
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
u8_t length;
|
||||
err_t res;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
p->payload = (void *)(size_t)data;
|
||||
fail_if(p == NULL);
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "foobar", 6);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, "local", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
offset = 2;
|
||||
length = mdns_compress_domain(p, &offset, &domain);
|
||||
fail_unless(length == domain.length);
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite* mdns_suite(void)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
TESTFUNC(readname_basic),
|
||||
TESTFUNC(readname_anydata),
|
||||
TESTFUNC(readname_short_buf),
|
||||
TESTFUNC(readname_long_label),
|
||||
TESTFUNC(readname_overflow),
|
||||
TESTFUNC(readname_jump_earlier),
|
||||
TESTFUNC(readname_jump_earlier_jump),
|
||||
TESTFUNC(readname_jump_maxdepth),
|
||||
TESTFUNC(readname_jump_later),
|
||||
TESTFUNC(readname_half_jump),
|
||||
TESTFUNC(readname_jump_toolong),
|
||||
TESTFUNC(readname_jump_loop_label),
|
||||
TESTFUNC(readname_jump_loop_jump),
|
||||
|
||||
TESTFUNC(add_label_basic),
|
||||
TESTFUNC(add_label_long_label),
|
||||
TESTFUNC(add_label_full),
|
||||
|
||||
TESTFUNC(domain_eq_basic),
|
||||
TESTFUNC(domain_eq_diff),
|
||||
TESTFUNC(domain_eq_case),
|
||||
TESTFUNC(domain_eq_anydata),
|
||||
TESTFUNC(domain_eq_length),
|
||||
|
||||
TESTFUNC(compress_full_match),
|
||||
TESTFUNC(compress_full_match_subset),
|
||||
TESTFUNC(compress_full_match_jump),
|
||||
TESTFUNC(compress_no_match),
|
||||
TESTFUNC(compress_2nd_label),
|
||||
TESTFUNC(compress_2nd_label_short),
|
||||
TESTFUNC(compress_jump_to_jump),
|
||||
TESTFUNC(compress_long_match),
|
||||
};
|
||||
return create_suite("MDNS", tests, sizeof(tests)/sizeof(testfunc), NULL, NULL);
|
||||
}
|
8
test/unit/mdns/test_mdns.h
Normal file
8
test/unit/mdns/test_mdns.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef LWIP_HDR_TEST_MDNS_H__
|
||||
#define LWIP_HDR_TEST_MDNS_H__
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite* mdns_suite(void);
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user