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 *ifindexes = 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_ifindexes = sd_machine_get_ifindexes(name, &ifindexes);
105 if (n_ifindexes < 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 = NO_RECOVERY;
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 (sz != PROTO_ADDRESS_SIZE(family)) {
176 r_tuple = (struct gaih_addrtuple*) (buffer + idx);
177 r_tuple->next = i == c-1 ? NULL : (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple)));
178 r_tuple->name = r_name;
179 r_tuple->family = family;
180 r_tuple->scopeid = n_ifindexes == 1 ? ifindexes[0] : 0;
181 memcpy(r_tuple->addr, a, sz);
183 idx += ALIGN(sizeof(struct gaih_addrtuple));
189 r = sd_bus_message_exit_container(reply);
196 **pat = *r_tuple_first;
198 *pat = r_tuple_first;
203 return NSS_STATUS_SUCCESS;
208 return NSS_STATUS_UNAVAIL;
211 enum nss_status _nss_mymachines_gethostbyname3_r(
214 struct hostent *result,
215 char *buffer, size_t buflen,
216 int *errnop, int *h_errnop,
220 _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
221 _cleanup_bus_unref_ sd_bus *bus = NULL;
222 _cleanup_free_ char *class = NULL;
223 unsigned c = 0, i = 0;
224 char *r_name, *r_aliases, *r_addr, *r_addr_list;
225 size_t l, idx, ms, alen;
237 if (af != AF_INET && af != AF_INET6) {
242 r = sd_machine_get_class(name, &class);
245 if (!streq(class, "container")) {
250 r = sd_bus_open_system(&bus);
254 r = sd_bus_call_method(bus,
255 "org.freedesktop.machine1",
256 "/org/freedesktop/machine1",
257 "org.freedesktop.machine1.Manager",
258 "GetMachineAddresses",
265 r = sd_bus_message_enter_container(reply, 'a', "(yay)");
269 r = count_addresses(reply, af, &c);
275 *h_errnop = HOST_NOT_FOUND;
276 return NSS_STATUS_NOTFOUND;
279 alen = PROTO_ADDRESS_SIZE(af);
284 (c > 0 ? c : 1) * ALIGN(alen) +
285 (c > 0 ? c+1 : 2) * sizeof(char*);
289 *h_errnop = NO_RECOVERY;
290 return NSS_STATUS_TRYAGAIN;
293 /* First, append name */
295 memcpy(r_name, name, l+1);
298 /* Second, create aliases array */
299 r_aliases = buffer + idx;
300 ((char**) r_aliases)[0] = NULL;
301 idx += sizeof(char*);
303 /* Third, append addresses */
304 r_addr = buffer + idx;
305 while ((r = sd_bus_message_enter_container(reply, 'r', "yay")) > 0) {
306 unsigned char family;
310 r = sd_bus_message_read(reply, "y", &family);
314 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
318 r = sd_bus_message_exit_container(reply);
330 memcpy(r_addr + i*ALIGN(alen), a, alen);
335 idx += c * ALIGN(alen);
337 r = sd_bus_message_exit_container(reply);
341 /* Third, append address pointer array */
342 r_addr_list = buffer + idx;
343 for (i = 0; i < c; i++)
344 ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen);
346 ((char**) r_addr_list)[i] = NULL;
347 idx += (c+1) * sizeof(char*);
351 result->h_name = r_name;
352 result->h_aliases = (char**) r_aliases;
353 result->h_addrtype = af;
354 result->h_length = alen;
355 result->h_addr_list = (char**) r_addr_list;
363 return NSS_STATUS_SUCCESS;
368 return NSS_STATUS_UNAVAIL;
371 NSS_GETHOSTBYNAME_FALLBACKS(mymachines)