Commit 04565341 authored by Simon Morlat's avatar Simon Morlat
Browse files

Allow DNS responses to come from an IP address that is not the one to which...

Allow DNS responses to come from an IP address that is not the one to which the request was sent (because of NAT64 networks powered by Mac computers)
parent dfefba74
......@@ -537,6 +537,9 @@ static int resolver_process_data(belle_sip_simple_resolver_context_t *ctx, unsig
#ifdef USE_GETADDRINFO_FALLBACK
ctx->getaddrinfo_cancelled = TRUE;
#endif
if (dns_res_was_asymetric(ctx->R)){
belle_sip_warning("DNS answer was not received from the DNS server IP address the request was sent to. This seems to be a known issue with NAT64 networks created by Apple computers.");
}
belle_sip_resolver_context_notify(BELLE_SIP_RESOLVER_CONTEXT(ctx));
return BELLE_SIP_STOP;
}
......@@ -685,6 +688,11 @@ static int _resolver_start_query(belle_sip_simple_resolver_context_t *ctx) {
return -1;
memset(&opts, 0, sizeof opts);
/* When there are IPv6 nameservers, allow responses to arrive from an IP address that is not the IP address to which the request was sent originally.
* Mac' NAT64 network tend to do this sometimes.*/
opts.udp_uses_connect = ctx->resconf->iface.ss_family != AF_INET6;
if (!opts.udp_uses_connect) belle_sip_message("Resolver is not using connect().");
if (!(ctx->R = dns_res_open(ctx->resconf, ctx->hosts, dns_hints_mortal(dns_hints_local(ctx->resconf, &error)), cache(ctx), &opts, &error))) {
belle_sip_error("%s dns_res_open error [%s]: %s", __FUNCTION__, ctx->name, dns_strerror(error));
......
......@@ -6419,6 +6419,7 @@ struct dns_socket {
struct dns_packet *answer;
size_t alen, apos;
int ip_differ; /*set when remote address and response from which it is received are different*/
}; /* struct dns_socket */
......@@ -6484,7 +6485,7 @@ static void dns_so_closefds(struct dns_socket *so, int which) {
static void dns_so_destroy(struct dns_socket *);
static struct dns_socket *dns_so_init(struct dns_socket *so, const struct sockaddr *local, int type, const struct dns_options *opts, int *error) {
static const struct dns_socket so_initializer = { .opts = DNS_OPTS_INITIALIZER, .udp = -1, .tcp = -1, };
static const struct dns_socket so_initializer = { .opts = DNS_OPTS_INITIALIZER, .udp = -1, .tcp = -1};
*so = so_initializer;
so->type = type;
......@@ -6749,8 +6750,9 @@ static int dns_so_tcp_recv(struct dns_socket *so) {
#endif
int dns_so_check(struct dns_socket *so) {
struct sockaddr_storage reset_ss;
int dns_so_check(struct dns_socket *so) {
struct sockaddr_storage tmp_ss;
socklen_t tmp_ss_len = sizeof(tmp_ss);
int error;
long n;
......@@ -6759,23 +6761,41 @@ retry:
case DNS_SO_UDP_INIT:
so->state++;
case DNS_SO_UDP_CONN:
memset(&reset_ss, 0, sizeof(reset_ss));
connect(so->udp, (struct sockaddr *)&reset_ss, sizeof(reset_ss)); // Reset the previous connection
if (0 != connect(so->udp, (struct sockaddr *)&so->remote, dns_sa_len(&so->remote)))
goto soerr;
memset(&tmp_ss, 0, sizeof(tmp_ss));
connect(so->udp, (struct sockaddr *)&tmp_ss, sizeof(tmp_ss)); // Reset the previous connection
if (so->opts.udp_uses_connect){
if (0 != connect(so->udp, (struct sockaddr *)&so->remote, dns_sa_len(&so->remote)))
goto soerr;
}
so->state++;
case DNS_SO_UDP_SEND:
if (0 > (n = send(so->udp, (void *)so->query->data, so->query->end, 0)))
goto soerr;
if (so->opts.udp_uses_connect){
if (0 > (n = send(so->udp, (void *)so->query->data, so->query->end, 0)))
goto soerr;
}else{
if (0 > (n = sendto(so->udp, (void *)so->query->data, so->query->end, 0, (struct sockaddr *)&so->remote, dns_sa_len(&so->remote))))
goto soerr;
}
so->stat.udp.sent.bytes += n;
so->stat.udp.sent.count++;
so->state++;
case DNS_SO_UDP_RECV:
if (0 > (n = recv(so->udp, (void *)so->answer->data, so->answer->size, 0)))
goto soerr;
if (so->opts.udp_uses_connect){
if (0 > (n = recv(so->udp, (void *)so->answer->data, so->answer->size, 0)))
goto soerr;
}else{
memset(&tmp_ss, 0, sizeof(tmp_ss));
tmp_ss_len = sizeof(tmp_ss);
if (0 > (n = recvfrom(so->udp, (void *)so->answer->data, so->answer->size, 0, (struct sockaddr *)&tmp_ss, &tmp_ss_len)))
goto soerr;
if (memcmp(&tmp_ss, &so->remote, tmp_ss_len) != 0){
so->ip_differ = 1;
}
}
so->stat.udp.rcvd.bytes += n;
so->stat.udp.rcvd.count++;
......@@ -8133,6 +8153,10 @@ void dns_res_enable_search(struct dns_resolver *res, unsigned char enable) {
res->search_enabled = enable;
}
int dns_res_was_asymetric(struct dns_resolver *res){
return res->so.ip_differ;
}
/*
* A D D R I N F O R O U T I N E S
......
......@@ -1098,6 +1098,7 @@ struct dns_options {
DNS_SYSPOLL,
DNS_LIBEVENT,
} events;
int udp_uses_connect;
}; /* struct dns_options */
......@@ -1202,6 +1203,8 @@ DNS_PUBLIC void dns_res_sethints(struct dns_resolver *, struct dns_hints *);
DNS_PUBLIC void dns_res_enable_search(struct dns_resolver *, unsigned char enable);
DNS_PUBLIC int dns_res_was_asymetric(struct dns_resolver *);
/*
* A D D R I N F O I N T E R F A C E
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment