/* Quake proxy */
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
extern char *optarg;
extern int optind;
#define VERSION "1.0"
#define MAX 4096
unsigned char msg[MAX];
char *name;
void usage ()
{
fprintf(stderr, "usage: %s [-l localport] [-r remoteport]", name);
fprintf(stderr, " [-h] server\n");
}
int main(int argc, char **argv)
{
int sfd, cfd, c2fd, n, ucl, i, pid, opt;
fd_set fds;
struct sockaddr_in cremote_addr, clocal_addr;
struct sockaddr_in sremote_addr, slocal_addr;
struct sockaddr_in kuk_addr;
struct hostent *host;
struct timeval tv, *tvp;
int localport = 27000, remoteport = 27000, debug = 0;
name = argv[0];
while (opt = getopt(argc, argv, "l:r:hv"), opt != -1) {
switch (opt) {
case 'l':
localport = atoi(optarg);
break;
case 'r':
remoteport = atoi(optarg);
break;
case 'v':
fprintf(stderr, "qudproxy version %s", VERSION);
return 0;
default:
usage();
return opt != 'h';
}
}
if (optind != argc - 1) {
usage();
return 1;
}
ucl = sizeof(struct sockaddr_in);
bzero(&sremote_addr, ucl);
sremote_addr.sin_family = AF_INET;
sremote_addr.sin_port = htons(remoteport);
n = inet_addr(argv[optind]);
if (n != -1)
memcpy(&sremote_addr.sin_addr, &n, sizeof(n));
else {
host = gethostbyname(argv[optind]);
if (host == NULL)
return(-1);
memcpy (&sremote_addr.sin_addr, host->h_addr, host->h_length);
}
bzero(&clocal_addr, ucl);
clocal_addr.sin_family = AF_INET;
clocal_addr.sin_port = htons(localport);
/* Surely there's a better way to determine our IP address. */
gethostname(msg, MAX);
host = gethostbyname(msg);
memcpy(&clocal_addr.sin_addr, host->h_addr, host->h_length);
bzero(&slocal_addr, ucl);
slocal_addr.sin_family = AF_INET;
slocal_addr.sin_addr.s_addr = htonl(INADDR_ANY);
cfd = socket(AF_INET, SOCK_DGRAM, 0);
bind(cfd, (struct sockaddr *)&clocal_addr, ucl);
sfd = socket(AF_INET, SOCK_DGRAM, 0);
bind(sfd, (struct sockaddr *)&slocal_addr, ucl);
while (1) {
int i;
FD_ZERO(&fds);
FD_SET(sfd, &fds);
FD_SET(cfd, &fds);
if (0 >= select(1 + (cfd > sfd ? cfd : sfd), &fds, NULL, NULL, NULL))
return 0;
if (FD_ISSET(cfd, &fds)) {
n = recvfrom(cfd, msg, MAX, 0,
(struct sockaddr *)&cremote_addr, &ucl);
if (n == -1) {
perror("qudproxy");
return 1;
}
sendto(sfd, msg, n, 0, (struct sockaddr *)&sremote_addr, ucl);
}
if (FD_ISSET(sfd, &fds)) {
n = recvfrom(sfd, msg, MAX, 0, NULL, &ucl);
if (n == -1) {
perror("qudproxy");
return 1;
}
sendto(cfd, msg, n, 0, (struct sockaddr *)&cremote_addr, ucl);
}
}
}