static int count_addresses(sd_bus_message *m, int af, const char **canonical) {
        int c = 0, r, ifindex;

        assert(m);
        assert(canonical);

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

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

        while ((r = sd_bus_message_enter_container(m, 'r', "iay")) > 0) {
                int family;

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

                r = sd_bus_message_skip(m, "ay");
                if (r < 0)
                        return r;

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

                if (af != AF_UNSPEC && family != af)
                        continue;

                c ++;
        }
        if (r < 0)
                return r;

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

        r = sd_bus_message_read(m, "s", canonical);
        if (r < 0)
                return r;

        r = sd_bus_message_rewind(m, true);
        if (r < 0)
                return r;

        return c;
}
Beispiel #2
0
_public_ int sd_bus_get_property_strv(
                sd_bus *bus,
                const char *destination,
                const char *path,
                const char *interface,
                const char *member,
                sd_bus_error *error,
                char ***ret) {

        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        int r;

        assert_return(bus, -EINVAL);
        assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
        assert_return(member_name_is_valid(member), -EINVAL);
        assert_return(ret, -EINVAL);
        assert_return(!bus_pid_changed(bus), -ECHILD);

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

        r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
        if (r < 0)
                return r;

        r = sd_bus_message_enter_container(reply, 'v', NULL);
        if (r < 0)
                return r;

        r = sd_bus_message_read_strv(reply, ret);
        if (r < 0)
                return r;

        return 0;
}
static int kbdctx_set_locale(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
        kbdctx *kc = userdata;
        const char *s, *ctype = NULL, *lang = NULL;
        int r;

        r = sd_bus_message_enter_container(m, 'a', "s");
        if (r < 0)
                goto error;

        while ((r = sd_bus_message_read(m, "s", &s)) > 0) {
                if (!ctype)
                        ctype = startswith(s, "LC_CTYPE=");
                if (!lang)
                        lang = startswith(s, "LANG=");
        }

        if (r < 0)
                goto error;

        r = sd_bus_message_exit_container(m);
        if (r < 0)
                goto error;

        kbdctx_refresh_compose_table(kc, ctype ? : lang);
        r = 0;

error:
        if (r < 0)
                log_debug_errno(r, "idev-keyboard: cannot parse locale property from locale1: %m");

        return r;
}
Beispiel #4
0
int bus_message_map_properties_changed(sd_bus *bus,
                                       sd_bus_message *m,
                                       const struct bus_properties_map *map,
                                       void *userdata) {
        const char *member;
        int r, invalidated, i;

        assert(bus);
        assert(m);
        assert(map);

        r = bus_message_map_all_properties(bus, m, map, userdata);
        if (r < 0)
                return r;

        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
        if (r < 0)
                return r;

        invalidated = 0;
        while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
                for (i = 0; map[i].member; i++)
                        if (streq(map[i].member, member)) {
                                ++invalidated;
                                break;
                        }

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

        return invalidated;
}
Beispiel #5
0
_public_ int sd_bus_get_property_trivial(
                sd_bus *bus,
                const char *destination,
                const char *path,
                const char *interface,
                const char *member,
                sd_bus_error *error,
                char type, void *ptr) {

        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        int r;

        assert_return(bus, -EINVAL);
        assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
        assert_return(member_name_is_valid(member), -EINVAL);
        assert_return(bus_type_is_trivial(type), -EINVAL);
        assert_return(ptr, -EINVAL);
        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
        assert_return(!bus_pid_changed(bus), -ECHILD);

        r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
        if (r < 0)
                return r;

        r = sd_bus_message_enter_container(reply, 'v', CHAR_TO_STR(type));
        if (r < 0)
                return r;

        r = sd_bus_message_read_basic(reply, type, ptr);
        if (r < 0)
                return r;

        return 0;
}
static void print_inhibitors(sd_bus *bus) {
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        const char *what, *who, *why, *mode;
        uint32_t uid, pid;
        unsigned n = 0;
        int r;

        r = sd_bus_call_method(bus,
                        "org.freedesktop.login1",
                        "/org/freedesktop/login1",
                        "org.freedesktop.login1.Manager",
                        "ListInhibitors",
                        &error,
                        &reply,
                        "");
        assert_se(r >= 0);

        r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
        assert_se(r >= 0);

        while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
                printf("what=<%s> who=<%s> why=<%s> mode=<%s> uid=<%"PRIu32"> pid=<%"PRIu32">\n",
                       what, who, why, mode, uid, pid);

                n++;
        }
        assert_se(r >= 0);

        printf("%u inhibitors\n", n);
}
Beispiel #7
0
_public_ int sd_bus_get_property(
                sd_bus *bus,
                const char *destination,
                const char *path,
                const char *interface,
                const char *member,
                sd_bus_error *error,
                sd_bus_message **reply,
                const char *type) {

        sd_bus_message *rep = NULL;
        int r;

        assert_return(bus, -EINVAL);
        assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
        assert_return(member_name_is_valid(member), -EINVAL);
        assert_return(reply, -EINVAL);
        assert_return(signature_is_single(type, false), -EINVAL);
        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
        assert_return(!bus_pid_changed(bus), -ECHILD);

        r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member);
        if (r < 0)
                return r;

        r = sd_bus_message_enter_container(rep, 'v', type);
        if (r < 0) {
                sd_bus_message_unref(rep);
                return r;
        }

        *reply = rep;
        return 0;
}
Beispiel #8
0
static int callback(sd_bus_message *m, void *user, sd_bus_error *error)
{
	sd_event *loop = user;
	int r;
	char *property = NULL;

	r = sd_bus_message_skip(m, "s");
	if (r < 0) {
		fprintf(stderr, "Error skipping message fields: %s\n",
				strerror(-r));
		quit(r, loop);
		return r;
	}

	r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
	if (r < 0) {
		fprintf(stderr, "Error entering container: %s\n",
				strerror(-r));
		quit(r, loop);
		return r;
	}

	while((r = sd_bus_message_enter_container(
					m,
					SD_BUS_TYPE_DICT_ENTRY,
					"sv")) > 0) {
		r = sd_bus_message_read(m, "s", &property);
		if (r < 0) {
			fprintf(stderr, "Error reading message: %s\n",
					strerror(-r));
			quit(r, loop);
			return r;
		}

		if(strcmp(property, "pgood"))
			continue;

		quit(0, loop);
		break;
	}

	return 0;
}
Beispiel #9
0
static int print_inhibitors(sd_bus *bus, sd_bus_error *error) {
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        const char *what, *who, *why, *mode;
        unsigned int uid, pid;
        unsigned n = 0;
        int r;

        r = sd_bus_call_method(
                        bus,
                        "org.freedesktop.login1",
                        "/org/freedesktop/login1",
                        "org.freedesktop.login1.Manager",
                        "ListInhibitors",
                        error,
                        &reply,
                        "");
        if (r < 0)
                return r;

        r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
        if (r < 0)
                return bus_log_parse_error(r);

        while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
                _cleanup_free_ char *comm = NULL, *u = NULL;

                get_process_comm(pid, &comm);
                u = uid_to_name(uid);

                printf("     Who: %s (UID "UID_FMT"/%s, PID "PID_FMT"/%s)\n"
                       "    What: %s\n"
                       "     Why: %s\n"
                       "    Mode: %s\n\n",
                       who, uid, strna(u), pid, strna(comm),
                       what,
                       why,
                       mode);

                n++;
        }
        if (r < 0)
                return bus_log_parse_error(r);

        r = sd_bus_message_exit_container(reply);
        if (r < 0)
                return bus_log_parse_error(r);

        printf("%u inhibitors listed.\n", n);
        return 0;
}
Beispiel #10
0
_public_ int sd_bus_get_property_string(
                sd_bus *bus,
                const char *destination,
                const char *path,
                const char *interface,
                const char *member,
                sd_bus_error *error,
                char **ret) {

        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
        const char *s;
        char *n;
        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(ret, -EINVAL, error);
        bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);

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

        r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
        if (r < 0)
                return r;

        r = sd_bus_message_enter_container(reply, 'v', "s");
        if (r < 0)
                goto fail;

        r = sd_bus_message_read_basic(reply, 's', &s);
        if (r < 0)
                goto fail;

        n = strdup(s);
        if (!n) {
                r = -ENOMEM;
                goto fail;
        }

        *ret = n;
        return 0;

fail:
        return sd_bus_error_set_errno(error, r);
}
Beispiel #11
0
static void manager_read_name(struct manager *m)
{
	_cleanup_sd_bus_error_ sd_bus_error err = SD_BUS_ERROR_NULL;
	_cleanup_sd_bus_message_ sd_bus_message *rep = NULL;
	const char *name;
	char *str;
	int r;

	r = sd_bus_call_method(m->bus,
			       "org.freedesktop.hostname1",
			       "/org/freedesktop/hostname1",
			       "org.freedesktop.DBus.Properties",
			       "Get",
			       &err,
			       &rep,
			       "ss", "org.freedesktop.hostname1", "Hostname");
	if (r < 0)
		goto error;

	r = sd_bus_message_enter_container(rep, 'v', "s");
	if (r < 0)
		goto error;

	r = sd_bus_message_read(rep, "s", &name);
	if (r < 0)
		name = "undefined";

	if (shl_isempty(name)) {
		log_warning("no hostname set on systemd.hostname1, using: %s",
			    m->friendly_name);
		return;
	}

	str = strdup(name);
	if (!str)
		return log_vENOMEM();

	free(m->friendly_name);
	m->friendly_name = str;
	log_debug("friendly-name from local hostname: %s", str);

	return;

error:
	log_warning("cannot read hostname from systemd.hostname1: %s",
		    bus_error_message(&err, r));
}
Beispiel #12
0
static int list_sessions(int argc, char *argv[], void *userdata) {
        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        const char *id, *user, *seat, *object;
        sd_bus *bus = userdata;
        unsigned k = 0;
        uint32_t uid;
        int r;

        assert(bus);
        assert(argv);

        pager_open_if_enabled();

        r = sd_bus_call_method(
                        bus,
                        "org.freedesktop.login1",
                        "/org/freedesktop/login1",
                        "org.freedesktop.login1.Manager",
                        "ListSessions",
                        &error, &reply,
                        "");
        if (r < 0) {
                log_error("Failed to list sessions: %s", bus_error_message(&error, r));
                return r;
        }

        r = sd_bus_message_enter_container(reply, 'a', "(susso)");
        if (r < 0)
                return bus_log_parse_error(r);

        if (arg_legend)
                printf("%10s %10s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT");

        while ((r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object)) > 0) {
                printf("%10s %10u %-16s %-16s\n", id, (unsigned) uid, user, seat);
                k++;
        }
        if (r < 0)
                return bus_log_parse_error(r);

        if (arg_legend)
                printf("\n%u sessions listed.\n", k);

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

        assert(p);

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

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

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

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

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

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

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

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

        return 0;
}
Beispiel #14
0
static int print_changes(sd_bus_message *m) {
        int r;

        if (arg_quiet)
                return 0;

        r = sd_bus_message_enter_container(m, 'a', "(sss)");
        if (r < 0)
                return bus_log_parse_error(r);

        for (;;) {
                const char *type, *path, *source;

                r = sd_bus_message_read(m, "(sss)", &type, &path, &source);
                if (r < 0)
                        return bus_log_parse_error(r);
                if (r == 0)
                        break;

                if (streq(type, "symlink"))
                        log_info("Created symlink %s %s %s.", path, special_glyph(SPECIAL_GLYPH_ARROW), source);
                else if (streq(type, "copy")) {
                        if (isempty(source))
                                log_info("Copied %s.", path);
                        else
                                log_info("Copied %s %s %s.", source, special_glyph(SPECIAL_GLYPH_ARROW), path);
                } else if (streq(type, "unlink"))
                        log_info("Removed %s.", path);
                else if (streq(type, "write"))
                        log_info("Written %s.", path);
                else if (streq(type, "mkdir"))
                        log_info("Created directory %s.", path);
                else
                        log_error("Unexpected change: %s/%s/%s", type, path, source);
        }

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

        return 0;
}
Beispiel #15
0
static int map_ntp_message(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
        NTPStatusInfo *p = userdata;
        const void *d;
        size_t sz;
        int32_t b;
        int r;

        assert(p);

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

        r = sd_bus_message_read(m, "uuuuitt",
                                &p->leap, &p->version, &p->mode, &p->stratum, &p->precision,
                                &p->root_delay, &p->root_dispersion);
        if (r < 0)
                return r;

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

        r = sd_bus_message_read(m, "ttttbtt",
                                &p->origin, &p->recv, &p->trans, &p->dest,
                                &b, &p->packet_count, &p->jitter);
        if (r < 0)
                return r;

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

        if (sz != 4)
                return -EINVAL;

        memcpy(p->reference.str, d, sz);

        p->spike = b;

        return 0;
}
Beispiel #16
0
static int list_users(sd_bus *bus, char **args, unsigned n) {
        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        const char *user, *object;
        unsigned k = 0;
        uint32_t uid;
        int r;

        pager_open_if_enabled();

        r = sd_bus_call_method(
                        bus,
                        "org.freedesktop.login1",
                        "/org/freedesktop/login1",
                        "org.freedesktop.login1.Manager",
                        "ListUsers",
                        &error, &reply,
                        "");
        if (r < 0) {
                log_error("Failed to list users: %s", bus_error_message(&error, r));
                return r;
        }

        r = sd_bus_message_enter_container(reply, 'a', "(uso)");
        if (r < 0)
                return bus_log_parse_error(r);

        if (arg_legend)
                printf("%10s %-16s\n", "UID", "USER");

        while ((r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object)) > 0) {
                printf("%10u %-16s\n", (unsigned) uid, user);
                k++;
        }
        if (r < 0)
                return bus_log_parse_error(r);

        if (arg_legend)
                printf("\n%u users listed.\n", k);

        return 0;
}
Beispiel #17
0
static int list_seats(sd_bus *bus, char **args, unsigned n) {
        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        const char *seat, *object;
        unsigned k = 0;
        int r;

        pager_open_if_enabled();

        r = sd_bus_call_method(
                        bus,
                        "org.freedesktop.login1",
                        "/org/freedesktop/login1",
                        "org.freedesktop.login1.Manager",
                        "ListSeats",
                        &error, &reply,
                        "");
        if (r < 0) {
                log_error("Failed to list seats: %s", bus_error_message(&error, r));
                return r;
        }

        r = sd_bus_message_enter_container(reply, 'a', "(so)");
        if (r < 0)
                return bus_log_parse_error(r);

        if (arg_legend)
                printf("%-16s\n", "SEAT");

        while ((r = sd_bus_message_read(reply, "(so)", &seat, &object)) > 0) {
                printf("%-16s\n", seat);
                k++;
        }
        if (r < 0)
                return bus_log_parse_error(r);

        if (arg_legend)
                printf("\n%u seats listed.\n", k);

        return 0;
}
Beispiel #18
0
static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
        const char *contents;
        int r;

        r = sd_bus_message_peek_type(m, NULL, &contents);
        if (r < 0)
                return r;

        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, contents);
        if (r < 0)
                return r;

        if (contents[0] == 's' || contents[0] == 'o') {
                const char *s;
                char **p = (char **) userdata;

                r = sd_bus_message_read_basic(m, contents[0], &s);
                if (r < 0)
                        return r;

                free(*p);
                *p = strdup(s);

                if (!*p)
                        return -ENOMEM;
        } else {
                r = sd_bus_message_read_basic(m, contents[0], userdata);
                if (r < 0)
                        return r;
        }

        r = sd_bus_message_skip(m, contents+1);
        if (r < 0)
                return r;

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

        return 0;
}
Beispiel #19
0
static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
        const char *name;
        int r;

        assert(bus);
        assert(m);

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

        while ((r = sd_bus_message_read(m, "(so)", &name, NULL)) > 0) {
                r = strv_extend(userdata, name);
                if (r < 0)
                        return r;
        }
        if (r < 0)
                return r;

        return sd_bus_message_exit_container(m);
}
Beispiel #20
0
static int resolve_host(sd_bus *bus, const char *name) {

        _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        const char *canonical = NULL;
        char ifname[IF_NAMESIZE] = "";
        unsigned c = 0;
        int r;
        uint64_t flags;
        usec_t ts;

        assert(name);

        if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
                return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);

        log_debug("Resolving %s (family %s, interface %s).", name, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);

        r = sd_bus_message_new_method_call(
                        bus,
                        &req,
                        "org.freedesktop.resolve1",
                        "/org/freedesktop/resolve1",
                        "org.freedesktop.resolve1.Manager",
                        "ResolveHostname");
        if (r < 0)
                return bus_log_create_error(r);

        r = sd_bus_message_append(req, "isit", arg_ifindex, name, arg_family, arg_flags);
        if (r < 0)
                return bus_log_create_error(r);

        ts = now(CLOCK_MONOTONIC);

        r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
        if (r < 0) {
                log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r));
                return r;
        }

        ts = now(CLOCK_MONOTONIC) - ts;

        r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
        if (r < 0)
                return bus_log_parse_error(r);

        while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
                const void *a;
                size_t sz;
                _cleanup_free_ char *pretty = NULL;
                int ifindex, family;

                assert_cc(sizeof(int) == sizeof(int32_t));

                r = sd_bus_message_read(reply, "ii", &ifindex, &family);
                if (r < 0)
                        return bus_log_parse_error(r);

                r = sd_bus_message_read_array(reply, 'y', &a, &sz);
                if (r < 0)
                        return bus_log_parse_error(r);

                r = sd_bus_message_exit_container(reply);
                if (r < 0)
                        return bus_log_parse_error(r);

                if (!IN_SET(family, AF_INET, AF_INET6)) {
                        log_debug("%s: skipping entry with family %d (%s)", name, family, af_to_name(family) ?: "unknown");
                        continue;
                }

                if (sz != FAMILY_ADDRESS_SIZE(family)) {
                        log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name, sz, af_to_name(family) ?: "unknown");
                        continue;
                }
Beispiel #21
0
int bus_message_map_all_properties(sd_bus *bus,
                                   sd_bus_message *m,
                                   const struct bus_properties_map *map,
                                   void *userdata) {
        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        int r;

        assert(bus);
        assert(m);
        assert(map);

        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
        if (r < 0)
                return r;

        while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
                const struct bus_properties_map *prop;
                const char *member;
                const char *contents;
                void *v;
                unsigned i;

                r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
                if (r < 0)
                        return r;

                for (i = 0, prop = NULL; map[i].member; i++)
                        if (streq(map[i].member, member)) {
                                prop = &map[i];
                                break;
                        }

                if (prop) {
                        r = sd_bus_message_peek_type(m, NULL, &contents);
                        if (r < 0)
                                return r;

                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
                        if (r < 0)
                                return r;

                        v = (uint8_t *)userdata + prop->offset;
                        if (map[i].set)
                                r = prop->set(bus, member, m, &error, v);
                        else
                                r = map_basic(bus, member, m, &error, v);
                        if (r < 0)
                                return r;

                        r = sd_bus_message_exit_container(m);
                        if (r < 0)
                                return r;
                } else {
                        r = sd_bus_message_skip(m, "v");
                        if (r < 0)
                                return r;
                }

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

        return sd_bus_message_exit_container(m);
}
Beispiel #22
0
int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        int r;

        assert(bus);
        assert(path);

        r = sd_bus_call_method(bus,
                        dest,
                        path,
                        "org.freedesktop.DBus.Properties",
                        "GetAll",
                        &error,
                        &reply,
                        "s", "");
        if (r < 0)
                return r;

        r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
        if (r < 0)
                return r;

        while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
                const char *name;
                const char *contents;

                r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
                if (r < 0)
                        return r;

                if (!filter || strv_find(filter, name)) {
                        r = sd_bus_message_peek_type(reply, NULL, &contents);
                        if (r < 0)
                                return r;

                        r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
                        if (r < 0)
                                return r;

                        r = bus_print_property(name, reply, all);
                        if (r < 0)
                                return r;
                        if (r == 0) {
                                if (all)
                                        printf("%s=[unprintable]\n", name);
                                /* skip what we didn't read */
                                r = sd_bus_message_skip(reply, contents);
                                if (r < 0)
                                        return r;
                        }

                        r = sd_bus_message_exit_container(reply);
                        if (r < 0)
                                return r;
                } else {
                        r = sd_bus_message_skip(reply, "v");
                        if (r < 0)
                                return r;
                }

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

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

        return 0;
}
Beispiel #23
0
int bus_print_property(const char *name, sd_bus_message *property, bool all) {
        char type;
        const char *contents;
        int r;

        assert(name);
        assert(property);

        r = sd_bus_message_peek_type(property, &type, &contents);
        if (r < 0)
                return r;

        switch (type) {

        case SD_BUS_TYPE_STRING: {
                const char *s;

                r = sd_bus_message_read_basic(property, type, &s);
                if (r < 0)
                        return r;

                if (all || !isempty(s))
                        printf("%s=%s\n", name, s);

                return 1;
        }

        case SD_BUS_TYPE_BOOLEAN: {
                bool b;

                r = sd_bus_message_read_basic(property, type, &b);
                if (r < 0)
                        return r;

                printf("%s=%s\n", name, yes_no(b));

                return 1;
        }

        case SD_BUS_TYPE_UINT64: {
                uint64_t u;

                r = sd_bus_message_read_basic(property, type, &u);
                if (r < 0)
                        return r;

                /* Yes, heuristics! But we can change this check
                 * should it turn out to not be sufficient */

                if (endswith(name, "Timestamp")) {
                        char timestamp[FORMAT_TIMESTAMP_MAX], *t;

                        t = format_timestamp(timestamp, sizeof(timestamp), u);
                        if (t || all)
                                printf("%s=%s\n", name, strempty(t));

                } else if (strstr(name, "USec")) {
                        char timespan[FORMAT_TIMESPAN_MAX];

                        printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
                } else
                        printf("%s=%llu\n", name, (unsigned long long) u);

                return 1;
        }

        case SD_BUS_TYPE_UINT32: {
                uint32_t u;

                r = sd_bus_message_read_basic(property, type, &u);
                if (r < 0)
                        return r;

                if (strstr(name, "UMask") || strstr(name, "Mode"))
                        printf("%s=%04o\n", name, u);
                else
                        printf("%s=%u\n", name, (unsigned) u);

                return 1;
        }

        case SD_BUS_TYPE_INT32: {
                int32_t i;

                r = sd_bus_message_read_basic(property, type, &i);
                if (r < 0)
                        return r;

                printf("%s=%i\n", name, (int) i);
                return 1;
        }

        case SD_BUS_TYPE_DOUBLE: {
                double d;

                r = sd_bus_message_read_basic(property, type, &d);
                if (r < 0)
                        return r;

                printf("%s=%g\n", name, d);
                return 1;
        }

        case SD_BUS_TYPE_ARRAY:
                if (streq(contents, "s")) {
                        bool first = true;
                        const char *str;

                        r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
                        if (r < 0)
                                return r;

                        while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
                                if (first)
                                        printf("%s=", name);

                                printf("%s%s", first ? "" : " ", str);

                                first = false;
                        }
                        if (r < 0)
                                return r;

                        if (first && all)
                                printf("%s=", name);
                        if (!first || all)
                                puts("");

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

                        return 1;

                } else if (streq(contents, "y")) {
                        const uint8_t *u;
                        size_t n;

                        r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
                        if (r < 0)
                                return r;

                        if (all || n > 0) {
                                unsigned int i;

                                printf("%s=", name);

                                for (i = 0; i < n; i++)
                                        printf("%02x", u[i]);

                                puts("");
                        }

                        return 1;

                } else if (streq(contents, "u")) {
                        uint32_t *u;
                        size_t n;

                        r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
                        if (r < 0)
                                return r;

                        if (all || n > 0) {
                                unsigned int i;

                                printf("%s=", name);

                                for (i = 0; i < n; i++)
                                        printf("%08x", u[i]);

                                puts("");
                        }

                        return 1;
                }

                break;
        }

        return 0;
}
Beispiel #24
0
int bus_verify_polkit_async(
                sd_bus_message *call,
                int capability,
                const char *action,
                bool interactive,
                Hashmap **registry,
                sd_bus_error *error) {

#ifdef ENABLE_POLKIT
        _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
        AsyncPolkitQuery *q;
        const char *sender;
        sd_bus_message_handler_t callback;
        void *userdata;
#endif
        int r;

        assert(call);
        assert(action);
        assert(registry);

#ifdef ENABLE_POLKIT
        q = hashmap_get(*registry, call);
        if (q) {
                int authorized, challenge;

                /* This is the second invocation of this function, and
                 * there's already a response from polkit, let's
                 * process it */
                assert(q->reply);

                if (sd_bus_message_is_method_error(q->reply, NULL)) {
                        const sd_bus_error *e;

                        /* Copy error from polkit reply */
                        e = sd_bus_message_get_error(q->reply);
                        sd_bus_error_copy(error, e);

                        /* Treat no PK available as access denied */
                        if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
                                return -EACCES;

                        return -sd_bus_error_get_errno(e);
                }

                r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
                if (r >= 0)
                        r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);

                if (r < 0)
                        return r;

                if (authorized)
                        return 1;

                return -EACCES;
        }
#endif

        r = sd_bus_query_sender_privilege(call, capability);
        if (r < 0)
                return r;
        else if (r > 0)
                return 1;

#ifdef ENABLE_POLKIT
        if (sd_bus_get_current_message(call->bus) != call)
                return -EINVAL;

        callback = sd_bus_get_current_handler(call->bus);
        if (!callback)
                return -EINVAL;

        userdata = sd_bus_get_current_userdata(call->bus);

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

        r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func);
        if (r < 0)
                return r;

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

        r = sd_bus_message_append(
                        pk,
                        "(sa{sv})sa{ss}us",
                        "system-bus-name", 1, "name", "s", sender,
                        action,
                        0,
                        interactive ? 1 : 0,
                        NULL);
        if (r < 0)
                return r;

        q = new0(AsyncPolkitQuery, 1);
        if (!q)
                return -ENOMEM;

        q->request = sd_bus_message_ref(call);
        q->callback = callback;
        q->userdata = userdata;

        r = hashmap_put(*registry, call, q);
        if (r < 0) {
                async_polkit_query_free(q);
                return r;
        }

        q->registry = *registry;

        r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
        if (r < 0) {
                async_polkit_query_free(q);
                return r;
        }

        return 0;
#endif

        return -EACCES;
}
Beispiel #25
0
int bus_verify_polkit(
                sd_bus_message *call,
                int capability,
                const char *action,
                bool interactive,
                bool *_challenge,
                sd_bus_error *e) {

        int r;

        assert(call);
        assert(action);

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

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

                r = sd_bus_call_method(
                                call->bus,
                                "org.freedesktop.PolicyKit1",
                                "/org/freedesktop/PolicyKit1/Authority",
                                "org.freedesktop.PolicyKit1.Authority",
                                "CheckAuthorization",
                                e,
                                &reply,
                                "(sa{sv})sa{ss}us",
                                "system-bus-name", 1, "name", "s", sender,
                                action,
                                0,
                                interactive ? 1 : 0,
                                "");

                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;
                }
        }
#endif

        return -EACCES;
}
Beispiel #26
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;
                }
        }
Beispiel #27
0
enum nss_status _nss_resolve_gethostbyaddr2_r(
                const void* addr, socklen_t len,
                int af,
                struct hostent *result,
                char *buffer, size_t buflen,
                int *errnop, int *h_errnop,
                int32_t *ttlp) {

        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        char *r_name, *r_aliases, *r_addr, *r_addr_list;
        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
        unsigned c = 0, i = 0;
        size_t ms = 0, idx;
        const char *n;
        int r, ifindex;

        assert(addr);
        assert(result);
        assert(buffer);
        assert(errnop);
        assert(h_errnop);

        if (!IN_SET(af, AF_INET, AF_INET6)) {
                *errnop = EAFNOSUPPORT;
                *h_errnop = NO_DATA;
                return NSS_STATUS_UNAVAIL;
        }

        if (len != FAMILY_ADDRESS_SIZE(af)) {
                *errnop = EINVAL;
                *h_errnop = NO_RECOVERY;
                return NSS_STATUS_UNAVAIL;
        }

        r = sd_bus_open_system(&bus);
        if (r < 0)
                goto fail;

        r = sd_bus_message_new_method_call(
                        bus,
                        &req,
                        "org.freedesktop.resolve1",
                        "/org/freedesktop/resolve1",
                        "org.freedesktop.resolve1.Manager",
                        "ResolveAddress");
        if (r < 0)
                goto fail;

        r = sd_bus_message_set_auto_start(req, false);
        if (r < 0)
                goto fail;

        r = sd_bus_message_append(req, "ii", 0, af);
        if (r < 0)
                goto fail;

        r = sd_bus_message_append_array(req, 'y', addr, len);
        if (r < 0)
                goto fail;

        r = sd_bus_message_append(req, "t", (uint64_t) 0);
        if (r < 0)
                goto fail;

        r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
        if (r < 0) {
                if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) {
                        *errnop = ESRCH;
                        *h_errnop = HOST_NOT_FOUND;
                        return NSS_STATUS_NOTFOUND;
                }

                if (bus_error_shall_fallback(&error)) {

                        enum nss_status (*fallback)(
                                        const void* addr, socklen_t len,
                                        int af,
                                        struct hostent *result,
                                        char *buffer, size_t buflen,
                                        int *errnop, int *h_errnop,
                                        int32_t *ttlp);

                        fallback = (enum nss_status (*)(
                                        const void* addr, socklen_t len,
                                        int af,
                                        struct hostent *result,
                                        char *buffer, size_t buflen,
                                        int *errnop, int *h_errnop,
                                        int32_t *ttlp))
                                find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyaddr2_r");

                        if (fallback)
                                return fallback(addr, len, af, result, buffer, buflen, errnop, h_errnop, ttlp);
                }

                *errnop = -r;
                *h_errnop = NO_RECOVERY;
                return NSS_STATUS_UNAVAIL;
        }

        r = sd_bus_message_enter_container(reply, 'a', "(is)");
        if (r < 0)
                goto fail;

        while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) {

                if (ifindex < 0) {
                        r = -EINVAL;
                        goto fail;
                }

                c++;
                ms += ALIGN(strlen(n) + 1);
        }
        if (r < 0)
                goto fail;

        r = sd_bus_message_rewind(reply, false);
        if (r < 0)
                return r;

        if (c <= 0) {
                *errnop = ESRCH;
                *h_errnop = HOST_NOT_FOUND;
                return NSS_STATUS_NOTFOUND;
        }

        ms += ALIGN(len) +              /* the address */
              2 * sizeof(char*) +       /* pointers to the address, plus trailing NULL */
              c * sizeof(char*);        /* pointers to aliases, plus trailing NULL */

        if (buflen < ms) {
                *errnop = ENOMEM;
                *h_errnop = TRY_AGAIN;
                return NSS_STATUS_TRYAGAIN;
        }

        /* First, place address */
        r_addr = buffer;
        memcpy(r_addr, addr, len);
        idx = ALIGN(len);

        /* Second, place address list */
        r_addr_list = buffer + idx;
        ((char**) r_addr_list)[0] = r_addr;
        ((char**) r_addr_list)[1] = NULL;
        idx += sizeof(char*) * 2;

        /* Third, reserve space for the aliases array */
        r_aliases = buffer + idx;
        idx += sizeof(char*) * c;

        /* Fourth, place aliases */
        i = 0;
        r_name = buffer + idx;
        while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) {
                char *p;
                size_t l;

                l = strlen(n);
                p = buffer + idx;
                memcpy(p, n, l+1);

                if (i > 1)
                        ((char**) r_aliases)[i-1] = p;
                i++;

                idx += ALIGN(l+1);
        }
        if (r < 0)
                goto fail;

        ((char**) r_aliases)[c-1] = NULL;
        assert(idx == ms);

        result->h_name = r_name;
        result->h_aliases = (char**) r_aliases;
        result->h_addrtype = af;
        result->h_length = len;
        result->h_addr_list = (char**) r_addr_list;

        if (ttlp)
                *ttlp = 0;

        /* Explicitly reset all error variables */
        *errnop = 0;
        *h_errnop = NETDB_SUCCESS;
        h_errno = 0;

        return NSS_STATUS_SUCCESS;

fail:
        *errnop = -r;
        *h_errnop = NO_DATA;
        return NSS_STATUS_UNAVAIL;
}
Beispiel #28
0
enum nss_status _nss_resolve_gethostbyname3_r(
                const char *name,
                int af,
                struct hostent *result,
                char *buffer, size_t buflen,
                int *errnop, int *h_errnop,
                int32_t *ttlp,
                char **canonp) {

        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        char *r_name, *r_aliases, *r_addr, *r_addr_list;
        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
        size_t l, idx, ms, alen;
        const char *canonical;
        int c, r, i = 0;

        assert(name);
        assert(result);
        assert(buffer);
        assert(errnop);
        assert(h_errnop);

        if (af == AF_UNSPEC)
                af = AF_INET;

        if (af != AF_INET && af != AF_INET6) {
                r = -EAFNOSUPPORT;
                goto fail;
        }

        r = sd_bus_open_system(&bus);
        if (r < 0)
                goto fail;

        r = sd_bus_message_new_method_call(
                        bus,
                        &req,
                        "org.freedesktop.resolve1",
                        "/org/freedesktop/resolve1",
                        "org.freedesktop.resolve1.Manager",
                        "ResolveHostname");
        if (r < 0)
                goto fail;

        r = sd_bus_message_set_auto_start(req, false);
        if (r < 0)
                goto fail;

        r = sd_bus_message_append(req, "isit", 0, name, af, (uint64_t) 0);
        if (r < 0)
                goto fail;

        r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
        if (r < 0) {
                if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) {
                        *errnop = ESRCH;
                        *h_errnop = HOST_NOT_FOUND;
                        return NSS_STATUS_NOTFOUND;
                }

                if (bus_error_shall_fallback(&error)) {

                        enum nss_status (*fallback)(
                                        const char *name,
                                        int af,
                                        struct hostent *result,
                                        char *buffer, size_t buflen,
                                        int *errnop, int *h_errnop,
                                        int32_t *ttlp,
                                        char **canonp);

                        fallback = (enum nss_status (*)(const char *name,
                                                        int af,
                                                        struct hostent *result,
                                                        char *buffer, size_t buflen,
                                                        int *errnop, int *h_errnop,
                                                        int32_t *ttlp,
                                                        char **canonp))
                                find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname3_r");
                        if (fallback)
                                return fallback(name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp);
                }

                *errnop = -r;
                *h_errnop = NO_RECOVERY;
                return NSS_STATUS_UNAVAIL;
        }

        c = count_addresses(reply, af, &canonical);
        if (c < 0) {
                r = c;
                goto fail;
        }
        if (c == 0) {
                *errnop = ESRCH;
                *h_errnop = HOST_NOT_FOUND;
                return NSS_STATUS_NOTFOUND;
        }

        if (isempty(canonical))
                canonical = name;

        alen = FAMILY_ADDRESS_SIZE(af);
        l = strlen(canonical);

        ms = ALIGN(l+1) + c * ALIGN(alen) + (c+2) * sizeof(char*);

        if (buflen < ms) {
                *errnop = ENOMEM;
                *h_errnop = TRY_AGAIN;
                return NSS_STATUS_TRYAGAIN;
        }

        /* First, append name */
        r_name = buffer;
        memcpy(r_name, canonical, l+1);
        idx = ALIGN(l+1);

        /* Second, create empty aliases array */
        r_aliases = buffer + idx;
        ((char**) r_aliases)[0] = NULL;
        idx += sizeof(char*);

        /* Third, append addresses */
        r_addr = buffer + idx;

        r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
        if (r < 0)
                goto fail;

        while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
                int ifindex, family;
                const void *a;
                size_t sz;

                r = sd_bus_message_read(reply, "ii", &ifindex, &family);
                if (r < 0)
                        goto fail;

                if (ifindex < 0) {
                        r = -EINVAL;
                        goto fail;
                }

                r = sd_bus_message_read_array(reply, 'y', &a, &sz);
                if (r < 0)
                        goto fail;

                r = sd_bus_message_exit_container(reply);
                if (r < 0)
                        goto fail;

                if (family != af)
                        continue;

                if (sz != alen) {
                        r = -EINVAL;
                        goto fail;
                }

                memcpy(r_addr + i*ALIGN(alen), a, alen);
                i++;
        }
        if (r < 0)
                goto fail;

        assert(i == c);
        idx += c * ALIGN(alen);

        /* Fourth, append address pointer array */
        r_addr_list = buffer + idx;
        for (i = 0; i < c; i++)
                ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen);

        ((char**) r_addr_list)[i] = NULL;
        idx += (c+1) * sizeof(char*);

        assert(idx == ms);

        result->h_name = r_name;
        result->h_aliases = (char**) r_aliases;
        result->h_addrtype = af;
        result->h_length = alen;
        result->h_addr_list = (char**) r_addr_list;

        /* Explicitly reset all error variables */
        *errnop = 0;
        *h_errnop = NETDB_SUCCESS;
        h_errno = 0;

        if (ttlp)
                *ttlp = 0;

        if (canonp)
                *canonp = r_name;

        return NSS_STATUS_SUCCESS;

fail:
        *errnop = -r;
        *h_errnop = NO_DATA;
        return NSS_STATUS_UNAVAIL;
}
Beispiel #29
0
enum nss_status _nss_resolve_gethostbyname4_r(
                const char *name,
                struct gaih_addrtuple **pat,
                char *buffer, size_t buflen,
                int *errnop, int *h_errnop,
                int32_t *ttlp) {

        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL;
        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
        const char *canonical = NULL;
        size_t l, ms, idx;
        char *r_name;
        int c, r, i = 0;

        assert(name);
        assert(pat);
        assert(buffer);
        assert(errnop);
        assert(h_errnop);

        r = sd_bus_open_system(&bus);
        if (r < 0)
                goto fail;

        r = sd_bus_message_new_method_call(
                        bus,
                        &req,
                        "org.freedesktop.resolve1",
                        "/org/freedesktop/resolve1",
                        "org.freedesktop.resolve1.Manager",
                        "ResolveHostname");
        if (r < 0)
                goto fail;

        r = sd_bus_message_set_auto_start(req, false);
        if (r < 0)
                goto fail;

        r = sd_bus_message_append(req, "isit", 0, name, AF_UNSPEC, (uint64_t) 0);
        if (r < 0)
                goto fail;

        r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
        if (r < 0) {
                if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) {
                        *errnop = ESRCH;
                        *h_errnop = HOST_NOT_FOUND;
                        return NSS_STATUS_NOTFOUND;
                }

                if (bus_error_shall_fallback(&error)) {

                        enum nss_status (*fallback)(
                                        const char *name,
                                        struct gaih_addrtuple **pat,
                                        char *buffer, size_t buflen,
                                        int *errnop, int *h_errnop,
                                        int32_t *ttlp);

                        fallback = (enum nss_status (*)(const char *name,
                                                        struct gaih_addrtuple **pat,
                                                        char *buffer, size_t buflen,
                                                        int *errnop, int *h_errnop,
                                                        int32_t *ttlp))
                                find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname4_r");
                        if (fallback)
                                return fallback(name, pat, buffer, buflen, errnop, h_errnop, ttlp);
                }

                *errnop = -r;
                *h_errnop = NO_RECOVERY;
                return NSS_STATUS_UNAVAIL;
        }

        c = count_addresses(reply, AF_UNSPEC, &canonical);
        if (c < 0) {
                r = c;
                goto fail;
        }
        if (c == 0) {
                *errnop = ESRCH;
                *h_errnop = HOST_NOT_FOUND;
                return NSS_STATUS_NOTFOUND;
        }

        if (isempty(canonical))
                canonical = name;

        l = strlen(canonical);
        ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c;
        if (buflen < ms) {
                *errnop = ENOMEM;
                *h_errnop = TRY_AGAIN;
                return NSS_STATUS_TRYAGAIN;
        }

        /* First, append name */
        r_name = buffer;
        memcpy(r_name, canonical, l+1);
        idx = ALIGN(l+1);

        /* Second, append addresses */
        r_tuple_first = (struct gaih_addrtuple*) (buffer + idx);

        r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
        if (r < 0)
                goto fail;

        while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
                int family, ifindex;
                const void *a;
                size_t sz;

                assert_cc(sizeof(int32_t) == sizeof(int));

                r = sd_bus_message_read(reply, "ii", &ifindex, &family);
                if (r < 0)
                        goto fail;

                if (ifindex < 0) {
                        r = -EINVAL;
                        goto fail;
                }

                r = sd_bus_message_read_array(reply, 'y', &a, &sz);
                if (r < 0)
                        goto fail;

                r = sd_bus_message_exit_container(reply);
                if (r < 0)
                        goto fail;

                if (!IN_SET(family, AF_INET, AF_INET6))
                        continue;

                if (sz != FAMILY_ADDRESS_SIZE(family)) {
                        r = -EINVAL;
                        goto fail;
                }

                r_tuple = (struct gaih_addrtuple*) (buffer + idx);
                r_tuple->next = i == c-1 ? NULL : (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple)));
                r_tuple->name = r_name;
                r_tuple->family = family;
                r_tuple->scopeid = ifindex;
                memcpy(r_tuple->addr, a, sz);

                idx += ALIGN(sizeof(struct gaih_addrtuple));
                i++;
        }
        if (r < 0)
                goto fail;

        assert(i == c);
        assert(idx == ms);

        if (*pat)
                **pat = *r_tuple_first;
        else
                *pat = r_tuple_first;

        if (ttlp)
                *ttlp = 0;

        /* Explicitly reset all error variables */
        *errnop = 0;
        *h_errnop = NETDB_SUCCESS;
        h_errno = 0;

        return NSS_STATUS_SUCCESS;

fail:
        *errnop = -r;
        *h_errnop = NO_DATA;
        return NSS_STATUS_UNAVAIL;
}
Beispiel #30
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;
}