#include #include #include #include #include #include "connection.h" #include "event.h" #include "list.h" #include "logging.h" #include "network.h" struct connection { struct list_head list; struct sockaddr_in src_addr; struct sockaddr_in dst_addr; int src_fd; int dst_fd; unsigned long login_time; }; static LIST_HEAD(connection_list); static struct connection * create_connection() { struct connection *con = malloc(sizeof(struct connection)); if (con == NULL) { log_print(LOG_WARN, "listen_handler(): out of memory"); return 0; } con->src_fd = con->dst_fd = -1; con->login_time = time(NULL); return con; } static int destroy_connection(struct connection *con) { if (con->src_fd != -1) { close(con->src_fd); event_remove_fd(con->src_fd); } if (con->dst_fd != -1) { close(con->dst_fd); event_remove_fd(con->dst_fd); } free(con); return 0; } static int forward_handler(int fd, void *privdata) { struct connection *con = (struct connection *)privdata; char buf[256]; int len = read(fd, buf, sizeof(buf)); if (len <= 0) { list_del(&con->list); destroy_connection(con); return -1; } /* client -> device */ if (con->src_fd == fd) write(con->dst_fd, buf, len); /* device -> client */ else if (con->dst_fd == fd) write(con->src_fd, buf, len); return 0; } static int client_handler(int fd, void *privdata) { struct connection *con = (struct connection *)privdata; char buf[256]; int len = read(fd, buf, sizeof(buf)); if (len <= 0) { list_del(&con->list); destroy_connection(con); return -1; } if (parse_saddr(buf, &con->dst_addr) != 0) { list_del(&con->list); destroy_connection(con); return -1; } // check destination con->dst_fd = tcp_connect_socket(&con->dst_addr); if (con->dst_fd < 0) { list_del(&con->list); destroy_connection(con); return -1; } log_print(LOG_INFO, "forwarding to %s", get_sockaddr_buf(&con->dst_addr)); event_add_readfd(con->dst_fd, forward_handler, con); event_add_readfd(con->src_fd, forward_handler, con); /* dismiss client_handler */ return -1; } static int admin_handler(int fd, void *privdata) { return -1; } int listen_handler(int fd, void *privdata) { int mode = (int)privdata; struct connection *con = create_connection(); if (con == NULL) { log_print(LOG_WARN, "listen_handler(): out of memory"); return 0; } unsigned int i = sizeof(con->src_addr); con->src_fd = accept(fd, (struct sockaddr *)&con->src_addr, &i); if (con->src_fd < 0) { free(con); return 0; } log_print(LOG_INFO, "accepted connection from %s", get_sockaddr_buf(&con->src_addr)); list_add_tail(&con->list, &connection_list); if (mode == CON_ADMIN) event_add_readfd(con->src_fd, client_handler, con); else event_add_readfd(con->src_fd, admin_handler, con); return 0; }