Zurück zur SP2 Übersicht
snailproxy.c
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <signal.h>
static void die(const char *msg) {
perror(msg);
exit(EXIT_FAILURE);
}
#define IN 0
#define OUT 1
static void copy(FILE *src, FILE *dst, int direction, pid_t partner) {
char *col = (direction == OUT) ? "\e[0;32m" : "\e[0;31m";
char *hcol = (direction == OUT) ? "\e[1;32m" : "\e[1;31m";
char *dir = (direction == OUT) ? "> " : "< ";
int last = '\n';
while (1) {
int c = fgetc(src);
if (c == EOF) {
printf("\n%s<lost connection>\e[0m\n\n", hcol);
fflush(stdout);
if (partner) {
kill(partner, 9);
}
break;
}
fputc(c, dst);
fflush(dst);
if (last == '\n') {
printf("%s%s\e[0m", hcol, dir);
fflush(stdout);
}
if (c == '\r') {
printf("%s\\r\e[0m", hcol);
fflush(stdout);
}
if (c == '\n') {
printf("%s\\n\e[0m", hcol);
fflush(stdout);
}
if (c != '\r') {
printf("%s%c\e[0m", col, c);
fflush(stdout);
}
last = c;
}
}
int main(int argc, char *argv[]) {
struct sigaction sa = {
.sa_handler = SIG_IGN,
.sa_flags = SA_RESTART,
};
sigemptyset(&sa.sa_mask);
sigaction(SIGCHLD, &sa, NULL);
const int listenSock = socket(AF_INET6, SOCK_STREAM, 0);
if (listenSock == -1) {
die("listenSock");
}
const struct sockaddr_in6 name = {
.sin6_family = AF_INET6,
.sin6_port = htons(1125),
.sin6_addr = in6addr_loopback,
};
const int flag = 1;
if (setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)) == -1) {
die("setsockopt");
}
if (bind(listenSock, (struct sockaddr *) &name, sizeof(name)) == -1) {
die("bind");
}
if (listen(listenSock, SOMAXCONN) == -1) {
die("listen");
}
printf("\x1B[1;37msnail-Proxy von nudelsalat | milan.stephan@fau.de | https://sp.milanstephan.de\x1B[0m\n");
printf("Warte auf Verbindung der \x1B[1;37msnail\x1B[0m...\n");
while (1) {
int clientSock = accept(listenSock, NULL, NULL);
if (clientSock < 0) {
perror("accept");
continue;
}
pid_t pid = fork();
if (pid == -1) {
die("fork");
}
if (pid == 0) {
close(listenSock);
struct addrinfo hints = {
.ai_socktype = SOCK_STREAM,
.ai_family = AF_UNSPEC,
.ai_flags = AI_ADDRCONFIG,
};
struct addrinfo *head;
getaddrinfo("faui03.cs.fau.de", "25", &hints, &head);
int sock;
struct addrinfo *curr;
for (curr = head; curr != NULL; curr = curr->ai_next) {
sock = socket(curr->ai_family, curr->ai_socktype, curr->ai_protocol);
if (connect(sock, curr->ai_addr, curr->ai_addrlen) == 0) {
break;
}
close(sock);
}
if (curr == NULL) {
fprintf(stderr, "Proxy could not connect to faui03.cs.fau.de:25\n");
exit(EXIT_FAILURE);
}
int sock2 = dup(sock);
FILE *out_tx = fdopen(sock, "w");
FILE *out_rx = fdopen(sock2, "r");
int sock3 = dup(clientSock);
FILE *in_tx = fdopen(clientSock, "w");
FILE *in_rx = fdopen(sock3, "r");
pid_t p = getpid();
pid_t p2 = fork();
if (p2 == -1) {
die("fork");
}
if (p2 == 0) {
copy(in_rx, out_tx, OUT, p);
exit(EXIT_SUCCESS);
}
copy(out_rx, in_tx, IN, p2);
exit(EXIT_SUCCESS);
}
close(clientSock);
}
}