I need to write a packet relay server which will have the following
functionality:
Off-topic here since out-of-focus of the standard. However, assuming BSD
socket API is used...
1.It will listen on multiple ports(udp/tcp).
That means just multiple sockets and select().
Upon receiving packet it will manipulate the packets without knowing
anything about the contents of the packets.
Dump your manipulations into this function:
static void manip(unsigned char* packet, size_t len)
{
//when called, a packet was received of length len
}
static struct {
int type;
unsigned short port;} config[] = {
{SOCK_STREAM, 80},
{SOCK_DGRAM, 53},
};
static int sockets[sizeof config / sizeof *config];
int main(void)
{
unsigned int i;
struct sockaddr_in sa;
int max;
fd_set sock_set;
sa.sin_family = AF_INET;
sa.sin_addr = INADDR_ANY;
max = -1;
for (i = 0; i < sizeof config / sizeof *config; i++)
{
sockets
= socket(AF_INET, config.type, 0);
if (sockets < 0) {
perror("socket failed");
return 111;
}
sa.sin_port = htons(config.port);
if (bind(sockets, (struct sockaddr*)&sa, sizeof sa)) {
perror("bind failed");
return 111;
}
if (listen(sockets, SOMAXCONN)) {
perror("listen failed");
return 111;
}
if (max < sockets) max = sockets;
}
for (; {
FD_ZERO(&sock_set);
for (i = 0; i < sizeof sockets / sizeof *sockets; i++)
FD_SET(sockets, &sock_set);
select(max + 1, &sock_set, NULL, NULL, NULL);
for (i = 0; i < sizeof sockets / sizeof *sockets; i++)
if (FD_ISSET(sockets, &sock_set)) {
char buf[1500];
ssize_t rc;
int readsock;
if (config.type == SOCK_STREAM)
readsock = accept(sockets, NULL, 0);
else readsock = sockets;
if (readsock < 0) {
perror("accept failed");
return 111;
}
rc = recv(readsock, buf, sizeof buf, 0)
if (rc < 0) {
perror("recv failed");
return 111;
}
manip(buf, rc);
if (config.type == SOCK_STREAM)
close(readsock);
}
}
}
2.When manipulation ends, it will forward the packets to a specified
ip/port interface.
TCP or UDP? Either way, you just create yet another socket, but you
don't bind() it, you connect() it to the target address and then send
the stuff after manip() finished.
So it will work as a relay. Any suggestion about the software? If any
open source implementation is available which does a similar job,
will be very helpful.
Ha! It will also by the way do an NAT. A real NAT would need to listen
to the control connection, too, to relay answers.