Esempio n. 1
0
void
tc_intercept_release_tunnel(int fd, tc_event_t *rev)
{
    if (!srv_settings.tunnel[fd].fd_valid) {
        tc_log_info(LOG_WARN, 0, "already released, fd:%d", fd);
        return;
    }

    tc_log_info(LOG_NOTICE, 0, "release tunnel related resources, fd:%d", fd);
    tc_socket_close(fd);           
    srv_settings.tunnel[fd].fd_valid = 0;
#if (INTERCEPT_COMBINED)
    if (srv_settings.tunnel[fd].combined != NULL) {
        free(srv_settings.tunnel[fd].combined);
        srv_settings.tunnel[fd].combined = NULL;
    } else {
        tc_log_info(LOG_NOTICE, 0, "crazy here, combined is null, fd:%d", fd);
    }
#endif
    if (rev == NULL) {
        if (srv_settings.tunnel[fd].ev == NULL) {
            tc_log_info(LOG_NOTICE, 0, "crazy here, ev is null, fd:%d", fd);
        } else {
            tc_event_del(srv_settings.tunnel[fd].ev->loop, 
                    srv_settings.tunnel[fd].ev, TC_EVENT_READ);
            tc_event_destroy(srv_settings.tunnel[fd].ev, 1);
            srv_settings.tunnel[fd].ev = NULL;
        }
    } else {
        tc_event_del(rev->loop, rev, TC_EVENT_READ);
    }
}
Esempio n. 2
0
static int 
tc_msg_event_process(tc_event_t *rev)
{
    msg_client_t msg;

    if (tc_socket_recv(rev->fd, (char *) &msg, MSG_CLIENT_SIZE) == TC_ERROR) {
        tc_socket_close(rev->fd);
        tc_log_info(LOG_NOTICE, 0, "close sock:%d", rev->fd);
        tc_event_del(rev->loop, rev, TC_EVENT_READ);
        return TC_ERROR;
    }

    switch (msg.type) {
        case CLIENT_ADD:
            tc_log_debug1(LOG_DEBUG, 0, "add client router:%u",
                          ntohs(msg.client_port));
            router_add(msg.client_ip, msg.client_port, rev->fd);
            break;
        case CLIENT_DEL:
            tc_log_debug1(LOG_DEBUG, 0, "del client router:%u",
                          ntohs(msg.client_port));
            router_del(msg.client_ip, msg.client_port);
            break;
    }

    return TC_OK;
}
Esempio n. 3
0
int
tc_socket_connect(int fd, uint32_t ip, uint16_t port)
{
    socklen_t           len;
    struct sockaddr_in  remote_addr;                           

    tc_memzero(&remote_addr, sizeof(remote_addr));               

    remote_addr.sin_family = AF_INET;                         
    remote_addr.sin_addr.s_addr = ip;                
    remote_addr.sin_port = htons(port);                       

    len = (socklen_t) (sizeof(remote_addr));

    if (connect(fd, (struct sockaddr *) &remote_addr, len) == -1) {
        tc_log_info(LOG_ERR, errno, "Can not connect to remote server(%s:%d)",
                inet_ntoa(remote_addr.sin_addr), port);
        tc_socket_close(fd);
        return TC_ERROR;
    } else {
        tc_log_info(LOG_INFO, 0, "connect to remote server(%s:%d)",
                inet_ntoa(remote_addr.sin_addr), port);
        return TC_OK;
    }

}
Esempio n. 4
0
static int
tc_msg_event_accept(tc_event_t *rev)
{
    tc_event_t     *ev;
    register int    fd;
    tunnel_basic_t *tunnel;

    if ((fd = tc_socket_accept(rev->fd)) == TC_INVALID_SOCK) {
        tc_log_info(LOG_ERR, 0, "msg accept failed, from listen:%d", rev->fd);
        return TC_ERR;
    }
    
    tc_log_info(LOG_NOTICE, 0, "it adds fd:%d", fd);

    if (tc_socket_set_nodelay(fd) == TC_ERR) {
        tc_log_info(LOG_ERR, 0, "Set no delay to socket(%d) failed.", rev->fd);
        tc_log_info(LOG_NOTICE, 0, "it close socket:%d", fd);
        tc_socket_close(fd);
        return TC_ERR;
    }

#if (TC_SINGLE)  
    if (!tc_intercept_check_tunnel_for_single(fd)) {
        tc_log_info(LOG_WARN, 0, "sth tries to connect to server.");
        tc_log_info(LOG_NOTICE, 0, "it close socket:%d", fd);
        tc_socket_close(fd);
        return TC_ERR;
    }
#endif   

    ev = tc_event_create(rev->loop->pool, fd, tc_msg_event_proc, NULL);
    if (ev == NULL) {
        tc_log_info(LOG_ERR, 0, "Msg event create failed.");
        return TC_ERR;
    }

    if (tc_event_add(rev->loop, ev, TC_EVENT_READ) == TC_EVENT_ERROR) {
        return TC_ERR;
    }

    tunnel = srv_settings.tunnel;
    tunnel[fd].ev = ev;
    tunnel[fd].first_in = 1;
    tunnel[fd].fd_valid = 1;

    return TC_OK;
}
Esempio n. 5
0
static int
connect_to_server(tc_event_loop_t *ev_lp)
{
    int              i, j, fd;
    uint32_t         target_ip;
    conns_t         *conns;
    uint16_t         target_port;

    for (i = 0; i < clt_settings.real_servers.num; i++) {

        conns = &(clt_settings.real_servers.conns[i]);
        target_ip = conns[i].ip;
        target_port = conns[i].port;
        if (target_port == 0) {
            target_port = clt_settings.srv_port;
        }

        if (conns[i].active != 0) {
            continue;
        }

        for (j = 0; j < conns->num; j++) {
             fd = conns->fds[j];
             if (fd > 0) {
                 tc_log_info(LOG_NOTICE, 0, "it close socket:%d", fd);
                 tc_socket_close(fd);
                 tc_event_del(clt_settings.ev[fd]->loop, 
                         clt_settings.ev[fd], TC_EVENT_READ);
                 tc_event_destroy(clt_settings.ev[fd], 0);
                 conns->fds[j] = -1;
             }
        }

        clt_settings.real_servers.conns[i].num = 0;
        clt_settings.real_servers.conns[i].remained_num = 0;

        for (j = 0; j < clt_settings.par_conns; j++) {
            fd = tc_message_init(ev_lp, target_ip, target_port);
            if (fd == TC_INVALID_SOCK) {
                return TC_ERR;
            }

            if (!send_version(fd)) {
                return TC_ERR;
            }

            if (j == 0) {
                clt_settings.real_servers.active_num++;
                conns[i].active = 1;
            }

            clt_settings.real_servers.conns[i].fds[j] = fd;
            clt_settings.real_servers.conns[i].num++;
            clt_settings.real_servers.conns[i].remained_num++;
        }
    }

    return TC_OK;
}
Esempio n. 6
0
void
tcp_copy_release_resources(void)
{
#if (TC_PCAP)
    int i;
#endif 
    tc_log_info(LOG_WARN, 0, "sig %d received", tc_over); 

    tc_output_stat();

    tc_dest_sess_table();

    check_resource_usage(NULL);
#if (TC_PLUGIN)
    if (clt_settings.plugin && clt_settings.plugin->exit_module) {
        clt_settings.plugin->exit_module(&clt_settings);
    }
#endif

    tc_event_loop_finish(&event_loop);
    tc_log_info(LOG_NOTICE, 0, "tc_event_loop_finish over");

#if (TC_DIGEST)
    tc_destroy_sha1();
    tc_destroy_digests();
#endif

#if (TC_PCAP)
    for (i = 0; i < clt_settings.devices.device_num; i++) {
        if (clt_settings.devices.device[i].pcap != NULL) {
            pcap_close(clt_settings.devices.device[i].pcap);
            clt_settings.devices.device[i].pcap = NULL;
        }
    }
#endif

#if (TC_OFFLINE)
    if (clt_settings.pcap != NULL) {
        pcap_close(clt_settings.pcap);
        clt_settings.pcap = NULL;
    }
#endif

    if (tc_raw_socket_out > 0) {
        tc_socket_close(tc_raw_socket_out);
        tc_raw_socket_out = TC_INVALID_SOCK;
    }

#if (TC_PCAP_SND)
    tc_pcap_over();
#endif
    tc_destroy_pool(clt_settings.pool);

    tc_log_end();
}
Esempio n. 7
0
int
tc_raw_socket_send(int fd, void *buf, size_t len, uint32_t ip)
{
    ssize_t             send_len, offset = 0, num_bytes;
    const char         *ptr;
    struct sockaddr_in  dst_addr;

    if (fd > 0) {
        
        memset(&dst_addr, 0, sizeof(struct sockaddr_in));

        dst_addr.sin_family = AF_INET;
        dst_addr.sin_addr.s_addr = ip;

        ptr = buf;

        /*
         * The output packet will take a special path of IP layer
         * (raw_sendmsg->raw_send_hdrinc->NF_INET_LOCAL_OUT->...).
         * No IP fragmentation will take place if needed. 
         * This means that a raw packet larger than the MTU of the 
         * interface will probably be discarded. Instead ip_local_error(), 
         * which does general sk_buff cleaning, is called and an 
         * error EMSGSIZE is returned. 
         */
        do {
            num_bytes = len - offset;
            send_len = sendto(fd, ptr + offset, num_bytes, 0, 
                    (struct sockaddr *) &dst_addr, sizeof(dst_addr));

            if (send_len == -1) {

                if (errno == EINTR) {
                    tc_log_info(LOG_NOTICE, errno, "raw fd:%d EINTR", fd);
                } else if (errno == EAGAIN) {
                    tc_log_info(LOG_NOTICE, errno, "raw fd:%d EAGAIN", fd);
                } else {
                    tc_log_info(LOG_ERR, errno, "raw fd:%d", fd);
                    tc_socket_close(fd);
                    return TC_ERROR;
                }

            }  else {
                offset += send_len;
            }

        } while (offset < len);
    } 

    return TC_OK;
}
Esempio n. 8
0
static void 
address_release()
{   
    int             i, j, fd;
    hash_node      *hn;
    link_list      *list;
    p_link_node     ln, tmp_ln;
    connections_t  *connections;

    if (addr_table == NULL) {
        return;
    }

    for (i = 0; i < addr_table->size; i++) {

        list = addr_table->lists[i];
        ln   = link_list_first(list);   
        while (ln) {

            tmp_ln = link_list_get_next(list, ln);
            hn = (hash_node *) ln->data;
            if (hn->data != NULL) {

                connections = (connections_t *) hn->data;
                hn->data = NULL;

                for (j = 0; j < connections->num; j++) {
                    fd = connections->fds[j];
                    if (fd > 0) {
                        tc_log_info(LOG_NOTICE, 0, "it close socket:%d", fd);
                        connections->fds[j] = -1;
                        tc_socket_close(fd);
                    }
                }
                free(connections);
            }
            ln = tmp_ln;
        }
    }

    tc_log_info(LOG_NOTICE, 0, "destroy addr table");
    hash_destroy(addr_table);
    free(addr_table);
    addr_table = NULL;

}
Esempio n. 9
0
static int
tc_process_server_msg(tc_event_t *rev)
{
#if (TCPCOPY_DR)
    int          i;
#endif
    msg_server_t msg;

    if (tc_socket_recv(rev->fd, (char *) &msg,
                MSG_SERVER_SIZE) == TC_ERROR)
    {
        tc_log_info(LOG_ERR, 0, 
                    "Recv socket(%d)error, server may be closed", rev->fd);
#if (TCPCOPY_DR)

        for (i = 0; i < clt_settings.real_servers.num; i++) {

            if (clt_settings.real_servers.fds[i] == rev->fd) {
                if (clt_settings.real_servers.active[i]) {
                    clt_settings.real_servers.active[i] = 0;
                    clt_settings.real_servers.active_num--;
                }
                tc_socket_close(rev->fd);
                tc_log_info(LOG_NOTICE, 0, "close sock:%d", rev->fd);
                tc_event_del(rev->loop, rev, TC_EVENT_READ);

                break;
            }
        }


        if (clt_settings.real_servers.active_num == 0) {
            return TC_ERR_EXIT;
        } else {
            return TC_OK;
        }
#else 
        return TC_ERR_EXIT;
#endif
    }

    process((char *) &msg, REMOTE);

    return TC_OK;
}
Esempio n. 10
0
int
tc_socket_send(int fd, char *buffer, int len)
{
    ssize_t     send_len, offset = 0, num_bytes;
    const char *ptr;

    if (len <= 0) {
        return TC_OK;
    }

    ptr = buffer;
    num_bytes = len - offset;

    do {

        send_len = send(fd, ptr + offset, num_bytes, 0);

        if (send_len == -1) {

            if (errno == EINTR) {
                tc_log_info(LOG_NOTICE, errno, "fd:%d EINTR", fd);
            } else if (errno == EAGAIN) {
                tc_log_info(LOG_NOTICE, errno, "fd:%d EAGAIN", fd);
            } else {
                tc_log_info(LOG_ERR, errno, "fd:%d", fd);
                tc_socket_close(fd);
                return TC_ERROR;
            }

        } else {

            if (send_len != num_bytes) {
                tc_log_info(LOG_WARN, 0, "fd:%d, slen:%ld, bsize:%ld",
                        fd, send_len, num_bytes);
            }

            offset += send_len;
        }
    } while (offset < len);

    return TC_OK;
}
Esempio n. 11
0
int tc_select_destroy(tc_event_loop_t *loop)
{
    int                       i;
    tc_event_t               *event;
    tc_select_multiplex_io_t *io;

    io = loop->io;

    for (i = 0; i < io->last; i++) {
        event = io->evs[i];
        if (event->fd > 0) {
            tc_socket_close(event->fd);
        }
        event->fd = -1;
        free(event);
    }

    free(io->evs);
    free(loop->io);

    return TC_EVENT_OK;
}
Esempio n. 12
0
int tc_epoll_destroy(tc_event_loop_t *loop)
{
    int                       i;
    tc_event_t               *event;
    tc_epoll_multiplex_io_t  *io;

    io = loop->io;

    for (i = 0; i <= io->max_fd; i++) {
        event = io->evs[i];
        if (event != NULL) {
            if (event->fd > 0) {
                tc_log_info(LOG_NOTICE, 0, "tc_epoll_destroy, close fd:%d",
                        event->fd);
                tc_socket_close(event->fd);
                event->fd = -1;
                tc_pfree(loop->pool, event);
            } else {
                tc_log_info(LOG_WARN, 0, "tc_epoll_destroy, fd < 0:%d",
                        event->fd);
                tc_pfree(loop->pool, event);
            }
        }
    }

    if (io->efd) {
        close(io->efd);
        io->efd = -1;
    }
    io->max_fd = -1;

    tc_pfree(loop->pool, io->events);
    tc_pfree(loop->pool, io->evs);
    tc_pfree(loop->pool, loop->io);

    return TC_EVENT_OK;
}
Esempio n. 13
0
int tc_select_destroy(tc_event_loop_t *loop)
{
    int                       i;
    tc_event_t               *event;
    tc_select_multiplex_io_t *io;

    io = loop->io;

    for (i = 0; i < io->last; i++) {
        event = io->evs[i];
        if (event->fd > 0) {
            tc_log_info(LOG_NOTICE, 0, "tc_select_destroy, close fd:%d", 
                    event->fd);
            tc_socket_close(event->fd);
        }
        event->fd = -1;
        tc_pfree(loop->pool, event);
    }

    tc_pfree(loop->pool, io->evs);
    tc_pfree(loop->pool, loop->io);

    return TC_EVENT_OK;
}
Esempio n. 14
0
static int
tc_process_server_msg(tc_event_t *rev)
{
#if (TCPCOPY_DR)
    int            i, j;
    connections_t *connections;
#endif
#if (!TCPCOPY_COMBINED)
    int            len;
    msg_server_t   msg;
#else
    int            num, k;
    unsigned char *p, aggr_resp[COMB_LENGTH + sizeof(uint16_t)];
#endif

#if (!TCPCOPY_COMBINED)
    len = MSG_SERVER_SIZE;
#endif

#if (!TCPCOPY_COMBINED)
    if (tc_socket_recv(rev->fd, (char *) &msg, len) == TC_ERROR)
#else
    if (tc_socket_cmb_recv(rev->fd, &num, (char *) aggr_resp) == TC_ERROR)
#endif
    {
        tc_log_info(LOG_ERR, 0, "Recv socket(%d)error", rev->fd);
        tc_log_info(LOG_ERR, 0, "server may be closed or");
        tc_log_info(LOG_ERR, 0, "backend TCP/IP kernel memeory is too low or");
        tc_log_info(LOG_ERR, 0, 
                "the version of intercept may not be equal to the version of tcpcopy");
#if (TCPCOPY_DR)

        for (i = 0; i < clt_settings.real_servers.num; i++) {

            connections = &(clt_settings.real_servers.connections[i]);
            for (j = 0; j < connections->num; j++) {
                if (connections->fds[j] == rev->fd) {
                    tc_socket_close(rev->fd);
                    tc_log_info(LOG_NOTICE, 0, "close sock:%d", rev->fd);
                    tc_event_del(rev->loop, rev, TC_EVENT_READ);
                    connections->num--;

                    if (connections->num == 0 && 
                            clt_settings.real_servers.active[i]) 
                    {
                        clt_settings.real_servers.active[i] = 0;
                        clt_settings.real_servers.active_num--;
                    }

                    break;
                }
            }
        }


        if (clt_settings.real_servers.active_num == 0) {
            return TC_ERR_EXIT;
        } else {
            return TC_OK;
        }
#else 
        return TC_ERR_EXIT;
#endif
    }

#if (!TCPCOPY_COMBINED)
    process_out((unsigned char *) &msg);
#else
    tc_log_debug1(LOG_DEBUG, 0, "resp packets:%d", num);
    p = aggr_resp + sizeof(uint16_t);
    for (k = 0; k < num; k++) {
        process_out(p);
        p = p + MSG_SERVER_SIZE;
    }
#endif

    return TC_OK;
}
Esempio n. 15
0
void
tcp_copy_release_resources()
{
    int i;

    tc_log_info(LOG_WARN, 0, "sig %d received", tc_over); 

    output_stat();

    tc_time_remove_timer();
    tc_log_info(LOG_NOTICE, 0, "remove timer over");

    destroy_for_sessions();

    tc_event_loop_finish(&event_loop);
    tc_log_info(LOG_NOTICE, 0, "tc_event_loop_finish over");

#if (TCPCOPY_DIGEST)
    tc_destroy_sha1();
    tc_destroy_digests();
#endif

#if (!TCPCOPY_DR)
    address_release();
#endif

    tc_log_end();

#ifdef TCPCOPY_MYSQL_ADVANCED
    release_mysql_user_pwd_info();
#endif

#if (TCPCOPY_PCAP)
    for (i = 0; i < clt_settings.devices.device_num; i++) {
        if (clt_settings.devices.device[i].pcap != NULL) {
            pcap_close(clt_settings.devices.device[i].pcap);
            clt_settings.devices.device[i].pcap = NULL;
        }
    }
#endif

#if (TCPCOPY_OFFLINE)
    if (clt_settings.pcap != NULL) {
        pcap_close(clt_settings.pcap);
        clt_settings.pcap = NULL;
    }
#endif

    if (tc_raw_socket_out > 0) {
        tc_socket_close(tc_raw_socket_out);
        tc_raw_socket_out = TC_INVALID_SOCKET;
    }

#if (TCPCOPY_PCAP_SEND)
    tc_pcap_over();
#endif

    if (clt_settings.transfer.mappings != NULL) {

        for (i = 0; i < clt_settings.transfer.num; i++) {
            free(clt_settings.transfer.mappings[i]);
        }

        free(clt_settings.transfer.mappings);
        clt_settings.transfer.mappings = NULL;
    }
}
Esempio n. 16
0
static int
connect_to_server(tc_event_loop_t *event_loop)
{
    int                    i, j, fd;
    uint32_t               target_ip;
    uint16_t               target_port;
    connections_t         *connections;

    /* 
     * add connections to the real servers for sending router info 
     * and receiving response packet
     */
    for (i = 0; i < clt_settings.real_servers.num; i++) {

        target_ip = clt_settings.real_servers.ips[i];
        target_port = clt_settings.real_servers.ports[i];
        if (target_port == 0) {
            target_port = clt_settings.srv_port;
        }

        if (clt_settings.real_servers.active[i] != 0) {
            continue;
        }

        connections = &(clt_settings.real_servers.connections[i]);
        for (j = 0; j < connections->num; j++) {
            fd = connections->fds[j];
            if (fd > 0) {
                tc_log_info(LOG_NOTICE, 0, "it close socket:%d", fd);
                tc_socket_close(fd);
                tc_event_del(clt_settings.ev[fd]->loop, 
                        clt_settings.ev[fd], TC_EVENT_READ);
                tc_event_destroy(clt_settings.ev[fd]);
                connections->fds[j] = -1;
            }
        }

        clt_settings.real_servers.connections[i].num = 0;
        clt_settings.real_servers.connections[i].remained_num = 0;

        for (j = 0; j < clt_settings.par_connections; j++) {
            fd = tc_message_init(event_loop, target_ip, target_port);
            if (fd == TC_INVALID_SOCKET) {
                return TC_ERROR;
            }

            if (!send_version(fd)) {
                return TC_ERROR;
            }

            if (j == 0) {
                clt_settings.real_servers.active_num++;
                clt_settings.real_servers.active[i] = 1;
            }

            clt_settings.real_servers.connections[i].fds[j] = fd;
            clt_settings.real_servers.connections[i].num++;
            clt_settings.real_servers.connections[i].remained_num++;

        }

        tc_log_info(LOG_NOTICE, 0, "add dr tunnels for exchanging info:%u:%u",
                target_ip, target_port);
    }

    return TC_OK;


}