X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fresolve%2Fresolved-dns-transaction.c;h=74b0634142be5fbd9fd141969402c27ac44617be;hp=53d6e18dc53b492d72cae392147c546a2d09f39d;hb=30fbcf24460263961855e0ce4d8867fd2af3e149;hpb=6e0684729420912df019cc64d3f8a3c8290cc5f1 diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index 53d6e18dc..74b063414 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -78,7 +78,7 @@ int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsQuestion *q) { assert(s); assert(q); - r = hashmap_ensure_allocated(&s->manager->dns_transactions, NULL, NULL); + r = hashmap_ensure_allocated(&s->manager->dns_transactions, NULL); if (r < 0) return r; @@ -118,8 +118,8 @@ static void dns_transaction_stop(DnsTransaction *t) { } static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) { + _cleanup_free_ char *pretty = NULL; DnsZoneItem *z; - Iterator i; assert(t); assert(p); @@ -127,14 +127,33 @@ static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) { if (manager_our_packet(t->scope->manager, p) != 0) return; - log_debug("Transaction on scope %s on %s/%s got tentative packet", + in_addr_to_string(p->family, &p->sender, &pretty); + + log_debug("Transaction on scope %s on %s/%s got tentative packet from %s", dns_protocol_to_string(t->scope->protocol), t->scope->link ? t->scope->link->name : "*", - t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family)); + t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family), + pretty); + + /* RFC 4795, Section 4.1 says that the peer with the + * lexicographically smaller IP address loses */ + if (memcmp(&p->sender, &p->destination, FAMILY_ADDRESS_SIZE(p->family)) >= 0) { + log_debug("Peer has lexicographically larger IP address and thus lost in the conflict."); + return; + } + + log_debug("We have the lexicographically larger IP address and thus lost in the conflict."); t->block_gc++; - SET_FOREACH(z, t->zone_items, i) + while ((z = set_first(t->zone_items))) { + /* First, make sure the zone item drops the reference + * to us */ + dns_zone_item_probe_stop(z); + + /* Secondly, report this as conflict, so that we might + * look for a different hostname */ dns_zone_item_conflict(z); + } t->block_gc--; dns_transaction_gc(t); @@ -147,7 +166,9 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) { assert(t); assert(!IN_SET(state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING)); - assert(IN_SET(t->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING)); + + if (!IN_SET(t->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING)) + return; /* Note that this call might invalidate the query. Callers * should hence not attempt to access the query or transaction @@ -194,6 +215,14 @@ static int on_stream_complete(DnsStream *s, int error) { return 0; } + if (dns_packet_validate_reply(p) <= 0) { + log_debug("Invalid LLMNR TCP packet."); + dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); + return 0; + } + + dns_scope_check_conflicts(t->scope, p); + t->block_gc++; dns_transaction_process_reply(t, p); t->block_gc--; @@ -368,7 +397,7 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) { } /* According to RFC 4795, section 2.9. only the RRs from the answer section shall be cached */ - dns_cache_put(&t->scope->cache, p->question, DNS_PACKET_RCODE(p), p->answer, DNS_PACKET_ANCOUNT(p), 0); + dns_cache_put(&t->scope->cache, p->question, DNS_PACKET_RCODE(p), p->answer, DNS_PACKET_ANCOUNT(p), 0, p->family, &p->sender); if (DNS_PACKET_RCODE(p) == DNS_RCODE_SUCCESS) dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS); @@ -443,7 +472,7 @@ int dns_transaction_go(DnsTransaction *t) { dns_transaction_stop(t); - log_debug("Beginning transaction on scope %s on %s/%s", + log_debug("Excercising transaction on scope %s on %s/%s", dns_protocol_to_string(t->scope->protocol), t->scope->link ? t->scope->link->name : "*", t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family)); @@ -505,7 +534,8 @@ int dns_transaction_go(DnsTransaction *t) { t->scope->manager->event, &t->timeout_event_source, clock_boottime_or_monotonic(), - now(clock_boottime_or_monotonic()) + jitter, LLMNR_JITTER_INTERVAL_USEC, + now(clock_boottime_or_monotonic()) + jitter, + LLMNR_JITTER_INTERVAL_USEC, on_transaction_timeout, t); if (r < 0) return r; @@ -540,7 +570,7 @@ int dns_transaction_go(DnsTransaction *t) { r = dns_transaction_open_tcp(t); } else { /* Try via UDP, and if that fails due to large size try via TCP */ - r = dns_scope_send(t->scope, t->sent); + r = dns_scope_emit(t->scope, t->sent); if (r == -EMSGSIZE) r = dns_transaction_open_tcp(t); }