1 /*
2  * Sample transparent proxy program.
3  *
4  * Sample implementation of a program which intercepts a TCP connectiona and
5  * just echos all data back to the origin.  Written to work via inetd as a
6  * "nonwait" program running as root; ie.
7  * tcpmux          stream  tcp     nowait root /usr/local/bin/proxy proxy
8  * with a NAT rue like this:
9  * rdr smc0 0/0 port 80 -> 127.0.0.1/32 port 1
10  */
11 #include <stdio.h>
12 #include <string.h>
13 #include <fcntl.h>
14 #include <syslog.h>
15 #if !defined(__SVR4) && !defined(__svr4__)
16 #include <strings.h>
17 #else
18 #include <sys/byteorder.h>
19 #endif
20 #include <sys/types.h>
21 #include <sys/time.h>
22 #include <sys/param.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <stddef.h>
26 #include <sys/socket.h>
27 #include <sys/ioctl.h>
28 #if defined(sun) && (defined(__svr4__) || defined(__SVR4))
29 # include <sys/ioccom.h>
30 # include <sys/sysmacros.h>
31 #endif
32 #include <netinet/in.h>
33 #include <netinet/in_systm.h>
34 #include <netinet/ip.h>
35 #include <netinet/tcp.h>
36 #include <net/if.h>
37 #include <netdb.h>
38 #include <arpa/nameser.h>
39 #include <arpa/inet.h>
40 #include <resolv.h>
41 #include <ctype.h>
42 #include "netinet/ip_compat.h"
43 #include "netinet/ip_fil.h"
44 #include "netinet/ip_proxy.h"
45 #include "netinet/ip_nat.h"
46 
47 
48 main(argc, argv)
49 int argc;
50 char *argv[];
51 {
52 	struct	sockaddr_in	sin, sloc, sout;
53 	natlookup_t	natlook;
54 	char	buffer[512];
55 	int	namelen, fd, n;
56 
57 	/*
58 	 * get IP# and port # of the remote end of the connection (at the
59 	 * origin).
60 	 */
61 	namelen = sizeof(sin);
62 	if (getpeername(0, (struct sockaddr *)&sin, &namelen) == -1) {
63 		perror("getpeername");
64 		exit(-1);
65 	}
66 
67 	/*
68 	 * get IP# and port # of the local end of the connection (at the
69 	 * man-in-the-middle).
70 	 */
71 	namelen = sizeof(sin);
72 	if (getsockname(0, (struct sockaddr *)&sloc, &namelen) == -1) {
73 		perror("getsockname");
74 		exit(-1);
75 	}
76 
77 	/*
78 	 * Build up the NAT natlookup structure.
79 	 */
80 	bzero((char *)&natlook, sizeof(natlook));
81 	natlook.nl_outip = sin.sin_addr;
82 	natlook.nl_inip = sloc.sin_addr;
83 	natlook.nl_flags = IPN_TCP;
84 	natlook.nl_outport = sin.sin_port;
85 	natlook.nl_inport = sloc.sin_port;
86 
87 	/*
88 	 * Open the NAT device and lookup the mapping pair.
89 	 */
90 	fd = open(IPL_NAT, O_RDONLY);
91 	if (ioctl(fd, SIOCGNATL, &natlook) == -1) {
92 		perror("ioctl");
93 		exit(-1);
94 	}
95 	close(fd);
96 	/*
97 	 * Log it
98 	 */
99 	syslog(LOG_DAEMON|LOG_INFO, "connect to %s,%d",
100 		inet_ntoa(natlook.nl_realip), ntohs(natlook.nl_realport));
101 	printf("connect to %s,%d\n",
102 		inet_ntoa(natlook.nl_realip), ntohs(natlook.nl_realport));
103 
104 	/*
105 	 * Just echo data read in from stdin to stdout
106 	 */
107 	while ((n = read(0, buffer, sizeof(buffer))) > 0)
108 		if (write(1, buffer, n) != n)
109 			break;
110 	close(0);
111 }
112