summaryrefslogtreecommitdiff
path: root/src/resolve/resolved-dns-packet.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-12-26 18:49:32 +0100
committerLennart Poettering <lennart@poettering.net>2015-12-27 01:41:40 +0100
commit519ef04651b07a547f010d6462603669d7fde4e5 (patch)
tree468de1de3bee781032f0be705587a116096faf41 /src/resolve/resolved-dns-packet.c
parent97cc656cf40e104c0305bde71ec6e835650ac3cb (diff)
resolved: rework OPT RR generation logic
This moves management of the OPT RR out of the scope management and into the server and packet management. There are now explicit calls for appending and truncating the OPT RR from a packet (dns_packet_append_opt() and dns_packet_truncate_opt()) as well as a call to do the right thing depending on a DnsServer's feature level (dns_server_adjust_opt()). This also unifies the code to pick a server between the TCP and UDP code paths, and makes sure the feature level used for the transaction is selected at the time the server is picked, and not changed until the next time we pick a server. The server selction code is now unified in dns_transaction_pick_server(). This all fixes problems when changing between UDP and TCP communication for the same server, and makes sure the UDP and TCP codepaths are more alike. It also makes sure we never keep the UDP port open when switchung to TCP, so that we don't have to handle incoming datagrams on the latter we don't expect. As the new code picks the DNS server at the time we make a connection, we don't need to invalidate the DNS server anymore when changing to the next one, thus dns_transaction_next_dns_server() has been removed.
Diffstat (limited to 'src/resolve/resolved-dns-packet.c')
-rw-r--r--src/resolve/resolved-dns-packet.c35
1 files changed, 33 insertions, 2 deletions
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index c425b89034..5f79701296 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -58,6 +58,7 @@ int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
p->size = p->rindex = DNS_PACKET_HEADER_SIZE;
p->allocated = a;
p->protocol = protocol;
+ p->opt_start = p->opt_size = (size_t) -1;
p->n_ref = 1;
*ret = p;
@@ -681,7 +682,7 @@ fail:
}
/* Append the OPT pseudo-RR described in RFC6891 */
-int dns_packet_append_opt_rr(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, size_t *start) {
+int dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, size_t *start) {
size_t saved_size;
int r;
@@ -689,6 +690,11 @@ int dns_packet_append_opt_rr(DnsPacket *p, uint16_t max_udp_size, bool edns0_do,
/* we must never advertise supported packet size smaller than the legacy max */
assert(max_udp_size >= DNS_PACKET_UNICAST_SIZE_MAX);
+ if (p->opt_start != (size_t) -1)
+ return -EBUSY;
+
+ assert(p->opt_size == (size_t) -1);
+
saved_size = p->size;
/* empty name */
@@ -721,6 +727,11 @@ int dns_packet_append_opt_rr(DnsPacket *p, uint16_t max_udp_size, bool edns0_do,
if (r < 0)
goto fail;
+ DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) + 1);
+
+ p->opt_start = saved_size;
+ p->opt_size = p->size - saved_size;
+
if (start)
*start = saved_size;
@@ -731,6 +742,27 @@ fail:
return r;
}
+int dns_packet_truncate_opt(DnsPacket *p) {
+ assert(p);
+
+ if (p->opt_start == (size_t) -1) {
+ assert(p->opt_size == (size_t) -1);
+ return 0;
+ }
+
+ assert(p->opt_size != (size_t) -1);
+ assert(DNS_PACKET_ARCOUNT(p) > 0);
+
+ if (p->opt_start + p->opt_size != p->size)
+ return -EBUSY;
+
+ dns_packet_truncate(p, p->opt_start);
+ DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) - 1);
+ p->opt_start = p->opt_size = (size_t) -1;
+
+ return 1;
+}
+
int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start, size_t *rdata_start) {
size_t saved_size, rdlength_offset, end, rdlength, rds;
int r;
@@ -1046,7 +1078,6 @@ fail:
return r;
}
-
int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
assert(p);