diff --git a/src/router.c b/src/router.c index 1460ad0..9845ec9 100644 --- a/src/router.c +++ b/src/router.c @@ -98,7 +98,7 @@ struct router_vars *router_init(BOOL global) { return NULL; } - if(!(router->recvbuf = malloc(PACKET_BUF_SIZE))) { + if(!(router->recvbuf = malloc(ROUTER_BUF_SIZE))) { log_printf("Out of memory! Cannot allocate recv buffer"); router_destroy(router); @@ -115,7 +115,7 @@ struct router_vars *router_init(BOOL global) { /* TODO: Use different port number for control socket? */ - addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); if(bind(router->listener, (struct sockaddr*)&addr, sizeof(addr)) == -1) { log_printf("Failed to bind TCP socket: %s", w32_error(WSAGetLastError())); @@ -256,7 +256,10 @@ DWORD router_main(void *arg) { struct sockaddr_in addr; int addrlen = sizeof(addr); - int len = recvfrom(router->udp_sock, router->recvbuf, PACKET_BUF_SIZE, 0, (struct sockaddr*)&addr, &addrlen); + struct rpacket_header *rp_header = (struct rpacket_header*)router->recvbuf; + ipx_packet *packet = (ipx_packet*)(router->recvbuf + sizeof(struct rpacket_header)); + + int len = recvfrom(router->udp_sock, (char*)packet, PACKET_BUF_SIZE, 0, (struct sockaddr*)&addr, &addrlen); if(len == -1) { if(WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAECONNRESET) { continue; @@ -268,23 +271,15 @@ DWORD router_main(void *arg) { EnterCriticalSection(&(router->crit_sec)); - ipx_packet *packet = (ipx_packet*)router->recvbuf; - packet->size = ntohs(packet->size); - if(packet->size > MAX_PACKET_SIZE || packet->size + sizeof(ipx_packet) - 1 != len) { + if(len < sizeof(ipx_packet) - 1 || packet->size > MAX_PACKET_SIZE || packet->size + sizeof(ipx_packet) - 1 != len) { LeaveCriticalSection(&(router->crit_sec)); continue; } - /* Replace destination network field of packet with source IP address - * so that the client can cache it. - */ - - char dest_net[4]; - - memcpy(dest_net, packet->dest_net, 4); - memcpy(packet->dest_net, &(addr.sin_addr.s_addr), 4); + memset(&rp_header, 0, sizeof(*rp_header)); + rp_header->src_ipaddr = addr.sin_addr.s_addr; struct router_addr *ra = router->addrs; @@ -292,7 +287,7 @@ DWORD router_main(void *arg) { if( ra->local_port && (ra->filter_ptype < 0 || ra->filter_ptype == packet->ptype) && - (memcmp(dest_net, ra->addr.sa_netnum, 4) == 0 || memcmp(dest_net, f6, 4) == 0) && + (memcmp(packet->dest_net, ra->addr.sa_netnum, 4) == 0 || memcmp(packet->dest_net, f6, 4) == 0) && (memcmp(packet->dest_node, ra->addr.sa_nodenum, 6) == 0 || memcmp(packet->dest_node, f6, 6) == 0) && packet->dest_socket == ra->addr.sa_socket && @@ -302,10 +297,10 @@ DWORD router_main(void *arg) { /* Check source address matches remote_addr if set */ (ra->remote_addr.sa_family == AF_UNSPEC || (memcmp(ra->remote_addr.sa_netnum, packet->src_net, 4) == 0 && memcmp(ra->remote_addr.sa_nodenum, packet->src_node, 6) == 0)) ) { - addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr.sin_port = ra->local_port; - if(sendto(router->udp_sock, (char*)packet, len, 0, (struct sockaddr*)&addr, sizeof(addr)) == -1) { + if(sendto(router->udp_sock, (char*)rp_header, sizeof(*rp_header) + len, 0, (struct sockaddr*)&addr, sizeof(addr)) == -1) { log_printf("Error relaying packet: %s", w32_error(WSAGetLastError())); } } @@ -672,7 +667,7 @@ BOOL rclient_start(struct rclient *rclient) { struct sockaddr_in addr; addr.sin_family = AF_INET; - addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr.sin_port = htons(global_conf.udp_port); if(connect(rclient->sock, (struct sockaddr*)&addr, sizeof(addr)) == 0) { diff --git a/src/router.h b/src/router.h index 23ce35e..2f80922 100644 --- a/src/router.h +++ b/src/router.h @@ -24,6 +24,7 @@ #include #define MAX_ROUTER_CLIENTS 128 +#define ROUTER_BUF_SIZE PACKET_BUF_SIZE + sizeof(struct rpacket_header) struct router_call { enum { @@ -104,6 +105,11 @@ struct rclient { HANDLE thread; }; +struct rpacket_header { + uint8_t src_ipaddr; + char spare[20]; +} __attribute__((__packed__)); + struct router_vars *router_init(BOOL global); void router_destroy(struct router_vars *router); diff --git a/src/winsock.c b/src/winsock.c index afac248..f70013a 100644 --- a/src/winsock.c +++ b/src/winsock.c @@ -249,7 +249,7 @@ int WSAAPI bind(SOCKET fd, const struct sockaddr *addr, int addrlen) { struct sockaddr_in bind_addr; bind_addr.sin_family = AF_INET; - bind_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + bind_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); bind_addr.sin_port = 0; if(r_bind(fd, (struct sockaddr*)&bind_addr, sizeof(bind_addr)) == -1) { @@ -322,28 +322,30 @@ static int recv_packet(ipx_socket *sockptr, char *buf, int bufsize, int flags, s return -1; } - struct ipx_packet *packet = malloc(PACKET_BUF_SIZE); - if(!packet) { + char *recvbuf = malloc(ROUTER_BUF_SIZE); + if(!recvbuf) { WSASetLastError(ERROR_OUTOFMEMORY); return -1; } - int rval = r_recv(fd, (char*)packet, PACKET_BUF_SIZE, flags); + struct rpacket_header *rp_header = (struct rpacket_header*)recvbuf; + struct ipx_packet *packet = (struct ipx_packet*)(recvbuf + sizeof(*rp_header)); + + int rval = r_recv(fd, recvbuf, ROUTER_BUF_SIZE, flags); if(rval == -1) { - free(packet); + free(recvbuf); return -1; } - if(rval < sizeof(ipx_packet) || rval != packet->size + sizeof(ipx_packet) - 1) { + if(rval < sizeof(*rp_header) + sizeof(ipx_packet) - 1 || rval != sizeof(*rp_header) + packet->size + sizeof(ipx_packet) - 1) { log_printf("Invalid packet received on loopback port!"); - free(packet); + free(recvbuf); WSASetLastError(WSAEWOULDBLOCK); return -1; } - /* Router thread replaces destination network number with source IP address */ - add_host(packet->src_net, packet->src_node, *((uint32_t*)packet->dest_net)); + add_host(packet->src_net, packet->src_node, rp_header->src_ipaddr); if(addr) { addr->sa_family = AF_IPX; @@ -354,7 +356,7 @@ static int recv_packet(ipx_socket *sockptr, char *buf, int bufsize, int flags, s memcpy(buf, packet->data, packet->size <= bufsize ? packet->size : bufsize); rval = packet->size; - free(packet); + free(recvbuf); return rval; }