aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ip6_icmp.c3
-rw-r--r--src/slirp.c47
-rw-r--r--src/slirp.h9
-rw-r--r--src/socket.c24
-rw-r--r--src/udp.c2
5 files changed, 67 insertions, 18 deletions
diff --git a/src/ip6_icmp.c b/src/ip6_icmp.c
index 21224bc..abb1a99 100644
--- a/src/ip6_icmp.c
+++ b/src/ip6_icmp.c
@@ -286,6 +286,7 @@ static void ndp_send_ra(Slirp *slirp)
struct ip6 *rip = mtod(t, struct ip6 *);
size_t pl_size = 0;
struct in6_addr addr;
+ uint16_t port;
uint32_t scope_id;
rip->ip_src = (struct in6_addr)LINKLOCAL_ADDR;
@@ -334,7 +335,7 @@ static void ndp_send_ra(Slirp *slirp)
pl_size += NDPOPT_PREFIXINFO_LEN;
/* Prefix information (NDP option) */
- if (get_dns6_addr(&addr, &scope_id) >= 0) {
+ if (get_dns6_addr(&addr, &port, &scope_id) >= 0) {
/* Host system does have an IPv6 DNS server, announce our proxy. */
struct ndpopt *opt3 = mtod(t, struct ndpopt *);
opt3->ndpopt_type = NDPOPT_RDNSS;
diff --git a/src/slirp.c b/src/slirp.c
index 62a018a..a84d6e4 100644
--- a/src/slirp.c
+++ b/src/slirp.c
@@ -87,6 +87,8 @@ unsigned curtime;
static struct in_addr dns_addr;
static struct in6_addr dns6_addr;
+static uint16_t dns_port;
+static uint16_t dns6_port;
static uint32_t dns6_scope_id;
static unsigned dns_addr_time;
static unsigned dns6_addr_time;
@@ -98,7 +100,7 @@ static unsigned dns6_addr_time;
#if defined(_WIN32)
-int get_dns_addr(struct in_addr *pdns_addr)
+int get_dns_addr(struct in_addr *pdns_addr, uint16_t *pdns_port)
{
FIXED_INFO *FixedInfo = NULL;
ULONG BufLen;
@@ -134,6 +136,7 @@ int get_dns_addr(struct in_addr *pdns_addr)
pIPAddr = &(FixedInfo->DnsServerList);
inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
*pdns_addr = tmp_addr;
+ *pdns_port = dns_port = htons(53); // TODO: honor custom port
dns_addr = tmp_addr;
dns_addr_time = curtime;
if (FixedInfo) {
@@ -230,16 +233,19 @@ failure:
return -1;
}
-int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id)
+int get_dns6_addr(struct in6_addr *pdns6_addr, uint16_t *pdns6_port,
+ uint32_t *scope_id)
{
if (!in6_zero(&dns6_addr) && (curtime - dns6_addr_time) < TIMEOUT_DEFAULT) {
*pdns6_addr = dns6_addr;
+ *pdns6_port = dns6_port;
*scope_id = dns6_scope_id;
return 0;
}
if (get_ipv6_dns_server(pdns6_addr, scope_id) == 0) {
dns6_addr = *pdns6_addr;
+ *pdns6_port = dns6_port = htons(53); // TODO: honor custom port
dns6_addr_time = curtime;
dns6_scope_id = *scope_id;
return 0;
@@ -258,10 +264,13 @@ static void winsock_cleanup(void)
#include <resolv.h>
static int get_dns_addr_cached(void *pdns_addr, void *cached_addr,
- socklen_t addrlen, unsigned *cached_time)
+ socklen_t addrlen,
+ uint16_t *pdns_port, uint16_t cached_port,
+ unsigned *cached_time)
{
if (curtime - *cached_time < TIMEOUT_DEFAULT) {
memcpy(pdns_addr, cached_addr, addrlen);
+ *pdns_port = cached_port;
return 0;
}
return 1;
@@ -269,6 +278,7 @@ static int get_dns_addr_cached(void *pdns_addr, void *cached_addr,
static int get_dns_addr_libresolv(int af, void *pdns_addr, void *cached_addr,
socklen_t addrlen,
+ uint16_t *pdns_port, uint16_t *cached_port,
uint32_t *scope_id, uint32_t *cached_scope_id,
unsigned *cached_time)
{
@@ -277,6 +287,7 @@ static int get_dns_addr_libresolv(int af, void *pdns_addr, void *cached_addr,
int count;
int found;
void *addr;
+ uint16_t port;
// we only support IPv4 and IPv4, we assume it's one or the other
assert(af == AF_INET || af == AF_INET6);
@@ -297,14 +308,17 @@ static int get_dns_addr_libresolv(int af, void *pdns_addr, void *cached_addr,
if (af == AF_INET) {
addr = &servers[i].sin.sin_addr;
+ port = servers[i].sin.sin_port;
} else { // af == AF_INET6
addr = &servers[i].sin6.sin6_addr;
+ port = servers[i].sin6.sin6_port;
}
// we use the first found entry
if (found == 1) {
memcpy(pdns_addr, addr, addrlen);
memcpy(cached_addr, addr, addrlen);
+ *pdns_port = *cached_port = port;
if (scope_id) {
*scope_id = 0;
}
@@ -323,7 +337,7 @@ static int get_dns_addr_libresolv(int af, void *pdns_addr, void *cached_addr,
if (!res) {
res = " (string conversion error)";
}
- DEBUG_MISC(" %s", res);
+ DEBUG_MISC(" %s, port %d", res, ntohs(port));
}
}
@@ -333,26 +347,29 @@ static int get_dns_addr_libresolv(int af, void *pdns_addr, void *cached_addr,
return 0;
}
-int get_dns_addr(struct in_addr *pdns_addr)
+int get_dns_addr(struct in_addr *pdns_addr, uint16_t *pdns_port)
{
if (dns_addr.s_addr != 0) {
int ret;
ret = get_dns_addr_cached(pdns_addr, &dns_addr, sizeof(dns_addr),
- &dns_addr_time);
+ pdns_port, dns_port, &dns_addr_time);
if (ret <= 0) {
return ret;
}
}
return get_dns_addr_libresolv(AF_INET, pdns_addr, &dns_addr,
- sizeof(dns_addr), NULL, NULL, &dns_addr_time);
+ sizeof(dns_addr),
+ pdns_port, &dns_port,
+ NULL, NULL, &dns_addr_time);
}
-int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id)
+int get_dns6_addr(struct in6_addr *pdns6_addr, uint16_t *pdns6_port,
+ uint32_t *scope_id)
{
if (!in6_zero(&dns6_addr)) {
int ret;
ret = get_dns_addr_cached(pdns6_addr, &dns6_addr, sizeof(dns6_addr),
- &dns6_addr_time);
+ pdns6_port, dns6_port, &dns6_addr_time);
if (ret == 0) {
*scope_id = dns6_scope_id;
}
@@ -362,6 +379,7 @@ int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id)
}
return get_dns_addr_libresolv(AF_INET6, pdns6_addr, &dns6_addr,
sizeof(dns6_addr),
+ pdns6_port, &dns6_port,
scope_id, &dns6_scope_id, &dns6_addr_time);
}
@@ -440,6 +458,7 @@ static bool try_and_setdns_server(int af, unsigned found, unsigned if_index,
static int get_dns_addr_resolv_conf(int af, void *pdns_addr, void *cached_addr,
socklen_t addrlen,
+ uint16_t *pdns_port, uint16_t *cached_port,
uint32_t *scope_id, uint32_t *cached_scope_id,
unsigned *cached_time)
{
@@ -488,10 +507,13 @@ static int get_dns_addr_resolv_conf(int af, void *pdns_addr, void *cached_addr,
cached_scope_id, cached_time);
}
+ if (found)
+ *pdns_port = *cached_port = htons(53); // TODO: honor custom port
+
return found ? 0 : -1;
}
-int get_dns_addr(struct in_addr *pdns_addr)
+int get_dns_addr(struct in_addr *pdns_addr, uint16_t *pdns_port)
{
static struct stat dns_addr_stat;
@@ -505,10 +527,12 @@ int get_dns_addr(struct in_addr *pdns_addr)
}
return get_dns_addr_resolv_conf(AF_INET, pdns_addr, &dns_addr,
sizeof(dns_addr),
+ pdns_port, &dns_port,
NULL, NULL, &dns_addr_time);
}
-int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id)
+int get_dns6_addr(struct in6_addr *pdns6_addr, uint16_t *pdns6_port,
+ uint32_t *scope_id)
{
static struct stat dns6_addr_stat;
@@ -525,6 +549,7 @@ int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id)
}
return get_dns_addr_resolv_conf(AF_INET6, pdns6_addr, &dns6_addr,
sizeof(dns6_addr),
+ pdns6_port, &dns6_port,
scope_id, &dns6_scope_id, &dns6_addr_time);
}
diff --git a/src/slirp.h b/src/slirp.h
index b4f46c8..6333031 100644
--- a/src/slirp.h
+++ b/src/slirp.h
@@ -231,11 +231,12 @@ struct Slirp {
*/
void if_start(Slirp *);
-/* Get the address of the DNS server on the host side */
-int get_dns_addr(struct in_addr *pdns_addr);
+/* Get the IPv4 address and port of the DNS server on the host side */
+int get_dns_addr(struct in_addr *pdns_addr, uint16_t *pdns_port);
-/* Get the IPv6 address of the DNS server on the host side */
-int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id);
+/* Get the IPv6 address and port of the DNS server on the host side */
+int get_dns6_addr(struct in6_addr *pdns6_addr, uint16_t *pdns_port,
+ uint32_t *scope_id);
/* ncsi.c */
diff --git a/src/socket.c b/src/socket.c
index 278bf27..b2f8587 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -968,7 +968,8 @@ void sofwdrain(struct socket *so)
static bool sotranslate_out4(Slirp *s, struct socket *so, struct sockaddr_in *sin)
{
if (!s->disable_dns && so->so_faddr.s_addr == s->vnameserver_addr.s_addr) {
- return so->so_fport == htons(53) && get_dns_addr(&sin->sin_addr) >= 0;
+ return (so->so_fport == htons(53) &&
+ get_dns_addr(&sin->sin_addr, &sin->sin_port) >= 0);
}
if (so->so_faddr.s_addr == s->vhost_addr.s_addr ||
@@ -987,7 +988,8 @@ static bool sotranslate_out6(Slirp *s, struct socket *so, struct sockaddr_in6 *s
{
if (!s->disable_dns && in6_equal(&so->so_faddr6, &s->vnameserver_addr6)) {
uint32_t scope_id;
- if (so->so_fport == htons(53) && get_dns6_addr(&sin->sin6_addr, &scope_id) >= 0) {
+ if (so->so_fport == htons(53) &&
+ get_dns6_addr(&sin->sin6_addr, &sin->sin6_port, &scope_id) >= 0) {
sin->sin6_scope_id = scope_id;
return true;
}
@@ -1034,6 +1036,8 @@ void sotranslate_in(struct socket *so, struct sockaddr_storage *addr)
struct sockaddr_in *sin = (struct sockaddr_in *)addr;
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
+ uint16_t dns_port;
+
switch (addr->ss_family) {
case AF_INET:
if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
@@ -1047,6 +1051,13 @@ void sotranslate_in(struct socket *so, struct sockaddr_storage *addr)
sin->sin_addr = so->so_faddr;
}
}
+
+ struct in_addr sin_addr;
+ if (get_dns_addr(&sin_addr, &dns_port) >= 0 &&
+ sin->sin_port == dns_port &&
+ sin->sin_addr.s_addr == sin_addr.s_addr)
+ sin->sin_port = htons(53);
+
break;
case AF_INET6:
@@ -1057,6 +1068,15 @@ void sotranslate_in(struct socket *so, struct sockaddr_storage *addr)
sin6->sin6_addr = so->so_faddr6;
}
}
+
+ struct in6_addr sin6_addr;
+ uint32_t scope_id;
+ if (get_dns6_addr(&sin6_addr, &dns_port, &scope_id) >= 0 &&
+ sin6->sin6_port == dns_port &&
+ sin6->sin6_scope_id == scope_id &&
+ in6_equal(&sin6->sin6_addr, &sin6_addr))
+ sin6->sin6_port = htons(53);
+
break;
default:
diff --git a/src/udp.c b/src/udp.c
index eb20bbb..14704e5 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -263,6 +263,8 @@ int udp_output(struct socket *so, struct mbuf *m, const struct sockaddr_in *sadd
DEBUG_ARG("m = %p", m);
DEBUG_ARG("saddr = %s", inet_ntop(AF_INET, &saddr->sin_addr, addr, sizeof(addr)));
DEBUG_ARG("daddr = %s", inet_ntop(AF_INET, &daddr->sin_addr, addr, sizeof(addr)));
+ DEBUG_ARG("s_inport = %d", ntohs(saddr->sin_port));
+ DEBUG_ARG("d_inport = %d", ntohs(daddr->sin_port));
/*
* Adjust for header