Exemplo n.º 1
0
static AvahiEntry * server_add_internal(
    AvahiServer *s,
    AvahiSEntryGroup *g,
    AvahiIfIndex interface,
    AvahiProtocol protocol,
    AvahiPublishFlags flags,
    AvahiRecord *r) {

    AvahiEntry *e;
    
    assert(s);
    assert(r);

    AVAHI_CHECK_VALIDITY_RETURN_NULL(s, s->state != AVAHI_SERVER_FAILURE && s->state != AVAHI_SERVER_INVALID, AVAHI_ERR_BAD_STATE);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(s, AVAHI_IF_VALID(interface), AVAHI_ERR_INVALID_INTERFACE);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(s, AVAHI_PROTO_VALID(protocol), AVAHI_ERR_INVALID_PROTOCOL);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(s, AVAHI_FLAGS_VALID(
                                         flags,
                                         AVAHI_PUBLISH_NO_ANNOUNCE|
                                         AVAHI_PUBLISH_NO_PROBE|
                                         AVAHI_PUBLISH_UNIQUE|
                                         AVAHI_PUBLISH_ALLOW_MULTIPLE|
                                         AVAHI_PUBLISH_UPDATE|
                                         AVAHI_PUBLISH_USE_WIDE_AREA|
                                         AVAHI_PUBLISH_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(s, avahi_is_valid_domain_name(r->key->name), AVAHI_ERR_INVALID_HOST_NAME);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(s, r->ttl != 0, AVAHI_ERR_INVALID_TTL);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(s, !avahi_key_is_pattern(r->key), AVAHI_ERR_IS_PATTERN);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(s, avahi_record_is_valid(r), AVAHI_ERR_INVALID_RECORD);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(s, r->key->clazz == AVAHI_DNS_CLASS_IN, AVAHI_ERR_INVALID_DNS_CLASS);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(s,
                                     (r->key->type != 0) &&
                                     (r->key->type != AVAHI_DNS_TYPE_ANY) &&
                                     (r->key->type != AVAHI_DNS_TYPE_OPT) &&
                                     (r->key->type != AVAHI_DNS_TYPE_TKEY) &&
                                     (r->key->type != AVAHI_DNS_TYPE_TSIG) &&
                                     (r->key->type != AVAHI_DNS_TYPE_IXFR) &&
                                     (r->key->type != AVAHI_DNS_TYPE_AXFR), AVAHI_ERR_INVALID_DNS_TYPE);

    transport_flags_from_domain(s, &flags, r->key->name);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(s, flags & AVAHI_PUBLISH_USE_MULTICAST, AVAHI_ERR_NOT_SUPPORTED);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(s, !s->config.disable_publishing, AVAHI_ERR_NOT_PERMITTED);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(s,
                                     !g ||
                                     (g->state != AVAHI_ENTRY_GROUP_ESTABLISHED && g->state != AVAHI_ENTRY_GROUP_REGISTERING) ||
                                     (flags & AVAHI_PUBLISH_UPDATE), AVAHI_ERR_BAD_STATE);
    
    if (flags & AVAHI_PUBLISH_UPDATE) {
        AvahiRecord *old_record;
        int is_first = 1;
        
        /* Update and existing record */

        /* Find the first matching entry */
        for (e = avahi_hashmap_lookup(s->entries_by_key, r->key); e; e = e->by_key_next) {
            if (!e->dead && e->group == g && e->interface == interface && e->protocol == protocol)
                break;

            is_first = 0;
        }

        /* Hmm, nothing found? */
        if (!e) {
            avahi_server_set_errno(s, AVAHI_ERR_NOT_FOUND);
            return NULL;
        }

        /* Update the entry */
        old_record = e->record;
        e->record = avahi_record_ref(r);
        e->flags = flags;

        /* Announce our changes when needed */
        if (!avahi_record_equal_no_ttl(old_record, r) && (!g || g->state != AVAHI_ENTRY_GROUP_UNCOMMITED)) {

            /* Remove the old entry from all caches, if needed */
            if (!(e->flags & AVAHI_PUBLISH_UNIQUE))
                avahi_goodbye_entry(s, e, 1, 0);

            /* Reannounce our updated entry */
            avahi_reannounce_entry(s, e);
        }

        /* If we were the first entry in the list, we need to update the key */
        if (is_first)
            avahi_hashmap_replace(s->entries_by_key, e->record->key, e);
        
        avahi_record_unref(old_record);

    } else {
        AvahiEntry *t;

        /* Add a new record */
    
        if (check_record_conflict(s, interface, protocol, r, flags) < 0) {
            avahi_server_set_errno(s, AVAHI_ERR_COLLISION);
            return NULL;
        }

        if (!(e = avahi_new(AvahiEntry, 1))) {
            avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY);
            return NULL;
        }
        
        e->server = s;
        e->record = avahi_record_ref(r);
        e->group = g;
        e->interface = interface;
        e->protocol = protocol;
        e->flags = flags;
        e->dead = 0;
        
        AVAHI_LLIST_HEAD_INIT(AvahiAnnouncer, e->announcers);
        
        AVAHI_LLIST_PREPEND(AvahiEntry, entries, s->entries, e);
        
        /* Insert into hash table indexed by name */
        t = avahi_hashmap_lookup(s->entries_by_key, e->record->key);
        AVAHI_LLIST_PREPEND(AvahiEntry, by_key, t, e);
        avahi_hashmap_replace(s->entries_by_key, e->record->key, t);
        
        /* Insert into group list */
        if (g)
            AVAHI_LLIST_PREPEND(AvahiEntry, by_group, g->entries, e); 
        
        avahi_announce_entry(s, e);
    }

    return e;
}
Exemplo n.º 2
0
int simple_protocol_setup(const AvahiPoll *poll_api) {
    struct sockaddr_un sa;
    mode_t u;
    int n;

    assert(!server);

    server = avahi_new(Server, 1);
    server->poll_api = poll_api;
    server->remove_socket = 0;
    server->fd = -1;
    server->n_clients = 0;
    AVAHI_LLIST_HEAD_INIT(Client, server->clients);
    server->watch = NULL;

    u = umask(0000);

    if ((n = sd_listen_fds(1)) < 0) {
        avahi_log_warn("Failed to acquire systemd file descriptors: %s", strerror(-n));
        goto fail;
    }

    if (n > 1) {
        avahi_log_warn("Too many systemd file descriptors passed.");
        goto fail;
    }

    if (n == 1) {
        int r;

        if ((r = sd_is_socket(SD_LISTEN_FDS_START, AF_LOCAL, SOCK_STREAM, 1)) < 0) {
            avahi_log_warn("Passed systemd file descriptor is of wrong type: %s", strerror(-r));
            goto fail;
        }

        server->fd = SD_LISTEN_FDS_START;

    } else {

        if ((server->fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) {
            avahi_log_warn("socket(AF_LOCAL, SOCK_STREAM, 0): %s", strerror(errno));
            goto fail;
        }

        memset(&sa, 0, sizeof(sa));
        sa.sun_family = AF_LOCAL;
        strncpy(sa.sun_path, AVAHI_SOCKET, sizeof(sa.sun_path)-1);

        /* We simply remove existing UNIX sockets under this name. The
           Avahi daemon makes sure that it runs only once on a host,
           therefore sockets that already exist are stale and may be
           removed without any ill effects */

        unlink(AVAHI_SOCKET);

        if (bind(server->fd, (struct sockaddr*) &sa, sizeof(sa)) < 0) {
            avahi_log_warn("bind(): %s", strerror(errno));
            goto fail;
        }

        server->remove_socket = 1;

        if (listen(server->fd, SOMAXCONN) < 0) {
            avahi_log_warn("listen(): %s", strerror(errno));
            goto fail;
        }
    }

    umask(u);

    server->watch = poll_api->watch_new(poll_api, server->fd, AVAHI_WATCH_IN, server_work, server);

    return 0;

fail:

    umask(u);
    simple_protocol_shutdown();

    return -1;
}
Exemplo n.º 3
0
AvahiIniFile* avahi_ini_file_load(const char *fname) {
    AvahiIniFile *f;
    FILE *fo;
    AvahiIniFileGroup *group = NULL;
    unsigned line;
    
    assert(fname);

    if (!(fo = fopen(fname, "r"))) {
        avahi_log_error("Failed to open file '%s': %s", fname, strerror(errno));
        return NULL;
    }
    
    f = avahi_new(AvahiIniFile, 1);
    AVAHI_LLIST_HEAD_INIT(AvahiIniFileGroup, f->groups);
    f->n_groups = 0;

    line = 0;
    while (!feof(fo)) {
        char ln[256], *s, *e;
        AvahiIniFilePair *pair;
        
        if (!(fgets(ln, sizeof(ln), fo)))
            break;

        line++;
        
        s = ln + strspn(ln, " \t");
        s[strcspn(s, "\r\n")] = 0;

        /* Skip comments and empty lines */
        if (*s == '#' || *s == '%' || *s == 0)
            continue;

        if (*s == '[') {
            /* new group */
            
            if (!(e = strchr(s, ']'))) {
                avahi_log_error("Unclosed group header in %s:%u: <%s>", fname, line, s);
                goto fail;
            }

            *e = 0;
            
            group = avahi_new(AvahiIniFileGroup, 1);
            group->name = avahi_strdup(s+1);
            group->n_pairs = 0;
            AVAHI_LLIST_HEAD_INIT(AvahiIniFilePair, group->pairs);
            
            AVAHI_LLIST_PREPEND(AvahiIniFileGroup, groups, f->groups, group);
            f->n_groups++;
        } else {

            /* Normal assignment */
            if (!(e = strchr(s, '='))) {
                avahi_log_error("Missing assignment in %s:%u: <%s>", fname, line, s);
                goto fail;
            }
            
            if (!group) {
                avahi_log_error("Assignment outside group in %s:%u <%s>", fname, line, s);
                goto fail;
            }
            
            /* Split the key and the value */
            *(e++) = 0;
            
            pair = avahi_new(AvahiIniFilePair, 1);
            pair->key = avahi_strdup(s);
            pair->value = avahi_strdup(e);
            
            AVAHI_LLIST_PREPEND(AvahiIniFilePair, pairs, group->pairs, pair);
            group->n_pairs++;
        }
    }
    
    fclose(fo);
        
    return f;

fail:

    if (fo)
        fclose(fo);

    if (f)
        avahi_ini_file_free(f);

    return NULL;
}