diff --git a/conf.c b/conf.c index 1adcf83..a995eb7 100644 --- a/conf.c +++ b/conf.c @@ -355,11 +355,9 @@ overlap: */ static void get_dns(struct ctx *c) { - struct in6_addr *dns6_send = &c->ip6.dns_send[0]; - struct in_addr *dns4_send = &c->ip4.dns_send[0]; + struct in6_addr *dns6 = &c->ip6.dns[0], dns6_tmp; + struct in_addr *dns4 = &c->ip4.dns[0], dns4_tmp; int dns4_set, dns6_set, dnss_set, dns_set, fd; - struct in6_addr *dns6 = &c->ip6.dns[0]; - struct in_addr *dns4 = &c->ip4.dns[0]; struct fqdn *s = c->dns_search; struct lineread resolvconf; int line_len; @@ -388,49 +386,44 @@ static void get_dns(struct ctx *c) *end = 0; if (!dns4_set && - dns4 - &c->ip4.dns[0] < ARRAY_SIZE(c->ip4.dns) - 1 && - inet_pton(AF_INET, p + 1, dns4)) { + dns4 - &c->ip4.dns[0] < ARRAY_SIZE(c->ip4.dns) - 1 + && inet_pton(AF_INET, p + 1, &dns4_tmp)) { /* Guest or container can only access local * addresses via local redirect */ - if (IN4_IS_ADDR_LOOPBACK(dns4)) { + if (IN4_IS_ADDR_LOOPBACK(&dns4_tmp)) { if (!c->no_map_gw) { - *dns4_send = c->ip4.gw; - dns4_send++; + *dns4 = c->ip4.gw; + dns4++; } } else { - *dns4_send = *dns4; - dns4_send++; + *dns4 = dns4_tmp; + dns4++; } - dns4++; - - dns4->s_addr = htonl(INADDR_ANY); - dns4_send->s_addr = htonl(INADDR_ANY); + if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_host)) + c->ip4.dns_host = dns4_tmp; } if (!dns6_set && - dns6 - &c->ip6.dns[0] < ARRAY_SIZE(c->ip6.dns) - 1 && - inet_pton(AF_INET6, p + 1, dns6)) { + dns6 - &c->ip6.dns[0] < ARRAY_SIZE(c->ip6.dns) - 1 + && inet_pton(AF_INET6, p + 1, &dns6_tmp)) { /* Guest or container can only access local * addresses via local redirect */ - if (IN6_IS_ADDR_LOOPBACK(dns6)) { + if (IN6_IS_ADDR_LOOPBACK(&dns6_tmp)) { if (!c->no_map_gw) { - memcpy(dns6_send, &c->ip6.gw, - sizeof(*dns6_send)); - dns6_send++; + memcpy(dns6, &c->ip6.gw, + sizeof(*dns6)); + dns6++; } } else { - memcpy(dns6_send, dns6, - sizeof(*dns6_send)); - dns6_send++; + memcpy(dns6, &dns6_tmp, sizeof(*dns6)); + dns6++; } - dns6++; - - memset(dns6, 0, sizeof(*dns6)); - memset(dns6_send, 0, sizeof(*dns6_send)); + if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_host)) + c->ip6.dns_host = dns6_tmp; } } else if (!dnss_set && strstr(line, "search ") == line && s == c->dns_search) { @@ -897,12 +890,10 @@ static void conf_print(const struct ctx *c) inet_ntop(AF_INET, &c->ip4.gw, buf4, sizeof(buf4))); } - for (i = 0; !IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_send[i]); - i++) { + for (i = 0; !IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns[i]); i++) { if (!i) info("DNS:"); - inet_ntop(AF_INET, &c->ip4.dns_send[i], buf4, - sizeof(buf4)); + inet_ntop(AF_INET, &c->ip4.dns[i], buf4, sizeof(buf4)); info(" %s", buf4); } @@ -933,8 +924,7 @@ static void conf_print(const struct ctx *c) inet_ntop(AF_INET6, &c->ip6.addr_ll, buf6, sizeof(buf6))); dns6: - for (i = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_send[i]); - i++) { + for (i = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[i]); i++) { if (!i) info("DNS:"); inet_ntop(AF_INET6, &c->ip6.dns[i], buf6, sizeof(buf6)); @@ -1230,17 +1220,17 @@ void conf(struct ctx *c, int argc, char **argv) c->no_dhcp_dns_search = 1; break; case 9: - if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_fwd) && - inet_pton(AF_INET6, optarg, &c->ip6.dns_fwd) && - !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_fwd) && - !IN6_IS_ADDR_LOOPBACK(&c->ip6.dns_fwd)) + if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_match) && + inet_pton(AF_INET6, optarg, &c->ip6.dns_match) && + !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_match) && + !IN6_IS_ADDR_LOOPBACK(&c->ip6.dns_match)) break; - if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_fwd) && - inet_pton(AF_INET, optarg, &c->ip4.dns_fwd) && - !IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_fwd) && - !IN4_IS_ADDR_BROADCAST(&c->ip4.dns_fwd) && - !IN4_IS_ADDR_LOOPBACK(&c->ip4.dns_fwd)) + if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_match) && + inet_pton(AF_INET, optarg, &c->ip4.dns_match) && + !IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_match) && + !IN4_IS_ADDR_BROADCAST(&c->ip4.dns_match) && + !IN4_IS_ADDR_LOOPBACK(&c->ip4.dns_match)) break; err("Invalid DNS forwarding address: %s", optarg); diff --git a/dhcp.c b/dhcp.c index 12da47a..6088886 100644 --- a/dhcp.c +++ b/dhcp.c @@ -359,9 +359,8 @@ int dhcp(const struct ctx *c, const struct pool *p) } for (i = 0, opts[6].slen = 0; - !c->no_dhcp_dns && !IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_send[i]); - i++) { - ((struct in_addr *)opts[6].s)[i] = c->ip4.dns_send[i]; + !c->no_dhcp_dns && !IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns[i]); i++) { + ((struct in_addr *)opts[6].s)[i] = c->ip4.dns[i]; opts[6].slen += sizeof(uint32_t); } diff --git a/dhcpv6.c b/dhcpv6.c index 67262e6..e763aed 100644 --- a/dhcpv6.c +++ b/dhcpv6.c @@ -379,7 +379,7 @@ static size_t dhcpv6_dns_fill(const struct ctx *c, char *buf, int offset) if (c->no_dhcp_dns) goto search; - for (i = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_send[i]); i++) { + for (i = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[i]); i++) { if (!i) { srv = (struct opt_dns_servers *)(buf + offset); offset += sizeof(struct opt_hdr); @@ -387,8 +387,7 @@ static size_t dhcpv6_dns_fill(const struct ctx *c, char *buf, int offset) srv->hdr.l = 0; } - memcpy(&srv->addr[i], &c->ip6.dns_send[i], - sizeof(srv->addr[i])); + memcpy(&srv->addr[i], &c->ip6.dns[i], sizeof(srv->addr[i])); srv->hdr.l += sizeof(srv->addr[i]); offset += sizeof(srv->addr[i]); } diff --git a/ndp.c b/ndp.c index 6d79477..80e1f19 100644 --- a/ndp.c +++ b/ndp.c @@ -121,7 +121,7 @@ int ndp(struct ctx *c, const struct icmp6hdr *ih, const struct in6_addr *saddr) if (c->no_dhcp_dns) goto dns_done; - for (n = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_send[n]); n++); + for (n = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[n]); n++); if (n) { *p++ = 25; /* RDNSS */ *p++ = 1 + 2 * n; /* length */ @@ -130,8 +130,8 @@ int ndp(struct ctx *c, const struct icmp6hdr *ih, const struct in6_addr *saddr) p += 4; for (i = 0; i < n; i++) { - memcpy(p, &c->ip6.dns_send[i], 16); - p += 16; /* address */ + memcpy(p, &c->ip6.dns[i], 16); /* address */ + p += 16; } for (n = 0; *c->dns_search[n].n; n++) diff --git a/passt.h b/passt.h index e93eea8..6649c0a 100644 --- a/passt.h +++ b/passt.h @@ -101,9 +101,9 @@ enum passt_modes { * @addr_seen: Latest IPv4 address seen as source from tap * @prefixlen: IPv4 prefix length (netmask) * @gw: Default IPv4 gateway, network order - * @dns: Host IPv4 DNS addresses, zero-terminated, network order - * @dns_send: Offered IPv4 DNS, zero-terminated, network order - * @dns_fwd: Address forwarded (UDP) to first IPv4 DNS, network order + * @dns: DNS addresses for DHCP, zero-terminated, network order + * @dns_match: Forward DNS query if sent to this address, network order + * @dns_host: Use this DNS on the host for forwarding, network order */ struct ip4_ctx { struct in_addr addr; @@ -111,8 +111,8 @@ struct ip4_ctx { int prefix_len; struct in_addr gw; struct in_addr dns[MAXNS + 1]; - struct in_addr dns_send[MAXNS + 1]; - struct in_addr dns_fwd; + struct in_addr dns_match; + struct in_addr dns_host; }; /** @@ -122,9 +122,9 @@ struct ip4_ctx { * @addr_seen: Latest IPv6 global/site address seen as source from tap * @addr_ll_seen: Latest IPv6 link-local address seen as source from tap * @gw: Default IPv6 gateway - * @dns: Host IPv6 DNS addresses, zero-terminated - * @dns_send: Offered IPv6 DNS addresses, zero-terminated - * @dns_fwd: Address forwarded (UDP) to first IPv6 DNS, network order + * @dns: DNS addresses for DHCPv6 and NDP, zero-terminated + * @dns_match: Forward DNS query if sent to this address + * @dns_host: Use this DNS on the host for forwarding */ struct ip6_ctx { struct in6_addr addr; @@ -133,8 +133,8 @@ struct ip6_ctx { struct in6_addr addr_ll_seen; struct in6_addr gw; struct in6_addr dns[MAXNS + 1]; - struct in6_addr dns_send[MAXNS + 1]; - struct in6_addr dns_fwd; + struct in6_addr dns_match; + struct in6_addr dns_host; }; #include diff --git a/udp.c b/udp.c index ff7f993..0aa6308 100644 --- a/udp.c +++ b/udp.c @@ -678,10 +678,10 @@ static void udp_sock_fill_data_v4(const struct ctx *c, int n, src_port = ntohs(b->s_in.sin_port); - if (!IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_fwd) && - IN4_ARE_ADDR_EQUAL(&b->s_in.sin_addr, &c->ip4.dns[0]) && + if (!IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_match) && + IN4_ARE_ADDR_EQUAL(&b->s_in.sin_addr, &c->ip4.dns_host) && src_port == 53) { - b->iph.saddr = c->ip4.dns_fwd.s_addr; + b->iph.saddr = c->ip4.dns_match.s_addr; } else if (IN4_IS_ADDR_LOOPBACK(&b->s_in.sin_addr) || IN4_IS_ADDR_UNSPECIFIED(&b->s_in.sin_addr)|| IN4_ARE_ADDR_EQUAL(&b->s_in.sin_addr, &c->ip4.addr_seen)) { @@ -770,10 +770,11 @@ static void udp_sock_fill_data_v6(const struct ctx *c, int n, if (IN6_IS_ADDR_LINKLOCAL(src)) { b->ip6h.daddr = c->ip6.addr_ll_seen; b->ip6h.saddr = b->s_in6.sin6_addr; - } else if (!IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_fwd) && - IN6_ARE_ADDR_EQUAL(src, &c->ip6.dns[0]) && src_port == 53) { + } else if (!IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_match) && + IN6_ARE_ADDR_EQUAL(src, &c->ip6.dns_host) && + src_port == 53) { b->ip6h.daddr = c->ip6.addr_seen; - b->ip6h.saddr = c->ip6.dns_fwd; + b->ip6h.saddr = c->ip6.dns_match; } else if (IN6_IS_ADDR_LOOPBACK(src) || IN6_ARE_ADDR_EQUAL(src, &c->ip6.addr_seen) || IN6_ARE_ADDR_EQUAL(src, &c->ip6.addr)) { @@ -1016,13 +1017,15 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr, udp_tap_map[V4][src].ts = now->tv_sec; - if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr, &c->ip4.gw) && !c->no_map_gw) { + if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr, &c->ip4.gw) && + !c->no_map_gw) { if (!(udp_tap_map[V4][dst].flags & PORT_LOCAL) || (udp_tap_map[V4][dst].flags & PORT_LOOPBACK)) s_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); else s_in.sin_addr = c->ip4.addr_seen; - } else if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr, &c->ip4.dns_fwd) && + } else if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr, + &c->ip4.dns_match) && ntohs(s_in.sin_port) == 53) { s_in.sin_addr = c->ip4.dns[0]; } @@ -1045,7 +1048,7 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr, s_in6.sin6_addr = c->ip6.addr; else s_in6.sin6_addr = c->ip6.addr_seen; - } else if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.dns_fwd) && + } else if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.dns_match) && ntohs(s_in6.sin6_port) == 53) { s_in6.sin6_addr = c->ip6.dns[0]; } else if (IN6_IS_ADDR_LINKLOCAL(&s_in6.sin6_addr)) {