From 436011fee88fb1f8e2941c518e5f7bd11d66559d Mon Sep 17 00:00:00 2001 From: "Alex Xu (Hello71)" Date: Thu, 14 Jul 2016 15:49:58 -0400 Subject: Rewrite args parsing to prepare for libpcap. --- src/checksum.h | 5 ++++ src/client.c | 22 +++++++--------- src/client.h | 7 ++++- src/common.h | 14 ++++++++++ src/server.c | 12 ++++----- src/server.h | 9 ++++++- src/udpastcp.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++------- test.sh | 4 +-- 8 files changed, 123 insertions(+), 32 deletions(-) diff --git a/src/checksum.h b/src/checksum.h index 74fe69f..192d538 100644 --- a/src/checksum.h +++ b/src/checksum.h @@ -1,3 +1,6 @@ +#ifndef CHECKSUM_H +#define CHECKSUM_H + #include struct sockaddr; @@ -14,3 +17,5 @@ uint16_t csum_partial(const void *buff, int len, uint16_t wsum); * otherwise identical to csum_partial. */ uint16_t csum_sockaddr_partial(const struct sockaddr *addr, int incl_port, uint16_t wsum); + +#endif diff --git a/src/client.c b/src/client.c index 733ffa0..1517481 100644 --- a/src/client.c +++ b/src/client.c @@ -23,8 +23,7 @@ #define PORTS_IN_INT (sizeof(int) * CHAR_BIT) struct c_data { - const char *r_host; - const char *r_port; + const struct common_data *common_data; struct o_c_sock *o_socks_by_caddr; struct o_c_rsock *o_rsocks; struct sockaddr_storage pkt_addr; @@ -410,9 +409,9 @@ static inline struct o_c_sock * c_sock_init(EV_P_ struct c_data *c_data) { struct o_c_sock *sock = NULL; struct addrinfo *res; - DBG("looking up [%s]:%s", c_data->r_host, c_data->r_port); + DBG("looking up [%s]:%s", c_data->common_data->remote_host, c_data->common_data->remote_port); // TODO: make this asynchronous - int r = getaddrinfo(c_data->r_host, c_data->r_port, NULL, &res); + int r = getaddrinfo(c_data->common_data->remote_host, c_data->common_data->remote_port, NULL, &res); if (r) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(r)); goto err; @@ -565,18 +564,17 @@ static void c_finish(EV_P_ ev_signal *w __attribute__((unused)), int revents __a ev_break(EV_A_ EVBREAK_ALL); } -int start_client(const char *s_host, const char *s_port, const char *r_host, const char *r_port) { +int start_client(const struct common_data *common_data) { struct addrinfo *res; - int r = getaddrinfo(s_host, s_port, NULL, &res); + int r = getaddrinfo(common_data->listen_host, common_data->listen_port, NULL, &res); if (r) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(r)); return 3; } struct c_data c_data = { - .s_addrlen = res->ai_addrlen, - .r_host = r_host, - .r_port = r_port + .common_data = common_data, + .s_addrlen = res->ai_addrlen }; c_data.s_sock = socket(res->ai_family, SOCK_DGRAM, 0); @@ -597,13 +595,13 @@ int start_client(const char *s_host, const char *s_port, const char *r_host, con return 4; } - global_c_data = &c_data; - atexit(c_cleanup); - struct ev_loop *loop = EV_DEFAULT; ev_io s_watcher; ev_signal iwatcher, twatcher; + global_c_data = &c_data; + atexit(c_cleanup); + s_watcher.data = &c_data; ev_io_init(&s_watcher, cs_cb, c_data.s_sock, EV_READ); diff --git a/src/client.h b/src/client.h index 69d4c7d..72c86fb 100644 --- a/src/client.h +++ b/src/client.h @@ -1 +1,6 @@ -int start_client(const char *s_host, const char *s_port, const char *r_host, const char *r_port); +#ifndef CLIENT_H +#define CLIENT_H +#include "common.h" + +int start_client(const struct common_data *); +#endif diff --git a/src/common.h b/src/common.h index fea0db7..9dd7318 100644 --- a/src/common.h +++ b/src/common.h @@ -1,3 +1,6 @@ +#ifndef COMMON_H +#define COMMON_H + #ifdef DEBUG #define DBG(...) do { fprintf(stderr, __VA_ARGS__); putc('\n', stderr); } while (0) #else @@ -7,3 +10,14 @@ #define IN_ADDR_PORT(addr) (((struct sockaddr_in *)addr)->sin_port) extern int free_mem_on_exit; +extern void *libpcap; + +struct common_data { + const char *listen_host; + const char *listen_port; + const char *remote_host; + const char *remote_port; + const char *device; +}; + +#endif diff --git a/src/server.c b/src/server.c index 382e675..b9c2783 100644 --- a/src/server.c +++ b/src/server.c @@ -20,10 +20,9 @@ #include "uthash.h" struct s_data { + const struct common_data *common_data; struct sockaddr *s_addr; struct sockaddr_storage pkt_addr; - const char *r_host; - const char *r_port; struct o_s_sock *o_socks_by_caddr; int s_sock; socklen_t s_addrlen; @@ -299,7 +298,7 @@ static void ss_cb(EV_P_ ev_io *w, int revents __attribute__((unused))) { sock->status = TCP_ESTABLISHED; struct addrinfo *res; - r = getaddrinfo(s_data->r_host, s_data->r_port, NULL, &res); + r = getaddrinfo(s_data->common_data->remote_host, s_data->common_data->remote_port, NULL, &res); if (r) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(r)); ev_break(EV_A_ EVBREAK_ONE); @@ -375,9 +374,9 @@ static void s_finish(EV_P_ ev_signal *w __attribute__((unused)), int revents __a ev_break(EV_A_ EVBREAK_ALL); } -int start_server(const char *s_host, const char *s_port, const char *r_host, const char *r_port) { +int start_server(const struct common_data *common_data) { struct addrinfo *res; - int r = getaddrinfo(s_host, s_port, NULL, &res); + int r = getaddrinfo(common_data->listen_host, common_data->listen_port, NULL, &res); if (r) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(r)); return 1; @@ -386,10 +385,9 @@ int start_server(const char *s_host, const char *s_port, const char *r_host, con char proto[] = { 0, IPPROTO_TCP }; struct s_data s_data = { + .common_data = common_data, .s_addr = res->ai_addr, .s_addrlen = res->ai_addrlen, - .r_host = r_host, - .r_port = r_port, .csum_p = csum_sockaddr_partial(res->ai_addr, 1, csum_partial(&proto, sizeof(proto), 0)) }; diff --git a/src/server.h b/src/server.h index 3157173..80fb26b 100644 --- a/src/server.h +++ b/src/server.h @@ -1 +1,8 @@ -int start_server(const char *s_addr, const char *s_port, const char *r_addr, const char *r_port); +#ifndef SERVER_H +#define SERVER_H + +#include "common.h" + +int start_server(const struct common_data *); + +#endif diff --git a/src/udpastcp.c b/src/udpastcp.c index fa8fea2..31d2d50 100644 --- a/src/udpastcp.c +++ b/src/udpastcp.c @@ -1,17 +1,78 @@ +#include #include #include #include #include +#include #include "common.h" #include "server.h" #include "client.h" int free_mem_on_exit = 0; +void *libpcap = NULL; + +void usage() { + puts("usage: udpintcp [OPTION]...\n" + "Make UDP look like TCP.\n" + "\n" + " -m MODE Client/server mode.\n" + " -h LISTEN_HOST -p LISTEN_PORT Listen on the specified host/port. Port is required.\n" + " -H REMOTE_HOST -P REMOTE_PORT Connect to the specified host/port. Always required.\n" + " -d DEVICE Use libpcap and listen on the specified interface.\n"); +} int main(int argc, char *argv[]) { - if (argc < 6) { - puts("usage: udpintcp client|server LISTEN_HOST LISTEN_PORT REMOTE_HOST REMOTE_PORT"); - return !(argc == 2 && !strcmp(argv[1], "--help")); + char ch; + struct common_data common_data = { + .listen_host = "::" + }; + const char *mode = NULL; + while ((ch = getopt(argc, argv, "m:h:p:H:P:d:")) != -1) { + switch (ch) { + case 'm': + mode = optarg; + break; + case 'h': + common_data.listen_host = optarg; + break; + case 'p': + common_data.listen_port = optarg; + break; + case 'H': + common_data.remote_host = optarg; + break; + case 'P': + common_data.remote_port = optarg; + break; + case 'd': + common_data.device = optarg; + break; + case '?': + usage(); + break; + default: + abort(); + } + if (optind > argc) { + fputs("extra arguments on command line\n", stderr); + exit(EXIT_FAILURE); + } + } + if (!mode) { + fputs("missing required argument: mode", stderr); + exit(EXIT_FAILURE); + } + if (!common_data.listen_port) { + fputs("missing required argument: listen port", stderr); + exit(EXIT_FAILURE); + } + if (!common_data.remote_host) { + fputs("missing required argument: remote host", stderr); + exit(EXIT_FAILURE); + } + if (!common_data.remote_port) { + fputs("missing required argument: remote port", stderr); + exit(EXIT_FAILURE); } srandom((unsigned int)time(NULL)); @@ -21,14 +82,17 @@ int main(int argc, char *argv[]) { free_mem_on_exit = 1; } - if (!strcmp(argv[1], "client")) { - DBG("starting client listening on [%s]:%s connecting to [%s]:%s", argv[2], argv[3], argv[4], argv[5]); - return start_client(argv[2], argv[3], argv[4], argv[5]) == 0; - } else if (!strcmp(argv[1], "server")) { - DBG("starting server listening on [%s]:%s connecting to [%s]:%s", argv[2], argv[3], argv[4], argv[5]); - return start_server(argv[2], argv[3], argv[4], argv[5]) == 0; + int (*startf)(struct common_data *); + + if (!strcmp(mode, "client")) { + startf = start_client; + } else if (!strcmp(mode, "server")) { + startf = start_server; } else { fputs("invalid mode\n", stderr); return 1; } + + DBG("starting %s listening on [%s]:%s connecting to [%s]:%s", mode, common_data.listen_host, common_data.listen_port, common_data.remote_host, common_data.remote_port); + return startf(&common_data); } diff --git a/test.sh b/test.sh index a82020a..62f3b93 100755 --- a/test.sh +++ b/test.sh @@ -7,9 +7,9 @@ test_bidi() { ( pids= trap 'kill $pids' INT TERM EXIT - $UDPASTCP client "$1" 36563 "$1" 64109 & + $UDPASTCP -m client -h "$1" -p 36563 -H "$1" -P 64109 & pids="$!" - $UDPASTCP server "$1" 64109 "$1" 41465 & + $UDPASTCP -m server -h "$1" -p 64109 -H "$1" -P 41465 & pids="$pids $!" ( ( sleep 0.5; echo BBBBBBBB; ) | socat "udp-listen:41465,pf=${2}" - ) & pids="$pids $!" -- cgit v1.2.3-54-g00ecf