summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/resolve/resolved-dns-packet.c2
-rw-r--r--src/resolve/resolved-dns-packet.h2
-rw-r--r--src/resolve/resolved-dns-scope.c21
-rw-r--r--src/resolve/resolved-dns-scope.h2
-rw-r--r--src/resolve/resolved-dns-server.c1
-rw-r--r--src/resolve/resolved-dns-server.h1
-rw-r--r--src/resolve/resolved-dns-transaction.c2
7 files changed, 26 insertions, 5 deletions
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index 49c36e38f3..cb713f1f85 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -267,7 +267,7 @@ static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start
return 0;
}
-static void dns_packet_truncate(DnsPacket *p, size_t sz) {
+void dns_packet_truncate(DnsPacket *p, size_t sz) {
Iterator i;
char *s;
void *n;
diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h
index ca94a208ba..385a8af796 100644
--- a/src/resolve/resolved-dns-packet.h
+++ b/src/resolve/resolved-dns-packet.h
@@ -162,6 +162,8 @@ int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *key, size_t *start
int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start);
int dns_packet_append_opt_rr(DnsPacket *p, uint16_t max_udp_size, size_t *start);
+void dns_packet_truncate(DnsPacket *p, size_t sz);
+
int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start);
int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start);
int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start);
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index a8c0ae1569..42478e41e2 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -158,12 +158,13 @@ void dns_scope_packet_lost(DnsScope *s, usec_t usec) {
s->resend_timeout = MIN(s->resend_timeout * 2, MULTICAST_RESEND_TIMEOUT_MAX_USEC);
}
-int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p) {
+int dns_scope_emit(DnsScope *s, int fd, DnsServer *server, DnsPacket *p) {
union in_addr_union addr;
int ifindex = 0, r;
int family;
uint16_t port;
uint32_t mtu;
+ size_t saved_size = 0;
assert(s);
assert(p);
@@ -178,9 +179,19 @@ int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p) {
switch (s->protocol) {
case DNS_PROTOCOL_DNS:
+ assert(server);
+
if (DNS_PACKET_QDCOUNT(p) > 1)
return -EOPNOTSUPP;
+ if (server->possible_features >= DNS_SERVER_FEATURE_LEVEL_EDNS0) {
+ r = dns_packet_append_opt_rr(p, DNS_PACKET_UNICAST_SIZE_MAX, &saved_size);
+ if (r < 0)
+ return r;
+
+ DNS_PACKET_HEADER(p)->arcount = htobe16(be16toh(DNS_PACKET_HEADER(p)->arcount) + 1);
+ }
+
if (p->size > DNS_PACKET_UNICAST_SIZE_MAX)
return -EMSGSIZE;
@@ -191,6 +202,12 @@ int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p) {
if (r < 0)
return r;
+ if (saved_size > 0) {
+ dns_packet_truncate(p, saved_size);
+
+ DNS_PACKET_HEADER(p)->arcount = htobe16(be16toh(DNS_PACKET_HEADER(p)->arcount) - 1);
+ }
+
break;
case DNS_PROTOCOL_LLMNR:
@@ -739,7 +756,7 @@ static int on_conflict_dispatch(sd_event_source *es, usec_t usec, void *userdata
return 0;
}
- r = dns_scope_emit(scope, -1, p);
+ r = dns_scope_emit(scope, -1, NULL, p);
if (r < 0)
log_debug_errno(r, "Failed to send conflict packet: %m");
}
diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h
index 7876410b7d..0480f702f8 100644
--- a/src/resolve/resolved-dns-scope.h
+++ b/src/resolve/resolved-dns-scope.h
@@ -80,7 +80,7 @@ DnsScope* dns_scope_free(DnsScope *s);
void dns_scope_packet_received(DnsScope *s, usec_t rtt);
void dns_scope_packet_lost(DnsScope *s, usec_t usec);
-int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p);
+int dns_scope_emit(DnsScope *s, int fd, DnsServer *server, DnsPacket *p);
int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port, DnsServer **server);
int dns_scope_udp_dns_socket(DnsScope *s, DnsServer **server);
diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c
index c5396a03c8..f8c921e4c8 100644
--- a/src/resolve/resolved-dns-server.c
+++ b/src/resolve/resolved-dns-server.c
@@ -478,5 +478,6 @@ void manager_next_dns_server(Manager *m) {
static const char* const dns_server_feature_level_table[_DNS_SERVER_FEATURE_LEVEL_MAX] = {
[DNS_SERVER_FEATURE_LEVEL_TCP] = "TCP",
[DNS_SERVER_FEATURE_LEVEL_UDP] = "UDP",
+ [DNS_SERVER_FEATURE_LEVEL_EDNS0] = "UDP+EDNS0",
};
DEFINE_STRING_TABLE_LOOKUP(dns_server_feature_level, DnsServerFeatureLevel);
diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h
index a3e8cbcc52..e9b425430f 100644
--- a/src/resolve/resolved-dns-server.h
+++ b/src/resolve/resolved-dns-server.h
@@ -34,6 +34,7 @@ typedef enum DnsServerType {
typedef enum DnsServerFeatureLevel {
DNS_SERVER_FEATURE_LEVEL_TCP,
DNS_SERVER_FEATURE_LEVEL_UDP,
+ DNS_SERVER_FEATURE_LEVEL_EDNS0,
_DNS_SERVER_FEATURE_LEVEL_MAX,
_DNS_SERVER_FEATURE_LEVEL_INVALID = -1
} DnsServerFeatureLevel;
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index 4398c2cb99..f81461a4fe 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -545,7 +545,7 @@ static int dns_transaction_emit(DnsTransaction *t) {
t->server = dns_server_ref(server);
}
- r = dns_scope_emit(t->scope, t->dns_udp_fd, t->sent);
+ r = dns_scope_emit(t->scope, t->dns_udp_fd, t->server, t->sent);
if (r < 0)
return r;