Ejemplo n.º 1
0
/*
 * This function tries to register the AFP DNS
 * SRV service type.
 */
static void register_stuff(void) {
    uint port;
    const struct vol *volume;
    DSI *dsi;
    char name[MAXINSTANCENAMELEN+1];
    AvahiStringList *strlist = NULL;
    AvahiStringList *strlist2 = NULL;
    char tmpname[256];

    assert(ctx->client);

    if (!ctx->group) {
        if (!(ctx->group = avahi_entry_group_new(ctx->client, publish_reply, ctx))) {
            LOG(log_error, logtype_afpd, "Failed to create entry group: %s",
                avahi_strerror(avahi_client_errno(ctx->client)));
            goto fail;
        }
    }

    if (avahi_entry_group_is_empty(ctx->group)) {
        /* Register our service */

        /* Build AFP volumes list */
        int i = 0;
        strlist = avahi_string_list_add_printf(strlist, "sys=waMa=0,adVF=0x100");

        for (volume = getvolumes(); volume; volume = volume->v_next) {

            if (convert_string(CH_UCS2, CH_UTF8_MAC, volume->v_u8mname, -1, tmpname, 255) <= 0) {
                LOG ( log_error, logtype_afpd, "Could not set Zeroconf volume name for TimeMachine");
                goto fail;
            }

            if (volume->v_flags & AFPVOL_TM) {
                if (volume->v_uuid) {
                    LOG(log_info, logtype_afpd, "Registering volume '%s' with UUID: '%s' for TimeMachine",
                        volume->v_localname, volume->v_uuid);
                    strlist = avahi_string_list_add_printf(strlist, "dk%u=adVN=%s,adVF=0xa1,adVU=%s",
                                                           i++, tmpname, volume->v_uuid);
                } else {
                    LOG(log_warning, logtype_afpd, "Registering volume '%s' for TimeMachine. But UUID is invalid.",
                        volume->v_localname);
                    strlist = avahi_string_list_add_printf(strlist, "dk%u=adVN=%s,adVF=0xa1",
                                                           i++, tmpname);
                }
            }
        }

        /* AFP server */
        for (dsi = ctx->obj->dsi; dsi; dsi = dsi->next) {
            port = getip_port((struct sockaddr *)&dsi->server);

            LOG(log_info, logtype_afpd, "hostname: %s", ctx->obj->options.hostname);

            if (convert_string(ctx->obj->options.unixcharset,
                               CH_UTF8,
                               ctx->obj->options.hostname,
                               -1,
                               name,
                               MAXINSTANCENAMELEN) <= 0) {
                LOG(log_error, logtype_afpd, "Could not set Zeroconf instance name: %s", ctx->obj->options.hostname);
                goto fail;
            }
            if ((dsi->bonjourname = strdup(name)) == NULL) {
                LOG(log_error, logtype_afpd, "Could not set Zeroconf instance name");
                goto fail;

            }
            LOG(log_info, logtype_afpd, "Registering server '%s' with Bonjour",
                dsi->bonjourname);

            if (avahi_entry_group_add_service(ctx->group,
                                              AVAHI_IF_UNSPEC,
                                              AVAHI_PROTO_UNSPEC,
                                              0,
                                              dsi->bonjourname,
                                              AFP_DNS_SERVICE_TYPE,
                                              NULL,
                                              NULL,
                                              port,
                                              NULL) < 0) {
                LOG(log_error, logtype_afpd, "Failed to add service: %s",
                    avahi_strerror(avahi_client_errno(ctx->client)));
                goto fail;
            }

            if (i && avahi_entry_group_add_service_strlst(ctx->group,
                    AVAHI_IF_UNSPEC,
                    AVAHI_PROTO_UNSPEC,
                    0,
                    dsi->bonjourname,
                    ADISK_SERVICE_TYPE,
                    NULL,
                    NULL,
                    9, /* discard */
                    strlist) < 0) {
                LOG(log_error, logtype_afpd, "Failed to add service: %s",
                    avahi_strerror(avahi_client_errno(ctx->client)));
                goto fail;
            }	/* if */

            if (ctx->obj->options.mimicmodel) {
                strlist2 = avahi_string_list_add_printf(strlist2, "model=%s", ctx->obj->options.mimicmodel);
                if (avahi_entry_group_add_service_strlst(ctx->group,
                        AVAHI_IF_UNSPEC,
                        AVAHI_PROTO_UNSPEC,
                        0,
                        dsi->bonjourname,
                        DEV_INFO_SERVICE_TYPE,
                        NULL,
                        NULL,
                        0,
                        strlist2) < 0) {
                    LOG(log_error, logtype_afpd, "Failed to add service: %s",
                        avahi_strerror(avahi_client_errno(ctx->client)));
                    goto fail;
                }
            } /* if (config->obj.options.mimicmodel) */

        }	/* for config*/

        if (avahi_entry_group_commit(ctx->group) < 0) {
            LOG(log_error, logtype_afpd, "Failed to commit entry group: %s",
                avahi_strerror(avahi_client_errno(ctx->client)));
            goto fail;
        }

    }	/* if avahi_entry_group_is_empty*/

    return;

fail:
    time(NULL);
//    avahi_threaded_poll_quit(ctx->threaded_poll);
}
Ejemplo n.º 2
0
/*
 * This function tries to register the AFP DNS
 * SRV service type.
 */
static void register_stuff(const AFPObj *obj) {
    uint                                        port;
    const struct vol                *volume;
    char                                        name[MAXINSTANCENAMELEN+1];
    DNSServiceErrorType         error;
    TXTRecordRef                        txt_adisk;
    TXTRecordRef                        txt_devinfo;
    char                                        tmpname[256];

    // If we had already registered, then we will unregister and re-register
    if(svc_refs) unregister_stuff();

    /* Register our service, prepare the TXT record */
    TXTRecordCreate(&txt_adisk, 0, NULL);
    if( 0 > TXTRecordPrintf(&txt_adisk, "sys", "waMa=0,adVF=0x100") ) {
        LOG ( log_error, logtype_afpd, "Could not create Zeroconf TXTRecord for sys");
        goto fail;
    }

    /* Build AFP volumes list */
    int i = 0;

    for (volume = getvolumes(); volume; volume = volume->v_next) {

        if (convert_string(CH_UCS2, CH_UTF8_MAC, volume->v_u8mname, -1, tmpname, 255) <= 0) {
            LOG ( log_error, logtype_afpd, "Could not set Zeroconf volume name for TimeMachine");
            goto fail;
        }

        if (volume->v_flags & AFPVOL_TM) {
            if (volume->v_uuid) {
                LOG(log_info, logtype_afpd, "Registering volume '%s' with UUID: '%s' for TimeMachine",
                    volume->v_localname, volume->v_uuid);
                if( 0 > TXTRecordKeyPrintf(&txt_adisk, "dk%u", i++, "adVN=%s,adVF=0xa1,adVU=%s",
                                   tmpname, volume->v_uuid) ) {
                    LOG ( log_error, logtype_afpd, "Could not set Zeroconf TXTRecord for dk%u", i);
                    goto fail;
                }
            } else {
                LOG(log_warning, logtype_afpd, "Registering volume '%s' for TimeMachine. But UUID is invalid.",
                    volume->v_localname);
                if( 0 > TXTRecordKeyPrintf(&txt_adisk, "dk%u", i++, "adVN=%s,adVF=0xa1", tmpname) ) {
                    LOG ( log_error, logtype_afpd, "Could not set Zeroconf TXTRecord for dk%u", i);
                    goto fail;
                }
            }
        }
    }

    /* AFP_DNS_SERVICE_TYPE */
    svc_ref_count = 1;
    if (i) {
        /* ADISK_SERVICE_TYPE */
        svc_ref_count++;
    }
    if (obj->options.mimicmodel) {
        /* DEV_INFO_SERVICE_TYPE */
        svc_ref_count++;
    }

    // Allocate the memory to store our service refs
    svc_refs = calloc(svc_ref_count, sizeof(DNSServiceRef));
    assert(svc_refs);
    svc_ref_count = 0;

    port = atoi(obj->options.port);

    if (convert_string(obj->options.unixcharset,
                       CH_UTF8,
                       obj->options.hostname,
                       -1,
                       name,
                       MAXINSTANCENAMELEN) <= 0) {
        LOG(log_error, logtype_afpd, "Could not set Zeroconf instance name");
        goto fail;
    }

    error = DNSServiceRegister(&svc_refs[svc_ref_count++],
                               0,               // no flags
                               0,               // all network interfaces
                               name,
                               AFP_DNS_SERVICE_TYPE,
                               "",            // default domains
                               NULL,            // default host name
                               htons(port),
                               0,               // length of TXT
                               NULL,            // no TXT
                               RegisterReply,           // callback
                               NULL);       // no context
    if (error != kDNSServiceErr_NoError) {
        LOG(log_error, logtype_afpd, "Failed to add service: %s, error=%d",
            AFP_DNS_SERVICE_TYPE, error);
        goto fail;
    }

    if (i) {
        error = DNSServiceRegister(&svc_refs[svc_ref_count++],
                                   0,               // no flags
                                   0,               // all network interfaces
                                   name,
                                   ADISK_SERVICE_TYPE,
                                   "",            // default domains
                                   NULL,            // default host name
                                   htons(port),
                                   TXTRecordGetLength(&txt_adisk),
                                   TXTRecordGetBytesPtr(&txt_adisk),
                                   RegisterReply,           // callback
                                   NULL);       // no context
        if (error != kDNSServiceErr_NoError) {
            LOG(log_error, logtype_afpd, "Failed to add service: %s, error=%d",
                ADISK_SERVICE_TYPE, error);
            goto fail;
        }
    }

    if (obj->options.mimicmodel) {
        LOG(log_info, logtype_afpd, "Registering server as model '%s'",
            obj->options.mimicmodel);
        TXTRecordCreate(&txt_devinfo, 0, NULL);
        if ( 0 > TXTRecordPrintf(&txt_devinfo, "model", obj->options.mimicmodel) ) {
            LOG ( log_error, logtype_afpd, "Could not create Zeroconf TXTRecord for model");
            goto fail;
        }

        error = DNSServiceRegister(&svc_refs[svc_ref_count++],
                                   0,               // no flags
                                   0,               // all network interfaces
                                   name,
                                   DEV_INFO_SERVICE_TYPE,
                                   "",            // default domains
                                   NULL,            // default host name
                                   /*
                                    * We would probably use port 0 zero, but we can't, from man DNSServiceRegister:
                                    *   "A value of 0 for a port is passed to register placeholder services.
                                    *    Place holder services are not found  when browsing, but other
                                    *    clients cannot register with the same name as the placeholder service."
                                    * We therefor use port 9 which is used by the adisk service type.
                                    */
                                   htons(9),
                                   TXTRecordGetLength(&txt_devinfo),
                                   TXTRecordGetBytesPtr(&txt_devinfo),
                                   RegisterReply,           // callback
                                   NULL);       // no context
        TXTRecordDeallocate(&txt_devinfo);
        if (error != kDNSServiceErr_NoError) {
            LOG(log_error, logtype_afpd, "Failed to add service: %s, error=%d",
                DEV_INFO_SERVICE_TYPE, error);
            goto fail;
        }
    } /* if (config->obj.options.mimicmodel) */

    /*
     * Now we can create the thread that will poll for the results
     * and handle the calling of the callbacks
     */
    if(pthread_create(&poller, NULL, polling_thread, NULL) != 0) {
        LOG(log_error, logtype_afpd, "Unable to start mDNS polling thread");
        goto fail;
    }

fail:
    TXTRecordDeallocate(&txt_adisk);
    return;
}