Example #1
0
int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_bus_message **reply) {
        sd_bus_message *q;
        int r;

        assert(i);
        assert(m);
        assert(reply);

        fputs("</node>\n", i->f);
        fflush(i->f);

        if (ferror(i->f))
                return -ENOMEM;

        r = sd_bus_message_new_method_return(bus, m, &q);
        if (r < 0)
                return r;

        r = sd_bus_message_append(q, "s", i->introspection);
        if (r < 0) {
                sd_bus_message_unref(q);
                return r;
        }

        *reply = q;
        return 0;
}
Example #2
0
_public_ int sd_bus_reply_method_return(
                sd_bus_message *call,
                const char *types, ...) {

        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
        int r;

        assert_return(call, -EINVAL);
        assert_return(call->sealed, -EPERM);
        assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
        assert_return(call->bus, -EINVAL);
        assert_return(!bus_pid_changed(call->bus), -ECHILD);

        if (!BUS_IS_OPEN(call->bus->state))
                return -ENOTCONN;

        if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
                return 0;

        r = sd_bus_message_new_method_return(call, &m);
        if (r < 0)
                return r;

        if (!isempty(types)) {
                va_list ap;

                va_start(ap, types);
                r = bus_message_append_ap(m, types, ap);
                va_end(ap);
                if (r < 0)
                        return r;
        }

        return sd_bus_send(call->bus, m, NULL);
}
Example #3
0
static int return_strv(sd_bus *bus, sd_bus_message *m, char **l) {
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        int r;

        r = sd_bus_message_new_method_return(m, &reply);
        if (r < 0)
                return r;

        r = sd_bus_message_append_strv(reply, l);
        if (r < 0)
                return r;

        return sd_bus_send(bus, reply, NULL);
}
Example #4
0
static int driver_get_security_context(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
        int r;

        r = get_creds(bus, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, error);
        if (r < 0)
                return r;

        r = sd_bus_message_new_method_return(m, &reply);
        if (r < 0)
                return r;

        r = sd_bus_message_append_array(reply, 'y', creds->label, strlen(creds->label));
        if (r < 0)
                return r;

        return sd_bus_send(bus, reply, NULL);
}
Example #5
0
static int method_get_product_uuid(sd_bus_message *m, void *userdata, sd_bus_error *error) {
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
        Context *c = userdata;
        int interactive, r;

        assert(m);
        assert(c);

        if (!c->has_uuid)
                return sd_bus_error_set(error, BUS_ERROR_NO_PRODUCT_UUID, "Failed to read product UUID from /sys/class/dmi/id/product_uuid");

        r = sd_bus_message_read(m, "b", &interactive);
        if (r < 0)
                return r;

        r = bus_verify_polkit_async(
                        m,
                        CAP_SYS_ADMIN,
                        "org.freedesktop.hostname1.get-product-uuid",
                        NULL,
                        interactive,
                        UID_INVALID,
                        &c->polkit_registry,
                        error);
        if (r < 0)
                return r;
        if (r == 0)
                return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */

        r = sd_bus_message_new_method_return(m, &reply);
        if (r < 0)
                return r;

        r = sd_bus_message_append_array(reply, 'y', &c->uuid, sizeof(c->uuid));
        if (r < 0)
                return r;

        return sd_bus_send(NULL, reply, NULL);
}
Example #6
0
int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error) {
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        Machine *m = userdata;
        int r;

        assert(message);
        assert(m);

        r = sd_bus_message_new_method_return(message, &reply);
        if (r < 0)
                return r;

        r = sd_bus_message_open_container(reply, 'a', "(iay)");
        if (r < 0)
                return r;

        switch (m->class) {

        case MACHINE_HOST: {
                _cleanup_free_ struct local_address *addresses = NULL;
                struct local_address *a;
                int n, i;

                n = local_addresses(NULL, 0, AF_UNSPEC, &addresses);
                if (n < 0)
                        return n;

                for (a = addresses, i = 0; i < n; a++, i++) {

                        r = sd_bus_message_open_container(reply, 'r', "iay");
                        if (r < 0)
                                return r;

                        r = sd_bus_message_append(reply, "i", addresses[i].family);
                        if (r < 0)
                                return r;

                        r = sd_bus_message_append_array(reply, 'y', &addresses[i].address, FAMILY_ADDRESS_SIZE(addresses[i].family));
                        if (r < 0)
                                return r;

                        r = sd_bus_message_close_container(reply);
                        if (r < 0)
                                return r;
                }

                break;
        }

        case MACHINE_CONTAINER: {
                _cleanup_close_pair_ int pair[2] = { -1, -1 };
                _cleanup_free_ char *us = NULL, *them = NULL;
                _cleanup_close_ int netns_fd = -1;
                const char *p;
                siginfo_t si;
                pid_t child;

                r = readlink_malloc("/proc/self/ns/net", &us);
                if (r < 0)
                        return r;

                p = procfs_file_alloca(m->leader, "ns/net");
                r = readlink_malloc(p, &them);
                if (r < 0)
                        return r;

                if (streq(us, them))
                        return sd_bus_error_setf(error, BUS_ERROR_NO_PRIVATE_NETWORKING, "Machine %s does not use private networking", m->name);

                r = namespace_open(m->leader, NULL, NULL, &netns_fd, NULL, NULL);
                if (r < 0)
                        return r;

                if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
                        return -errno;

                child = fork();
                if (child < 0)
                        return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");

                if (child == 0) {
                        _cleanup_free_ struct local_address *addresses = NULL;
                        struct local_address *a;
                        int i, n;

                        pair[0] = safe_close(pair[0]);

                        r = namespace_enter(-1, -1, netns_fd, -1, -1);
                        if (r < 0)
                                _exit(EXIT_FAILURE);

                        n = local_addresses(NULL, 0, AF_UNSPEC, &addresses);
                        if (n < 0)
                                _exit(EXIT_FAILURE);

                        for (a = addresses, i = 0; i < n; a++, i++) {
                                struct iovec iov[2] = {
                                        { .iov_base = &a->family, .iov_len = sizeof(a->family) },
                                        { .iov_base = &a->address, .iov_len = FAMILY_ADDRESS_SIZE(a->family) },
                                };

                                r = writev(pair[1], iov, 2);
                                if (r < 0)
                                        _exit(EXIT_FAILURE);
                        }

                        pair[1] = safe_close(pair[1]);

                        _exit(EXIT_SUCCESS);
                }
static void *server(void *p) {
        struct context *c = p;
        sd_bus *bus = NULL;
        sd_id128_t id;
        bool quit = false;
        int r;

        assert_se(sd_id128_randomize(&id) >= 0);

        assert_se(sd_bus_new(&bus) >= 0);
        assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
        assert_se(sd_bus_set_server(bus, 1, id) >= 0);
        assert_se(sd_bus_set_anonymous(bus, c->server_anonymous_auth) >= 0);
        assert_se(sd_bus_negotiate_fds(bus, c->server_negotiate_unix_fds) >= 0);
        assert_se(sd_bus_start(bus) >= 0);

        while (!quit) {
                _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;

                r = sd_bus_process(bus, &m);
                if (r < 0) {
                        log_error("Failed to process requests: %s", strerror(-r));
                        goto fail;
                }

                if (r == 0) {
                        r = sd_bus_wait(bus, (uint64_t) -1);
                        if (r < 0) {
                                log_error("Failed to wait: %s", strerror(-r));
                                goto fail;
                        }

                        continue;
                }

                if (!m)
                        continue;

                log_info("Got message! member=%s", strna(sd_bus_message_get_member(m)));

                if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Exit")) {

                        assert_se((sd_bus_can_send(bus, 'h') >= 1) == (c->server_negotiate_unix_fds && c->client_negotiate_unix_fds));

                        r = sd_bus_message_new_method_return(m, &reply);
                        if (r < 0) {
                                log_error("Failed to allocate return: %s", strerror(-r));
                                goto fail;
                        }

                        quit = true;

                } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
                        r = sd_bus_message_new_method_error(
                                        m,
                                        &reply,
                                        &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method."));
                        if (r < 0) {
                                log_error("Failed to allocate return: %s", strerror(-r));
                                goto fail;
                        }
                }

                if (reply) {
                        r = sd_bus_send(bus, reply, NULL);
                        if (r < 0) {
                                log_error("Failed to send reply: %s", strerror(-r));
                                goto fail;
                        }
                }
        }

        r = 0;

fail:
        if (bus) {
                sd_bus_flush(bus);
                sd_bus_unref(bus);
        }

        return INT_TO_PTR(r);
}
SOL_API int
sol_gatt_pending_reply(struct sol_gatt_pending *pending, int error,
    struct sol_buffer *buf)
{
    sd_bus_message *reply = NULL;
    struct context *ctx = bluetooth_get_context();
    const struct sol_gatt_attr *attr;
    const char *interface;
    int r;

    SOL_NULL_CHECK(pending, -EINVAL);

    attr = pending->attr;

    if (error) {
        r = error;
        goto done;
    }

    switch (pending->type) {
    case PENDING_READ:
    case PENDING_WRITE:
        r = sd_bus_message_new_method_return(pending->m, &reply);
        SOL_INT_CHECK(r, < 0, r);

        if (pending->type == PENDING_READ) {
            r = -EINVAL;
            SOL_NULL_CHECK_GOTO(buf, done);

            r = sd_bus_message_append_array(reply, 'y', buf->data, buf->used);
            SOL_INT_CHECK_GOTO(r, < 0, done);
        }
        break;

    case PENDING_INDICATE:
    case PENDING_NOTIFY:
        r = -EINVAL;
        pending->buf = buf;
        SOL_NULL_CHECK_GOTO(pending->buf, done);

        if (attr->type == SOL_GATT_ATTR_TYPE_DESCRIPTOR)
            interface = "org.bluez.GattDescriptor1";
        else
            interface = "org.bluez.GattCharacteristic1";

        r = sd_bus_emit_properties_changed(sol_bus_client_get_bus(ctx->bluez),
            attr->_priv, interface, "Value", NULL);
        SOL_INT_CHECK_GOTO(r, < 0, done);
        break;
    case PENDING_REMOTE_READ:
        pending->read((void *)pending->user_data, true, pending->attr, buf);
        pending->read = NULL;
        destroy_pending(pending);
        break;

    case PENDING_REMOTE_WRITE:
        pending->write((void *)pending->user_data, true, pending->attr);
        pending->write = NULL;
        destroy_pending(pending);
        break;
    }
Example #9
0
static void bus_method_resolve_record_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', "(qqay)");
        if (r < 0)
                goto finish;

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

                for (i = 0; i < answer->n_rrs; i++) {
                        _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
                        size_t start;

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

                        r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0);
                        if (r < 0)
                                goto finish;

                        r = dns_packet_append_rr(p, answer->rrs[i], &start);
                        if (r < 0)
                                goto finish;

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

                        r = sd_bus_message_append(reply, "qq", answer->rrs[i]->key->class, answer->rrs[i]->key->type);
                        if (r < 0)
                                goto finish;

                        r = sd_bus_message_append_array(reply, 'y', DNS_PACKET_DATA(p) + start, p->size - start);
                        if (r < 0)
                                goto finish;

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

                        added ++;
                }
        }
Example #10
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);
}
Example #11
0
static void bus_method_resolve_hostname_complete(DnsQuery *q) {
        _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *cname = NULL, *canonical = NULL;
        _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', "(iay)");
        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) {
                                /* Hmm, if this is not an address record,
                                   maybe it's a cname? If so, remember this */
                                r = dns_question_matches_cname(q->question, answer->rrs[i]);
                                if (r < 0)
                                        goto finish;
                                if (r > 0)
                                        cname = dns_resource_record_ref(answer->rrs[i]);

                                continue;
                        }

                        r = append_address(reply, answer->rrs[i]);
                        if (r < 0)
                                goto finish;

                        if (!canonical)
                                canonical = dns_resource_record_ref(answer->rrs[i]);

                        added ++;
                }
        }

        if (added <= 0) {
                if (!cname) {
                        r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of requested type", q->request_hostname);
                        goto finish;
                }

                /* This has a cname? Then update the query with the
                 * new cname. */
                r = dns_query_cname_redirect(q, cname->cname.name);
                if (r < 0) {
                        if (r == -ELOOP)
                                r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop on '%s'", q->request_hostname);
                        else
                                r = sd_bus_reply_method_errno(q->request, -r, NULL);

                        goto finish;
                }

                /* Before we restart the query, let's see if any of
                 * the RRs we already got already answers our query */
                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 = append_address(reply, answer->rrs[i]);
                        if (r < 0)
                                goto finish;

                        if (!canonical)
                                canonical = dns_resource_record_ref(answer->rrs[i]);

                        added++;
                }

                /* If we didn't find anything, then let's restart the
                 * query, this time with the cname */
                if (added <= 0) {
                        r = dns_query_go(q);
                        if (r == -ESRCH) {
                                r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
                                goto finish;
                        }
                        if (r < 0) {
                                r = sd_bus_reply_method_errno(q->request, -r, NULL);
                                goto finish;
                        }

                        return;
                }
        }

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

        /* Return the precise spelling and uppercasing reported by the server */
        assert(canonical);
        r = sd_bus_message_append(reply, "st", DNS_RESOURCE_KEY_NAME(canonical->key), 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 hostname reply: %m");
                sd_bus_reply_method_errno(q->request, -r, NULL);
        }

        dns_query_free(q);
}
Example #12
0
int bus_image_common_get_metadata(
                Manager *m,
                sd_bus_message *message,
                const char *name_or_path,
                Image *image,
                sd_bus_error *error) {

        _cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL;
        _cleanup_hashmap_free_ Hashmap *unit_files = NULL;
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
        _cleanup_free_ PortableMetadata **sorted = NULL;
        _cleanup_strv_free_ char **matches = NULL;
        size_t i;
        int r;

        assert(name_or_path || image);
        assert(message);

        if (!m) {
                assert(image);
                m = image->userdata;
        }

        r = sd_bus_message_read_strv(message, &matches);
        if (r < 0)
                return r;

        r = bus_image_acquire(m,
                              message,
                              name_or_path,
                              image,
                              BUS_IMAGE_AUTHENTICATE_BY_PATH,
                              "org.freedesktop.portable1.inspect-images",
                              &image,
                              error);
        if (r < 0)
                return r;
        if (r == 0) /* Will call us back */
                return 1;

        r = portable_extract(
                        image->path,
                        matches,
                        &os_release,
                        &unit_files,
                        error);
        if (r < 0)
                return r;

        r = portable_metadata_hashmap_to_sorted_array(unit_files, &sorted);
        if (r < 0)
                return r;

        r = sd_bus_message_new_method_return(message, &reply);
        if (r < 0)
                return r;

        r = sd_bus_message_append(reply, "s", image->path);
        if (r < 0)
                return r;

        r = append_fd(reply, os_release);
        if (r < 0)
                return r;

        r = sd_bus_message_open_container(reply, 'a', "{say}");
        if (r < 0)
                return r;

        for (i = 0; i < hashmap_size(unit_files); i++) {

                r = sd_bus_message_open_container(reply, 'e', "say");
                if (r < 0)
                        return r;

                r = sd_bus_message_append(reply, "s", sorted[i]->name);
                if (r < 0)
                        return r;

                r = append_fd(reply, sorted[i]);
                if (r < 0)
                        return r;

                r = sd_bus_message_close_container(reply);
                if (r < 0)
                        return r;
        }

        r = sd_bus_message_close_container(reply);
        if (r < 0)
                return r;

        return sd_bus_send(NULL, reply, NULL);
}