]> git.meshlink.io Git - catta/commitdiff
* rename the configuration variables register_xxx and announce_xxx to publish_xxx
authorLennart Poettering <lennart@poettering.net>
Sat, 18 Jun 2005 16:18:49 +0000 (16:18 +0000)
committerLennart Poettering <lennart@poettering.net>
Sat, 18 Jun 2005 16:18:49 +0000 (16:18 +0000)
* 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
avahi-core/core.h
avahi-core/iface.c
avahi-core/server.c
avahi-daemon/Makefile.am
avahi-daemon/avahi.conf [new file with mode: 0644]
avahi-daemon/main.c
avahi-discover/main.c

index 60e19b67cdc8561624fc9e5bf2abcf8eefbf14ca..7af0dd40aa0541276ef8f2cc923b2e1d3de1bdd3 100644 (file)
@@ -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;
     
index 6e8d9ddb7ec42e0204c9abe69123ced2e52e4c4c..c9274c47ad2c59fdba386cdbbb0305b4cf8509d9 100644 (file)
@@ -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. */
index 73f4cdf5c5d232caa4b6496334bfbc85c0de39bf..7972a5c02e3ff3bf4403624fe2ffeac4f216458b 100644 (file)
@@ -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)) {
 
index 1630b29098b85ca4a1cfd91c86cef69afc294dcb..0c0065809bcbf87c2155bed994f9e89ff393a055 100644 (file)
@@ -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;
 }
index f90b16d9c7a657bea5d04ee5b2d471f6fc23d33b..bb983a37b032c9164512c477ae699a72cfc25984 100644 (file)
 # 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 (file)
index 0000000..900d04b
--- /dev/null
@@ -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
index d59e9fb3df2ffe1d62418f8a39ec6d3a73ad5ba2..4373f9af8bc122732e9ea7f7dd81b7fee4d4ab0b 100644 (file)
 #include <config.h>
 #endif
 
+#include <getopt.h>
+#include <string.h>
+#include <signal.h>
+
+#include <libdaemon/dfork.h>
+#include <libdaemon/dsignal.h>
+#include <libdaemon/dlog.h>
+#include <libdaemon/dpid.h>
+
 #include <avahi-core/core.h>
+#include <avahi-core/log.h>
 
 #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;
 }
index f8cb9536824dc8612c8f315dc459d841933e1210..557ad418d847c1cbbf55fc246ef97b8401ac2c0f 100644 (file)
@@ -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);