add connredir
[hband-ld-preload-libs.git] / src / connredir.c
blob6a40b157d1d2f437c3241387cb816d1a2b6e66b5
1 /*
3 connredir.c
5 USAGE
7 LD_PRELOAD=$PWD/connredir.so CONNREDIR_ORIG_IP=169.254.169.254 CONNREDIR_ORIG_PORT=80 CONNREDIR_TO_IP=127.0.0.1 CONNREDIR_TO_PORT=8080 wget ...
9 LD_PRELOAD=$PWD/connredir.so CONNREDIR_ORIG_IP=127.0.0.1 CONNREDIR_ORIG_PORT=25 CONNREDIR_TO=stdout sendmail ...
11 DESCRIPTION
13 This shared library is intended to extend connect(2) standard library function by ip/port override capability, so you control
14 programs, where to connect, without modifying or configuring themself.
16 On each connect() calls, it checks that the destination IP and port match to the ones in CONNREDIR_ORIG_IP and CONNREDIR_ORIG_PORT
17 environment variables. Then changes them to the IP and port numbers in CONNREDIR_TO_IP and CONNREDIR_TO_PORT respectively.
19 Leave CONNREDIR_ORIG_PORT unset to override all ports.
20 Leave CONNREDIR_TO_PORT unset to not override the destination port number.
22 If CONNREDIR_TO is set, then it's evaluated before CONNREDIR_TO_IP.
23 Valid values for CONNREDIR_TO: stdout.
24 When CONNREDIR_TO is 'stdout', connredir replaces the socket's FD, which is about to be connected, to the STDOUT, so you can
25 make your program communicate on STDIO instead of INET. Useful when combined with socat(1).
27 COMPATIBILITY
29 inet sockets (ipv4)
30 SOCK_STREAM (tcp)
32 ENVIRONMENT VARIABLES
34 CONNREDIR_ORIG_IP
35 CONNREDIR_ORIG_PORT
36 CONNREDIR_TO
37 CONNREDIR_TO_IP
38 CONNREDIR_TO_PORT
40 COMPILE
42 gcc -D_GNU_SOURCE -ldl -shared -fPIC -o connredir.so connredir.c
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <sys/types.h>
48 #include <sys/socket.h>
49 #include <netinet/in.h>
50 #include <arpa/inet.h>
51 #include <dlfcn.h>
52 #include <errno.h>
54 void _connredir_ip_parse_error(const char* s)
56 fprintf(stderr, "connredir: failed to parse ip address: %s\n", s);
59 int connect(int sockfd, const struct sockaddr_in *orig_sockaddr, socklen_t addrlen)
61 struct in_addr orig_ip;
62 char *orig_ip_str;
63 char *orig_port_str;
64 in_port_t orig_port = 0;
66 char *redir_to;
68 char *to_ip_str;
69 struct in_addr to_ip;
70 char *to_port_str;
71 in_port_t to_port = 0;
73 struct sockaddr_in to_sockaddr;
74 int (*orig_connect)(int, const struct sockaddr_in *, socklen_t) = dlsym(RTLD_NEXT, "connect");
77 if(orig_sockaddr->sin_family != AF_INET) goto stdlib;
79 orig_ip_str = getenv("CONNREDIR_ORIG_IP");
80 if(orig_ip_str == NULL) goto stdlib;
82 if(inet_aton(orig_ip_str, &orig_ip) == 0)
84 _connredir_ip_parse_error(orig_ip_str);
85 goto stdlib;
87 if(ntohl(orig_sockaddr->sin_addr.s_addr) != ntohl(orig_ip.s_addr)) goto stdlib;
89 orig_port_str = getenv("CONNREDIR_ORIG_PORT");
90 if(orig_port_str != NULL) orig_port = atoi(orig_port_str);
91 if(orig_port != 0 && orig_port != ntohs(orig_sockaddr->sin_port)) goto stdlib;
94 redir_to = getenv("CONNREDIR_TO");
95 if(redir_to != NULL)
97 if(strcmp(redir_to, "stdout")==0)
99 if(dup2(fileno(stdout), sockfd) == -1) { perror("connredir: dup2"); goto stdlib; }
100 fprintf(stderr, "connredir: redirecting %s:%d -> stdout\n", inet_ntoa(orig_sockaddr->sin_addr), ntohs(orig_sockaddr->sin_port));
101 return 0;
103 else
105 fprintf(stderr, "connredir: unknown redirection '%s'\n", redir_to);
106 goto stdlib;
110 to_ip_str = getenv("CONNREDIR_TO_IP");
111 if(to_ip_str == NULL) goto stdlib;
113 if(inet_aton(to_ip_str, &to_ip) == 0)
115 _connredir_ip_parse_error(to_ip_str);
116 goto stdlib;
119 to_port_str = getenv("CONNREDIR_TO_PORT");
120 if(to_port_str != NULL) to_port = atoi(to_port_str);
122 to_sockaddr.sin_family = AF_INET;
123 to_sockaddr.sin_port = to_port == 0 ? orig_sockaddr->sin_port : htons(to_port);
124 to_sockaddr.sin_addr = to_ip;
126 fprintf(stderr, "connredir: redirecting %s:%d -> ", inet_ntoa(orig_sockaddr->sin_addr), ntohs(orig_sockaddr->sin_port));
127 fprintf(stderr, "%s:%d\n", inet_ntoa(to_sockaddr.sin_addr), ntohs(to_sockaddr.sin_port));
128 orig_sockaddr = &to_sockaddr;
130 stdlib:
131 return orig_connect(sockfd, orig_sockaddr, addrlen);