Files
udpxd/udpxd.c

202 lines
4.7 KiB
C
Raw Normal View History

2015-04-21 20:09:12 +02:00
/*
This file is part of udpxd.
Copyright (C) 2015 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tom AT vondein DOT org>.
*/
#include "udpxd.h"
#include "net.h"
#include "client.h"
/* global client list */
client_t *clients = NULL;
int VERBOSE = 0;
2015-04-24 22:03:50 +02:00
/* parse ip:port */
int parse_ip(char *src, char *ip, char *pt) {
char *ptr = NULL;
2015-04-21 20:09:12 +02:00
2015-04-24 22:03:50 +02:00
if (strchr(optarg, '[')) {
/* v6 */
ptr = strtok(&src[1], "]");
2015-04-21 20:09:12 +02:00
2015-04-24 22:03:50 +02:00
if(strlen(ptr) > INET6_ADDRSTRLEN) {
fprintf(stderr, "ip v6 address is too long!\n");
return 1;
}
strncpy(ip, ptr, strlen(ptr)+1);
ptr = strtok(NULL, "]");
if(ptr)
ptr = &ptr[1]; /* remove : */
}
else if(strchr(optarg, ':')) {
/* v4 */
ptr = strtok(src, ":");
if(strlen(ptr) > INET_ADDRSTRLEN) {
fprintf(stderr, "ip v4 address is too long!\n");
return 1;
}
strncpy(ip, ptr, strlen(ptr)+1);
ptr = strtok(NULL, ":");
}
else {
fprintf(stderr, "Invalid ip/port specification!\n");
return 1;
}
2015-04-21 20:09:12 +02:00
2015-04-24 22:03:50 +02:00
if(ptr != NULL) {
/* got a port */
if(strlen(ptr) > 5) {
fprintf(stderr, "port is too long!\n");
return 1;
}
else {
if(atoi(ptr) > 65535) {
fprintf(stderr, "maximum port number possible: 65535!\n");
return 1;
2015-04-21 20:09:12 +02:00
}
2015-04-24 22:03:50 +02:00
strncpy(pt, ptr, strlen(ptr)+1);
2015-04-21 20:09:12 +02:00
}
2015-04-24 22:03:50 +02:00
}
else {
fprintf(stderr, "Port is missing!\n");
return 1;
}
return 0;
2015-04-21 20:09:12 +02:00
}
2015-04-24 22:03:50 +02:00
2015-04-21 20:09:12 +02:00
int main ( int argc, char* argv[] ) {
2015-04-24 22:03:50 +02:00
int opt, err;
2015-04-21 20:09:12 +02:00
char *inip, *inpt, *srcip, *dstip, *dstpt;
2015-04-24 22:03:50 +02:00
err = 0;
2015-04-21 20:09:12 +02:00
static struct option longopts[] = {
{ "listen", required_argument, NULL, 'l' },
{ "bind", required_argument, NULL, 'b' },
{ "dest", required_argument, NULL, 'd' },
{ "version", no_argument, NULL, 'v' },
{ "help", no_argument, NULL, 'h' },
{ "verbose", no_argument, NULL, 'V' }
};
if( argc < 2 ) {
usage();
return 1;
}
srcip = dstip = inip = dstpt = inpt = NULL;
2015-04-24 22:03:50 +02:00
2015-04-21 20:09:12 +02:00
while ((opt = getopt_long(argc, argv, "l:b:d:vVh?", longopts, NULL)) != -1) {
switch (opt) {
case 'v':
fprintf(stderr, "This is %s version %s\n", argv[0], UDPXD_VERSION);
return 1;
break;
case 'h':
case '?':
usage();
return 1;
break;
case 'V':
VERBOSE = 1;
break;
case 'l':
2015-04-24 22:03:50 +02:00
inip = malloc(INET6_ADDRSTRLEN+1);
inpt = malloc(6);
if (parse_ip(optarg, inip, inpt) != 0) {
2015-04-21 20:09:12 +02:00
fprintf(stderr, "Parameter -l has the format <ip-address:port>!\n");
2015-04-24 22:03:50 +02:00
err = 1;
2015-04-21 20:09:12 +02:00
}
break;
case 'd':
2015-04-24 22:03:50 +02:00
dstip = malloc(INET6_ADDRSTRLEN+1);
dstpt = malloc(6);
if (parse_ip(optarg, dstip, dstpt) != 0) {
2015-04-21 20:09:12 +02:00
fprintf(stderr, "Parameter -d has the format <ip-address:port>!\n");
2015-04-24 22:03:50 +02:00
err = 1;
2015-04-21 20:09:12 +02:00
}
break;
case 'b':
2015-04-24 22:03:50 +02:00
if(strlen(optarg) > INET6_ADDRSTRLEN) {
fprintf(stderr, "Bind ip address is too long!\n");
err = 1;
}
srcip = malloc(INET6_ADDRSTRLEN+1);
2015-04-21 20:09:12 +02:00
strncpy(srcip, optarg, strlen(optarg));
break;
default:
usage();
return 1;
break;
}
}
if(inip == NULL) {
fprintf(stderr, "-l parameter is required!\n");
usage();
2015-04-24 22:03:50 +02:00
err = 1;
2015-04-21 20:09:12 +02:00
}
if(dstip == NULL) {
fprintf(stderr, "-d parameter is required!\n");
usage();
2015-04-24 22:03:50 +02:00
err = 1;
2015-04-21 20:09:12 +02:00
}
2015-04-24 22:03:50 +02:00
if(! err) {
err = start_listener (inip, inpt, srcip, dstip, dstpt);
2015-04-21 20:09:12 +02:00
}
2015-04-24 22:03:50 +02:00
/* FIXME: add sighandler */
if(srcip != NULL)
free(srcip);
if(dstip != NULL)
free(dstip);
if(inip != NULL)
free(inip);
if(inpt != NULL)
free(inpt);
if(dstpt != NULL)
free(dstpt);
return err;
2015-04-21 20:09:12 +02:00
}
void usage() {
fprintf(stderr,
"Usage: udpxd [-lbdvhV]\n\n"
"Options:\n"
"--listen -l <ip:port> listen for incoming requests\n"
"--bind -b <ip> bind ip used for outgoing requests\n"
"--dest -d <ip:port> destination to forward requests to\n"
"--help -h -? print help message\n"
"--version -v print program version\n"
"--verbose -V enable verbose logging\n\n"
"Options -l and -d are mandatory.\n\n"
"This is udpxd version %s.\n", UDPXD_VERSION
);
}