mirror of
https://codeberg.org/scip/udpxd.git
synced 2025-12-16 03:20:58 +01:00
ipv6 works now as well, added fork, added syslog
This commit is contained in:
2
Makefile
2
Makefile
@@ -21,7 +21,7 @@
|
||||
# warning: do not set -O to 2, see TODO
|
||||
CFLAGS = -Wall -Wextra -Werror -O1 -g
|
||||
LDFLAGS=
|
||||
OBJS = host.o client.o net.o udpxd.o
|
||||
OBJS = host.o client.o net.o udpxd.o log.o
|
||||
DST = udpxd
|
||||
PREFIX = /usr/local
|
||||
UID = root
|
||||
|
||||
@@ -7,7 +7,7 @@ This is the README file for the network program udpxd.
|
||||
udpxd can be used to forward or proxy UDP client traffic
|
||||
to another port on another system. It also supports binding
|
||||
to a specific ip address which will be used as the source
|
||||
for outgoing packets.
|
||||
for outgoing packets. It supports ip version 4 and 6.
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
8
TODO
8
TODO
@@ -1,12 +1,4 @@
|
||||
MUST:
|
||||
- support ipv6
|
||||
+ half done: not tested yet, just compiles.
|
||||
+ check for bind_h: must be same proto as dst_h (both v4 or both v6!)
|
||||
+ v6ize verbose outputs
|
||||
+ check for scopeid for dst_h (no route to host?), also the id
|
||||
must match for bind_h
|
||||
- daemonize
|
||||
- syslog
|
||||
- if compiled with -O2, gcc mangles the dst sockaddr_in pointers in some weird ways
|
||||
|
||||
MAYBE:
|
||||
|
||||
7
client.c
7
client.c
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include "client.h"
|
||||
#include "log.h"
|
||||
|
||||
void client_del(client_t *client) {
|
||||
HASH_DEL(clients, client);
|
||||
@@ -72,10 +73,8 @@ void client_clean(int asap) {
|
||||
client_iter(clients, current) {
|
||||
diff = now - current->lastseen;
|
||||
if(diff >= MAXAGE || asap) {
|
||||
if(VERBOSE) {
|
||||
fprintf(stderr, "closing socket %s:%d for client %s:%d (aged out after %d seconds)\n",
|
||||
current->src->ip, current->src->port, current->dst->ip, current->dst->port, MAXAGE);
|
||||
}
|
||||
verbose("closing socket %s:%d for client %s:%d (aged out after %d seconds)\n",
|
||||
current->src->ip, current->src->port, current->dst->ip, current->dst->port, MAXAGE);
|
||||
client_close(current);
|
||||
}
|
||||
}
|
||||
|
||||
1
client.h
1
client.h
@@ -54,6 +54,7 @@ typedef struct _client_t client_t;
|
||||
|
||||
extern client_t *clients;
|
||||
extern int VERBOSE;
|
||||
extern int FORKED;
|
||||
|
||||
/* wrapper for HASH_ITER */
|
||||
/** Iterate over the list of clients.
|
||||
|
||||
42
host.c
42
host.c
@@ -40,17 +40,24 @@ host_t *get_host(char *ip, int port, struct sockaddr_in *v4, struct sockaddr_in6
|
||||
|
||||
tmp->sin6_family = AF_INET6;
|
||||
tmp->sin6_port = htons( port );
|
||||
|
||||
|
||||
unsigned int scope = get_v6_scope(ip);
|
||||
if (is_linklocal((struct in6_addr*)&tmp->sin6_addr))
|
||||
tmp->sin6_scope_id = get_v6_scope(ip);
|
||||
tmp->sin6_scope_id = scope;
|
||||
else
|
||||
tmp->sin6_scope_id = 0;
|
||||
|
||||
host->is_v6 = 1;
|
||||
host->sock = (struct sockaddr*)tmp;
|
||||
host->size = sizeof(struct sockaddr_in6);
|
||||
host->ip = malloc(INET6_ADDRSTRLEN+1);
|
||||
memcpy(host->ip, ip, INET6_ADDRSTRLEN);
|
||||
if(tmp->sin6_scope_id != 0) {
|
||||
host->ip = malloc(INET6_ADDRSTRLEN + 9); /* plus [ % ] \0 , scope*/
|
||||
sprintf(host->ip, "[%s%%%d]", ip, scope);
|
||||
}
|
||||
else {
|
||||
host->ip = malloc(INET6_ADDRSTRLEN + 3); /* plus [ ] \0 */
|
||||
sprintf(host->ip, "[%s]", ip);
|
||||
}
|
||||
}
|
||||
else {
|
||||
struct sockaddr_in *tmp = malloc(sizeof(struct sockaddr_in));
|
||||
@@ -58,6 +65,7 @@ host_t *get_host(char *ip, int port, struct sockaddr_in *v4, struct sockaddr_in6
|
||||
tmp->sin_family = AF_INET;
|
||||
tmp->sin_addr.s_addr = inet_addr( ip );
|
||||
tmp->sin_port = htons( port );
|
||||
|
||||
host->sock = (struct sockaddr*)tmp;
|
||||
host->size = sizeof(struct sockaddr_in);
|
||||
host->ip = malloc(INET_ADDRSTRLEN+1);
|
||||
@@ -69,20 +77,31 @@ host_t *get_host(char *ip, int port, struct sockaddr_in *v4, struct sockaddr_in6
|
||||
memcpy(tmp, v4, sizeof(struct sockaddr_in));
|
||||
host->ip = malloc(INET_ADDRSTRLEN);
|
||||
inet_ntop(AF_INET, (struct in_addr *)&tmp->sin_addr, host->ip, INET_ADDRSTRLEN);
|
||||
|
||||
host->port = ntohs(tmp->sin_port);
|
||||
host->sock = (struct sockaddr*)tmp;
|
||||
host->size = sizeof(struct sockaddr_in);
|
||||
//fprintf(stderr, "%s sock: %p\n", host->ip, tmp);
|
||||
}
|
||||
else if(v6 != NULL) {
|
||||
struct sockaddr_in6 *tmp = malloc(sizeof(struct sockaddr_in6));
|
||||
memcpy(tmp, v6, sizeof(struct sockaddr_in6));
|
||||
host->ip = malloc(INET6_ADDRSTRLEN);
|
||||
inet_ntop(AF_INET, (struct in6_addr *)&tmp->sin6_addr, host->ip, INET6_ADDRSTRLEN);
|
||||
char *myip = malloc(INET6_ADDRSTRLEN);
|
||||
inet_ntop(AF_INET6, (struct in6_addr *)&tmp->sin6_addr, myip, INET6_ADDRSTRLEN);
|
||||
|
||||
host->port = ntohs(tmp->sin6_port);
|
||||
host->sock = (struct sockaddr*)tmp;
|
||||
host->is_v6 = 1;
|
||||
host->size = sizeof(struct sockaddr_in6);
|
||||
|
||||
if(tmp->sin6_scope_id != 0) {
|
||||
host->ip = malloc(INET6_ADDRSTRLEN + 9); /* plus [ % ] \0 , scope*/
|
||||
sprintf(host->ip, "[%s%%%d]", ip, tmp->sin6_scope_id);
|
||||
}
|
||||
else {
|
||||
host->ip = malloc(INET6_ADDRSTRLEN + 3); /* plus [ ] \0 */
|
||||
sprintf(host->ip, "[%s]", myip);
|
||||
}
|
||||
free(myip);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "call invalid!\n");
|
||||
@@ -92,8 +111,12 @@ host_t *get_host(char *ip, int port, struct sockaddr_in *v4, struct sockaddr_in6
|
||||
return host;
|
||||
}
|
||||
|
||||
char *is_v6(char *ip) {
|
||||
return strchr(ip, ':');
|
||||
int is_v6(char *ip) {
|
||||
char *IS = strchr(ip, ':');
|
||||
if(IS == NULL)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* via http://stackoverflow.com/questions/13504934/binding-sockets-to-ipv6-addresses
|
||||
@@ -126,7 +149,6 @@ unsigned get_v6_scope(const char *ip){
|
||||
}
|
||||
}
|
||||
freeifaddrs(addrs);
|
||||
fprintf(stderr, "scope: %d\n", scope);
|
||||
return scope;
|
||||
}
|
||||
|
||||
|
||||
2
host.h
2
host.h
@@ -49,7 +49,7 @@ typedef struct _host_t host_t;
|
||||
unsigned get_v6_scope(const char *ip);
|
||||
int is_linklocal(struct in6_addr *a);
|
||||
host_t *get_host(char *ip, int port, struct sockaddr_in *v4, struct sockaddr_in6 *v6);
|
||||
char *is_v6(char *ip);
|
||||
int is_v6(char *ip);
|
||||
void host_dump(host_t *host);
|
||||
void host_clean(host_t *host);
|
||||
|
||||
|
||||
41
log.c
Normal file
41
log.c
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
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 "log.h"
|
||||
|
||||
|
||||
|
||||
void verbose(const char * fmt, ...) {
|
||||
if(VERBOSE) {
|
||||
char *msg = NULL;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vasprintf(&msg, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if(FORKED) {
|
||||
syslog(LOG_INFO, msg);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
39
log.h
Normal file
39
log.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
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>.
|
||||
*/
|
||||
|
||||
#ifndef _HAVE_LOG_H
|
||||
#define _HAVE_LOG_H
|
||||
|
||||
#define _WITH_DPRINTF
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <syslog.h>
|
||||
|
||||
extern int VERBOSE;
|
||||
extern int FORKED;
|
||||
|
||||
void verbose(const char * fmt, ...);
|
||||
|
||||
#endif
|
||||
111
net.c
111
net.c
@@ -22,6 +22,7 @@
|
||||
#include "net.h"
|
||||
#include "client.h"
|
||||
#include "host.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
|
||||
@@ -87,10 +88,57 @@ int bindsocket( host_t *sock_h) {
|
||||
return fd;
|
||||
}
|
||||
|
||||
int start_listener (char *inip, char *inpt, char *srcip, char *dstip, char *dstpt) {
|
||||
host_t *listen_h = get_host(inip, atoi(inpt), NULL, NULL);
|
||||
host_t *dst_h = get_host(dstip, atoi(dstpt), NULL, NULL);
|
||||
host_t *bind_h = NULL;
|
||||
int start_listener (char *inip, char *inpt, char *srcip, char *dstip, char *dstpt, char *pidfile) {
|
||||
host_t *listen_h, *dst_h, *bind_h;
|
||||
|
||||
if(FORKED) {
|
||||
// fork
|
||||
pid_t pid, sid;
|
||||
FILE *fd;
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0) {
|
||||
perror("fork error");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pid > 0) {
|
||||
/* leave parent */
|
||||
if((fd = fopen(pidfile, "w")) == NULL) {
|
||||
perror("failed to write pidfile");
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
fprintf(fd, "%d\n", pid);
|
||||
fclose(fd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
sid = setsid();
|
||||
if (sid < 0) {
|
||||
perror("set sid error");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((chdir("/")) < 0) {
|
||||
perror("failed to chdir to /");
|
||||
return 1;
|
||||
}
|
||||
|
||||
umask(0);
|
||||
close(STDIN_FILENO);
|
||||
close(STDOUT_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
|
||||
openlog("udpxd", LOG_NOWAIT|LOG_PID, LOG_USER);
|
||||
}
|
||||
|
||||
listen_h = get_host(inip, atoi(inpt), NULL, NULL);
|
||||
dst_h = get_host(dstip, atoi(dstpt), NULL, NULL);
|
||||
bind_h = NULL;
|
||||
|
||||
if(srcip != NULL) {
|
||||
bind_h = get_host(srcip, 0, NULL, NULL);
|
||||
@@ -102,19 +150,18 @@ int start_listener (char *inip, char *inpt, char *srcip, char *dstip, char *dstp
|
||||
bind_h = get_host("0.0.0.0", 0, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
int listen = bindsocket(listen_h);
|
||||
|
||||
if(listen == -1)
|
||||
return 1;
|
||||
|
||||
if(VERBOSE) {
|
||||
fprintf(stderr, "Listening on %s:%s, forwarding to %s:%s",
|
||||
inip, inpt, dstip, dstpt);
|
||||
verbose("Listening on %s:%s, forwarding to %s:%s",
|
||||
listen_h->ip, inpt, dst_h->ip, dstpt);
|
||||
if(srcip != NULL)
|
||||
fprintf(stderr, ", binding to %s\n", srcip);
|
||||
verbose(", binding to %s\n", bind_h->ip);
|
||||
else
|
||||
fprintf(stderr, "\n");
|
||||
verbose("\n");
|
||||
}
|
||||
|
||||
main_loop(listen, listen_h, bind_h, dst_h);
|
||||
@@ -123,6 +170,8 @@ int start_listener (char *inip, char *inpt, char *srcip, char *dstip, char *dstp
|
||||
host_clean(listen_h);
|
||||
host_clean(dst_h);
|
||||
|
||||
closelog();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -148,21 +197,15 @@ void handle_inside(int inside, host_t *listen_h, host_t *bind_h, host_t *dst_h)
|
||||
|
||||
free(src);
|
||||
|
||||
if(VERBOSE) {
|
||||
fprintf(stderr, "New incomming request from %s:%d with %d bytes\n",
|
||||
src_h->ip, src_h->port, len);
|
||||
}
|
||||
|
||||
if(len > 0) {
|
||||
/* do we know it ? */
|
||||
client = client_find_src(src_h);
|
||||
if(client != NULL) {
|
||||
/* yes, we know it, send req out via existing bind socket */
|
||||
if(VERBOSE) {
|
||||
fprintf(stderr, "Client %s:%d is known, forwarding data to %s:%d ",
|
||||
src_h->ip, src_h->port, dst_h->ip, dst_h->port);
|
||||
|
||||
}
|
||||
verbose("Client %s:%d is known, forwarding %d bytes to %s:%d ",
|
||||
src_h->ip, src_h->port, len, dst_h->ip, dst_h->port);
|
||||
verb_prbind(bind_h);
|
||||
|
||||
if(sendto(client->socket, buffer, len, 0, (struct sockaddr*)dst_h->sock, dst_h->size) < 0) {
|
||||
fprintf(stderr, "unable to forward to %s:%d\n", dst_h->ip, dst_h->port);
|
||||
perror(NULL);
|
||||
@@ -173,11 +216,9 @@ void handle_inside(int inside, host_t *listen_h, host_t *bind_h, host_t *dst_h)
|
||||
}
|
||||
else {
|
||||
/* unknown client, open new out socket */
|
||||
if(VERBOSE) {
|
||||
fprintf(stderr, "Client %s:%d is unknown, forwarding data to %s:%d ",
|
||||
src_h->ip, src_h->port, dst_h->ip, dst_h->port);
|
||||
|
||||
}
|
||||
verbose("Client %s:%d is unknown, forwarding %d bytes to %s:%d ",
|
||||
src_h->ip, src_h->port, len, dst_h->ip, dst_h->port);
|
||||
verb_prbind(bind_h);
|
||||
|
||||
output = bindsocket(bind_h);
|
||||
|
||||
@@ -205,20 +246,9 @@ void handle_inside(int inside, host_t *listen_h, host_t *bind_h, host_t *dst_h)
|
||||
}
|
||||
|
||||
client_add(client);
|
||||
|
||||
if(VERBOSE) {
|
||||
if(strcmp(bind_h->ip, "0.0.0.0") != 0 || strcmp(bind_h->ip, "::0") != 0) {
|
||||
fprintf(stderr, "from %s:%d\n", ret_h->ip, ret_h->port);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: free? */
|
||||
}
|
||||
|
||||
/* handle answer from the outside */
|
||||
@@ -310,3 +340,14 @@ void int_handler(int sig) {
|
||||
signal(sig, SIG_IGN);
|
||||
longjmp(JumpBuffer, 1);
|
||||
}
|
||||
|
||||
void verb_prbind (host_t *bind_h) {
|
||||
if(VERBOSE) {
|
||||
if(strcmp(bind_h->ip, "0.0.0.0") != 0 || strcmp(bind_h->ip, "[::0]") != 0) {
|
||||
verbose("from %s:%d\n", bind_h->ip, bind_h->port);
|
||||
}
|
||||
else {
|
||||
verbose("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
7
net.h
7
net.h
@@ -30,7 +30,9 @@
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
@@ -44,6 +46,7 @@
|
||||
|
||||
extern client_t *clients;
|
||||
extern int VERBOSE;
|
||||
extern int FORKED;
|
||||
|
||||
|
||||
|
||||
@@ -51,13 +54,13 @@ void handle_inside(int inside, host_t *listen_h, host_t *bind_h, host_t *dst_h);
|
||||
void handle_outside(int inside, int outside, host_t *outside_h);
|
||||
|
||||
int main_loop(int listensocket, host_t *listen_h, host_t *bind_h, host_t *dst_h);
|
||||
int start_listener (char *inip, char *inpt, char *srcip, char *dstip, char *dstpt);
|
||||
int start_listener (char *inip, char *inpt, char *srcip, char *dstip, char *dstpt, char *pidfile);
|
||||
|
||||
int fill_set(fd_set *fds);
|
||||
int get_sender(fd_set *fds);
|
||||
int bindsocket( host_t *sock_h);
|
||||
void int_handler(int sig);
|
||||
|
||||
void verb_prbind (host_t *bind_h);
|
||||
|
||||
#define _IS_LINK_LOCAL(a) do { IN6_IS_ADDR_LINKLOCAL(a); } while(0)
|
||||
|
||||
|
||||
43
udpxd.c
43
udpxd.c
@@ -26,6 +26,7 @@
|
||||
/* global client list */
|
||||
client_t *clients = NULL;
|
||||
int VERBOSE = 0;
|
||||
int FORKED = 1;
|
||||
|
||||
/* parse ip:port */
|
||||
int parse_ip(char *src, char *ip, char *pt) {
|
||||
@@ -90,6 +91,8 @@ int parse_ip(char *src, char *ip, char *pt) {
|
||||
int main ( int argc, char* argv[] ) {
|
||||
int opt, err;
|
||||
char *inip, *inpt, *srcip, *dstip, *dstpt;
|
||||
char pidfile[MAX_BUFFER_SIZE];
|
||||
|
||||
err = 0;
|
||||
|
||||
static struct option longopts[] = {
|
||||
@@ -98,7 +101,9 @@ int main ( int argc, char* argv[] ) {
|
||||
{ "dest", required_argument, NULL, 'd' },
|
||||
{ "version", no_argument, NULL, 'v' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "verbose", no_argument, NULL, 'V' }
|
||||
{ "verbose", no_argument, NULL, 'V' },
|
||||
{ "foreground",no_argument, NULL, 'f' },
|
||||
{ "pidfile", required_argument, NULL, 'p' },
|
||||
};
|
||||
|
||||
if( argc < 2 ) {
|
||||
@@ -107,13 +112,17 @@ int main ( int argc, char* argv[] ) {
|
||||
}
|
||||
|
||||
srcip = dstip = inip = dstpt = inpt = NULL;
|
||||
strncpy(pidfile, "/var/run/udpxd.pid", 19);
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "l:b:d:vVh?", longopts, NULL)) != -1) {
|
||||
while ((opt = getopt_long(argc, argv, "l:b:d:vfVh?", longopts, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 'v':
|
||||
fprintf(stderr, "This is %s version %s\n", argv[0], UDPXD_VERSION);
|
||||
return 1;
|
||||
break;
|
||||
case 'f':
|
||||
FORKED = 0;
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
usage();
|
||||
@@ -146,6 +155,9 @@ int main ( int argc, char* argv[] ) {
|
||||
srcip = malloc(INET6_ADDRSTRLEN+1);
|
||||
strncpy(srcip, optarg, strlen(optarg));
|
||||
break;
|
||||
case 'p':
|
||||
strncpy(pidfile, optarg, strlen(optarg));
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
return 1;
|
||||
@@ -165,12 +177,17 @@ int main ( int argc, char* argv[] ) {
|
||||
err = 1;
|
||||
}
|
||||
|
||||
if(srcip != NULL) {
|
||||
if(is_v6(srcip) != is_v6(dstip)) {
|
||||
fprintf(stderr, "Bind ip and destination ip must be both v4 or v6 and can't be mixed!\n");
|
||||
err = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(! err) {
|
||||
err = start_listener (inip, inpt, srcip, dstip, dstpt);
|
||||
err = start_listener (inip, inpt, srcip, dstip, dstpt, pidfile);
|
||||
}
|
||||
|
||||
/* FIXME: add sighandler */
|
||||
|
||||
if(srcip != NULL)
|
||||
free(srcip);
|
||||
if(dstip != NULL)
|
||||
@@ -187,14 +204,16 @@ int main ( int argc, char* argv[] ) {
|
||||
|
||||
void usage() {
|
||||
fprintf(stderr,
|
||||
"Usage: udpxd [-lbdvhV]\n\n"
|
||||
"Usage: udpxd [-lbdfpvhV]\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"
|
||||
"--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"
|
||||
"--foreground -f don't fork into background\n"
|
||||
"--pidfile -p <file> pidfile, default: /var/run/udpxd.pid\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
|
||||
);
|
||||
|
||||
2
udpxd.h
2
udpxd.h
@@ -36,7 +36,7 @@
|
||||
#include <sys/fcntl.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define UDPXD_VERSION "0.0.1"
|
||||
#define UDPXD_VERSION "0.0.2"
|
||||
|
||||
|
||||
void usage();
|
||||
|
||||
57
udpxd.pod
57
udpxd.pod
@@ -4,15 +4,17 @@ udpxd - A general purpose UDP relay/port forwarder/proxy
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
Usage: udpxd [-lbdvhV]
|
||||
|
||||
Usage: udpxd [-lbdfpvhV]
|
||||
|
||||
Options:
|
||||
--listen -l <ip:port> listen for incoming requests
|
||||
--bind -b <ip> bind ip used for outgoing requests
|
||||
--dest -d <ip:port> destination to forward requests to
|
||||
--help -h -? print help message
|
||||
--version -v print program version
|
||||
--verbose -V enable verbose logging
|
||||
--listen -l <ip:port> listen for incoming requests
|
||||
--bind -b <ip> bind ip used for outgoing requests
|
||||
--dest -d <ip:port> destination to forward requests to
|
||||
--foreground -f don't fork into background
|
||||
--pidfile -p <file> pidfile, default: /var/run/udpxd.pid
|
||||
--help -h -? print help message
|
||||
--version -v print program version
|
||||
--verbose -V enable verbose logging
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
@@ -39,6 +41,32 @@ with B<-b>.
|
||||
|
||||
The options B<-l> and B<-d> are mandatory.
|
||||
|
||||
If the option B<-f> has not been specified, udpxd forks into
|
||||
the background and becomes a daemon. It writes it pidfile to
|
||||
C</var/run/udpxd.pid>, which can be changed with the B<-p>
|
||||
option.
|
||||
|
||||
B<Caution: udpxd does not drop its privileges. If started as
|
||||
root, it will continue to run as root. This may change in the
|
||||
future.>
|
||||
|
||||
Udpxd supports ip version 4 and 6, it doesn't support hostnames,
|
||||
-l, -d and -b must be ip addresses. In order to specify an ipv6
|
||||
address and a port, use:
|
||||
|
||||
-l [::1]:53
|
||||
|
||||
that is, surround the ipv6 address with brackets.
|
||||
|
||||
Port forwardings can be mixed:
|
||||
|
||||
listen | forward to
|
||||
-------+-----------
|
||||
ipv4 | ipv4
|
||||
ipv6 | ipv4
|
||||
ipv4 | ipv6
|
||||
ipv6 | ipv6
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
Let's say you operate a multihomed unix system named 'foo'
|
||||
@@ -82,9 +110,20 @@ In this case for the client everything looks as before, but the
|
||||
ntp server on the other end will see ntp requests coming from
|
||||
192.168.1.45 instead.
|
||||
|
||||
Here we listen on the ip v6 loopback address and forward traffic
|
||||
to another ip v6 destination address:
|
||||
|
||||
udpxd -l [::1]:53 -d [2001:4860:4860::8888]:53
|
||||
|
||||
Or, we could listen on an ip v4 address and forward to an ip v6
|
||||
address:
|
||||
|
||||
udpxd -l 192.168.1.1:53 -d [2001:4860:4860::8888]:53
|
||||
|
||||
=head1 FILES
|
||||
|
||||
udpxd currently does not write or open any files.
|
||||
B</var/run/udpxd.pid>: created if running in daemon mode (-f not
|
||||
specified).
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
|
||||
Reference in New Issue
Block a user