Beispiel #1
0
/* accept the socket and do a little sanity checking */
static int dsi_tcp_open(DSI *dsi)
{
    pid_t pid;
    SOCKLEN_T len;

    len = sizeof(dsi->client);
    dsi->socket = accept(dsi->serversock, (struct sockaddr *) &dsi->client, &len);

#ifdef TCPWRAP
    {
        struct request_info req;
        request_init(&req, RQ_DAEMON, dsi->program, RQ_FILE, dsi->socket, NULL);
        fromhost(&req);
        if (!hosts_access(&req)) {
            LOG(deny_severity, logtype_dsi, "refused connect from %s", eval_client(&req));
            close(dsi->socket);
            errno = ECONNREFUSED;
            dsi->socket = -1;
        }
    }
#endif /* TCPWRAP */

    if (dsi->socket < 0)
        return -1;

    getitimer(ITIMER_PROF, &itimer);
    if (0 == (pid = fork()) ) { /* child */
        static struct itimerval timer = {{0, 0}, {DSI_TCPTIMEOUT, 0}};
        struct sigaction newact, oldact;
        u_int8_t block[DSI_BLOCKSIZ];
        size_t stored;

        /* Immediateyl mark globally that we're a child now */
        parent_or_child = 1;

        /* reset signals */
        server_reset_signal();

#ifndef DEBUGGING
        /* install an alarm to deal with non-responsive connections */
        newact.sa_handler = timeout_handler;
        sigemptyset(&newact.sa_mask);
        newact.sa_flags = 0;
        sigemptyset(&oldact.sa_mask);
        oldact.sa_flags = 0;
        setitimer(ITIMER_PROF, &itimer, NULL);

        if ((sigaction(SIGALRM, &newact, &oldact) < 0) ||
            (setitimer(ITIMER_REAL, &timer, NULL) < 0)) {
            LOG(log_error, logtype_dsi, "dsi_tcp_open: %s", strerror(errno));
            exit(EXITERR_SYS);
        }
#endif

        /* read in commands. this is similar to dsi_receive except
         * for the fact that we do some sanity checking to prevent
         * delinquent connections from causing mischief. */

        /* read in the first two bytes */
        len = dsi_stream_read(dsi, block, 2);
        if (!len ) {
            /* connection already closed, don't log it (normal OSX 10.3 behaviour) */
            exit(EXITERR_CLNT);
        }
        if (len < 2 || (block[0] > DSIFL_MAX) || (block[1] > DSIFUNC_MAX)) {
            LOG(log_error, logtype_dsi, "dsi_tcp_open: invalid header");
            exit(EXITERR_CLNT);
        }

        /* read in the rest of the header */
        stored = 2;
        while (stored < DSI_BLOCKSIZ) {
            len = dsi_stream_read(dsi, block + stored, sizeof(block) - stored);
            if (len > 0)
                stored += len;
            else {
                LOG(log_error, logtype_dsi, "dsi_tcp_open: stream_read: %s", strerror(errno));
                exit(EXITERR_CLNT);
            }
        }

        dsi->header.dsi_flags = block[0];
        dsi->header.dsi_command = block[1];
        memcpy(&dsi->header.dsi_requestID, block + 2,
               sizeof(dsi->header.dsi_requestID));
        memcpy(&dsi->header.dsi_code, block + 4, sizeof(dsi->header.dsi_code));
        memcpy(&dsi->header.dsi_len, block + 8, sizeof(dsi->header.dsi_len));
        memcpy(&dsi->header.dsi_reserved, block + 12,
               sizeof(dsi->header.dsi_reserved));
        dsi->clientID = ntohs(dsi->header.dsi_requestID);

        /* make sure we don't over-write our buffers. */
        dsi->cmdlen = min(ntohl(dsi->header.dsi_len), DSI_CMDSIZ);

        stored = 0;
        while (stored < dsi->cmdlen) {
            len = dsi_stream_read(dsi, dsi->commands + stored, dsi->cmdlen - stored);
            if (len > 0)
                stored += len;
            else {
                LOG(log_error, logtype_dsi, "dsi_tcp_open: stream_read: %s", strerror(errno));
                exit(EXITERR_CLNT);
            }
        }

        /* stop timer and restore signal handler */
#ifndef DEBUGGING
        memset(&timer, 0, sizeof(timer));
        setitimer(ITIMER_REAL, &timer, NULL);
        sigaction(SIGALRM, &oldact, NULL);
#endif

        LOG(log_info, logtype_dsi, "AFP/TCP session from %s:%u",
            getip_string((struct sockaddr *)&dsi->client),
            getip_port((struct sockaddr *)&dsi->client));
    }

    /* send back our pid */
    return pid;
}
Beispiel #2
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);
}