diff --git a/Makefile b/Makefile index 217a4a3..0406ca9 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ $(DIRS_TARGET): $(MKDIR_P) $@ $(TARGET): $(OBJFILES) - $(CC) $(LDFLAGS) -o $@ $^ /usr/lib/libmilter.a + $(CC) $(LDFLAGS) -o $@ $^ $(BUILDDIR)/%.o: $(SRCDIR)/%.c $(CC) $(CFLAGS) -c -o $@ $< diff --git a/include/config.h b/include/config.h index 72536dc..a5f5a0f 100644 --- a/include/config.h +++ b/include/config.h @@ -17,6 +17,8 @@ #ifndef CONFIG_H #define CONFIG_H -extern char* socket_location; +#include + +extern uint16_t listen_port, forward_port; #endif /* CONFIG_H */ diff --git a/src/config.c b/src/config.c index 18a756d..fc16d3c 100644 --- a/src/config.c +++ b/src/config.c @@ -16,5 +16,4 @@ */ #include "config.h" -char* socket_location = "/var/run/mailattach"; - +uint16_t listen_port = 4269, forward_port = 4270; diff --git a/src/main.c b/src/main.c index f82eb2a..e4b3e1b 100644 --- a/src/main.c +++ b/src/main.c @@ -12,25 +12,196 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include + #include "version.h" #include "config.h" #include "attach.h" +/* + * error - wrapper for perror + */ +void error(char *msg) { + perror(msg); + exit(1); +} + + +struct client_info { + int fd; +}; + +void* client_handle_async(void* params){ + + struct client_info * cli = params; + struct sockaddr_in serveraddr; /* server's addr */ + int remote_fd; + + remote_fd = socket(AF_INET, SOCK_STREAM, 0); + if (remote_fd < 0){ + error("ERROR opening client socket"); + } + + /* build the server's Internet address */ + bzero((char *) &serveraddr, sizeof(serveraddr)); + + serveraddr.sin_family = AF_INET; + serveraddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + serveraddr.sin_port = htons(forward_port); + + /* connect: create a connection with the server */ + if (connect(remote_fd,(struct sockaddr *) &serveraddr, + sizeof(serveraddr)) < 0){ + error("ERROR connecting"); + } + + int n; /* message byte size */ + char buf[1024]; + struct pollfd fds[2]; + memset(fds, 0 , sizeof(fds)); + fds[0].fd = cli->fd; + fds[0].events = POLLIN; + fds[1].fd = remote_fd; + fds[1].events = POLLIN; + + int timeout = (10 * 1000); /* 10 seconds */ + + while(poll(fds, 2, timeout) > 0){ + for(size_t i = 0; i < 2; i++){ + if(!(fds[i].revents & POLLIN)){ + continue; + + } + bzero(buf, sizeof(buf)); + n = read(fds[i].fd, buf, sizeof(buf)); + if (n <= 0) { + goto closeup; + } + printf("%lu: %s\n", i, buf); + write((fds[!i].fd), buf, n); + + } + } + +closeup: + + printf("Disconnecting clients"); + close(cli->fd); + close(remote_fd); + free(cli); + + return NULL; +} + int main(int argc, char* argv[]){ - FILE* logfile = fopen("/tmp/shit", "a+"); - - fprintf(logfile, "INIT\n"); - fprintf(logfile, "Arguments passed on:\n"); - for(size_t i = 0; i < argc; i++){ - fprintf(logfile, "\t%lu:%s\n",i, argv[i]); + printf("INIT\n"); + printf("Arguments passed on:\n"); + for(int i = 0; i < argc; i++){ + printf("\t%i:%s\n",i, argv[i]); } - char input[1024]; - fread(input, sizeof(input), 1, stdin); - fprintf(logfile, input); - fclose(logfile); + int parentfd; /* parent socket */ + int childfd; /* child socket */ + socklen_t clientlen; /* byte size of client's address */ + struct sockaddr_in serveraddr; /* server's addr */ + struct sockaddr_in clientaddr; /* client addr */ + struct hostent *hostp; /* client host info */ + char *hostaddrp; /* dotted decimal host addr string */ + int optval; /* flag value for setsockopt */ + + /* + * socket: create the parent socket + */ + parentfd = socket(AF_INET, SOCK_STREAM, 0); + if (parentfd < 0){ + error("ERROR opening socket"); + } + + /* setsockopt: Handy debugging trick that lets + * us rerun the server immediately after we kill it; + * otherwise we have to wait about 20 secs. + * Eliminates "ERROR on binding: Address already in use" error. + */ + optval = 1; + setsockopt(parentfd, SOL_SOCKET, SO_REUSEADDR, + (const void *)&optval , sizeof(int)); + + /* + * build the server's Internet address + */ + bzero((char *) &serveraddr, sizeof(serveraddr)); + + /* this is an Internet address */ + serveraddr.sin_family = AF_INET; + + /* let the system figure out our IP address */ + serveraddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + /* this is the port we will listen on */ + serveraddr.sin_port = htons((unsigned short)listen_port); + + /* + * bind: associate the parent socket with a port + */ + if (bind(parentfd, (struct sockaddr *) &serveraddr, + sizeof(serveraddr)) < 0) { + error("ERROR on binding"); + } + + /* + * listen: make this socket ready to accept connection requests + */ + if (listen(parentfd, 5) < 0) /* allow 5 requests to queue up */ + error("ERROR on listen"); + + /* + * main loop: wait for a connection request, echo input line, + * then close connection. + */ + clientlen = sizeof(clientaddr); + char hostaddr_str[20]; + inet_ntop(AF_INET,(struct sockaddr *) &serveraddr, hostaddr_str, 20); + printf("Listening for clients on port %u\n", listen_port); + while (1) { + + /* + * accept: wait for a connection request + */ + childfd = accept(parentfd, (struct sockaddr *) &clientaddr, &clientlen); + if (childfd < 0) + error("ERROR on accept"); + + /* + * gethostbyaddr: determine who sent the message + */ + hostp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr, + sizeof(clientaddr.sin_addr.s_addr), AF_INET); + if (hostp == NULL) + error("ERROR on gethostbyaddr"); + hostaddrp = inet_ntoa(clientaddr.sin_addr); + if (hostaddrp == NULL) + error("ERROR on inet_ntoa\n"); + printf("server established connection with %s (%s) fd %i\n", + hostp->h_name, hostaddrp, childfd); + + struct client_info* cli = malloc(sizeof(struct client_info)); + memset(cli, 0, sizeof(struct client_info)); + cli->fd = childfd; + pthread_t executing_thread; + int status = pthread_create(&executing_thread, NULL, + client_handle_async, cli); + if(status < 0){ + error("Failed to create thread"); + } + } return EX_TEMPFAIL;