Esempio n. 1
0
const char *dns_server_string(DnsServer *server) {
        assert(server);

        if (!server->server_string)
                (void) in_addr_to_string(server->family, &server->address, &server->server_string);

        return strna(server->server_string);
}
Esempio n. 2
0
static void test_in_addr_to_string_one(int f, const char *addr) {
        union in_addr_union ua;
        _cleanup_free_ char *r = NULL;

        assert_se(in_addr_from_string(f, addr, &ua) >= 0);
        assert_se(in_addr_to_string(f, &ua, &r) >= 0);
        printf("test_in_addr_to_string_one: %s == %s\n", addr, r);
        assert_se(streq(addr, r));
}
Esempio n. 3
0
static void print_local_addresses(struct local_address *a, unsigned n) {
        unsigned i;

        for (i = 0; i < n; i++) {
                _cleanup_free_ char *b = NULL;

                assert_se(in_addr_to_string(a[i].family, &a[i].address, &b) >= 0);
                printf("%s if%i scope=%i metric=%u address=%s\n", af_to_name(a[i].family), a[i].ifindex, a[i].scope, a[i].metric, b);
        }
}
Esempio n. 4
0
static int dump_gateways(
                sd_netlink *rtnl,
                sd_hwdb *hwdb,
                const char *prefix,
                int ifindex) {
        _cleanup_free_ struct local_address *local = NULL;
        int r, n, i;

        n = local_gateways(rtnl, ifindex, AF_UNSPEC, &local);
        if (n < 0)
                return n;

        for (i = 0; i < n; i++) {
                _cleanup_free_ char *gateway = NULL, *description = NULL;

                r = in_addr_to_string(local[i].family, &local[i].address, &gateway);
                if (r < 0)
                        return r;

                r = get_gateway_description(rtnl, hwdb, local[i].ifindex, local[i].family, &local[i].address, &description);
                if (r < 0)
                        log_debug_errno(r, "Could not get description of gateway: %m");

                printf("%*s%s",
                       (int) strlen(prefix),
                       i == 0 ? prefix : "",
                       gateway);

                if (description)
                        printf(" (%s)", description);

                /* Show interface name for the entry if we show
                 * entries for all interfaces */
                if (ifindex <= 0) {
                        char name[IF_NAMESIZE+1];

                        if (if_indextoname(local[i].ifindex, name)) {
                                fputs(" on ", stdout);
                                fputs(name, stdout);
                        } else
                                printf(" on %%%i", local[i].ifindex);
                }

                fputc('\n', stdout);
        }

        return 0;
}
Esempio n. 5
0
static int map_server_address(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
        char **p = (char **) userdata;
        const void *d;
        int family, r;
        size_t sz;

        assert(p);

        r = sd_bus_message_enter_container(m, 'r', "iay");
        if (r < 0)
                return r;

        r = sd_bus_message_read(m, "i", &family);
        if (r < 0)
                return r;

        r = sd_bus_message_read_array(m, 'y', &d, &sz);
        if (r < 0)
                return r;

        r = sd_bus_message_exit_container(m);
        if (r < 0)
                return r;

        if (sz == 0 && family == AF_UNSPEC) {
                *p = mfree(*p);
                return 0;
        }

        if (!IN_SET(family, AF_INET, AF_INET6)) {
                log_error("Unknown address family %i", family);
                return -EINVAL;
        }

        if (sz != FAMILY_ADDRESS_SIZE(family)) {
                log_error("Invalid address size");
                return -EINVAL;
        }

        r = in_addr_to_string(family, d, p);
        if (r < 0)
                return r;

        return 0;
}
Esempio n. 6
0
static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
        _cleanup_free_ char *pretty = NULL;
        DnsZoneItem *z;

        assert(t);
        assert(p);

        if (manager_our_packet(t->scope->manager, p) != 0)
                return;

        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),
                  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++;
        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);
}
Esempio n. 7
0
DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
        assert(m);

        if (m->current_dns_server == s)
                return s;

        if (s) {
                _cleanup_free_ char *ip = NULL;

                in_addr_to_string(s->family, &s->address, &ip);
                log_info("Switching to system DNS server %s.", strna(ip));
        }

        dns_server_unref(m->current_dns_server);
        m->current_dns_server = dns_server_ref(s);

        if (m->unicast_scope)
                dns_cache_flush(&m->unicast_scope->cache);

        return s;
}
Esempio n. 8
0
static int dump_addresses(
                sd_netlink *rtnl,
                const char *prefix,
                int ifindex) {

        _cleanup_free_ struct local_address *local = NULL;
        int r, n, i;

        n = local_addresses(rtnl, ifindex, AF_UNSPEC, &local);
        if (n < 0)
                return n;

        for (i = 0; i < n; i++) {
                _cleanup_free_ char *pretty = NULL;

                r = in_addr_to_string(local[i].family, &local[i].address, &pretty);
                if (r < 0)
                        return r;

                printf("%*s%s",
                       (int) strlen(prefix),
                       i == 0 ? prefix : "",
                       pretty);

                if (ifindex <= 0) {
                        char name[IF_NAMESIZE+1];

                        if (if_indextoname(local[i].ifindex, name)) {
                                fputs(" on ", stdout);
                                fputs(name, stdout);
                        } else
                                printf(" on %%%i", local[i].ifindex);
                }

                fputc('\n', stdout);
        }

        return 0;
}
Esempio n. 9
0
static void ll_handler(sd_ipv4ll *ll, int event, void *userdata) {
        _cleanup_free_ char *address = NULL;
        struct in_addr addr = {};

        assert_se(ll);

        if (sd_ipv4ll_get_address(ll, &addr) >= 0)
                assert_se(in_addr_to_string(AF_INET, (const union in_addr_union*) &addr, &address) >= 0);

        switch (event) {
        case SD_IPV4LL_EVENT_BIND:
                log_info("bound %s", strna(address));
                break;
        case SD_IPV4LL_EVENT_CONFLICT:
                log_info("conflict on %s", strna(address));
                break;
        case SD_IPV4LL_EVENT_STOP:
                log_error("the client was stopped with address %s", strna(address));
                break;
        default:
                assert_not_reached("invalid LL event");
        }
}
Esempio n. 10
0
static int dump_addresses(sd_rtnl *rtnl, const char *prefix, int ifindex) {
        _cleanup_free_ struct local_address *local = NULL;
        int r, n, i;

        n = local_addresses(rtnl, ifindex, &local);
        if (n < 0)
                return n;

        for (i = 0; i < n; i++) {
                _cleanup_free_ char *pretty = NULL;

                r = in_addr_to_string(local[i].family, &local[i].address, &pretty);
                if (r < 0)
                        return r;

                printf("%*s%s\n",
                       (int) strlen(prefix),
                       i == 0 ? prefix : "",
                       pretty);
        }

        return 0;
}
int routing_policy_serialize_rules(Set *rules, FILE *f) {
        RoutingPolicyRule *rule = NULL;
        Iterator i;
        int r;

        assert(f);

        SET_FOREACH(rule, rules, i) {
                _cleanup_free_ char *from_str = NULL, *to_str = NULL;
                bool space = false;

                fputs("RULE=", f);

                if (!in_addr_is_null(rule->family, &rule->from)) {
                        r = in_addr_to_string(rule->family, &rule->from, &from_str);
                        if (r < 0)
                                return r;

                        fprintf(f, "from=%s/%hhu",
                                from_str, rule->from_prefixlen);
                        space = true;
                }

                if (!in_addr_is_null(rule->family, &rule->to)) {
                        r = in_addr_to_string(rule->family, &rule->to, &to_str);
                        if (r < 0)
                                return r;

                        fprintf(f, "%sto=%s/%hhu",
                                space ? " " : "",
                                to_str, rule->to_prefixlen);
                        space = true;
                }

                if (rule->tos != 0) {
                        fprintf(f, "%stos=%hhu",
                                space ? " " : "",
                                rule->tos);
                        space = true;
                }

                if (rule->fwmark != 0) {
                        fprintf(f, "%sfwmark=%"PRIu32"/%"PRIu32,
                                space ? " " : "",
                                rule->fwmark, rule->fwmask);
                        space = true;
                }

                if (rule->iif) {
                        fprintf(f, "%siif=%s",
                                space ? " " : "",
                                rule->iif);
                        space = true;
                }

                if (rule->oif) {
                        fprintf(f, "%soif=%s",
                                space ? " " : "",
                                rule->oif);
                        space = true;
                }

                fprintf(f, "%stable=%"PRIu32 "\n",
                        space ? " " : "",
                        rule->table);
        }
Esempio n. 12
0
static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
        sd_ipv4acd *ll = userdata;
        int r = 0;

        assert(ll);

        switch (ll->state) {
        case IPV4ACD_STATE_INIT:

                ipv4acd_set_state(ll, IPV4ACD_STATE_WAITING_PROBE, true);

                if (ll->conflict >= MAX_CONFLICTS) {
                        log_ipv4acd_notice(ll, "Max conflicts reached, delaying by %us", RATE_LIMIT_INTERVAL);
                        r = ipv4acd_set_next_wakeup(ll, RATE_LIMIT_INTERVAL, PROBE_WAIT);
                        if (r < 0)
                                goto out;

                        ll->conflict = 0;
                } else {
                        r = ipv4acd_set_next_wakeup(ll, 0, PROBE_WAIT);
                        if (r < 0)
                                goto out;
                }

                break;
        case IPV4ACD_STATE_WAITING_PROBE:
        case IPV4ACD_STATE_PROBING:
                /* Send a probe */
                r = arp_send_probe(ll->fd, ll->index, ll->address, &ll->mac_addr);
                if (r < 0) {
                        log_ipv4acd_error_errno(ll, r, "Failed to send ARP probe: %m");
                        goto out;
                } else {
                        _cleanup_free_ char *address = NULL;
                        union in_addr_union addr = { .in.s_addr = ll->address };

                        r = in_addr_to_string(AF_INET, &addr, &address);
                        if (r >= 0)
                                log_ipv4acd_debug(ll, "Probing %s", address);
                }

                if (ll->iteration < PROBE_NUM - 2) {
                        ipv4acd_set_state(ll, IPV4ACD_STATE_PROBING, false);

                        r = ipv4acd_set_next_wakeup(ll, PROBE_MIN, (PROBE_MAX-PROBE_MIN));
                        if (r < 0)
                                goto out;
                } else {
                        ipv4acd_set_state(ll, IPV4ACD_STATE_WAITING_ANNOUNCE, true);

                        r = ipv4acd_set_next_wakeup(ll, ANNOUNCE_WAIT, 0);
                        if (r < 0)
                                goto out;
                }

                break;

        case IPV4ACD_STATE_ANNOUNCING:
                if (ll->iteration >= ANNOUNCE_NUM - 1) {
                        ipv4acd_set_state(ll, IPV4ACD_STATE_RUNNING, false);

                        break;
                }
        case IPV4ACD_STATE_WAITING_ANNOUNCE:
                /* Send announcement packet */
                r = arp_send_announcement(ll->fd, ll->index, ll->address, &ll->mac_addr);
                if (r < 0) {
                        log_ipv4acd_error_errno(ll, r, "Failed to send ARP announcement: %m");
                        goto out;
                } else
                        log_ipv4acd_debug(ll, "ANNOUNCE");

                ipv4acd_set_state(ll, IPV4ACD_STATE_ANNOUNCING, false);

                r = ipv4acd_set_next_wakeup(ll, ANNOUNCE_INTERVAL, 0);
                if (r < 0)
                        goto out;

                if (ll->iteration == 0) {
                        ll->conflict = 0;
                        ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_BIND);
                }

                break;
        default:
                assert_not_reached("Invalid state.");
        }

out:
        if (r < 0)
                sd_ipv4acd_stop(ll);

        return 1;
}

static void ipv4acd_on_conflict(sd_ipv4acd *ll) {
        _cleanup_free_ char *address = NULL;
        union in_addr_union addr = { .in.s_addr = ll->address };
        int r;

        assert(ll);

        ll->conflict++;

        r = in_addr_to_string(AF_INET, &addr, &address);
        if (r >= 0)
                log_ipv4acd_debug(ll, "Conflict on %s (%u)", address, ll->conflict);

        ipv4acd_stop(ll);

        ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_CONFLICT);
}

static int ipv4acd_on_packet(sd_event_source *s, int fd,
                            uint32_t revents, void *userdata) {
        sd_ipv4acd *ll = userdata;
        struct ether_arp packet;
        int r;

        assert(ll);
        assert(fd >= 0);

        r = read(fd, &packet, sizeof(struct ether_arp));
        if (r < (int) sizeof(struct ether_arp))
                goto out;

        switch (ll->state) {
        case IPV4ACD_STATE_ANNOUNCING:
        case IPV4ACD_STATE_RUNNING:
                if (ipv4acd_arp_conflict(ll, &packet)) {
                        usec_t ts;

                        assert_se(sd_event_now(ll->event, clock_boottime_or_monotonic(), &ts) >= 0);

                        /* Defend address */
                        if (ts > ll->defend_window) {
                                ll->defend_window = ts + DEFEND_INTERVAL * USEC_PER_SEC;
                                r = arp_send_announcement(ll->fd, ll->index, ll->address, &ll->mac_addr);
                                if (r < 0) {
                                        log_ipv4acd_error_errno(ll, r, "Failed to send ARP announcement: %m");
                                        goto out;
                                } else
                                        log_ipv4acd_debug(ll, "DEFEND");

                        } else
                                ipv4acd_on_conflict(ll);
                }

                break;
        case IPV4ACD_STATE_WAITING_PROBE:
        case IPV4ACD_STATE_PROBING:
        case IPV4ACD_STATE_WAITING_ANNOUNCE:
                /* BPF ensures this packet indicates a conflict */
                ipv4acd_on_conflict(ll);

                break;
        default:
                assert_not_reached("Invalid state.");
        }

out:
        if (r < 0)
                sd_ipv4acd_stop(ll);

        return 1;
}
Esempio n. 13
0
static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
        sd_ipv4acd *acd = userdata;
        int r = 0;

        assert(acd);

        switch (acd->state) {

        case IPV4ACD_STATE_STARTED:
                ipv4acd_set_state(acd, IPV4ACD_STATE_WAITING_PROBE, true);

                if (acd->n_conflict >= MAX_CONFLICTS) {
                        char ts[FORMAT_TIMESPAN_MAX];
                        log_ipv4acd(acd, "Max conflicts reached, delaying by %s", format_timespan(ts, sizeof(ts), RATE_LIMIT_INTERVAL_USEC, 0));

                        r = ipv4acd_set_next_wakeup(acd, RATE_LIMIT_INTERVAL_USEC, PROBE_WAIT_USEC);
                        if (r < 0)
                                goto fail;
                } else {
                        r = ipv4acd_set_next_wakeup(acd, 0, PROBE_WAIT_USEC);
                        if (r < 0)
                                goto fail;
                }

                break;

        case IPV4ACD_STATE_WAITING_PROBE:
        case IPV4ACD_STATE_PROBING:
                /* Send a probe */
                r = arp_send_probe(acd->fd, acd->ifindex, acd->address, &acd->mac_addr);
                if (r < 0) {
                        log_ipv4acd_errno(acd, r, "Failed to send ARP probe: %m");
                        goto fail;
                } else {
                        _cleanup_free_ char *address = NULL;
                        union in_addr_union addr = { .in.s_addr = acd->address };

                        (void) in_addr_to_string(AF_INET, &addr, &address);
                        log_ipv4acd(acd, "Probing %s", strna(address));
                }

                if (acd->n_iteration < PROBE_NUM - 2) {
                        ipv4acd_set_state(acd, IPV4ACD_STATE_PROBING, false);

                        r = ipv4acd_set_next_wakeup(acd, PROBE_MIN_USEC, (PROBE_MAX_USEC-PROBE_MIN_USEC));
                        if (r < 0)
                                goto fail;
                } else {
                        ipv4acd_set_state(acd, IPV4ACD_STATE_WAITING_ANNOUNCE, true);

                        r = ipv4acd_set_next_wakeup(acd, ANNOUNCE_WAIT_USEC, 0);
                        if (r < 0)
                                goto fail;
                }

                break;

        case IPV4ACD_STATE_ANNOUNCING:
                if (acd->n_iteration >= ANNOUNCE_NUM - 1) {
                        ipv4acd_set_state(acd, IPV4ACD_STATE_RUNNING, false);
                        break;
                }

                /* fall through */

        case IPV4ACD_STATE_WAITING_ANNOUNCE:
                /* Send announcement packet */
                r = arp_send_announcement(acd->fd, acd->ifindex, acd->address, &acd->mac_addr);
                if (r < 0) {
                        log_ipv4acd_errno(acd, r, "Failed to send ARP announcement: %m");
                        goto fail;
                } else
                        log_ipv4acd(acd, "ANNOUNCE");

                ipv4acd_set_state(acd, IPV4ACD_STATE_ANNOUNCING, false);

                r = ipv4acd_set_next_wakeup(acd, ANNOUNCE_INTERVAL_USEC, 0);
                if (r < 0)
                        goto fail;

                if (acd->n_iteration == 0) {
                        acd->n_conflict = 0;
                        ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_BIND);
                }

                break;

        default:
                assert_not_reached("Invalid state.");
        }

        return 0;

fail:
        sd_ipv4acd_stop(acd);
        return 0;
}

static void ipv4acd_on_conflict(sd_ipv4acd *acd) {
        _cleanup_free_ char *address = NULL;
        union in_addr_union addr = { .in.s_addr = acd->address };

        assert(acd);

        acd->n_conflict++;

        (void) in_addr_to_string(AF_INET, &addr, &address);
        log_ipv4acd(acd, "Conflict on %s (%u)", strna(address), acd->n_conflict);

        ipv4acd_reset(acd);
        ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_CONFLICT);
}

static int ipv4acd_on_packet(
                sd_event_source *s,
                int fd,
                uint32_t revents,
                void *userdata) {

        sd_ipv4acd *acd = userdata;
        struct ether_arp packet;
        ssize_t n;
        int r;

        assert(s);
        assert(acd);
        assert(fd >= 0);

        n = recv(fd, &packet, sizeof(struct ether_arp), 0);
        if (n < 0) {
                if (errno == EAGAIN || errno == EINTR)
                        return 0;

                log_ipv4acd_errno(acd, errno, "Failed to read ARP packet: %m");
                goto fail;
        }
        if ((size_t) n != sizeof(struct ether_arp)) {
                log_ipv4acd(acd, "Ignoring too short ARP packet.");
                return 0;
        }

        switch (acd->state) {

        case IPV4ACD_STATE_ANNOUNCING:
        case IPV4ACD_STATE_RUNNING:

                if (ipv4acd_arp_conflict(acd, &packet)) {
                        usec_t ts;

                        assert_se(sd_event_now(acd->event, clock_boottime_or_monotonic(), &ts) >= 0);

                        /* Defend address */
                        if (ts > acd->defend_window) {
                                acd->defend_window = ts + DEFEND_INTERVAL_USEC;
                                r = arp_send_announcement(acd->fd, acd->ifindex, acd->address, &acd->mac_addr);
                                if (r < 0) {
                                        log_ipv4acd_errno(acd, r, "Failed to send ARP announcement: %m");
                                        goto fail;
                                } else
                                        log_ipv4acd(acd, "DEFEND");

                        } else
                                ipv4acd_on_conflict(acd);
                }
                break;

        case IPV4ACD_STATE_WAITING_PROBE:
        case IPV4ACD_STATE_PROBING:
        case IPV4ACD_STATE_WAITING_ANNOUNCE:
                /* BPF ensures this packet indicates a conflict */
                ipv4acd_on_conflict(acd);
                break;

        default:
                assert_not_reached("Invalid state.");
        }

        return 0;

fail:
        sd_ipv4acd_stop(acd);
        return 0;
}
Esempio n. 14
0
static void bus_method_resolve_address_complete(DnsQuery *q) {
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
        unsigned added = 0, i;
        int r;

        assert(q);

        if (q->state != DNS_TRANSACTION_SUCCESS) {
                r = reply_query_state(q);
                goto finish;
        }

        r = sd_bus_message_new_method_return(q->request, &reply);
        if (r < 0)
                goto finish;

        r = sd_bus_message_append(reply, "i", q->answer_ifindex);
        if (r < 0)
                goto finish;

        r = sd_bus_message_open_container(reply, 'a', "s");
        if (r < 0)
                goto finish;

        if (q->answer) {
                answer = dns_answer_ref(q->answer);

                for (i = 0; i < answer->n_rrs; i++) {
                        r = dns_question_matches_rr(q->question, answer->rrs[i]);
                        if (r < 0)
                                goto finish;
                        if (r == 0)
                                continue;

                        r = sd_bus_message_append(reply, "s", answer->rrs[i]->ptr.name);
                        if (r < 0)
                                goto finish;

                        added ++;
                }
        }

        if (added <= 0) {
                _cleanup_free_ char *ip = NULL;

                in_addr_to_string(q->request_family, &q->request_address, &ip);

                r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Address '%s' does not have any RR of requested type", ip);
                goto finish;
        }

        r = sd_bus_message_close_container(reply);
        if (r < 0)
                goto finish;

        r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
        if (r < 0)
                goto finish;

        r = sd_bus_send(q->manager->bus, reply, NULL);

finish:
        if (r < 0) {
                log_error_errno(r, "Failed to send address reply: %m");
                sd_bus_reply_method_errno(q->request, -r, NULL);
        }

        dns_query_free(q);
}
Esempio n. 15
0
static int reply_query_state(DnsQuery *q) {
        _cleanup_free_ char *ip = NULL;
        const char *name;
        int r;

        if (q->request_hostname)
                name = q->request_hostname;
        else {
                r = in_addr_to_string(q->request_family, &q->request_address, &ip);
                if (r < 0)
                        return r;

                name = ip;
        }

        switch (q->state) {

        case DNS_TRANSACTION_NO_SERVERS:
                return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");

        case DNS_TRANSACTION_TIMEOUT:
                return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out");

        case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED:
                return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed");

        case DNS_TRANSACTION_INVALID_REPLY:
                return sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");

        case DNS_TRANSACTION_RESOURCES:
                return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_RESOURCES, "Not enough resources");

        case DNS_TRANSACTION_ABORTED:
                return sd_bus_reply_method_errorf(q->request, BUS_ERROR_ABORTED, "Query aborted");

        case DNS_TRANSACTION_FAILURE: {
                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;

                if (q->answer_rcode == DNS_RCODE_NXDOMAIN)
                        sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", name);
                else {
                        const char *rc, *n;
                        char p[3]; /* the rcode is 4 bits long */

                        rc = dns_rcode_to_string(q->answer_rcode);
                        if (!rc) {
                                sprintf(p, "%i", q->answer_rcode);
                                rc = p;
                        }

                        n = strappenda(_BUS_ERROR_DNS, rc);
                        sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", name, rc);
                }

                return sd_bus_reply_method_error(q->request, &error);
        }

        case DNS_TRANSACTION_NULL:
        case DNS_TRANSACTION_PENDING:
        case DNS_TRANSACTION_SUCCESS:
        default:
                assert_not_reached("Impossible state");
        }
}