]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve-host/resolve-host.c
util-lib: split string parsing related calls from util.[ch] into parse-util.[ch]
[thirdparty/systemd.git] / src / resolve-host / resolve-host.c
CommitLineData
bdef7319
ZJS
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2014 Zbigniew Jędrzejewski-Szmek
7
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.
12
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.
17
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/>.
20***/
21
bdef7319
ZJS
22#include <net/if.h>
23#include <getopt.h>
24
25#include "sd-bus.h"
3f6fd1ba
LP
26
27#include "af-list.h"
bdef7319 28#include "bus-error.h"
3f6fd1ba 29#include "bus-util.h"
bdef7319 30#include "in-addr-util.h"
6bedfcbb 31#include "parse-util.h"
51323288 32#include "resolved-def.h"
3f6fd1ba 33#include "resolved-dns-packet.h"
2d4c5cbc 34
bdef7319
ZJS
35#define DNS_CALL_TIMEOUT_USEC (45*USEC_PER_SEC)
36
37static int arg_family = AF_UNSPEC;
38static int arg_ifindex = 0;
de292aa1 39static int arg_type = 0;
2d4c5cbc 40static uint16_t arg_class = 0;
b93312f5 41static bool arg_legend = true;
51323288
LP
42static uint64_t arg_flags = 0;
43
78c6a153 44static void print_source(uint64_t flags, usec_t rtt) {
74998408 45 char rtt_str[FORMAT_TIMESTAMP_MAX];
51323288
LP
46
47 if (!arg_legend)
48 return;
49
78c6a153 50 if (flags == 0)
51323288
LP
51 return;
52
53 fputs("\n-- Information acquired via", stdout);
54
55 if (flags != 0)
56 printf(" protocol%s%s%s",
57 flags & SD_RESOLVED_DNS ? " DNS" :"",
58 flags & SD_RESOLVED_LLMNR_IPV4 ? " LLMNR/IPv4" : "",
59 flags & SD_RESOLVED_LLMNR_IPV6 ? " LLMNR/IPv6" : "");
60
74998408
TG
61 assert_se(format_timespan(rtt_str, sizeof(rtt_str), rtt, 100));
62
63 printf(" in %s", rtt_str);
64
51323288
LP
65 fputc('.', stdout);
66 fputc('\n', stdout);
67}
bdef7319 68
79266746 69static int resolve_host(sd_bus *bus, const char *name) {
bdef7319
ZJS
70
71 _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
72 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
79266746 73 const char *canonical = NULL;
78c6a153 74 char ifname[IF_NAMESIZE] = "";
bdef7319 75 unsigned c = 0;
78c6a153 76 int r;
51323288 77 uint64_t flags;
74998408 78 usec_t ts;
bdef7319
ZJS
79
80 assert(name);
81
78c6a153
LP
82 if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
83 return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);
84
85 log_debug("Resolving %s (family %s, interface %s).", name, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
bdef7319
ZJS
86
87 r = sd_bus_message_new_method_call(
88 bus,
89 &req,
90 "org.freedesktop.resolve1",
91 "/org/freedesktop/resolve1",
92 "org.freedesktop.resolve1.Manager",
93 "ResolveHostname");
02dd6e18
LP
94 if (r < 0)
95 return bus_log_create_error(r);
bdef7319 96
51323288 97 r = sd_bus_message_append(req, "isit", arg_ifindex, name, arg_family, arg_flags);
02dd6e18
LP
98 if (r < 0)
99 return bus_log_create_error(r);
bdef7319 100
74998408
TG
101 ts = now(CLOCK_MONOTONIC);
102
bdef7319
ZJS
103 r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
104 if (r < 0) {
105 log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r));
106 return r;
107 }
108
74998408
TG
109 ts = now(CLOCK_MONOTONIC) - ts;
110
78c6a153 111 r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
02dd6e18
LP
112 if (r < 0)
113 return bus_log_parse_error(r);
bdef7319 114
78c6a153 115 while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
bdef7319 116 const void *a;
bdef7319
ZJS
117 size_t sz;
118 _cleanup_free_ char *pretty = NULL;
78c6a153
LP
119 int ifindex, family;
120
121 assert_cc(sizeof(int) == sizeof(int32_t));
bdef7319 122
78c6a153 123 r = sd_bus_message_read(reply, "ii", &ifindex, &family);
02dd6e18
LP
124 if (r < 0)
125 return bus_log_parse_error(r);
bdef7319
ZJS
126
127 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
02dd6e18
LP
128 if (r < 0)
129 return bus_log_parse_error(r);
bdef7319 130
bdef7319 131 r = sd_bus_message_exit_container(reply);
02dd6e18
LP
132 if (r < 0)
133 return bus_log_parse_error(r);
bdef7319 134
79266746 135 if (!IN_SET(family, AF_INET, AF_INET6)) {
be636413 136 log_debug("%s: skipping entry with family %d (%s)", name, family, af_to_name(family) ?: "unknown");
bdef7319
ZJS
137 continue;
138 }
139
140 if (sz != FAMILY_ADDRESS_SIZE(family)) {
78c6a153 141 log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name, sz, af_to_name(family) ?: "unknown");
bdef7319
ZJS
142 continue;
143 }
144
78c6a153
LP
145 ifname[0] = 0;
146 if (ifindex > 0 && !if_indextoname(ifindex, ifname))
147 log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
bdef7319 148
bdef7319 149 r = in_addr_to_string(family, a, &pretty);
78c6a153
LP
150 if (r < 0)
151 return log_error_errno(r, "Failed to print address for %s: %m", name);
bdef7319 152
79266746
LP
153 printf("%*s%s %s%s%s\n",
154 (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
155 pretty,
156 isempty(ifname) ? "" : "%", ifname);
bdef7319
ZJS
157
158 c++;
159 }
79266746
LP
160 if (r < 0)
161 return bus_log_parse_error(r);
162
163 r = sd_bus_message_exit_container(reply);
164 if (r < 0)
165 return bus_log_parse_error(r);
166
51323288 167 r = sd_bus_message_read(reply, "st", &canonical, &flags);
79266746
LP
168 if (r < 0)
169 return bus_log_parse_error(r);
170
ece174c5 171 if (!streq(name, canonical))
79266746
LP
172 printf("%*s%s (%s)\n",
173 (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
174 canonical);
bdef7319
ZJS
175
176 if (c == 0) {
177 log_error("%s: no addresses found", name);
79266746
LP
178 return -ESRCH;
179 }
180
78c6a153 181 print_source(flags, ts);
51323288 182
79266746
LP
183 return 0;
184}
185
186static int resolve_address(sd_bus *bus, int family, const union in_addr_union *address, int ifindex) {
187 _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
188 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
189 _cleanup_free_ char *pretty = NULL;
190 char ifname[IF_NAMESIZE] = "";
51323288 191 uint64_t flags;
79266746 192 unsigned c = 0;
74998408 193 usec_t ts;
79266746
LP
194 int r;
195
196 assert(bus);
197 assert(IN_SET(family, AF_INET, AF_INET6));
198 assert(address);
199
78c6a153
LP
200 if (ifindex <= 0)
201 ifindex = arg_ifindex;
202
79266746
LP
203 r = in_addr_to_string(family, address, &pretty);
204 if (r < 0)
205 return log_oom();
206
78c6a153
LP
207 if (ifindex > 0 && !if_indextoname(ifindex, ifname))
208 return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
79266746
LP
209
210 log_debug("Resolving %s%s%s.", pretty, isempty(ifname) ? "" : "%", ifname);
211
212 r = sd_bus_message_new_method_call(
213 bus,
214 &req,
215 "org.freedesktop.resolve1",
216 "/org/freedesktop/resolve1",
217 "org.freedesktop.resolve1.Manager",
218 "ResolveAddress");
219 if (r < 0)
220 return bus_log_create_error(r);
221
51323288 222 r = sd_bus_message_append(req, "ii", ifindex, family);
79266746
LP
223 if (r < 0)
224 return bus_log_create_error(r);
225
226 r = sd_bus_message_append_array(req, 'y', address, FAMILY_ADDRESS_SIZE(family));
227 if (r < 0)
228 return bus_log_create_error(r);
229
51323288 230 r = sd_bus_message_append(req, "t", arg_flags);
79266746
LP
231 if (r < 0)
232 return bus_log_create_error(r);
233
74998408
TG
234 ts = now(CLOCK_MONOTONIC);
235
79266746
LP
236 r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
237 if (r < 0) {
238 log_error("%s: resolve call failed: %s", pretty, bus_error_message(&error, r));
239 return r;
240 }
241
74998408
TG
242 ts = now(CLOCK_MONOTONIC) - ts;
243
78c6a153 244 r = sd_bus_message_enter_container(reply, 'a', "(is)");
79266746
LP
245 if (r < 0)
246 return bus_log_create_error(r);
247
78c6a153
LP
248 while ((r = sd_bus_message_enter_container(reply, 'r', "is")) > 0) {
249 const char *n;
250
251 assert_cc(sizeof(int) == sizeof(int32_t));
79266746 252
78c6a153
LP
253 r = sd_bus_message_read(reply, "is", &ifindex, &n);
254 if (r < 0)
255 return r;
256
257 r = sd_bus_message_exit_container(reply);
258 if (r < 0)
259 return r;
260
261 ifname[0] = 0;
262 if (ifindex > 0 && !if_indextoname(ifindex, ifname))
263 log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
264
265 printf("%*s%*s%*s%s %s\n",
79266746 266 (int) strlen(pretty), c == 0 ? pretty : "",
78c6a153
LP
267 isempty(ifname) ? 0 : 1, c > 0 || isempty(ifname) ? "" : "%",
268 (int) strlen(ifname), c == 0 ? ifname : "",
79266746
LP
269 c == 0 ? ":" : " ",
270 n);
271
272 c++;
bdef7319 273 }
79266746
LP
274 if (r < 0)
275 return bus_log_parse_error(r);
bdef7319 276
02dd6e18
LP
277 r = sd_bus_message_exit_container(reply);
278 if (r < 0)
279 return bus_log_parse_error(r);
280
51323288
LP
281 r = sd_bus_message_read(reply, "t", &flags);
282 if (r < 0)
283 return bus_log_parse_error(r);
284
79266746
LP
285 if (c == 0) {
286 log_error("%s: no names found", pretty);
287 return -ESRCH;
288 }
289
78c6a153 290 print_source(flags, ts);
51323288 291
79266746
LP
292 return 0;
293}
294
295static int parse_address(const char *s, int *family, union in_addr_union *address, int *ifindex) {
296 const char *percent, *a;
297 int ifi = 0;
298 int r;
299
300 percent = strchr(s, '%');
301 if (percent) {
302 r = safe_atoi(percent+1, &ifi);
303 if (r < 0 || ifi <= 0) {
304 ifi = if_nametoindex(percent+1);
305 if (ifi <= 0)
306 return -EINVAL;
307 }
308
309 a = strndupa(s, percent - s);
310 } else
311 a = s;
312
313 r = in_addr_from_string_auto(a, family, address);
314 if (r < 0)
315 return r;
316
317 *ifindex = ifi;
02dd6e18 318 return 0;
bdef7319
ZJS
319}
320
2d4c5cbc
LP
321static int resolve_record(sd_bus *bus, const char *name) {
322
323 _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
324 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
78c6a153 325 char ifname[IF_NAMESIZE] = "";
2d4c5cbc 326 unsigned n = 0;
51323288 327 uint64_t flags;
78c6a153 328 int r;
74998408 329 usec_t ts;
2d4c5cbc
LP
330
331 assert(name);
332
78c6a153
LP
333 if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
334 return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);
335
336 log_debug("Resolving %s %s %s (interface %s).", name, dns_class_to_string(arg_class), dns_type_to_string(arg_type), isempty(ifname) ? "*" : ifname);
2d4c5cbc
LP
337
338 r = sd_bus_message_new_method_call(
339 bus,
340 &req,
341 "org.freedesktop.resolve1",
342 "/org/freedesktop/resolve1",
343 "org.freedesktop.resolve1.Manager",
344 "ResolveRecord");
345 if (r < 0)
346 return bus_log_create_error(r);
347
de292aa1 348 assert((uint16_t) arg_type == arg_type);
51323288 349 r = sd_bus_message_append(req, "isqqt", arg_ifindex, name, arg_class, arg_type, arg_flags);
2d4c5cbc
LP
350 if (r < 0)
351 return bus_log_create_error(r);
352
74998408
TG
353 ts = now(CLOCK_MONOTONIC);
354
2d4c5cbc
LP
355 r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
356 if (r < 0) {
357 log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r));
358 return r;
359 }
360
74998408
TG
361 ts = now(CLOCK_MONOTONIC) - ts;
362
78c6a153 363 r = sd_bus_message_enter_container(reply, 'a', "(iqqay)");
51323288
LP
364 if (r < 0)
365 return bus_log_parse_error(r);
366
78c6a153 367 while ((r = sd_bus_message_enter_container(reply, 'r', "iqqay")) > 0) {
2d4c5cbc
LP
368 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
369 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
370 _cleanup_free_ char *s = NULL;
371 uint16_t c, t;
78c6a153 372 int ifindex;
2d4c5cbc
LP
373 const void *d;
374 size_t l;
375
78c6a153
LP
376 assert_cc(sizeof(int) == sizeof(int32_t));
377
378 r = sd_bus_message_read(reply, "iqq", &ifindex, &c, &t);
2d4c5cbc
LP
379 if (r < 0)
380 return bus_log_parse_error(r);
381
382 r = sd_bus_message_read_array(reply, 'y', &d, &l);
383 if (r < 0)
384 return bus_log_parse_error(r);
385
386 r = sd_bus_message_exit_container(reply);
387 if (r < 0)
388 return bus_log_parse_error(r);
389
390 r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0);
391 if (r < 0)
392 return log_oom();
393
f6a5fec6
LP
394 p->refuse_compression = true;
395
2d4c5cbc
LP
396 r = dns_packet_append_blob(p, d, l, NULL);
397 if (r < 0)
398 return log_oom();
399
400 r = dns_packet_read_rr(p, &rr, NULL);
401 if (r < 0) {
402 log_error("Failed to parse RR.");
403 return r;
404 }
405
406 r = dns_resource_record_to_string(rr, &s);
407 if (r < 0) {
408 log_error("Failed to format RR.");
409 return r;
410 }
411
78c6a153
LP
412 ifname[0] = 0;
413 if (ifindex > 0 && !if_indextoname(ifindex, ifname))
414 log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
415
416 printf("%s%s%s\n", s, isempty(ifname) ? "" : " # interface ", ifname);
2d4c5cbc
LP
417 n++;
418 }
419 if (r < 0)
420 return bus_log_parse_error(r);
421
422 r = sd_bus_message_exit_container(reply);
423 if (r < 0)
424 return bus_log_parse_error(r);
425
51323288
LP
426 r = sd_bus_message_read(reply, "t", &flags);
427 if (r < 0)
428 return bus_log_parse_error(r);
429
2d4c5cbc
LP
430 if (n == 0) {
431 log_error("%s: no records found", name);
432 return -ESRCH;
433 }
434
78c6a153 435 print_source(flags, ts);
51323288 436
2d4c5cbc
LP
437 return 0;
438}
439
b93312f5
ZJS
440static void help_dns_types(void) {
441 int i;
442 const char *t;
443
444 if (arg_legend)
09b1fe14 445 puts("Known DNS RR types:");
b93312f5
ZJS
446 for (i = 0; i < _DNS_TYPE_MAX; i++) {
447 t = dns_type_to_string(i);
448 if (t)
449 puts(t);
450 }
451}
452
453static void help_dns_classes(void) {
454 int i;
455 const char *t;
456
457 if (arg_legend)
09b1fe14 458 puts("Known DNS RR classes:");
b93312f5
ZJS
459 for (i = 0; i < _DNS_CLASS_MAX; i++) {
460 t = dns_class_to_string(i);
461 if (t)
462 puts(t);
463 }
464}
465
bdef7319
ZJS
466static void help(void) {
467 printf("%s [OPTIONS...]\n\n"
468 "Resolve IPv4 or IPv6 addresses.\n\n"
51323288
LP
469 " -h --help Show this help\n"
470 " --version Show package version\n"
471 " -4 Resolve IPv4 addresses\n"
472 " -6 Resolve IPv6 addresses\n"
473 " -i INTERFACE Look on interface\n"
474 " -p --protocol=PROTOCOL Look via protocol\n"
475 " -t --type=TYPE Query RR with DNS type\n"
476 " -c --class=CLASS Query RR with DNS class\n"
dad29dff 477 " --legend[=BOOL] Do [not] print column headers\n"
79266746 478 , program_invocation_short_name);
bdef7319
ZJS
479}
480
481static int parse_argv(int argc, char *argv[]) {
482 enum {
483 ARG_VERSION = 0x100,
dad29dff 484 ARG_LEGEND,
bdef7319
ZJS
485 };
486
487 static const struct option options[] = {
51323288
LP
488 { "help", no_argument, NULL, 'h' },
489 { "version", no_argument, NULL, ARG_VERSION },
490 { "type", required_argument, NULL, 't' },
491 { "class", required_argument, NULL, 'c' },
3fa4999b 492 { "legend", optional_argument, NULL, ARG_LEGEND },
51323288 493 { "protocol", required_argument, NULL, 'p' },
bdef7319
ZJS
494 {}
495 };
496
2d4c5cbc 497 int c, r;
bdef7319
ZJS
498
499 assert(argc >= 0);
500 assert(argv);
501
51323288 502 while ((c = getopt_long(argc, argv, "h46i:t:c:p:", options, NULL)) >= 0)
bdef7319
ZJS
503 switch(c) {
504
505 case 'h':
506 help();
507 return 0; /* done */;
508
509 case ARG_VERSION:
3f6fd1ba 510 return version();
bdef7319
ZJS
511
512 case '4':
513 arg_family = AF_INET;
514 break;
515
516 case '6':
517 arg_family = AF_INET6;
518 break;
519
3fa4999b
LP
520 case 'i': {
521 int ifi;
522
523 if (safe_atoi(optarg, &ifi) >= 0 && ifi > 0)
524 arg_ifindex = ifi;
525 else {
526 ifi = if_nametoindex(optarg);
527 if (ifi <= 0)
528 return log_error_errno(errno, "Unknown interface %s: %m", optarg);
529
530 arg_ifindex = ifi;
531 }
532
2d4c5cbc 533 break;
3fa4999b 534 }
2d4c5cbc
LP
535
536 case 't':
b93312f5
ZJS
537 if (streq(optarg, "help")) {
538 help_dns_types();
539 return 0;
540 }
541
de292aa1
ZJS
542 arg_type = dns_type_from_string(optarg);
543 if (arg_type < 0) {
2d4c5cbc 544 log_error("Failed to parse RR record type %s", optarg);
590baf91 545 return arg_type;
2d4c5cbc 546 }
de292aa1 547 assert(arg_type > 0 && (uint16_t) arg_type == arg_type);
b93312f5 548
2d4c5cbc
LP
549 break;
550
551 case 'c':
b93312f5
ZJS
552 if (streq(optarg, "help")) {
553 help_dns_classes();
554 return 0;
555 }
556
2d4c5cbc
LP
557 r = dns_class_from_string(optarg, &arg_class);
558 if (r < 0) {
559 log_error("Failed to parse RR record class %s", optarg);
560 return r;
bdef7319 561 }
b93312f5
ZJS
562
563 break;
564
dad29dff
LP
565 case ARG_LEGEND:
566 if (optarg) {
567 r = parse_boolean(optarg);
568 if (r < 0) {
569 log_error("Failed to parse --legend= argument");
570 return r;
571 }
572
573 arg_legend = !!r;
574 } else
575 arg_legend = false;
bdef7319
ZJS
576 break;
577
51323288
LP
578 case 'p':
579 if (streq(optarg, "dns"))
580 arg_flags |= SD_RESOLVED_DNS;
581 else if (streq(optarg, "llmnr"))
582 arg_flags |= SD_RESOLVED_LLMNR;
583 else if (streq(optarg, "llmnr-ipv4"))
584 arg_flags |= SD_RESOLVED_LLMNR_IPV4;
585 else if (streq(optarg, "llmnr-ipv6"))
586 arg_flags |= SD_RESOLVED_LLMNR_IPV6;
587 else {
588 log_error("Unknown protocol specifier: %s", optarg);
589 return -EINVAL;
590 }
591
592 break;
593
bdef7319
ZJS
594 case '?':
595 return -EINVAL;
596
597 default:
598 assert_not_reached("Unhandled option");
599 }
600
2d4c5cbc
LP
601 if (arg_type == 0 && arg_class != 0) {
602 log_error("--class= may only be used in conjunction with --type=");
603 return -EINVAL;
604 }
605
606 if (arg_type != 0 && arg_class == 0)
607 arg_class = DNS_CLASS_IN;
608
bdef7319
ZJS
609 return 1 /* work to do */;
610}
611
bdef7319 612int main(int argc, char **argv) {
03976f7b 613 _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
bdef7319
ZJS
614 int r;
615
616 log_parse_environment();
617 log_open();
618
619 r = parse_argv(argc, argv);
620 if (r <= 0)
79266746
LP
621 goto finish;
622
623 if (optind >= argc) {
624 log_error("No arguments passed");
625 r = -EINVAL;
626 goto finish;
627 }
bdef7319
ZJS
628
629 r = sd_bus_open_system(&bus);
630 if (r < 0) {
da927ba9 631 log_error_errno(r, "sd_bus_open_system: %m");
79266746 632 goto finish;
bdef7319
ZJS
633 }
634
635 while (argv[optind]) {
79266746
LP
636 int family, ifindex, k;
637 union in_addr_union a;
638
2d4c5cbc
LP
639 if (arg_type != 0)
640 k = resolve_record(bus, argv[optind]);
641 else {
642 k = parse_address(argv[optind], &family, &a, &ifindex);
643 if (k >= 0)
644 k = resolve_address(bus, family, &a, ifindex);
645 else
646 k = resolve_host(bus, argv[optind]);
647 }
bdef7319 648
bdef7319
ZJS
649 if (r == 0)
650 r = k;
79266746
LP
651
652 optind++;
bdef7319
ZJS
653 }
654
79266746 655finish:
bdef7319
ZJS
656 return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
657}