<commit_before>/*
 * IPCP and flow management functionalities exported by the kernel.
 *
 * Copyright (C) 2015-2016 Nextworks
 * Author: <NAME> <<EMAIL>>
 *
 * This file is part of rlite.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <poll.h>
#include <unistd.h>
#include <sys/ioctl.h>

#include "rlite/conf.h"

static struct rl_msg_base *
wait_for_next_msg(int fd, int timeout)
{
    struct pollfd pfd;
    int ret;

    pfd.fd     = fd;
    pfd.events = POLLIN;

    ret = poll(&pfd, 1, timeout);
    if (ret <= 0) {
        if (ret == 0) {
            errno = ETIMEDOUT;
        }
        return NULL;
    }

    return rl_read_next_msg(fd, 1);
}

/* Create an IPC process. */
long int
rl_conf_ipcp_create(const char *name, const char *dif_type,
                    const char *dif_name)
{
    struct rl_kmsg_ipcp_create msg;
    struct rl_kmsg_ipcp_create_resp *resp;
    long int ret = -1;
    int fd;

    fd = rina_open();
    if (fd < 0) {
        return fd;
    }

    memset(&msg, 0, sizeof(msg));
    msg.msg_type = RLITE_KER_IPCP_CREATE;
    msg.event_id = 1;
    msg.name     = name ? rl_strdup(name, RL_MT_UTILS) : NULL;
    msg.dif_type = rl_strdup(dif_type, RL_MT_UTILS);
    msg.dif_name = rl_strdup(dif_name, RL_MT_UTILS);

    ret = rl_write_msg(fd, RLITE_MB(&msg), 0);
    if (ret < 0) {
        rl_msg_free(rl_ker_numtables, RLITE_KER_MSG_MAX, RLITE_MB(&msg));
        goto out;
    }

    resp = (struct rl_kmsg_ipcp_create_resp *)wait_for_next_msg(fd, 3000);
    if (!resp) {
        ret = -1L;
        rl_msg_free(rl_ker_numtables, RLITE_KER_MSG_MAX, RLITE_MB(&msg));
        goto out;
    }

    ret = resp->ipcp_id;

    rl_msg_free(rl_ker_numtables, RLITE_KER_MSG_MAX, RLITE_MB(&msg));
    rl_msg_free(rl_ker_numtables, RLITE_KER_MSG_MAX, RLITE_MB(resp));
    rl_free(resp, RL_MT_MSG);
out:
    close(fd);

    return ret;
}

/* Wait for an uIPCP to show up. */
int
rl_conf_ipcp_uipcp_wait(rl_ipcp_id_t ipcp_id)
{
    struct rl_kmsg_ipcp_uipcp_wait msg;
    int ret;
    int fd;

    fd = rina_open();
    if (fd < 0) {
        return fd;
    }

    memset(&msg, 0, sizeof(msg));
    msg.msg_type = RLITE_KER_IPCP_UIPCP_WAIT;
    msg.event_id = 1;
    msg.ipcp_id  = ipcp_id;

    ret = rl_write_msg(fd, RLITE_MB(&msg), 0);
    rl_msg_free(rl_ker_numtables, RLITE_KER_MSG_MAX, RLITE_MB(&msg));
    close(fd);

    return ret;
}

/* Destroy an IPC process. */
int
rl_conf_ipcp_destroy(rl_ipcp_id_t ipcp_id, const int sync)
{
    struct rl_kmsg_ipcp_destroy msg;
    int ret;
    int fd;

    fd = rina_open();
    if (fd < 0) {
        return fd;
    }

    if (sync) {
        ret = ioctl(fd, RLITE_IOCTL_CHFLAGS, RL_F_IPCPS);
        if (ret < 0) {
            perror("ioctl()");
            return ret;
        }
    }

    memset(&msg, 0, sizeof(msg));
    msg.msg_type = RLITE_KER_IPCP_DESTROY;
    msg.event_id = 1;
    msg.ipcp_id  = ipcp_id;

    ret = rl_write_msg(fd, RLITE_MB(&msg), 0);
    rl_msg_free(rl_ker_numtables, RLITE_KER_MSG_MAX, RLITE_MB(&msg));

    /* Possibly wait for the kernel to notify us about the IPCP being
     * removed by the kernel (once all the references are gone) . */
    while (sync) {
        struct rl_kmsg_ipcp_update *upd;

        upd = (struct rl_kmsg_ipcp_update *)rl_read_next_msg(fd, 1);
        if (!upd) {
            if (errno) {
                perror("rl_read_next_msg()");
            }
            break;
        }
        assert(upd->msg_type == RLITE_KER_IPCP_UPDATE);

        if (upd->update_type == RL_IPCP_UPDATE_DEL && upd->ipcp_id == ipcp_id) {
            break;
        }
        rl_msg_free(rl_ker_numtables, RLITE_KER_MSG_MAX, RLITE_MB(upd));
        rl_free(upd, RL_MT_MSG);
    }

    close(fd);

    return ret;
}

static int
rl_ipcp_config_fill(struct rl_kmsg_ipcp_config *req, rl_ipcp_id_t ipcp_id,
                    const char *param_name, const char *param_value)
{
    memset(req, 0, sizeof(*req));
    req->msg_type = RLITE_KER_IPCP_CONFIG;
    req->event_id = 1;<commit_msg>lib: conf: ipcp_destroy: don't wait response on error<commit_after>/*
 * IPCP and flow management functionalities exported by the kernel.
 *
 * Copyright (C) 2015-2016 Nextworks
 * Author: <NAME> <<EMAIL>>
 *
 * This file is part of rlite.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <poll.h>
#include <unistd.h>
#include <sys/ioctl.h>

#include "rlite/conf.h"

static struct rl_msg_base *
wait_for_next_msg(int fd, int timeout)
{
    struct pollfd pfd;
    int ret;

    pfd.fd     = fd;
    pfd.events = POLLIN;

    ret = poll(&pfd, 1, timeout);
    if (ret <= 0) {
        if (ret == 0) {
            errno = ETIMEDOUT;
        }
        return NULL;
    }

    return rl_read_next_msg(fd, 1);
}

/* Create an IPC process. */
long int
rl_conf_ipcp_create(const char *name, const char *dif_type,
                    const char *dif_name)
{
    struct rl_kmsg_ipcp_create msg;
    struct rl_kmsg_ipcp_create_resp *resp;
    long int ret = -1;
    int fd;

    fd = rina_open();
    if (fd < 0) {
        return fd;
    }

    memset(&msg, 0, sizeof(msg));
    msg.msg_type = RLITE_KER_IPCP_CREATE;
    msg.event_id = 1;
    msg.name     = name ? rl_strdup(name, RL_MT_UTILS) : NULL;
    msg.dif_type = rl_strdup(dif_type, RL_MT_UTILS);
    msg.dif_name = rl_strdup(dif_name, RL_MT_UTILS);

    ret = rl_write_msg(fd, RLITE_MB(&msg), 0);
    if (ret < 0) {
        rl_msg_free(rl_ker_numtables, RLITE_KER_MSG_MAX, RLITE_MB(&msg));
        goto out;
    }

    resp = (struct rl_kmsg_ipcp_create_resp *)wait_for_next_msg(fd, 3000);
    if (!resp) {
        ret = -1L;
        rl_msg_free(rl_ker_numtables, RLITE_KER_MSG_MAX, RLITE_MB(&msg));
        goto out;
    }

    ret = resp->ipcp_id;

    rl_msg_free(rl_ker_numtables, RLITE_KER_MSG_MAX, RLITE_MB(&msg));
    rl_msg_free(rl_ker_numtables, RLITE_KER_MSG_MAX, RLITE_MB(resp));
    rl_free(resp, RL_MT_MSG);
out:
    close(fd);

    return ret;
}

/* Wait for an uIPCP to show up. */
int
rl_conf_ipcp_uipcp_wait(rl_ipcp_id_t ipcp_id)
{
    struct rl_kmsg_ipcp_uipcp_wait msg;
    int ret;
    int fd;

    fd = rina_open();
    if (fd < 0) {
        return fd;
    }

    memset(&msg, 0, sizeof(msg));
    msg.msg_type = RLITE_KER_IPCP_UIPCP_WAIT;
    msg.event_id = 1;
    msg.ipcp_id  = ipcp_id;

    ret = rl_write_msg(fd, RLITE_MB(&msg), 0);
    rl_msg_free(rl_ker_numtables, RLITE_KER_MSG_MAX, RLITE_MB(&msg));
    close(fd);

    return ret;
}

/* Destroy an IPC process. */
int
rl_conf_ipcp_destroy(rl_ipcp_id_t ipcp_id, const int sync)
{
    struct rl_kmsg_ipcp_destroy msg;
    int ret;
    int fd;

    fd = rina_open();
    if (fd < 0) {
        return fd;
    }

    if (sync) {
        ret = ioctl(fd, RLITE_IOCTL_CHFLAGS, RL_F_IPCPS);
        if (ret < 0) {
            perror("ioctl()");
            return ret;
        }
    }

    memset(&msg, 0, sizeof(msg));
    msg.msg_type = RLITE_KER_IPCP_DESTROY;
    msg.event_id = 1;
    msg.ipcp_id  = ipcp_id;

    ret = rl_write_msg(fd, RLITE_MB(&msg), 0);
    rl_msg_free(rl_ker_numtables, RLITE_KER_MSG_MAX, RLITE_MB(&msg));

    /* Possibly wait for the kernel to notify us about the IPCP being
     * removed by the kernel (once all the references are gone) . */
    while (!ret && sync) {
        struct rl_kmsg_ipcp_update *upd;

        upd = (struct rl_kmsg_ipcp_update *)rl_read_next_msg(fd, 1);
        if (!upd) {
            if (errno) {
                perror("rl_read_next_msg()");
            }
            break;
        }
        assert(upd->msg_type == RLITE_KER_IPCP_UPDATE);

        if (upd->update_type == RL_IPCP_UPDATE_DEL && upd->ipcp_id == ipcp_id) {
            break;
        }
        rl_msg_free(rl_ker_numtables, RLITE_KER_MSG_MAX, RLITE_MB(upd));
        rl_free(upd, RL_MT_MSG);
    }

    close(fd);

    return ret;
}

static int
rl_ipcp_config_fill(struct rl_kmsg_ipcp_config *req, rl_ipcp_id_t ipcp_id,
                    const char *param_name, const char *param_value)
{
    memset(req, 0, sizeof(*req));
    req->msg_type = RLITE_KER_IPCP_CONFIG;
    req->event_id = 1;
{'fraction_non_alphanumeric': 0.10874532613211467, 'fraction_numerical': 0.009970918155380142, 'mean_word_length': 2.7379658385093166, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3345149', 'n_tokens_mistral': 3850, 'n_tokens_neox': 3627, 'n_words': 909}