mirror of https://github.com/getdnsapi/getdns.git
Merge branch 'huitema-develop' into develop
This commit is contained in:
commit
7bf953b2bd
|
@ -67,7 +67,8 @@ C99COMPATFLAGS=@C99COMPATFLAGS@
|
||||||
|
|
||||||
GETDNS_OBJ=const-info.lo convert.lo dict.lo dnssec.lo general.lo \
|
GETDNS_OBJ=const-info.lo convert.lo dict.lo dnssec.lo general.lo \
|
||||||
list.lo request-internal.lo pubkey-pinning.lo rr-dict.lo \
|
list.lo request-internal.lo pubkey-pinning.lo rr-dict.lo \
|
||||||
rr-iter.lo server.lo stub.lo sync.lo ub_loop.lo util-internal.lo
|
rr-iter.lo server.lo stub.lo sync.lo ub_loop.lo util-internal.lo \
|
||||||
|
mdns.lo
|
||||||
|
|
||||||
GLDNS_OBJ=keyraw.lo gbuffer.lo wire2str.lo parse.lo parseutil.lo rrdef.lo \
|
GLDNS_OBJ=keyraw.lo gbuffer.lo wire2str.lo parse.lo parseutil.lo rrdef.lo \
|
||||||
str2wire.lo
|
str2wire.lo
|
||||||
|
@ -243,12 +244,18 @@ general.lo general.o: $(srcdir)/general.c config.h $(srcdir)/general.h getdns/ge
|
||||||
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \
|
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \
|
||||||
$(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \
|
$(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \
|
||||||
getdns/getdns_extra.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
|
getdns/getdns_extra.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
|
||||||
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/dict.h
|
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/dict.h \
|
||||||
|
$(srcdir)/mdns.h
|
||||||
list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \
|
list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \
|
||||||
getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \
|
getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \
|
||||||
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
|
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
|
||||||
$(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
|
$(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
|
||||||
$(srcdir)/list.h $(srcdir)/dict.h
|
$(srcdir)/list.h $(srcdir)/dict.h
|
||||||
|
mdns.lo mdns.o: $(srcdir)/mdns.c config.h $(srcdir)/debug.h $(srcdir)/context.h getdns/getdns.h \
|
||||||
|
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
|
||||||
|
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
|
||||||
|
$(srcdir)/server.h $(srcdir)/general.h $(srcdir)/gldns/pkthdr.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
|
||||||
|
$(srcdir)/gldns/gbuffer.h $(srcdir)/mdns.h
|
||||||
pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c config.h $(srcdir)/debug.h getdns/getdns.h \
|
pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c config.h $(srcdir)/debug.h getdns/getdns.h \
|
||||||
$(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/types-internal.h \
|
$(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/types-internal.h \
|
||||||
$(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \
|
$(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \
|
||||||
|
|
|
@ -1813,12 +1813,17 @@ getdns_context_set_namespaces(getdns_context *context,
|
||||||
|
|
||||||
for (i = 0; i < namespace_count; i++) {
|
for (i = 0; i < namespace_count; i++) {
|
||||||
if (namespaces[i] == GETDNS_NAMESPACE_NETBIOS ||
|
if (namespaces[i] == GETDNS_NAMESPACE_NETBIOS ||
|
||||||
namespaces[i] == GETDNS_NAMESPACE_MDNS ||
|
#ifndef HAVE_MDNS_SUPPORT
|
||||||
|
namespaces[i] == GETDNS_NAMESPACE_MDNS ||
|
||||||
|
#endif
|
||||||
namespaces[i] == GETDNS_NAMESPACE_NIS)
|
namespaces[i] == GETDNS_NAMESPACE_NIS)
|
||||||
r = GETDNS_RETURN_NOT_IMPLEMENTED;
|
r = GETDNS_RETURN_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
else if (namespaces[i] != GETDNS_NAMESPACE_DNS &&
|
else if (namespaces[i] != GETDNS_NAMESPACE_DNS &&
|
||||||
namespaces[i] != GETDNS_NAMESPACE_LOCALNAMES)
|
#ifdef HAVE_MDNS_SUPPORT
|
||||||
|
namespaces[i] != GETDNS_NAMESPACE_MDNS &&
|
||||||
|
#endif
|
||||||
|
namespaces[i] != GETDNS_NAMESPACE_LOCALNAMES )
|
||||||
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
||||||
}
|
}
|
||||||
GETDNS_FREE(context->my_mf, context->namespaces);
|
GETDNS_FREE(context->my_mf, context->namespaces);
|
||||||
|
|
28
src/debug.h
28
src/debug.h
|
@ -47,6 +47,21 @@
|
||||||
#define STUB_DEBUG_CLEANUP "--- CLEANUP: "
|
#define STUB_DEBUG_CLEANUP "--- CLEANUP: "
|
||||||
#define STUB_DEBUG_DAEMON "GETDNS_DAEMON: "
|
#define STUB_DEBUG_DAEMON "GETDNS_DAEMON: "
|
||||||
|
|
||||||
|
#ifdef GETDNS_ON_WINDOWS
|
||||||
|
#define DEBUG_ON(...) do { \
|
||||||
|
struct timeval tv; \
|
||||||
|
struct tm tm; \
|
||||||
|
char buf[10]; \
|
||||||
|
time_t tsec; \
|
||||||
|
\
|
||||||
|
gettimeofday(&tv, NULL); \
|
||||||
|
tsec = (time_t) tv.tv_sec; \
|
||||||
|
gmtime_s(&tm, (const time_t *) &tsec); \
|
||||||
|
strftime(buf, 10, "%H:%M:%S", &tm); \
|
||||||
|
fprintf(stderr, "[%s.%.6d] ", buf, (int)tv.tv_usec); \
|
||||||
|
fprintf(stderr, __VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
#define DEBUG_ON(...) do { \
|
#define DEBUG_ON(...) do { \
|
||||||
struct timeval tv; \
|
struct timeval tv; \
|
||||||
struct tm tm; \
|
struct tm tm; \
|
||||||
|
@ -58,6 +73,7 @@
|
||||||
fprintf(stderr, "[%s.%.6d] ", buf, (int)tv.tv_usec); \
|
fprintf(stderr, "[%s.%.6d] ", buf, (int)tv.tv_usec); \
|
||||||
fprintf(stderr, __VA_ARGS__); \
|
fprintf(stderr, __VA_ARGS__); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define DEBUG_NL(...) do { \
|
#define DEBUG_NL(...) do { \
|
||||||
struct timeval tv; \
|
struct timeval tv; \
|
||||||
|
@ -110,5 +126,17 @@
|
||||||
#define DEBUG_SERVER(...) DEBUG_OFF(__VA_ARGS__)
|
#define DEBUG_SERVER(...) DEBUG_OFF(__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MDNS_DEBUG_ENTRY "-> MDNS ENTRY: "
|
||||||
|
#define MDNS_DEBUG_READ "-- MDNS READ: "
|
||||||
|
#define MDNS_DEBUG_WRITE "-- MDNS WRITE: "
|
||||||
|
#define MDNS_DEBUG_CLEANUP "-- MDNS CLEANUP:"
|
||||||
|
|
||||||
|
#if defined(MDNS_DEBUG) && MDNS_DEBUG
|
||||||
|
#include <time.h>
|
||||||
|
#define DEBUG_MDNS(...) DEBUG_ON(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define DEBUG_MDNS(...) DEBUG_OFF(__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
/* debug.h */
|
/* debug.h */
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#include "dnssec.h"
|
#include "dnssec.h"
|
||||||
#include "stub.h"
|
#include "stub.h"
|
||||||
#include "dict.h"
|
#include "dict.h"
|
||||||
|
#include "mdns.h"
|
||||||
|
|
||||||
/* cancel, cleanup and send timeout to callback */
|
/* cancel, cleanup and send timeout to callback */
|
||||||
static void
|
static void
|
||||||
|
@ -476,6 +477,28 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
|
||||||
( req, localnames_response);
|
( req, localnames_response);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_MDNS_SUPPORT
|
||||||
|
} else if (context->namespaces[i] == GETDNS_NAMESPACE_MDNS) {
|
||||||
|
/* Check whether the name belongs in the MDNS space */
|
||||||
|
if (!(r = _getdns_mdns_namespace_check(req)))
|
||||||
|
{
|
||||||
|
// Submit the query to the MDNS transport.
|
||||||
|
for (netreq_p = req->netreqs
|
||||||
|
; !r && (netreq = *netreq_p)
|
||||||
|
; netreq_p++) {
|
||||||
|
if ((r = _getdns_submit_mdns_request(netreq))) {
|
||||||
|
if (r == DNS_REQ_FINISHED) {
|
||||||
|
if (return_netreq_p)
|
||||||
|
*return_netreq_p = NULL;
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
}
|
||||||
|
netreq->state = NET_REQ_FINISHED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Stop processing more namespaces, since there was a match */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_MDNS_SUPPORT */
|
||||||
} else if (context->namespaces[i] == GETDNS_NAMESPACE_DNS) {
|
} else if (context->namespaces[i] == GETDNS_NAMESPACE_DNS) {
|
||||||
|
|
||||||
/* TODO: We will get a good return code here even if
|
/* TODO: We will get a good return code here even if
|
||||||
|
|
|
@ -0,0 +1,361 @@
|
||||||
|
/*
|
||||||
|
* Functions for MDNS resolving.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Christian Huitema <huitema@huitema.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "context.h"
|
||||||
|
#include "general.h"
|
||||||
|
#include "gldns/pkthdr.h"
|
||||||
|
#include "util-internal.h"
|
||||||
|
#include "mdns.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_MDNS_SUPPORT
|
||||||
|
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
typedef u_short sa_family_t;
|
||||||
|
#define _getdns_EWOULDBLOCK (WSAGetLastError() == WSATRY_AGAIN ||\
|
||||||
|
WSAGetLastError() == WSAEWOULDBLOCK)
|
||||||
|
#define _getdns_EINPROGRESS (WSAGetLastError() == WSAEINPROGRESS)
|
||||||
|
#else
|
||||||
|
#define _getdns_EWOULDBLOCK (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||||
|
#define _getdns_EINPROGRESS (errno == EINPROGRESS)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint64_t _getdns_get_time_as_uintt64();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constants defined in RFC 6762
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MDNS_MCAST_IPV4_LONG 0xE00000FB /* 224.0.0.251 */
|
||||||
|
#define MDNS_MCAST_PORT 5353
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: When we start supporting IPv6 with MDNS, need to define this:
|
||||||
|
* static uint8_t mdns_mcast_ipv6[] = {
|
||||||
|
* 0xFF, 0x02, 0, 0, 0, 0, 0, 0,
|
||||||
|
* 0, 0, 0, 0, 0, 0, 0, 0xFB };
|
||||||
|
*/
|
||||||
|
|
||||||
|
static uint8_t mdns_suffix_dot_local[] = { 5, 'l', 'o', 'c', 'a', 'l', 0 };
|
||||||
|
static uint8_t mdns_suffix_254_169_in_addr_arpa[] = {
|
||||||
|
3, '2', '5', '4',
|
||||||
|
3, '1', '6', '9',
|
||||||
|
7, 'i', 'n', '-', 'a', 'd', 'd', 'r',
|
||||||
|
4, 'a', 'r', 'p', 'a', 0 };
|
||||||
|
static uint8_t mdns_suffix_8_e_f_ip6_arpa[] = {
|
||||||
|
1, '8', 1, 'e', 1, 'f',
|
||||||
|
7, 'i', 'p', 'v', '6',
|
||||||
|
4, 'a', 'r', 'p', 'a', 0 };
|
||||||
|
static uint8_t mdns_suffix_9_e_f_ip6_arpa[] = {
|
||||||
|
1, '9', 1, 'e', 1, 'f',
|
||||||
|
7, 'i', 'p', 'v', '6',
|
||||||
|
4, 'a', 'r', 'p', 'a', 0 };
|
||||||
|
static uint8_t mdns_suffix_a_e_f_ip6_arpa[] = {
|
||||||
|
1, 'a', 1, 'e', 1, 'f',
|
||||||
|
7, 'i', 'p', 'v', '6',
|
||||||
|
4, 'a', 'r', 'p', 'a', 0 };
|
||||||
|
static uint8_t mdns_suffix_b_e_f_ip6_arpa[] = {
|
||||||
|
1, 'b', 1, 'e', 1, 'f',
|
||||||
|
7, 'i', 'p', 'v', '6',
|
||||||
|
4, 'a', 'r', 'p', 'a', 0 };
|
||||||
|
|
||||||
|
/* TODO: actualy delete what is required.. */
|
||||||
|
static void
|
||||||
|
mdns_cleanup(getdns_network_req *netreq)
|
||||||
|
{
|
||||||
|
DEBUG_MDNS("%s %-35s: MSG: %p\n",
|
||||||
|
MDNS_DEBUG_CLEANUP, __FUNCTION__, netreq);
|
||||||
|
getdns_dns_req *dnsreq = netreq->owner;
|
||||||
|
|
||||||
|
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
|
||||||
|
|
||||||
|
GETDNS_NULL_FREE(dnsreq->context->mf, netreq->tcp.read_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_getdns_cancel_mdns_request(getdns_network_req *netreq)
|
||||||
|
{
|
||||||
|
mdns_cleanup(netreq);
|
||||||
|
if (netreq->fd >= 0) {
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
closesocket(netreq->fd);
|
||||||
|
#else
|
||||||
|
close(netreq->fd);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mdns_timeout_cb(void *userarg)
|
||||||
|
{
|
||||||
|
getdns_network_req *netreq = (getdns_network_req *)userarg;
|
||||||
|
DEBUG_MDNS("%s %-35s: MSG: %p\n",
|
||||||
|
MDNS_DEBUG_CLEANUP, __FUNCTION__, netreq);
|
||||||
|
|
||||||
|
/* TODO: do we need a retry logic here? */
|
||||||
|
|
||||||
|
/* Check the required cleanup */
|
||||||
|
mdns_cleanup(netreq);
|
||||||
|
if (netreq->fd >= 0)
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
closesocket(netreq->fd);
|
||||||
|
#else
|
||||||
|
close(netreq->fd);
|
||||||
|
#endif
|
||||||
|
netreq->state = NET_REQ_TIMED_OUT;
|
||||||
|
if (netreq->owner->user_callback) {
|
||||||
|
netreq->debug_end_time = _getdns_get_time_as_uintt64();
|
||||||
|
(void)_getdns_context_request_timed_out(netreq->owner);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_getdns_check_dns_req_complete(netreq->owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**************************/
|
||||||
|
/* UDP callback functions */
|
||||||
|
/**************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
mdns_udp_read_cb(void *userarg)
|
||||||
|
{
|
||||||
|
getdns_network_req *netreq = (getdns_network_req *)userarg;
|
||||||
|
getdns_dns_req *dnsreq = netreq->owner;
|
||||||
|
ssize_t read;
|
||||||
|
DEBUG_MDNS("%s %-35s: MSG: %p \n", MDNS_DEBUG_READ,
|
||||||
|
__FUNCTION__, netreq);
|
||||||
|
|
||||||
|
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
|
||||||
|
|
||||||
|
read = recvfrom(netreq->fd, (void *)netreq->response,
|
||||||
|
netreq->max_udp_payload_size + 1, /* If read == max_udp_payload_size
|
||||||
|
* then all is good. If read ==
|
||||||
|
* max_udp_payload_size + 1, then
|
||||||
|
* we receive more then requested!
|
||||||
|
* i.e. overflow
|
||||||
|
*/
|
||||||
|
0, NULL, NULL);
|
||||||
|
if (read == -1 && _getdns_EWOULDBLOCK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (read < GLDNS_HEADER_SIZE)
|
||||||
|
return; /* Not DNS */
|
||||||
|
|
||||||
|
if (GLDNS_ID_WIRE(netreq->response) != netreq->query_id)
|
||||||
|
return; /* Cache poisoning attempt ;) */
|
||||||
|
|
||||||
|
// TODO: check whether EDNS server cookies are required for MDNS
|
||||||
|
|
||||||
|
// TODO: check that the source address originates from the local network.
|
||||||
|
// TODO: check TTL = 255
|
||||||
|
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
closesocket(netreq->fd);
|
||||||
|
#else
|
||||||
|
close(netreq->fd);
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* TODO: how to handle an MDNS response with TC bit set?
|
||||||
|
* Ignore it for now, as we do not support any kind of TCP fallback
|
||||||
|
* for basic MDNS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
netreq->response_len = read;
|
||||||
|
netreq->debug_end_time = _getdns_get_time_as_uintt64();
|
||||||
|
netreq->state = NET_REQ_FINISHED;
|
||||||
|
_getdns_check_dns_req_complete(dnsreq);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mdns_udp_write_cb(void *userarg)
|
||||||
|
{
|
||||||
|
getdns_network_req *netreq = (getdns_network_req *)userarg;
|
||||||
|
getdns_dns_req *dnsreq = netreq->owner;
|
||||||
|
size_t pkt_len = netreq->response - netreq->query;
|
||||||
|
struct sockaddr_in mdns_mcast_v4;
|
||||||
|
int ttl = 255;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
DEBUG_MDNS("%s %-35s: MSG: %p \n", MDNS_DEBUG_WRITE,
|
||||||
|
__FUNCTION__, netreq);
|
||||||
|
|
||||||
|
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
|
||||||
|
|
||||||
|
netreq->debug_start_time = _getdns_get_time_as_uintt64();
|
||||||
|
netreq->debug_udp = 1;
|
||||||
|
netreq->query_id = (uint16_t) arc4random();
|
||||||
|
GLDNS_ID_SET(netreq->query, netreq->query_id);
|
||||||
|
|
||||||
|
/* do we need to handle options valid in the MDNS context? */
|
||||||
|
|
||||||
|
/* Probably no need for TSIG in MDNS */
|
||||||
|
|
||||||
|
|
||||||
|
/* Always use multicast address */
|
||||||
|
mdns_mcast_v4.sin_family = AF_INET;
|
||||||
|
mdns_mcast_v4.sin_port = htons(MDNS_MCAST_PORT);
|
||||||
|
mdns_mcast_v4.sin_addr.s_addr = htonl(MDNS_MCAST_IPV4_LONG);
|
||||||
|
|
||||||
|
|
||||||
|
/* Set TTL=255 for compliance with RFC 6762 */
|
||||||
|
r = setsockopt(netreq->fd, IPPROTO_IP, IP_TTL, (const char *)&ttl, sizeof(ttl));
|
||||||
|
|
||||||
|
if (r != 0 ||
|
||||||
|
(ssize_t)pkt_len != sendto(
|
||||||
|
netreq->fd, (const void *)netreq->query, pkt_len, 0,
|
||||||
|
(struct sockaddr *)&mdns_mcast_v4,
|
||||||
|
sizeof(mdns_mcast_v4))) {
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
closesocket(netreq->fd);
|
||||||
|
#else
|
||||||
|
close(netreq->fd);
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GETDNS_SCHEDULE_EVENT(
|
||||||
|
dnsreq->loop, netreq->fd, dnsreq->context->timeout,
|
||||||
|
getdns_eventloop_event_init(&netreq->event, netreq,
|
||||||
|
mdns_udp_read_cb, NULL, mdns_timeout_cb));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MDNS Request Submission
|
||||||
|
*/
|
||||||
|
|
||||||
|
getdns_return_t
|
||||||
|
_getdns_submit_mdns_request(getdns_network_req *netreq)
|
||||||
|
{
|
||||||
|
DEBUG_MDNS("%s %-35s: MSG: %p TYPE: %d\n", MDNS_DEBUG_ENTRY, __FUNCTION__,
|
||||||
|
netreq, netreq->request_type);
|
||||||
|
int fd = -1;
|
||||||
|
getdns_dns_req *dnsreq = netreq->owner;
|
||||||
|
|
||||||
|
/* Open the UDP socket required for the request */
|
||||||
|
if ((fd = socket(
|
||||||
|
AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
|
||||||
|
return -1;
|
||||||
|
/* TODO: do we need getdns_sock_nonblock(fd); */
|
||||||
|
|
||||||
|
/* Schedule the MDNS request */
|
||||||
|
netreq->fd = fd;
|
||||||
|
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
|
||||||
|
GETDNS_SCHEDULE_EVENT(
|
||||||
|
dnsreq->loop, netreq->fd, dnsreq->context->timeout,
|
||||||
|
getdns_eventloop_event_init(&netreq->event, netreq,
|
||||||
|
NULL, mdns_udp_write_cb, mdns_timeout_cb));
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MDNS name space management
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
mdns_suffix_compare(register const uint8_t *d1, register const uint8_t *d2)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
uint8_t *d1_head = (uint8_t *) d1;
|
||||||
|
uint8_t *d1_current;
|
||||||
|
uint8_t *d2_current;
|
||||||
|
int is_matching = 0;
|
||||||
|
int part_length;
|
||||||
|
int i;
|
||||||
|
uint8_t c;
|
||||||
|
|
||||||
|
/* Skip the first name part, since we want at least one label before the suffix */
|
||||||
|
if (*d1_head != 0)
|
||||||
|
d1_head += *d1_head + 1;
|
||||||
|
|
||||||
|
while (*d1_head != 0)
|
||||||
|
{
|
||||||
|
/* check whether we have a match at this point */
|
||||||
|
d1_current = d1_head;
|
||||||
|
d2_current = (uint8_t *) d2;
|
||||||
|
is_matching = 0;
|
||||||
|
|
||||||
|
/* compare length and value of all successive labels */
|
||||||
|
while (*d1_current == *d2_current)
|
||||||
|
{
|
||||||
|
part_length = *d1_current;
|
||||||
|
if (part_length == 0)
|
||||||
|
{
|
||||||
|
/* We have reached the top label, there is a match */
|
||||||
|
ret = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The label's lengths are matching, check the content */
|
||||||
|
is_matching = 1;
|
||||||
|
d1_current++;
|
||||||
|
d2_current++;
|
||||||
|
|
||||||
|
for (i = 0; i < part_length; i++)
|
||||||
|
{
|
||||||
|
c = d1_current[i];
|
||||||
|
if (isupper(c))
|
||||||
|
c = tolower(c);
|
||||||
|
if (c != d2_current[i])
|
||||||
|
{
|
||||||
|
is_matching = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* move the pointers to the next label */
|
||||||
|
if (is_matching)
|
||||||
|
{
|
||||||
|
d1_current += part_length;
|
||||||
|
d2_current += part_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if no match found yet, move to the next label of d1 */
|
||||||
|
if (is_matching)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
d1_head += *d1_head + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getdns_return_t
|
||||||
|
_getdns_mdns_namespace_check(
|
||||||
|
getdns_dns_req *dnsreq)
|
||||||
|
{
|
||||||
|
getdns_return_t ret = GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
|
||||||
|
/* Checking the prefixes defined in RFC 6762 */
|
||||||
|
if (mdns_suffix_compare(dnsreq->name, mdns_suffix_dot_local) ||
|
||||||
|
mdns_suffix_compare(dnsreq->name, mdns_suffix_254_169_in_addr_arpa) ||
|
||||||
|
mdns_suffix_compare(dnsreq->name, mdns_suffix_8_e_f_ip6_arpa) ||
|
||||||
|
mdns_suffix_compare(dnsreq->name, mdns_suffix_9_e_f_ip6_arpa) ||
|
||||||
|
mdns_suffix_compare(dnsreq->name, mdns_suffix_a_e_f_ip6_arpa) ||
|
||||||
|
mdns_suffix_compare(dnsreq->name, mdns_suffix_b_e_f_ip6_arpa))
|
||||||
|
ret = GETDNS_RETURN_GOOD;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_MDNS_SUPPORT */
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Functions for MDNS resolving.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Christian Huitema <huitema@huitema.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MDNS_H
|
||||||
|
#define MDNS_H
|
||||||
|
|
||||||
|
#ifdef HAVE_MDNS_SUPPORT
|
||||||
|
#include "getdns/getdns.h"
|
||||||
|
#include "types-internal.h"
|
||||||
|
|
||||||
|
getdns_return_t
|
||||||
|
_getdns_submit_mdns_request(getdns_network_req *netreq);
|
||||||
|
|
||||||
|
getdns_return_t
|
||||||
|
_getdns_mdns_namespace_check(getdns_dns_req *dnsreq);
|
||||||
|
#endif /* HAVE_MDNS_SUPPORT */
|
||||||
|
|
||||||
|
#endif /* MDNS_H */
|
|
@ -96,7 +96,7 @@ static int upstream_connect(getdns_upstream *upstream,
|
||||||
static int fallback_on_write(getdns_network_req *netreq);
|
static int fallback_on_write(getdns_network_req *netreq);
|
||||||
|
|
||||||
static void stub_timeout_cb(void *userarg);
|
static void stub_timeout_cb(void *userarg);
|
||||||
static uint64_t _getdns_get_time_as_uintt64();
|
uint64_t _getdns_get_time_as_uintt64();
|
||||||
/*****************************/
|
/*****************************/
|
||||||
/* General utility functions */
|
/* General utility functions */
|
||||||
/*****************************/
|
/*****************************/
|
||||||
|
@ -490,7 +490,7 @@ stub_cleanup(getdns_network_req *netreq)
|
||||||
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
|
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
|
||||||
|
|
||||||
/* Nothing globally scheduled? Then nothing queued */
|
/* Nothing globally scheduled? Then nothing queued */
|
||||||
if (!(upstream = netreq->upstream)->event.ev)
|
if (!netreq->upstream || !(upstream = netreq->upstream)->event.ev)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Delete from upstream->netreq_by_query_id (if present) */
|
/* Delete from upstream->netreq_by_query_id (if present) */
|
||||||
|
@ -1271,7 +1271,7 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
||||||
return STUB_TCP_ERROR;
|
return STUB_TCP_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t
|
uint64_t
|
||||||
_getdns_get_time_as_uintt64() {
|
_getdns_get_time_as_uintt64() {
|
||||||
|
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|
Loading…
Reference in New Issue