1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
31 #include "in-addr-util.h"
33 NSS_GETHOSTBYNAME_PROTOTYPES(mymachines);
35 static int count_addresses(sd_bus_message *m, int af, unsigned *ret) {
42 while ((r = sd_bus_message_enter_container(m, 'r', "iay")) > 0) {
45 r = sd_bus_message_read(m, "i", &family);
49 r = sd_bus_message_skip(m, "ay");
53 r = sd_bus_message_exit_container(m);
57 if (af != AF_UNSPEC && family != af)
65 r = sd_bus_message_rewind(m, false);
73 enum nss_status _nss_mymachines_gethostbyname4_r(
75 struct gaih_addrtuple **pat,
76 char *buffer, size_t buflen,
77 int *errnop, int *h_errnop,
80 struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL;
81 _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
82 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
83 _cleanup_free_ int *ifindices = NULL;
84 _cleanup_free_ char *class = NULL;
86 unsigned i = 0, c = 0;
96 r = sd_machine_get_class(name, &class);
99 if (!streq(class, "container")) {
104 n_ifindices = sd_machine_get_ifindices(name, &ifindices);
105 if (n_ifindices < 0) {
110 r = sd_bus_open_system(&bus);
114 r = sd_bus_call_method(bus,
115 "org.freedesktop.machine1",
116 "/org/freedesktop/machine1",
117 "org.freedesktop.machine1.Manager",
118 "GetMachineAddresses",
125 r = sd_bus_message_enter_container(reply, 'a', "(iay)");
129 r = count_addresses(reply, AF_UNSPEC, &c);
135 *h_errnop = HOST_NOT_FOUND;
136 return NSS_STATUS_NOTFOUND;
140 ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c;
143 *h_errnop = TRY_AGAIN;
144 return NSS_STATUS_TRYAGAIN;
147 /* First, append name */
149 memcpy(r_name, name, l+1);
152 /* Second, append addresses */
153 r_tuple_first = (struct gaih_addrtuple*) (buffer + idx);
154 while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
159 r = sd_bus_message_read(reply, "i", &family);
163 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
167 r = sd_bus_message_exit_container(reply);
171 if (!IN_SET(family, AF_INET, AF_INET6)) {
176 if (sz != FAMILY_ADDRESS_SIZE(family)) {
181 r_tuple = (struct gaih_addrtuple*) (buffer + idx);
182 r_tuple->next = i == c-1 ? NULL : (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple)));
183 r_tuple->name = r_name;
184 r_tuple->family = family;
185 r_tuple->scopeid = n_ifindices == 1 ? ifindices[0] : 0;
186 memcpy(r_tuple->addr, a, sz);
188 idx += ALIGN(sizeof(struct gaih_addrtuple));
194 r = sd_bus_message_exit_container(reply);
201 **pat = *r_tuple_first;
203 *pat = r_tuple_first;
208 /* Explicitly reset all error variables */
210 *h_errnop = NETDB_SUCCESS;
213 return NSS_STATUS_SUCCESS;
218 return NSS_STATUS_UNAVAIL;
221 enum nss_status _nss_mymachines_gethostbyname3_r(
224 struct hostent *result,
225 char *buffer, size_t buflen,
226 int *errnop, int *h_errnop,
230 _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
231 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
232 _cleanup_free_ char *class = NULL;
233 unsigned c = 0, i = 0;
234 char *r_name, *r_aliases, *r_addr, *r_addr_list;
235 size_t l, idx, ms, alen;
247 if (af != AF_INET && af != AF_INET6) {
252 r = sd_machine_get_class(name, &class);
255 if (!streq(class, "container")) {
260 r = sd_bus_open_system(&bus);
264 r = sd_bus_call_method(bus,
265 "org.freedesktop.machine1",
266 "/org/freedesktop/machine1",
267 "org.freedesktop.machine1.Manager",
268 "GetMachineAddresses",
275 r = sd_bus_message_enter_container(reply, 'a', "(iay)");
279 r = count_addresses(reply, af, &c);
285 *h_errnop = HOST_NOT_FOUND;
286 return NSS_STATUS_NOTFOUND;
289 alen = FAMILY_ADDRESS_SIZE(af);
294 (c > 0 ? c : 1) * ALIGN(alen) +
295 (c > 0 ? c+1 : 2) * sizeof(char*);
299 *h_errnop = NO_RECOVERY;
300 return NSS_STATUS_TRYAGAIN;
303 /* First, append name */
305 memcpy(r_name, name, l+1);
308 /* Second, create aliases array */
309 r_aliases = buffer + idx;
310 ((char**) r_aliases)[0] = NULL;
311 idx += sizeof(char*);
313 /* Third, append addresses */
314 r_addr = buffer + idx;
315 while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
320 r = sd_bus_message_read(reply, "i", &family);
324 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
328 r = sd_bus_message_exit_container(reply);
340 memcpy(r_addr + i*ALIGN(alen), a, alen);
345 idx += c * ALIGN(alen);
347 r = sd_bus_message_exit_container(reply);
351 /* Third, append address pointer array */
352 r_addr_list = buffer + idx;
353 for (i = 0; i < c; i++)
354 ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen);
356 ((char**) r_addr_list)[i] = NULL;
357 idx += (c+1) * sizeof(char*);
361 result->h_name = r_name;
362 result->h_aliases = (char**) r_aliases;
363 result->h_addrtype = af;
364 result->h_length = alen;
365 result->h_addr_list = (char**) r_addr_list;
373 /* Explicitly reset all error variables */
375 *h_errnop = NETDB_SUCCESS;
378 return NSS_STATUS_SUCCESS;
383 return NSS_STATUS_UNAVAIL;
386 NSS_GETHOSTBYNAME_FALLBACKS(mymachines)