]> git.meshlink.io Git - catta/blob - avahi-utils/avahi-resolve.c
0077248daa7b68c98bcc2ee2271802209f15c97d
[catta] / avahi-utils / avahi-resolve.c
1 /* $Id$ */
2
3 /***
4   This file is part of avahi.
5
6   avahi is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as
8   published by the Free Software Foundation; either version 2.1 of the
9   License, or (at your option) any later version.
10
11   avahi is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14   Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with avahi; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <getopt.h>
29 #include <assert.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <net/if.h>
34 #include <locale.h>
35
36 #include <avahi-common/simple-watch.h>
37 #include <avahi-common/error.h>
38 #include <avahi-common/malloc.h>
39 #include <avahi-common/domain.h>
40 #include <avahi-common/llist.h>
41 #include <avahi-common/i18n.h>
42 #include <avahi-client/client.h>
43 #include <avahi-client/lookup.h>
44
45 #include "sigint.h"
46
47 typedef enum {
48     COMMAND_UNSPEC,
49     COMMAND_HELP,
50     COMMAND_VERSION,
51     COMMAND_RESOLVE_HOST_NAME,
52     COMMAND_RESOLVE_ADDRESS
53 } Command;
54
55 typedef struct Config {
56     int verbose;
57     Command command;
58     AvahiProtocol proto;
59 } Config;
60
61 static AvahiSimplePoll *simple_poll = NULL;
62 static AvahiClient *client = NULL;
63
64 static int n_resolving = 0;
65
66 static void host_name_resolver_callback(
67     AvahiHostNameResolver *r,
68     AVAHI_GCC_UNUSED AvahiIfIndex interface,
69     AVAHI_GCC_UNUSED AvahiProtocol protocol,
70     AvahiResolverEvent event,
71     const char *name,
72     const AvahiAddress *a,
73     AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
74     AVAHI_GCC_UNUSED void *userdata) {
75
76     assert(r);
77
78     switch (event) {
79         case AVAHI_RESOLVER_FOUND: {
80             char address[AVAHI_ADDRESS_STR_MAX];
81
82             avahi_address_snprint(address, sizeof(address), a);
83
84             printf("%s\t%s\n", name, address);
85
86             break;
87         }
88
89         case AVAHI_RESOLVER_FAILURE:
90
91             fprintf(stderr, _("Failed to resolve host name '%s': %s\n"), name, avahi_strerror(avahi_client_errno(client)));
92             break;
93     }
94
95
96     avahi_host_name_resolver_free(r);
97
98     assert(n_resolving > 0);
99     n_resolving--;
100
101     if (n_resolving <= 0)
102         avahi_simple_poll_quit(simple_poll);
103 }
104
105 static void address_resolver_callback(
106     AvahiAddressResolver *r,
107     AVAHI_GCC_UNUSED AvahiIfIndex interface,
108     AVAHI_GCC_UNUSED AvahiProtocol protocol,
109     AvahiResolverEvent event,
110     const AvahiAddress *a,
111     const char *name,
112     AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
113     AVAHI_GCC_UNUSED void *userdata) {
114
115     char address[AVAHI_ADDRESS_STR_MAX];
116     assert(r);
117
118     avahi_address_snprint(address, sizeof(address), a);
119
120     switch (event) {
121         case AVAHI_RESOLVER_FOUND:
122
123             printf("%s\t%s\n", address, name);
124             break;
125
126         case AVAHI_RESOLVER_FAILURE:
127
128             fprintf(stderr, _("Failed to resolve address '%s': %s\n"), address, avahi_strerror(avahi_client_errno(client)));
129             break;
130     }
131
132
133     avahi_address_resolver_free(r);
134
135     assert(n_resolving > 0);
136     n_resolving--;
137
138     if (n_resolving <= 0)
139         avahi_simple_poll_quit(simple_poll);
140 }
141
142 static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) {
143     switch (state) {
144         case AVAHI_CLIENT_FAILURE:
145             fprintf(stderr, _("Client failure, exiting: %s\n"), avahi_strerror(avahi_client_errno(c)));
146             avahi_simple_poll_quit(simple_poll);
147             break;
148
149         case AVAHI_CLIENT_S_REGISTERING:
150         case AVAHI_CLIENT_S_RUNNING:
151         case AVAHI_CLIENT_S_COLLISION:
152         case AVAHI_CLIENT_CONNECTING:
153             ;
154     }
155 }
156
157 static void help(FILE *f, const char *argv0) {
158     fprintf(f,
159             _("%s [options] %s <host name ...>\n"
160               "%s [options] %s <address ... >\n\n"
161               "    -h --help            Show this help\n"
162               "    -V --version         Show version\n"
163               "    -n --name            Resolve host name\n"
164               "    -a --address         Resolve address\n"
165               "    -v --verbose         Enable verbose mode\n"
166               "    -6                   Lookup IPv6 address\n"
167               "    -4                   Lookup IPv4 address\n"),
168             argv0, strstr(argv0, "host-name") ? "[-n]" : "-n",
169             argv0, strstr(argv0, "address") ? "[-a]" : "-a");
170 }
171
172 static int parse_command_line(Config *c, const char *argv0, int argc, char *argv[]) {
173     int o;
174
175     static const struct option long_options[] = {
176         { "help",           no_argument,       NULL, 'h' },
177         { "version",        no_argument,       NULL, 'V' },
178         { "name",           no_argument,       NULL, 'n' },
179         { "address",        no_argument,       NULL, 'a' },
180         { "verbose",        no_argument,       NULL, 'v' },
181         { NULL, 0, NULL, 0 }
182     };
183
184     assert(c);
185
186     c->command = strstr(argv0, "address") ? COMMAND_RESOLVE_ADDRESS : (strstr(argv0, "host-name") ? COMMAND_RESOLVE_HOST_NAME : COMMAND_UNSPEC);
187     c->proto = AVAHI_PROTO_UNSPEC;
188     c->verbose = 0;
189
190     while ((o = getopt_long(argc, argv, "hVnav46", long_options, NULL)) >= 0) {
191
192         switch(o) {
193             case 'h':
194                 c->command = COMMAND_HELP;
195                 break;
196             case 'V':
197                 c->command = COMMAND_VERSION;
198                 break;
199             case 'n':
200                 c->command = COMMAND_RESOLVE_HOST_NAME;
201                 break;
202             case 'a':
203                 c->command = COMMAND_RESOLVE_ADDRESS;
204                 break;
205             case 'v':
206                 c->verbose = 1;
207                 break;
208             case '4':
209                 c->proto = AVAHI_PROTO_INET;
210                 break;
211             case '6':
212                 c->proto = AVAHI_PROTO_INET6;
213                 break;
214             default:
215                 return -1;
216         }
217     }
218
219     if (c->command == COMMAND_RESOLVE_ADDRESS || c->command == COMMAND_RESOLVE_HOST_NAME) {
220         if (optind >= argc) {
221             fprintf(stderr, _("Too few arguments\n"));
222             return -1;
223         }
224     }
225
226     return 0;
227 }
228
229 int main(int argc, char *argv[]) {
230     int ret = 1, error;
231     Config config;
232     const char *argv0;
233
234     avahi_init_i18n();
235     setlocale(LC_ALL, "");
236
237     if ((argv0 = strrchr(argv[0], '/')))
238         argv0++;
239     else
240         argv0 = argv[0];
241
242     if (parse_command_line(&config, argv0, argc, argv) < 0)
243         goto fail;
244
245     switch (config.command) {
246         case COMMAND_UNSPEC:
247             ret = 1;
248             fprintf(stderr, _("No command specified.\n"));
249             break;
250
251         case COMMAND_HELP:
252             help(stdout, argv0);
253             ret = 0;
254             break;
255
256         case COMMAND_VERSION:
257             printf("%s "PACKAGE_VERSION"\n", argv0);
258             ret = 0;
259             break;
260
261         case COMMAND_RESOLVE_HOST_NAME:
262         case COMMAND_RESOLVE_ADDRESS: {
263             int i;
264
265             if (!(simple_poll = avahi_simple_poll_new())) {
266                 fprintf(stderr, _("Failed to create simple poll object.\n"));
267                 goto fail;
268             }
269
270             if (sigint_install(simple_poll) < 0)
271                 goto fail;
272
273             if (!(client = avahi_client_new(avahi_simple_poll_get(simple_poll), 0, client_callback, NULL, &error))) {
274                 fprintf(stderr, _("Failed to create client object: %s\n"), avahi_strerror(error));
275                 goto fail;
276             }
277
278             if (config.verbose) {
279                 const char *version, *hn;
280
281                 if (!(version = avahi_client_get_version_string(client))) {
282                     fprintf(stderr, _("Failed to query version string: %s\n"), avahi_strerror(avahi_client_errno(client)));
283                     goto fail;
284                 }
285
286                 if (!(hn = avahi_client_get_host_name_fqdn(client))) {
287                     fprintf(stderr, _("Failed to query host name: %s\n"), avahi_strerror(avahi_client_errno(client)));
288                     goto fail;
289                 }
290
291                 fprintf(stderr, _("Server version: %s; Host name: %s\n"), version, hn);
292             }
293
294             n_resolving = 0;
295
296             for (i = optind; i < argc; i++) {
297
298                 if (config.command == COMMAND_RESOLVE_HOST_NAME) {
299
300                     if (!(avahi_host_name_resolver_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, argv[i], config.proto, 0, host_name_resolver_callback, NULL))) {
301                         fprintf(stderr, _("Failed to create host name resolver: %s\n"), avahi_strerror(avahi_client_errno(client)));
302                         goto fail;
303                     }
304
305                 } else {
306                     AvahiAddress a;
307
308                     assert(config.command == COMMAND_RESOLVE_ADDRESS);
309
310                     if (!avahi_address_parse(argv[i], AVAHI_PROTO_UNSPEC, &a)) {
311                         fprintf(stderr, _("Failed to parse address '%s'\n"), argv[i]);
312                         goto fail;
313                     }
314
315                     if (!(avahi_address_resolver_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, &a, 0, address_resolver_callback, NULL))) {
316                         fprintf(stderr, _("Failed to create address resolver: %s\n"), avahi_strerror(avahi_client_errno(client)));
317                         goto fail;
318                     }
319                 }
320
321                 n_resolving++;
322             }
323
324             avahi_simple_poll_loop(simple_poll);
325             ret = 0;
326             break;
327         }
328     }
329
330 fail:
331
332     if (client)
333         avahi_client_free(client);
334
335     sigint_uninstall();
336
337     if (simple_poll)
338         avahi_simple_poll_free(simple_poll);
339
340     return ret;
341 }