mirror of
https://codeberg.org/scip/udpxd.git
synced 2025-12-16 19:40:58 +01:00
forgot
This commit is contained in:
2
Makefile
2
Makefile
@@ -21,7 +21,7 @@
|
|||||||
# warning: do not set -O to 2, see TODO
|
# warning: do not set -O to 2, see TODO
|
||||||
CFLAGS = -Wall -Wextra -Werror -O1 -g
|
CFLAGS = -Wall -Wextra -Werror -O1 -g
|
||||||
LDFLAGS=
|
LDFLAGS=
|
||||||
OBJS = client.o net.o udpxd.o
|
OBJS = host.o client.o net.o udpxd.o
|
||||||
DST = udpxd
|
DST = udpxd
|
||||||
PREFIX = /usr/local
|
PREFIX = /usr/local
|
||||||
UID = root
|
UID = root
|
||||||
|
|||||||
10
client.c
10
client.c
@@ -35,10 +35,10 @@ client_t *client_find_fd(int fd) {
|
|||||||
return client; /* maybe NULL! */
|
return client; /* maybe NULL! */
|
||||||
}
|
}
|
||||||
|
|
||||||
client_t *client_find_src(struct sockaddr_in *src) {
|
client_t *client_find_src(host_t *src) {
|
||||||
client_t *current = NULL;
|
client_t *current = NULL;
|
||||||
client_iter(clients, current) {
|
client_iter(clients, current) {
|
||||||
if (current->src == src)
|
if(strcmp(current->src->ip, src->ip) == 0 && current->src->port == src->port)
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -48,7 +48,7 @@ void client_seen(client_t *client) {
|
|||||||
client->lastseen = (long)time(0);
|
client->lastseen = (long)time(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
client_t *client_new(int fd, struct sockaddr_in *src, struct sockaddr_in *dst) {
|
client_t *client_new(int fd, host_t *src, host_t *dst) {
|
||||||
client_t *client = malloc(sizeof(client_t));
|
client_t *client = malloc(sizeof(client_t));
|
||||||
client->socket = fd;
|
client->socket = fd;
|
||||||
client->src = src;
|
client->src = src;
|
||||||
@@ -73,10 +73,8 @@ void client_clean() {
|
|||||||
diff = now - current->lastseen;
|
diff = now - current->lastseen;
|
||||||
if(diff >= MAXAGE) {
|
if(diff >= MAXAGE) {
|
||||||
if(VERBOSE) {
|
if(VERBOSE) {
|
||||||
char *srcip = inet_ntoa(current->src->sin_addr);
|
|
||||||
char *bindip = inet_ntoa(current->dst->sin_addr);
|
|
||||||
fprintf(stderr, "closing socket %s:%d for client %s:%d (aged out after %d seconds)\n",
|
fprintf(stderr, "closing socket %s:%d for client %s:%d (aged out after %d seconds)\n",
|
||||||
srcip, ntohs(current->src->sin_port), bindip, ntohs(current->dst->sin_port), MAXAGE);
|
current->src->ip, current->src->port, current->dst->ip, current->dst->port, MAXAGE);
|
||||||
}
|
}
|
||||||
client_close(current);
|
client_close(current);
|
||||||
}
|
}
|
||||||
|
|||||||
10
client.h
10
client.h
@@ -39,14 +39,16 @@ typedef uint8_t byte;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "uthash.h"
|
#include "uthash.h"
|
||||||
|
#include "host.h"
|
||||||
|
|
||||||
#define MAXAGE 3600 /* seconds after which to close outgoing sockets and forget client src */
|
#define MAXAGE 3600 /* seconds after which to close outgoing sockets and forget client src */
|
||||||
|
|
||||||
struct _client_t {
|
struct _client_t {
|
||||||
int socket; /* bind socket for outgoing traffic */
|
int socket; /* bind socket for outgoing traffic */
|
||||||
struct sockaddr_in *src; /* client src (ip+port) from incoming socket */
|
host_t *src; /* client src (ip+port) from incoming socket */
|
||||||
struct sockaddr_in *dst; /* client dst (ip+port) to outgoing socket */
|
host_t *dst; /* client dst (ip+port) to outgoing socket */
|
||||||
uint64_t lastseen; /* when did we recv last time from it */
|
uint64_t lastseen; /* when did we recv last time from it */
|
||||||
|
size_t size; /* sockaddr size */
|
||||||
UT_hash_handle hh;
|
UT_hash_handle hh;
|
||||||
};
|
};
|
||||||
typedef struct _client_t client_t;
|
typedef struct _client_t client_t;
|
||||||
@@ -78,8 +80,8 @@ void client_close(client_t *client);
|
|||||||
void client_clean();
|
void client_clean();
|
||||||
|
|
||||||
client_t *client_find_fd(int fd);
|
client_t *client_find_fd(int fd);
|
||||||
client_t *client_find_src(struct sockaddr_in *src);
|
client_t *client_find_src(host_t *src);
|
||||||
client_t *client_new(int fd, struct sockaddr_in *src, struct sockaddr_in *dst);
|
client_t *client_new(int fd, host_t *src, host_t *dst);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
188
net.c
188
net.c
@@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
#include "host.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char *ntoa(struct sockaddr_in *src) {
|
char *ntoa(struct sockaddr_in *src) {
|
||||||
@@ -29,6 +31,7 @@ char *ntoa(struct sockaddr_in *src) {
|
|||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* called each time when the loop restarts to feed select() correctly */
|
/* called each time when the loop restarts to feed select() correctly */
|
||||||
int fill_set(fd_set *fds) {
|
int fill_set(fd_set *fds) {
|
||||||
int max = 0;
|
int max = 0;
|
||||||
@@ -58,57 +61,106 @@ int get_sender(fd_set *fds) {
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* bind to a socket, either for listen() or for outgoing src ip binding */
|
/* bind to a socket, either for listen() or for outgoing src ip binding */
|
||||||
int bindsocket( char* ip, int port ) {
|
int bindsocket( host_t *sock_h) {
|
||||||
int fd;
|
int fd;
|
||||||
struct sockaddr_in addr;
|
int err = 0;
|
||||||
|
|
||||||
addr.sin_family = AF_INET;
|
if(sock_h->is_v6) {
|
||||||
addr.sin_addr.s_addr = inet_addr( ip );
|
fd = socket( PF_INET6, SOCK_DGRAM, IPPROTO_UDP );
|
||||||
addr.sin_port = htons( port );
|
}
|
||||||
|
else {
|
||||||
|
fd = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
|
||||||
|
}
|
||||||
|
|
||||||
fd = socket( PF_INET, SOCK_DGRAM, IPPROTO_IP );
|
if( -1 == bind( fd, (struct sockaddr*)sock_h->sock, sock_h->size ) ) {
|
||||||
if( -1 == bind( fd, (struct sockaddr*)&addr, sizeof( addr ) ) ) {
|
err = 1;
|
||||||
fprintf( stderr, "Cannot bind address (%s:%d)\n", ip, port );
|
}
|
||||||
exit( 1 );
|
|
||||||
|
if(err) {
|
||||||
|
fprintf( stderr, "Cannot bind address ([%s]:%d)\n", sock_h->ip, sock_h->port );
|
||||||
|
perror(NULL);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle new or known incoming requests */
|
int start_listener (char *inip, char *inpt, char *srcip, char *dstip, char *dstpt) {
|
||||||
void handle_inside(int inside, char *bindip, struct sockaddr_in *dst) {
|
host_t *listen_h = get_host(inip, atoi(inpt), NULL, NULL);
|
||||||
int len;
|
host_t *dst_h = get_host(dstip, atoi(dstpt), NULL, NULL);
|
||||||
unsigned char buffer[MAX_BUFFER_SIZE];
|
host_t *bind_h = NULL;
|
||||||
struct sockaddr_in *src;
|
|
||||||
client_t *client;
|
if(srcip != NULL) {
|
||||||
int output;
|
bind_h = get_host(srcip, 0, NULL, NULL);
|
||||||
char *srcip;
|
}
|
||||||
char *dstip = ntoa(dst);
|
else {
|
||||||
size_t size = sizeof(struct sockaddr_in);
|
if(dst_h->is_v6)
|
||||||
src = malloc(size);
|
bind_h = get_host("::0", 0, NULL, NULL);
|
||||||
|
else
|
||||||
len = recvfrom( inside, buffer, sizeof( buffer ), 0, (struct sockaddr*)src, (socklen_t *)&size );
|
bind_h = get_host("0.0.0.0", 0, NULL, NULL);
|
||||||
srcip = ntoa(src);
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
if(srcip != NULL)
|
||||||
|
fprintf(stderr, ", binding to %s\n", srcip);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
main_loop(listen, listen_h, bind_h, dst_h);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* handle new or known incoming requests
|
||||||
|
FIXME: check client handling:
|
||||||
|
http://long.ccaba.upc.es/long/045Guidelines/eva/ipv6.html#daytimeServer6
|
||||||
|
*/
|
||||||
|
void handle_inside(int inside, host_t *listen_h, host_t *bind_h, host_t *dst_h) {
|
||||||
|
int len;
|
||||||
|
unsigned char buffer[MAX_BUFFER_SIZE];
|
||||||
|
void *src;
|
||||||
|
client_t *client;
|
||||||
|
host_t *src_h;
|
||||||
|
int output;
|
||||||
|
size_t size = listen_h->size;
|
||||||
|
|
||||||
|
src = malloc(size);
|
||||||
|
|
||||||
|
len = recvfrom( inside, buffer, sizeof( buffer ), 0,
|
||||||
|
(struct sockaddr*)src, (socklen_t *)&size );
|
||||||
|
|
||||||
|
if(listen_h->is_v6)
|
||||||
|
src_h = get_host(NULL, 0, NULL, (struct sockaddr_in6 *)src);
|
||||||
|
else
|
||||||
|
src_h = get_host(NULL, 0, (struct sockaddr_in *)src, NULL);
|
||||||
|
|
||||||
if(VERBOSE) {
|
if(VERBOSE) {
|
||||||
char *srcip = ntoa(src);
|
|
||||||
fprintf(stderr, "New incomming request from %s:%d with %d bytes\n",
|
fprintf(stderr, "New incomming request from %s:%d with %d bytes\n",
|
||||||
srcip, ntohs(src->sin_port), len);
|
src_h->ip, src_h->port, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(len > 0) {
|
if(len > 0) {
|
||||||
/* do we know it ? */
|
/* do we know it ? */
|
||||||
client = client_find_src(src);
|
client = client_find_src(src_h);
|
||||||
if(client != NULL) {
|
if(client != NULL) {
|
||||||
/* yes, we know it, send req out via existing bind socket */
|
/* yes, we know it, send req out via existing bind socket */
|
||||||
if(VERBOSE) {
|
if(VERBOSE) {
|
||||||
fprintf(stderr, "Client %s:%d is known, forwarding data to %s:%d\n",
|
fprintf(stderr, "Client %s:%d is known, forwarding data to %s:%d\n",
|
||||||
srcip, ntohs(src->sin_port), dstip, ntohs(dst->sin_port));
|
src_h->ip, src_h->port, dst_h->ip, dst_h->port);
|
||||||
|
|
||||||
}
|
}
|
||||||
if(sendto(client->socket, buffer, len, 0, (struct sockaddr*)dst, size) < 0) {
|
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", dstip, ntohs(dst->sin_port));
|
fprintf(stderr, "unable to forward to %s:%d\n", dst_h->ip, dst_h->port);
|
||||||
perror(NULL);
|
perror(NULL);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -119,29 +171,38 @@ void handle_inside(int inside, char *bindip, struct sockaddr_in *dst) {
|
|||||||
/* unknown client, open new out socket */
|
/* unknown client, open new out socket */
|
||||||
if(VERBOSE) {
|
if(VERBOSE) {
|
||||||
fprintf(stderr, "Client %s:%d is unknown, forwarding data to %s:%d ",
|
fprintf(stderr, "Client %s:%d is unknown, forwarding data to %s:%d ",
|
||||||
srcip, ntohs(src->sin_port), dstip, ntohs(dst->sin_port));
|
src_h->ip, src_h->port, dst_h->ip, dst_h->port);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bindip == NULL)
|
output = bindsocket(bind_h);
|
||||||
output = bindsocket("0.0.0.0", 0);
|
|
||||||
else
|
|
||||||
output = bindsocket(bindip, 0);
|
|
||||||
|
|
||||||
/* send req out */
|
/* send req out */
|
||||||
if(sendto(output, buffer, len, 0, (struct sockaddr*)dst, size) < 0) {
|
if(sendto(output, buffer, len, 0, (struct sockaddr*)dst_h->sock, dst_h->size) < 0) {
|
||||||
fprintf(stderr, "unable to forward to %s:%d\n", dstip, ntohs(dst->sin_port));
|
fprintf(stderr, "unable to forward to %s:%d\n", dst_h->ip, dst_h->port);
|
||||||
perror(NULL);
|
perror(NULL);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
struct sockaddr_in *ret = malloc(size);
|
size = listen_h->size;
|
||||||
getsockname(output, (struct sockaddr*)ret, (socklen_t *)&size);
|
host_t *ret_h;
|
||||||
client = client_new(output, src, ret);
|
if(listen_h->is_v6) {
|
||||||
|
struct sockaddr_in6 *ret = malloc(size);
|
||||||
|
getsockname(output, (struct sockaddr*)ret, (socklen_t *)&size);
|
||||||
|
ret_h = get_host(NULL, 0, NULL, ret);
|
||||||
|
client = client_new(output, src_h, ret_h);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
struct sockaddr_in *ret = malloc(size);
|
||||||
|
getsockname(output, (struct sockaddr*)ret, (socklen_t *)&size);
|
||||||
|
ret_h = get_host(NULL, 0, ret, NULL);
|
||||||
|
client = client_new(output, src_h, ret_h);
|
||||||
|
}
|
||||||
|
|
||||||
client_add(client);
|
client_add(client);
|
||||||
|
|
||||||
if(VERBOSE) {
|
if(VERBOSE) {
|
||||||
if(bindip != NULL) {
|
if(strcmp(bind_h->ip, "0.0.0.0") != 0 || strcmp(bind_h->ip, "::0") != 0) {
|
||||||
char *bindip = ntoa(ret);
|
fprintf(stderr, "from %s:%d\n", ret_h->ip, ret_h->port);
|
||||||
fprintf(stderr, "from %s:%d\n", bindip, ntohs(ret->sin_port));
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
@@ -151,18 +212,17 @@ void handle_inside(int inside, char *bindip, struct sockaddr_in *dst) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(dstip);
|
/* FIXME: free? */
|
||||||
free(srcip);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle answer from the outside */
|
/* handle answer from the outside */
|
||||||
void handle_outside(int inside, int outside) {
|
void handle_outside(int inside, int outside, host_t *outside_h) {
|
||||||
int len;
|
int len;
|
||||||
unsigned char buffer[MAX_BUFFER_SIZE];
|
unsigned char buffer[MAX_BUFFER_SIZE];
|
||||||
struct sockaddr_in *src;
|
void *src;
|
||||||
client_t *client;
|
client_t *client;
|
||||||
|
|
||||||
size_t size = sizeof(struct sockaddr_in);
|
size_t size = outside_h->size;
|
||||||
src = malloc(size);
|
src = malloc(size);
|
||||||
|
|
||||||
len = recvfrom( outside, buffer, sizeof( buffer ), 0, (struct sockaddr*)src, (socklen_t *)&size );
|
len = recvfrom( outside, buffer, sizeof( buffer ), 0, (struct sockaddr*)src, (socklen_t *)&size );
|
||||||
@@ -172,7 +232,7 @@ void handle_outside(int inside, int outside) {
|
|||||||
client = client_find_fd(outside);
|
client = client_find_fd(outside);
|
||||||
if(client != NULL) {
|
if(client != NULL) {
|
||||||
/* yes, we know it */
|
/* yes, we know it */
|
||||||
if(sendto(inside, buffer, len, 0, (struct sockaddr*)client->src, size) < 0) {
|
if(sendto(inside, buffer, len, 0, (struct sockaddr*)client->src, client->size) < 0) {
|
||||||
perror("unable to send back to client"); /* FIXME: add src+port */
|
perror("unable to send back to client"); /* FIXME: add src+port */
|
||||||
client_close(client);
|
client_close(client);
|
||||||
}
|
}
|
||||||
@@ -180,3 +240,33 @@ void handle_outside(int inside, int outside) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* runs forever, handles incoming requests on the inside and answers on the outside */
|
||||||
|
int main_loop(int listensocket, host_t *listen_h, host_t *bind_h, host_t *dst_h) {
|
||||||
|
int max, sender;
|
||||||
|
fd_set fds;
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
max = fill_set(&fds);
|
||||||
|
|
||||||
|
FD_SET(listensocket, &fds);
|
||||||
|
if (listensocket > max)
|
||||||
|
max = listensocket;
|
||||||
|
|
||||||
|
select(max + 1, &fds, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
if (FD_ISSET(listensocket, &fds)) {
|
||||||
|
/* incoming client on the inside, get src, bind output fd, add to list
|
||||||
|
if known, otherwise just handle it */
|
||||||
|
handle_inside(listensocket, listen_h, bind_h, dst_h);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* remote answer came in on an output fd, proxy back to the inside */
|
||||||
|
sender = get_sender(&fds);
|
||||||
|
handle_outside(listensocket, sender, dst_h);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close old outputs, if any */
|
||||||
|
client_clean();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
17
net.h
17
net.h
@@ -35,6 +35,7 @@
|
|||||||
#include <sys/fcntl.h>
|
#include <sys/fcntl.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
|
||||||
#define MAX_BUFFER_SIZE 65535
|
#define MAX_BUFFER_SIZE 65535
|
||||||
@@ -42,10 +43,20 @@
|
|||||||
extern client_t *clients;
|
extern client_t *clients;
|
||||||
extern int VERBOSE;
|
extern int VERBOSE;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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 fill_set(fd_set *fds);
|
int fill_set(fd_set *fds);
|
||||||
int get_sender(fd_set *fds);
|
int get_sender(fd_set *fds);
|
||||||
int bindsocket( char* ip, int port );
|
int bindsocket( host_t *sock_h);
|
||||||
void handle_inside(int inside, char *bindip, struct sockaddr_in *dst);
|
|
||||||
void handle_outside(int inside, int outside);
|
|
||||||
|
|
||||||
|
#define _IS_LINK_LOCAL(a) do { IN6_IS_ADDR_LINKLOCAL(a); } while(0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
172
udpxd.c
172
udpxd.c
@@ -27,43 +27,70 @@
|
|||||||
client_t *clients = NULL;
|
client_t *clients = NULL;
|
||||||
int VERBOSE = 0;
|
int VERBOSE = 0;
|
||||||
|
|
||||||
/* runs forever, handles incoming requests on the inside and answers on the outside */
|
/* parse ip:port */
|
||||||
int main_loop(int listensocket, char *bindip, struct sockaddr_in *dst) {
|
int parse_ip(char *src, char *ip, char *pt) {
|
||||||
int max, sender;
|
char *ptr = NULL;
|
||||||
fd_set fds;
|
|
||||||
|
|
||||||
for(;;) {
|
if (strchr(optarg, '[')) {
|
||||||
FD_ZERO(&fds);
|
/* v6 */
|
||||||
max = fill_set(&fds);
|
ptr = strtok(&src[1], "]");
|
||||||
|
|
||||||
FD_SET(listensocket, &fds);
|
if(strlen(ptr) > INET6_ADDRSTRLEN) {
|
||||||
if (listensocket > max)
|
fprintf(stderr, "ip v6 address is too long!\n");
|
||||||
max = listensocket;
|
return 1;
|
||||||
|
|
||||||
select(max + 1, &fds, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
if (FD_ISSET(listensocket, &fds)) {
|
|
||||||
/* incoming client on the inside, get src, bind output fd, add to list
|
|
||||||
if known, otherwise just handle it */
|
|
||||||
handle_inside(listensocket, bindip, dst);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* remote answer came in on an output fd, proxy back to the inside */
|
|
||||||
sender = get_sender(&fds);
|
|
||||||
handle_outside(listensocket, sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* close old outputs, if any */
|
|
||||||
client_clean();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 main ( int argc, char* argv[] ) {
|
||||||
int listen, opt;
|
int opt, err;
|
||||||
char *inip, *inpt, *srcip, *dstip, *dstpt;
|
char *inip, *inpt, *srcip, *dstip, *dstpt;
|
||||||
struct sockaddr_in *dst;
|
err = 0;
|
||||||
char colon[] = ":";
|
|
||||||
|
|
||||||
static struct option longopts[] = {
|
static struct option longopts[] = {
|
||||||
{ "listen", required_argument, NULL, 'l' },
|
{ "listen", required_argument, NULL, 'l' },
|
||||||
@@ -80,7 +107,7 @@ int main ( int argc, char* argv[] ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
srcip = dstip = inip = dstpt = inpt = NULL;
|
srcip = dstip = inip = dstpt = inpt = NULL;
|
||||||
|
|
||||||
while ((opt = getopt_long(argc, argv, "l:b:d:vVh?", longopts, NULL)) != -1) {
|
while ((opt = getopt_long(argc, argv, "l:b:d:vVh?", longopts, NULL)) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'v':
|
case 'v':
|
||||||
@@ -96,49 +123,27 @@ int main ( int argc, char* argv[] ) {
|
|||||||
VERBOSE = 1;
|
VERBOSE = 1;
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
if(strchr(optarg, ':')) {
|
inip = malloc(INET6_ADDRSTRLEN+1);
|
||||||
char *ptr = NULL;
|
inpt = malloc(6);
|
||||||
ptr = strtok(optarg, colon);
|
if (parse_ip(optarg, inip, inpt) != 0) {
|
||||||
inip = malloc( strlen(ptr)+1);
|
|
||||||
strncpy(inip, ptr, strlen(ptr)+1);
|
|
||||||
ptr = strtok(NULL, colon);
|
|
||||||
if(ptr != NULL) {
|
|
||||||
inpt = malloc( strlen(ptr)+1);
|
|
||||||
strncpy(inpt, ptr, strlen(ptr)+1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fprintf(stderr, "Listen port for parameter -l is missing!\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fprintf(stderr, "Parameter -l has the format <ip-address:port>!\n");
|
fprintf(stderr, "Parameter -l has the format <ip-address:port>!\n");
|
||||||
return 0;
|
err = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
if(strchr(optarg, ':')) {
|
dstip = malloc(INET6_ADDRSTRLEN+1);
|
||||||
char *ptr = NULL;
|
dstpt = malloc(6);
|
||||||
ptr = strtok(optarg, colon);
|
if (parse_ip(optarg, dstip, dstpt) != 0) {
|
||||||
dstip = malloc( strlen(ptr)+1);
|
|
||||||
strncpy(dstip, ptr, strlen(ptr)+1);
|
|
||||||
ptr = strtok(NULL, colon);
|
|
||||||
if(ptr != NULL) {
|
|
||||||
dstpt = malloc( strlen(ptr)+1);
|
|
||||||
strncpy(dstpt, ptr, strlen(ptr)+1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fprintf(stderr, "Destination port for parameter -d is missing!\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fprintf(stderr, "Parameter -d has the format <ip-address:port>!\n");
|
fprintf(stderr, "Parameter -d has the format <ip-address:port>!\n");
|
||||||
return 0;
|
err = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
srcip = malloc(strlen(optarg));
|
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));
|
strncpy(srcip, optarg, strlen(optarg));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -151,36 +156,33 @@ int main ( int argc, char* argv[] ) {
|
|||||||
if(inip == NULL) {
|
if(inip == NULL) {
|
||||||
fprintf(stderr, "-l parameter is required!\n");
|
fprintf(stderr, "-l parameter is required!\n");
|
||||||
usage();
|
usage();
|
||||||
return 1;
|
err = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dstip == NULL) {
|
if(dstip == NULL) {
|
||||||
fprintf(stderr, "-d parameter is required!\n");
|
fprintf(stderr, "-d parameter is required!\n");
|
||||||
usage();
|
usage();
|
||||||
return 1;
|
err = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
listen = bindsocket(inip, atoi(inpt));
|
if(! err) {
|
||||||
|
err = start_listener (inip, inpt, srcip, dstip, dstpt);
|
||||||
dst = malloc(sizeof(struct sockaddr_in));
|
|
||||||
dst->sin_family = AF_INET;
|
|
||||||
dst->sin_addr.s_addr = inet_addr( dstip );
|
|
||||||
dst->sin_port = htons( atoi( dstpt ) );
|
|
||||||
|
|
||||||
if(VERBOSE) {
|
|
||||||
fprintf(stderr, "Listening on %s:%s, forwarding to %s:%s",
|
|
||||||
inip, inpt, dstip, dstpt);
|
|
||||||
if(srcip != NULL)
|
|
||||||
fprintf(stderr, ", binding to %s\n", srcip);
|
|
||||||
else
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main_loop(listen, srcip, dst);
|
/* FIXME: add sighandler */
|
||||||
|
|
||||||
/* FIXME: add sighandler, clean up mem */
|
if(srcip != NULL)
|
||||||
|
free(srcip);
|
||||||
return 0;
|
if(dstip != NULL)
|
||||||
|
free(dstip);
|
||||||
|
if(inip != NULL)
|
||||||
|
free(inip);
|
||||||
|
if(inpt != NULL)
|
||||||
|
free(inpt);
|
||||||
|
if(dstpt != NULL)
|
||||||
|
free(dstpt);
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usage() {
|
void usage() {
|
||||||
|
|||||||
Reference in New Issue
Block a user