summaryrefslogtreecommitdiff
path: root/src/resolve/resolved-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/resolve/resolved-manager.c')
-rw-r--r--src/resolve/resolved-manager.c62
1 files changed, 52 insertions, 10 deletions
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index e8811fa1d8..30036049da 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -36,6 +36,7 @@
#include "random-util.h"
#include "resolved-bus.h"
#include "resolved-conf.h"
+#include "resolved-dns-stub.h"
#include "resolved-etc-hosts.h"
#include "resolved-llmnr.h"
#include "resolved-manager.h"
@@ -493,6 +494,7 @@ int manager_new(Manager **ret) {
m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
m->mdns_ipv4_fd = m->mdns_ipv6_fd = -1;
+ m->dns_stub_udp_fd = m->dns_stub_tcp_fd = -1;
m->hostname_fd = -1;
m->llmnr_support = RESOLVE_SUPPORT_YES;
@@ -555,6 +557,10 @@ int manager_start(Manager *m) {
assert(m);
+ r = manager_dns_stub_start(m);
+ if (r < 0)
+ return r;
+
r = manager_llmnr_start(m);
if (r < 0)
return r;
@@ -584,6 +590,11 @@ Manager *manager_free(Manager *m) {
dns_scope_free(m->unicast_scope);
+ /* At this point only orphaned streams should remain. All others should have been freed already by their
+ * owners */
+ while (m->dns_streams)
+ dns_stream_unref(m->dns_streams);
+
hashmap_free(m->links);
hashmap_free(m->dns_transactions);
@@ -595,6 +606,7 @@ Manager *manager_free(Manager *m) {
manager_llmnr_stop(m);
manager_mdns_stop(m);
+ manager_dns_stub_stop(m);
sd_bus_slot_unref(m->prepare_for_sleep_slot);
sd_event_source_unref(m->bus_retry_event_source);
@@ -809,7 +821,14 @@ int manager_write(Manager *m, int fd, DnsPacket *p) {
return 0;
}
-static int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_addr *addr, uint16_t port, DnsPacket *p) {
+static int manager_ipv4_send(
+ Manager *m,
+ int fd,
+ int ifindex,
+ const struct in_addr *destination,
+ uint16_t port,
+ const struct in_addr *source,
+ DnsPacket *p) {
union sockaddr_union sa = {
.in.sin_family = AF_INET,
};
@@ -822,14 +841,14 @@ static int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_ad
assert(m);
assert(fd >= 0);
- assert(addr);
+ assert(destination);
assert(port > 0);
assert(p);
iov.iov_base = DNS_PACKET_DATA(p);
iov.iov_len = p->size;
- sa.in.sin_addr = *addr;
+ sa.in.sin_addr = *destination;
sa.in.sin_port = htobe16(port),
mh.msg_iov = &iov;
@@ -853,12 +872,23 @@ static int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_ad
pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
pi->ipi_ifindex = ifindex;
+
+ if (source)
+ pi->ipi_spec_dst = *source;
}
return sendmsg_loop(fd, &mh, 0);
}
-static int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_addr *addr, uint16_t port, DnsPacket *p) {
+static int manager_ipv6_send(
+ Manager *m,
+ int fd,
+ int ifindex,
+ const struct in6_addr *destination,
+ uint16_t port,
+ const struct in6_addr *source,
+ DnsPacket *p) {
+
union sockaddr_union sa = {
.in6.sin6_family = AF_INET6,
};
@@ -871,14 +901,14 @@ static int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_a
assert(m);
assert(fd >= 0);
- assert(addr);
+ assert(destination);
assert(port > 0);
assert(p);
iov.iov_base = DNS_PACKET_DATA(p);
iov.iov_len = p->size;
- sa.in6.sin6_addr = *addr;
+ sa.in6.sin6_addr = *destination;
sa.in6.sin6_port = htobe16(port),
sa.in6.sin6_scope_id = ifindex;
@@ -903,24 +933,36 @@ static int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_a
pi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
pi->ipi6_ifindex = ifindex;
+
+ if (source)
+ pi->ipi6_addr = *source;
}
return sendmsg_loop(fd, &mh, 0);
}
-int manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p) {
+int manager_send(
+ Manager *m,
+ int fd,
+ int ifindex,
+ int family,
+ const union in_addr_union *destination,
+ uint16_t port,
+ const union in_addr_union *source,
+ DnsPacket *p) {
+
assert(m);
assert(fd >= 0);
- assert(addr);
+ assert(destination);
assert(port > 0);
assert(p);
log_debug("Sending %s packet with id %" PRIu16 " on interface %i/%s.", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p), ifindex, af_to_name(family));
if (family == AF_INET)
- return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p);
+ return manager_ipv4_send(m, fd, ifindex, &destination->in, port, &source->in, p);
if (family == AF_INET6)
- return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p);
+ return manager_ipv6_send(m, fd, ifindex, &destination->in6, port, &source->in6, p);
return -EAFNOSUPPORT;
}