mirror of
https://codeberg.org/scip/udpxd.git
synced 2025-12-16 19:40:58 +01:00
v4 works again
This commit is contained in:
8
client.c
8
client.c
@@ -60,18 +60,18 @@ client_t *client_new(int fd, host_t *src, host_t *dst) {
|
|||||||
void client_close(client_t *client) {
|
void client_close(client_t *client) {
|
||||||
client_del(client);
|
client_del(client);
|
||||||
close(client->socket);
|
close(client->socket);
|
||||||
free(client->src);
|
host_clean(client->src);
|
||||||
free(client->dst);
|
host_clean(client->dst);
|
||||||
free(client);
|
free(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
void client_clean() {
|
void client_clean(int asap) {
|
||||||
uint32_t now = (long)time(0);
|
uint32_t now = (long)time(0);
|
||||||
uint32_t diff;
|
uint32_t diff;
|
||||||
client_t *current;
|
client_t *current;
|
||||||
client_iter(clients, current) {
|
client_iter(clients, current) {
|
||||||
diff = now - current->lastseen;
|
diff = now - current->lastseen;
|
||||||
if(diff >= MAXAGE) {
|
if(diff >= MAXAGE || asap) {
|
||||||
if(VERBOSE) {
|
if(VERBOSE) {
|
||||||
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",
|
||||||
current->src->ip, current->src->port, current->dst->ip, current->dst->port, MAXAGE);
|
current->src->ip, current->src->port, current->dst->ip, current->dst->port, MAXAGE);
|
||||||
|
|||||||
3
client.h
3
client.h
@@ -48,7 +48,6 @@ struct _client_t {
|
|||||||
host_t *src; /* client src (ip+port) from incoming socket */
|
host_t *src; /* client src (ip+port) from incoming socket */
|
||||||
host_t *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;
|
||||||
@@ -77,7 +76,7 @@ void client_del(client_t *client);
|
|||||||
void client_add(client_t *client);
|
void client_add(client_t *client);
|
||||||
void client_seen(client_t *client);
|
void client_seen(client_t *client);
|
||||||
void client_close(client_t *client);
|
void client_close(client_t *client);
|
||||||
void client_clean();
|
void client_clean(int asap);
|
||||||
|
|
||||||
client_t *client_find_fd(int fd);
|
client_t *client_find_fd(int fd);
|
||||||
client_t *client_find_src(host_t *src);
|
client_t *client_find_src(host_t *src);
|
||||||
|
|||||||
19
host.c
19
host.c
@@ -49,6 +49,8 @@ host_t *get_host(char *ip, int port, struct sockaddr_in *v4, struct sockaddr_in6
|
|||||||
host->is_v6 = 1;
|
host->is_v6 = 1;
|
||||||
host->sock = (struct sockaddr*)tmp;
|
host->sock = (struct sockaddr*)tmp;
|
||||||
host->size = sizeof(struct sockaddr_in6);
|
host->size = sizeof(struct sockaddr_in6);
|
||||||
|
host->ip = malloc(INET6_ADDRSTRLEN+1);
|
||||||
|
memcpy(host->ip, ip, INET6_ADDRSTRLEN);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
struct sockaddr_in *tmp = malloc(sizeof(struct sockaddr_in));
|
struct sockaddr_in *tmp = malloc(sizeof(struct sockaddr_in));
|
||||||
@@ -58,6 +60,8 @@ host_t *get_host(char *ip, int port, struct sockaddr_in *v4, struct sockaddr_in6
|
|||||||
tmp->sin_port = htons( port );
|
tmp->sin_port = htons( port );
|
||||||
host->sock = (struct sockaddr*)tmp;
|
host->sock = (struct sockaddr*)tmp;
|
||||||
host->size = sizeof(struct sockaddr_in);
|
host->size = sizeof(struct sockaddr_in);
|
||||||
|
host->ip = malloc(INET_ADDRSTRLEN+1);
|
||||||
|
memcpy(host->ip, ip, INET_ADDRSTRLEN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(v4 != NULL) {
|
else if(v4 != NULL) {
|
||||||
@@ -68,6 +72,7 @@ host_t *get_host(char *ip, int port, struct sockaddr_in *v4, struct sockaddr_in6
|
|||||||
host->port = ntohs(tmp->sin_port);
|
host->port = ntohs(tmp->sin_port);
|
||||||
host->sock = (struct sockaddr*)tmp;
|
host->sock = (struct sockaddr*)tmp;
|
||||||
host->size = sizeof(struct sockaddr_in);
|
host->size = sizeof(struct sockaddr_in);
|
||||||
|
//fprintf(stderr, "%s sock: %p\n", host->ip, tmp);
|
||||||
}
|
}
|
||||||
else if(v6 != NULL) {
|
else if(v6 != NULL) {
|
||||||
struct sockaddr_in6 *tmp = malloc(sizeof(struct sockaddr_in6));
|
struct sockaddr_in6 *tmp = malloc(sizeof(struct sockaddr_in6));
|
||||||
@@ -130,3 +135,17 @@ unsigned get_v6_scope(const char *ip){
|
|||||||
int is_linklocal(struct in6_addr *a) {
|
int is_linklocal(struct in6_addr *a) {
|
||||||
return ((a->s6_addr[0] == 0xfe) && ((a->s6_addr[1] & 0xc0) == 0x80));
|
return ((a->s6_addr[0] == 0xfe) && ((a->s6_addr[1] & 0xc0) == 0x80));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void host_dump(host_t *host) {
|
||||||
|
fprintf(stderr, "host - ip: %s\n", host->ip);
|
||||||
|
fprintf(stderr, " port: %d\n", host->port);
|
||||||
|
fprintf(stderr, " isv6: %d\n", host->is_v6);
|
||||||
|
fprintf(stderr, " size: %ld\n", host->size);
|
||||||
|
fprintf(stderr, " src: %p\n", host->sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_clean(host_t *host) {
|
||||||
|
free(host->sock);
|
||||||
|
free(host->ip);
|
||||||
|
free(host);
|
||||||
|
}
|
||||||
|
|||||||
2
host.h
2
host.h
@@ -50,5 +50,7 @@ unsigned get_v6_scope(const char *ip);
|
|||||||
int is_linklocal(struct in6_addr *a);
|
int is_linklocal(struct in6_addr *a);
|
||||||
host_t *get_host(char *ip, int port, struct sockaddr_in *v4, struct sockaddr_in6 *v6);
|
host_t *get_host(char *ip, int port, struct sockaddr_in *v4, struct sockaddr_in6 *v6);
|
||||||
char *is_v6(char *ip);
|
char *is_v6(char *ip);
|
||||||
|
void host_dump(host_t *host);
|
||||||
|
void host_clean(host_t *host);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
100
net.c
100
net.c
@@ -102,6 +102,7 @@ int start_listener (char *inip, char *inpt, char *srcip, char *dstip, char *dstp
|
|||||||
bind_h = get_host("0.0.0.0", 0, NULL, NULL);
|
bind_h = get_host("0.0.0.0", 0, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int listen = bindsocket(listen_h);
|
int listen = bindsocket(listen_h);
|
||||||
|
|
||||||
if(listen == -1)
|
if(listen == -1)
|
||||||
@@ -118,13 +119,14 @@ int start_listener (char *inip, char *inpt, char *srcip, char *dstip, char *dstp
|
|||||||
|
|
||||||
main_loop(listen, listen_h, bind_h, dst_h);
|
main_loop(listen, listen_h, bind_h, dst_h);
|
||||||
|
|
||||||
|
host_clean(bind_h);
|
||||||
|
host_clean(listen_h);
|
||||||
|
host_clean(dst_h);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle new or known incoming requests
|
/* 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) {
|
void handle_inside(int inside, host_t *listen_h, host_t *bind_h, host_t *dst_h) {
|
||||||
int len;
|
int len;
|
||||||
unsigned char buffer[MAX_BUFFER_SIZE];
|
unsigned char buffer[MAX_BUFFER_SIZE];
|
||||||
@@ -144,6 +146,8 @@ void handle_inside(int inside, host_t *listen_h, host_t *bind_h, host_t *dst_h)
|
|||||||
else
|
else
|
||||||
src_h = get_host(NULL, 0, (struct sockaddr_in *)src, NULL);
|
src_h = get_host(NULL, 0, (struct sockaddr_in *)src, NULL);
|
||||||
|
|
||||||
|
free(src);
|
||||||
|
|
||||||
if(VERBOSE) {
|
if(VERBOSE) {
|
||||||
fprintf(stderr, "New incomming request from %s:%d with %d bytes\n",
|
fprintf(stderr, "New incomming request from %s:%d with %d bytes\n",
|
||||||
src_h->ip, src_h->port, len);
|
src_h->ip, src_h->port, len);
|
||||||
@@ -155,7 +159,7 @@ void handle_inside(int inside, host_t *listen_h, host_t *bind_h, host_t *dst_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 ",
|
||||||
src_h->ip, src_h->port, dst_h->ip, dst_h->port);
|
src_h->ip, src_h->port, dst_h->ip, dst_h->port);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -189,12 +193,14 @@ void handle_inside(int inside, host_t *listen_h, host_t *bind_h, host_t *dst_h)
|
|||||||
struct sockaddr_in6 *ret = malloc(size);
|
struct sockaddr_in6 *ret = malloc(size);
|
||||||
getsockname(output, (struct sockaddr*)ret, (socklen_t *)&size);
|
getsockname(output, (struct sockaddr*)ret, (socklen_t *)&size);
|
||||||
ret_h = get_host(NULL, 0, NULL, ret);
|
ret_h = get_host(NULL, 0, NULL, ret);
|
||||||
|
free(ret);
|
||||||
client = client_new(output, src_h, ret_h);
|
client = client_new(output, src_h, ret_h);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
struct sockaddr_in *ret = malloc(size);
|
struct sockaddr_in *ret = malloc(size);
|
||||||
getsockname(output, (struct sockaddr*)ret, (socklen_t *)&size);
|
getsockname(output, (struct sockaddr*)ret, (socklen_t *)&size);
|
||||||
ret_h = get_host(NULL, 0, ret, NULL);
|
ret_h = get_host(NULL, 0, ret, NULL);
|
||||||
|
free(ret);
|
||||||
client = client_new(output, src_h, ret_h);
|
client = client_new(output, src_h, ret_h);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,47 +232,81 @@ void handle_outside(int inside, int outside, host_t *outside_h) {
|
|||||||
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 );
|
||||||
|
free(src);
|
||||||
|
|
||||||
if(len > 0) {
|
if(len > 0) {
|
||||||
/* do we know it? */
|
/* do we know it? */
|
||||||
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, client->size) < 0) {
|
/* FIXME: check src vs. client->src ? */
|
||||||
|
if(sendto(inside, buffer, len, 0,
|
||||||
|
(struct sockaddr*)client->src->sock, client->src->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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "weird, no matching client found!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "weird, recvfrom returned 0 bytes!\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jmp_buf JumpBuffer;
|
||||||
|
|
||||||
/* runs forever, handles incoming requests on the inside and answers on the 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 main_loop(int listensocket, host_t *listen_h, host_t *bind_h, host_t *dst_h) {
|
||||||
int max, sender;
|
int max, sender;
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
|
|
||||||
for(;;) {
|
signal(SIGINT, int_handler);
|
||||||
FD_ZERO(&fds);
|
signal(SIGTERM, int_handler);
|
||||||
max = fill_set(&fds);
|
|
||||||
|
|
||||||
FD_SET(listensocket, &fds);
|
for(;;) {
|
||||||
if (listensocket > max)
|
if (setjmp(JumpBuffer) == 1) {
|
||||||
max = listensocket;
|
break;
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we came here via signal handler,
|
||||||
|
clean up */
|
||||||
|
client_t *current = NULL;
|
||||||
|
client_iter(clients, current) {
|
||||||
|
close(current->socket);
|
||||||
|
}
|
||||||
|
close(listensocket);
|
||||||
|
client_clean(1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void int_handler(int sig) {
|
||||||
|
signal(sig, SIG_IGN);
|
||||||
|
longjmp(JumpBuffer, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
4
net.h
4
net.h
@@ -28,6 +28,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@@ -54,7 +56,7 @@ int start_listener (char *inip, char *inpt, char *srcip, char *dstip, char *dstp
|
|||||||
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( host_t *sock_h);
|
int bindsocket( host_t *sock_h);
|
||||||
|
void int_handler(int sig);
|
||||||
|
|
||||||
|
|
||||||
#define _IS_LINK_LOCAL(a) do { IN6_IS_ADDR_LINKLOCAL(a); } while(0)
|
#define _IS_LINK_LOCAL(a) do { IN6_IS_ADDR_LINKLOCAL(a); } while(0)
|
||||||
|
|||||||
Reference in New Issue
Block a user