diff --git a/CMakeLists.txt b/CMakeLists.txt index daf4ff9..8a884da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ list(APPEND CSOURCES add_executable(donar ${CSOURCES} src/donar.c) add_executable(measlat ${CSOURCES} src/meas_lat.c) add_executable(udpecho ${CSOURCES} src/udp_echo.c) +add_executable(torecho ${CSOURCES} src/tor_echo.c) find_package(PkgConfig REQUIRED) pkg_search_module(GLIB REQUIRED glib-2.0) @@ -45,6 +46,9 @@ target_link_libraries(measlat ${GLIB_LDFLAGS}) target_include_directories(udpecho PRIVATE ${GLIB_INCLUDE_DIRS}) target_link_libraries(udpecho ${GLIB_LDFLAGS}) -install(TARGETS donar measlat udpecho +target_include_directories(torecho PRIVATE ${GLIB_INCLUDE_DIRS}) +target_link_libraries(torecho ${GLIB_LDFLAGS}) + +install(TARGETS donar measlat udpecho torecho RUNTIME DESTINATION bin LIBRARY DESTINATION lib) \ No newline at end of file diff --git a/src/tor_echo.c b/src/tor_echo.c new file mode 100644 index 0000000..d07d2bc --- /dev/null +++ b/src/tor_echo.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include "tor_ctl.h" +#include "evt_core.h" +#include "net_tools.h" + +void create_onion_services(struct tor_os_str* tos, struct tor_ctl* tctl, uint16_t* ports, int ports_count) { + tor_os_create (tos, "onion_services.pub", "onion_services.txt", ports_count); + tor_os_read (tos); + + int err = 0; + err = tor_ctl_connect (tctl, "127.0.0.1", "9051"); + if (err < 0) { + fprintf(stderr, "Unable to open Tor Socket\n"); + exit(EXIT_FAILURE); + } + err = tor_ctl_add_onion (tctl, tos, ports); + if (err != 0) { + fprintf(stderr, "Unable to create Onion Services (error: %d)\n", err); + exit(EXIT_FAILURE); + } +} + +int on_tcp(struct evt_core_ctx* ctx, struct evt_core_fdinfo* fdinfo) { + char buffer[1500]; + ssize_t nread, nwritten; + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + + nread = recvfrom(fdinfo->fd, buffer, sizeof(buffer), MSG_TRUNC, (struct sockaddr*)&addr, &addrlen); + if (nread == -1 && errno == EAGAIN) return 1; // Read done + if (nread <= 0 || nread > sizeof(buffer)) { + fprintf(stderr, "Message is either truncated or an error occured. nread=%ld\n", nread); + perror("read errno"); + exit(EXIT_FAILURE); + } + + nwritten = sendto(fdinfo->fd, buffer, nread, 0, (struct sockaddr*)&addr, addrlen); + // @FIXME don't support EAGAIN on write. Could be intended, you don't think so? + if (nwritten != nread) { + fprintf(stderr, "Didn't write the same number of bytes as read. nread=%ld, nwritten=%ld\n", nread, nwritten); + perror("write errno"); + exit(EXIT_FAILURE); + } + return 0; +} + +int main(int argc, char** argv) { + setvbuf(stdout, NULL, _IONBF, 0); + printf("~ torecho ~\n"); + + int tcp_serv_sock = 0; + struct evt_core_ctx evts = {0}; + uint16_t ports = {7500}; + int port_count = sizeof(ports[0]) / sizeof(ports); + struct tor_os_str tos; + struct tor_ctl tctl; + + // 1. Register categories + struct evt_core_cat tcp_co = { + .app_ctx = NULL, + .free_app_ctx = NULL, + .cb = on_tcp_co, + .err_cb = NULL, + .name = "tcp-all", + .flags = EPOLLIN, + .socklist = NULL + }; + struct evt_core_cat tcp_all = { + .app_ctx = NULL, + .free_app_ctx = NULL, + .cb = on_tcp, + .err_cb = NULL, + .name = "tcp-all", + .flags = EPOLLIN | EPOLLOUT | EPOLLET, + .socklist = NULL + }; + evt_core_init(&evts); + evt_core_add_cat(&evts, &tcp_co); + evt_core_add_cat(&evts, &tcp_all); + printf("--- Categories created\n"); + + // 2. Create or load onion services + create_onion_services (&tos, &tctl, ports, ports_count); + printf("--- Onion services created\n"); + + // 3. Create TCP server + tcp_serv_sock = create_tcp_server ("127.0.0.1", ports[0]); + + char url[1024]; + struct evt_core_cat cat = {0}; + struct evt_core_fdinfo fdinfo = {0}; + fdinfo.cat = &cat; + fdinfo.url = url; + + fdinfo.fd = udp_sock; + sprintf(url, "tcp:all:127.0.0.1:%s", port); + fdinfo.cat->name = "tcp-all"; + evt_core_add_fd(&evts, &fdinfo); + printf("--- TCP server is listening\n"); + + // 4. Start main loop + evt_core_loop (&evts); + + return 0; +}