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, unsigned af, unsigned *ret) {
42 while ((r = sd_bus_message_enter_container(m, 'r', "yay")) > 0) {
45 r = sd_bus_message_read(m, "y", &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_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', "(yay)");
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', "yay")) > 0) {
155 unsigned char family;
159 r = sd_bus_message_read(reply, "y", &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 != PROTO_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 return NSS_STATUS_SUCCESS;
213 return NSS_STATUS_UNAVAIL;
216 enum nss_status _nss_mymachines_gethostbyname3_r(
219 struct hostent *result,
220 char *buffer, size_t buflen,
221 int *errnop, int *h_errnop,
225 _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
226 _cleanup_bus_unref_ sd_bus *bus = NULL;
227 _cleanup_free_ char *class = NULL;
228 unsigned c = 0, i = 0;
229 char *r_name, *r_aliases, *r_addr, *r_addr_list;
230 size_t l, idx, ms, alen;
242 if (af != AF_INET && af != AF_INET6) {
247 r = sd_machine_get_class(name, &class);
250 if (!streq(class, "container")) {
255 r = sd_bus_open_system(&bus);
259 r = sd_bus_call_method(bus,
260 "org.freedesktop.machine1",
261 "/org/freedesktop/machine1",
262 "org.freedesktop.machine1.Manager",
263 "GetMachineAddresses",
270 r = sd_bus_message_enter_container(reply, 'a', "(yay)");
274 r = count_addresses(reply, af, &c);
280 *h_errnop = HOST_NOT_FOUND;
281 return NSS_STATUS_NOTFOUND;
284 alen = PROTO_ADDRESS_SIZE(af);
289 (c > 0 ? c : 1) * ALIGN(alen) +
290 (c > 0 ? c+1 : 2) * sizeof(char*);
294 *h_errnop = NO_RECOVERY;
295 return NSS_STATUS_TRYAGAIN;
298 /* First, append name */
300 memcpy(r_name, name, l+1);
303 /* Second, create aliases array */
304 r_aliases = buffer + idx;
305 ((char**) r_aliases)[0] = NULL;
306 idx += sizeof(char*);
308 /* Third, append addresses */
309 r_addr = buffer + idx;
310 while ((r = sd_bus_message_enter_container(reply, 'r', "yay")) > 0) {
311 unsigned char family;
315 r = sd_bus_message_read(reply, "y", &family);
319 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
323 r = sd_bus_message_exit_container(reply);
335 memcpy(r_addr + i*ALIGN(alen), a, alen);
340 idx += c * ALIGN(alen);
342 r = sd_bus_message_exit_container(reply);
346 /* Third, append address pointer array */
347 r_addr_list = buffer + idx;
348 for (i = 0; i < c; i++)
349 ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen);
351 ((char**) r_addr_list)[i] = NULL;
352 idx += (c+1) * sizeof(char*);
356 result->h_name = r_name;
357 result->h_aliases = (char**) r_aliases;
358 result->h_addrtype = af;
359 result->h_length = alen;
360 result->h_addr_list = (char**) r_addr_list;
368 return NSS_STATUS_SUCCESS;
373 return NSS_STATUS_UNAVAIL;
376 NSS_GETHOSTBYNAME_FALLBACKS(mymachines)