/* 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 . You can contact me by mail: . */ #include "udpxd.h" #include "net.h" #include "client.h" /* global client list */ client_t *clients = NULL; int VERBOSE = 0; /* parse ip:port */ int parse_ip(char *src, char *ip, char *pt) { char *ptr = NULL; if (strchr(optarg, '[')) { /* v6 */ ptr = strtok(&src[1], "]"); 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; } 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; } strncpy(pt, ptr, strlen(ptr)+1); } } else { fprintf(stderr, "Port is missing!\n"); return 1; } return 0; } int main ( int argc, char* argv[] ) { int opt, err; char *inip, *inpt, *srcip, *dstip, *dstpt; err = 0; 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; 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': inip = malloc(INET6_ADDRSTRLEN+1); inpt = malloc(6); if (parse_ip(optarg, inip, inpt) != 0) { fprintf(stderr, "Parameter -l has the format !\n"); err = 1; } break; case 'd': dstip = malloc(INET6_ADDRSTRLEN+1); dstpt = malloc(6); if (parse_ip(optarg, dstip, dstpt) != 0) { fprintf(stderr, "Parameter -d has the format !\n"); err = 1; } break; case 'b': if(strlen(optarg) > INET6_ADDRSTRLEN) { fprintf(stderr, "Bind ip address is too long!\n"); err = 1; } srcip = malloc(INET6_ADDRSTRLEN+1); strncpy(srcip, optarg, strlen(optarg)); break; default: usage(); return 1; break; } } if(inip == NULL) { fprintf(stderr, "-l parameter is required!\n"); usage(); err = 1; } if(dstip == NULL) { fprintf(stderr, "-d parameter is required!\n"); usage(); err = 1; } if(! err) { err = start_listener (inip, inpt, srcip, dstip, dstpt); } /* 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; } void usage() { fprintf(stderr, "Usage: udpxd [-lbdvhV]\n\n" "Options:\n" "--listen -l listen for incoming requests\n" "--bind -b bind ip used for outgoing requests\n" "--dest -d 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 ); }