X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=avahi-daemon%2Fmain.c;h=460a9d63da253e9096458d9072df8f00339aee23;hb=b671bd2201bf8e0a0af9f8da72ae80c3218d3000;hp=6d8abb153e98eccc83297568575f02c28e9b49e4;hpb=9d709a294b81066a0942a7a642df1b3d4940ad26;p=catta diff --git a/avahi-daemon/main.c b/avahi-daemon/main.c index 6d8abb1..460a9d6 100644 --- a/avahi-daemon/main.c +++ b/avahi-daemon/main.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +42,20 @@ #include #include +#ifdef HAVE_INOTIFY +#ifdef HAVE_SYS_INOTIFY_H +#include +#else +#include "inotify-nosys.h" +#endif +#endif + +#ifdef HAVE_KQUEUE +#include +#include +#include +#endif + #include #include #include @@ -379,7 +394,6 @@ static int parse_command_line(DaemonConfig *c, int argc, char *argv[]) { assert(c); - opterr = 0; while ((o = getopt_long(argc, argv, "hDkVf:rcs", long_options, NULL)) >= 0) { switch(o) { @@ -426,7 +440,6 @@ static int parse_command_line(DaemonConfig *c, int argc, char *argv[]) { c->debug = 1; break; default: - fprintf(stderr, "Invalid command line argument: %c\n", o); return -1; } } @@ -442,7 +455,7 @@ static int parse_command_line(DaemonConfig *c, int argc, char *argv[]) { static int is_yes(const char *s) { assert(s); - return *s == 'y' || *s == 'Y'; + return *s == 'y' || *s == 'Y' || *s == '1' || *s == 't' || *s == 'T'; } static int load_config_file(DaemonConfig *c) { @@ -541,8 +554,12 @@ static int load_config_file(DaemonConfig *c) { c->server_config.add_service_cookie = is_yes(p->value); else if (strcasecmp(p->key, "publish-dns-servers") == 0) { avahi_strfreev(c->publish_dns_servers); - c->publish_dns_servers = avahi_split_csv(p->value); - } else { + c->publish_dns_servers = avahi_split_csv(p->value); + } else if (strcasecmp(p->key, "publish-a-on-ipv6") == 0) + c->server_config.publish_a_on_ipv6 = is_yes(p->value); + else if (strcasecmp(p->key, "publish-aaaa-on-ipv4") == 0) + c->server_config.publish_aaaa_on_ipv4 = is_yes(p->value); + else { avahi_log_error("Invalid configuration key \"%s\" in group \"%s\"\n", p->key, g->name); goto finish; } @@ -652,6 +669,165 @@ static void dump(const char *text, AVAHI_GCC_UNUSED void* userdata) { avahi_log_info("%s", text); } +#ifdef HAVE_INOTIFY + +static int inotify_fd = -1; + +static void add_inotify_watches(void) { + int c = 0; + /* We ignore the return values, because one or more of these files + * might not exist and we're OK with that. In addition we never + * want to remove these watches, hence we keep their ids? */ + +#ifdef ENABLE_CHROOT + c = config.use_chroot; +#endif + + inotify_add_watch(inotify_fd, c ? "/services" : AVAHI_SERVICE_DIR, IN_CLOSE_WRITE|IN_DELETE|IN_DELETE_SELF|IN_MOVED_FROM|IN_MOVED_TO|IN_MOVE_SELF +#ifdef IN_ONLYDIR + |IN_ONLYDIR +#endif + ); + inotify_add_watch(inotify_fd, c ? "/" : AVAHI_CONFIG_DIR, IN_CLOSE_WRITE|IN_DELETE|IN_DELETE_SELF|IN_MOVED_FROM|IN_MOVED_TO|IN_MOVE_SELF +#ifdef IN_ONLYDIR + |IN_ONLYDIR +#endif + ); +} + +#endif + +#ifdef HAVE_KQUEUE + +#define NUM_WATCHES 2 + +static int kq = -1; +static int kfds[NUM_WATCHES]; +static int num_kfds = 0; + +static void add_kqueue_watch(const char *dir); + +static void add_kqueue_watches(void) { + int c = 0; + +#ifdef ENABLE_CHROOT + c = config.use_chroot; +#endif + + add_kqueue_watch(c ? "/" : AVAHI_CONFIG_DIR); + add_kqueue_watch(c ? "/services" : AVAHI_SERVICE_DIR); +} + +static void add_kqueue_watch(const char *dir) { + int fd; + struct kevent ev; + + if (kq < 0) + return; + + if (num_kfds >= NUM_WATCHES) + return; + + fd = open(dir, O_RDONLY); + if (fd < 0) + return; + EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, + NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_RENAME, + 0, 0); + if (kevent(kq, &ev, 1, NULL, 0, NULL) == -1) { + close(fd); + return; + } + + kfds[num_kfds++] = fd; +} + +#endif + +static void reload_config(void) { + +#ifdef HAVE_INOTIFY + /* Refresh in case the config dirs have been removed */ + add_inotify_watches(); +#endif + +#ifdef HAVE_KQUEUE + add_kqueue_watches(); +#endif + +#ifdef ENABLE_CHROOT + static_service_load(config.use_chroot); + static_hosts_load(config.use_chroot); +#else + static_service_load(0); + static_hosts_load(0); +#endif + static_service_add_to_server(); + static_hosts_add_to_server(); + + if (resolv_conf_entry_group) + avahi_s_entry_group_reset(resolv_conf_entry_group); + + load_resolv_conf(); + + update_wide_area_servers(); + + if (config.publish_resolv_conf && resolv_conf && resolv_conf[0]) + resolv_conf_entry_group = add_dns_servers(avahi_server, resolv_conf_entry_group, resolv_conf); +} + +#ifdef HAVE_INOTIFY + +static void inotify_callback(AvahiWatch *watch, int fd, AVAHI_GCC_UNUSED AvahiWatchEvent event, AVAHI_GCC_UNUSED void *userdata) { + char* buffer; + int n = 0; + + assert(fd == inotify_fd); + assert(watch); + + ioctl(inotify_fd, FIONREAD, &n); + if (n <= 0) + n = 128; + + buffer = avahi_malloc(n); + if (read(inotify_fd, buffer, n) < 0 ) { + avahi_free(buffer); + avahi_log_error("Failed to read inotify event: %s", avahi_strerror(errno)); + return; + } + avahi_free(buffer); + + avahi_log_info("Files changed, reloading."); + reload_config(); +} + +#endif + +#ifdef HAVE_KQUEUE + +static void kqueue_callback(AvahiWatch *watch, int fd, AVAHI_GCC_UNUSED AvahiWatchEvent event, AVAHI_GCC_UNUSED void *userdata) { + struct kevent ev; + struct timespec nullts = { 0, 0 }; + int res; + + assert(fd == kq); + assert(watch); + + res = kevent(kq, NULL, 0, &ev, 1, &nullts); + + if (res > 0) { + /* Sleep for a half-second to avoid potential races + * during install/uninstall. */ + usleep(500000); + avahi_log_info("Files changed, reloading."); + reload_config(); + } else { + avahi_log_error("Failed to read kqueue event: %s", avahi_strerror(errno)); + } +} + +#endif + static void signal_callback(AvahiWatch *watch, AVAHI_GCC_UNUSED int fd, AVAHI_GCC_UNUSED AvahiWatchEvent event, AVAHI_GCC_UNUSED void *userdata) { int sig; const AvahiPoll *poll_api; @@ -680,26 +856,8 @@ static void signal_callback(AvahiWatch *watch, AVAHI_GCC_UNUSED int fd, AVAHI_GC case SIGHUP: avahi_log_info("Got SIGHUP, reloading."); -#ifdef ENABLE_CHROOT - static_service_load(config.use_chroot); - static_hosts_load(config.use_chroot); -#else - static_service_load(0); - static_hosts_load(0); -#endif - static_service_add_to_server(); - static_hosts_add_to_server(); - - if (resolv_conf_entry_group) - avahi_s_entry_group_reset(resolv_conf_entry_group); - - load_resolv_conf(); - - update_wide_area_servers(); - - if (config.publish_resolv_conf && resolv_conf && resolv_conf[0]) - resolv_conf_entry_group = add_dns_servers(avahi_server, resolv_conf_entry_group, resolv_conf); + reload_config(); break; case SIGUSR1: @@ -722,6 +880,13 @@ static int run_server(DaemonConfig *c) { const AvahiPoll *poll_api = NULL; AvahiWatch *sig_watch = NULL; int retval_is_sent = 0; +#ifdef HAVE_INOTIFY + AvahiWatch *inotify_watch = NULL; +#endif +#ifdef HAVE_KQUEUE + int i; + AvahiWatch *kqueue_watch = NULL; +#endif assert(c); @@ -784,6 +949,32 @@ static int run_server(DaemonConfig *c) { #endif +#ifdef HAVE_INOTIFY + if ((inotify_fd = inotify_init()) < 0) + avahi_log_warn( "Failed to initialize inotify: %s", strerror(errno)); + else { + add_inotify_watches(); + + if (!(inotify_watch = poll_api->watch_new(poll_api, inotify_fd, AVAHI_WATCH_IN, inotify_callback, NULL))) { + avahi_log_error( "Failed to create inotify watcher"); + goto finish; + } + } +#endif + +#ifdef HAVE_KQUEUE + if ((kq = kqueue()) < 0) + avahi_log_warn( "Failed to initialize kqueue: %s", strerror(errno)); + else { + add_kqueue_watches(); + + if (!(kqueue_watch = poll_api->watch_new(poll_api, kq, AVAHI_WATCH_IN, kqueue_callback, NULL))) { + avahi_log_error( "Failed to create kqueue watcher"); + goto finish; + } + } +#endif + load_resolv_conf(); #ifdef ENABLE_CHROOT static_service_load(config.use_chroot); @@ -847,6 +1038,24 @@ finish: if (sig_watch) poll_api->watch_free(sig_watch); +#ifdef HAVE_INOTIFY + if (inotify_watch) + poll_api->watch_free(inotify_watch); + if (inotify_fd >= 0) + close(inotify_fd); +#endif + +#ifdef HAVE_KQUEUE + if (kqueue_watch) + poll_api->watch_free(kqueue_watch); + if (kq >= 0) + close(kq); + for (i = 0; i < num_kfds; i++) { + if (kfds[i] >= 0) + close(kfds[i]); + } +#endif + if (simple_poll_api) { avahi_simple_poll_free(simple_poll_api); simple_poll_api = NULL; @@ -1150,6 +1359,11 @@ int main(int argc, char *argv[]) { if (config.use_syslog || config.daemonize) daemon_log_use = DAEMON_LOG_SYSLOG; + if (daemon_close_all(-1) < 0) { + avahi_log_error("Failed to close remaining file descriptors: %s", strerror(errno)); + goto finish; + } + if (make_runtime_dir() < 0) goto finish;