Compare commits

..

12 Commits

4 changed files with 120 additions and 34 deletions

View File

@@ -10,3 +10,4 @@ TODO
## Usage ## Usage
./proxy <local-address> <local-port> <remote-address> <remote-port> ./proxy <local-address> <local-port> <remote-address> <remote-port>
### If the program doesn't work, check the errno. Run 'errno $?' to get the resulting error. Also, CHECK YOUR FIREWALL!!!

View File

@@ -1,5 +1,6 @@
#include "easysock.h" #include "easysock.h"
int create_socket(int network, char transport) { int create_socket(int network, char transport) {
int domain; int domain;
int type; int type;
@@ -25,7 +26,7 @@ int create_socket(int network, char transport) {
} }
void create_addr(int network, char* address, int port,struct sockaddr* dest) { int create_addr(int network, char* address, int port,struct sockaddr* dest) {
if (network == 4) { if (network == 4) {
struct sockaddr_in listen_address; struct sockaddr_in listen_address;
@@ -33,7 +34,7 @@ void create_addr(int network, char* address, int port,struct sockaddr* dest) {
listen_address.sin_port = htons(port); listen_address.sin_port = htons(port);
inet_pton(AF_INET,address,&listen_address.sin_addr); inet_pton(AF_INET,address,&listen_address.sin_addr);
memcpy(dest,&listen_address,sizeof(listen_address)); memcpy(dest,&listen_address,sizeof(listen_address));
return; return 0;
} else if (network == 6) { } else if (network == 6) {
struct sockaddr_in6 listen_ipv6; struct sockaddr_in6 listen_ipv6;
@@ -41,10 +42,10 @@ void create_addr(int network, char* address, int port,struct sockaddr* dest) {
listen_ipv6.sin6_port = htons(port); listen_ipv6.sin6_port = htons(port);
inet_pton(AF_INET6,address,&listen_ipv6.sin6_addr); inet_pton(AF_INET6,address,&listen_ipv6.sin6_addr);
memcpy(dest,&listen_ipv6,sizeof(listen_ipv6)); memcpy(dest,&listen_ipv6,sizeof(listen_ipv6));
return; return 0;
} else { } else {
exit(2); return -202;
} }
} }
@@ -52,7 +53,7 @@ void create_addr(int network, char* address, int port,struct sockaddr* dest) {
int create_local (int network, char transport, char* address, int port,struct sockaddr* addr_struct) { int create_local (int network, char transport, char* address, int port,struct sockaddr* addr_struct) {
int socket = create_socket(network,transport); int socket = create_socket(network,transport);
if (socket < 0) { if (socket < 0) {
exit(errno); return (-1 * errno);
} }
create_addr(network,address,port,addr_struct); create_addr(network,address,port,addr_struct);
int addrlen; int addrlen;
@@ -61,7 +62,7 @@ int create_local (int network, char transport, char* address, int port,struct so
} else if (network == 6) { } else if (network == 6) {
addrlen = sizeof(struct sockaddr_in6); addrlen = sizeof(struct sockaddr_in6);
} else { } else {
exit(7); return -207;
} }
/* The value of addrlen should be the size of the 'sockaddr'. /* The value of addrlen should be the size of the 'sockaddr'.
@@ -70,26 +71,49 @@ int create_local (int network, char transport, char* address, int port,struct so
int i = bind (socket,addr_struct,(socklen_t)addrlen); int i = bind (socket,addr_struct,(socklen_t)addrlen);
if (i < 0) { if (i < 0) {
exit(errno); return (-1 * errno);
} }
return socket; return socket;
} }
int create_remote (int network,char transport,char* address,int port,struct sockaddr* remote_addr_struct) { int create_remote (int network,char transport,char* address,int port,struct sockaddr* remote_addr_struct) {
struct addrinfo hints; /* Used to tell getaddrinfo what kind of address we want */
struct addrinfo* results; /* Used by getaddrinfo to store the addresses */
if (check_ip_ver(address) < 0) { /* If the address is a domain name */
int err_code;
char* port_str = malloc(10 * sizeof(char));
sprintf(port_str,"%d",port); /* getaddrinfo expects a string for its port */
memset(&hints,'\0',sizeof(hints));
hints.ai_socktype = char_to_socktype(transport);
err_code = getaddrinfo(address,port_str,&hints,&results);
if (err_code != 0) {
exit(err_code);
}
remote_addr_struct = results->ai_addr;
network = inet_to_int(results->ai_family);
} else {
create_addr(network,address,port,remote_addr_struct);
}
int socket = create_socket(network,transport); int socket = create_socket(network,transport);
if (socket < 0) { if (socket < 0) {
exit(errno); return (-1 * errno);
} }
create_addr(network,address,port,remote_addr_struct);
int addrlen; int addrlen;
if (network == 4) { if (network == 4) {
addrlen = sizeof(struct sockaddr_in); addrlen = sizeof(struct sockaddr_in);
} else if (network == 6) { } else if (network == 6) {
addrlen = sizeof(struct sockaddr_in6); addrlen = sizeof(struct sockaddr_in6);
} else { } else {
exit(7); return (-1 * errno);
} }
/* The value of addrlen should be the size of the 'sockaddr'. /* The value of addrlen should be the size of the 'sockaddr'.
@@ -98,7 +122,49 @@ int create_remote (int network,char transport,char* address,int port,struct sock
int i = connect(socket,remote_addr_struct,(socklen_t)addrlen); int i = connect(socket,remote_addr_struct,(socklen_t)addrlen);
if (i < 0) { if (i < 0) {
exit(errno); return (-1 * errno);
} }
return socket; return socket;
} }
int check_ip_ver(char* address) {
char buffer[16]; /* 16 chars - 128 bits - is enough to hold an ipv6 address */
if (inet_pton(AF_INET,address,buffer) == 1) {
return 4;
} else if (inet_pton(AF_INET6,address,buffer) == 1) {
return 6;
} else {
return -1;
}
}
int int_to_inet(int network) {
if (network == 4) {
return AF_INET;
} else if (network == 6) {
return AF_INET6;
} else {
return -207;
}
}
int inet_to_int(int af_type) {
if (af_type == AF_INET) {
return 4;
} else if (af_type == AF_INET6) {
return 6;
} else {
return -207;
}
}
int char_to_socktype(char transport) {
if (transport == 'T') {
return SOCK_STREAM;
} else if (transport == 'U') {
return SOCK_DGRAM;
} else {
return -250;
}
}

View File

@@ -2,7 +2,9 @@
#define EASYSOCK_H_ #define EASYSOCK_H_
#include <string.h> #include <string.h>
#include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@@ -26,10 +28,10 @@ int create_socket(int network, char transport);
port is self-explanatory; port is self-explanatory;
and dest is a pointer to the sockaddr struct that will be filled in. and dest is a pointer to the sockaddr struct that will be filled in.
The function exits with error code 2 if the network parameter contained neither '4' The function returns with -202 if the network parameter contained neither '4'
nor '6'. */ nor '6'. */
void create_addr(int network, char* address, int port,struct sockaddr* dest); int create_addr(int network, char* address, int port,struct sockaddr* dest);
@@ -37,7 +39,7 @@ void create_addr(int network, char* address, int port,struct sockaddr* dest);
_binds_ the addresses. It is used for local sockets (server sockets). Parameters are _binds_ the addresses. It is used for local sockets (server sockets). Parameters are
same as above. same as above.
It prints the error returned by 'bind' if something went wrong, and exits with error code '3'.*/ It prints the error returned by 'bind' if something went wrong, and returns ( -1 * errno ).*/
int create_local (int network, char transport, char* address, int port,struct sockaddr* addr_struct); int create_local (int network, char transport, char* address, int port,struct sockaddr* addr_struct);
@@ -46,9 +48,29 @@ int create_local (int network, char transport, char* address, int port,struct so
requested address. It is used for remote sockets (client sockets). The paramters are same requested address. It is used for remote sockets (client sockets). The paramters are same
as above. This function needs an empty 'sockaddr *' structure passed to it, which it will fill. as above. This function needs an empty 'sockaddr *' structure passed to it, which it will fill.
It prints the error returned by 'connect' if something went wrong, and exits with error code '3'.*/ If something goes wrong, this function returns with ( -1 * errno ). */
int create_remote (int network,char transport,char* address,int port,struct sockaddr* remote_addr_struct); int create_remote (int network,char transport,char* address,int port,struct sockaddr* remote_addr_struct);
/* check_ip_ver - This function checks if the given string is an IPv4 address (returns 4),
IPv6 address (returns 6) or neither (returns -1). */
int check_ip_ver(char* address);
/* int_to_inet - Takes an int value (4 for IPv4, 6 for IPv6) and returns AF_INET or
AF_INET6 respectively. */
int int_to_inet(int network);
/* char_to_socktype - Takes a character that represents a transport-layer protocol
(currently only supports 'T' for TCP or 'U' for UDP - it returns -250 if
the given characters is neither of these) and return the appropriate SOCKTYPE value. */
int char_to_socktype(char transport);
/* inet_to_int - Takes an int value that corresponds to AF_INET or AF_INET6,
and returns the appropriate int value. */
int inet_to_int(int af_type);
#endif #endif

31
main.c
View File

@@ -13,18 +13,6 @@ void forward_data(int from_fd, int to_fd) {
} }
} }
int check_ip_ver(char* address) {
char buffer[16]; /* 16 chars - 128 bits - is enough to hold an ipv6 address */
if (inet_pton(AF_INET,address,buffer) == 1) {
return 4;
} else if (inet_pton(AF_INET6,address,buffer) == 1) {
return 6;
} else {
return -1;
}
}
void print_prog_info() { void print_prog_info() {
printf("%s [Local IP address] [local port] [remote IP address] [remote port]\n",PROG_NAME); printf("%s [Local IP address] [local port] [remote IP address] [remote port]\n",PROG_NAME);
} }
@@ -62,7 +50,7 @@ int main(int argc,char* argv[]) {
if (argc != 5) { if (argc != 5) {
print_prog_info(); print_prog_info();
exit(30); exit(230);
} }
@@ -73,22 +61,28 @@ int main(int argc,char* argv[]) {
int preferred_local_network = check_ip_ver(local_addr); int preferred_local_network = check_ip_ver(local_addr);
int preferred_remote_network = check_ip_ver(remote_addr); int preferred_remote_network = check_ip_ver(remote_addr);
if (preferred_remote_network < 0) { /* This value will be less than 0 if the remote address is a domain name */
printf("Using %d for local\nUsing hostname for remote\n",preferred_local_network);
} else {
printf("Using %d for local\nUsing %d for remote\n",preferred_local_network,preferred_remote_network); printf("Using %d for local\nUsing %d for remote\n",preferred_local_network,preferred_remote_network);
}
if ((preferred_local_network == -1) || (preferred_remote_network == -1)) { if (preferred_local_network == -1) {
exit(7); exit(207); /* If the _local_ address isn't an IP address, then we've got problems. */
} }
char preferred_transport = 'T'; char preferred_transport = 'T';
struct sockaddr addr_struct; struct sockaddr addr_struct;
int server_sock = create_local(preferred_local_network,preferred_transport,local_addr,local_port,&addr_struct); int server_sock = create_local(preferred_local_network,preferred_transport,local_addr,local_port,&addr_struct);
if (server_sock < 0) {
exit(-1 * server_sock);
}
int addrlen; int addrlen;
if (check_ip_ver(local_addr) == 4) { if (check_ip_ver(local_addr) == 4) {
addrlen = sizeof(struct sockaddr_in); addrlen = sizeof(struct sockaddr_in);
} else if (check_ip_ver(local_addr) == 6) { } else if (check_ip_ver(local_addr) == 6) {
addrlen = sizeof(struct sockaddr_in6); addrlen = sizeof(struct sockaddr_in6);
} else { } else {
exit(7); exit(207);
} }
listen(server_sock,50); /* Arbitrary number, change later */ listen(server_sock,50); /* Arbitrary number, change later */
@@ -99,6 +93,9 @@ int main(int argc,char* argv[]) {
while (1) { while (1) {
int from_client = accept(server_sock,&addr_struct,(socklen_t *)&addrlen); int from_client = accept(server_sock,&addr_struct,(socklen_t *)&addrlen);
int to_server = create_remote(preferred_remote_network,preferred_transport,remote_addr,remote_port,&remote_addr_struct); int to_server = create_remote(preferred_remote_network,preferred_transport,remote_addr,remote_port,&remote_addr_struct);
if (to_server < 0) {
exit(-1 * to_server);
}
printf("Connection established to %s:%d\n",remote_addr,remote_port); printf("Connection established to %s:%d\n",remote_addr,remote_port);
if (fork() == 0) { if (fork() == 0) {