#include <grp.h>
#include <pwd.h>
#include <sys/stat.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <time.h>
+#include <stdlib.h>
#include <libdaemon/dfork.h>
#include <libdaemon/dsignal.h>
#include <avahi-core/core.h>
#include <avahi-core/log.h>
+#include <avahi-glib/glib-malloc.h>
+#include <avahi-glib/glib-watch.h>
#include "main.h"
#include "simple-protocol.h"
#define RESOLV_CONF "/etc/resolv.conf"
-static AvahiEntryGroup *dns_servers_entry_group = NULL;
-static AvahiEntryGroup *resolv_conf_entry_group = NULL;
+static AvahiSEntryGroup *dns_servers_entry_group = NULL;
+static AvahiSEntryGroup *resolv_conf_entry_group = NULL;
static gchar **resolv_conf = NULL;
#define MAX_NAME_SERVERS 10
-static gint load_resolv_conf(const DaemonConfig *config) {
+static gint load_resolv_conf(const DaemonConfig *c) {
gint ret = -1;
FILE *f;
gint i = 0;
g_strfreev(resolv_conf);
resolv_conf = NULL;
- if (!config->publish_resolv_conf)
+ if (!c->publish_resolv_conf)
return 0;
if (!(f = fopen(RESOLV_CONF, "r"))) {
return ret;
}
-static AvahiEntryGroup* add_dns_servers(AvahiServer *s, gchar **l) {
+static AvahiSEntryGroup* add_dns_servers(AvahiServer *s, AvahiSEntryGroup* g, gchar **l) {
gchar **p;
- AvahiEntryGroup *g;
g_assert(s);
g_assert(l);
- g = avahi_entry_group_new(s, NULL, NULL);
+ if (!g)
+ g = avahi_s_entry_group_new(s, NULL, NULL);
+
+ g_assert(avahi_s_entry_group_is_empty(g));
for (p = l; *p; p++) {
AvahiAddress a;
avahi_log_warn("Failed to parse address '%s', ignoring.", *p);
else
if (avahi_server_add_dns_server_address(s, g, -1, AF_UNSPEC, NULL, AVAHI_DNS_SERVER_RESOLVE, &a, 53) < 0) {
- avahi_entry_group_free(g);
+ avahi_s_entry_group_free(g);
+ avahi_log_error("Failed to add DNS server address: %s", avahi_strerror(avahi_server_errno(s)));
return NULL;
}
}
- avahi_entry_group_commit(g);
+ avahi_s_entry_group_commit(g);
return g;
-
}
static void remove_dns_server_entry_groups(void) {
- if (resolv_conf_entry_group) {
- avahi_entry_group_free(resolv_conf_entry_group);
- resolv_conf_entry_group = NULL;
- }
+
+ if (resolv_conf_entry_group)
+ avahi_s_entry_group_reset(resolv_conf_entry_group);
- if (dns_servers_entry_group) {
- avahi_entry_group_free(dns_servers_entry_group);
- dns_servers_entry_group = NULL;
- }
+ if (dns_servers_entry_group)
+ avahi_s_entry_group_reset(dns_servers_entry_group);
}
-static void server_callback(AvahiServer *s, AvahiServerState state, gpointer userdata) {
- DaemonConfig *config = userdata;
+static void server_callback(AvahiServer *s, AvahiServerState state, void *userdata) {
+ DaemonConfig *c = userdata;
g_assert(s);
- g_assert(config);
+ g_assert(c);
#ifdef ENABLE_DBUS
- if (config->enable_dbus)
+ if (c->enable_dbus)
dbus_protocol_server_state_changed(state);
#endif
remove_dns_server_entry_groups();
if (resolv_conf && resolv_conf[0])
- resolv_conf_entry_group = add_dns_servers(s, resolv_conf);
+ resolv_conf_entry_group = add_dns_servers(s, resolv_conf_entry_group, resolv_conf);
- if (config->publish_dns_servers && config->publish_dns_servers[0])
- dns_servers_entry_group = add_dns_servers(s, config->publish_dns_servers);
+ if (c->publish_dns_servers && c->publish_dns_servers[0])
+ dns_servers_entry_group = add_dns_servers(s, dns_servers_entry_group, c->publish_dns_servers);
simple_protocol_restart_queries();
avahi_server_set_host_name(s, n);
g_free(n);
}
-
-
}
static void help(FILE *f, const gchar *argv0) {
argv0);
}
-static gint parse_command_line(DaemonConfig *config, int argc, char *argv[]) {
- gint c;
+static gint parse_command_line(DaemonConfig *c, int argc, char *argv[]) {
+ gint o;
static const struct option const long_options[] = {
{ "help", no_argument, NULL, 'h' },
{ "check", no_argument, NULL, 'c' },
};
- g_assert(config);
+ g_assert(c);
opterr = 0;
- while ((c = getopt_long(argc, argv, "hDkVf:rc", long_options, NULL)) >= 0) {
+ while ((o = getopt_long(argc, argv, "hDkVf:rc", long_options, NULL)) >= 0) {
- switch(c) {
+ switch(o) {
case 'h':
- config->command = DAEMON_HELP;
+ c->command = DAEMON_HELP;
break;
case 'D':
- config->daemonize = TRUE;
+ c->daemonize = TRUE;
break;
case 'k':
- config->command = DAEMON_KILL;
+ c->command = DAEMON_KILL;
break;
case 'V':
- config->command = DAEMON_VERSION;
+ c->command = DAEMON_VERSION;
break;
case 'f':
- g_free(config->config_file);
- config->config_file = g_strdup(optarg);
+ g_free(c->config_file);
+ c->config_file = g_strdup(optarg);
break;
case 'r':
- config->command = DAEMON_RELOAD;
+ c->command = DAEMON_RELOAD;
break;
case 'c':
- config->command = DAEMON_CHECK;
+ c->command = DAEMON_CHECK;
break;
default:
- fprintf(stderr, "Invalid command line argument: %c\n", c);
+ fprintf(stderr, "Invalid command line argument: %c\n", o);
return -1;
}
}
return *s == 'y' || *s == 'Y';
}
-static gint load_config_file(DaemonConfig *config) {
+static gint load_config_file(DaemonConfig *c) {
int r = -1;
GKeyFile *f = NULL;
GError *err = NULL;
gchar **groups = NULL, **g, **keys = NULL, *v = NULL;
- g_assert(config);
+ g_assert(c);
f = g_key_file_new();
g_key_file_set_list_separator(f, ',');
- if (!g_key_file_load_from_file(f, config->config_file ? config->config_file : AVAHI_CONFIG_FILE, G_KEY_FILE_NONE, &err)) {
+ if (!g_key_file_load_from_file(f, c->config_file ? c->config_file : AVAHI_CONFIG_FILE, G_KEY_FILE_NONE, &err)) {
fprintf(stderr, "Unable to read config file: %s\n", err->message);
goto finish;
}
v = g_key_file_get_value(f, *g, *k, NULL);
if (g_strcasecmp(*k, "host-name") == 0) {
- g_free(config->server_config.host_name);
- config->server_config.host_name = v;
+ g_free(c->server_config.host_name);
+ c->server_config.host_name = v;
v = NULL;
} else if (g_strcasecmp(*k, "domain-name") == 0) {
- g_free(config->server_config.domain_name);
- config->server_config.domain_name = v;
+ g_free(c->server_config.domain_name);
+ c->server_config.domain_name = v;
v = NULL;
} else if (g_strcasecmp(*k, "use-ipv4") == 0)
- config->server_config.use_ipv4 = is_yes(v);
+ c->server_config.use_ipv4 = is_yes(v);
else if (g_strcasecmp(*k, "use-ipv6") == 0)
- config->server_config.use_ipv6 = is_yes(v);
+ c->server_config.use_ipv6 = is_yes(v);
else if (g_strcasecmp(*k, "check-response-ttl") == 0)
- config->server_config.check_response_ttl = is_yes(v);
+ c->server_config.check_response_ttl = is_yes(v);
else if (g_strcasecmp(*k, "use-iff-running") == 0)
- config->server_config.use_iff_running = is_yes(v);
+ c->server_config.use_iff_running = is_yes(v);
else if (g_strcasecmp(*k, "enable-dbus") == 0)
- config->enable_dbus = is_yes(v);
+ c->enable_dbus = is_yes(v);
else if (g_strcasecmp(*k, "drop-root") == 0)
- config->drop_root = is_yes(v);
+ c->drop_root = is_yes(v);
else {
fprintf(stderr, "Invalid configuration key \"%s\" in group \"%s\"\n", *k, *g);
goto finish;
v = g_key_file_get_string(f, *g, *k, NULL);
if (g_strcasecmp(*k, "publish-addresses") == 0)
- config->server_config.publish_addresses = is_yes(v);
+ c->server_config.publish_addresses = is_yes(v);
else if (g_strcasecmp(*k, "publish-hinfo") == 0)
- config->server_config.publish_hinfo = is_yes(v);
+ c->server_config.publish_hinfo = is_yes(v);
else if (g_strcasecmp(*k, "publish-workstation") == 0)
- config->server_config.publish_workstation = is_yes(v);
+ c->server_config.publish_workstation = is_yes(v);
else if (g_strcasecmp(*k, "publish-domain") == 0)
- config->server_config.publish_domain = is_yes(v);
+ c->server_config.publish_domain = is_yes(v);
else if (g_strcasecmp(*k, "publish-resolv-conf-dns-servers") == 0)
- config->publish_resolv_conf = is_yes(v);
+ c->publish_resolv_conf = is_yes(v);
else if (g_strcasecmp(*k, "publish-dns-servers") == 0) {
- g_strfreev(config->publish_dns_servers);
- config->publish_dns_servers = g_key_file_get_string_list(f, *g, *k, NULL, NULL);
+ g_strfreev(c->publish_dns_servers);
+ c->publish_dns_servers = g_key_file_get_string_list(f, *g, *k, NULL, NULL);
} else {
fprintf(stderr, "Invalid configuration key \"%s\" in group \"%s\"\n", *k, *g);
goto finish;
v = g_key_file_get_string(f, *g, *k, NULL);
if (g_strcasecmp(*k, "enable-reflector") == 0)
- config->server_config.enable_reflector = is_yes(v);
+ c->server_config.enable_reflector = is_yes(v);
else if (g_strcasecmp(*k, "reflect-ipv") == 0)
- config->server_config.reflect_ipv = is_yes(v);
+ c->server_config.reflect_ipv = is_yes(v);
else {
fprintf(stderr, "Invalid configuration key \"%s\" in group \"%s\"\n", *k, *g);
goto finish;
daemon_log(log_level_map[level], "%s", txt);
}
+static void dump(const gchar *text, gpointer userdata) {
+ avahi_log_info("%s", text);
+}
+
static gboolean signal_callback(GIOChannel *source, GIOCondition condition, gpointer data) {
gint sig;
GMainLoop *loop = data;
static_service_load();
static_service_add_to_server();
- if (resolv_conf_entry_group) {
- avahi_entry_group_free(resolv_conf_entry_group);
- resolv_conf_entry_group = NULL;
- }
+ if (resolv_conf_entry_group)
+ avahi_s_entry_group_reset(resolv_conf_entry_group);
load_resolv_conf(&config);
if (resolv_conf && resolv_conf[0])
- resolv_conf_entry_group = add_dns_servers(avahi_server, resolv_conf);
+ resolv_conf_entry_group = add_dns_servers(avahi_server, resolv_conf_entry_group, resolv_conf);
+
+ break;
+ case SIGUSR1:
+ avahi_log_info("Got SIGUSR1, dumping record data.");
+ avahi_server_dump(avahi_server, dump, NULL);
break;
default:
return TRUE;
}
-static gint run_server(DaemonConfig *config) {
+static gint run_server(DaemonConfig *c) {
GMainLoop *loop = NULL;
gint r = -1;
GIOChannel *io = NULL;
guint watch_id = (guint) -1;
+ gint error;
+ AvahiGLibPoll *poll_api;
- g_assert(config);
-
+ g_assert(c);
+
+ poll_api = avahi_glib_poll_new(NULL);
loop = g_main_loop_new(NULL, FALSE);
- if (daemon_signal_init(SIGINT, SIGQUIT, SIGHUP, SIGTERM, 0) < 0) {
+ if (daemon_signal_init(SIGINT, SIGQUIT, SIGHUP, SIGTERM, SIGUSR1, 0) < 0) {
avahi_log_error("Could not register signal handlers (%s).", strerror(errno));
goto finish;
}
}
g_io_channel_set_close_on_unref(io, FALSE);
- g_io_add_watch(io, G_IO_IN, signal_callback, loop);
+ watch_id = g_io_add_watch(io, G_IO_IN, signal_callback, loop);
if (simple_protocol_setup(NULL) < 0)
goto finish;
#ifdef ENABLE_DBUS
- if (config->enable_dbus)
+ if (c->enable_dbus)
if (dbus_protocol_setup(loop) < 0)
goto finish;
#endif
- if (!(avahi_server = avahi_server_new(NULL, &config->server_config, server_callback, config)))
+ if (!(avahi_server = avahi_server_new(avahi_glib_poll_get(poll_api), &c->server_config, server_callback, c, &error))) {
+ avahi_log_error("Failed to create server: %s", avahi_strerror(error));
goto finish;
+ }
- load_resolv_conf(config);
+ load_resolv_conf(c);
static_service_load();
- if (config->daemonize) {
+ if (c->daemonize)
daemon_retval_send(0);
- r = 0;
- }
+
+ r = 0;
g_main_loop_run(loop);
simple_protocol_shutdown();
#ifdef ENABLE_DBUS
- if (config->enable_dbus)
+ if (c->enable_dbus)
dbus_protocol_shutdown();
#endif
-
if (avahi_server)
avahi_server_free(avahi_server);
if (io)
g_io_channel_unref(io);
-
+ if (poll_api)
+ avahi_glib_poll_free(poll_api);
+
if (loop)
g_main_loop_unref(loop);
-
- if (r != 0 && config->daemonize)
+
+ if (r != 0 && c->daemonize)
daemon_retval_send(1);
return r;
}
+#define RANDOM_DEVICE "/dev/urandom"
+
+static void init_rand_seed(void) {
+ int fd;
+ unsigned seed = 0;
+
+ /* Try to initialize seed from /dev/urandom, to make it a little
+ * less predictable, and to make sure that multiple machines
+ * booted at the same time choose different random seeds. */
+ if ((fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) {
+ read(fd, &seed, sizeof(seed));
+ close(fd);
+ }
+
+ /* If the initialization failed by some reason, we add the time to the seed*/
+ seed |= (unsigned) time(NULL);
+
+ srand(seed);
+}
+
int main(int argc, char *argv[]) {
gint r = 255;
const gchar *argv0;
gboolean wrote_pid_file = FALSE;
avahi_set_log_function(log_function);
+ avahi_set_allocator(avahi_glib_allocator());
+
+ init_rand_seed();
avahi_server_config_init(&config.server_config);
config.command = DAEMON_RUN;
else
argv0 = argv[0];
- daemon_pid_file_ident = daemon_log_ident = (char *) argv0;
+ daemon_pid_file_ident = (const char *) argv0;
+ daemon_log_ident = (char*) argv0;
daemon_pid_file_proc = pid_file_proc;
if (parse_command_line(&config, argc, argv) < 0)
/* Child */
}
+
+ printf("%s "PACKAGE_VERSION" starting up.\n", argv0);
+
chdir("/");
if (make_runtime_dir() < 0)