Skip to content

Commit a407657

Browse files
committed
resolved: implement full LLMNR conflict detection logic
1 parent 3ef77d0 commit a407657

11 files changed

+467
-58
lines changed

src/resolve/resolved-dns-cache.c

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ struct DnsCacheItem {
4343
usec_t until;
4444
DnsCacheItemType type;
4545
unsigned prioq_idx;
46+
int owner_family;
47+
union in_addr_union owner_address;
4648
LIST_FIELDS(DnsCacheItem, by_key);
4749
};
4850

@@ -256,13 +258,20 @@ static void dns_cache_item_update_positive(DnsCache *c, DnsCacheItem *i, DnsReso
256258
prioq_reshuffle(c->by_expiry, i, &i->prioq_idx);
257259
}
258260

259-
static int dns_cache_put_positive(DnsCache *c, DnsResourceRecord *rr, usec_t timestamp) {
261+
static int dns_cache_put_positive(
262+
DnsCache *c,
263+
DnsResourceRecord *rr,
264+
usec_t timestamp,
265+
int owner_family,
266+
const union in_addr_union *owner_address) {
267+
260268
_cleanup_(dns_cache_item_freep) DnsCacheItem *i = NULL;
261269
DnsCacheItem *existing;
262270
int r;
263271

264272
assert(c);
265273
assert(rr);
274+
assert(owner_address);
266275

267276
/* New TTL is 0? Delete the entry... */
268277
if (rr->ttl <= 0) {
@@ -298,6 +307,8 @@ static int dns_cache_put_positive(DnsCache *c, DnsResourceRecord *rr, usec_t tim
298307
i->rr = dns_resource_record_ref(rr);
299308
i->until = timestamp + MIN(i->rr->ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC);
300309
i->prioq_idx = PRIOQ_IDX_NULL;
310+
i->owner_family = owner_family;
311+
i->owner_address = *owner_address;
301312

302313
r = dns_cache_link_item(c, i);
303314
if (r < 0)
@@ -307,12 +318,21 @@ static int dns_cache_put_positive(DnsCache *c, DnsResourceRecord *rr, usec_t tim
307318
return 0;
308319
}
309320

310-
static int dns_cache_put_negative(DnsCache *c, DnsResourceKey *key, int rcode, usec_t timestamp, uint32_t soa_ttl) {
321+
static int dns_cache_put_negative(
322+
DnsCache *c,
323+
DnsResourceKey *key,
324+
int rcode,
325+
usec_t timestamp,
326+
uint32_t soa_ttl,
327+
int owner_family,
328+
const union in_addr_union *owner_address) {
329+
311330
_cleanup_(dns_cache_item_freep) DnsCacheItem *i = NULL;
312331
int r;
313332

314333
assert(c);
315334
assert(key);
335+
assert(owner_address);
316336

317337
dns_cache_remove(c, key);
318338

@@ -340,6 +360,8 @@ static int dns_cache_put_negative(DnsCache *c, DnsResourceKey *key, int rcode, u
340360
i->key = dns_resource_key_ref(key);
341361
i->until = timestamp + MIN(soa_ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC);
342362
i->prioq_idx = PRIOQ_IDX_NULL;
363+
i->owner_family = owner_family;
364+
i->owner_address = *owner_address;
343365

344366
r = dns_cache_link_item(c, i);
345367
if (r < 0)
@@ -349,7 +371,16 @@ static int dns_cache_put_negative(DnsCache *c, DnsResourceKey *key, int rcode, u
349371
return 0;
350372
}
351373

352-
int dns_cache_put(DnsCache *c, DnsQuestion *q, int rcode, DnsAnswer *answer, unsigned max_rrs, usec_t timestamp) {
374+
int dns_cache_put(
375+
DnsCache *c,
376+
DnsQuestion *q,
377+
int rcode,
378+
DnsAnswer *answer,
379+
unsigned max_rrs,
380+
usec_t timestamp,
381+
int owner_family,
382+
const union in_addr_union *owner_address) {
383+
353384
unsigned i;
354385
int r;
355386

@@ -382,7 +413,7 @@ int dns_cache_put(DnsCache *c, DnsQuestion *q, int rcode, DnsAnswer *answer, uns
382413

383414
/* Second, add in positive entries for all contained RRs */
384415
for (i = 0; i < MIN(max_rrs, answer->n_rrs); i++) {
385-
r = dns_cache_put_positive(c, answer->rrs[i], timestamp);
416+
r = dns_cache_put_positive(c, answer->rrs[i], timestamp, owner_family, owner_address);
386417
if (r < 0)
387418
goto fail;
388419
}
@@ -403,7 +434,7 @@ int dns_cache_put(DnsCache *c, DnsQuestion *q, int rcode, DnsAnswer *answer, uns
403434
if (r == 0)
404435
continue;
405436

406-
r = dns_cache_put_negative(c, q->keys[i], rcode, timestamp, MIN(soa->soa.minimum, soa->ttl));
437+
r = dns_cache_put_negative(c, q->keys[i], rcode, timestamp, MIN(soa->soa.minimum, soa->ttl), owner_family, owner_address);
407438
if (r < 0)
408439
goto fail;
409440
}
@@ -495,3 +526,39 @@ int dns_cache_lookup(DnsCache *c, DnsQuestion *q, int *rcode, DnsAnswer **ret) {
495526

496527
return n;
497528
}
529+
530+
int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_family, const union in_addr_union *owner_address) {
531+
DnsCacheItem *i, *first;
532+
bool same_owner = true;
533+
534+
assert(cache);
535+
assert(rr);
536+
537+
dns_cache_prune(cache);
538+
539+
/* See if there's a cache entry for the same key. If there
540+
* isn't there's no conflict */
541+
first = hashmap_get(cache->by_key, rr->key);
542+
if (!first)
543+
return 0;
544+
545+
/* See if the RR key is owned by the same owner, if so, there
546+
* isn't a conflict either */
547+
LIST_FOREACH(by_key, i, first) {
548+
if (i->owner_family != owner_family ||
549+
!in_addr_equal(owner_family, &i->owner_address, owner_address)) {
550+
same_owner = false;
551+
break;
552+
}
553+
}
554+
if (same_owner)
555+
return 0;
556+
557+
/* See if there's the exact same RR in the cache. If yes, then
558+
* there's no conflict. */
559+
if (dns_cache_get(cache, rr))
560+
return 0;
561+
562+
/* There's a conflict */
563+
return 1;
564+
}

src/resolve/resolved-dns-cache.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,7 @@ typedef struct DnsCache {
4040
void dns_cache_flush(DnsCache *c);
4141
void dns_cache_prune(DnsCache *c);
4242

43-
int dns_cache_put(DnsCache *c, DnsQuestion *q, int rcode, DnsAnswer *answer, unsigned max_rrs, usec_t timestamp);
43+
int dns_cache_put(DnsCache *c, DnsQuestion *q, int rcode, DnsAnswer *answer, unsigned max_rrs, usec_t timestamp, int owner_family, const union in_addr_union *owner_address);
4444
int dns_cache_lookup(DnsCache *c, DnsQuestion *q, int *rcode, DnsAnswer **answer);
45+
46+
int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_family, const union in_addr_union *owner_address);

src/resolve/resolved-dns-packet.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,6 +1358,9 @@ int dns_packet_extract(DnsPacket *p) {
13581358
unsigned n, i;
13591359
int r;
13601360

1361+
if (p->extracted)
1362+
return 0;
1363+
13611364
saved_rindex = p->rindex;
13621365
dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
13631366

@@ -1409,6 +1412,8 @@ int dns_packet_extract(DnsPacket *p) {
14091412
p->answer = answer;
14101413
answer = NULL;
14111414

1415+
p->extracted = true;
1416+
14121417
r = 0;
14131418

14141419
finish:

src/resolve/resolved-dns-packet.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ struct DnsPacket {
8181
union in_addr_union sender, destination;
8282
uint16_t sender_port, destination_port;
8383
uint32_t ttl;
84+
85+
bool extracted;
8486
};
8587

8688
static inline uint8_t* DNS_PACKET_DATA(DnsPacket *p) {

0 commit comments

Comments
 (0)