static int resolve_host(sd_bus *bus, const char *name) { _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; 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) return log_error_errno(r, "%s: resolve call failed: %s", name, bus_error_message(&error, 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) { _cleanup_free_ char *pretty = NULL; int ifindex, family; const void *a; size_t sz; 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"); return -EINVAL; }
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; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); assert(pat); assert(buffer); assert(errnop); assert(h_errnop); r = sd_bus_open_system(&bus); if (r < 0) goto fallback; 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)) goto fallback; goto fail; } 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; fallback: { _nss_gethostbyname4_r_t fallback; fallback = (_nss_gethostbyname4_r_t) find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname4_r"); if (fallback) return fallback(name, pat, buffer, buflen, errnop, h_errnop, ttlp); } fail: *errnop = -r; *h_errnop = NO_RECOVERY; return NSS_STATUS_UNAVAIL; }
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; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); 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 fallback; 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)) goto fallback; goto fail; } 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; fallback: { _nss_gethostbyname3_r_t fallback; fallback = (_nss_gethostbyname3_r_t) find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname3_r"); if (fallback) return fallback(name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp); } fail: *errnop = -r; *h_errnop = NO_RECOVERY; return NSS_STATUS_UNAVAIL; }
int main(int argc, char *argv[]) { _cleanup_bus_message_unref_ 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_bus_unref_ 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, "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); } #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, "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, ©, "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}"); 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(); return 0; }