blob: 180d6b916205dbbac1e1fa740f084041eeb2c5ec [file] [log] [blame]
/*
* Copyright (c) 2020 Friedt Professional Engineering Services, Inc
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdbool.h>
#include <stdint.h>
#include <ztest.h>
#include <net/dns_sd.h>
#include <net/net_context.h>
#include <net/net_pkt.h>
#include "dns_pack.h"
#include "dns_sd.h"
#define BUFSZ 256
#define IP_ADDR(a, b, c, d) ((uint32_t) \
0 \
| ((a & 0xff) << 24) \
| ((b & 0xff) << 16) \
| ((c & 0xff) << 8) \
| ((d & 0xff) << 0) \
)
extern bool label_is_valid(const char *label, size_t label_size);
extern int add_a_record(const struct dns_sd_rec *inst, uint32_t ttl,
uint16_t host_offset, uint32_t addr,
uint8_t *buf,
uint16_t buf_offset, uint16_t buf_size);
extern int add_ptr_record(const struct dns_sd_rec *inst, uint32_t ttl,
uint8_t *buf, uint16_t buf_offset,
uint16_t buf_size,
uint16_t *service_offset,
uint16_t *instance_offset,
uint16_t *domain_offset);
extern int add_txt_record(const struct dns_sd_rec *inst, uint32_t ttl,
uint16_t instance_offset, uint8_t *buf,
uint16_t buf_offset, uint16_t buf_size);
extern int add_aaaa_record(const struct dns_sd_rec *inst, uint32_t ttl,
uint16_t host_offset, const uint8_t addr[16],
uint8_t *buf, uint16_t buf_offset,
uint16_t buf_size);
extern int add_srv_record(const struct dns_sd_rec *inst, uint32_t ttl,
uint16_t instance_offset,
uint16_t domain_offset,
uint8_t *buf, uint16_t buf_offset,
uint16_t buf_size,
uint16_t *host_offset);
extern size_t service_proto_size(const struct dns_sd_rec *ref);
extern bool rec_is_valid(const struct dns_sd_rec *ref);
extern int setup_dst_addr(struct net_context *ctx, struct net_pkt *pkt,
struct sockaddr *dst, socklen_t *dst_len);
/** Text for advertised service */
static const uint8_t nasxxxxxx_text[] = "\x06" "path=/";
/** A completely invalid record */
DNS_SD_REGISTER_SERVICE(invalid_dns_sd_record, NULL, NULL,
NULL, NULL, NULL, NULL);
/* initialized to zero for illustrative purposes */
static uint16_t nonconst_port;
DNS_SD_REGISTER_SERVICE(nasxxxxxx_ephemeral, "NASXXXXXX", "_http",
"_tcp", "local", nasxxxxxx_text, &nonconst_port);
/** Sample advertised service */
#define CONST_PORT 8080
DNS_SD_REGISTER_TCP_SERVICE(nasxxxxxx, "NASXXXXXX", "_http",
"local", nasxxxxxx_text, CONST_PORT);
/** Buffer for DNS queries */
static uint8_t create_query_buf[BUFSZ];
/**
* @brief Create a DNS query
*
* @param inst the service instance to query
* @param the type of DNS Resource Record to query
* @param[out] size the size of the resulting query
*
* @return on success a pointer to the buffer containing the query
* @return NULL on failure
*/
static uint8_t *create_query(const struct dns_sd_rec *inst,
uint8_t rr_type, size_t *size)
{
uint16_t offs = 0;
uint8_t label_size;
uint16_t sp_size = service_proto_size(inst);
uint16_t expected_req_buf_size = 0
+ sizeof(struct dns_header)
+ sp_size
+ sizeof(struct dns_query);
struct dns_header *hdr =
(struct dns_header *)&create_query_buf[0];
hdr->id = htons(0);
hdr->qdcount = htons(1);
offs += sizeof(struct dns_header);
label_size = strlen(inst->service);
create_query_buf[offs++] = label_size;
memcpy(&create_query_buf[offs], inst->service, label_size);
offs += label_size;
label_size = strlen(inst->proto);
create_query_buf[offs++] = label_size;
memcpy(&create_query_buf[offs], inst->proto, label_size);
offs += label_size;
label_size = strlen(inst->domain);
create_query_buf[offs++] = label_size;
memcpy(&create_query_buf[offs], inst->domain, label_size);
offs += label_size;
create_query_buf[offs++] = '\0';
struct dns_query *query =
(struct dns_query *)&create_query_buf[offs];
query->type = htons(rr_type);
query->class_ = htons(DNS_CLASS_IN);
offs += sizeof(struct dns_query);
zassert_equal(expected_req_buf_size, offs,
"sz: %zu offs: %u", expected_req_buf_size, offs);
*size = offs;
return create_query_buf;
}
/** Test for @ref label_is_valid */
static void test_label_is_valid(void)
{
zassert_equal(false, label_is_valid(NULL,
DNS_LABEL_MIN_SIZE), "");
zassert_equal(false, label_is_valid("",
DNS_LABEL_MIN_SIZE - 1),
"");
zassert_equal(false, label_is_valid(
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
DNS_LABEL_MAX_SIZE + 1), "");
zassert_equal(true, label_is_valid("a",
DNS_LABEL_MIN_SIZE), "");
zassert_equal(true, label_is_valid(
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
DNS_LABEL_MAX_SIZE), "");
zassert_equal(false, label_is_valid("9abc", 4), "");
zassert_equal(true, label_is_valid("a9bc", 4), "");
zassert_equal(false, label_is_valid("-abc", 4), "");
zassert_equal(true, label_is_valid("a-bc", 4), "");
zassert_equal(true, label_is_valid("A-Bc", 4), "");
}
/** Test for @ref dns_sd_rec_is_valid */
static void test_dns_sd_rec_is_valid(void)
{
DNS_SD_REGISTER_TCP_SERVICE(name_min,
"x",
"_x",
"xx",
DNS_SD_EMPTY_TXT,
CONST_PORT);
zassert_equal(true, rec_is_valid(&name_min), "");
DNS_SD_REGISTER_TCP_SERVICE(name_max,
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"_xxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
DNS_SD_EMPTY_TXT,
CONST_PORT);
zassert_equal(true, rec_is_valid(&name_max), "");
DNS_SD_REGISTER_TCP_SERVICE(label_too_small,
"x",
"_",
"xx",
DNS_SD_EMPTY_TXT,
CONST_PORT);
zassert_equal(false, rec_is_valid(&label_too_small), "");
DNS_SD_REGISTER_TCP_SERVICE(label_too_big,
"x",
"_x",
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
DNS_SD_EMPTY_TXT,
CONST_PORT);
zassert_equal(false, rec_is_valid(&label_too_big), "");
DNS_SD_REGISTER_TCP_SERVICE(invalid_instance,
"abc" "\x01" "def",
"_x",
"xx",
DNS_SD_EMPTY_TXT,
CONST_PORT);
zassert_equal(false, rec_is_valid(&invalid_instance), "");
DNS_SD_REGISTER_TCP_SERVICE(invalid_service_prefix,
"x",
"xx",
"xx",
DNS_SD_EMPTY_TXT,
CONST_PORT);
zassert_equal(false, rec_is_valid(
&invalid_service_prefix), "");
DNS_SD_REGISTER_TCP_SERVICE(invalid_service,
"x",
"_x.y",
"xx",
DNS_SD_EMPTY_TXT,
CONST_PORT);
zassert_equal(false, rec_is_valid(&invalid_service), "");
DNS_SD_REGISTER_SERVICE(invalid_proto,
"x",
"_y",
"_wtf",
"xx",
DNS_SD_EMPTY_TXT,
&nonconst_port);
zassert_equal(false, rec_is_valid(&invalid_proto), "");
/* We do not currently support subdomains */
DNS_SD_REGISTER_TCP_SERVICE(invalid_domain,
"x",
"_x",
"x.y",
DNS_SD_EMPTY_TXT,
CONST_PORT);
zassert_equal(false, rec_is_valid(&invalid_domain), "");
zassert_equal(true, rec_is_valid(&nasxxxxxx), "");
}
/** Test for @ref creqte_query */
static void test_create_query(void)
{
size_t actual_query_size = -1;
uint8_t *actual_query = create_query(&nasxxxxxx,
DNS_RR_TYPE_PTR,
&actual_query_size);
uint8_t expected_query[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x05, 0x5f, 0x68, 0x74,
0x74, 0x70, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05,
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c,
0x00, 0x01
};
size_t expected_query_size = sizeof(expected_query);
zassert_equal(actual_query_size, expected_query_size, "");
zassert_mem_equal(expected_query, actual_query,
MIN(actual_query_size, expected_query_size),
"");
}
/** Test for @ref add_ptr_record */
static void test_add_ptr_record(void)
{
const uint32_t ttl = DNS_SD_PTR_TTL;
const uint32_t offset = sizeof(struct dns_header);
uint16_t service_offset = -1;
uint16_t instance_offset = -1;
uint16_t domain_offset = -1;
static uint8_t actual_buf[BUFSZ];
static const uint8_t expected_buf[] = {
0x05, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x04, 0x5f,
0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00,
0x11, 0x94, 0x00, 0x0c, 0x09, 0x4e, 0x41, 0x53,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc0, 0x0c,
};
int expected_int = sizeof(expected_buf);
int actual_int = add_ptr_record(&nasxxxxxx, ttl,
actual_buf, offset,
sizeof(actual_buf),
&service_offset,
&instance_offset,
&domain_offset);
zassert_equal(actual_int, expected_int, "");
zassert_equal(instance_offset, 40, "");
zassert_equal(domain_offset, 23, "");
memmove(actual_buf, actual_buf + offset, actual_int);
zassert_mem_equal(actual_buf, expected_buf,
MIN(actual_int, expected_int), "");
/* dns_sd_rec_is_valid failure */
DNS_SD_REGISTER_TCP_SERVICE(null_label,
NULL,
"_x",
"xx",
DNS_SD_EMPTY_TXT,
CONST_PORT);
zassert_equal(-EINVAL, add_ptr_record(&null_label, ttl,
actual_buf, offset,
actual_int,
&service_offset,
&instance_offset,
&domain_offset), "");
/* buffer too small failure */
zassert_equal(-ENOSPC, add_ptr_record(&nasxxxxxx, ttl,
actual_buf, offset, 0,
&service_offset,
&instance_offset,
&domain_offset), "");
/* offset too big for message compression (service) */
zassert_equal(-E2BIG, add_ptr_record(&nasxxxxxx, ttl,
actual_buf, DNS_SD_PTR_MASK,
0xffff, &service_offset,
&instance_offset,
&domain_offset), "");
/* offset too big for message compression (instance) */
zassert_equal(-E2BIG, add_ptr_record(&nasxxxxxx, ttl,
actual_buf, 0x3fff,
0xffff, &service_offset,
&instance_offset,
&domain_offset), "");
}
/** Test for @ref add_txt_record */
static void test_add_txt_record(void)
{
const uint32_t ttl = DNS_SD_TXT_TTL;
const uint32_t offset = 0;
const uint16_t instance_offset = 0x28;
static uint8_t actual_buf[BUFSZ];
static const uint8_t expected_buf[] = {
0xc0, 0x28, 0x00, 0x10, 0x80, 0x01, 0x00, 0x00,
0x11, 0x94, 0x00, 0x07, 0x06, 0x70, 0x61, 0x74,
0x68, 0x3d, 0x2f
};
int expected_int = sizeof(expected_buf);
int actual_int = add_txt_record(&nasxxxxxx, ttl,
instance_offset, actual_buf,
offset,
sizeof(actual_buf));
zassert_equal(actual_int, expected_int, "");
zassert_mem_equal(actual_buf, expected_buf, MIN(actual_int,
expected_int),
"");
/* too big for message compression */
zassert_equal(-E2BIG,
add_txt_record(&nasxxxxxx, ttl, DNS_SD_PTR_MASK,
actual_buf, offset,
sizeof(actual_buf)), "");
/* buffer too small */
zassert_equal(-ENOSPC, add_txt_record(&nasxxxxxx, ttl, offset,
actual_buf, offset,
0), "");
}
/** Test for @ref add_srv_record */
static void test_add_srv_record(void)
{
const uint32_t ttl = DNS_SD_SRV_TTL;
const uint32_t offset = 0;
const uint16_t instance_offset = 0x28;
const uint16_t domain_offset = 0x17;
uint16_t host_offset = -1;
static uint8_t actual_buf[BUFSZ];
static const uint8_t expected_buf[] = {
0xc0, 0x28, 0x00, 0x21, 0x80, 0x01, 0x00, 0x00,
0x00, 0x78, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00,
0x1f, 0x90, 0x09, 0x4e, 0x41, 0x53, 0x58, 0x58,
0x58, 0x58, 0x58, 0x58, 0xc0, 0x17
};
int expected_int = sizeof(expected_buf);
int actual_int = add_srv_record(&nasxxxxxx, ttl,
instance_offset, domain_offset,
actual_buf,
offset, sizeof(actual_buf),
&host_offset);
zassert_equal(actual_int, expected_int, "");
zassert_equal(host_offset, 18, "");
zassert_mem_equal(actual_buf, expected_buf,
MIN(actual_int, expected_int), "");
/* offset too big for message compression (instance) */
zassert_equal(-E2BIG,
add_srv_record(&nasxxxxxx, ttl, DNS_SD_PTR_MASK,
domain_offset,
actual_buf, offset,
sizeof(actual_buf),
&host_offset), "");
/* offset too big for message compression (domain) */
zassert_equal(-E2BIG, add_srv_record(&nasxxxxxx, ttl,
instance_offset,
DNS_SD_PTR_MASK,
actual_buf, offset,
sizeof(actual_buf),
&host_offset), "");
/* buffer too small */
zassert_equal(-ENOSPC, add_srv_record(&nasxxxxxx, ttl,
instance_offset,
domain_offset,
actual_buf,
offset, 0,
&host_offset), "");
}
/** Test for @ref add_a_record */
static void test_add_a_record(void)
{
const uint32_t ttl = DNS_SD_A_TTL;
const uint32_t offset = 0;
const uint16_t host_offset = 0x59;
/* this one is made up */
const uint32_t addr = IP_ADDR(177, 5, 240, 13);
static uint8_t actual_buf[BUFSZ];
static const uint8_t expected_buf[] = {
0xc0, 0x59, 0x00, 0x01, 0x80, 0x01, 0x00, 0x00,
0x00, 0x78, 0x00, 0x04, 0xb1, 0x05, 0xf0, 0x0d,
};
int expected_int = sizeof(expected_buf);
int actual_int = add_a_record(&nasxxxxxx, ttl, host_offset,
addr, actual_buf, offset,
sizeof(actual_buf));
zassert_equal(actual_int, expected_int, "");
zassert_mem_equal(actual_buf, expected_buf,
MIN(actual_int, expected_int), "");
/* test offset too large */
zassert_equal(-E2BIG,
add_a_record(&nasxxxxxx, ttl, DNS_SD_PTR_MASK,
addr, actual_buf, offset,
sizeof(actual_buf)), "");
/* test buffer too small */
zassert_equal(-ENOSPC, add_a_record(&nasxxxxxx, ttl,
host_offset, addr,
actual_buf, offset,
0), "");
}
/** Test for @ref add_aaaa_record */
static void test_add_aaaa_record(void)
{
const uint32_t ttl = DNS_SD_AAAA_TTL;
const uint32_t offset = 0;
const uint16_t host_offset = 0x59;
/* this one is made up */
const uint8_t addr[16] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
};
static uint8_t actual_buf[BUFSZ];
static const uint8_t expected_buf[] = {
0xc0, 0x59, 0x00, 0x1c, 0x80, 0x01, 0x00, 0x00,
0x00, 0x78, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01,
};
int expected_int = sizeof(expected_buf);
int actual_int = add_aaaa_record(&nasxxxxxx, ttl, host_offset,
addr, actual_buf, offset,
sizeof(actual_buf));
zassert_equal(actual_int, expected_int, "");
zassert_mem_equal(actual_buf, expected_buf,
MIN(actual_int, expected_int), "");
/* offset too large for message compression */
zassert_equal(-E2BIG,
add_aaaa_record(&nasxxxxxx, ttl, DNS_SD_PTR_MASK,
addr, actual_buf,
offset,
sizeof(actual_buf)), "");
/* buffer too small */
zassert_equal(-ENOSPC,
add_aaaa_record(&nasxxxxxx, ttl, host_offset,
addr, actual_buf,
offset, 0), "");
}
/** Test for @ref dns_sd_handle_ptr_query */
static void test_dns_sd_handle_ptr_query(void)
{
struct in_addr addr = {
.s_addr = htonl(IP_ADDR(177, 5, 240, 13)),
};
static uint8_t actual_rsp[512];
static uint8_t expected_rsp[] = {
0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x03, 0x05, 0x5f, 0x68, 0x74,
0x74, 0x70, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05,
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c,
0x00, 0x01, 0x00, 0x00, 0x11, 0x94, 0x00, 0x0c,
0x09, 0x4e, 0x41, 0x53, 0x58, 0x58, 0x58, 0x58,
0x58, 0x58, 0xc0, 0x0c, 0xc0, 0x28, 0x00, 0x10,
0x80, 0x01, 0x00, 0x00, 0x11, 0x94, 0x00, 0x07,
0x06, 0x70, 0x61, 0x74, 0x68, 0x3d, 0x2f, 0xc0,
0x28, 0x00, 0x21, 0x80, 0x01, 0x00, 0x00, 0x00,
0x78, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x1f,
0x90, 0x09, 0x4e, 0x41, 0x53, 0x58, 0x58, 0x58,
0x58, 0x58, 0x58, 0xc0, 0x17, 0xc0, 0x59, 0x00,
0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00,
0x04, 0xb1, 0x05, 0xf0, 0x0d,
};
int expected_int = sizeof(expected_rsp);
int actual_int = dns_sd_handle_ptr_query(&nasxxxxxx,
&addr,
NULL,
&actual_rsp[0],
sizeof(actual_rsp) -
sizeof(struct dns_header));
zassert_true(actual_int > 0,
"dns_sd_handle_ptr_query() failed (%d)",
actual_int);
zassert_equal(actual_int, expected_int, "act: %d exp: %d", actual_int, expected_int);
zassert_mem_equal(actual_rsp, expected_rsp,
MIN(actual_int, expected_int), "");
/* show non-advertisement for uninitialized port */
nonconst_port = 0;
zassert_equal(-EHOSTDOWN, dns_sd_handle_ptr_query(&nasxxxxxx_ephemeral,
&addr, NULL, &actual_rsp[0], sizeof(actual_rsp) -
sizeof(struct dns_header)), "port zero should not "
"produce any DNS-SD query response");
/* show advertisement for initialized port */
nonconst_port = CONST_PORT;
expected_int = sizeof(expected_rsp);
zassert_equal(expected_int, dns_sd_handle_ptr_query(&nasxxxxxx_ephemeral,
&addr, NULL, &actual_rsp[0], sizeof(actual_rsp) -
sizeof(struct dns_header)), "");
zassert_equal(-EINVAL, dns_sd_handle_ptr_query(
&invalid_dns_sd_record,
&addr, NULL, &actual_rsp[0], sizeof(actual_rsp) -
sizeof(struct dns_header)), "");
}
/** Test for @ref dns_sd_handle_ptr_query */
static void test_dns_sd_handle_service_type_enum(void)
{
DNS_SD_REGISTER_TCP_SERVICE(chromecast,
"Chromecast-abcd",
"_googlecast",
"local",
DNS_SD_EMPTY_TXT,
CONST_PORT);
struct in_addr addr = {
.s_addr = htonl(IP_ADDR(177, 5, 240, 13)),
};
static uint8_t actual_rsp[512];
static uint8_t expected_rsp[] = {
0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x09, 0x5f, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x07, 0x5f, 0x64, 0x6e, 0x73,
0x2d, 0x73, 0x64, 0x04, 0x5f, 0x75, 0x64, 0x70, 0x05,
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00,
0x01, 0x00, 0x00, 0x11, 0x94, 0x00, 0x13, 0x0b, 0x5f,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73,
0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, 0xc0, 0x23,
};
int expected_int = sizeof(expected_rsp);
int actual_int = dns_sd_handle_service_type_enum(&chromecast,
&addr,
NULL,
&actual_rsp[0],
sizeof(actual_rsp) -
sizeof(struct dns_header));
zassert_true(actual_int > 0, "dns_sd_handle_service_type_enum() failed (%d)", actual_int);
zassert_equal(actual_int, expected_int, "act: %d exp: %d", actual_int, expected_int);
zassert_mem_equal(actual_rsp, expected_rsp, MIN(actual_int, expected_int), "");
/* show non-advertisement for uninitialized port */
nonconst_port = 0;
zassert_equal(-EHOSTDOWN,
dns_sd_handle_service_type_enum(&nasxxxxxx_ephemeral, &addr, NULL,
&actual_rsp[0], sizeof(actual_rsp) - sizeof(struct dns_header)),
"port zero should not "
"produce any DNS-SD query response");
zassert_equal(-EINVAL,
dns_sd_handle_service_type_enum(&invalid_dns_sd_record, &addr, NULL,
&actual_rsp[0], sizeof(actual_rsp) - sizeof(struct dns_header)),
"");
}
/** Test @ref dns_sd_rec_match */
static void test_dns_sd_rec_match(void)
{
DNS_SD_REGISTER_TCP_SERVICE(record,
"NGINX",
"_http",
"local",
DNS_SD_EMPTY_TXT,
CONST_PORT);
static const struct dns_sd_rec filter_ok = {
.instance = NULL,
.service = "_http",
.proto = "_tcp",
.domain = NULL,
.text = NULL,
.text_size = 0,
.port = NULL,
};
static const struct dns_sd_rec filter_nok = {
.instance = NULL,
.service = "_wtftp",
.proto = "_udp",
.domain = NULL,
.text = NULL,
.text_size = 0,
.port = NULL,
};
zassert_equal(false, dns_sd_rec_match(NULL, NULL), "");
zassert_equal(false, dns_sd_rec_match(NULL, &filter_ok), "");
zassert_equal(false, dns_sd_rec_match(&record, NULL), "");
zassert_equal(false, dns_sd_rec_match(&record, &filter_nok), "");
zassert_equal(true, dns_sd_rec_match(&record, &filter_ok), "");
}
/** Test @ref setup_dst_addr */
static void test_setup_dst_addr(void)
{
int ret;
struct net_if *iface;
struct sockaddr dst;
socklen_t dst_len;
iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY));
zassert_not_null(iface, "Interface not available");
/* IPv4 case */
struct net_context *ctx_v4;
struct net_pkt *pkt_v4;
struct in_addr addr_v4_expect = { { { 224, 0, 0, 251 } } };
memset(&dst, 0, sizeof(struct sockaddr));
ret = net_context_get(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &ctx_v4);
zassert_equal(ret, 0, "Create IPv4 UDP context failed");
pkt_v4 = net_pkt_alloc_with_buffer(iface, 0, AF_INET,
IPPROTO_UDP, K_SECONDS(1));
zassert_not_null(pkt_v4, "Packet alloc failed");
zassert_equal(0, setup_dst_addr(ctx_v4, pkt_v4, &dst, &dst_len), "");
zassert_equal(255, ctx_v4->ipv4_ttl, "");
zassert_true(net_ipv4_addr_cmp(&addr_v4_expect,
&net_sin(&dst)->sin_addr), "");
zassert_equal(8, dst_len, "");
#if defined(CONFIG_NET_IPV6)
/* IPv6 case */
struct net_context *ctx_v6;
struct net_pkt *pkt_v6;
struct in6_addr addr_v6_expect = { { { 0xff, 0x02, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0xfb } } };
memset(&dst, 0, sizeof(struct sockaddr));
ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &ctx_v6);
zassert_equal(ret, 0, "Create IPv6 UDP context failed");
pkt_v6 = net_pkt_alloc_with_buffer(iface, 0, AF_INET6,
IPPROTO_UDP, K_SECONDS(1));
zassert_not_null(pkt_v6, "Packet alloc failed");
zassert_equal(0, setup_dst_addr(ctx_v6, pkt_v6, &dst, &dst_len), "");
zassert_equal(255, ctx_v6->ipv6_hop_limit, "");
zassert_true(net_ipv6_addr_cmp(&addr_v6_expect,
&net_sin6(&dst)->sin6_addr), "");
zassert_equal(24, dst_len, "");
#endif
/* Unknown family case */
struct net_context *ctx_xx;
struct net_pkt *pkt_xx;
ret = net_context_get(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &ctx_xx);
zassert_equal(ret, 0, "Create IPV4 udp context failed");
pkt_xx = net_pkt_alloc_with_buffer(iface, 0, AF_PACKET,
IPPROTO_UDP, K_SECONDS(1));
zassert_not_null(pkt_xx, "Packet alloc failed");
zassert_equal(-EPFNOSUPPORT,
setup_dst_addr(ctx_xx, pkt_xx, &dst, &dst_len), "");
}
/** test for @ref dns_sd_is_service_type_enumeration */
static void test_is_service_type_enumeration(void)
{
static const struct dns_sd_rec filter_ok = {
.instance = "_services",
.service = "_dns-sd",
.proto = "_udp",
/* TODO: support additional service domains */
.domain = "local",
.text = dns_sd_empty_txt,
.text_size = sizeof(dns_sd_empty_txt),
.port = &dns_sd_port_zero,
};
zassert_true(dns_sd_is_service_type_enumeration(&filter_ok), "");
static const struct dns_sd_rec filter_nok = {
/* not a service_type_enumeration */
.instance = "_serv1c3s", .service = "_dns-sd",
.proto = "_udp", .domain = "local",
.text = dns_sd_empty_txt, .text_size = sizeof(dns_sd_empty_txt),
.port = &dns_sd_port_zero,
};
zassert_false(dns_sd_is_service_type_enumeration(&filter_nok), "");
}
static void test_extract_service_type_enumeration(void)
{
static const uint8_t query[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x09, 0x5f,
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x07, 0x5f, 0x64, 0x6e, 0x73, 0x2d,
0x73, 0x64, 0x04, 0x5f, 0x75, 0x64, 0x70, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00,
};
struct dns_sd_rec record;
char instance[DNS_SD_INSTANCE_MAX_SIZE + 1];
char service[DNS_SD_SERVICE_MAX_SIZE + 1];
char proto[DNS_SD_PROTO_SIZE + 1];
char domain[DNS_SD_DOMAIN_MAX_SIZE + 1];
char *label[4];
size_t size[] = {
ARRAY_SIZE(instance),
ARRAY_SIZE(service),
ARRAY_SIZE(proto),
ARRAY_SIZE(domain),
};
size_t n = ARRAY_SIZE(label);
BUILD_ASSERT(ARRAY_SIZE(label) == ARRAY_SIZE(size), "");
/*
* work around for bug in compliance scripts which say that the array
* should be static const (incorrect)
*/
label[0] = instance;
label[1] = service;
label[2] = proto;
label[3] = domain;
zassert_equal(ARRAY_SIZE(query),
dns_sd_query_extract(query, ARRAY_SIZE(query), &record, label, size, &n),
"failed to extract service type enumeration");
zassert_true(dns_sd_is_service_type_enumeration(&record), "");
}
static void test_wildcard_comparison(void)
{
size_t n_matches = 0;
size_t n_records = 0;
struct dns_sd_rec filter;
dns_sd_create_wildcard_filter(&filter);
DNS_SD_FOREACH(record) {
if (!rec_is_valid(record)) {
continue;
}
++n_records;
}
DNS_SD_FOREACH(record) {
if (!rec_is_valid(record)) {
continue;
}
if (dns_sd_rec_match(record, &filter)) {
++n_matches;
}
}
zassert_true(n_records > 0, "there must be > 0 records");
zassert_equal(n_matches, n_records, "wildcard filter does not match "
"all records: n_records: %zu n_matches: %zu", n_records, n_matches);
}
void test_main(void)
{
ztest_test_suite(dns_sd_tests,
ztest_unit_test(test_label_is_valid),
ztest_unit_test(test_dns_sd_rec_is_valid),
ztest_unit_test(test_create_query),
ztest_unit_test(test_add_ptr_record),
ztest_unit_test(test_add_txt_record),
ztest_unit_test(test_add_srv_record),
ztest_unit_test(test_add_a_record),
ztest_unit_test(test_add_aaaa_record),
ztest_unit_test(test_dns_sd_handle_ptr_query),
ztest_unit_test(test_dns_sd_rec_match),
ztest_unit_test(test_setup_dst_addr),
ztest_unit_test(test_is_service_type_enumeration),
ztest_unit_test(test_extract_service_type_enumeration),
ztest_unit_test(test_wildcard_comparison),
ztest_unit_test(test_dns_sd_handle_service_type_enum));
ztest_run_test_suite(dns_sd_tests);
}