/*
 * put client socket in non blocking mode and
 * create a prelude_io object for IO abstraction.
 *
 * Tell server-logic to handle event on the newly accepted client.
 */
static int setup_client_socket(server_generic_t *server,
                               server_generic_client_t *cdata, int client)
{
        int ret;

#ifdef HAVE_TCP_WRAPPERS
        if ( server->sa->sa_family != AF_UNIX ) {
                ret = tcpd_auth(cdata, client);
                if ( ret < 0 )
                        return -1;
        }
#endif
        /*
         * set client socket non blocking.
         */
#if ! ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__)
        ret = fcntl(client, F_SETFL, O_NONBLOCK);
        if ( ret < 0 )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "could not set non blocking mode for client: %s", strerror(errno));

        fcntl(client, F_SETFD, fcntl(client, F_GETFD) | FD_CLOEXEC);
#endif

        ret = prelude_io_new(&cdata->fd);
        if ( ret < 0 )
                return ret;

        prelude_io_set_sys_io(cdata->fd, client);

        cdata->msg = NULL;
        cdata->state = 0;

        return 0;
}
Exemple #2
0
static int process_event(prelude_client_profile_t *cp, int server_sock, prelude_io_t *fd,
                         gnutls_x509_privkey_t key, gnutls_x509_crt_t cacrt, gnutls_x509_crt_t crt)
{
        char buf[512];
        void *inaddr;
        socklen_t len;
        int ret, csock;
        union {
                struct sockaddr sa;
#ifndef HAVE_IPV6
                struct sockaddr_in addr;
# define ADDR_PORT(x) (x).sin_port
#else
                struct sockaddr_in6 addr;
# define ADDR_PORT(x) (x).sin6_port
#endif
        } addr;

        len = sizeof(addr.addr);

        csock = accept(server_sock, &addr.sa, &len);
        if ( csock < 0 ) {
                fprintf(stderr, "accept returned an error: %s.\n", strerror(errno));
                return -1;
        }

        inaddr = prelude_sockaddr_get_inaddr(&addr.sa);
        if ( ! inaddr )
                return -1;

        inet_ntop(addr.sa.sa_family, inaddr, buf, sizeof(buf));
        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ":%u", ntohs(ADDR_PORT(addr.addr)));

        prelude_io_set_sys_io(fd, csock);

        fprintf(stderr, "\nConnection from %s...\n", buf);
        ret = handle_client_connection("", cp, fd, key, cacrt, crt);
        if ( ret == 0 )
                fprintf(stderr, "%s successfully registered.\n", buf);

        prelude_io_close(fd);

        return ret;
}
static int send_queued_alert(server_generic_client_t *client)
{
        int ret;

        do {
                ret = gnutls_alert_send(prelude_io_get_fdptr(client->fd), GNUTLS_AL_FATAL, client->alert);
        } while ( ret < 0 && ret == GNUTLS_E_INTERRUPTED );

        if ( ret == GNUTLS_E_AGAIN ) {
                server_generic_notify_write_enable(client);
                return 0;
        }

        client->alert = 0;
        gnutls_deinit(prelude_io_get_fdptr(client->fd));
        prelude_io_set_sys_io(client->fd, prelude_io_get_fd(client->fd));

        return 1;
}