From 768d6a386735d3a0805547a2de728886f2aa8798 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 18 Jun 2005 16:18:49 +0000 Subject: * rename the configuration variables register_xxx and announce_xxx to publish_xxx * implement command line parsing and configuration file parsing * implement daemonizing support (partially) git-svn-id: file:///home/lennart/svn/public/avahi/trunk@127 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- avahi-core/avahi-reflector.c | 8 +- avahi-core/core.h | 12 +- avahi-core/iface.c | 4 +- avahi-core/server.c | 22 +-- avahi-daemon/Makefile.am | 7 +- avahi-daemon/avahi.conf | 18 +++ avahi-daemon/main.c | 346 +++++++++++++++++++++++++++++++++++++++---- avahi-discover/main.c | 2 +- 8 files changed, 364 insertions(+), 55 deletions(-) create mode 100644 avahi-daemon/avahi.conf diff --git a/avahi-core/avahi-reflector.c b/avahi-core/avahi-reflector.c index 60e19b6..7af0dd4 100644 --- a/avahi-core/avahi-reflector.c +++ b/avahi-core/avahi-reflector.c @@ -36,10 +36,10 @@ int main(int argc, char*argv[]) { GMainLoop *loop; avahi_server_config_init(&config); - config.register_hinfo = FALSE; - config.register_addresses = FALSE; - config.register_workstation = FALSE; - config.announce_domain = FALSE; + config.publish_hinfo = FALSE; + config.publish_addresses = FALSE; + config.publish_workstation = FALSE; + config.publish_domain = FALSE; config.use_ipv6 = FALSE; config.enable_reflector = TRUE; diff --git a/avahi-core/core.h b/avahi-core/core.h index 6e8d9dd..c9274c4 100644 --- a/avahi-core/core.h +++ b/avahi-core/core.h @@ -75,14 +75,14 @@ typedef struct AvahiServerConfig { gchar *domain_name; /**< Default domain name. If left empty defaults to .local */ gboolean use_ipv4; /**< Enable IPv4 support */ gboolean use_ipv6; /**< Enable IPv6 support */ - gboolean register_hinfo; /**< Register a HINFO record for the host containing the local OS and CPU type */ - gboolean register_addresses; /**< Register A, AAAA and PTR records for all local IP addresses */ - gboolean register_workstation; /**< Register a _workstation._tcp service */ + gboolean publish_hinfo; /**< Register a HINFO record for the host containing the local OS and CPU type */ + gboolean publish_addresses; /**< Register A, AAAA and PTR records for all local IP addresses */ + gboolean publish_workstation; /**< Register a _workstation._tcp service */ + gboolean publish_domain; /**< Announce the local domain for browsing */ gboolean check_response_ttl; /**< If enabled the server ignores all incoming responses with IP TTL != 255 */ - gboolean announce_domain; /**< Announce the local domain for browsing */ - gboolean use_iff_running; /**< Require IFF_RUNNING on local network interfaces. This is the official way to check for link beat. Unfortunately this doesn't work with all drivers. So bettere leave this off. */ + gboolean use_iff_running; /**< Require IFF_RUNNING on local network interfaces. This is the official way to check for link beat. Unfortunately this doesn't work with all drivers. So bettere leave this off. */ gboolean enable_reflector; /**< Reflect incoming mDNS traffic to all local networks. This allows mDNS based network browsing beyond ethernet borders */ - gboolean ipv_reflect; /**< if enable_reflector is TRUE, enable/disable reflecting between IPv4 and IPv6 */ + gboolean reflect_ipv; /**< if enable_reflector is TRUE, enable/disable reflecting between IPv4 and IPv6 */ } AvahiServerConfig; /** Allocate a new mDNS responder object. */ diff --git a/avahi-core/iface.c b/avahi-core/iface.c index 73f4cdf..7972a5c 100644 --- a/avahi-core/iface.c +++ b/avahi-core/iface.c @@ -45,7 +45,7 @@ static void update_address_rr(AvahiInterfaceMonitor *m, AvahiInterfaceAddress *a if (avahi_interface_address_relevant(a) && !remove && - m->server->config.register_addresses && + m->server->config.publish_addresses && (m->server->state == AVAHI_SERVER_RUNNING || m->server->state == AVAHI_SERVER_REGISTERING)) { @@ -87,7 +87,7 @@ static void update_hw_interface_rr(AvahiInterfaceMonitor *m, AvahiHwInterface *h update_interface_rr(m, i, remove); if (!remove && - m->server->config.register_workstation && + m->server->config.publish_workstation && (m->server->state == AVAHI_SERVER_RUNNING || m->server->state == AVAHI_SERVER_REGISTERING)) { diff --git a/avahi-core/server.c b/avahi-core/server.c index 1630b29..0c00658 100644 --- a/avahi-core/server.c +++ b/avahi-core/server.c @@ -484,7 +484,7 @@ static void reflect_response(AvahiServer *s, AvahiInterface *i, AvahiRecord *r, return; for (j = s->monitor->interfaces; j; j = j->interface_next) - if (j != i && (s->config.ipv_reflect || j->protocol == i->protocol)) + if (j != i && (s->config.reflect_ipv || j->protocol == i->protocol)) avahi_interface_post_response(j, r, flush_cache, NULL, TRUE); } @@ -511,7 +511,7 @@ static void reflect_query(AvahiServer *s, AvahiInterface *i, AvahiKey *k) { return; for (j = s->monitor->interfaces; j; j = j->interface_next) - if (j != i && (s->config.ipv_reflect || j->protocol == i->protocol)) { + if (j != i && (s->config.reflect_ipv || j->protocol == i->protocol)) { /* Post the query to other networks */ avahi_interface_post_query(j, k, TRUE); @@ -533,7 +533,7 @@ static void reflect_probe(AvahiServer *s, AvahiInterface *i, AvahiRecord *r) { return; for (j = s->monitor->interfaces; j; j = j->interface_next) - if (j != i && (s->config.ipv_reflect || j->protocol == i->protocol)) + if (j != i && (s->config.reflect_ipv || j->protocol == i->protocol)) avahi_interface_post_probe(j, r, TRUE); } @@ -775,7 +775,7 @@ static void reflect_legacy_unicast_query_packet(AvahiServer *s, AvahiDnsPacket * for (j = s->monitor->interfaces; j; j = j->interface_next) if (avahi_interface_relevant(j) && j != i && - (s->config.ipv_reflect || j->protocol == i->protocol)) { + (s->config.reflect_ipv || j->protocol == i->protocol)) { if (j->protocol == AF_INET && s->fd_legacy_unicast_ipv4 >= 0) { avahi_send_dns_packet_ipv4(s->fd_legacy_unicast_ipv4, j->hardware->index, p, NULL, 0); @@ -1105,7 +1105,7 @@ static void register_hinfo(AvahiServer *s) { g_assert(s); - if (!s->config.register_hinfo || s->hinfo_entry_group) + if (!s->config.publish_hinfo || s->hinfo_entry_group) return; s->hinfo_entry_group = avahi_entry_group_new(s, avahi_host_rr_entry_group_callback, NULL); @@ -1136,7 +1136,7 @@ static void register_localhost(AvahiServer *s) { static void register_browse_domain(AvahiServer *s) { g_assert(s); - if (!s->config.announce_domain || s->browse_domain_entry_group) + if (!s->config.publish_domain || s->browse_domain_entry_group) return; s->browse_domain_entry_group = avahi_entry_group_new(s, NULL, NULL); @@ -1870,18 +1870,18 @@ AvahiServerConfig* avahi_server_config_init(AvahiServerConfig *c) { g_assert(c); memset(c, 0, sizeof(AvahiServerConfig)); - c->register_hinfo = TRUE; - c->register_addresses = TRUE; c->use_ipv6 = TRUE; c->use_ipv4 = TRUE; c->host_name = NULL; c->domain_name = NULL; c->check_response_ttl = TRUE; - c->announce_domain = TRUE; + c->publish_hinfo = TRUE; + c->publish_addresses = TRUE; + c->publish_workstation = TRUE; + c->publish_domain = TRUE; c->use_iff_running = FALSE; c->enable_reflector = FALSE; - c->ipv_reflect = FALSE; - c->register_workstation = TRUE; + c->reflect_ipv = FALSE; return c; } diff --git a/avahi-daemon/Makefile.am b/avahi-daemon/Makefile.am index f90b16d..bb983a3 100644 --- a/avahi-daemon/Makefile.am +++ b/avahi-daemon/Makefile.am @@ -17,13 +17,18 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -AM_CFLAGS=-I$(top_srcdir) -D_GNU_SOURCE -DAVAHI_SERVICE_DIRECTORY=\"`pwd`\" +AM_CFLAGS=-I$(top_srcdir) -D_GNU_SOURCE -DAVAHI_SERVICE_DIRECTORY=\"`pwd`\" -DAVAHI_CONFIG_FILE=\"avahi.conf\" AM_LDADD=-lexpat # GLIB 2.0 AM_CFLAGS+=$(GLIB20_CFLAGS) AM_LDADD+=$(GLIB20_LIBS) +# libdaemon +AM_CFLAGS+=$(LIBDAEMON_CFLAGS) +AM_LDADD+=$(LIBDAEMON_LIBS) + + if ENABLE_DBUS # DBUS AM_CFLAGS+=$(DBUS_CFLAGS) diff --git a/avahi-daemon/avahi.conf b/avahi-daemon/avahi.conf new file mode 100644 index 0000000..900d04b --- /dev/null +++ b/avahi-daemon/avahi.conf @@ -0,0 +1,18 @@ +[server] +#host-name=foo +#domain-name=local +use-ipv4=yes +use-ipv6=no +check-response-ttl=yes +use-iff-running=yes +enable-dbus=yes + +[publish] +publish-addresses=yes +publish-hinfo=yes +publish-workstation=yes +publish-domain=yes + +[reflector] +enable-reflector=no +reflect-ipv=no diff --git a/avahi-daemon/main.c b/avahi-daemon/main.c index d59e9fb..4373f9a 100644 --- a/avahi-daemon/main.c +++ b/avahi-daemon/main.c @@ -23,19 +23,45 @@ #include #endif +#include +#include +#include + +#include +#include +#include +#include + #include +#include #include "main.h" #include "simple-protocol.h" +#include "dbus-protocol.h" #include "static-services.h" AvahiServer *avahi_server = NULL; +typedef enum { + DAEMON_RUN, + DAEMON_KILL, + DAEMON_VERSION, + DAEMON_HELP +} DaemonCommand; + +typedef struct { + AvahiServerConfig server_config; + DaemonCommand command; + gboolean daemonize; + gchar *config_file; + gboolean enable_dbus; +} DaemonConfig; + static void server_callback(AvahiServer *s, AvahiServerState state, gpointer userdata) { g_assert(s); if (state == AVAHI_SERVER_RUNNING) { - g_message("Server startup complete. Host name is <%s>", avahi_server_get_host_name_fqdn(s)); + avahi_log_info("Server startup complete. Host name is <%s>", avahi_server_get_host_name_fqdn(s)); static_service_add_to_server(); } else if (state == AVAHI_SERVER_COLLISION) { gchar *n; @@ -43,7 +69,7 @@ static void server_callback(AvahiServer *s, AvahiServerState state, gpointer use static_service_remove_from_server(); n = avahi_alternative_host_name(avahi_server_get_host_name(s)); - g_message("Host name conflict, retrying with <%s>", n); + avahi_log_warn("Host name conflict, retrying with <%s>", n); avahi_server_set_host_name(s, n); g_free(n); } @@ -52,64 +78,227 @@ static void server_callback(AvahiServer *s, AvahiServerState state, gpointer use static void help(FILE *f, const gchar *argv0) { fprintf(f, "%s [options]\n" - " -h --help Show this help\n" - " -D --daemon Daemonize after startup\n" - " -k --kill Kill a running daemon\n" - " -v --version Show version\n", + " -h --help Show this help\n" + " -D --daemonize Daemonize after startup\n" + " -k --kill Kill a running daemon\n" + " -V --version Show version\n" + " -f --file=FILE Load the specified configuration file instead of the default\n", argv0); } -static gint parse_command_line(AvahiServerConfig *config, int argc, char *argv[]) { +static gint parse_command_line(DaemonConfig *config, int argc, char *argv[]) { + gint c; + + static const struct option const long_options[] = { + { "help", no_argument, NULL, 'h' }, + { "daemonize", no_argument, NULL, 'D' }, + { "kill", no_argument, NULL, 'k' }, + { "version", no_argument, NULL, 'V' }, + { "file", required_argument, NULL, 'f' }, + }; - return 0; -} + g_assert(config); -static gint load_config_file(AvahiServerConfig *config) { + opterr = 0; + while ((c = getopt_long(argc, argv, "hDkVf:", long_options, NULL)) >= 0) { + switch(c) { + case 'h': + config->command = DAEMON_HELP; + break; + case 'D': + config->daemonize = TRUE; + break; + case 'k': + config->command = DAEMON_KILL; + break; + case 'V': + config->command = DAEMON_VERSION; + break; + case 'f': + g_free(config->config_file); + config->config_file = g_strdup(optarg); + break; + default: + fprintf(stderr, "Invalid command line argument: %c\n", c); + return -1; + } + } + + if (optind < argc) { + fprintf(stderr, "Too many arguments\n"); + return -1; + } + return 0; } -int main(int argc, char *argv[]) { - GMainLoop *loop = NULL; - gint r = 255; - AvahiServerConfig config; +static gboolean is_yes(const gchar *s) { + g_assert(s); + + return *s == 'y' || *s == 'Y'; +} - avahi_server_config_init(&config); +static gint load_config_file(DaemonConfig *config) { + int r = -1; + GKeyFile *f = NULL; + GError *err = NULL; + gchar **groups = NULL, **g, **keys = NULL; - if (load_config_file(&config) < 0) + g_assert(config); + + f = g_key_file_new(); + + if (!g_key_file_load_from_file(f, config->config_file ? config->config_file : AVAHI_CONFIG_FILE, G_KEY_FILE_NONE, &err)) { + fprintf(stderr, "Unable to read config file: %s\n", err->message); goto finish; + } - if (parse_command_line(&config, argc, argv) < 0) - goto finish; + groups = g_key_file_get_groups(f, NULL); + + for (g = groups; *g; g++) { + if (g_strcasecmp(*g, "server") == 0) { + gchar **k; + + keys = g_key_file_get_keys(f, *g, NULL, NULL); + + for (k = keys; *k; k++) { + if (g_strcasecmp(*k, "host-name") == 0) { + g_free(config->server_config.host_name); + config->server_config.host_name = g_strdup(g_key_file_get_string(f, *g, *k, NULL)); + } else if (g_strcasecmp(*k, "domain-name") == 0) { + g_free(config->server_config.domain_name); + config->server_config.domain_name = g_strdup(g_key_file_get_string(f, *g, *k, NULL)); + } else if (g_strcasecmp(*k, "use-ipv4") == 0) + config->server_config.use_ipv4 = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + else if (g_strcasecmp(*k, "use-ipv6") == 0) + config->server_config.use_ipv6 = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + else if (g_strcasecmp(*k, "check-response-ttl") == 0) + config->server_config.check_response_ttl = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + else if (g_strcasecmp(*k, "use-iff-running") == 0) + config->server_config.use_iff_running = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + else if (g_strcasecmp(*k, "enable-dbus") == 0) + config->enable_dbus = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + else { + fprintf(stderr, "Invalid configuration key \"%s\" in group \"%s\"\n", *k, *g); + goto finish; + } + } + + } else if (g_strcasecmp(*g, "publish") == 0) { + gchar **k; + + keys = g_key_file_get_keys(f, *g, NULL, NULL); + + for (k = keys; *k; k++) { + if (g_strcasecmp(*k, "publish-addresses") == 0) + config->server_config.publish_addresses = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + else if (g_strcasecmp(*k, "publish-hinfo") == 0) + config->server_config.publish_hinfo = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + else if (g_strcasecmp(*k, "publish-workstation") == 0) + config->server_config.publish_workstation = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + else if (g_strcasecmp(*k, "publish-domain") == 0) + config->server_config.publish_domain = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + else { + fprintf(stderr, "Invalid configuration key \"%s\" in group \"%s\"\n", *k, *g); + goto finish; + } + } + + } else if (g_strcasecmp(*g, "reflector") == 0) { + gchar **k; + + keys = g_key_file_get_keys(f, *g, NULL, NULL); + + for (k = keys; *k; k++) { + if (g_strcasecmp(*k, "enable-reflector") == 0) + config->server_config.enable_reflector = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + else if (g_strcasecmp(*k, "reflect-ipv") == 0) + config->server_config.reflect_ipv = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + else { + fprintf(stderr, "Invalid configuration key \"%s\" in group \"%s\"\n", *k, *g); + goto finish; + } + } - loop = g_main_loop_new(NULL, FALSE); + } else { + fprintf(stderr, "Invalid configuration file group \"%s\".\n", *g); + goto finish; + } + } + + r = 0; + +finish: + + g_strfreev(groups); + g_strfreev(keys); + + if (err) + g_error_free (err); + + if (f) + g_key_file_free(f); + + return r; +} + +static void log_function(AvahiLogLevel level, const gchar *txt) { + + static const int const log_level_map[] = { + LOG_ERR, + LOG_WARNING, + LOG_NOTICE, + LOG_INFO, + LOG_DEBUG + }; + + g_assert(level < AVAHI_LOG_LEVEL_MAX); + g_assert(txt); + daemon_log(log_level_map[level], "%s", txt); +} + +static gint run_server(DaemonConfig *config) { + GMainLoop *loop = NULL; + gint r = -1; + + g_assert(config); + + loop = g_main_loop_new(NULL, FALSE); + if (simple_protocol_setup(NULL) < 0) goto finish; - + #ifdef ENABLE_DBUS - if (dbus_protocol_setup (loop) < 0) - goto finish; + if (config->enable_dbus) + if (dbus_protocol_setup(loop) < 0) + goto finish; #endif - - if (!(avahi_server = avahi_server_new(NULL, &config, server_callback, NULL))) + + if (!(avahi_server = avahi_server_new(NULL, &config->server_config, server_callback, NULL))) goto finish; - + static_service_load(); + if (config->daemonize) { + daemon_retval_send(0); + r = 0; + } + g_main_loop_run(loop); - r = 0; - -finish: +finish: + static_service_remove_from_server(); static_service_free_all(); simple_protocol_shutdown(); #ifdef ENABLE_DBUS - dbus_protocol_shutdown(); + if (config->enable_dbus) + dbus_protocol_shutdown(); #endif if (avahi_server) @@ -118,7 +307,104 @@ finish: if (loop) g_main_loop_unref(loop); - avahi_server_config_free(&config); + if (r != 0 && config->daemonize) + daemon_retval_send(0); + + return r; +} + +int main(int argc, char *argv[]) { + gint r = 255; + DaemonConfig config; + const gchar *argv0; + gboolean wrote_pid_file = FALSE; + + avahi_set_log_function(log_function); + + avahi_server_config_init(&config.server_config); + config.command = DAEMON_RUN; + config.daemonize = FALSE; + config.config_file = NULL; + config.enable_dbus = TRUE; + + if ((argv0 = strrchr(argv[0], '/'))) + argv0++; + else + argv0 = argv[0]; + daemon_pid_file_ident = daemon_log_ident = (char *) argv0; + + if (parse_command_line(&config, argc, argv) < 0) + goto finish; + + if (load_config_file(&config) < 0) + goto finish; + + if (config.command == DAEMON_HELP) { + help(stdout, argv0); + r = 0; + } else if (config.command == DAEMON_VERSION) { + printf("%s "PACKAGE_VERSION"\n", argv0); + + } else if (config.command == DAEMON_KILL) { + if (daemon_pid_file_kill_wait(SIGTERM, 5) < 0) { + avahi_log_warn("Failed to kill daemon"); + goto finish; + } + + r = 0; + + } else if (config.command == DAEMON_RUN) { + pid_t pid; + + if ((pid = daemon_pid_file_is_running()) >= 0) { + avahi_log_error("Daemon already running on PID %u", pid); + goto finish; + } + + if (config.daemonize) { + + daemon_retval_init(); + + if ((pid = daemon_fork()) < 0) + goto finish; + else if (pid != 0) { + int ret; + /** Parent **/ + + if ((ret = daemon_retval_wait(20)) < 0) { + avahi_log_error("Could not recieve return value from daemon process."); + goto finish; + } + + r = ret; + goto finish; + } + + /* Child */ + } + + if (daemon_pid_file_create() < 0) { + avahi_log_error("Failed to create PID file."); + daemon_retval_send(1); + goto finish; + } else + wrote_pid_file = TRUE; + + if (run_server(&config) == 0) + r = 0; + } + +finish: + + if (config.daemonize) + daemon_retval_done(); + + avahi_server_config_free(&config.server_config); + g_free(config.config_file); + + if (wrote_pid_file) + daemon_pid_file_remove(); + return r; } diff --git a/avahi-discover/main.c b/avahi-discover/main.c index f8cb953..557ad41 100644 --- a/avahi-discover/main.c +++ b/avahi-discover/main.c @@ -270,7 +270,7 @@ int main(int argc, char *argv[]) { service_type_hash_table = g_hash_table_new((GHashFunc) avahi_domain_hash, (GEqualFunc) avahi_domain_equal); avahi_server_config_init(&config); - config.register_hinfo = config.register_addresses = config.announce_domain = config.register_workstation = FALSE; + config.publish_hinfo = config.publish_addresses = config.publish_domain = config.publish_workstation = FALSE; server = avahi_server_new(NULL, &config, NULL, NULL); avahi_server_config_free(&config); -- cgit