Exemplo n.º 1
0
/* Handle an incoming connection.
 *
 *  return -1 if no crypto inbound connection.
 *  return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection.
 *
 * Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce
 * and the session public key for the connection in session_key.
 * to accept it see: accept_crypto_inbound(...).
 * to refuse it just call kill_connection(...) on the connection id.
 */
int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key)
{
    while (1) {
        int incoming_con = incoming_connection(c->lossless_udp, 1);

        if (incoming_con != -1) {
            if (is_connected(c->lossless_udp, incoming_con) == LUDP_TIMED_OUT) {
                kill_connection(c->lossless_udp, incoming_con);
                continue;
            }

            if (id_packet(c->lossless_udp, incoming_con) == 2) {
                uint8_t temp_data[MAX_DATA_SIZE];
                uint16_t len = read_packet_silent(c->lossless_udp, incoming_con, temp_data);

                if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) {
                    return incoming_con;
                } else {
                    kill_connection(c->lossless_udp, incoming_con);
                }
            } else {
                kill_connection(c->lossless_udp, incoming_con);
            }
        } else {
            break;
        }
    }

    return -1;
}
Exemplo n.º 2
0
static void
reset_connection(struct argos_net_conn *conn, int flush_buffers)
{
    if (flush_buffers) {
        buffer_empty(conn->inbuf);
        buffer_empty(conn->outbuf);
        buffer_empty(conn->pktbuf);
    } else {
        if (conn->outbuf_unsync) {
            /* 
             * Even if flush_buffers=0, we still need to flush the outbuf if its
             * unsynced (otherwise we might get out of sync when we resume
             * sending to the server after reconnecting).
             */
            buffer_empty(conn->outbuf);
        }

        /*
         * always flush inbuf for the same reason (could use a variable to avoid
         * unnecessary flushes...)
         */
        buffer_empty(conn->inbuf);
    }

    /* if connection is shutting down, check if outbuf is now empty */
    if (conn->shutdown && buffers_are_empty(conn)) {
        kill_connection(conn);
        return;
    }

    close_socket(conn->sock);

    conn->sock = 0;
    conn->status_flags |= ARGOS_NET_STATS_CONN_DOWN;

    /* schedule an reconnection event */
    conn->state = ARGOS_NET_CONN_BACKOFF;
    conn->reconnect_evt_reg =
        async_schedule_sec(conn->cur_backoff, reconnect_event, conn, 0);

    if (conn->reconnect_evt_reg == NULL) {
        orion_log_errno("async_schedule_sec");
        kill_connection(conn);
        orion_log_err("failed to schedule reconnection event"
            "; connection is now dead");
    }

    /* exponentially increase backoff */
    conn->cur_backoff *= 2;
    if (conn->cur_backoff > conn->max_backoff)
        conn->cur_backoff = conn->max_backoff;

    /* make this callback last */
    if (conn->breakhandler != NULL)
        conn->breakhandler(conn, conn->breakhandler_user);
}
Exemplo n.º 3
0
/* Kill a crypto connection.
 *
 *  return 0 if killed successfully.
 *  return 1 if there was a problem.
 */
int crypto_kill(Net_Crypto *c, int crypt_connection_id)
{
    if (crypt_connection_id_not_valid(c, crypt_connection_id))
        return 1;

    if (c->crypto_connections[crypt_connection_id].status != CRYPTO_CONN_NO_CONNECTION) {
        c->crypto_connections[crypt_connection_id].status = CRYPTO_CONN_NO_CONNECTION;
        kill_connection(c->lossless_udp, c->crypto_connections[crypt_connection_id].number);
        memset(&(c->crypto_connections[crypt_connection_id]), 0 , sizeof(Crypto_Connection));
        c->crypto_connections[crypt_connection_id].number = ~0;
        uint32_t i;

        for (i = c->crypto_connections_length; i != 0; --i) {
            if (c->crypto_connections[i - 1].status != CRYPTO_CONN_NO_CONNECTION)
                break;
        }

        if (c->crypto_connections_length != i) {
            c->crypto_connections_length = i;
            realloc_cryptoconnection(c, c->crypto_connections_length);
        }

        return 0;
    }

    return 1;
}
Exemplo n.º 4
0
/* handle an incoming connection
   return -1 if no crypto inbound connection
   return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection
   Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce
   and the session public key for the connection in session_key
   to accept it see: accept_crypto_inbound(...)
   to refuse it just call kill_connection(...) on the connection id */
int crypto_inbound(uint8_t * public_key, uint8_t * secret_nonce, uint8_t * session_key)
{
    uint32_t i;
    for(i = 0; i < MAX_INCOMING; ++i)
    {
        if(incoming_connections[i] != -1)
        {
            if(is_connected(incoming_connections[i]) == 4 || is_connected(incoming_connections[i]) == 0)
            {
                kill_connection(incoming_connections[i]);
                incoming_connections[i] = -1;
                continue;
            }
            if(id_packet(incoming_connections[i]) == 2)
            {
                uint8_t temp_data[MAX_DATA_SIZE];
                uint16_t len = read_packet(incoming_connections[i], temp_data);
                if(handle_cryptohandshake(public_key, secret_nonce, session_key, temp_data, len))
                {
                    int connection_id = incoming_connections[i];
                    incoming_connections[i] = -1; /* remove this connection from the incoming connection list. */
                    return connection_id;
                }
            }
        }
    }
    return -1;
}
Exemplo n.º 5
0
void
argos_net_shutdown(struct argos_net_conn *conn)
{
    if (conn->shutdown == 0) {
        conn->shutdown = 1;
        if (buffers_are_empty(conn))
            kill_connection(conn);
    }
}
Exemplo n.º 6
0
static void killTimedout(void)
{
    uint32_t i;
    for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
        if (crypto_connections[i].status != CONN_NO_CONNECTION && is_connected(crypto_connections[i].number) == 4)
            crypto_connections[i].status = CONN_TIMED_OUT;
        else if (is_connected(crypto_connections[i].number) == 4) {
            kill_connection(crypto_connections[i].number);
            crypto_connections[i].number = ~0;
        }
    }
}
Exemplo n.º 7
0
/* kill a crypto connection
   return 0 if killed successfully
   return 1 if there was a problem. */
int crypto_kill(int crypt_connection_id)
{
    if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
        return 1;
    if (crypto_connections[crypt_connection_id].status != CONN_NO_CONNECTION) {
        crypto_connections[crypt_connection_id].status = CONN_NO_CONNECTION;
        kill_connection(crypto_connections[crypt_connection_id].number);
        memset(&crypto_connections[crypt_connection_id], 0 ,sizeof(Crypto_Connection));
        crypto_connections[crypt_connection_id].number = ~0;
        return 0;
    }
    return 1;
}
Exemplo n.º 8
0
void
argos_net_close(struct argos_net_conn *conn)
{
    orion_log_func();

    if (conn->state != ARGOS_NET_CONN_DEAD)
        kill_connection(conn);

    buffer_destroy(conn->inbuf);
    buffer_destroy(conn->outbuf);
    buffer_destroy(conn->pktbuf);
    free(conn);
}
Exemplo n.º 9
0
static ssize_t
socket_send(struct argos_net_conn *conn, const void *msg, size_t len)
{
#if ARGOS_NET_TRACE_IO
    struct timeval start;
    if (gettimeofday(&start, NULL) != 0) {
        orion_log_crit_errno("gettimeofday");
        return -1;
    }
#endif /* #if ARGOS_NET_TRACE_IO */

    ssize_t sentlen = send(conn->sock, msg, len, 0);
    if (sentlen == -1) {
        if (IS_NETWORK_ERROR(errno)) {
            /* network error; reset our connection */
            orion_log_warn_errno("send() failed");
            reset_connection(conn, 0);
        } else {
            /* anything else is a fatal error */
            orion_log_crit_errno("send");
            kill_connection(conn);
            orion_log_crit("unexpected send() error; connection is now dead");
        }

        return -1;
    } else {
        /* send() succeeded */
        assert(sentlen > 0);

        /* this variable is used even if ARGOS_NET_TRACE_IO is false */
        struct timeval end;
        if (gettimeofday(&end, NULL) != 0) {
            orion_log_crit_errno("gettimeofday");
            return -1;
        }

#if ARGOS_NET_TRACE_IO
        struct timeval elapsed;
        orion_time_subtract(&end, &start, &elapsed);
        float elapsed_msec = elapsed.tv_sec*1000 + (float)elapsed.tv_usec/1000;

        orion_log_debug("sent %u bytes in %.2f ms (%.2f MB/s); requested %u",
            sentlen, elapsed_msec, ((sentlen/elapsed_msec)*1000)/(1024*1024), len);
#endif /* #if ARGOS_NET_TRACE_IO */

        conn->bytes_sent += sentlen;
        conn->last_send = end;
        conn->stall_logged = 0;
        return sentlen;
    }
}
Exemplo n.º 10
0
static void kill_timedout(Net_Crypto *c)
{
    uint32_t i;

    for (i = 0; i < c->crypto_connections_length; ++i) {
        if (c->crypto_connections[i].status != CONN_NO_CONNECTION
                && is_connected(c->lossless_udp, c->crypto_connections[i].number) == 4)
            c->crypto_connections[i].status = CONN_TIMED_OUT;
        else if (is_connected(c->lossless_udp, c->crypto_connections[i].number) == 4) {
            kill_connection(c->lossless_udp, c->crypto_connections[i].number);
            c->crypto_connections[i].number = ~0;
        }
    }
}
Exemplo n.º 11
0
static void
write_cb(int fd, void *arg)
{
    struct argos_net_conn *conn = arg;

    if (conn->state == ARGOS_NET_CONN_CONNECTING) {
        handle_connect(conn);
    }
    else if (conn->state == ARGOS_NET_CONN_CONNECTED) {
        /* this callback shouldn't happen unless outbuf is non-empty */
        size_t datalen = buffer_len(conn->outbuf);
        assert(datalen > 0);

        /*
         * when possible, we want to make sure to feed send() large blocks of
         * data at a time, so if there is only a little data in the outbuf, try
         * to get some more by compressing and moving over some of the pktbuf
         */
        if (datalen < SEND_SOFT_MIN) {
            (void) compress_and_xfer(conn, 0 /* don't force */);
            datalen = buffer_len(conn->outbuf);
        }

        ssize_t len = socket_send(conn, buffer_head(conn->outbuf), datalen);
        if (len != -1) {
            if (buffer_discard(conn->outbuf, len) == -1)
                KABOOM("buffer_discard");

            /*
             * When a partial-send occurs, this means we might have sent part of
             * a message and left the remainder sitting at the head of the
             * outbuf.  This is not a problem for the server (it will receive
             * and buffer the portion that was sent, waiting for us to send the
             * remainder) - however, it means that we cannot arbitrarily send
             * things down the socket until we finish off this partially-sent
             * message.  We call this state "unsynced" because we don't know if
             * we stopped sending on a message boundary or not.
             */
            if (buffer_len(conn->outbuf) == 0)
                conn->outbuf_unsync = 0;
            else if (datalen != len)
                conn->outbuf_unsync = 1;

            /* if connection is shutting down, check if buffers are now empty */
            if (conn->shutdown && buffers_are_empty(conn))
                kill_connection(conn);
        }
    }
}
Exemplo n.º 12
0
/* kill a crypto connection
   return 0 if killed successfully
   return 1 if there was a problem. */
int crypto_kill(int crypt_connection_id)
{ 
    if(crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
    {
        return 1;   
    }
    if(crypto_connections[crypt_connection_id].status != 0)
    {
        crypto_connections[crypt_connection_id].status = 0;
        kill_connection(crypto_connections[crypt_connection_id].number);
        crypto_connections[crypt_connection_id].number = ~0;
        return 0;
    }
    return 1;
}
Exemplo n.º 13
0
static void killTimedout()
{
    uint32_t i;
    for(i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i)
    {
        if(crypto_connections[i].status != 0 && is_connected(crypto_connections[i].number) == 4)
        {
            crypto_connections[i].status = 4;
        }
        else if(is_connected(crypto_connections[i].number) == 4)
        {
            kill_connection(crypto_connections[i].number);
            crypto_connections[i].number = ~0;
        }
    }
}
Exemplo n.º 14
0
static void
read_cb(int fd, void *arg)
{
    struct argos_net_conn *conn = arg;

    /*
     * We only want to do reads if conn->state == NET_CONN_CONNECTED, but we
     * don't assert() this because its possible for this socket to be selected
     * simultaneously for both a read and a write and then for our state to
     * change during the write attempt.
     */
    if (conn->state != ARGOS_NET_CONN_CONNECTED)
        return;

    ssize_t len = recv(conn->sock, buffer_tail(conn->inbuf), buffer_remaining(conn->inbuf), 0);
    if (len == -1) {
        if (IS_NETWORK_ERROR(errno)) {
            /* network error; reset our connection */
            orion_log_warn_errno("recv");
            reset_connection(conn, 0);
        } else if (errno == EINTR) {
            /* don't care; ignore it */
        } else {
            /* anything else is a fatal error */
            orion_log_crit_errno("recv");
            kill_connection(conn);
            orion_log_crit("unexpected recv() error; connection is now dead");
        }
    } else if (len == 0) {
        /* EOF received (maybe other end is shutting down?) */
        orion_log_info("EOF received from remote end - closing socket");
        if (buffer_len(conn->inbuf) > 0)
            orion_log_warn("incomplete message received (inbuflen=%d)",
                buffer_len(conn->inbuf));
        reset_connection(conn, 1 /* flush buffers */);
    } else {
        /* ok, we read some data into the inbuf; update the buffer */
        int rv = buffer_expand(conn->inbuf, len);
        if (rv == -1) KABOOM("buffer_expand");

        conn->bytes_recv += len;

        /* now process (i.e. look for complete messages in) the inbuf */
        process_inbuf(conn);
    }
}
Exemplo n.º 15
0
static void
handle_connect(struct argos_net_conn *conn)
{
    assert(conn->state == ARGOS_NET_CONN_CONNECTING);

    /*
     * connect() completed, but did it succeed or fail?  getpeername() will
     * tell us.  reference: http://cr.yp.to/docs/connect.html
     */
    struct sockaddr_in sin;
    socklen_t slen = sizeof(sin);
    if (getpeername(conn->sock, (struct sockaddr*)&sin, &slen) == -1) {
        if (errno == ENOTCONN) {
            /* connect failed; ok now use error slippage to get the real error */
            char c;
            int rv = read(conn->sock, &c, 1);
            assert(rv == -1);
            handle_connect_failure(conn);
        } else if (errno == ECONNRESET) {
            /* 
             * not sure if this can actually happen - perhaps with perfect
             * timing (connection lost right before we call getpeername)
             */
            orion_log_warn_errno("getpeername");
            reset_connection(conn, 0);
        } else {
            /* this is unexpected... */
            orion_log_crit_errno("getpeername");
            kill_connection(conn);
            orion_log_crit("unexpected getpeername() error after asynchronous"
                " connect() selected for writability; connection is now dead");
        }
    } else {
        /* connect succeeded */
        orion_log_info("connect() succeeded asynchronously");
        handle_connect_success(conn);
    }
}
Exemplo n.º 16
0
static int
attempt_connect(struct argos_net_conn *conn)
{
    if (!conn->connect_failed)
        orion_log_func();

    assert(conn->state == ARGOS_NET_CONN_IDLE);

    /* create and set up the actual socket */
    conn->sock = socket(AF_INET, SOCK_STREAM, 0);
    if (conn->sock < 0) {
        orion_log_errno("socket");
        goto fail;
    }

    /* set non-blocking on socket */
    int status = fcntl(conn->sock, F_GETFL, NULL);
    if (status < 0) {
        orion_log_crit_errno("fcntl(F_GETFL)");
        goto fail;
    }

    status |= O_NONBLOCK;

    if (fcntl(conn->sock, F_SETFL, status) < 0) {
        orion_log_crit_errno("fcntl(F_SETFL)");
        goto fail;
    }

    /* prevent socket from throwing SIGPIPE signals */
    int on = 1;
    if (setsockopt(conn->sock, SOL_SOCKET, SO_NOSIGPIPE, (void *)&on,
            sizeof(on)) < 0) {
        orion_log_crit_errno("setsockopt(SO_NOSIGPIPE)");
        goto fail;
    }

    /* select for writes (that's how completion of a connect() is signaled) */
    int rv = async_add_write_fd(conn->sock, ARGOS_NET_CONNECT_ASYNCPRIO,
        writable_cb, write_cb, conn);
    if (rv != 0) {
        orion_log_errno("async_add_write_fd");
        async_remove_fd(conn->sock);
        goto fail;
    }

    /* finally ready to attempt the connect() call */
    rv = connect(conn->sock, (struct sockaddr*)&conn->remote_addr,
        sizeof(conn->remote_addr));

    if (rv == -1)
        return handle_connect_failure(conn);
    
    /* else, rv=0 which means instant success (odd...) */
    orion_log_info("connect() succeeded immediately");
    handle_connect_success(conn);
    return 0;

 fail:
    /* 
     * something very bad happened; presumably either there is a code bug or the
     * OS is in bad shape (e.g. out of memory, no more file descriptors, etc.)
     */
    kill_connection(conn);
    orion_log_crit("failed to create network client");
    return -1;
}
Exemplo n.º 17
0
/*  Display the menu that allows the user to act
    on a connection.

*/
static void
statevent_interactivemenu_conn( const int debuglvl, struct vuurmuur_config *cnf,
                                StatEventCtl *ctl, Conntrack *ct,
                                VR_ConntrackRequest *connreq, Zones *zones,
                                BlockList *blocklist, Interfaces *interfaces,
                                Services *services, StatEventGen *gen_ptr)
{
    VrWin           *win = NULL;
    VrMenu          *menu = NULL;
    int             ch = 0;
    int             menu_items = 10;
    char            *str = NULL;
    const int       width = 70;
    /* top menu */
    char            *key_choices[] =    {   "F12",
                                            "F10"};
    int             key_choices_n = 2;
    char            *cmd_choices[] =    {   gettext("help"),
                                            gettext("back")};
    int             cmd_choices_n = 2;
    StatEventConn   *con = (StatEventConn *)gen_ptr;
    Conntrack       *privct = NULL;
    char            ungroup_conns = FALSE;
    char            *title = gettext("Manage Connection");

    /* if needed get our own private ungrouped ct */
    if(connreq->group_conns == TRUE)
    {
        ungroup_conns = TRUE; /* we are ungrouping the list */

        connreq->group_conns = FALSE;

        privct = conn_init_ct(debuglvl, zones, interfaces,
            services, blocklist);
        if(privct == NULL)
            return;

        conn_ct_get_connections(debuglvl, cnf, privct, connreq);

        ct = privct;
    }

    /* create the window and put it in the middle of the screen */
    win = VrNewWin(menu_items + 2,width,0,0,vccnf.color_win);
    if(win == NULL)
    {
        (void)vrprint.error(-1, VR_ERR, "VrNewWin failed");
        return;
    }
    VrWinSetTitle(win, title);

    menu = VrNewMenu(menu_items, width - 2, 1,1, menu_items,vccnf.color_win,vccnf.color_win_rev);
    if(menu == NULL)
    {
        (void)vrprint.error(-1, VR_ERR, "VrNewMenu failed");
        return;
    }

    VrMenuSetDescFreeFunc(menu, free);
    VrMenuSetupNameList(debuglvl, menu);
    VrMenuSetupDescList(debuglvl, menu);

    /* setup menu items */
    if(con->cnt == 1)   str = VrGetString(gettext("Kill this connection"));
    else                str = VrGetString(gettext("Kill all connections with this service/source/destination"),con->cnt);
    VrMenuAddItem(debuglvl, menu, "1", str);

    str = VrGetString("--- %s ---", gettext("Kill options"));
    VrMenuAddSepItem(debuglvl, menu, str);

    str = VrGetString(gettext("Kill all connections with source %s"), con->src_ip);
    VrMenuAddItem(debuglvl, menu, "2", str);

    str = VrGetString(gettext("Kill all connections with destination %s"), con->dst_ip);
    VrMenuAddItem(debuglvl, menu, "3", str);

    str = VrGetString(gettext("Kill all connections of %s"), con->src_ip);
    VrMenuAddItem(debuglvl, menu, "4", str);

    str = VrGetString(gettext("Kill all connections of %s"), con->dst_ip);
    VrMenuAddItem(debuglvl, menu, "5", str);

    str = VrGetString("--- %s ---", gettext("BlockList options"));
    VrMenuAddSepItem(debuglvl, menu, str);

    str = VrGetString(gettext("Add source %s to BlockList"), con->src_ip);
    VrMenuAddItem(debuglvl, menu, "6", str);

    str = VrGetString(gettext("Add destination %s to BlockList"), con->dst_ip);
    VrMenuAddItem(debuglvl, menu, "7", str);

    str = VrGetString(gettext("Add both source and destination to BlockList"));
    VrMenuAddItem(debuglvl, menu, "8", str);

    VrMenuConnectToWin(debuglvl, menu, win);
    VrMenuPost(debuglvl, menu);

    draw_top_menu(debuglvl, top_win, title, key_choices_n,
            key_choices, cmd_choices_n, cmd_choices);

    update_panels();
    doupdate();

    /* user input */
    char quit = FALSE;
    while(quit == FALSE)
    {
        ch = VrWinGetch(win);

        switch(ch)
        {
            case 27:
            case 'q':
            case 'Q':
            case KEY_F(10):
                quit = TRUE;
                break;

            case 10:
            {
                ITEM *cur = current_item(menu->m);
                if(cur != NULL)
                {
                    int act = atoi((char *)item_name(cur));
                    switch(act)
                    {
                        case 1: /* kill */
                        {
                            /* check if the conntrack tool is set */
                            if(conf.conntrack_location[0] == '\0')
                            {
                                (void)vrprint.error(-1, VR_ERR, STR_CONNTRACK_LOC_NOT_SET);
                            }
                            else if(con->cnt == 1)
                            {
                                if(confirm(gettext("Kill connection"),gettext("Are you sure?"),
                                    vccnf.color_win_note, vccnf.color_win_note_rev|A_BOLD, 1) == 1)
                                {
                                    kill_connection(debuglvl, conf.conntrack_location,
                                        con->src_ip, con->dst_ip, con->protocol,
                                        con->src_port, con->dst_port);
                                }
                            }
                            else
                            {
                                vrprint.debug(__FUNC__, "cnt %u, src %s srcip %s dst %s dstip %s ser %s",
                                        con->cnt, con->src, con->src_ip, con->dst,
                                        con->dst_ip, con->ser);

                                if(confirm(gettext("Kill connections"),gettext("Are you sure?"),
                                    vccnf.color_win_note, vccnf.color_win_note_rev|A_BOLD, 1) == 1)
                                {
                                    kill_connections(debuglvl, &conf, connreq, ct, con);
                                }
                            }
                            break;
                        }

                        case 2: /* kill all src ip */
                            /* check if the conntrack tool is set */
                            if(conf.conntrack_location[0] == '\0')
                            {
                                (void)vrprint.error(-1, VR_ERR, STR_CONNTRACK_LOC_NOT_SET);
                            }
                            else if(confirm(gettext("Kill connections"),gettext("Are you sure?"),
                                vccnf.color_win_note, vccnf.color_win_note_rev|A_BOLD, 1) == 1)
                            {
                                kill_connections_by_ip(debuglvl, &conf, ct, con->src_ip, NULL, NULL, CONN_UNUSED);
                            }
                            break;

                        case 3: /* kill all dst ip */
                            /* check if the conntrack tool is set */
                            if(conf.conntrack_location[0] == '\0')
                            {
                                (void)vrprint.error(-1, VR_ERR, STR_CONNTRACK_LOC_NOT_SET);
                            }
                            else if(confirm(gettext("Kill connections"),gettext("Are you sure?"),
                                vccnf.color_win_note, vccnf.color_win_note_rev|A_BOLD, 1) == 1)
                            {
                                kill_connections_by_ip(debuglvl, &conf, ct, NULL, con->dst_ip, NULL, CONN_UNUSED);
                            }
                            break;

                        case 4:
                            /* check if the conntrack tool is set */
                            if(conf.conntrack_location[0] == '\0')
                            {
                                (void)vrprint.error(-1, VR_ERR, STR_CONNTRACK_LOC_NOT_SET);
                            }
                            else if(confirm(gettext("Kill connections"),gettext("Are you sure?"),
                                vccnf.color_win_note, vccnf.color_win_note_rev|A_BOLD, 1) == 1)
                            {
                                kill_connections_by_ip(debuglvl, &conf, ct, NULL, con->src_ip, NULL, CONN_UNUSED);
                                kill_connections_by_ip(debuglvl, &conf, ct, con->src_ip, NULL, NULL, CONN_UNUSED);
                            }
                            break;

                        case 5:
                            /* check if the conntrack tool is set */
                            if(conf.conntrack_location[0] == '\0')
                            {
                                (void)vrprint.error(-1, VR_ERR, STR_CONNTRACK_LOC_NOT_SET);
                            }
                            else if(confirm(gettext("Kill connections"),gettext("Are you sure?"),
                                vccnf.color_win_note, vccnf.color_win_note_rev|A_BOLD, 1) == 1)
                            {
                                kill_connections_by_ip(debuglvl, &conf, ct, NULL, con->dst_ip, NULL, CONN_UNUSED);
                                kill_connections_by_ip(debuglvl, &conf, ct, con->dst_ip, NULL, NULL, CONN_UNUSED);
                            }
                            break;


                        case 6:
                            if(confirm(gettext("Add to BlockList and Apply Changes"),gettext("Are you sure?"),
                                vccnf.color_win_note, vccnf.color_win_note_rev|A_BOLD, 1) == 1)
                            {
                                block_and_kill(debuglvl, ct, zones, blocklist, interfaces, con->src_ip);
                            }
                            break;

                        case 7:
                            if(confirm(gettext("Add to BlockList and Apply Changes"),gettext("Are you sure?"),
                                vccnf.color_win_note, vccnf.color_win_note_rev|A_BOLD, 1) == 1)
                            {
                                block_and_kill(debuglvl, ct, zones, blocklist, interfaces, con->dst_ip);
                            }
                            break;

                        case 8:
                            if(confirm(gettext("Add to BlockList and Apply Changes"),gettext("Are you sure?"),
                                vccnf.color_win_note, vccnf.color_win_note_rev|A_BOLD, 1) == 1)
                            {
                                block_and_kill(debuglvl, ct, zones, blocklist, interfaces, con->src_ip);
                                block_and_kill(debuglvl, ct, zones, blocklist, interfaces, con->dst_ip);
                            }
                            break;

                        default:
                            break;
                    }
                }

                break;
            }

            case KEY_F(12):
            case 'h':
            case 'H':
            case '?':
                print_help(debuglvl, ctl->help_actions);
                break;

            default:
                (void)VrMenuDefaultNavigation(debuglvl, menu, ch);
                break;
        }
    }

    VrDelMenu(debuglvl, menu);
    VrDelWin(win);
    update_panels();
    doupdate();

    /* we have ungrouped the list, clean up here. */
    if(ungroup_conns == TRUE)
    {
        connreq->group_conns = TRUE;

        conn_ct_clear_connections(debuglvl, privct);
        conn_free_ct(debuglvl, &privct, NULL);
    }

    return;
}
Exemplo n.º 18
0
void
test_send_pdu(struct proc *p, iscsi_test_send_pdu_parameters_t *par)
{
	static uint8_t pad_bytes[4] = { 0 };
	test_pars_t *tp;
	connection_t *conn;
	pdu_t *pdu;
	uint32_t psize = par->pdu_size;
	void *pdu_ptr = par->pdu_ptr;
	struct uio *uio;
	uint32_t i, pad, dsl, size;
	int s;

	if ((tp = find_test_id(par->test_id)) == NULL) {
		par->status = ISCSI_STATUS_INVALID_ID;
		return;
	}
	if (!psize || pdu_ptr == NULL ||
		((par->options & ISCSITEST_SFLAG_UPDATE_FIELDS) && psize < BHS_SIZE)) {
		par->status = ISCSI_STATUS_PARAMETER_INVALID;
		return;
	}
	if ((conn = tp->connection) == NULL) {
		par->status = ISCSI_STATUS_TEST_INACTIVE;
		return;
	}
	if ((pdu = get_pdu(conn, TRUE)) == NULL) {
		par->status = ISCSI_STATUS_TEST_CONNECTION_CLOSED;
		return;
	}
	DEB(1, ("Test Send PDU, id %d\n", par->test_id));

	if ((par->status = map_databuf(p, &pdu_ptr, psize)) != 0) {
		free_pdu(pdu);
		return;
	}

	i = 1;
	if (!par->options) {
		pdu->io_vec[0].iov_base = pdu_ptr;
		pdu->io_vec[0].iov_len = size = psize;
	} else {
		memcpy(&pdu->pdu, pdu_ptr, BHS_SIZE);

		if (!(pdu->pdu.Opcode & OP_IMMEDIATE))
			conn->session->CmdSN++;
		pdu->pdu.p.command.CmdSN = htonl(conn->session->CmdSN);

		dsl = psize - BHS_SIZE;
		size = BHS_SIZE;

		hton3(dsl, pdu->pdu.DataSegmentLength);

		if (conn->HeaderDigest &&
			!(par->options & ISCSITEST_SFLAG_NO_HEADER_DIGEST)) {
			pdu->pdu.HeaderDigest = gen_digest(&pdu->pdu, BHS_SIZE);
			size += 4;
		}

		pdu->io_vec[0].iov_base = &pdu->pdu;
		pdu->io_vec[0].iov_len = size;

		if (dsl) {
			pdu->io_vec[1].iov_base = &pdu_ptr[BHS_SIZE];
			pdu->io_vec[1].iov_len = dsl;
			i++;
			size += dsl;

			/* Pad to next multiple of 4 */
			pad = (par->options & ISCSITEST_SFLAG_NO_PADDING) ? 0 : size & 0x03;

			if (pad) {
				pad = 4 - pad;
				pdu->io_vec[i].iov_base = pad_bytes;
				pdu->io_vec[i].iov_len = pad;
				i++;
				size += pad;
			}

			if (conn->DataDigest &&
				!(par->options & ISCSITEST_SFLAG_NO_DATA_DIGEST)) {
				pdu->data_digest = gen_digest_2(&pdu_ptr[BHS_SIZE], dsl,
												pad_bytes, pad);
				pdu->io_vec[i].iov_base = &pdu->data_digest;
				pdu->io_vec[i].iov_len = 4;
				i++;
				size += 4;
			}
		}
	}
	uio = &pdu->uio;
	uio->uio_iov = pdu->io_vec;
	UIO_SETUP_SYSSPACE(uio);
	uio->uio_rw = UIO_WRITE;
	uio->uio_iovcnt = i;
	uio->uio_resid = size;

	pdu->disp = PDUDISP_SIGNAL;
	pdu->flags = PDUF_BUSY | PDUF_NOUPDATE;

	s = splbio();
	/* Enqueue for sending */
	if (pdu->pdu.Opcode & OP_IMMEDIATE)
		TAILQ_INSERT_HEAD(&conn->pdus_to_send, pdu, send_chain);
	else
		TAILQ_INSERT_TAIL(&conn->pdus_to_send, pdu, send_chain);

	wakeup(&conn->pdus_to_send);
	tsleep(pdu, PINOD, "test_send_pdu", 0);
	splx(s);

	unmap_databuf(p, pdu_ptr, psize);
	par->status = ISCSI_STATUS_SUCCESS;
	if (par->options & ISCSITEST_KILL_CONNECTION)
		kill_connection(conn, ISCSI_STATUS_TEST_CONNECTION_CLOSED, NO_LOGOUT,
						TRUE);
}
Exemplo n.º 19
0
static void
process_inbuf(struct argos_net_conn *conn)
{
    while (buffer_len(conn->inbuf) >= sizeof(struct argos_net_minimal_msg)) {
        struct argos_net_minimal_msg *header =
            (struct argos_net_minimal_msg *)buffer_head(conn->inbuf);

        uint16_t msgtype = ntohs(header->msgtype);
        uint32_t msglen = ntohl(header->msglen);

        /* check that message type and length are valid */
        if (ARGOS_NET_VALIDATE_MSGTYPE(msgtype) == 0) {
            orion_log_crit("invalid message type received; type=%hu, len=%u",
                msgtype, msglen);
            reset_connection(conn, 1 /* flush buffers */);
            return;
        }

        if (ARGOS_NET_VALIDATE_MSGLEN(msgtype, msglen) == 0) {
            orion_log_crit("invalid message len received; type=%hu, len=%u",
                msgtype, msglen);
            reset_connection(conn, 1 /* flush buffers */);
            return;
        }

        if (msglen > buffer_len(conn->inbuf)) {
            /* complete message not yet received */
            if (msglen > buffer_size(conn->inbuf)) {
                /* error - message is bigger than the entire inbuf */
                orion_log_err("inbuf too small for msgtype %hu (len=%u)",
                    msgtype, msglen);
                reset_connection(conn, 1 /* flush buffers */);
                return;
            }

            /* wait for more bytes to arrive on socket */
            break;
        }

        /* ok great, message length must be valid - process it */
        switch (msgtype) {
        case ARGOS_NET_CLOSECONN_MSGTYPE: {
            struct argos_net_closeconn_msg msg;
            int rv = buffer_read(conn->inbuf, &msg, sizeof(msg));
            assert(rv >= 0);

            orion_log_info("received close-connection message from server");
            reset_connection(conn, 1 /* flush buffers */);
            break;
        }

        case ARGOS_NET_ERROR_MSGTYPE: {
            struct argos_net_error_msg msg;
            int rv = buffer_read(conn->inbuf, &msg, sizeof(msg));
            assert(rv >= 0);

            char buf[ARGOS_NET_MAX_ERR_LEN+1];
            ssize_t bodylen = msglen - sizeof(msg);
            rv = buffer_read(conn->inbuf, buf, bodylen);
            assert(rv >= 0);
            buf[bodylen] = '\0';

            if (conn->errhandler != NULL)
                conn->errhandler(ntohs(msg.errnum), buf, conn->errhandler_user);
            else
                orion_log_err("[server] %s (%s)", strerror(ntohs(msg.errnum)),
                    buf);
            break;
        }

        case ARGOS_NET_HANDSHAKE_MSGTYPE: {
            struct argos_net_handshake_msg msg;
            int rv = buffer_read(conn->inbuf, &msg, sizeof(msg));
            assert(rv >= 0);

            /* sniffers should never receive handshake messages */
            orion_log_crit("received handshake message from server");
            reset_connection(conn, 1 /* flush buffers */);
            break;
        }

        case ARGOS_NET_PCAP_MSGTYPE: {
            struct argos_net_pcap_msg msg;
            int rv = buffer_read(conn->inbuf, &msg, sizeof(msg));
            assert(rv >= 0);

            size_t bodylen = msglen - sizeof(msg);
            assert(bodylen == ntohl(msg.caplen));

            if (conn->pkthandler == NULL) {
                int rv = buffer_discard(conn->inbuf, bodylen);
                assert(rv >= 0);
                break;
            }

            struct pcap_pkthdr pcap_hdr;
            pcap_hdr.len = ntohl(msg.pktlen);
            pcap_hdr.caplen = ntohl(msg.caplen);
            pcap_hdr.ts.tv_sec = ntohl(msg.ts_sec);
            pcap_hdr.ts.tv_usec = ntohl(msg.ts_usec);

            /*
             * index directly into buffer if possible (i.e. if the data
             * doesn't wrap in the buffer)
             */
            if (buffer_len(conn->inbuf) >= bodylen) {
                conn->pkthandler(&pcap_hdr, buffer_head(conn->inbuf),
                    conn->pkthandler_user);
                buffer_discard(conn->inbuf, bodylen);
            } else {
                /* data wraps; need to copy into a temporary buffer */
                u_char tempbuf[ARGOS_NET_MAX_PKT_LEN];
                buffer_read(conn->inbuf, tempbuf, bodylen);
                conn->pkthandler(&pcap_hdr, tempbuf, conn->pkthandler_user);
            }
            break;
        }

        case ARGOS_NET_SETBPF_MSGTYPE: {
            struct argos_net_setbpf_msg msg;
            int rv = buffer_read(conn->inbuf, &msg, sizeof(msg));
            assert(rv >= 0);

            char buf[ARGOS_NET_MAX_BPF_LEN+1];
            size_t bodylen = msglen - sizeof(msg);
            rv = buffer_read(conn->inbuf, buf, bodylen);
            assert(rv >= 0);
            buf[bodylen] = '\0';

            if (conn->bpfhandler != NULL)
                conn->bpfhandler(buf, conn->bpfhandler_user);
            /* else, just discard and ignore */
            break;
        }

        case ARGOS_NET_SETCHAN_MSGTYPE: {
            struct argos_net_setchan_msg msg;
            int rv = buffer_read(conn->inbuf, &msg, sizeof(msg));
            assert(rv >= 0);

            if (conn->chanhandler != NULL)
                conn->chanhandler(ntohs(msg.chan), conn->chanhandler_user);
            /* else, just discard and ignore */
            break;
        }

        case ARGOS_NET_STARTCLICK_MSGTYPE: {
            struct argos_net_startclick_msg msg;
            int rv = buffer_read(conn->inbuf, &msg, sizeof(msg));
            assert(rv >= 0);

            size_t bodylen = msglen - sizeof(msg);
            char *click_conf = malloc(bodylen+1);
            if (click_conf == NULL) {
                char errmsg[256];
                snprintf(errmsg, sizeof(errmsg), "malloc(%d): %s", bodylen,
                    strerror(errno));

                orion_log_crit_errno("malloc()");
                argos_net_send_errmsg(conn, errno, errmsg);
                kill_connection(conn);
                return;
            }

            rv = buffer_read(conn->inbuf, click_conf, bodylen);
            assert(rv >= 0);
            click_conf[bodylen] = '\0';

            /* is this click config any different from the last one we got? */
            uint32_t key = ntohl(msg.key);
            if (key == conn->click_config_key) {
                /* keys match; we can ignore this message */
                orion_log_debug("click-configuration keys match (%d)", key);
            } else {
                /* keys don't match; need to run this new configuration */
                orion_log_debug("new click-configuration key: %d", key);
                conn->click_config_key = key;
                if (conn->clickhandler != NULL)
                    conn->clickhandler(click_conf, conn->clickhandler_user);
            }

            free(click_conf);
            break;
        }

        case ARGOS_NET_STATS_MSGTYPE: {
            struct argos_net_stats_msg msg;
            int rv = buffer_read(conn->inbuf, &msg, sizeof(msg));
            assert(rv >= 0);

            orion_log_warn("received stats message from server");
            break;
        }

        default:
            orion_log_crit("process_inbuf() of net.c out of sync with net.h;"
                " no switch case for msgtype %hu", msgtype);
            kill_connection(conn);
        }
    }
}
Exemplo n.º 20
0
static int
handle_connect_failure(struct argos_net_conn *conn)
{
    switch (errno) {
        /* these errors indicate some kind of programming error */
    case EBADF:
    case ENOTSOCK:
    case EAFNOSUPPORT:
    case EFAULT:
        /* fall through */

        /*
         * generally, these are non-fatal, but should never happen in this
         * code; if they do, this indicates a programming error
         */
    case EISCONN:
    case EALREADY:
        orion_log_crit_errno("connect");
        kill_connection(conn);
        orion_log_crit("unexpected connect() error; connection is now dead");
        return -1;
        
        /* these are transient errors; we retry connecting */
    case EADDRNOTAVAIL:
    case ETIMEDOUT:
    case ECONNREFUSED:
    case ENETUNREACH:
    case EHOSTUNREACH:
    case EADDRINUSE:
    case ECONNRESET:

        /*
         * EAGAIN is NOT the same as EINPROGRESS; it means that the server's
         * connection backlog is full
         */
    case EAGAIN:
        if (!conn->connect_failed) {
            orion_log_warn_errno("connect");
            conn->connect_failed = 1;
        }
        reset_connection(conn, 0);
        return 0;

        /* these aren't really errors; the connect() should still work */
    case EINPROGRESS:
        /*
         * this errno is ok if returned by connect() itself, but shouldn't be
         * returned via error slippage from a recv() after a failed connect
         */
        if (conn->state == ARGOS_NET_CONN_CONNECTING) {
            orion_log_crit_errno("read after failed connect");
            kill_connection(conn);
            orion_log_crit("unexpected recv() error; connection is now dead");
        }
        /* fall through */

    case EINTR:
        orion_log_debug("connect() in progress (\"%s\")", strerror(errno));
        conn->state = ARGOS_NET_CONN_CONNECTING;
        return 0;

    default:
        /* unknown errno */
        orion_log_crit_errno("read after failed connect");
        orion_log_crit("unexpected connect errno");
        kill_connection(conn);
        return -1;
    }
}
Exemplo n.º 21
0
STATIC int
test_mod(test_pars_t *tp, pdu_t *pdu, iscsi_pdu_kind_t kind, int rxtx, int err)
{
	mod_desc_t *mod;
	uint32_t mpoff, off;
	int i, rc = 0, s;

	tp->pdu_count[kind][rxtx]++;
	tp->pdu_count[ANY_PDU][rxtx]++;

	do {
		if ((mod = TAILQ_FIRST(&tp->mods)) == NULL) {
			return check_loss(tp, rxtx);
		}
		if (mod->pars.which_pdu != ANY_PDU &&
		    mod->pars.which_pdu != kind) {
			return check_loss(tp, rxtx);
		}
		mpoff = mod->pars.pdu_offset;

		switch (mod->pars.which_offset) {
		case ABSOLUTE_ANY:
			off = tp->pdu_count[ANY_PDU][CNT_TX] +
				  tp->pdu_count[ANY_PDU][CNT_RX];
			break;
		case RELATIVE_ANY:
			off = (tp->pdu_count[ANY_PDU][CNT_TX] +
				   tp->pdu_count[ANY_PDU][CNT_RX]) -
				(tp->pdu_last[ANY_PDU][CNT_TX] + tp->pdu_last[ANY_PDU][CNT_RX]);
			break;

		case ABSOLUTE_PDUKIND:
			off = tp->pdu_count[kind][rxtx];
			break;
		case RELATIVE_PDUKIND:
			off = tp->pdu_count[kind][rxtx] - tp->pdu_last[kind][rxtx];
			break;

		case ABSOLUTE_TX:
			if (rxtx != CNT_TX)
				return check_loss(tp, rxtx);
			off = tp->pdu_count[ANY_PDU][CNT_TX];
			break;
		case RELATIVE_TX:
			if (rxtx != CNT_TX)
				return check_loss(tp, rxtx);
			off = tp->pdu_count[ANY_PDU][CNT_TX] -
				  tp->pdu_last[ANY_PDU][CNT_TX];
			break;

		case ABSOLUTE_RX:
			if (rxtx != CNT_RX)
				return check_loss(tp, rxtx);
			off = tp->pdu_count[ANY_PDU][CNT_RX];
			break;
		case RELATIVE_RX:
			if (rxtx != CNT_RX)
				return check_loss(tp, rxtx);
			off = tp->pdu_count[ANY_PDU][CNT_RX] -
				  tp->pdu_last[ANY_PDU][CNT_RX];
			break;

		default:
			/* bad offset - skip this entry */
			mpoff = off = 0;
			break;
		}

		DEB(1, ("test_mod: kind=%d, rxtx=%d, pdukind=%d, mpoff=%d, "
				"whichoff=%d, off=%d\n", kind, rxtx, mod->pars.which_pdu,
				mpoff, mod->pars.which_offset, off));

		if (!off || (mpoff != 0 && mpoff < off)) {
			/* This might happen in some cases. Just discard the modification. */
			s = splbio();
			TAILQ_REMOVE(&tp->mods, mod, link);
			splx(s);

			update_options(tp, mod);

			if (mod->pars.options & ISCSITEST_OPT_WAIT_FOR_COMPLETION) {
				mod->pars.status = ISCSI_STATUS_TEST_MODIFICATION_SKIPPED;
				wakeup(mod);
			}
			free(mod, M_TEMP);
		}
	} while (mpoff && mpoff < off);

	if (mpoff > off)
		return check_loss(tp, rxtx);

	DEB(1, ("test_mod: opt=%x, pdu_ptr=%x, num_mods=%d\n", mod->pars.options,
			(int) mod->pdu_ptr, mod->pars.num_pdu_mods));

	if (mod->pdu_ptr)
		test_get(pdu, mod, err);

	if (mod->pars.options & ISCSITEST_OPT_DISCARD_PDU)
		rc = 1;
	else if (check_loss(tp, rxtx))
		rc = 1;
	else if (mod->pars.num_pdu_mods) {
		if (!(mod->pars.options & ISCSITEST_OPT_MOD_PERMANENT)) {
			/*
             * Note: if the PDU is later resent, the unmodified one will be
             * used as resend_pdu restores the original io vector.
             */
			pdu->mod_pdu = pdu->pdu;
			pdu->io_vec[0].iov_base = &pdu->mod_pdu;
		}
		for (i = 0; i < mod->pars.num_pdu_mods; i++) {
			mod_pdu(pdu, &mod->mods[i]);
		}
	}

	if (rxtx == CNT_TX) {
		if (mod->pars.options & ISCSITEST_OPT_NO_RESPONSE_PDU) {
			ccb_t *ccb = pdu->owner;

			DEB(1, ("test_mod: No response expected, completing CCB %x\n",
					(int)ccb));

			if (ccb != NULL &&
				(ccb->disp == CCBDISP_WAIT || ccb->disp == CCBDISP_SCSIPI)) {
				/* simulate timeout */
				wake_ccb(ccb, ISCSI_STATUS_TIMEOUT);
			}
		}

		if ((mod->pars.options & ISCSITEST_SFLAG_UPDATE_FIELDS) &&
			mod->pars.num_pdu_mods) {
			connection_t *conn = pdu->connection;

			if (conn->HeaderDigest &&
				!(mod->pars.options & ISCSITEST_SFLAG_NO_HEADER_DIGEST))
				pdu->pdu.HeaderDigest = gen_digest(&pdu->pdu, BHS_SIZE);

			if (pdu->uio.uio_iovcnt > 1 && conn->DataDigest &&
				!(mod->pars.options & ISCSITEST_SFLAG_NO_DATA_DIGEST))
				pdu->data_digest = gen_digest_2(
						pdu->io_vec[1].iov_base,
						pdu->io_vec[1].iov_len,
						pdu->io_vec[2].iov_base,
						pdu->io_vec[2].iov_len);
		}
	}

	s = splbio();
	TAILQ_REMOVE(&tp->mods, mod, link);
	update_options(tp, mod);
	/* we've modified a PDU - copy current count into last count */
	memcpy(tp->pdu_last, tp->pdu_count, sizeof(tp->pdu_last));
	splx(s);

	if (mod->pars.options & ISCSITEST_OPT_WAIT_FOR_COMPLETION) {
		wakeup(mod);
	}
	if (mod->pars.options & ISCSITEST_KILL_CONNECTION) {
		kill_connection(tp->connection,
				ISCSI_STATUS_TEST_CONNECTION_CLOSED,
				NO_LOGOUT, TRUE);
	}
	free(mod, M_TEMP);

	return rc;
}