4 * Sample program to be used as a transparent proxy.
6 * Must be executed with permission enough to do an ioctl on /dev/ipl
7 * or equivalent. This is just a sample and is only alpha quality.
8 * - Darren Reed (8 April 1996)
14 #include <sys/types.h>
16 #include <sys/syslog.h>
17 #include <sys/socket.h>
18 #include <sys/ioctl.h>
19 #include <netinet/in.h>
21 #include "netinet/ip_compat.h"
22 #include "netinet/ip_fil.h"
23 #include "netinet/ip_nat.h"
24 #include "netinet/ipl.h"
26 #define RELAY_BUFSZ 8192
28 char ibuff[RELAY_BUFSZ];
29 char obuff[RELAY_BUFSZ];
31 int relay(ifd, ofd, rfd)
35 char *irh, *irt, *rrh, *rrt;
36 char *iwh, *iwt, *rwh, *rwt;
52 if (irh < (ibuff + RELAY_BUFSZ))
56 if (iwh < (obuff + RELAY_BUFSZ))
59 switch ((n = select(nfd + 1, &rfds, &wfds, NULL, NULL)))
65 if (FD_ISSET(ifd, &rfds)) {
66 rw = read(ifd, irh, ibuff + RELAY_BUFSZ - irh);
74 if (n && FD_ISSET(ofd, &wfds)) {
75 rw = write(ofd, iwt, iwh - iwt);
81 if (n && FD_ISSET(rfd, &rfds)) {
82 rw = read(rfd, iwh, obuff + RELAY_BUFSZ - iwh);
90 if (n && FD_ISSET(rfd, &wfds)) {
91 rw = write(rfd, irt, irh - irt);
109 struct sockaddr_in sin;
112 natlookup_t *nlp = &nl;
113 int fd, sl = sizeof(sl), se;
115 openlog(argv[0], LOG_PID|LOG_NDELAY, LOG_DAEMON);
116 if ((fd = open(IPNAT_NAME, O_RDONLY)) == -1) {
120 syslog(LOG_ERR, "open: %m\n");
124 bzero(&obj, sizeof(obj));
125 obj.ipfo_rev = IPFILTER_VERSION;
126 obj.ipfo_size = sizeof(nl);
128 obj.ipfo_type = IPFOBJ_NATLOOKUP;
130 bzero(&nl, sizeof(nl));
131 nl.nl_flags = IPN_TCP;
133 bzero(&sin, sizeof(sin));
134 sin.sin_family = AF_INET;
136 if (getsockname(0, (struct sockaddr *)&sin, &sl) == -1) {
138 perror("getsockname");
140 syslog(LOG_ERR, "getsockname: %m\n");
143 nl.nl_inip.s_addr = sin.sin_addr.s_addr;
144 nl.nl_inport = sin.sin_port;
147 bzero(&sin, sizeof(sin));
148 sin.sin_family = AF_INET;
150 if (getpeername(0, (struct sockaddr *)&sin, &sl) == -1) {
152 perror("getpeername");
154 syslog(LOG_ERR, "getpeername: %m\n");
157 nl.nl_outip.s_addr = sin.sin_addr.s_addr;
158 nl.nl_outport = sin.sin_port;
161 if (ioctl(fd, SIOCGNATL, &obj) == -1) {
165 syslog(LOG_ERR, "ioctl: %m\n");
169 sin.sin_port = nl.nl_realport;
170 sin.sin_addr = nl.nl_realip;
173 fd = socket(AF_INET, SOCK_STREAM, 0);
174 if (connect(fd, (struct sockaddr *)&sin, sl) == -1) {
178 syslog(LOG_ERR, "connect: %m\n");
182 (void) ioctl(fd, F_SETFL, ioctl(fd, F_GETFL, 0)|O_NONBLOCK);
183 (void) ioctl(0, F_SETFL, ioctl(fd, F_GETFL, 0)|O_NONBLOCK);
184 (void) ioctl(1, F_SETFL, ioctl(fd, F_GETFL, 0)|O_NONBLOCK);
186 syslog(LOG_NOTICE, "connected to %s,%d\n", inet_ntoa(sin.sin_addr),
187 ntohs(sin.sin_port));
188 if (relay(0, 1, fd) == -1) {
192 syslog(LOG_ERR, "relay: %m\n");