Exemple #1
0
static void start_scope_unit(sd_bus *connection, pid_t child_pid, long memory_limit,
                             char *devices, const char *unit_name) {
    sd_bus_message *message = NULL;
    check(sd_bus_message_new_method_call(connection, &message, systemd_bus_name, systemd_path_name,
                                         manager_interface, "StartTransientUnit"));

    check(sd_bus_message_append(message, "ss", unit_name, "fail"));
    check(sd_bus_message_open_container(message, 'a', "(sv)"));
    check(sd_bus_message_append(message, "(sv)", "PIDs", "au", 1, child_pid));
    check(sd_bus_message_append(message, "(sv)", "Description", "s",
                                "Playpen application sandbox"));
    check(sd_bus_message_append(message, "(sv)", "MemoryLimit", "t",
                                1024ULL * 1024ULL * (unsigned long long)memory_limit));
    check(sd_bus_message_append(message, "(sv)", "DevicePolicy", "s", "strict"));

    if (devices) {
        check(sd_bus_message_open_container(message, 'r', "sv"));
        check(sd_bus_message_append(message, "s", "DeviceAllow"));
        check(sd_bus_message_open_container(message, 'v', "a(ss)"));
        check(sd_bus_message_open_container(message, 'a', "(ss)"));

        for (char *s_ptr = devices, *saveptr; ; s_ptr = NULL) {
            const char *device = strtok_r(s_ptr, ",", &saveptr);
            if (!device) break;
            char *split = strchr(device, ':');
            if (!split) errx(EXIT_FAILURE, "invalid device parameter `%s`", device);
            *split = '\0';
            sd_bus_message_append(message, "(ss)", device, split + 1);
        }

        check(sd_bus_message_close_container(message));
        check(sd_bus_message_close_container(message));
        check(sd_bus_message_close_container(message));
    }

    check(sd_bus_message_append(message, "(sv)", "CPUAccounting", "b", 1));
    check(sd_bus_message_append(message, "(sv)", "BlockIOAccounting", "b", 1));
    check(sd_bus_message_close_container(message));
    check(sd_bus_message_append(message, "a(sa(sv))", 0));

    sd_bus_error error = SD_BUS_ERROR_NULL;
    int rc = sd_bus_call(connection, message, 0, &error, NULL);
    if (rc < 0) errx(EXIT_FAILURE, "%s",
                     sd_bus_error_is_set(&error) ? error.message : strerror(-rc));
    sd_bus_message_unref(message);

    wait_for_unit(child_pid, unit_name);
}
Exemple #2
0
static int append_address(sd_bus_message *reply, DnsResourceRecord *rr) {
        int r;

        assert(reply);
        assert(rr);

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

        if (rr->key->type == DNS_TYPE_A) {
                r = sd_bus_message_append(reply, "i", AF_INET);
                if (r < 0)
                        return r;

                r = sd_bus_message_append_array(reply, 'y', &rr->a.in_addr, sizeof(struct in_addr));

        } else if (rr->key->type == DNS_TYPE_AAAA) {
                r = sd_bus_message_append(reply, "i", AF_INET6);
                if (r < 0)
                        return r;

                r = sd_bus_message_append_array(reply, 'y', &rr->aaaa.in6_addr, sizeof(struct in6_addr));
        } else
                return -EAFNOSUPPORT;

        if (r < 0)
                return r;

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

        return 0;
}
static int
adapter_set_powered(struct context *ctx, const char *path, bool powered)
{
    sd_bus *bus = sol_bus_client_get_bus(ctx->bluez);
    const char *service = sol_bus_client_get_service(ctx->bluez);
    sd_bus_message *m;
    int r;

    m = create_property_set(bus, service, path,
        "org.bluez.Adapter1", "Powered");
    SOL_NULL_CHECK(m, -ENOMEM);

    r = sd_bus_message_open_container(m, 'v', "b");
    SOL_INT_CHECK_GOTO(r, < 0, done);

    r = sd_bus_message_append(m, "b", &powered);
    SOL_INT_CHECK_GOTO(r, < 0, done);

    r = sd_bus_message_close_container(m);
    SOL_INT_CHECK_GOTO(r, < 0, done);

    r = sd_bus_call_async(bus, NULL, m, sol_bus_log_callback, NULL, 0);
    SOL_INT_CHECK_GOTO(r, < 0, done);

done:
    sd_bus_message_unref(m);

    return r;
}
Exemple #4
0
static int message_start_transient_unit_new(sd_bus *bus, const char *name, sd_bus_message **ret) {
        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
        char **i;
        int r;

        assert(bus);
        assert(name);
        assert(ret);

        r = sd_bus_message_new_method_call(
                        bus,
                        &m,
                        "org.freedesktop.systemd1",
                        "/org/freedesktop/systemd1",
                        "org.freedesktop.systemd1.Manager",
                        "StartTransientUnit");
        if (r < 0)
                return r;

        r = sd_bus_message_append(m, "ss", name, "fail");
        if (r < 0)
                return r;

        r = sd_bus_message_open_container(m, 'a', "(sv)");
        if (r < 0)
                return r;

        STRV_FOREACH(i, arg_property) {
                r = sd_bus_message_open_container(m, 'r', "sv");
                if (r < 0)
                        return r;

                r = bus_append_unit_property_assignment(m, *i);
                if (r < 0)
                        return r;

                r = sd_bus_message_close_container(m);
                if (r < 0)
                        return r;
        }
Exemple #5
0
_public_ int sd_bus_set_property(
                sd_bus *bus,
                const char *destination,
                const char *path,
                const char *interface,
                const char *member,
                sd_bus_error *error,
                const char *type, ...) {

        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
        va_list ap;
        int r;

        bus_assert_return(bus, -EINVAL, error);
        bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
        bus_assert_return(member_name_is_valid(member), -EINVAL, error);
        bus_assert_return(signature_is_single(type, false), -EINVAL, error);
        bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);

        if (!BUS_IS_OPEN(bus->state)) {
                r = -ENOTCONN;
                goto fail;
        }

        r = sd_bus_message_new_method_call(bus, &m, destination, path, "org.freedesktop.DBus.Properties", "Set");
        if (r < 0)
                goto fail;

        r = sd_bus_message_append(m, "ss", strempty(interface), member);
        if (r < 0)
                goto fail;

        r = sd_bus_message_open_container(m, 'v', type);
        if (r < 0)
                goto fail;

        va_start(ap, type);
        r = sd_bus_message_appendv(m, type, ap);
        va_end(ap);
        if (r < 0)
                goto fail;

        r = sd_bus_message_close_container(m);
        if (r < 0)
                goto fail;

        return sd_bus_call(bus, m, 0, error, NULL);

fail:
        return sd_bus_error_set_errno(error, r);
}
Exemple #6
0
static int transient_unit_set_properties(sd_bus_message *m, char **properties) {
        char **i;
        int r;

        r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description);
        if (r < 0)
                return r;

        STRV_FOREACH(i, properties) {
                r = sd_bus_message_open_container(m, 'r', "sv");
                if (r < 0)
                        return r;

                r = bus_append_unit_property_assignment(m, *i);
                if (r < 0)
                        return r;

                r = sd_bus_message_close_container(m);
                if (r < 0)
                        return r;
        }
Exemple #7
0
int register_machine(
                const char *machine_name,
                pid_t pid,
                const char *directory,
                sd_id128_t uuid,
                int local_ifindex,
                const char *slice,
                CustomMount *mounts,
                unsigned n_mounts,
                int kill_signal,
                char **properties,
                bool keep_unit) {

        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
        int r;

        r = sd_bus_default_system(&bus);
        if (r < 0)
                return log_error_errno(r, "Failed to open system bus: %m");

        if (keep_unit) {
                r = sd_bus_call_method(
                                bus,
                                "org.freedesktop.machine1",
                                "/org/freedesktop/machine1",
                                "org.freedesktop.machine1.Manager",
                                "RegisterMachineWithNetwork",
                                &error,
                                NULL,
                                "sayssusai",
                                machine_name,
                                SD_BUS_MESSAGE_APPEND_ID128(uuid),
                                "nspawn",
                                "container",
                                (uint32_t) pid,
                                strempty(directory),
                                local_ifindex > 0 ? 1 : 0, local_ifindex);
        } else {
                _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
                char **i;
                unsigned j;

                r = sd_bus_message_new_method_call(
                                bus,
                                &m,
                                "org.freedesktop.machine1",
                                "/org/freedesktop/machine1",
                                "org.freedesktop.machine1.Manager",
                                "CreateMachineWithNetwork");
                if (r < 0)
                        return bus_log_create_error(r);

                r = sd_bus_message_append(
                                m,
                                "sayssusai",
                                machine_name,
                                SD_BUS_MESSAGE_APPEND_ID128(uuid),
                                "nspawn",
                                "container",
                                (uint32_t) pid,
                                strempty(directory),
                                local_ifindex > 0 ? 1 : 0, local_ifindex);
                if (r < 0)
                        return bus_log_create_error(r);

                r = sd_bus_message_open_container(m, 'a', "(sv)");
                if (r < 0)
                        return bus_log_create_error(r);

                if (!isempty(slice)) {
                        r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
                        if (r < 0)
                                return bus_log_create_error(r);
                }

                r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "strict");
                if (r < 0)
                        return bus_log_create_error(r);

                /* If you make changes here, also make sure to update
                 * [email protected], to keep the device
                 * policies in sync regardless if we are run with or
                 * without the --keep-unit switch. */
                r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 9,
                                          /* Allow the container to
                                           * access and create the API
                                           * device nodes, so that
                                           * PrivateDevices= in the
                                           * container can work
                                           * fine */
                                          "/dev/null", "rwm",
                                          "/dev/zero", "rwm",
                                          "/dev/full", "rwm",
                                          "/dev/random", "rwm",
                                          "/dev/urandom", "rwm",
                                          "/dev/tty", "rwm",
                                          "/dev/net/tun", "rwm",
                                          /* Allow the container
                                           * access to ptys. However,
                                           * do not permit the
                                           * container to ever create
                                           * these device nodes. */
                                          "/dev/pts/ptmx", "rw",
                                          "char-pts", "rw");
                if (r < 0)
                        return bus_log_create_error(r);

                for (j = 0; j < n_mounts; j++) {
                        CustomMount *cm = mounts + j;

                        if (cm->type != CUSTOM_MOUNT_BIND)
                                continue;

                        r = is_device_node(cm->source);
                        if (r < 0)
                                return log_error_errno(r, "Failed to stat %s: %m", cm->source);

                        if (r) {
                                r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1,
                                        cm->source, cm->read_only ? "r" : "rw");
                                if (r < 0)
                                        return log_error_errno(r, "Failed to append message arguments: %m");
                        }
                }

                if (kill_signal != 0) {
                        r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal);
                        if (r < 0)
                                return bus_log_create_error(r);

                        r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed");
                        if (r < 0)
                                return bus_log_create_error(r);
                }

                STRV_FOREACH(i, properties) {
                        r = sd_bus_message_open_container(m, 'r', "sv");
                        if (r < 0)
                                return bus_log_create_error(r);

                        r = bus_append_unit_property_assignment(m, *i);
                        if (r < 0)
                                return r;

                        r = sd_bus_message_close_container(m);
                        if (r < 0)
                                return bus_log_create_error(r);
                }

                r = sd_bus_message_close_container(m);
                if (r < 0)
                        return bus_log_create_error(r);

                r = sd_bus_call(bus, m, 0, &error, NULL);
        }
Exemple #8
0
static int start_transient_service(
    sd_bus *bus,
    char **argv,
    int *retval) {

    _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
    _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
    _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
    _cleanup_free_ char *service = NULL, *pty_path = NULL;
    _cleanup_close_ int master = -1;
    int r;

    assert(bus);
    assert(argv);
    assert(retval);

    if (arg_pty) {

        if (arg_transport == BUS_TRANSPORT_LOCAL) {
            master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY);
            if (master < 0)
                return log_error_errno(errno, "Failed to acquire pseudo tty: %m");

            r = ptsname_malloc(master, &pty_path);
            if (r < 0)
                return log_error_errno(r, "Failed to determine tty name: %m");

            if (unlockpt(master) < 0)
                return log_error_errno(errno, "Failed to unlock tty: %m");

        } else if (arg_transport == BUS_TRANSPORT_MACHINE) {
            _cleanup_(sd_bus_unrefp) sd_bus *system_bus = NULL;
            _cleanup_(sd_bus_message_unrefp) sd_bus_message *pty_reply = NULL;
            const char *s;

            r = sd_bus_default_system(&system_bus);
            if (r < 0)
                return log_error_errno(r, "Failed to connect to system bus: %m");

            r = sd_bus_call_method(system_bus,
                                   "org.freedesktop.machine1",
                                   "/org/freedesktop/machine1",
                                   "org.freedesktop.machine1.Manager",
                                   "OpenMachinePTY",
                                   &error,
                                   &pty_reply,
                                   "s", arg_host);
            if (r < 0) {
                log_error("Failed to get machine PTY: %s", bus_error_message(&error, -r));
                return r;
            }

            r = sd_bus_message_read(pty_reply, "hs", &master, &s);
            if (r < 0)
                return bus_log_parse_error(r);

            master = fcntl(master, F_DUPFD_CLOEXEC, 3);
            if (master < 0)
                return log_error_errno(errno, "Failed to duplicate master fd: %m");

            pty_path = strdup(s);
            if (!pty_path)
                return log_oom();
        } else
            assert_not_reached("Can't allocate tty via ssh");
    }

    if (!arg_no_block) {
        r = bus_wait_for_jobs_new(bus, &w);
        if (r < 0)
            return log_error_errno(r, "Could not watch jobs: %m");
    }

    if (arg_unit) {
        r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".service", &service);
        if (r < 0)
            return log_error_errno(r, "Failed to mangle unit name: %m");
    } else {
        r = make_unit_name(bus, UNIT_SERVICE, &service);
        if (r < 0)
            return r;
    }

    r = sd_bus_message_new_method_call(
            bus,
            &m,
            "org.freedesktop.systemd1",
            "/org/freedesktop/systemd1",
            "org.freedesktop.systemd1.Manager",
            "StartTransientUnit");
    if (r < 0)
        return bus_log_create_error(r);

    r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
    if (r < 0)
        return bus_log_create_error(r);

    /* Name and mode */
    r = sd_bus_message_append(m, "ss", service, "fail");
    if (r < 0)
        return bus_log_create_error(r);

    /* Properties */
    r = sd_bus_message_open_container(m, 'a', "(sv)");
    if (r < 0)
        return bus_log_create_error(r);

    r = transient_service_set_properties(m, argv, pty_path);
    if (r < 0)
        return bus_log_create_error(r);

    r = sd_bus_message_close_container(m);
    if (r < 0)
        return bus_log_create_error(r);

    /* Auxiliary units */
    r = sd_bus_message_append(m, "a(sa(sv))", 0);
    if (r < 0)
        return bus_log_create_error(r);

    polkit_agent_open_if_enabled();

    r = sd_bus_call(bus, m, 0, &error, &reply);
    if (r < 0)
        return log_error_errno(r, "Failed to start transient service unit: %s", bus_error_message(&error, r));

    if (w) {
        const char *object;

        r = sd_bus_message_read(reply, "o", &object);
        if (r < 0)
            return bus_log_parse_error(r);

        r = bus_wait_for_jobs_one(w, object, arg_quiet);
        if (r < 0)
            return r;
    }

    if (!arg_quiet)
        log_info("Running as unit: %s", service);

    if (arg_wait || master >= 0) {
        _cleanup_(run_context_free) RunContext c = {};

        c.bus = sd_bus_ref(bus);

        r = sd_event_default(&c.event);
        if (r < 0)
            return log_error_errno(r, "Failed to get event loop: %m");

        if (master >= 0) {
            assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT, -1) >= 0);
            (void) sd_event_add_signal(c.event, NULL, SIGINT, NULL, NULL);
            (void) sd_event_add_signal(c.event, NULL, SIGTERM, NULL, NULL);

            if (!arg_quiet)
                log_info("Press ^] three times within 1s to disconnect TTY.");

            r = pty_forward_new(c.event, master, PTY_FORWARD_IGNORE_INITIAL_VHANGUP, &c.forward);
            if (r < 0)
                return log_error_errno(r, "Failed to create PTY forwarder: %m");

            pty_forward_set_handler(c.forward, pty_forward_handler, &c);
        }

        if (arg_wait) {
            _cleanup_free_ char *path = NULL;
            const char *mt;

            path = unit_dbus_path_from_name(service);
            if (!path)
                return log_oom();

            mt = strjoina("type='signal',"
                          "sender='org.freedesktop.systemd1',"
                          "path='", path, "',"
                          "interface='org.freedesktop.DBus.Properties',"
                          "member='PropertiesChanged'");
            r = sd_bus_add_match(bus, &c.match, mt, on_properties_changed, &c);
            if (r < 0)
                return log_error_errno(r, "Failed to add properties changed signal.");

            r = sd_bus_attach_event(bus, c.event, 0);
            if (r < 0)
                return log_error_errno(r, "Failed to attach bus to event loop.");
        }

        r = sd_event_loop(c.event);
        if (r < 0)
            return log_error_errno(r, "Failed to run event loop: %m");

        if (c.forward) {
            char last_char = 0;

            r = pty_forward_get_last_char(c.forward, &last_char);
            if (r >= 0 && !arg_quiet && last_char != '\n')
                fputc('\n', stdout);
        }

        if (!arg_quiet) {
            if (!isempty(c.result))
                log_info("Finished with result: %s", strna(c.result));

            if (c.exit_code == CLD_EXITED)
                log_info("Main processes terminated with: code=%s/status=%i", sigchld_code_to_string(c.exit_code), c.exit_status);
            else if (c.exit_code > 0)
                log_info("Main processes terminated with: code=%s/status=%s", sigchld_code_to_string(c.exit_code), signal_to_string(c.exit_status));

            if (c.inactive_enter_usec > 0 && c.inactive_enter_usec != USEC_INFINITY &&
                    c.inactive_exit_usec > 0 && c.inactive_exit_usec != USEC_INFINITY &&
                    c.inactive_enter_usec > c.inactive_exit_usec) {
                char ts[FORMAT_TIMESPAN_MAX];
                log_info("Service runtime: %s", format_timespan(ts, sizeof(ts), c.inactive_enter_usec - c.inactive_exit_usec, USEC_PER_MSEC));
            }

            if (c.cpu_usage_nsec > 0 && c.cpu_usage_nsec != NSEC_INFINITY) {
                char ts[FORMAT_TIMESPAN_MAX];
                log_info("CPU time consumed: %s", format_timespan(ts, sizeof(ts), (c.cpu_usage_nsec + NSEC_PER_USEC - 1) / NSEC_PER_USEC, USEC_PER_MSEC));
            }
        }

        /* Try to propagate the service's return value */
        if (c.result && STR_IN_SET(c.result, "success", "exit-code") && c.exit_code == CLD_EXITED)
            *retval = c.exit_status;
        else
            *retval = EXIT_FAILURE;
    }

    return 0;
}
Exemple #9
0
static int start_transient_scope(
    sd_bus *bus,
    char **argv) {

    _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
    _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
    _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
    _cleanup_strv_free_ char **env = NULL, **user_env = NULL;
    _cleanup_free_ char *scope = NULL;
    const char *object = NULL;
    int r;

    assert(bus);
    assert(argv);

    r = bus_wait_for_jobs_new(bus, &w);
    if (r < 0)
        return log_oom();

    if (arg_unit) {
        r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".scope", &scope);
        if (r < 0)
            return log_error_errno(r, "Failed to mangle scope name: %m");
    } else {
        r = make_unit_name(bus, UNIT_SCOPE, &scope);
        if (r < 0)
            return r;
    }

    r = sd_bus_message_new_method_call(
            bus,
            &m,
            "org.freedesktop.systemd1",
            "/org/freedesktop/systemd1",
            "org.freedesktop.systemd1.Manager",
            "StartTransientUnit");
    if (r < 0)
        return bus_log_create_error(r);

    r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
    if (r < 0)
        return bus_log_create_error(r);

    /* Name and Mode */
    r = sd_bus_message_append(m, "ss", scope, "fail");
    if (r < 0)
        return bus_log_create_error(r);

    /* Properties */
    r = sd_bus_message_open_container(m, 'a', "(sv)");
    if (r < 0)
        return bus_log_create_error(r);

    r = transient_scope_set_properties(m);
    if (r < 0)
        return bus_log_create_error(r);

    r = sd_bus_message_close_container(m);
    if (r < 0)
        return bus_log_create_error(r);

    /* Auxiliary units */
    r = sd_bus_message_append(m, "a(sa(sv))", 0);
    if (r < 0)
        return bus_log_create_error(r);

    polkit_agent_open_if_enabled();

    r = sd_bus_call(bus, m, 0, &error, &reply);
    if (r < 0) {
        log_error("Failed to start transient scope unit: %s", bus_error_message(&error, -r));
        return r;
    }

    if (arg_nice_set) {
        if (setpriority(PRIO_PROCESS, 0, arg_nice) < 0)
            return log_error_errno(errno, "Failed to set nice level: %m");
    }

    if (arg_exec_group) {
        gid_t gid;

        r = get_group_creds(&arg_exec_group, &gid);
        if (r < 0)
            return log_error_errno(r, "Failed to resolve group %s: %m", arg_exec_group);

        if (setresgid(gid, gid, gid) < 0)
            return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
    }

    if (arg_exec_user) {
        const char *home, *shell;
        uid_t uid;
        gid_t gid;

        r = get_user_creds(&arg_exec_user, &uid, &gid, &home, &shell);
        if (r < 0)
            return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user);

        r = strv_extendf(&user_env, "HOME=%s", home);
        if (r < 0)
            return log_oom();

        r = strv_extendf(&user_env, "SHELL=%s", shell);
        if (r < 0)
            return log_oom();

        r = strv_extendf(&user_env, "USER=%s", arg_exec_user);
        if (r < 0)
            return log_oom();

        r = strv_extendf(&user_env, "LOGNAME=%s", arg_exec_user);
        if (r < 0)
            return log_oom();

        if (!arg_exec_group) {
            if (setresgid(gid, gid, gid) < 0)
                return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
        }

        if (setresuid(uid, uid, uid) < 0)
            return log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", uid);
    }

    env = strv_env_merge(3, environ, user_env, arg_environment);
    if (!env)
        return log_oom();

    r = sd_bus_message_read(reply, "o", &object);
    if (r < 0)
        return bus_log_parse_error(r);

    r = bus_wait_for_jobs_one(w, object, arg_quiet);
    if (r < 0)
        return r;

    if (!arg_quiet)
        log_info("Running scope as unit: %s", scope);

    execvpe(argv[0], argv, env);

    return log_error_errno(errno, "Failed to execute: %m");
}
Exemple #10
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 ++;
                }
        }
Exemple #11
0
static int ratbagd_profile_get_resolutions(sd_bus *bus,
					   const char *path,
					   const char *interface,
					   const char *property,
					   sd_bus_message *reply,
					   void *userdata,
					   sd_bus_error *error)
{
	struct ratbagd_profile *profile = userdata;
	unsigned int i, n_resolutions;
	int r;

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

	n_resolutions = ratbag_profile_get_num_resolutions(profile->lib_profile);
	for (i = 0; i < n_resolutions; ++i) {
		struct ratbag_resolution *resolution;
		bool cap_separate_xy_resolution;
		unsigned int dpi_x, dpi_y, report_rate;

		resolution = ratbag_profile_get_resolution(profile->lib_profile, i);
		if (!resolution)
			continue;

		cap_separate_xy_resolution = ratbag_resolution_has_capability(resolution,
							RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION);
		report_rate = ratbag_resolution_get_report_rate(resolution);
		if (cap_separate_xy_resolution) {
			dpi_x = ratbag_resolution_get_dpi_x(resolution);
			dpi_y = ratbag_resolution_get_dpi_y(resolution);
		} else {
			dpi_x = ratbag_resolution_get_dpi(resolution);
		}

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

		if (cap_separate_xy_resolution) {
			r = sd_bus_message_append(reply, "{sv}",
						  "dpi-x", "u", dpi_x);
			if (r < 0)
				return r;

			r = sd_bus_message_append(reply, "{sv}",
						  "dpi-y", "u", dpi_y);
			if (r < 0)
				return r;
		} else {
			r = sd_bus_message_append(reply, "{sv}",
						  "dpi", "u", dpi_x);
			if (r < 0)
				return r;
		}

		r = sd_bus_message_append(reply, "{sv}",
					  "report-rate", "u", report_rate);
		if (r < 0)
			return r;

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

	return sd_bus_message_close_container(reply);
}
Exemple #12
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);
}
Exemple #13
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);
}
Exemple #14
0
int main(int argc, char *argv[]) {
        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
        int r, boolean;
        const char *x, *y, *z, *a, *b, *c, *d;
        uint8_t u, v;
        void *buffer = NULL;
        size_t sz;
        char *h;
        const int32_t integer_array[] = { -1, -2, 0, 1, 2 }, *return_array;

        r = sd_bus_message_new_method_call(NULL, "foobar.waldo", "/", "foobar.waldo", "Piep", &m);
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "s", "a string");
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "s", NULL);
        assert_se(r < 0);

        r = sd_bus_message_append(m, "as", 2, "string #1", "string #2");
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "sass", "foobar", 5, "foo", "bar", "waldo", "piep", "pap", "after");
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "a{yv}", 2, 3, "s", "foo", 5, "s", "waldo");
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "ba(ss)", 255, 3, "aaa", "1", "bbb", "2", "ccc", "3");
        assert_se(r >= 0);

        r = sd_bus_message_open_container(m, 'a', "s");
        assert_se(r >= 0);

        r = sd_bus_message_append_basic(m, 's', "foobar");
        assert_se(r >= 0);

        r = sd_bus_message_append_basic(m, 's', "waldo");
        assert_se(r >= 0);

        r = sd_bus_message_close_container(m);
        assert_se(r >= 0);

        r = sd_bus_message_append_array(m, 'i', integer_array, sizeof(integer_array));
        assert_se(r >= 0);

        r = bus_message_seal(m, 4711);
        assert_se(r >= 0);

        bus_message_dump(m);

        r = bus_message_get_blob(m, &buffer, &sz);
        assert_se(r >= 0);

        h = hexmem(buffer, sz);
        assert_se(h);

        log_info("message size = %lu, contents =\n%s", (unsigned long) sz, h);
        free(h);

#ifdef HAVE_GLIB
        {
                GDBusMessage *g;
                char *p;

#if !defined(GLIB_VERSION_2_36)
                g_type_init();
#endif

                g = g_dbus_message_new_from_blob(buffer, sz, 0, NULL);
                p = g_dbus_message_print(g, 0);
                log_info("%s", p);
                g_free(p);
                g_object_unref(g);
        }
#endif

        {
                DBusMessage *w;
                DBusError error;

                dbus_error_init(&error);

                w = dbus_message_demarshal(buffer, sz, &error);
                if (!w) {
                        log_error("%s", error.message);
                } else
                        dbus_message_unref(w);
        }

        m = sd_bus_message_unref(m);

        r = bus_message_from_malloc(buffer, sz, NULL, 0, NULL, NULL, &m);
        assert_se(r >= 0);

        bus_message_dump(m);

        assert_se(sd_bus_message_rewind(m, true) >= 0);

        r = sd_bus_message_read(m, "sas", &x, 2, &y, &z);
        assert_se(r > 0);
        assert_se(streq(x, "a string"));
        assert_se(streq(y, "string #1"));
        assert_se(streq(z, "string #2"));

        r = sd_bus_message_read(m, "sass", &x, 5, &y, &z, &a, &b, &c, &d);
        assert_se(r > 0);
        assert_se(streq(x, "foobar"));
        assert_se(streq(y, "foo"));
        assert_se(streq(z, "bar"));
        assert_se(streq(a, "waldo"));
        assert_se(streq(b, "piep"));
        assert_se(streq(c, "pap"));
        assert_se(streq(d, "after"));

        r = sd_bus_message_read(m, "a{yv}", 2, &u, "s", &x, &v, "s", &y);
        assert_se(r > 0);
        assert_se(u == 3);
        assert_se(streq(x, "foo"));
        assert_se(v == 5);
        assert_se(streq(y, "waldo"));

        r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d);
        assert_se(r > 0);
        assert_se(boolean);
        assert_se(streq(x, "aaa"));
        assert_se(streq(y, "1"));
        assert_se(streq(a, "bbb"));
        assert_se(streq(b, "2"));
        assert_se(streq(c, "ccc"));
        assert_se(streq(d, "3"));

        r = sd_bus_message_read(m, "as", 2, &x, &y);
        assert_se(r > 0);
        assert_se(streq(x, "foobar"));
        assert_se(streq(y, "waldo"));

        r = sd_bus_message_read_array(m, 'i', (const void**) &return_array, &sz);
        assert_se(r > 0);
        assert_se(sz == sizeof(integer_array));
        assert_se(memcmp(integer_array, return_array, sz) == 0);

        r = sd_bus_message_peek_type(m, NULL, NULL);
        assert_se(r == 0);

        return 0;
}
Exemple #15
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);
}
//------------------------------------------------------------------------
// Takes FRU data, invokes Parser for each fru record area and updates
// Inventory
//------------------------------------------------------------------------
int ipmi_update_inventory(fru_area_vec_t & area_vec)
{
    // Generic error reporter
    int rc = 0;

    // Dictionary object to hold Name:Value pair
    sd_bus_message *fru_dict = NULL;

    // SD Bus error report mechanism.
    sd_bus_error bus_error = SD_BUS_ERROR_NULL;

    // Response from sd bus calls
    sd_bus_message *response = NULL;

    // For each FRU area, extract the needed data , get it parsed and update
    // the Inventory.
    for(auto& iter : area_vec)
    {
        // Start fresh on each.
        sd_bus_error_free(&bus_error);
        sd_bus_message_unref(response);
        sd_bus_message_unref(fru_dict);

        // Constructor to allow further initializations and customization.
        rc = sd_bus_message_new_method_call((iter)->get_bus_type(),
                                            &fru_dict,
                                            (iter)->get_bus_name(),
                                            (iter)->get_obj_path(),
                                            (iter)->get_intf_name(),
                                            "update");
        if(rc < 0)
        {
            fprintf(stderr,"ERROR: creating a update method call for bus_name:[%s]\n",
                    (iter)->get_bus_name());
            break;
        }

        // A Dictionary ({}) having (string, variant)
        rc = sd_bus_message_open_container(fru_dict, 'a', "{sv}");
        if(rc < 0)
        {
            fprintf(stderr,"ERROR:[%d] creating a dict container:\n",errno);
            break;
        }

        // Fill the container with information
        rc = parse_fru_area((iter)->get_type(), (void *)(iter)->get_data(), (iter)->get_len(), fru_dict);
        if(rc < 0)
        {
            fprintf(stderr,"ERROR parsing FRU records\n");
            break;
        }

        sd_bus_message_close_container(fru_dict);

        // Now, Make the actual call to update the FRU inventory database with the
        // dictionary given by FRU Parser. There is no response message expected for
        // this.
        rc = sd_bus_call((iter)->get_bus_type(),     // On the System Bus
                         fru_dict,                   // With the Name:value dictionary array
                         0,                          //
                         &bus_error,                 // Object to return error.
                         &response);                 // Response message if any.

        if(rc < 0)
        {
            fprintf(stderr, "ERROR:[%s] updating FRU inventory for ID:[0x%X]\n",
                    bus_error.message, (iter)->get_fruid());
            break;
        }
        else if((iter)->is_bmc_fru())
        {
            // For FRUs that are accessible by HostBoot, host boot does all of
            // these.
            printf("SUCCESS: Updated:[%s_%d] successfully. Setting Valid bit\n",
                    (iter)->get_name(), (iter)->get_fruid());

            (iter)->set_valid(true);
        }
        else
        {
            printf("SUCCESS: Updated:[%s_%d] successfully\n",
                        (iter)->get_name(), (iter)->get_fruid());
        }
    } // END walking the vector of areas and updating

    sd_bus_error_free(&bus_error);
    sd_bus_message_unref(response);
    sd_bus_message_unref(fru_dict);

    return rc;
}
Exemple #17
0
static int start_transient_timer(
    sd_bus *bus,
    char **argv) {

    _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
    _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
    _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
    _cleanup_free_ char *timer = NULL, *service = NULL;
    const char *object = NULL;
    int r;

    assert(bus);
    assert(argv);

    r = bus_wait_for_jobs_new(bus, &w);
    if (r < 0)
        return log_oom();

    if (arg_unit) {
        switch (unit_name_to_type(arg_unit)) {

        case UNIT_SERVICE:
            service = strdup(arg_unit);
            if (!service)
                return log_oom();

            r = unit_name_change_suffix(service, ".timer", &timer);
            if (r < 0)
                return log_error_errno(r, "Failed to change unit suffix: %m");
            break;

        case UNIT_TIMER:
            timer = strdup(arg_unit);
            if (!timer)
                return log_oom();

            r = unit_name_change_suffix(timer, ".service", &service);
            if (r < 0)
                return log_error_errno(r, "Failed to change unit suffix: %m");
            break;

        default:
            r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".service", &service);
            if (r < 0)
                return log_error_errno(r, "Failed to mangle unit name: %m");

            r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".timer", &timer);
            if (r < 0)
                return log_error_errno(r, "Failed to mangle unit name: %m");

            break;
        }
    } else {
        r = make_unit_name(bus, UNIT_SERVICE, &service);
        if (r < 0)
            return r;

        r = unit_name_change_suffix(service, ".timer", &timer);
        if (r < 0)
            return log_error_errno(r, "Failed to change unit suffix: %m");
    }

    r = sd_bus_message_new_method_call(
            bus,
            &m,
            "org.freedesktop.systemd1",
            "/org/freedesktop/systemd1",
            "org.freedesktop.systemd1.Manager",
            "StartTransientUnit");
    if (r < 0)
        return bus_log_create_error(r);

    r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
    if (r < 0)
        return bus_log_create_error(r);

    /* Name and Mode */
    r = sd_bus_message_append(m, "ss", timer, "fail");
    if (r < 0)
        return bus_log_create_error(r);

    /* Properties */
    r = sd_bus_message_open_container(m, 'a', "(sv)");
    if (r < 0)
        return bus_log_create_error(r);

    r = transient_timer_set_properties(m);
    if (r < 0)
        return bus_log_create_error(r);

    r = sd_bus_message_close_container(m);
    if (r < 0)
        return bus_log_create_error(r);

    r = sd_bus_message_open_container(m, 'a', "(sa(sv))");
    if (r < 0)
        return bus_log_create_error(r);

    if (!strv_isempty(argv)) {
        r = sd_bus_message_open_container(m, 'r', "sa(sv)");
        if (r < 0)
            return bus_log_create_error(r);

        r = sd_bus_message_append(m, "s", service);
        if (r < 0)
            return bus_log_create_error(r);

        r = sd_bus_message_open_container(m, 'a', "(sv)");
        if (r < 0)
            return bus_log_create_error(r);

        r = transient_service_set_properties(m, argv, NULL);
        if (r < 0)
            return bus_log_create_error(r);

        r = sd_bus_message_close_container(m);
        if (r < 0)
            return bus_log_create_error(r);

        r = sd_bus_message_close_container(m);
        if (r < 0)
            return bus_log_create_error(r);
    }

    r = sd_bus_message_close_container(m);
    if (r < 0)
        return bus_log_create_error(r);

    polkit_agent_open_if_enabled();

    r = sd_bus_call(bus, m, 0, &error, &reply);
    if (r < 0) {
        log_error("Failed to start transient timer unit: %s", bus_error_message(&error, -r));
        return r;
    }

    r = sd_bus_message_read(reply, "o", &object);
    if (r < 0)
        return bus_log_parse_error(r);

    r = bus_wait_for_jobs_one(w, object, arg_quiet);
    if (r < 0)
        return r;

    if (!arg_quiet) {
        log_info("Running timer as unit: %s", timer);
        if (argv[0])
            log_info("Will run service as unit: %s", service);
    }

    return 0;
}
Exemple #18
0
int allocate_scope(
                sd_bus *bus,
                const char *machine_name,
                pid_t pid,
                const char *slice,
                CustomMount *mounts,
                unsigned n_mounts,
                int kill_signal,
                char **properties) {

        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
        _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
        _cleanup_free_ char *scope = NULL;
        const char *description, *object;
        int r;

        assert(bus);

        r = bus_wait_for_jobs_new(bus, &w);
        if (r < 0)
                return log_error_errno(r, "Could not watch job: %m");

        r = unit_name_mangle_with_suffix(machine_name, UNIT_NAME_NOGLOB, ".scope", &scope);
        if (r < 0)
                return log_error_errno(r, "Failed to mangle scope name: %m");

        r = sd_bus_message_new_method_call(
                        bus,
                        &m,
                        "org.freedesktop.systemd1",
                        "/org/freedesktop/systemd1",
                        "org.freedesktop.systemd1.Manager",
                        "StartTransientUnit");
        if (r < 0)
                return bus_log_create_error(r);

        r = sd_bus_message_append(m, "ss", scope, "fail");
        if (r < 0)
                return bus_log_create_error(r);

        /* Properties */
        r = sd_bus_message_open_container(m, 'a', "(sv)");
        if (r < 0)
                return bus_log_create_error(r);

        description = strjoina("Container ", machine_name);

        r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)",
                                  "PIDs", "au", 1, pid,
                                  "Description", "s", description,
                                  "Delegate", "b", 1,
                                  "Slice", "s", isempty(slice) ? "machine.slice" : slice);
        if (r < 0)
                return bus_log_create_error(r);

        r = append_controller_property(bus, m);
        if (r < 0)
                return r;

        r = append_machine_properties(
                        m,
                        mounts,
                        n_mounts,
                        kill_signal,
                        properties);
        if (r < 0)
                return r;

        r = bus_append_unit_property_assignment_many(m, UNIT_SCOPE, properties);
        if (r < 0)
                return r;

        r = sd_bus_message_close_container(m);
        if (r < 0)
                return bus_log_create_error(r);

        /* No auxiliary units */
        r = sd_bus_message_append(
                        m,
                        "a(sa(sv))",
                        0);
        if (r < 0)
                return bus_log_create_error(r);

        r = sd_bus_call(bus, m, 0, &error, &reply);
        if (r < 0) {
                log_error("Failed to allocate scope: %s", bus_error_message(&error, r));
                return r;
        }

        r = sd_bus_message_read(reply, "o", &object);
        if (r < 0)
                return bus_log_parse_error(r);

        r = bus_wait_for_jobs_one(w, object, false);
        if (r < 0)
                return r;

        return 0;
}
int main(int argc, char *argv[]) {
        _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL;
        const char *unique;
        uint8_t *p;
        sd_bus *a, *b;
        int r, bus_ref;
        sd_bus_message *m;
        int f;
        uint64_t sz;
        uint32_t u32;
        size_t i, l;
        char *s;
        _cleanup_close_ int sfd = -1;

        log_set_max_level(LOG_DEBUG);

        assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0);

        bus_ref = bus_kernel_create_bus(name, false, &bus_name);
        if (bus_ref == -ENOENT)
                return EXIT_TEST_SKIP;

        assert_se(bus_ref >= 0);

        address = strappend("kernel:path=", bus_name);
        assert_se(address);

        r = sd_bus_new(&a);
        assert_se(r >= 0);

        r = sd_bus_new(&b);
        assert_se(r >= 0);

        r = sd_bus_set_address(a, address);
        assert_se(r >= 0);

        r = sd_bus_set_address(b, address);
        assert_se(r >= 0);

        r = sd_bus_start(a);
        assert_se(r >= 0);

        r = sd_bus_start(b);
        assert_se(r >= 0);

        r = sd_bus_get_unique_name(a, &unique);
        assert_se(r >= 0);

        r = sd_bus_message_new_method_call(b, &m, unique, "/a/path", "an.inter.face", "AMethod");
        assert_se(r >= 0);

        r = sd_bus_message_open_container(m, 'r', "aysay");
        assert_se(r >= 0);

        r = sd_bus_message_append_array_space(m, 'y', FIRST_ARRAY, (void**) &p);
        assert_se(r >= 0);

        p[0] = '<';
        memset(p+1, 'L', FIRST_ARRAY-2);
        p[FIRST_ARRAY-1] = '>';

        f = memfd_new_and_map(NULL, STRING_SIZE, (void**) &s);
        assert_se(f >= 0);

        s[0] = '<';
        for (i = 1; i < STRING_SIZE-2; i++)
                s[i] = '0' + (i % 10);
        s[STRING_SIZE-2] = '>';
        s[STRING_SIZE-1] = 0;
        munmap(s, STRING_SIZE);

        r = memfd_get_size(f, &sz);
        assert_se(r >= 0);
        assert_se(sz == STRING_SIZE);

        r = sd_bus_message_append_string_memfd(m, f, 0, (uint64_t) -1);
        assert_se(r >= 0);

        close(f);

        f = memfd_new_and_map(NULL, SECOND_ARRAY, (void**) &p);
        assert_se(f >= 0);

        p[0] = '<';
        memset(p+1, 'P', SECOND_ARRAY-2);
        p[SECOND_ARRAY-1] = '>';
        munmap(p, SECOND_ARRAY);

        r = memfd_get_size(f, &sz);
        assert_se(r >= 0);
        assert_se(sz == SECOND_ARRAY);

        r = sd_bus_message_append_array_memfd(m, 'y', f, 0, (uint64_t) -1);
        assert_se(r >= 0);

        close(f);

        r = sd_bus_message_close_container(m);
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "u", 4711);
        assert_se(r >= 0);

        assert_se((sfd = memfd_new_and_map(NULL, 6, (void**) &p)) >= 0);
        memcpy(p, "abcd\0", 6);
        munmap(p, 6);
        assert_se(sd_bus_message_append_string_memfd(m, sfd, 1, 4) >= 0);

        r = bus_message_seal(m, 55, 99*USEC_PER_SEC);
        assert_se(r >= 0);

        bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);

        r = sd_bus_send(b, m, NULL);
        assert_se(r >= 0);

        sd_bus_message_unref(m);

        r = sd_bus_process(a, &m);
        assert_se(r > 0);

        bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
        sd_bus_message_rewind(m, true);

        r = sd_bus_message_enter_container(m, 'r', "aysay");
        assert_se(r > 0);

        r = sd_bus_message_read_array(m, 'y', (const void**) &p, &l);
        assert_se(r > 0);
        assert_se(l == FIRST_ARRAY);

        assert_se(p[0] == '<');
        for (i = 1; i < l-1; i++)
                assert_se(p[i] == 'L');
        assert_se(p[l-1] == '>');

        r = sd_bus_message_read(m, "s", &s);
        assert_se(r > 0);

        assert_se(s[0] == '<');
        for (i = 1; i < STRING_SIZE-2; i++)
                assert_se(s[i] == (char) ('0' + (i % 10)));
        assert_se(s[STRING_SIZE-2] == '>');
        assert_se(s[STRING_SIZE-1] == 0);

        r = sd_bus_message_read_array(m, 'y', (const void**) &p, &l);
        assert_se(r > 0);
        assert_se(l == SECOND_ARRAY);

        assert_se(p[0] == '<');
        for (i = 1; i < l-1; i++)
                assert_se(p[i] == 'P');
        assert_se(p[l-1] == '>');

        r = sd_bus_message_exit_container(m);
        assert_se(r > 0);

        r = sd_bus_message_read(m, "u", &u32);
        assert_se(r > 0);
        assert_se(u32 == 4711);

        r = sd_bus_message_read(m, "s", &s);
        assert_se(r > 0);
        assert_se(streq_ptr(s, "bcd"));

        sd_bus_message_unref(m);

        sd_bus_unref(a);
        sd_bus_unref(b);

        return 0;
}
Exemple #20
0
int bus_test_polkit(
                sd_bus_message *call,
                int capability,
                const char *action,
                const char **details,
                uid_t good_user,
                bool *_challenge,
                sd_bus_error *e) {

        int r;

        assert(call);
        assert(action);

        /* Tests non-interactively! */

        r = check_good_user(call, good_user);
        if (r != 0)
                return r;

        r = sd_bus_query_sender_privilege(call, capability);
        if (r < 0)
                return r;
        else if (r > 0)
                return 1;
#ifdef ENABLE_POLKIT
        else {
                _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL;
                _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
                int authorized = false, challenge = false;
                const char *sender, **k, **v;

                sender = sd_bus_message_get_sender(call);
                if (!sender)
                        return -EBADMSG;

                r = sd_bus_message_new_method_call(
                                call->bus,
                                &request,
                                "org.freedesktop.PolicyKit1",
                                "/org/freedesktop/PolicyKit1/Authority",
                                "org.freedesktop.PolicyKit1.Authority",
                                "CheckAuthorization");
                if (r < 0)
                        return r;

                r = sd_bus_message_append(
                                request,
                                "(sa{sv})s",
                                "system-bus-name", 1, "name", "s", sender,
                                action);
                if (r < 0)
                        return r;

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

                STRV_FOREACH_PAIR(k, v, details) {
                        r = sd_bus_message_append(request, "{ss}", *k, *v);
                        if (r < 0)
                                return r;
                }

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

                r = sd_bus_message_append(request, "us", 0, NULL);
                if (r < 0)
                        return r;

                r = sd_bus_call(call->bus, request, 0, e, &reply);
                if (r < 0) {
                        /* Treat no PK available as access denied */
                        if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
                                sd_bus_error_free(e);
                                return -EACCES;
                        }

                        return r;
                }

                r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
                if (r < 0)
                        return r;

                r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
                if (r < 0)
                        return r;

                if (authorized)
                        return 1;

                if (_challenge) {
                        *_challenge = challenge;
                        return 0;
                }
        }
Exemple #21
0
int register_machine(
                sd_bus *bus,
                const char *machine_name,
                pid_t pid,
                const char *directory,
                sd_id128_t uuid,
                int local_ifindex,
                const char *slice,
                CustomMount *mounts,
                unsigned n_mounts,
                int kill_signal,
                char **properties,
                bool keep_unit,
                const char *service) {

        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        int r;

        assert(bus);

        if (keep_unit) {
                r = sd_bus_call_method(
                                bus,
                                "org.freedesktop.machine1",
                                "/org/freedesktop/machine1",
                                "org.freedesktop.machine1.Manager",
                                "RegisterMachineWithNetwork",
                                &error,
                                NULL,
                                "sayssusai",
                                machine_name,
                                SD_BUS_MESSAGE_APPEND_ID128(uuid),
                                service,
                                "container",
                                (uint32_t) pid,
                                strempty(directory),
                                local_ifindex > 0 ? 1 : 0, local_ifindex);
        } else {
                _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;

                r = sd_bus_message_new_method_call(
                                bus,
                                &m,
                                "org.freedesktop.machine1",
                                "/org/freedesktop/machine1",
                                "org.freedesktop.machine1.Manager",
                                "CreateMachineWithNetwork");
                if (r < 0)
                        return bus_log_create_error(r);

                r = sd_bus_message_append(
                                m,
                                "sayssusai",
                                machine_name,
                                SD_BUS_MESSAGE_APPEND_ID128(uuid),
                                service,
                                "container",
                                (uint32_t) pid,
                                strempty(directory),
                                local_ifindex > 0 ? 1 : 0, local_ifindex);
                if (r < 0)
                        return bus_log_create_error(r);

                r = sd_bus_message_open_container(m, 'a', "(sv)");
                if (r < 0)
                        return bus_log_create_error(r);

                if (!isempty(slice)) {
                        r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
                        if (r < 0)
                                return bus_log_create_error(r);
                }

                r = append_controller_property(bus, m);
                if (r < 0)
                        return r;

                r = append_machine_properties(
                                m,
                                mounts,
                                n_mounts,
                                kill_signal,
                                properties);
                if (r < 0)
                        return r;

                r = bus_append_unit_property_assignment_many(m, UNIT_SERVICE, properties);
                if (r < 0)
                        return r;

                r = sd_bus_message_close_container(m);
                if (r < 0)
                        return bus_log_create_error(r);

                r = sd_bus_call(bus, m, 0, &error, NULL);
        }

        if (r < 0) {
                log_error("Failed to register machine: %s", bus_error_message(&error, r));
                return r;
        }

        return 0;
}
Exemple #22
0
static int transient_service_set_properties(sd_bus_message *m, char **argv, const char *pty_path) {
    int r;

    assert(m);

    r = transient_unit_set_properties(m, arg_property);
    if (r < 0)
        return r;

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

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

    if (arg_wait) {
        r = sd_bus_message_append(m, "(sv)", "AddRef", "b", 1);
        if (r < 0)
            return r;
    }

    if (arg_remain_after_exit) {
        r = sd_bus_message_append(m, "(sv)", "RemainAfterExit", "b", arg_remain_after_exit);
        if (r < 0)
            return r;
    }

    if (arg_service_type) {
        r = sd_bus_message_append(m, "(sv)", "Type", "s", arg_service_type);
        if (r < 0)
            return r;
    }

    if (arg_exec_user) {
        r = sd_bus_message_append(m, "(sv)", "User", "s", arg_exec_user);
        if (r < 0)
            return r;
    }

    if (arg_exec_group) {
        r = sd_bus_message_append(m, "(sv)", "Group", "s", arg_exec_group);
        if (r < 0)
            return r;
    }

    if (arg_nice_set) {
        r = sd_bus_message_append(m, "(sv)", "Nice", "i", arg_nice);
        if (r < 0)
            return r;
    }

    if (pty_path) {
        const char *e;

        r = sd_bus_message_append(m,
                                  "(sv)(sv)(sv)(sv)",
                                  "StandardInput", "s", "tty",
                                  "StandardOutput", "s", "tty",
                                  "StandardError", "s", "tty",
                                  "TTYPath", "s", pty_path);
        if (r < 0)
            return r;

        e = getenv("TERM");
        if (e) {
            char *n;

            n = strjoina("TERM=", e);
            r = sd_bus_message_append(m,
                                      "(sv)",
                                      "Environment", "as", 1, n);
            if (r < 0)
                return r;
        }
    }

    if (!strv_isempty(arg_environment)) {
        r = sd_bus_message_open_container(m, 'r', "sv");
        if (r < 0)
            return r;

        r = sd_bus_message_append(m, "s", "Environment");
        if (r < 0)
            return r;

        r = sd_bus_message_open_container(m, 'v', "as");
        if (r < 0)
            return r;

        r = sd_bus_message_append_strv(m, arg_environment);
        if (r < 0)
            return r;

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

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

    /* Exec container */
    {
        r = sd_bus_message_open_container(m, 'r', "sv");
        if (r < 0)
            return r;

        r = sd_bus_message_append(m, "s", "ExecStart");
        if (r < 0)
            return r;

        r = sd_bus_message_open_container(m, 'v', "a(sasb)");
        if (r < 0)
            return r;

        r = sd_bus_message_open_container(m, 'a', "(sasb)");
        if (r < 0)
            return r;

        r = sd_bus_message_open_container(m, 'r', "sasb");
        if (r < 0)
            return r;

        r = sd_bus_message_append(m, "s", argv[0]);
        if (r < 0)
            return r;

        r = sd_bus_message_append_strv(m, argv);
        if (r < 0)
            return r;

        r = sd_bus_message_append(m, "b", false);
        if (r < 0)
            return r;

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

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

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

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

    return 0;
}
Exemple #23
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);
                }
Exemple #24
0
int main(int argc, char *argv[]) {
        _cleanup_free_ char *bus_name = NULL, *address = NULL;
        uint8_t *p;
        sd_bus *a, *b;
        int r, bus_ref;
        sd_bus_message *m;
        sd_memfd *f;
        uint64_t sz;
        uint32_t u32;
        size_t i, l;
        char *s;

        log_set_max_level(LOG_DEBUG);

        bus_ref = bus_kernel_create("deine-mutter", &bus_name);
        if (bus_ref == -ENOENT)
                return EXIT_TEST_SKIP;

        assert_se(bus_ref >= 0);

        address = strappend("kernel:path=", bus_name);
        assert_se(address);

        r = sd_bus_new(&a);
        assert_se(r >= 0);

        r = sd_bus_new(&b);
        assert_se(r >= 0);

        r = sd_bus_set_address(a, address);
        assert_se(r >= 0);

        r = sd_bus_set_address(b, address);
        assert_se(r >= 0);

        r = sd_bus_start(a);
        assert_se(r >= 0);

        r = sd_bus_start(b);
        assert_se(r >= 0);

        r = sd_bus_message_new_method_call(b, ":1.1", "/a/path", "an.inter.face", "AMethod", &m);
        assert_se(r >= 0);

        r = sd_bus_message_open_container(m, 'r', "aysay");
        assert_se(r >= 0);

        r = sd_bus_message_append_array_space(m, 'y', FIRST_ARRAY, (void**) &p);
        assert_se(r >= 0);

        memset(p, 'L', FIRST_ARRAY);

        r = sd_memfd_new_and_map(&f, STRING_SIZE, (void**) &s);
        assert_se(r >= 0);

        for (i = 0; i < STRING_SIZE-1; i++)
                s[i] = '0' + (i % 10);

        s[STRING_SIZE-1] = 0;
        munmap(s, STRING_SIZE);

        r = sd_memfd_get_size(f, &sz);
        assert_se(r >= 0);
        assert_se(sz == STRING_SIZE);

        r = sd_bus_message_append_string_memfd(m, f);
        assert_se(r >= 0);

        sd_memfd_free(f);

        r = sd_memfd_new_and_map(&f, SECOND_ARRAY, (void**) &p);
        assert_se(r >= 0);

        memset(p, 'P', SECOND_ARRAY);
        munmap(p, SECOND_ARRAY);

        r = sd_memfd_get_size(f, &sz);
        assert_se(r >= 0);
        assert_se(sz == SECOND_ARRAY);

        r = sd_bus_message_append_array_memfd(m, 'y', f);
        assert_se(r >= 0);

        sd_memfd_free(f);

        r = sd_bus_message_close_container(m);
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "u", 4711);
        assert_se(r >= 0);

        r = bus_message_seal(m, 55);
        assert_se(r >= 0);

        bus_message_dump(m, stdout, true);

        r = sd_bus_send(b, m, NULL);
        assert_se(r >= 0);

        sd_bus_message_unref(m);

        r = sd_bus_process(a, &m);
        assert_se(r > 0);

        bus_message_dump(m, stdout, true);
        sd_bus_message_rewind(m, true);

        r = sd_bus_message_enter_container(m, 'r', "aysay");
        assert_se(r > 0);

        r = sd_bus_message_read_array(m, 'y', (const void**) &p, &l);
        assert_se(r > 0);
        assert_se(l == FIRST_ARRAY);

        for (i = 0; i < l; i++)
                assert_se(p[i] == 'L');

        r = sd_bus_message_read(m, "s", &s);
        assert_se(r > 0);

        for (i = 0; i < STRING_SIZE-1; i++)
                assert_se(s[i] == (char) ('0' + (i % 10)));
        assert_se(s[STRING_SIZE-1] == 0);

        r = sd_bus_message_read_array(m, 'y', (const void**) &p, &l);
        assert_se(r > 0);
        assert_se(l == SECOND_ARRAY);

        for (i = 0; i < l; i++)
                assert_se(p[i] == 'P');

        r = sd_bus_message_exit_container(m);
        assert_se(r > 0);

        r = sd_bus_message_read(m, "u", &u32);
        assert_se(r > 0);
        assert_se(u32 == 4711);

        sd_bus_message_unref(m);

        sd_bus_unref(a);
        sd_bus_unref(b);

        return 0;
}
Exemple #25
0
int main(int argc, char *argv[]) {
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *copy = NULL;
        int r, boolean;
        const char *x, *x2, *y, *z, *a, *b, *c, *d, *a_signature;
        uint8_t u, v;
        void *buffer = NULL;
        size_t sz;
        char *h;
        const int32_t integer_array[] = { -1, -2, 0, 1, 2 }, *return_array;
        char *s;
        _cleanup_free_ char *first = NULL, *second = NULL, *third = NULL;
        _cleanup_fclose_ FILE *ms = NULL;
        size_t first_size = 0, second_size = 0, third_size = 0;
        _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
        double dbl;
        uint64_t u64;

        r = sd_bus_default_system(&bus);
        if (r < 0)
                return EXIT_TEST_SKIP;

        r = sd_bus_message_new_method_call(bus, &m, "foobar.waldo", "/", "foobar.waldo", "Piep");
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "");
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "s", "a string");
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "s", NULL);
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "asg", 2, "string #1", "string #2", "sba(tt)ss");
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "sass", "foobar", 5, "foo", "bar", "waldo", "piep", "pap", "after");
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "a{yv}", 2, 3, "s", "foo", 5, "s", "waldo");
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "y(ty)y(yt)y", 8, 777ULL, 7, 9, 77, 7777ULL, 10);
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "()");
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "ba(ss)", 255, 3, "aaa", "1", "bbb", "2", "ccc", "3");
        assert_se(r >= 0);

        r = sd_bus_message_open_container(m, 'a', "s");
        assert_se(r >= 0);

        r = sd_bus_message_append_basic(m, 's', "foobar");
        assert_se(r >= 0);

        r = sd_bus_message_append_basic(m, 's', "waldo");
        assert_se(r >= 0);

        r = sd_bus_message_close_container(m);
        assert_se(r >= 0);

        r = sd_bus_message_append_string_space(m, 5, &s);
        assert_se(r >= 0);
        strcpy(s, "hallo");

        r = sd_bus_message_append_array(m, 'i', integer_array, sizeof(integer_array));
        assert_se(r >= 0);

        r = sd_bus_message_append_array(m, 'u', NULL, 0);
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "a(stdo)", 1, "foo", 815ULL, 47.0, "/");
        assert_se(r >= 0);

        r = bus_message_seal(m, 4711, 0);
        assert_se(r >= 0);

        bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);

        ms = open_memstream(&first, &first_size);
        bus_message_dump(m, ms, 0);
        fflush(ms);
        assert_se(!ferror(ms));

        r = bus_message_get_blob(m, &buffer, &sz);
        assert_se(r >= 0);

        h = hexmem(buffer, sz);
        assert_se(h);

        log_info("message size = %zu, contents =\n%s", sz, h);
        free(h);

#ifdef HAVE_GLIB
        {
                GDBusMessage *g;
                char *p;

#if !defined(GLIB_VERSION_2_36)
                g_type_init();
#endif

                g = g_dbus_message_new_from_blob(buffer, sz, 0, NULL);
                p = g_dbus_message_print(g, 0);
                log_info("%s", p);
                g_free(p);
                g_object_unref(g);
        }
#endif

#ifdef HAVE_DBUS
        {
                DBusMessage *w;
                DBusError error;

                dbus_error_init(&error);

                w = dbus_message_demarshal(buffer, sz, &error);
                if (!w)
                        log_error("%s", error.message);
                else
                        dbus_message_unref(w);

                dbus_error_free(&error);
        }
#endif

        m = sd_bus_message_unref(m);

        r = bus_message_from_malloc(bus, buffer, sz, NULL, 0, NULL, &m);
        assert_se(r >= 0);

        bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);

        fclose(ms);
        ms = open_memstream(&second, &second_size);
        bus_message_dump(m, ms, 0);
        fflush(ms);
        assert_se(!ferror(ms));
        assert_se(first_size == second_size);
        assert_se(memcmp(first, second, first_size) == 0);

        assert_se(sd_bus_message_rewind(m, true) >= 0);

        r = sd_bus_message_read(m, "ssasg", &x, &x2, 2, &y, &z, &a_signature);
        assert_se(r > 0);
        assert_se(streq(x, "a string"));
        assert_se(streq(x2, ""));
        assert_se(streq(y, "string #1"));
        assert_se(streq(z, "string #2"));
        assert_se(streq(a_signature, "sba(tt)ss"));

        r = sd_bus_message_read(m, "sass", &x, 5, &y, &z, &a, &b, &c, &d);
        assert_se(r > 0);
        assert_se(streq(x, "foobar"));
        assert_se(streq(y, "foo"));
        assert_se(streq(z, "bar"));
        assert_se(streq(a, "waldo"));
        assert_se(streq(b, "piep"));
        assert_se(streq(c, "pap"));
        assert_se(streq(d, "after"));

        r = sd_bus_message_read(m, "a{yv}", 2, &u, "s", &x, &v, "s", &y);
        assert_se(r > 0);
        assert_se(u == 3);
        assert_se(streq(x, "foo"));
        assert_se(v == 5);
        assert_se(streq(y, "waldo"));

        r = sd_bus_message_read(m, "y(ty)", &v, &u64, &u);
        assert_se(r > 0);
        assert_se(v == 8);
        assert_se(u64 == 777);
        assert_se(u == 7);

        r = sd_bus_message_read(m, "y(yt)", &v, &u, &u64);
        assert_se(r > 0);
        assert_se(v == 9);
        assert_se(u == 77);
        assert_se(u64 == 7777);

        r = sd_bus_message_read(m, "y", &v);
        assert_se(r > 0);
        assert_se(v == 10);

        r = sd_bus_message_read(m, "()");
        assert_se(r > 0);

        r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d);
        assert_se(r > 0);
        assert_se(boolean);
        assert_se(streq(x, "aaa"));
        assert_se(streq(y, "1"));
        assert_se(streq(a, "bbb"));
        assert_se(streq(b, "2"));
        assert_se(streq(c, "ccc"));
        assert_se(streq(d, "3"));

        assert_se(sd_bus_message_verify_type(m, 'a', "s") > 0);

        r = sd_bus_message_read(m, "as", 2, &x, &y);
        assert_se(r > 0);
        assert_se(streq(x, "foobar"));
        assert_se(streq(y, "waldo"));

        r = sd_bus_message_read_basic(m, 's', &s);
        assert_se(r > 0);
        assert_se(streq(s, "hallo"));

        r = sd_bus_message_read_array(m, 'i', (const void**) &return_array, &sz);
        assert_se(r > 0);
        assert_se(sz == sizeof(integer_array));
        assert_se(memcmp(integer_array, return_array, sz) == 0);

        r = sd_bus_message_read_array(m, 'u', (const void**) &return_array, &sz);
        assert_se(r > 0);
        assert_se(sz == 0);

        r = sd_bus_message_read(m, "a(stdo)", 1, &x, &u64, &dbl, &y);
        assert_se(r > 0);
        assert_se(streq(x, "foo"));
        assert_se(u64 == 815ULL);
        assert_se(fabs(dbl - 47.0) < 0.1);
        assert_se(streq(y, "/"));

        r = sd_bus_message_peek_type(m, NULL, NULL);
        assert_se(r == 0);

        r = sd_bus_message_new_method_call(bus, &copy, "foobar.waldo", "/", "foobar.waldo", "Piep");
        assert_se(r >= 0);

        r = sd_bus_message_rewind(m, true);
        assert_se(r >= 0);

        r = sd_bus_message_copy(copy, m, true);
        assert_se(r >= 0);

        r = bus_message_seal(copy, 4712, 0);
        assert_se(r >= 0);

        fclose(ms);
        ms = open_memstream(&third, &third_size);
        bus_message_dump(copy, ms, 0);
        fflush(ms);
        assert_se(!ferror(ms));

        printf("<%.*s>\n", (int) first_size, first);
        printf("<%.*s>\n", (int) third_size, third);

        assert_se(first_size == third_size);
        assert_se(memcmp(first, third, third_size) == 0);

        r = sd_bus_message_rewind(m, true);
        assert_se(r >= 0);

        assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0);

        r = sd_bus_message_skip(m, "ssasg");
        assert_se(r > 0);

        assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0);

        r = sd_bus_message_skip(m, "sass");
        assert_se(r >= 0);

        assert_se(sd_bus_message_verify_type(m, 'a', "{yv}") > 0);

        r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y()");
        assert_se(r >= 0);

        assert_se(sd_bus_message_verify_type(m, 'b', NULL) > 0);

        r = sd_bus_message_read(m, "b", &boolean);
        assert_se(r > 0);
        assert_se(boolean);

        r = sd_bus_message_enter_container(m, 0, NULL);
        assert_se(r > 0);

        r = sd_bus_message_read(m, "(ss)", &x, &y);
        assert_se(r > 0);

        r = sd_bus_message_read(m, "(ss)", &a, &b);
        assert_se(r > 0);

        r = sd_bus_message_read(m, "(ss)", &c, &d);
        assert_se(r > 0);

        r = sd_bus_message_read(m, "(ss)", &x, &y);
        assert_se(r == 0);

        r = sd_bus_message_exit_container(m);
        assert_se(r >= 0);

        assert_se(streq(x, "aaa"));
        assert_se(streq(y, "1"));
        assert_se(streq(a, "bbb"));
        assert_se(streq(b, "2"));
        assert_se(streq(c, "ccc"));
        assert_se(streq(d, "3"));

        test_bus_label_escape();
        test_bus_path_encode();
        test_bus_path_encode_unique();
        test_bus_path_encode_many();

        return 0;
}
//------------------------------------------------------------------------
// Takes FRU data, invokes Parser for each fru record area and updates
// Inventory
//------------------------------------------------------------------------
int ipmi_update_inventory(const uint8_t fruid, const uint8_t *fru_data, 
                          fru_area_vec_t & area_vec)
{
    // Now, use this fru dictionary object and connect with FRU Inventory Dbus
    // and update the data for this FRU ID.
    int rc = 0;
    
    // Dictionary object to hold Name:Value pair
    sd_bus_message *fru_dict = NULL;

    // SD Bus error report mechanism.
    sd_bus_error bus_error = SD_BUS_ERROR_NULL;

    // Gets a hook onto either a SYSTEM or SESSION bus
    sd_bus *bus_type = ipmid_get_sd_bus_connection();

    // Req message contains the specifics about which method etc that we want to
    // access on which bus, object
    sd_bus_message *response = NULL;

    // For each FRU area, extract the needed data , get it parsed and update
    // the Inventory.
    for(auto& iter : area_vec)
    {
        uint8_t area_type = (iter).type;

        uint8_t area_data[(iter).len];
        memset(area_data, 0x0, sizeof(area_data));

        // Grab area specific data
        memmove(area_data, (iter).offset, (iter).len);

        // Need this to get respective DBUS objects
        const char *area_name  = NULL;

        if(area_type == IPMI_FRU_AREA_CHASSIS_INFO)
        {
            area_name = "CHASSIS_";
        }
        else if(area_type == IPMI_FRU_AREA_BOARD_INFO)
        {
            area_name = "BOARD_";
        }
        else if(area_type == IPMI_FRU_AREA_PRODUCT_INFO)
        {
            area_name = "PRODUCT_";
        }
        else
        {
            fprintf(stderr, "ERROR: Invalid Area type :[%d]",area_type);
            break;
        }
 
        // What we need is BOARD_1, PRODUCT_1, CHASSIS_1 etc..
        char fru_area_name[16] = {0};
        sprintf(fru_area_name,"%s%d",area_name, fruid);

#ifdef __IPMI_DEBUG__
        printf("Updating Inventory with :[%s]\n",fru_area_name);
#endif
        // Each area needs a clean set.       
        sd_bus_error_free(&bus_error);
        sd_bus_message_unref(response);
        sd_bus_message_unref(fru_dict);
    
        // We want to call a method "getObjectFromId" on System Bus that is
        // made available over  OpenBmc system services.
        rc = sd_bus_call_method(bus_type,                   // On the System Bus
                                bus_name,                   // Service to contact
                                object_name,                // Object path 
                                intf_name,                  // Interface name
                                "getObjectFromId",          // Method to be called
                                &bus_error,                 // object to return error
                                &response,                  // Response message on success
                                "ss",                       // input message (string,byte)
                                "FRU_STR",                  // First argument to getObjectFromId
                                fru_area_name);             // Second Argument

        if(rc < 0)
        {
            fprintf(stderr, "Failed to issue method call: %s\n", bus_error.message);
            break;
        }

        // Method getObjectFromId returns 3 parameters and all are strings, namely
        // bus_name , object_path and interface name for accessing that particular 
        // FRU over Inventory SDBUS manager. 'sss' here mentions that format.
        char *inv_bus_name, *inv_obj_path, *inv_intf_name;
        rc = sd_bus_message_read(response, "(sss)", &inv_bus_name, &inv_obj_path, &inv_intf_name);
        if(rc < 0)
        {
            fprintf(stderr, "Failed to parse response message:[%s]\n", strerror(-rc));
            break;
        }

#ifdef __IPMI_DEBUG__
        printf("fru_area=[%s], inv_bus_name=[%s], inv_obj_path=[%s],inv_intf_name=[%s]\n",
                fru_area_name, inv_bus_name, inv_obj_path, inv_intf_name);
#endif

        // Constructor to allow further initializations and customization.
        rc = sd_bus_message_new_method_call(bus_type,
                                            &fru_dict,
                                            inv_bus_name,
                                            inv_obj_path,
                                            inv_intf_name,
                                            "update");
        if(rc < 0)
        {
            fprintf(stderr,"ERROR: creating a update method call\n");
            break;
        }

        // A Dictionary ({}) having (string, variant)
        rc = sd_bus_message_open_container(fru_dict, 'a', "{sv}");
        if(rc < 0)
        {
            fprintf(stderr,"ERROR:[%d] creating a dict container:\n",errno);
            break;
        }

        // Fill the container with information
        rc = parse_fru_area((iter).type, (void *)area_data, (iter).len, fru_dict);
        if(rc < 0)
        {
            fprintf(stderr,"ERROR parsing FRU records\n");
            break;
        }

        sd_bus_message_close_container(fru_dict);

        // Now, Make the actual call to update the FRU inventory database with the
        // dictionary given by FRU Parser. There is no response message expected for
        // this.
        rc = sd_bus_call(bus_type,            // On the System Bus
                         fru_dict,            // With the Name:value dictionary array
                         0,                   // 
                         &bus_error,          // Object to return error.
                         &response);          // Response message if any.

        if(rc < 0)
        {
            fprintf(stderr, "ERROR:[%s] updating FRU inventory for ID:[0x%X]\n",
                    bus_error.message, fruid);
        }
        else
        {
            printf("SUCCESS: Updated:[%s] successfully\n",fru_area_name);
        }
    } // END walking the vector of areas and updating

    sd_bus_error_free(&bus_error);
    sd_bus_message_unref(response);
    sd_bus_message_unref(fru_dict);
    sd_bus_unref(bus_type);

    return rc;
}