summaryrefslogtreecommitdiff
path: root/src/udpastcp.c
blob: 31d2d507025bb983547458ab6f270f7f57474587 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <dlfcn.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#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[]) {
    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));

    if (getenv("UDPASTCP_RELEASE_MEMORY")) {
        DBG("UDPASTCP_RELEASE_MEMORY is set, will free all memory on exit.");
        free_mem_on_exit = 1;
    }

    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);
}