Example #1
0
FLB_INLINE int net_io_tls_write(struct flb_thread *th, struct flb_io_upstream *u,
                     void *data, size_t len, size_t *out_len)
{
    int ret;
    size_t total = 0;

    if (!u->tls_session) {
        u->tls_session = flb_tls_session_new(u->tls->context);
        if (!u->tls_session) {
            flb_error("[io_tls] could not create tls session");
            return -1;
        }

        ret = flb_io_net_tls_connect(u, th);
        if (ret == -1) {
            flb_error("[io_tls] could not connect/initiate TLS session");
            return -1;
        }
    }

 retry_write:
    ret = mbedtls_ssl_write(&u->tls_session->ssl,
                            data + total,
                            len - total);
    if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
        io_tls_event_switch(u, MK_EVENT_WRITE);
        flb_thread_yield(th, FLB_FALSE);
        goto retry_write;
    }
    else if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
        io_tls_event_switch(u, MK_EVENT_READ);
        flb_thread_yield(th, FLB_FALSE);
        goto retry_write;
    }
    else if (ret < 0) {
        char err_buf[72];
        mbedtls_strerror(ret, err_buf, sizeof(err_buf));
        flb_debug("[tls] SSL error: %s", err_buf);

        /* There was an error transmitting data */
        mk_event_del(u->evl, &u->event);
        tls_session_destroy(u->tls_session);
        u->tls_session = NULL;
        return -1;
    }

    /* Update statistics */
    //flb_stats_update(out->stats_fd, ret, 0);

    /* Update counter and check if we need to continue writing */
    total += ret;
    if (total < len) {
        io_tls_event_switch(u, MK_EVENT_WRITE);
        flb_thread_yield(th, FLB_FALSE);
        goto retry_write;
    }

    mk_event_del(u->evl, &u->event);
    return 0;
}
Example #2
0
/* Create a new mqtt request instance */
struct tcp_conn *tcp_conn_add(int fd, struct flb_in_tcp_config *ctx)
{
    int ret;
    struct tcp_conn *conn;
    struct mk_event *event;

    conn = flb_malloc(sizeof(struct tcp_conn));
    if (!conn) {
        return NULL;
    }

    /* Set data for the event-loop */
    event = &conn->event;
    MK_EVENT_NEW(event);
    event->fd           = fd;
    event->type         = FLB_ENGINE_EV_CUSTOM;
    event->handler      = tcp_conn_event;

    /* Connection info */
    conn->fd      = fd;
    conn->ctx     = ctx;
    conn->buf_len = 0;
    conn->rest    = 0;
    conn->status  = TCP_NEW;

    conn->buf_data = flb_malloc(ctx->chunk_size);
    if (!conn->buf_data) {
        perror("malloc");
        close(fd);
        flb_error("[in_tcp] could not allocate new connection");
        flb_free(conn);
        return NULL;
    }
    conn->buf_size = ctx->chunk_size;
    conn->in       = ctx->in;

    /* Initialize JSON parser */
    flb_pack_state_init(&conn->pack_state);

    /* Register instance into the event loop */
    ret = mk_event_add(ctx->evl, fd, FLB_ENGINE_EV_CUSTOM, MK_EVENT_READ, conn);
    if (ret == -1) {
        flb_error("[in_tcp] could not register new connection");
        close(fd);
        flb_free(conn->buf_data);
        flb_free(conn);
        return NULL;
    }

    mk_list_add(&conn->_head, &ctx->connections);

    return conn;
}
Example #3
0
void _io_tls_error(int ret, char *file, int line)
{
    char err_buf[72];

    mbedtls_strerror(ret, err_buf, sizeof(err_buf));
    flb_error("[io_tls] flb_io_tls.c:%i %s", line, err_buf);
}
Example #4
0
/* Initialize plugin */
int in_mqtt_init(struct flb_input_instance *in,
                 struct flb_config *config, void *data)
{
    int ret;
    struct flb_in_mqtt_config *ctx;
    (void) data;

    /* Allocate space for the configuration */
    ctx = mqtt_config_init(in);
    if (!ctx) {
        return -1;
    }
    ctx->msgp_len = 0;

    /* Set the context */
    flb_input_set_context(in, ctx);

    /* Create TCP server */
    ctx->server_fd = flb_net_server(ctx->tcp_port, ctx->listen);
    if (ctx->server_fd > 0) {
        flb_debug("[in_mqtt] binding %s:%s", ctx->listen, ctx->tcp_port);
    }
    else {
        flb_error("[in_mqtt] could not bind address %s:%s",
                  ctx->listen, ctx->tcp_port);
        mqtt_config_free(ctx);
        return -1;
    }
    ctx->evl = config->evl;

    /* Collect upon data available on the standard input */
    ret = flb_input_set_collector_event(in,
                                        in_mqtt_collect,
                                        ctx->server_fd,
                                        config);
    if (ret == -1) {
        flb_error("[in_mqtt] Could not set collector for MQTT input plugin");
        mqtt_config_free(ctx);
        return -1;
    }

    return 0;
}
Example #5
0
static inline int io_tls_event_switch(struct flb_io_upstream *u, int mask)
{
    int ret;
    struct mk_event *event;

    event = &u->event;
    if (event->mask & ~mask) {
        ret = mk_event_add(u->evl,
                           event->fd,
                           FLB_ENGINE_EV_THREAD,
                           mask, &u->event);
        if (ret == -1) {
            flb_error("[io_tls] error changing mask to %i", mask);
            return -1;
        }
    }

    return 0;
}
Example #6
0
/*
 * For a server event, the collection event means a new client have arrived, we
 * accept the connection and create a new MQTT instance which will wait for
 * events/data (MQTT control packages)
 */
int in_mqtt_collect(struct flb_config *config, void *in_context)
{
    int fd;
    struct flb_in_mqtt_config *ctx = in_context;
    struct mqtt_conn *conn;

    /* Accept the new connection */
    fd = flb_net_accept(ctx->server_fd);
    if (fd == -1) {
        flb_error("[in_mqtt] could not accept new connection");
        return -1;
    }

    flb_trace("[in_mqtt] [fd=%i] new TCP connection", fd);
    conn = mqtt_conn_add(fd, ctx);
    if (!conn) {
        return -1;
    }
    return 0;
}
Example #7
0
struct flb_tls_session *flb_tls_session_new(struct flb_tls_context *ctx)
{
    int ret;
    struct flb_tls_session *session;

    session = malloc(sizeof(struct flb_tls_session));
    if (!session) {
        return NULL;
    }

    mbedtls_ssl_init(&session->ssl);
    mbedtls_ssl_config_init(&session->conf);

    ret = mbedtls_ssl_config_defaults(&session->conf,
                                      MBEDTLS_SSL_IS_CLIENT,
                                      MBEDTLS_SSL_TRANSPORT_STREAM,
                                      MBEDTLS_SSL_PRESET_DEFAULT);
    if (ret != 0) {
        io_tls_error(ret);
    }

    mbedtls_ssl_conf_rng(&session->conf,
                         mbedtls_ctr_drbg_random,
                         &ctx->ctr_drbg);
    mbedtls_ssl_conf_authmode(&session->conf, MBEDTLS_SSL_VERIFY_NONE);

    ret = mbedtls_ssl_setup(&session->ssl, &session->conf);
    if (ret == -1) {
        flb_error("[tls] ssl_setup");
        goto error;
    }

    return session;

 error:
    free(session);
    return NULL;
}
Example #8
0
FLB_INLINE int flb_io_net_connect(struct flb_io_upstream *u,
                                  struct flb_thread *th)
{
    int fd;
    int ret;
    int error = 0;
    socklen_t len = sizeof(error);

    if (u->fd > 0) {
        close(u->fd);
    }

    /* Create the socket */
    fd = flb_net_socket_create(AF_INET, FLB_TRUE);
    if (fd == -1) {
        flb_error("[io] could not create socket");
        return -1;
    }
    u->fd = fd;

    /* Make the socket non-blocking */
    flb_net_socket_nonblocking(u->fd);

    /* Start the connection */
    ret = flb_net_tcp_fd_connect(fd, u->tcp_host, u->tcp_port);
    if (ret == -1) {
        if (errno == EINPROGRESS) {
            flb_debug("[upstream] connection in process");
        }
        else {
        }

        u->event.mask = MK_EVENT_EMPTY;
        u->event.status = MK_EVENT_NONE;
        u->thread = th;

        ret = mk_event_add(u->evl,
                           fd,
                           FLB_ENGINE_EV_THREAD,
                           MK_EVENT_WRITE, &u->event);
        if (ret == -1) {
            /*
             * If we failed here there no much that we can do, just
             * let the caller we failed
             */
            close(fd);
            return -1;
        }

        /*
         * Return the control to the parent caller, we need to wait for
         * the event loop to get back to us.
         */
        flb_thread_yield(th, FLB_FALSE);

        /* We got a notification, remove the event registered */
        ret = mk_event_del(u->evl, &u->event);
        assert(ret == 0);

        /* Check the connection status */
        if (u->event.mask & MK_EVENT_WRITE) {
            ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len);
            if (ret == -1) {
                flb_error("[io] could not validate socket status");
                return -1;
            }

            if (error != 0) {
                /* Connection is broken, not much to do here */
                flb_debug("[io] connection failed");
                return -1;
            }
            u->event.mask   = MK_EVENT_EMPTY;
            u->event.status = MK_EVENT_NONE;
        }
        else {
            return -1;
        }
    }

    flb_debug("[io] connection OK");
    return 0;
}
Example #9
0
void cb_forward_flush(void *data, size_t bytes,
                      char *tag, int tag_len,
                      struct flb_input_instance *i_ins, void *out_context,
                      struct flb_config *config)
{
    int ret = -1;
    int entries = 0;
    size_t off = 0;
    size_t total;
    size_t bytes_sent;
    msgpack_packer   mp_pck;
    msgpack_sbuffer  mp_sbuf;
    msgpack_unpacked result;
    struct flb_out_forward_config *ctx = out_context;
    struct flb_upstream_conn *u_conn;
    (void) i_ins;
    (void) config;

    flb_debug("[out_forward] request %lu bytes to flush", bytes);

    /* Initialize packager */
    msgpack_sbuffer_init(&mp_sbuf);
    msgpack_packer_init(&mp_pck, &mp_sbuf, msgpack_sbuffer_write);

    /* Count number of entries, is there a better way to do this ? */
    msgpack_unpacked_init(&result);
    while (msgpack_unpack_next(&result, data, bytes, &off)) {
        entries++;
    }
    flb_debug("[out_fw] %i entries tag='%s' tag_len=%i",
              entries, tag, tag_len);
    msgpack_unpacked_destroy(&result);

    /* Output: root array */
    msgpack_pack_array(&mp_pck, 2);
    msgpack_pack_str(&mp_pck, tag_len);
    msgpack_pack_str_body(&mp_pck, tag, tag_len);
    msgpack_pack_array(&mp_pck, entries);

    /* Get a TCP connection instance */
    u_conn = flb_upstream_conn_get(ctx->u);
    if (!u_conn) {
        flb_error("[out_forward] no upstream connections available");
        msgpack_sbuffer_destroy(&mp_sbuf);
        FLB_OUTPUT_RETURN(FLB_RETRY);
    }

    /* Write message header */
    ret = flb_io_net_write(u_conn, mp_sbuf.data, mp_sbuf.size, &bytes_sent);
    if (ret == -1) {
        flb_error("[out_forward] could not write chunk header");
        msgpack_sbuffer_destroy(&mp_sbuf);
        flb_upstream_conn_release(u_conn);
        FLB_OUTPUT_RETURN(FLB_RETRY);
    }

    msgpack_sbuffer_destroy(&mp_sbuf);
    total = ret;

    /* Write body */
    ret = flb_io_net_write(u_conn, data, bytes, &bytes_sent);
    if (ret == -1) {
        flb_error("[out_forward] error writing content body");
        flb_upstream_conn_release(u_conn);
        FLB_OUTPUT_RETURN(FLB_RETRY);
    }

    total += bytes_sent;
    flb_upstream_conn_release(u_conn);
    flb_trace("[out_forward] ended write()=%d bytes", total);

    FLB_OUTPUT_RETURN(FLB_OK);
}
Example #10
0
/* Init serial input */
int in_serial_init(struct flb_input_instance *in,
                   struct flb_config *config, void *data)
{
    int fd;
    int ret;
    int br;
    struct flb_in_serial_config *ctx;
    (void) data;

    ctx = flb_calloc(1, sizeof(struct flb_in_serial_config));
    if (!ctx) {
        perror("calloc");
        return -1;
    }
    ctx->format = FLB_SERIAL_FORMAT_NONE;

    if (!serial_config_read(ctx, in)) {
        return -1;
    }

    /* Initialize JSON pack state */
    if (ctx->format == FLB_SERIAL_FORMAT_JSON) {
        flb_pack_state_init(&ctx->pack_state);
    }

    /* set context */
    flb_input_set_context(in, ctx);

    /* initialize MessagePack buffers */
    msgpack_sbuffer_init(&ctx->mp_sbuf);
    msgpack_packer_init(&ctx->mp_pck, &ctx->mp_sbuf, msgpack_sbuffer_write);

    /* open device */
    fd = open(ctx->file, O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (fd == -1) {
        perror("open");
        flb_error("[in_serial] Could not open serial port device");
        flb_free(ctx);
        return -1;
    }
    ctx->fd = fd;

    /* Store original settings */
    tcgetattr(fd, &ctx->tio_orig);

    /* Reset for new... */
    memset(&ctx->tio, 0, sizeof(ctx->tio));
    tcgetattr(fd, &ctx->tio);

    br = atoi(ctx->bitrate);
    cfsetospeed(&ctx->tio, (speed_t) flb_serial_speed(br));
    cfsetispeed(&ctx->tio, (speed_t) flb_serial_speed(br));

    /* Settings */
    ctx->tio.c_cflag     &=  ~PARENB;        /* 8N1 */
    ctx->tio.c_cflag     &=  ~CSTOPB;
    ctx->tio.c_cflag     &=  ~CSIZE;
    ctx->tio.c_cflag     |=  CS8;
    ctx->tio.c_cflag     &=  ~CRTSCTS;       /* No flow control */
    ctx->tio.c_cc[VMIN]   =  ctx->min_bytes; /* Min number of bytes to read  */
    ctx->tio.c_cflag     |=  CREAD | CLOCAL; /* Enable READ & ign ctrl lines */

    tcflush(fd, TCIFLUSH);
    tcsetattr(fd, TCSANOW, &ctx->tio);

#if __linux__
    /* Set our collector based on a file descriptor event */
    ret = flb_input_set_collector_event(in,
                                        in_serial_collect,
                                        ctx->fd,
                                        config);
#else
    /* Set our collector based on a timer event */
    ret = flb_input_set_collector_time(in,
                                       in_serial_collect,
                                       IN_SERIAL_COLLECT_SEC,
                                       IN_SERIAL_COLLECT_NSEC,
                                       config);
#endif
    return ret;
}
Example #11
0
/*
 * This routine perform a TCP connection and the required TLS/SSL
 * handshake,
 */
FLB_INLINE int flb_io_net_tls_connect(struct flb_io_upstream *u,
                                      struct flb_thread *th)
{
    int fd;
    int ret;
    int error = 0;
    int flag;
    socklen_t len = sizeof(error);
    struct flb_tls_session *session;

    if (u->fd > 0) {
        close(u->fd);
    }

    /* Create the socket */
    fd = flb_net_socket_create(AF_INET, FLB_TRUE);
    if (fd == -1) {
        flb_error("[io] could not create socket");
        return -1;
    }
    u->fd = fd;

    /* Make the socket non-blocking */
    flb_net_socket_nonblocking(u->fd);

    /* Start the connection */
    ret = flb_net_tcp_fd_connect(fd, u->tcp_host, u->tcp_port);
    if (ret == -1) {
        if (errno == EINPROGRESS) {
            flb_debug("[upstream] connection in process");
        }
        else {
            close(u->fd);
            if (u->tls_session) {
                tls_session_destroy(u->tls_session);
                u->tls_session = NULL;
            }
            return -1;
        }

        MK_EVENT_NEW(&u->event);
        u->thread = th;

        ret = mk_event_add(u->evl,
                           fd,
                           FLB_ENGINE_EV_THREAD,
                           MK_EVENT_WRITE, &u->event);
        if (ret == -1) {
            /*
             * If we failed here there no much that we can do, just
             * let the caller we failed
             */
            flb_error("[io_tls] connect failed registering event");
            close(fd);
            return -1;
        }

        /*
         * Return the control to the parent caller, we need to wait for
         * the event loop to get back to us.
         */
        flb_thread_yield(th, FLB_FALSE);

        /* Check the connection status */
        if (u->event.mask & MK_EVENT_WRITE) {
            ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len);
            if (ret == -1) {
                flb_error("[io_tls] could not validate socket status");
                goto error;
            }

            if (error != 0) {
                /* Connection is broken, not much to do here */
                flb_error("[io_tls] connection failed");
                goto error;
            }
        }
        else {
            return -1;
        }
    }

    /* Configure TLS and prepare handshake */
    session = u->tls_session;
    mbedtls_ssl_set_bio(&session->ssl,
                        u,
                        mbedtls_net_send, mbedtls_net_recv, NULL);

 retry_handshake:
    ret = mbedtls_ssl_handshake(&session->ssl);

    if (ret != 0) {
        if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
            ret !=  MBEDTLS_ERR_SSL_WANT_WRITE) {
            io_tls_error(ret);
            goto error;
        }

        if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
            flag = MK_EVENT_WRITE;
        }
        else if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
            flag = MK_EVENT_READ;
        }
        else {

        }

        /*
         * FIXME: if we need multiple reads we are invoking the same
         * system call multiple times.
         */
        ret = mk_event_add(u->evl,
                           u->event.fd,
                           FLB_ENGINE_EV_THREAD,
                           flag, &u->event);
        if (ret == -1) {
            goto error;
        }

        flb_thread_yield(th, FLB_FALSE);
        goto retry_handshake;
    }
    else {
        flb_debug("[io_tls] Handshake OK");
    }

    if (u->event.status == MK_EVENT_REGISTERED) {
        mk_event_del(u->evl, &u->event);
    }
    flb_debug("[io_tls] connection OK");
    return 0;

 error:
    if (u->event.status == MK_EVENT_REGISTERED) {
        mk_event_del(u->evl, &u->event);
    }

    return -1;
}