DEFINE_HASH_OPS(dns_packet_hash_ops, DnsPacket, dns_packet_hash_func, dns_packet_compare_func);
+bool dns_packet_equal(const DnsPacket *a, const DnsPacket *b) {
+ return dns_packet_compare_func(a, b) == 0;
+}
+
static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
[DNS_RCODE_SUCCESS] = "SUCCESS",
[DNS_RCODE_FORMERR] = "FORMERR",
int dns_packet_skip_question(DnsPacket *p);
int dns_packet_extract(DnsPacket *p);
+bool dns_packet_equal(const DnsPacket *a, const DnsPacket *b);
+
/* https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6 */
enum {
DNS_RCODE_SUCCESS = 0,
return;
}
+ if (manager_packet_from_our_transaction(m, p)) {
+ log_debug("Got our own packet looped back, ignoring.");
+ return;
+ }
+
r = dns_packet_extract(p);
if (r < 0) {
log_debug_errno(r, "Failed to extract resources from incoming packet, ignoring packet: %m");
return !!manager_find_link_address(m, p->family, &p->sender);
}
+bool manager_packet_from_our_transaction(Manager *m, DnsPacket *p) {
+ DnsTransaction *t;
+
+ assert(m);
+ assert(p);
+
+ /* Let's see if we have a transaction with a query message with the exact same binary contents as the
+ * one we just got. If so, it's almost definitely a packet loop of some kind. */
+
+ t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
+ if (!t)
+ return false;
+
+ return t->sent && dns_packet_equal(t->sent, p);
+}
+
DnsScope* manager_find_scope(Manager *m, DnsPacket *p) {
Link *l;
int manager_next_hostname(Manager *m);
bool manager_packet_from_local_address(Manager *m, DnsPacket *p);
+bool manager_packet_from_our_transaction(Manager *m, DnsPacket *p);
+
DnsScope* manager_find_scope(Manager *m, DnsPacket *p);
void manager_verify_all(Manager *m);