v4 works again

This commit is contained in:
TLINDEN
2015-04-25 20:14:24 +02:00
parent ecbd71ad5b
commit 7816f75170
6 changed files with 99 additions and 37 deletions

View File

@@ -60,18 +60,18 @@ client_t *client_new(int fd, host_t *src, host_t *dst) {
void client_close(client_t *client) {
client_del(client);
close(client->socket);
free(client->src);
free(client->dst);
host_clean(client->src);
host_clean(client->dst);
free(client);
}
void client_clean() {
void client_clean(int asap) {
uint32_t now = (long)time(0);
uint32_t diff;
client_t *current;
client_iter(clients, current) {
diff = now - current->lastseen;
if(diff >= MAXAGE) {
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);

View File

@@ -48,7 +48,6 @@ struct _client_t {
host_t *src; /* client src (ip+port) from incoming socket */
host_t *dst; /* client dst (ip+port) to outgoing socket */
uint64_t lastseen; /* when did we recv last time from it */
size_t size; /* sockaddr size */
UT_hash_handle hh;
};
typedef struct _client_t client_t;
@@ -77,7 +76,7 @@ void client_del(client_t *client);
void client_add(client_t *client);
void client_seen(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_src(host_t *src);

19
host.c
View File

@@ -49,6 +49,8 @@ host_t *get_host(char *ip, int port, struct sockaddr_in *v4, struct sockaddr_in6
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);
}
else {
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 );
host->sock = (struct sockaddr*)tmp;
host->size = sizeof(struct sockaddr_in);
host->ip = malloc(INET_ADDRSTRLEN+1);
memcpy(host->ip, ip, INET_ADDRSTRLEN);
}
}
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->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));
@@ -130,3 +135,17 @@ unsigned get_v6_scope(const char *ip){
int is_linklocal(struct in6_addr *a) {
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
View File

@@ -50,5 +50,7 @@ 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);
void host_dump(host_t *host);
void host_clean(host_t *host);
#endif

54
net.c
View File

@@ -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);
}
int listen = bindsocket(listen_h);
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);
host_clean(bind_h);
host_clean(listen_h);
host_clean(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
*/
/* handle new or known incoming requests */
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];
@@ -144,6 +146,8 @@ void handle_inside(int inside, host_t *listen_h, host_t *bind_h, host_t *dst_h)
else
src_h = get_host(NULL, 0, (struct sockaddr_in *)src, NULL);
free(src);
if(VERBOSE) {
fprintf(stderr, "New incomming request from %s:%d with %d bytes\n",
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) {
/* 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\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);
}
@@ -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);
getsockname(output, (struct sockaddr*)ret, (socklen_t *)&size);
ret_h = get_host(NULL, 0, NULL, ret);
free(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);
free(ret);
client = client_new(output, src_h, ret_h);
}
@@ -226,26 +232,44 @@ void handle_outside(int inside, int outside, host_t *outside_h) {
src = malloc(size);
len = recvfrom( outside, buffer, sizeof( buffer ), 0, (struct sockaddr*)src, (socklen_t *)&size );
free(src);
if(len > 0) {
/* do we know it? */
client = client_find_fd(outside);
if(client != NULL) {
/* 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 */
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 */
int main_loop(int listensocket, host_t *listen_h, host_t *bind_h, host_t *dst_h) {
int max, sender;
fd_set fds;
signal(SIGINT, int_handler);
signal(SIGTERM, int_handler);
for(;;) {
if (setjmp(JumpBuffer) == 1) {
break;
}
FD_ZERO(&fds);
max = fill_set(&fds);
@@ -267,6 +291,22 @@ int main_loop(int listensocket, host_t *listen_h, host_t *bind_h, host_t *dst_h)
}
/* close old outputs, if any */
client_clean();
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
View File

@@ -28,6 +28,8 @@
#include <stdint.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/socket.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 get_sender(fd_set *fds);
int bindsocket( host_t *sock_h);
void int_handler(int sig);
#define _IS_LINK_LOCAL(a) do { IN6_IS_ADDR_LINKLOCAL(a); } while(0)