Beispiel #1
0
/* Just IPv4 for now... */
int mk_socket_server(char *port, char *listen_addr,
                     int reuse_port, struct mk_server *server)
{
    int ret;
    int socket_fd = -1;
    struct addrinfo hints;
    struct addrinfo *res, *rp;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    ret = getaddrinfo(listen_addr, port, &hints, &res);
    if(ret != 0) {
        mk_err("Can't get addr info: %s", gai_strerror(ret));
        return -1;
    }

    for (rp = res; rp != NULL; rp = rp->ai_next) {
        socket_fd = mk_socket_create(rp->ai_family,
                                     rp->ai_socktype, rp->ai_protocol);
        if (socket_fd == -1) {
            mk_warn("Error creating server socket, retrying");
            continue;
        }

        ret = mk_socket_set_tcp_nodelay(socket_fd);
        if (ret == -1) {
            mk_warn("Could not set TCP_NODELAY");
        }

        mk_socket_reset(socket_fd);

        /* Check if reuse port can be enabled on this socket */
        if (reuse_port == MK_TRUE &&
            (server->kernel_features & MK_KERNEL_SO_REUSEPORT)) {
            ret = mk_socket_set_tcp_reuseport(socket_fd);
            if (ret == -1) {
                mk_warn("Could not use SO_REUSEPORT, using fair balancing mode");
                server->scheduler_mode = MK_SCHEDULER_FAIR_BALANCING;
            }
        }

        ret = mk_socket_bind(socket_fd, rp->ai_addr, rp->ai_addrlen,
                             MK_SOMAXCONN, server);
        if(ret == -1) {
            mk_err("Cannot listen on %s:%s", listen_addr, port);
            freeaddrinfo(res);
            return -1;
        }
        break;
    }
    freeaddrinfo(res);

    if (rp == NULL)
        return -1;

    return socket_fd;
}
Beispiel #2
0
/* Run current process in background mode (daemon, evil Monkey >:) */
int mk_utils_set_daemon()
{
    pid_t pid;

    if ((pid = fork()) < 0){
		mk_err("Error: Failed creating to switch to daemon mode(fork failed)");
        exit(EXIT_FAILURE);
	}

    if (pid > 0) /* parent */
        exit(EXIT_SUCCESS);

    /* set files mask */
    umask(0);

    /* Create new session */
    setsid();

    if (chdir("/") < 0) { /* make sure we can unmount the inherited filesystem */
        mk_err("Error: Unable to unmount the inherited filesystem in the daemon process");
        exit(EXIT_FAILURE);
	}

    /* Our last STDOUT messages */
    mk_details();
    mk_info("Background mode ON");

    fclose(stderr);
    fclose(stdout);

    return 0;
}
Beispiel #3
0
int _mkp_network_io_server(int port, char *listen_addr, int reuse_port)
{
    int socket_fd = -1;
    int ret;
    char *port_str = 0;
    unsigned long len;
    struct addrinfo hints;
    struct addrinfo *res, *rp;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    mk_api->str_build(&port_str, &len, "%d", port);

    ret = getaddrinfo(listen_addr, port_str, &hints, &res);
    mk_api->mem_free(port_str);
    if(ret != 0) {
        mk_err("Can't get addr info: %s", gai_strerror(ret));
        return -1;
    }

    for(rp = res; rp != NULL; rp = rp->ai_next) {
        socket_fd = _mkp_network_io_create_socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);

        if( socket_fd == -1) {
            mk_warn("Error creating server socket, retrying");
            continue;
        }

        mk_api->socket_set_tcp_nodelay(socket_fd);
        mk_api->socket_reset(socket_fd);

        /* Check if reuse port can be enabled on this socket */
        if (reuse_port == MK_TRUE &&
            (mk_api->config->kernel_features & MK_KERNEL_SO_REUSEPORT)) {
            ret = mk_api->socket_set_tcp_reuseport(socket_fd);
            if (ret == -1) {
                mk_warn("Could not use SO_REUSEPORT, using fair balancing mode");
                mk_api->config->scheduler_mode = MK_SCHEDULER_FAIR_BALANCING;
            }
        }

        ret = _mkp_network_io_bind(socket_fd, rp->ai_addr, rp->ai_addrlen, MK_SOMAXCONN);
        if(ret == -1) {
            mk_err("Cannot listen on %s:%i\n", listen_addr, port);
            continue;
        }
        break;
    }
    freeaddrinfo(res);

    if (rp == NULL)
        return -1;

    return socket_fd;
}
Beispiel #4
0
static struct proxy_server_entry_array *proxy_parse_ServerList(char
                                                               *server_addr)
{
    char *tmp;
    int server_num = 0;
    struct mk_string_line *entry;
    struct mk_list *line, *head;
    struct mk_list *server_list = mk_api->str_split_line(server_addr);
    struct proxy_server_entry_array *proxy_server_array = 0;

    if (!server_addr) {
        return 0;
    }

    line = mk_api->str_split_line(server_addr);
    if (!line) {
        return 0;
    }

    mk_list_foreach(head, line) {
        server_num++;
    }
    if (!server_num) {
        return 0;
    }

    proxy_server_array =
        mk_api->mem_alloc(sizeof(struct proxy_server_entry_array) +
                          sizeof(struct proxy_server_entry) * server_num);
    if (!proxy_server_array) {
        return 0;
    }
    proxy_server_array->length = server_num;

    server_num = 0;
    mk_list_foreach(head, line) {
        entry = mk_list_entry(head, struct mk_string_line, _head);
        if (!entry) {
            mk_err("ProxyReverse: Invalid configuration ServerList");
            mk_api->mem_free(proxy_server_array);
            return 0;
        }

        tmp = memchr(entry->val, ':', entry->len);
        if (!tmp) {
            mk_err("ProxyReverse: Invalid configuration ServerList");
            mk_api->mem_free(proxy_server_array);
            return 0;
        }

        *tmp = '\0';

        proxy_server_array->entry[server_num].hostname =
            mk_api->str_dup(entry->val);
        proxy_server_array->entry[server_num].port = strtol(tmp + 1, 0, 10);

        server_num++;
    }
Beispiel #5
0
/* Write Monkey's PID */
int mk_utils_register_pid()
{
    int fd;
    char pidstr[MK_MAX_PID_LEN];
    unsigned long len = 0;
    char *filepath = NULL;
    struct flock lock;
    struct stat sb;
    struct mk_config_listener *listen;

    if (config->pid_status == MK_TRUE)
        return -1;

    listen = mk_list_entry_first(&config->listeners,
                                 struct mk_config_listener, _head);
    mk_string_build(&filepath, &len, "%s.%s",
                    config->pid_file_path,
                    listen->port);
    if (!stat(filepath, &sb)) {
        /* file exists, perhaps previously kepts by SIGKILL */
        unlink(filepath);
    }

    if ((fd = open(filepath, O_WRONLY | O_CREAT | O_CLOEXEC, 0444)) < 0) {
        mk_err("Error: I can't log pid of monkey");
        exit(EXIT_FAILURE);
    }

    /* create a write exclusive lock for the entire file */
    lock.l_type = F_WRLCK;
    lock.l_start = 0;
    lock.l_whence = SEEK_SET;
    lock.l_len = 0;

    if (fcntl(fd, F_SETLK, &lock) < 0) {
        close(fd);
        mk_err("Error: I cannot set the lock for the pid of monkey");
        exit(EXIT_FAILURE);
    }

    sprintf(pidstr, "%i", getpid());
    ssize_t write_len = strlen(pidstr);
    if (write(fd, pidstr, write_len) != write_len) {
        close(fd);
        mk_err("Error: I cannot write the lock for the pid of monkey");
        exit(EXIT_FAILURE);
    }

    mk_mem_free(filepath);
    config->pid_status = MK_TRUE;

    return 0;
}
Beispiel #6
0
/* Write Monkey's PID */
int mk_utils_register_pid(char *path)
{
    int fd;
    int ret;
    char pidstr[MK_MAX_PID_LEN];
    struct flock lock;
    struct stat sb;

    if (stat(path, &sb) == 0) {
        /* file exists, perhaps previously kepts by SIGKILL */
        ret = unlink(path);
        if (ret == -1) {
            mk_err("Could not remove old PID-file path");
            exit(EXIT_FAILURE);
        }

    }

#ifdef __rtems__
#define MK_UTILS_OPEN_FLAGS ( O_WRONLY | O_CREAT )
#else
#define MK_UTILS_OPEN_FLAGS ( O_WRONLY | O_CREAT | O_CLOEXEC )
#endif

    if ((fd = open(path,
                   MK_UTILS_OPEN_FLAGS, 0444)) < 0) {
        mk_err("Error: I can't log pid of monkey");
        exit(EXIT_FAILURE);
    }

    /* create a write exclusive lock for the entire file */
    lock.l_type = F_WRLCK;
    lock.l_start = 0;
    lock.l_whence = SEEK_SET;
    lock.l_len = 0;

    if (fcntl(fd, F_SETLK, &lock) < 0) {
        close(fd);
        mk_err("Error: I cannot set the lock for the pid of monkey");
        exit(EXIT_FAILURE);
    }

    sprintf(pidstr, "%i", getpid());
    ssize_t write_len = strlen(pidstr);
    if (write(fd, pidstr, write_len) != write_len) {
        close(fd);
        mk_err("Error: I cannot write the lock for the pid of monkey");
        exit(EXIT_FAILURE);
    }

    close(fd);
    return 0;
}
Beispiel #7
0
/* Return process to the original user */
int mk_user_undo_uidgid()
{
    if (config->is_seteuid == MK_TRUE) {
        if (setegid(0) < 0) {
            mk_err("Can't restore effective GID");
        }
        if (seteuid(0) < 0) {
            mk_err("Can't restore effective UID");
        }
    }
    return 0;
}
Beispiel #8
0
int _mkp_network_io_server(int port, char *listen_addr)
{
    int socket_fd = -1;
    int ret;
    char *port_str = 0;
    unsigned long len;
    struct addrinfo hints;
    struct addrinfo *res, *rp;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    mk_api->str_build(&port_str, &len, "%d", port);

    ret = getaddrinfo(listen_addr, port_str, &hints, &res);
    mk_api->mem_free(port_str);
    if(ret != 0) {
        mk_err("Can't get addr info: %s", gai_strerror(ret));
        return -1;
    }

    for(rp = res; rp != NULL; rp = rp->ai_next) {
        socket_fd = _mkp_network_io_create_socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);

        if( socket_fd == -1) {
            mk_warn("Error creating server socket, retrying");
            continue;
        }

        mk_api->socket_set_tcp_nodelay(socket_fd);
        mk_api->socket_reset(socket_fd);
        ret = _mkp_network_io_bind(socket_fd, rp->ai_addr, rp->ai_addrlen, MK_SOMAXCONN);

        if(ret == -1) {
            mk_err("Port %i cannot be used, retrying\n", port);
            continue;
        }
        break;
    }
    freeaddrinfo(res);

    if (rp == NULL)
        return -1;

    return socket_fd;
}
Beispiel #9
0
/* Write Monkey's PID */
int mk_utils_register_pid(char *path)
{
    int fd;
    int ret;
    char pidstr[MK_MAX_PID_LEN];
    struct flock lock;
    struct stat sb;

    if (stat(path, &sb) == 0) {
        /* file exists, perhaps previously kepts by SIGKILL */
        ret = unlink(path);
        if (ret == -1) {
            mk_err("Could not remove old PID-file path: %s", path);
            exit(EXIT_FAILURE);
        }
    }

    if ((fd = open(path,
                   O_WRONLY | O_CREAT | O_CLOEXEC, 0444)) < 0) {
        mk_err("I cannot create PID file '%s'", path);
        exit(EXIT_FAILURE);
    }

    /* create a write exclusive lock for the entire file */
    lock.l_type = F_WRLCK;
    lock.l_start = 0;
    lock.l_whence = SEEK_SET;
    lock.l_len = 0;

    if (fcntl(fd, F_SETLK, &lock) < 0) {
        close(fd);
        mk_err("I cannot set the lock for the PID file '%s'", path);
        exit(EXIT_FAILURE);
    }

    sprintf(pidstr, "%i", getpid());
    ssize_t write_len = strlen(pidstr);
    if (write(fd, pidstr, write_len) != write_len) {
        close(fd);
        mk_err("I cannot write PID number at '%s' file", path);
        exit(EXIT_FAILURE);
    }

    close(fd);
    return 0;
}
Beispiel #10
0
/* Write Monkey's PID */
int mk_utils_register_pid()
{
    int fd;
    char pidstr[MK_MAX_PID_LEN];
    struct flock lock;
    struct stat sb;

    if (mk_config->pid_status == MK_TRUE)
        return -1;

    if (!stat(mk_config->pid_file_path, &sb)) {
        /* file exists, perhaps previously kepts by SIGKILL */
        unlink(mk_config->pid_file_path);
    }

    if ((fd = open(mk_config->pid_file_path,
                   O_WRONLY | O_CREAT | O_CLOEXEC, 0444)) < 0) {
        mk_err("Error: I can't log pid of monkey");
        exit(EXIT_FAILURE);
    }

    /* create a write exclusive lock for the entire file */
    lock.l_type = F_WRLCK;
    lock.l_start = 0;
    lock.l_whence = SEEK_SET;
    lock.l_len = 0;

    if (fcntl(fd, F_SETLK, &lock) < 0) {
        close(fd);
        mk_err("Error: I cannot set the lock for the pid of monkey");
        exit(EXIT_FAILURE);
    }

    sprintf(pidstr, "%i", getpid());
    ssize_t write_len = strlen(pidstr);
    if (write(fd, pidstr, write_len) != write_len) {
        close(fd);
        mk_err("Error: I cannot write the lock for the pid of monkey");
        exit(EXIT_FAILURE);
    }

    mk_config->pid_status = MK_TRUE;

    return 0;
}
Beispiel #11
0
/* We need to know how to solve the problem with AF_INET and AF_INET6 */
int _mkp_network_io_connect(char *host, int port)
{
    int ret;
    int socket_fd = -1;
    char *port_str = 0;
    unsigned long len;
    struct addrinfo hints;
    struct addrinfo *res, *rp;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    mk_api->str_build(&port_str, &len, "%d", port);

    ret = getaddrinfo(host, port_str, &hints, &res);
    mk_api->mem_free(port_str);
    if(ret != 0) {
        mk_err("Can't get addr info: %s", gai_strerror(ret));
        return -1;
    }
    for(rp = res; rp != NULL; rp = rp->ai_next) {
        socket_fd = _mkp_network_io_create_socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);

        if( socket_fd == -1) {
            mk_warn("Error creating client socket, retrying");
            continue;
        }

        if (connect(socket_fd,
                    (struct sockaddr *) rp->ai_addr, rp->ai_addrlen) == -1) {
            close(socket_fd);
            mk_err("Can't connect to %s, retrying", host);
            continue;
        }

        break;
    }
    freeaddrinfo(res);

    if (rp == NULL)
        return -1;

    return socket_fd;
}
Beispiel #12
0
int mk_socket_connect(char *host, int port, int async)
{
    int ret;
    int socket_fd = -1;
    char *port_str = 0;
    unsigned long len;
    struct addrinfo hints;
    struct addrinfo *res, *rp;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    mk_string_build(&port_str, &len, "%d", port);

    ret = getaddrinfo(host, port_str, &hints, &res);
    mk_mem_free(port_str);
    if(ret != 0) {
        mk_err("Can't get addr info: %s", gai_strerror(ret));
        return -1;
    }
    for (rp = res; rp != NULL; rp = rp->ai_next) {
        socket_fd = mk_socket_create(rp->ai_family,
                                     rp->ai_socktype, rp->ai_protocol);

        if (socket_fd == -1) {
            mk_warn("Error creating client socket, retrying");
            continue;
        }

        if (async == MK_TRUE) {
            mk_socket_set_nonblocking(socket_fd);
        }

        ret = connect(socket_fd,
                      (struct sockaddr *) rp->ai_addr, rp->ai_addrlen);
        if (ret == -1) {
            if (errno == EINPROGRESS) {
                break;
            }
            else {
                printf("%s", strerror(errno));
                perror("connect");
                exit(1);
                close(socket_fd);
                continue;
            }
        }
        break;
    }
    freeaddrinfo(res);

    if (rp == NULL)
        return -1;

    return socket_fd;
}
//duda_package_t *duda_package_load(const char *pkgname)
duda_package_t *duda_package_load(const char *pkgname, struct duda_api_objects *api)
{
    int ret;
    char *package = NULL;
    void *handle = NULL;
    unsigned long len;
    struct file_info finfo;
    duda_package_t *(*init_pkg)() = NULL;
    duda_package_t *package_info;

    mk_api->str_build(&package, &len, "%s/%s.dpkg", packages_root, pkgname);
    ret = mk_api->file_get_info(package, &finfo);

    if (ret != 0) {
        mk_err("Duda: Package '%s' not found", pkgname);
        mk_api->mem_free(package);
        exit(EXIT_FAILURE);
    }

    if (finfo.is_file == MK_FALSE) {
        mk_warn("Duda: Invalid Package '%s'", pkgname);
        mk_api->mem_free(package);
        return NULL;
    }

    handle = duda_load_library(package);
    if (!handle) {
        mk_warn("Duda: Invalid Package format '%s'", pkgname);
        mk_api->mem_free(package);
        return NULL;
    }

    init_pkg = duda_load_symbol(handle, "init_duda_package");
    if (!init_pkg) {
        mk_err("Duda: the package '%s' is broken", pkgname);
        exit(EXIT_FAILURE);
    }

    package_info = init_pkg(api);
    mk_api->mem_free(package);

    return package_info;
}
Beispiel #14
0
/* Change process user */
int mk_user_set_uidgid()
{
    struct passwd *usr;

    /* Launched by root ? */
    if (geteuid() == 0 && config->user) {
        struct rlimit rl;

        if (getrlimit(RLIMIT_NOFILE, &rl)) {
            mk_warn("cannot get resource limits");
        }

        /* Check if user exists  */
        if ((usr = getpwnam(config->user)) == NULL) {
            mk_err("Invalid user '%s'", config->user);
            goto out;
        }

        if (initgroups(config->user, usr->pw_gid) != 0) {
            mk_err("Initgroups() failed");
        }

        /* Change process UID and GID */
        if (setegid(usr->pw_gid) == -1) {
            mk_err("I cannot change the GID to %u", usr->pw_gid);
        }

        if (seteuid(usr->pw_uid) == -1) {
            mk_err("I cannot change the UID to %u", usr->pw_uid);
        }

        config->is_seteuid = MK_TRUE;
    }

    out:

    /* Variables set for run checks on file permission */
    EUID = geteuid();
    EGID = getegid();

    return 0;
}
Beispiel #15
0
int mk_socket_set_nonblocking(int sockfd)
{

    MK_TRACE("Socket, set FD %i to non-blocking", sockfd);

    if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0) | O_NONBLOCK | O_CLOEXEC) == -1) {
        mk_err("Can't set to non-blocking mode socket %i", sockfd);
        return -1;
    }
    return 0;
}
Beispiel #16
0
int mk_epoll_create(int max_events)
{
    int efd;

    efd = epoll_create(max_events);
    if (efd == -1) {
        perror("epoll_create");
        mk_err("epoll_create() failed");
    }

    return efd;
}
Beispiel #17
0
/* Just IPv4 for now... */
int mk_socket_server(char *port, char *listen_addr, int reuse_port)
{
    int socket_fd;

    if (!mk_config->network) {
        mk_err("No network layer plugin was found. Aborting.");
        exit(EXIT_FAILURE);
    }

    socket_fd = mk_config->network->server(port, listen_addr, reuse_port);
    if (socket_fd < 0) {
        exit(EXIT_FAILURE);
    }

    return socket_fd;
}
Beispiel #18
0
/*
 * Read the main configuration file for dirhtml: dirhtml.conf,
 * it will alloc the dirhtml_conf struct
*/
int mk_dirhtml_read_config(char *path)
{
    unsigned long len;
    char *default_file = NULL;
    struct mk_rconf *conf;
    struct mk_rconf_section *section;
    struct file_info finfo;

    mk_api->str_build(&default_file, &len, "%sdirhtml.conf", path);
    conf = mk_api->config_create(default_file);
    if (!conf) {
        return -1;
    }

    section = mk_api->config_section_get(conf, "DIRLISTING");
    if (!section) {
        mk_err("Could not find DIRLISTING tag in configuration file");
        exit(EXIT_FAILURE);
    }

    /* alloc dirhtml config struct */
    dirhtml_conf = mk_api->mem_alloc(sizeof(struct dirhtml_config));
    dirhtml_conf->theme = mk_api->config_section_get_key(section, "Theme",
                                                         MK_RCONF_STR);
    dirhtml_conf->theme_path = NULL;

    mk_api->str_build(&dirhtml_conf->theme_path, &len,
                      "%sthemes/%s/", path, dirhtml_conf->theme);
    mk_api->mem_free(default_file);

    if (mk_api->file_get_info(dirhtml_conf->theme_path,
                              &finfo, MK_FILE_READ) != 0) {
        mk_warn("Dirlisting: cannot load theme from '%s'", dirhtml_conf->theme_path);
        mk_warn("Dirlisting: unloading plugin");
        return -1;
    }

    mk_api->config_free(conf);
    return 0;
}
Beispiel #19
0
static inline
struct mk_sched_conn *mk_server_listen_handler(struct mk_sched_worker *sched,
                                               void *data)
{
    int ret;
    int client_fd = -1;
    struct mk_sched_conn *conn;
    struct mk_server_listen *listener = data;

    client_fd = mk_socket_accept(listener->server_fd);
    if (mk_unlikely(client_fd == -1)) {
        MK_TRACE("[server] Accept connection failed: %s", strerror(errno));
        goto error;
    }

    conn = mk_sched_add_connection(client_fd, listener, sched);
    if (mk_unlikely(!conn)) {
        goto error;
    }

    ret = mk_event_add(sched->loop, client_fd,
                       MK_EVENT_CONNECTION, MK_EVENT_READ, conn);
    if (mk_unlikely(ret != 0)) {
        mk_err("[server] Error registering file descriptor: %s",
               strerror(errno));
        goto error;
    }

    sched->accepted_connections++;
    MK_TRACE("[server] New connection arrived: FD %i", client_fd);
    return conn;

error:
    if (client_fd != -1) {
        listener->network->network->close(client_fd);
    }

    return NULL;
}
Beispiel #20
0
void mk_cheetah_loop_server()
{
    int n, ret;
    int buf_len;
    unsigned long len;
    char buf[1024];
    char cmd[1024];
    int server_fd;
    int remote_fd;
    size_t address_length;
    struct sockaddr_un address;
    socklen_t socket_size = sizeof(struct sockaddr_in);
    struct mk_config_listener *listener;

    /* Create listening socket */
    server_fd = socket(PF_UNIX, SOCK_STREAM, 0);
    if (server_fd < 0) {
        perror("socket() failed");
        exit(EXIT_FAILURE);
    }

    listener = mk_list_entry_first(&mk_api->config->listeners,
                                   struct mk_config_listener,
                                 _head);
    cheetah_server = NULL;
    mk_api->str_build(&cheetah_server, &len, "/tmp/cheetah.%s",
                      listener->port);
    unlink(cheetah_server);

    address.sun_family = AF_UNIX;
    sprintf(address.sun_path, "%s", cheetah_server);
    address_length = sizeof(address.sun_family) + len + 1;

    if (bind(server_fd, (struct sockaddr *) &address, address_length) != 0) {
        perror("bind");
        mk_err("Cheetah: could not bind address %s", address.sun_path);
        exit(EXIT_FAILURE);
    }

    if (listen(server_fd, 5) != 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    while (1) {
        /* Listen for incoming connections */
        remote_fd = accept(server_fd, (struct sockaddr *) &address, &socket_size);
        cheetah_socket = remote_fd;

        buf_len = 0;
        memset(buf, '\0', 1024);

        /* Send welcome message and prompt */
        mk_cheetah_welcome_msg();
        CHEETAH_WRITE(MK_CHEETAH_PROMPT, ANSI_BOLD, ANSI_GREEN, ANSI_RESET);

        while (1) {
            /* Read incoming data */
            n = read(remote_fd, buf+buf_len, 1024 - buf_len);
            if (n <= 0) {
                break;
            }
            else {
              buf_len += n;
              if (buf[buf_len-1] == '\n') {
                  /* Filter command */
                  strncpy(cmd, buf, buf_len - 1);
                  cmd[buf_len - 1] = '\0';

                  /* Run command */
                  ret = mk_cheetah_cmd(cmd);

                  if (ret == -1) {
                      break;
                  }

                  /* Write prompt */
                  CHEETAH_WRITE(MK_CHEETAH_PROMPT, ANSI_BOLD, ANSI_GREEN, ANSI_RESET);
                  buf_len = 0;
                  memset(buf, '\0', 1024);
              }
            }
        }

        close(remote_fd);
    }
}
Beispiel #21
0
int duda_body_buffer_flush(int sock, struct duda_body_buffer *bb)
{
    int i;
    int count = 0;
    unsigned int bytes_sent, bytes_to;
    int reset_to = -1;
    struct mk_iov *buf = bb->buf;

    /* FIXME: Temporal Check */
    if (mk_unlikely(buf->iov_idx > IOV_MAX)) {
        mk_err("Boddy buffer flush: enqueued data is larger than IOV_MAX (%i)\n",
                IOV_MAX);
        exit(EXIT_FAILURE);
    }

    bytes_sent = mk_api->socket_sendv(sock, buf);
    PLUGIN_TRACE("body_flush: %i/%i", bytes_sent, buf->total_len);
    /*
     * If the call sent less data than total, we must modify the mk_iov struct
     * to mark the buffers already processed and set them with with length = zero,
     * so on the next calls to this function Monkey will skip buffers with bytes
     * length = 0.
     */
    if (bytes_sent < buf->total_len) {
        /* Go around each buffer entry and check where the offset took place */
        for (i = 0; i < buf->iov_idx; i++) {
            if (count + buf->io[i].iov_len == bytes_sent) {
                reset_to = i;
                break;
            }
            else if (bytes_sent < (count + buf->io[i].iov_len)) {
                reset_to = i - 1;
                bytes_to = (bytes_sent - count);
                buf->io[i].iov_base += bytes_to;
                buf->io[i].iov_len   = buf->io[i].iov_len - bytes_to;
                break;
            }
            count += buf->io[i].iov_len;
        }

        /* Reset entries */
        for (i = 0; i <= reset_to; i++) {
            buf->io[i].iov_len = 0;
        }

        buf->total_len -= bytes_sent;

#ifdef TRACE
        PLUGIN_TRACE("new total len: %i (iov_idx=%i)",
                     buf->total_len,
                     buf->iov_idx);
        int j;

        for (j = 0; j < buf->iov_idx; j++) {
            PLUGIN_TRACE("io[%i] = %i", j, buf->io[j].iov_len);
        }
#endif
    }

    /* Successfully end ? */
    if (bytes_sent == buf->total_len) {
        buf->total_len = 0;
        return 0;
    }

    return bytes_sent;
}
Beispiel #22
0
/* Read configuration parameters */
int mk_patas_conf(char *confdir)
{
    int res;
    int val_port;
    char *val_host;
    char *val_uri;
    unsigned long len;
    char *conf_path=NULL;

    struct mk_config_section *section;
    struct mk_config_entry *entry;
    struct mk_patas_node *node;

    /* Init nodes list */
    mk_patas_nodes_list = mk_api->mem_alloc(sizeof(struct mk_list));
    mk_list_init(mk_patas_nodes_list);

    /* Read configuration */
    mk_api->str_build(&conf_path, &len, "%s/patas.conf", confdir);
    conf = mk_api->config_create(conf_path);
    section = mk_api->config_section_get(conf, "NODE");

    while (section) { 
        entry = section->entry;
        val_host = NULL;
        val_port = -1;
        val_uri = NULL;

        /* Get section values */
        val_host = mk_api->config_section_getval(section, "IP", MK_CONFIG_VAL_STR);
        val_port = (int)  mk_api->config_section_getval(section, "Port", MK_CONFIG_VAL_NUM);
        val_uri  = mk_api->config_section_getval(section, "Uri", MK_CONFIG_VAL_LIST);

        if (val_host && val_uri && val_port > 0) {
            /* validate that node:ip is not pointing this server */
            if (mk_patas_validate_node(val_host, val_port) < 0) {
                break;
            }

            /* alloc node */
            node = mk_api->mem_alloc(sizeof(struct mk_patas_node));
            node->host = val_host;
            node->port = val_port;
                
            /* pre-socket stuff */
            node->sockaddr = mk_api->mem_alloc_z(sizeof(struct sockaddr_in));
            node->sockaddr->sin_family = AF_INET;

            res = inet_pton(AF_INET, node->host, 
                            (void *) (&(node->sockaddr->sin_addr.s_addr)));
            if (res < 0) {
                mk_warn("Can't set remote->sin_addr.s_addr");
                mk_api->mem_free(node->sockaddr);
                return -1;
            }
            else if (res == 0) {
                mk_err("Invalid IP address");
                mk_api->mem_free(node->sockaddr);
                return -1;
            }

            node->sockaddr->sin_port = htons(node->port);
                
            /* add node to list */
            PLUGIN_TRACE("Balance Node: %s:%i", val_host, val_port);

            mk_list_add(&node->_head, mk_patas_nodes_list);
            mk_patas_n_nodes++;
        }
        section = section->next;
    }

    mk_api->mem_free(conf_path);
    return 0;
}
Beispiel #23
0
/*
 * Initialize the global Event structure used by threads to access the
 * global file descriptor table.
 */
int mk_event_initalize()
{
    int i;
    int ret;
    mk_event_fdt_t *efdt;
    struct rlimit rlim;

    /*
     * Event File Descriptor Table (EFDT)
     * ----------------------------------
     * The main requirement for this implementation is that we need to maintain
     * a state of each file descriptor registered events, such as READ, WRITE,
     * SLEEPING, etc. This is required not by Monkey core but is a fundamental
     * piece to let plugins perform safe operations over file descriptors and
     * their events.
     *
     * The EFDT is created in the main process context and aims to be used by
     * every Worker thread. Once a connection arrives and it's notified to the
     * Worker, this last one will register the file descriptor status on the
     * EFDT.
     *
     * The EFDT is a fixed size array that contains entries for each possible
     * file descriptor number assigned for a TCP connection. In order to make
     * sure the assigned number can be used as an index of the array, we have
     * verified that the Linux Kernel always assigns a number in a range as
     * defined in __alloc_fd() on file file.c:
     *
     *   start: > 2
     *
     *   end  : rlim.rlim.cur
     *
     * The maximum number assigned is always the process soft limit for
     * RLIMIT_NOFILE, so basically we are safe trusting on this model.
     *
     * Note: as we make sure each file descriptor number is only handled by one
     * thread, there is no race conditions.
     */

    efdt = mk_mem_malloc_z(sizeof(mk_event_fdt_t));
    if (!efdt) {
        mk_err("Event: could not allocate memory for event FD Table");
        return -1;
    }

    /*
     * Despites what config->server_capacity says, we need to prepare to handle
     * a high number of file descriptors as process limit allows.
     */
    ret = getrlimit(RLIMIT_NOFILE, &rlim);
    if (ret == -1) {
        mk_libc_error("getrlimit");
        return -1;
    }
    efdt->size = rlim.rlim_cur;
    efdt->states = mk_mem_malloc_z(sizeof(struct mk_event_fd_state) * efdt->size);
    if (!efdt->states) {
        mk_err("Event: could not allocate memory for events states on FD Table");
        return -1;
    }

    /* mark all file descriptors as available */
    for (i = 0; i < efdt->size; i++) {
        efdt->states[i].fd   = -1;
        efdt->states[i].mask = MK_EVENT_EMPTY;
    }

    mk_events_fdt = efdt;
    return 0;
}