+void link_address_add_rrs(LinkAddress *a, bool force_remove) {
+ int r;
+
+ assert(a);
+
+ if (a->family == AF_INET) {
+
+ if (!force_remove &&
+ link_address_relevant(a) &&
+ a->link->llmnr_ipv4_scope &&
+ a->link->llmnr_support == SUPPORT_YES &&
+ a->link->manager->llmnr_support == SUPPORT_YES) {
+
+ if (!a->link->manager->host_ipv4_key) {
+ a->link->manager->host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->hostname);
+ if (!a->link->manager->host_ipv4_key) {
+ r = -ENOMEM;
+ goto fail;
+ }
+ }
+
+ if (!a->llmnr_address_rr) {
+ a->llmnr_address_rr = dns_resource_record_new(a->link->manager->host_ipv4_key);
+ if (!a->llmnr_address_rr) {
+ r = -ENOMEM;
+ goto fail;
+ }
+
+ a->llmnr_address_rr->a.in_addr = a->in_addr.in;
+ a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
+ }
+
+ if (!a->llmnr_ptr_rr) {
+ r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->hostname);
+ if (r < 0)
+ goto fail;
+
+ a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
+ }
+
+ r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_address_rr, true);
+ if (r < 0)
+ log_warning_errno(r, "Failed to add A record to LLMNR zone: %m");
+
+ r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_ptr_rr, false);
+ if (r < 0)
+ log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m");
+ } else {
+ if (a->llmnr_address_rr) {
+ if (a->link->llmnr_ipv4_scope)
+ dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
+ a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
+ }
+
+ if (a->llmnr_ptr_rr) {
+ if (a->link->llmnr_ipv4_scope)
+ dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
+ a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
+ }
+ }
+ }
+
+ if (a->family == AF_INET6) {
+
+ if (!force_remove &&
+ link_address_relevant(a) &&
+ a->link->llmnr_ipv6_scope &&
+ a->link->llmnr_support == SUPPORT_YES &&
+ a->link->manager->llmnr_support == SUPPORT_YES) {
+
+ if (!a->link->manager->host_ipv6_key) {
+ a->link->manager->host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->hostname);
+ if (!a->link->manager->host_ipv6_key) {
+ r = -ENOMEM;
+ goto fail;
+ }
+ }
+
+ if (!a->llmnr_address_rr) {
+ a->llmnr_address_rr = dns_resource_record_new(a->link->manager->host_ipv6_key);
+ if (!a->llmnr_address_rr) {
+ r = -ENOMEM;
+ goto fail;
+ }
+
+ a->llmnr_address_rr->aaaa.in6_addr = a->in_addr.in6;
+ a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
+ }
+
+ if (!a->llmnr_ptr_rr) {
+ r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->hostname);
+ if (r < 0)
+ goto fail;
+
+ a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
+ }
+
+ r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_address_rr, true);
+ if (r < 0)
+ log_warning_errno(r, "Failed to add AAAA record to LLMNR zone: %m");
+
+ r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_ptr_rr, false);
+ if (r < 0)
+ log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m");
+ } else {
+ if (a->llmnr_address_rr) {
+ if (a->link->llmnr_ipv6_scope)
+ dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
+ a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
+ }
+
+ if (a->llmnr_ptr_rr) {
+ if (a->link->llmnr_ipv6_scope)
+ dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
+ a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
+ }
+ }
+ }
+
+ return;
+
+fail:
+ log_debug_errno(r, "Failed to update address RRs: %m");
+}
+