manager_next_dns_server(s->manager);
}
-int dns_scope_emit(DnsScope *s, DnsPacket *p) {
+int dns_scope_emit(DnsScope *s, DnsPacket *p, DnsServer **server) {
+ DnsServer *srv = NULL;
union in_addr_union addr;
int ifindex = 0, r;
int family;
mtu = manager_find_mtu(s->manager);
if (s->protocol == DNS_PROTOCOL_DNS) {
- DnsServer *srv;
-
if (DNS_PACKET_QDCOUNT(p) > 1)
return -EOPNOTSUPP;
if (r < 0)
return r;
+ if (server)
+ *server = srv;
+
return 1;
}
-int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port) {
+int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port, DnsServer **server) {
+ DnsServer *srv = NULL;
_cleanup_close_ int fd = -1;
union sockaddr_union sa = {};
socklen_t salen;
assert((family == AF_UNSPEC) == !address);
if (family == AF_UNSPEC) {
- DnsServer *srv;
-
srv = dns_scope_get_dns_server(s);
if (!srv)
return -ESRCH;
if (r < 0 && errno != EINPROGRESS)
return -errno;
+ if (server)
+ *server = srv;
+
ret = fd;
fd = -1;
return 0;
}
- r = dns_scope_emit(scope, p);
+ r = dns_scope_emit(scope, p, NULL);
if (r < 0)
log_debug_errno(r, "Failed to send conflict packet: %m");
}
int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol p, int family);
DnsScope* dns_scope_free(DnsScope *s);
-int dns_scope_emit(DnsScope *s, DnsPacket *p);
-int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port);
+int dns_scope_emit(DnsScope *s, DnsPacket *p, DnsServer **server);
+int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port, DnsServer **server);
DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain);
int dns_scope_good_key(DnsScope *s, DnsResourceKey *key);
dns_packet_unref(t->received);
dns_answer_unref(t->cached);
+ dns_server_unref(t->server);
dns_stream_free(t->stream);
if (t->scope) {
}
static int dns_transaction_open_tcp(DnsTransaction *t) {
+ _cleanup_(dns_server_unrefp) DnsServer *server = NULL;
_cleanup_close_ int fd = -1;
int r;
return 0;
if (t->scope->protocol == DNS_PROTOCOL_DNS)
- fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53);
+ fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53, &server);
else if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
/* When we already received a query to this (but it was truncated), send to its sender address */
if (t->received)
- fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port);
+ fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port, NULL);
else {
union in_addr_union address;
int family = AF_UNSPEC;
if (r == 0)
return -EINVAL;
- fd = dns_scope_tcp_socket(t->scope, family, &address, LLMNR_PORT);
+ fd = dns_scope_tcp_socket(t->scope, family, &address, LLMNR_PORT, NULL);
}
} else
return -EAFNOSUPPORT;
return r;
}
+
+ dns_server_unref(t->server);
+ t->server = dns_server_ref(server);
t->received = dns_packet_unref(t->received);
t->stream->complete = on_stream_complete;
t->stream->transaction = t;
}
t->n_attempts++;
+ t->server = dns_server_unref(t->server);
t->received = dns_packet_unref(t->received);
t->cached = dns_answer_unref(t->cached);
t->cached_rcode = 0;
* always be made via TCP on LLMNR */
r = dns_transaction_open_tcp(t);
} else {
+ DnsServer *server;
+
/* Try via UDP, and if that fails due to large size try via TCP */
- r = dns_scope_emit(t->scope, t->sent);
- if (r == -EMSGSIZE)
+ r = dns_scope_emit(t->scope, t->sent, &server);
+ if (r >= 0)
+ t->server = dns_server_ref(server);
+ else if (r == -EMSGSIZE)
r = dns_transaction_open_tcp(t);
}
if (r == -ESRCH) {
/* No servers to send this to? */
dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
return 0;
- }
- if (r < 0) {
+ } else if (r < 0) {
if (t->scope->protocol != DNS_PROTOCOL_DNS) {
dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
return 0;