Ejemplo n.º 1
0
static int load_config_file(DaemonConfig *c) {
    int r = -1;
    AvahiIniFile *f;
    AvahiIniFileGroup *g;

    assert(c);

    if (!(f = avahi_ini_file_load(c->config_file ? c->config_file : AVAHI_CONFIG_FILE)))
        goto finish;
    
    for (g = f->groups; g; g = g->groups_next) {
        
        if (strcasecmp(g->name, "server") == 0) {
            AvahiIniFilePair *p;

            for (p = g->pairs; p; p = p->pairs_next) {

                if (strcasecmp(p->key, "host-name") == 0) {
                    avahi_free(c->server_config.host_name);
                    c->server_config.host_name = avahi_strdup(p->value);
                } else if (strcasecmp(p->key, "domain-name") == 0) {
                    avahi_free(c->server_config.domain_name);
                    c->server_config.domain_name = avahi_strdup(p->value);
                } else if (strcasecmp(p->key, "browse-domains") == 0) {
                    char **e, **t;

                    e = avahi_split_csv(p->value);
                    
                    for (t = e; *t; t++) {
                        char cleaned[AVAHI_DOMAIN_NAME_MAX];

                        if (!avahi_normalize_name(*t, cleaned, sizeof(cleaned))) {
                            avahi_log_error("Invalid domain name \"%s\" for key \"%s\" in group \"%s\"\n", *t, p->key, g->name);
                            avahi_strfreev(e);
                            goto finish;
                        }

                        c->server_config.browse_domains = avahi_string_list_add(c->server_config.browse_domains, cleaned);
                    }
                    
                    avahi_strfreev(e);

                    c->server_config.browse_domains = filter_duplicate_domains(c->server_config.browse_domains);
                } else if (strcasecmp(p->key, "use-ipv4") == 0)
                    c->server_config.use_ipv4 = is_yes(p->value);
                else if (strcasecmp(p->key, "use-ipv6") == 0)
                    c->server_config.use_ipv6 = is_yes(p->value);
                else if (strcasecmp(p->key, "check-response-ttl") == 0)
                    c->server_config.check_response_ttl = is_yes(p->value);
                else if (strcasecmp(p->key, "allow-point-to-point") == 0)
                    c->server_config.allow_point_to_point = is_yes(p->value);
                else if (strcasecmp(p->key, "use-iff-running") == 0)
                    c->server_config.use_iff_running = is_yes(p->value);
                else if (strcasecmp(p->key, "disallow-other-stacks") == 0)
                    c->server_config.disallow_other_stacks = is_yes(p->value);
#ifdef HAVE_DBUS
                else if (strcasecmp(p->key, "enable-dbus") == 0) {

                    if (*(p->value) == 'w' || *(p->value) == 'W') {
                        c->fail_on_missing_dbus = 0;
                        c->enable_dbus = 1;
                    } else if (*(p->value) == 'y' || *(p->value) == 'Y') {
                        c->fail_on_missing_dbus = 1;
                        c->enable_dbus = 1;
                    } else {
                        c->enable_dbus = 0;
                    }
                }
#endif
                else {
                    avahi_log_error("Invalid configuration key \"%s\" in group \"%s\"\n", p->key, g->name);
                    goto finish;
                }
            }
            
        } else if (strcasecmp(g->name, "publish") == 0) {
            AvahiIniFilePair *p;

            for (p = g->pairs; p; p = p->pairs_next) {
                
                if (strcasecmp(p->key, "publish-addresses") == 0)
                    c->server_config.publish_addresses = is_yes(p->value);
                else if (strcasecmp(p->key, "publish-hinfo") == 0)
                    c->server_config.publish_hinfo = is_yes(p->value);
                else if (strcasecmp(p->key, "publish-workstation") == 0)
                    c->server_config.publish_workstation = is_yes(p->value);
                else if (strcasecmp(p->key, "publish-domain") == 0)
                    c->server_config.publish_domain = is_yes(p->value);
                else if (strcasecmp(p->key, "publish-resolv-conf-dns-servers") == 0)
                    c->publish_resolv_conf = is_yes(p->value);
                else if (strcasecmp(p->key, "disable-publishing") == 0)
                    c->server_config.disable_publishing = is_yes(p->value);
                else if (strcasecmp(p->key, "disable-user-service-publishing") == 0)
                    c->disable_user_service_publishing = is_yes(p->value);
                else if (strcasecmp(p->key, "add-service-cookie") == 0)
                    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 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;
                }
            }

        } else if (strcasecmp(g->name, "wide-area") == 0) {
            AvahiIniFilePair *p;

            for (p = g->pairs; p; p = p->pairs_next) {
                
                if (strcasecmp(p->key, "enable-wide-area") == 0)
                    c->server_config.enable_wide_area = is_yes(p->value);
                else {
                    avahi_log_error("Invalid configuration key \"%s\" in group \"%s\"\n", p->key, g->name);
                    goto finish;
                }
            }
            
        } else if (strcasecmp(g->name, "reflector") == 0) {
            AvahiIniFilePair *p;

            for (p = g->pairs; p; p = p->pairs_next) {
                
                if (strcasecmp(p->key, "enable-reflector") == 0)
                    c->server_config.enable_reflector = is_yes(p->value);
                else if (strcasecmp(p->key, "reflect-ipv") == 0)
                    c->server_config.reflect_ipv = is_yes(p->value);
                else {
                    avahi_log_error("Invalid configuration key \"%s\" in group \"%s\"\n", p->key, g->name);
                    goto finish;
                }
            }
            
        } else if (strcasecmp(g->name, "rlimits") == 0) {
            AvahiIniFilePair *p;

            for (p = g->pairs; p; p = p->pairs_next) {
                
                if (strcasecmp(p->key, "rlimit-as") == 0) {
                    c->rlimit_as_set = 1;
                    c->rlimit_as = atoi(p->value);
                } else if (strcasecmp(p->key, "rlimit-core") == 0) {
                    c->rlimit_core_set = 1;
                    c->rlimit_core = atoi(p->value);
                } else if (strcasecmp(p->key, "rlimit-data") == 0) {
                    c->rlimit_data_set = 1;
                    c->rlimit_data = atoi(p->value);
                } else if (strcasecmp(p->key, "rlimit-fsize") == 0) {
                    c->rlimit_fsize_set = 1;
                    c->rlimit_fsize = atoi(p->value);
                } else if (strcasecmp(p->key, "rlimit-nofile") == 0) {
                    c->rlimit_nofile_set = 1;
                    c->rlimit_nofile = atoi(p->value);
                } else if (strcasecmp(p->key, "rlimit-stack") == 0) {
                    c->rlimit_stack_set = 1;
                    c->rlimit_stack = atoi(p->value);
                } else if (strcasecmp(p->key, "rlimit-nproc") == 0) {
#ifdef RLIMIT_NPROC
                    c->rlimit_nproc_set = 1;
                    c->rlimit_nproc = atoi(p->value);
#else
                    avahi_log_error("Ignoring configuration key \"%s\" in group \"%s\"\n", p->key, g->name);
#endif
                } else {
                    avahi_log_error("Invalid configuration key \"%s\" in group \"%s\"\n", p->key, g->name);
                    goto finish;
                }

            }
            
        } else {
            avahi_log_error("Invalid configuration file group \"%s\".\n", g->name);
            goto finish;
        }
    }

    r = 0;

finish:

    if (f)
        avahi_ini_file_free(f);
    
    return r;
}
Ejemplo n.º 2
0
char *avahi_alternative_service_name(const char *s) {
    const char *e;
    char *r;

    assert(s);

    if (!avahi_is_valid_service_name(s))
        return NULL;
    
    if ((e = strstr(s, " #"))) {
        const char *n, *p;
        e += 2;
    
        while ((n = strstr(e, " #")))
            e = n + 2;

        for (p = e; *p; p++)
            if (!isdigit(*p)) {
                e = NULL;
                break;
            }

        if (e && (*e == '0' || *e == 0))
            e = NULL;
    }
    
    if (e) {
        char *c, *m;
        size_t l;
        int n;

        n = atoi(e)+1;
        if (!(m = avahi_strdup_printf("%i", n)))
            return NULL;

        l = e-s-2;

        if (l >= AVAHI_LABEL_MAX-1-strlen(m)-2)
            l = AVAHI_LABEL_MAX-1-strlen(m)-2;

        if (!(c = avahi_strndup(s, l))) {
            avahi_free(m);
            return NULL;
        }

        drop_incomplete_utf8(c);
        
        r = avahi_strdup_printf("%s #%s", c, m);
        avahi_free(c);
        avahi_free(m);
    } else {
        char *c;

        if (!(c = avahi_strndup(s, AVAHI_LABEL_MAX-1-3)))
            return NULL;
        
        drop_incomplete_utf8(c);
        
        r = avahi_strdup_printf("%s #2", c);
        avahi_free(c);
    }

    assert(avahi_is_valid_service_name(r));
    
    return r;
}
Ejemplo n.º 3
0
static void server_callback(AvahiServer *s, AvahiServerState state, void *userdata) {
    DaemonConfig *c = userdata;
    
    assert(s);
    assert(c);

    /* This function is possibly called before the global variable
     * avahi_server has been set, therefore we do it explicitly */

    avahi_server = s;
    
#ifdef HAVE_DBUS
    if (c->enable_dbus && state != AVAHI_SERVER_INVALID && state != AVAHI_SERVER_FAILURE)
        dbus_protocol_server_state_changed(state);
#endif

    switch (state) {
        case AVAHI_SERVER_RUNNING:
            avahi_log_info("Server startup complete. Host name is %s. Local service cookie is %u.", avahi_server_get_host_name_fqdn(s), avahi_server_get_local_service_cookie(s));
            
            avahi_set_proc_title(argv0, "%s: running [%s]", argv0, avahi_server_get_host_name_fqdn(s));
            
            static_service_add_to_server();
            static_hosts_add_to_server();
            
            remove_dns_server_entry_groups();
            
            if (c->publish_resolv_conf && resolv_conf_name_servers && resolv_conf_name_servers[0])
                resolv_conf_entry_group = add_dns_servers(s, resolv_conf_entry_group, resolv_conf_name_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();
            break;
            
        case AVAHI_SERVER_COLLISION: {
            char *n;
            
            avahi_set_proc_title(argv0, "%s: collision", argv0);
            
            static_service_remove_from_server();
            static_hosts_remove_from_server();
            remove_dns_server_entry_groups();

            n = avahi_alternative_host_name(avahi_server_get_host_name(s));
            avahi_log_warn("Host name conflict, retrying with <%s>", n);
            avahi_server_set_host_name(s, n);
            avahi_free(n);

            break;
        }

        case AVAHI_SERVER_FAILURE:

            avahi_log_error("Server error: %s", avahi_strerror(avahi_server_errno(s)));
            avahi_simple_poll_quit(simple_poll_api);
            break;

        case AVAHI_SERVER_REGISTERING:

            avahi_set_proc_title(argv0, "%s: registering [%s]", argv0, avahi_server_get_host_name_fqdn(s));
            
            static_service_remove_from_server();
            static_hosts_remove_from_server();
            remove_dns_server_entry_groups();
            
            break;

        case AVAHI_SERVER_INVALID:
            break;
            
    }
}
Ejemplo n.º 4
0
static int parse_command_line(DaemonConfig *c, int argc, char *argv[]) {
    int o;

    enum {
        OPTION_NO_RLIMITS = 256,
        OPTION_NO_DROP_ROOT,
#ifdef ENABLE_CHROOT        
        OPTION_NO_CHROOT,
#endif
        OPTION_NO_PROC_TITLE,
        OPTION_DEBUG
    };
    
    static const struct option 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' },
        { "reload",         no_argument,       NULL, 'r' },
        { "check",          no_argument,       NULL, 'c' },
        { "syslog",         no_argument,       NULL, 's' },
        { "no-rlimits",     no_argument,       NULL, OPTION_NO_RLIMITS },
        { "no-drop-root",   no_argument,       NULL, OPTION_NO_DROP_ROOT },
#ifdef ENABLE_CHROOT
        { "no-chroot",      no_argument,       NULL, OPTION_NO_CHROOT },
#endif
        { "no-proc-title",  no_argument,       NULL, OPTION_NO_PROC_TITLE },
        { "debug",          no_argument,       NULL, OPTION_DEBUG },
        { NULL, 0, NULL, 0 }
    };

    assert(c);

    while ((o = getopt_long(argc, argv, "hDkVf:rcs", long_options, NULL)) >= 0) {

        switch(o) {
            case 's':
                c->use_syslog = 1;
                break;
            case 'h':
                c->command = DAEMON_HELP;
                break;
            case 'D':
                c->daemonize = 1;
                break;
            case 'k':
                c->command = DAEMON_KILL;
                break;
            case 'V':
                c->command = DAEMON_VERSION;
                break;
            case 'f':
                avahi_free(c->config_file);
                c->config_file = avahi_strdup(optarg);
                break;
            case 'r':
                c->command = DAEMON_RELOAD;
                break;
            case 'c':
                c->command = DAEMON_CHECK;
                break;
            case OPTION_NO_RLIMITS:
                c->set_rlimits = 0;
                break;
            case OPTION_NO_DROP_ROOT:
                c->drop_root = 0;
                break;
#ifdef ENABLE_CHROOT
            case OPTION_NO_CHROOT:
                c->use_chroot = 0;
                break;
#endif
            case OPTION_NO_PROC_TITLE:
                c->modify_proc_title = 0;
                break;
            case OPTION_DEBUG:
                c->debug = 1;
                break;
            default:
                return -1;
        }
    }

    if (optind < argc) {
        fprintf(stderr, "Too many arguments\n");
        return -1;
    }
        
    return 0;
}
Ejemplo n.º 5
0
void avahi_llmnr_query_scheduler_free(AvahiLLMNRQueryScheduler *s) {
    assert(s);

    avahi_llmnr_query_scheduler_clear(s);
    avahi_free(s);
}
Ejemplo n.º 6
0
int main(int argc, char *argv[]) {
    int r = 255;
    int wrote_pid_file = 0;

    avahi_set_log_function(log_function);

    init_rand_seed();
    
    avahi_server_config_init(&config.server_config);
    config.command = DAEMON_RUN;
    config.daemonize = 0;
    config.config_file = NULL;
#ifdef HAVE_DBUS
    config.enable_dbus = 1;
    config.fail_on_missing_dbus = 1;
#endif
    
    config.drop_root = 1;
    config.set_rlimits = 1;
#ifdef ENABLE_CHROOT
    config.use_chroot = 1;
#endif
    config.modify_proc_title = 1;

    config.disable_user_service_publishing = 0;
    config.publish_dns_servers = NULL;
    config.publish_resolv_conf = 0;
    config.use_syslog = 0;
    config.debug = 0;
    config.rlimit_as_set = 0;
    config.rlimit_core_set = 0;
    config.rlimit_data_set = 0;
    config.rlimit_fsize_set = 0;
    config.rlimit_nofile_set = 0;
    config.rlimit_stack_set = 0;
#ifdef RLIMIT_NPROC
    config.rlimit_nproc_set = 0;
#endif
    
    if ((argv0 = strrchr(argv[0], '/')))
        argv0 = avahi_strdup(argv0 + 1);
    else
        argv0 = avahi_strdup(argv[0]);

    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)
        goto finish;

    if (config.modify_proc_title)
        avahi_init_proc_title(argc, argv);

#ifdef ENABLE_CHROOT
    config.use_chroot = config.use_chroot && config.drop_root;
#endif
    
    if (config.command == DAEMON_HELP) {
        help(stdout);
        r = 0;
    } else if (config.command == DAEMON_VERSION) {
        printf("%s "PACKAGE_VERSION"\n", argv0);
        r = 0;
    } else if (config.command == DAEMON_KILL) {
        if (daemon_pid_file_kill_wait(SIGTERM, 5) < 0) {
            avahi_log_warn("Failed to kill daemon: %s", strerror(errno));
            goto finish;
        }

        r = 0;

    } else if (config.command == DAEMON_RELOAD) {
        if (daemon_pid_file_kill(SIGHUP) < 0) {
            avahi_log_warn("Failed to kill daemon: %s", strerror(errno));
            goto finish;
        }

        r = 0;
        
    } else if (config.command == DAEMON_CHECK)
        r = (daemon_pid_file_is_running() >= 0) ? 0 : 1;
    else if (config.command == DAEMON_RUN) {
        pid_t pid;

        if (getuid() != 0 && config.drop_root) {
            avahi_log_error("This program is intended to be run as root.");
            goto finish;
        }
        
        if ((pid = daemon_pid_file_is_running()) >= 0) {
            avahi_log_error("Daemon already running on PID %u", pid);
            goto finish;
        }

        if (load_config_file(&config) < 0)
            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 receive return value from daemon process.");
                    goto finish;
                }

                r = ret;
                goto finish;
            }

            /* Child */
        }

        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;

        if (config.drop_root) {
#ifdef ENABLE_CHROOT
            if (config.use_chroot)
                if (avahi_caps_reduce() < 0)
                    goto finish;
#endif
            
            if (drop_root() < 0)
                goto finish;

#ifdef ENABLE_CHROOT
            if (config.use_chroot)
                if (avahi_caps_reduce2() < 0)
                    goto finish;
#endif
        }

        if (daemon_pid_file_create() < 0) {
            avahi_log_error("Failed to create PID file: %s", strerror(errno));

            if (config.daemonize)
                daemon_retval_send(1);
            goto finish;
        } else
            wrote_pid_file = 1;

        if (config.set_rlimits)
            enforce_rlimits();

        chdir("/");

#ifdef ENABLE_CHROOT
        if (config.drop_root && config.use_chroot)
            if (avahi_chroot_helper_start(argv0) < 0) {
                avahi_log_error("failed to start chroot() helper daemon.");
                goto finish;
            }
#endif
        avahi_log_info("%s "PACKAGE_VERSION" starting up.", argv0);

        avahi_set_proc_title(argv0, "%s: starting up", argv0);
        
        if (run_server(&config) == 0)
            r = 0;
    }
        
finish:

    if (config.daemonize)
        daemon_retval_done();

    avahi_server_config_free(&config.server_config);
    avahi_free(config.config_file);
    avahi_strfreev(config.publish_dns_servers);
    avahi_strfreev(resolv_conf_name_servers);
    avahi_strfreev(resolv_conf_search_domains);

    if (wrote_pid_file) {
#ifdef ENABLE_CHROOT
        avahi_chroot_helper_unlink(pid_file_proc());
#else
        daemon_pid_file_remove();
#endif
    }

#ifdef ENABLE_CHROOT
    avahi_chroot_helper_shutdown();
#endif

    avahi_free(argv0);
    
    return r;
}
Ejemplo n.º 7
0
static void create_services(AvahiClient *c) {
    char *n, r[128];
    int ret;
    assert(c);
	
    /* If this is the first time we're called, let's create a new
     * entry group if necessary */
	
    if (!group)
        if (!(group = avahi_entry_group_new(c, entry_group_callback, NULL))) {
            fprintf(stderr, "avahi_entry_group_new() failed: %s\n", avahi_strerror(avahi_client_errno(c)));
            goto fail;
        }
	
    /* If the group is empty (either because it was just created, or
     * because it was reset previously, add our entries.  */
	
    if (avahi_entry_group_is_empty(group)) {
        fprintf(stderr, "Adding service '%s'\n", name);
		
        /* Create some random TXT data */
        snprintf(r, sizeof(r), "random=%i", rand());
		
        /* We will now add two services and one subtype to the entry
         * group. The two services have the same name, but differ in
         * the service type (IPP vs. BSD LPR). Only services with the
         * same name should be put in the same entry group. */
		
        /* Add the service for IPP */
        if ((ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, name, "_gbmon._tcp", NULL, NULL, 1000, "test=blah", r, NULL)) < 0) {
			
            if (ret == AVAHI_ERR_COLLISION)
                goto collision;
			
            fprintf(stderr, "Failed to add _ipp._tcp service: %s\n", avahi_strerror(ret));
            goto fail;
        }
		
        /* Tell the server to register the service */
        if ((ret = avahi_entry_group_commit(group)) < 0) {
            fprintf(stderr, "Failed to commit entry group: %s\n", avahi_strerror(ret));
            goto fail;
        }
    }
	
    return;
	
collision:
	
    /* A service name collision with a local service happened. Let's
     * pick a new name */
    n = avahi_alternative_service_name(name);
    avahi_free(name);
    name = n;
	
    fprintf(stderr, "Service name collision, renaming service to '%s'\n", name);
	
    avahi_entry_group_reset(group);
	
    create_services(c);
    return;
	
fail:
    avahi_simple_poll_quit(simple_poll);
}
Ejemplo n.º 8
0
void Publisher::nextName() {
	char *newName = avahi_alternative_service_name(info.getServiceName().c_str());
	info.setServiceName(std::string(newName));
	avahi_free(newName);
}
Ejemplo n.º 9
0
void static_hosts_load(int in_chroot) {
    FILE *f;
    unsigned int line = 0;
    StaticHost *h, *next;
    const char *filename = in_chroot ? "/hosts" : AVAHI_CONFIG_DIR "/hosts";

    if (!(f = fopen(filename, "r"))) {
        if (errno != ENOENT)
            avahi_log_error ("Failed to open static hosts file: %s", strerror (errno));
        return;
    }

    current_iteration++;
    
    while (!feof(f)) {
        unsigned int len;
        char ln[256], *s;
        char *host, *ip;
        AvahiAddress a;

        if (!fgets(ln, sizeof (ln), f))
            break;

        line++;

        /* Find the start of the line, ignore whitespace */
        s = ln + strspn(ln, " \t");
        /* Set the end of the string to NULL */
        s[strcspn(s, "#\r\n")] = 0;

        /* Ignore blank lines */
        if (*s == 0)
            continue;

        /* Read the first string (ip) up to the next whitespace */
        len = strcspn(s, " \t");
        ip = avahi_strndup(s, len);

        /* Skip past it */
        s += len;

        /* Find the next token */
        s += strspn(s, " \t");
        len = strcspn(s, " \t");
        host = avahi_strndup(s, len);

        if (*host == 0)
        {
            avahi_log_error("%s:%d: Error, unexpected end of line!", filename, line);
            avahi_free(host);
            avahi_free(ip);
            goto fail;
        }

        /* Skip over the host */
        s += len;

        /* Skip past any more spaces */
        s += strspn(s, " \t");
        
        /* Anything left? */
        if (*s != 0) {
            avahi_log_error ("%s:%d: Junk on the end of the line!", filename, line);
            avahi_free(host);
            avahi_free(ip);
            goto fail;
        }

        if (!avahi_address_parse(ip, AVAHI_PROTO_UNSPEC, &a)) {
            avahi_log_error("Static host name %s: failed to parse address %s", host, ip);
            avahi_free(host);
            avahi_free(ip);
            goto fail;
        }

        avahi_free(ip);

        if ((h = static_host_find(host, &a)))
            avahi_free(host);
        else {
            h = static_host_new();
            h->host = host;
            h->address = a;

            avahi_log_info("Loading new static hostname %s.", h->host);
        }

        h->iteration = current_iteration;
    }

    for (h = hosts; h; h = next) {
        next = h->hosts_next;
        
        if (h->iteration != current_iteration) {
            avahi_log_info("Static hostname %s vanished, removing.", h->host);
            static_host_free(h);
        }
    }

fail:
    
    fclose(f);
}
Ejemplo n.º 10
0
/* handle address coming or going away */
static int
rtm_dispatch_newdeladdr(struct rtm_dispinfo *di)
{
        Address                 *ap;
        struct ifa_msghdr       *ifam;
        struct sockaddr         *sa;
        struct sockaddr_in      *sin;
        int                     link_local;

/* macro to skip to next RTA; has side-effects */
#define SKIPRTA(ifamsgp, rta, sa)                                       \
        do {                                                            \
                if ((ifamsgp)->ifam_addrs & (rta))                      \
                        (sa) = next_sa((sa));                           \
        } while (0)

        ifam = &((rtmunion_t *)di->di_buf)->ifam;

        assert(ifam->ifam_type == RTM_NEWADDR ||
               ifam->ifam_type == RTM_DELADDR);

        daemon_log(LOG_DEBUG, "%s: %s for iface %d (%s)", __func__,
            ifam->ifam_type == RTM_NEWADDR ? "NEWADDR" : "DELADDR",
            ifam->ifam_index, (ifam->ifam_index == ifindex) ? "ours" : "not ours");

        if (ifam->ifam_index != ifindex)
                return (0);

        if (!(ifam->ifam_addrs & RTA_IFA)) {
                daemon_log(LOG_ERR, "ifa msg has no RTA_IFA.");
                return (0);
        }

        /* skip over rtmsg padding correctly */
        sa = (struct sockaddr *)(ifam + 1);
        SKIPRTA(ifam, RTA_DST, sa);
        SKIPRTA(ifam, RTA_GATEWAY, sa);
        SKIPRTA(ifam, RTA_NETMASK, sa);
        SKIPRTA(ifam, RTA_GENMASK, sa);
        SKIPRTA(ifam, RTA_IFP, sa);

        /*
         * sa now points to RTA_IFA sockaddr; we are only interested
         * in updates for routable addresses.
         */
        if (sa->sa_family != AF_INET) {
                daemon_log(LOG_DEBUG, "%s: RTA_IFA family not AF_INET (=%d)", __func__, sa->sa_family);
                return (0);
        }

        sin = (struct sockaddr_in *)sa;
        link_local = IN_LINKLOCAL(ntohl(sin->sin_addr.s_addr));

        daemon_log(LOG_DEBUG, "%s: %s for %s (%s)", __func__,
            ifam->ifam_type == RTM_NEWADDR ? "NEWADDR" : "DELADDR",
            inet_ntoa(sin->sin_addr), link_local ? "link local" : "routable");

        if (link_local)
                return (0);

        for (ap = addresses; ap; ap = ap->addresses_next) {
                if (ap->address == sin->sin_addr.s_addr)
                        break;
        }
        if (ifam->ifam_type == RTM_DELADDR && ap != NULL) {
                AVAHI_LLIST_REMOVE(Address, addresses, addresses, ap);
                avahi_free(ap);
        }
        if (ifam->ifam_type == RTM_NEWADDR && ap == NULL) {
                ap = avahi_new(Address, 1);
                ap->address = sin->sin_addr.s_addr;
                AVAHI_LLIST_PREPEND(Address, addresses, addresses, ap);
        }

        return (0);
#undef SKIPRTA
}
Ejemplo n.º 11
0
AvahiNetlink *avahi_netlink_new(const AvahiPoll *poll_api, uint32_t groups, void (*cb) (AvahiNetlink *nl, struct nlmsghdr *n, void* userdata), void* userdata) {
    int fd = -1;
    const int on = 1;
    struct sockaddr_nl addr;
    AvahiNetlink *nl = NULL;

    assert(poll_api);
    assert(cb);

    if ((fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) {
        avahi_log_error(__FILE__": socket(PF_NETLINK): %s", strerror(errno));
        return NULL;
    }

    memset(&addr, 0, sizeof(addr));
    addr.nl_family = AF_NETLINK;
    addr.nl_groups = groups;
    addr.nl_pid = 0;

    if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
        avahi_log_error(__FILE__": bind(): %s", strerror(errno));
        goto fail;
    }

    if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
        avahi_log_error(__FILE__": SO_PASSCRED: %s", strerror(errno));
        goto fail;
    }

    if (!(nl = avahi_new(AvahiNetlink, 1))) {
        avahi_log_error(__FILE__": avahi_new() failed.");
        goto fail;
    }

    nl->poll_api = poll_api;
    nl->fd = fd;
    nl->seq = 0;
    nl->callback = cb;
    nl->userdata = userdata;

    if (!(nl->buffer = avahi_new(uint8_t, nl->buffer_length = 64*1024))) {
        avahi_log_error(__FILE__": avahi_new() failed.");
        goto fail;
    }

    if (!(nl->watch = poll_api->watch_new(poll_api, fd, AVAHI_WATCH_IN, socket_event, nl))) {
        avahi_log_error(__FILE__": Failed to create watch.");
        goto fail;
    }

    return nl;

fail:

    if (fd >= 0)
        close(fd);

    if (nl) {
        avahi_free(nl->buffer);
        avahi_free(nl);
    }

    return NULL;
}
Ejemplo n.º 12
0
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char *argv[]) {
    char *t, *v;
    uint8_t data[1024];
    AvahiStringList *a = NULL, *b, *p;
    size_t size, n;
    int r;

    a = avahi_string_list_new("prefix", "a", "b", NULL);
    
    a = avahi_string_list_add(a, "start");
    a = avahi_string_list_add(a, "foo=99");
    a = avahi_string_list_add(a, "bar");
    a = avahi_string_list_add(a, "");
    a = avahi_string_list_add(a, "");
    a = avahi_string_list_add(a, "quux");
    a = avahi_string_list_add(a, "");
    a = avahi_string_list_add_arbitrary(a, (const uint8_t*) "null\0null", 9);
    a = avahi_string_list_add_printf(a, "seven=%i %c", 7, 'x');
    a = avahi_string_list_add_pair(a, "blubb", "blaa");
    a = avahi_string_list_add_pair(a, "uxknurz", NULL);
    a = avahi_string_list_add_pair_arbitrary(a, "uxknurz2", (const uint8_t*) "blafasel\0oerks", 14);
    
    a = avahi_string_list_add(a, "end");

    t = avahi_string_list_to_string(a);
    printf("--%s--\n", t);
    avahi_free(t);
    
    n = avahi_string_list_serialize(a, NULL, 0);
    size = avahi_string_list_serialize(a, data, sizeof(data));
    assert(size == n);

    printf("%u\n", size);

    for (t = (char*) data, n = 0; n < size; n++, t++) {
        if (*t <= 32)
            printf("(%u)", *t);
        else
            printf("%c", *t);
    }

    printf("\n");
    
    assert(avahi_string_list_parse(data, size, &b) == 0);

    printf("equal: %i\n", avahi_string_list_equal(a, b));
    
    t = avahi_string_list_to_string(b);
    printf("--%s--\n", t);
    avahi_free(t);

    avahi_string_list_free(b);

    b = avahi_string_list_copy(a);

    assert(avahi_string_list_equal(a, b));

    t = avahi_string_list_to_string(b);
    printf("--%s--\n", t);
    avahi_free(t);

    p = avahi_string_list_find(a, "seven");
    assert(p);
    
    r = avahi_string_list_get_pair(p, &t, &v, NULL);  
    assert(r >= 0);
    assert(t);
    assert(v);
    
    printf("<%s>=<%s>\n", t, v);
    avahi_free(t);
    avahi_free(v);

    p = avahi_string_list_find(a, "quux");
    assert(p);

    r = avahi_string_list_get_pair(p, &t, &v, NULL);
    assert(r >= 0);
    assert(t);
    assert(!v);

    printf("<%s>=<%s>\n", t, v);
    avahi_free(t);
    avahi_free(v);
    
    avahi_string_list_free(a);
    avahi_string_list_free(b);

    n = avahi_string_list_serialize(NULL, NULL, 0);
    size = avahi_string_list_serialize(NULL, data, sizeof(data));
    assert(size == 1);
    assert(size == n);

    assert(avahi_string_list_parse(data, size, &a) == 0);
    assert(!a);
    
    return 0;
}
Ejemplo n.º 13
0
static void resolve_callback(
    AvahiServiceResolver *r,
    AVAHI_GCC_UNUSED AvahiIfIndex interface,
    AVAHI_GCC_UNUSED AvahiProtocol protocol,
    AvahiResolverEvent event,
    const char *name,
    const char *type,
    const char *domain,
    const char *host_name,
    const AvahiAddress *address,
    uint16_t port,
    AvahiStringList *txt,
    AvahiLookupResultFlags flags,
    AVAHI_GCC_UNUSED void* userdata) {

    assert(r);

    /* Called whenever a service has been resolved successfully or timed out */

    switch (event) {
        case AVAHI_RESOLVER_FAILURE:
            fprintf(stderr, "(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r))));
            break;

        case AVAHI_RESOLVER_FOUND: {
            char a[AVAHI_ADDRESS_STR_MAX], *t;

            fprintf(stderr, "Service '%s' of type '%s' in domain '%s':\n", name, type, domain);

            avahi_address_snprint(a, sizeof(a), address);

            /* Copy hostname and port to global variables, ready to be returned later */
            if (tvh_hostname == NULL) {
              tvh_hostname = strdup(host_name);
              tvh_ip = strdup(a);
              tvh_port = port;
            }

            t = avahi_string_list_to_string(txt);
            fprintf(stderr,
                    "\t%s:%u (%s)\n"
                    "\tTXT=%s\n"
                    "\tcookie is %u\n"
                    "\tis_local: %i\n"
                    "\tour_own: %i\n"
                    "\twide_area: %i\n"
                    "\tmulticast: %i\n"
                    "\tcached: %i\n",
                    host_name, port, a,
                    t,
                    avahi_string_list_get_service_cookie(txt),
                    !!(flags & AVAHI_LOOKUP_RESULT_LOCAL),
                    !!(flags & AVAHI_LOOKUP_RESULT_OUR_OWN),
                    !!(flags & AVAHI_LOOKUP_RESULT_WIDE_AREA),
                    !!(flags & AVAHI_LOOKUP_RESULT_MULTICAST),
                    !!(flags & AVAHI_LOOKUP_RESULT_CACHED));

            avahi_free(t);

        }
    }

    avahi_service_resolver_free(r);
}
Ejemplo n.º 14
0
char *avahi_alternative_host_name(const char *s) {
    const char *e;
    char *r;

    assert(s);

    if (!avahi_is_valid_host_name(s))
        return NULL;
    
    if ((e = strrchr(s, '-'))) {
        const char *p;

        e++;
        
        for (p = e; *p; p++)
            if (!isdigit(*p)) {
                e = NULL;
                break;
            }

        if (e && (*e == '0' || *e == 0))
            e = NULL;
    }

    if (e) {
        char *c, *m;
        size_t l;
        int n;

        n = atoi(e)+1;
        if (!(m = avahi_strdup_printf("%i", n)))
            return NULL;

        l = e-s-1;

        if (l >= AVAHI_LABEL_MAX-1-strlen(m)-1)
            l = AVAHI_LABEL_MAX-1-strlen(m)-1;

        if (!(c = avahi_strndup(s, l))) {
            avahi_free(m);
            return NULL;
        }

        drop_incomplete_utf8(c);
        
        r = avahi_strdup_printf("%s-%s", c, m);
        avahi_free(c);
        avahi_free(m);
        
    } else {
        char *c;

        if (!(c = avahi_strndup(s, AVAHI_LABEL_MAX-1-2)))
            return NULL;

        drop_incomplete_utf8(c);
        
        r = avahi_strdup_printf("%s-2", c);
        avahi_free(c);
    }

    assert(avahi_is_valid_host_name(r));

    return r;
}
Ejemplo n.º 15
0
/*****************************************************************************
 * resolve_callback
 *****************************************************************************/
static void resolve_callback(
    AvahiServiceResolver *r,
    AvahiIfIndex interface,
    AvahiProtocol protocol,
    AvahiResolverEvent event,
    const char *name,
    const char *type,
    const char *domain,
    const char *host_name,
    const AvahiAddress *address,
    uint16_t port,
    AvahiStringList *txt,
    AvahiLookupResultFlags flags,
    void* userdata )
{
    services_discovery_t *p_sd = ( services_discovery_t* )userdata;
    services_discovery_sys_t *p_sys = p_sd->p_sys;

    VLC_UNUSED(interface); VLC_UNUSED(host_name);
    VLC_UNUSED(flags);

    if( event == AVAHI_RESOLVER_FAILURE )
    {
        msg_Err( p_sd,
                 "failed to resolve service '%s' of type '%s' in domain '%s'",
                 name, type, domain );
    }
    else if( event == AVAHI_RESOLVER_FOUND )
    {
        char a[128];
        char *psz_uri = NULL;
        char *psz_addr = NULL;
        AvahiStringList *asl = NULL;
        input_item_t *p_input = NULL;

        msg_Err( p_sd, "service '%s' of type '%s' in domain '%s' port %i",
                 name, type, domain, port );

        avahi_address_snprint(a, (sizeof(a)/sizeof(a[0]))-1, address);
        if( protocol == AVAHI_PROTO_INET6 )
            if( asprintf( &psz_addr, "[%s]", a ) == -1 )
                return;

        const char *psz_protocol = NULL;
        for( unsigned int i = 0; i < NB_PROTOCOLS; i++ )
        {
            if( !strcmp(type, protocols[i].psz_service_name) )
                psz_protocol = protocols[i].psz_protocol;
        }
        if( psz_protocol == NULL )
            return;

        if( txt != NULL )
            asl = avahi_string_list_find( txt, "path" );
        if( asl != NULL )
        {
            size_t size;
            char *key = NULL;
            char *value = NULL;
            if( avahi_string_list_get_pair( asl, &key, &value, &size ) == 0 &&
                value != NULL )
            {
                if( asprintf( &psz_uri, "%s://%s:%d%s",
                          psz_protocol,
                          psz_addr != NULL ? psz_addr : a,
                          port, value ) == -1 )
                {
                    free( psz_addr );
                    return;
                }
            }
            if( key != NULL )
                avahi_free( (void *)key );
            if( value != NULL )
                avahi_free( (void *)value );
        }
        else
        {
            if( asprintf( &psz_uri, "%s://%s:%d",
                      psz_protocol,
                      psz_addr != NULL ? psz_addr : a, port ) == -1 )
            {
                free( psz_addr );
                return;
            }
        }

        free( psz_addr );

        if( psz_uri != NULL )
        {
            p_input = input_item_New( psz_uri, name );
            free( psz_uri );
        }
        if( p_input != NULL )
        {
            vlc_dictionary_insert( &p_sys->services_name_to_input_item,
                name, p_input );
            services_discovery_AddItem( p_sd, p_input );
            input_item_Release( p_input );
       }
    }

    avahi_service_resolver_free( r );
}
Ejemplo n.º 16
0
static void 
create_services(AvahiClient *c) 
{
  char *n;
  int ret;
  assert(c);

  /* If this is the first time we're called, let's create a new
   * entry group if necessary */

  if (!group)
    if (!(group = avahi_entry_group_new(c, entry_group_callback, NULL))) {
      tvhlog(LOG_ERR, "AVAHI",
	     "avahi_enty_group_new() failed: %s", 
	     avahi_strerror(avahi_client_errno(c)));
      goto fail;
    }

  /* If the group is empty (either because it was just created, or
   * because it was reset previously, add our entries.  */

  if (avahi_entry_group_is_empty(group)) {
     tvhlog(LOG_DEBUG, "AVAHI", "Adding service '%s'", name);

    /* Add the service for HTSP */
    if ((ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, 
					     AVAHI_PROTO_UNSPEC, 0, name, 
					     "_htsp._tcp", NULL, NULL, 9982,
					     NULL)) < 0) {

      if (ret == AVAHI_ERR_COLLISION)
	goto collision;

      tvhlog(LOG_ERR, "AVAHI",
	     "Failed to add _htsp._tcp service: %s", 
	     avahi_strerror(ret));
      goto fail;
    }


    /* Add the service for HTTP */
    if ((ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, 
					     AVAHI_PROTO_UNSPEC, 0, name, 
					     "_http._tcp", NULL, NULL, 9981,
					     "path=/",
					     NULL)) < 0) {

      if (ret == AVAHI_ERR_COLLISION)
	goto collision;

      tvhlog(LOG_ERR, "AVAHI",
	     "Failed to add _http._tcp service: %s", 
	     avahi_strerror(ret));
      goto fail;
    }

    /* Tell the server to register the service */
    if ((ret = avahi_entry_group_commit(group)) < 0) {
      tvhlog(LOG_ERR, "AVAHI",
	     "Failed to commit entry group: %s", 
	     avahi_strerror(ret));
      goto fail;
    }
  }

  return;

 collision:

  /* A service name collision with a local service happened. Let's
   * pick a new name */
  n = avahi_alternative_service_name(name);
  avahi_free(name);
  name = n;

  tvhlog(LOG_ERR, "AVAHI",
	 "Service name collision, renaming service to '%s'", name);

  avahi_entry_group_reset(group);

  create_services(c);
  return;

 fail:
  return;
}
Ejemplo n.º 17
0
static void destroy_timeout(AvahiTimeout *t) {
    assert(t);

    AVAHI_LLIST_REMOVE(AvahiTimeout, timeouts, t->glib_poll->timeouts, t);
    avahi_free(t);
}