4
This file is based on an example that is part of avahi, which is copyright:
5
Lennart Poettering <lennart (at) poettering (dot) de>
6
Trent Lloyd <lathiat@bur.st>
7
Sebastien Estienne <sebastien.estienne@gmail.com>
9
James Willcox <snorp@snorp.net>
11
Modifications for mass-enlist-udeb are copyright 2009-2012 Canonical Ltd.
13
avahi is free software; you can redistribute it and/or modify it
14
under the terms of the GNU Lesser General Public License as
15
published by the Free Software Foundation; either version 2.1 of the
16
License, or (at your option) any later version.
18
avahi is distributed in the hope that it will be useful, but WITHOUT
19
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
21
Public License for more details.
23
You should have received a copy of the GNU Lesser General Public
24
License along with avahi; if not, write to the Free Software
25
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
39
#include <avahi-core/core.h>
40
#include <avahi-core/lookup.h>
41
#include <avahi-core/log.h>
42
#include <avahi-common/simple-watch.h>
43
#include <avahi-common/malloc.h>
44
#include <avahi-common/error.h>
46
#include <debian-installer.h>
48
static AvahiSimplePoll *simple_poll = NULL;
49
static AvahiServer *server = NULL;
51
static di_hash_table *resolver_hash = NULL;
55
static void quiet_logger(AvahiLogLevel level, const char *txt) {
58
static bool resolver_equal_func(const void *key1, const void *key2) {
59
return !strcmp((const char *) key1, (const char *) key2);
62
static uint32_t resolver_hash_func(const void *key) {
63
/* save reimplementing our own hash algorithm ... */
65
rstring.string = (char *) key;
66
rstring.size = strlen(key);
67
return di_rstring_hash(&rstring);
70
static void resolve_callback(
71
AvahiSServiceResolver *r,
72
AVAHI_GCC_UNUSED AvahiIfIndex interface,
73
AVAHI_GCC_UNUSED AvahiProtocol protocol,
74
AvahiResolverEvent event,
78
const char *host_name,
79
const AvahiAddress *address,
82
AvahiLookupResultFlags flags,
83
AVAHI_GCC_UNUSED void* userdata) {
87
/* Called whenever a service has been resolved successfully or timed out */
90
case AVAHI_RESOLVER_FAILURE:
92
fprintf(stderr, "(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, avahi_strerror(avahi_server_errno(server)));
95
case AVAHI_RESOLVER_FOUND: {
96
char *human_address = avahi_malloc0(AVAHI_ADDRESS_STR_MAX);
98
if (avahi_address_snprint(human_address, AVAHI_ADDRESS_STR_MAX, address)) {
99
if (address->proto == AVAHI_PROTO_INET6)
100
key = avahi_strdup_printf("[%s]:%u", human_address, port);
101
else if (strncmp(human_address, "169.254.169.254", 15) == 0)
102
key = avahi_strdup_printf("%s:%u", name, port);
104
key = avahi_strdup_printf("%s:%u", human_address, port);
107
fprintf(stderr, "(Resolver) failed to resolve %s to IP address/port\n", key);
109
avahi_free(human_address);
111
if (di_hash_table_lookup(resolver_hash, key)) {
113
fprintf(stderr, "(Resolver) Already seen %s\n", key);
116
di_hash_table_insert(resolver_hash, key, "");
118
fprintf(stderr, "(Resolver) Service '%s' of type '%s' in domain '%s':\n", name, type, domain);
119
printf("%s|%s\n", name, key);
122
/* don't free key; di_hash_table_insert doesn't copy it */
126
avahi_s_service_resolver_free(r);
129
static void browse_callback(
130
AvahiSServiceBrowser *b,
131
AvahiIfIndex interface,
132
AvahiProtocol protocol,
133
AvahiBrowserEvent event,
137
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
140
AvahiServer *s = userdata;
143
/* Called whenever a new services becomes available on the LAN or is removed from the LAN */
147
case AVAHI_BROWSER_FAILURE:
148
fprintf(stderr, "(Browser) %s\n", avahi_strerror(avahi_server_errno(server)));
149
avahi_simple_poll_quit(simple_poll);
152
case AVAHI_BROWSER_NEW:
154
fprintf(stderr, "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
156
/* We ignore the returned resolver object. In the callback
157
function we free it. If the server is terminated before
158
the callback function is called the server will free
159
the resolver for us. */
161
if (!(avahi_s_service_resolver_new(s, interface, protocol, name, type, domain, AVAHI_PROTO_INET, 0, resolve_callback, s)))
162
fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_server_errno(s)));
166
case AVAHI_BROWSER_REMOVE:
168
fprintf(stderr, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
171
case AVAHI_BROWSER_ALL_FOR_NOW:
173
fprintf(stderr, "(Browser) %s\n", "ALL_FOR_NOW");
177
case AVAHI_BROWSER_CACHE_EXHAUSTED:
179
fprintf(stderr, "(Browser) %s\n", "CACHE_EXHAUSTED");
184
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char*argv[]) {
185
AvahiServerConfig config;
186
AvahiSServiceBrowser *sb = NULL;
190
if (getenv("MAAS_ENLIST_DEBUG"))
193
/* Initialize the pseudo-RNG */
197
avahi_set_log_function(quiet_logger);
199
/* Allocate main loop object */
200
if (!(simple_poll = avahi_simple_poll_new())) {
201
fprintf(stderr, "Failed to create simple poll object.\n");
205
/* Do not publish any local records */
206
avahi_server_config_init(&config);
207
config.publish_hinfo = 0;
208
config.publish_addresses = 0;
209
config.publish_workstation = 0;
210
config.publish_domain = 0;
212
/* Allocate a new server */
213
server = avahi_server_new(avahi_simple_poll_get(simple_poll), &config, NULL, NULL, &error);
215
/* Free the configuration data */
216
avahi_server_config_free(&config);
218
/* Check whether creating the server object succeeded */
220
fprintf(stderr, "Failed to create server: %s\n", avahi_strerror(error));
224
/* Create the service browser */
225
if (!(sb = avahi_s_service_browser_new(server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_maas._tcp", NULL, 0, browse_callback, server))) {
226
fprintf(stderr, "Failed to create service browser: %s\n", avahi_strerror(avahi_server_errno(server)));
230
/* Create a hash table so we can uniquify resolver results */
231
resolver_hash = di_hash_table_new_full(resolver_hash_func, resolver_equal_func, avahi_free, NULL);
233
/* Run the main loop */
234
avahi_simple_poll_loop(simple_poll);
241
di_hash_table_destroy (resolver_hash);
245
avahi_s_service_browser_free(sb);
248
avahi_server_free(server);
251
avahi_simple_poll_free(simple_poll);