2 * Sample program to be used as a transparent proxy.
4 * Must be executed with permission enough to do an ioctl on /dev/ipl
5 * or equivalent. This is just a sample and is only alpha quality.
6 * - Darren Reed (8 April 1996)
11 #include <sys/types.h>
13 #include <sys/errno.h>
14 #include <sys/syslog.h>
15 #include <sys/ioctl.h>
16 #include <netinet/in.h>
18 #include <sys/socket.h>
19 #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105000000)
25 #define RELAY_BUFSZ 8192
27 char ibuff
[RELAY_BUFSZ
];
28 char obuff
[RELAY_BUFSZ
];
30 int relay(ifd
, ofd
, rfd
)
38 char *irh
, *irt
, *rrh
, *rrt
;
39 char *iwh
, *iwt
, *rwh
, *rwt
;
58 set
[0].events
= (iwh
< (obuff
+ RELAY_BUFSZ
) ? POLLIN
: 0) |
59 (irh
> irt
? POLLOUT
: 0);
60 set
[1].events
= (irh
< (ibuff
+ RELAY_BUFSZ
) ? POLLIN
: 0);
61 set
[2].events
= (iwh
> iwt
? POLLOUT
: 0);
63 switch ((n
= poll(set
, 3, INFTIM
)))
69 if (irh
< (ibuff
+ RELAY_BUFSZ
))
73 if (iwh
< (obuff
+ RELAY_BUFSZ
))
76 switch ((n
= select(nfd
+ 1, &rfds
, &wfds
, NULL
, NULL
)))
84 if (set
[1].revents
& POLLIN
)
86 if (FD_ISSET(ifd
, &rfds
))
89 rw
= read(ifd
, irh
, ibuff
+ RELAY_BUFSZ
- irh
);
98 if (set
[2].revents
& POLLOUT
)
100 if (n
&& FD_ISSET(ofd
, &wfds
))
103 rw
= write(ofd
, iwt
, iwh
- iwt
);
110 if (set
[0].revents
& POLLIN
)
112 if (n
&& FD_ISSET(rfd
, &rfds
))
115 rw
= read(rfd
, iwh
, obuff
+ RELAY_BUFSZ
- iwh
);
124 if (set
[0].revents
& POLLOUT
)
126 if (n
&& FD_ISSET(rfd
, &wfds
))
129 rw
= write(rfd
, irt
, irh
- irt
);
147 struct sockaddr_in sin
;
149 natlookup_t
*nlp
= &nl
;
150 int fd
, sl
= sizeof(sl
), se
;
152 openlog(argv
[0], LOG_PID
|LOG_NDELAY
, LOG_DAEMON
);
153 if ((fd
= open("/dev/ipnat", O_RDONLY
)) == -1) {
157 syslog(LOG_ERR
, "open: %m\n");
161 bzero(&nl
, sizeof(nl
));
162 nl
.nl_flags
= IPN_TCP
;
164 bzero(&sin
, sizeof(sin
));
165 sin
.sin_family
= AF_INET
;
167 if (getsockname(0, (struct sockaddr
*)&sin
, &sl
) == -1) {
169 perror("getsockname");
171 syslog(LOG_ERR
, "getsockname: %m\n");
174 nl
.nl_inip
.s_addr
= sin
.sin_addr
.s_addr
;
175 nl
.nl_inport
= sin
.sin_port
;
178 bzero(&sin
, sizeof(sin
));
179 sin
.sin_family
= AF_INET
;
181 if (getpeername(0, (struct sockaddr
*)&sin
, &sl
) == -1) {
183 perror("getpeername");
185 syslog(LOG_ERR
, "getpeername: %m\n");
188 nl
.nl_outip
.s_addr
= sin
.sin_addr
.s_addr
;
189 nl
.nl_outport
= sin
.sin_port
;
192 if (ioctl(fd
, SIOCGNATL
, &nlp
) == -1) {
196 syslog(LOG_ERR
, "ioctl: %m\n");
200 sin
.sin_port
= nl
.nl_realport
;
201 sin
.sin_addr
= nl
.nl_realip
;
204 fd
= socket(AF_INET
, SOCK_STREAM
, 0);
205 if (connect(fd
, (struct sockaddr
*)&sin
, sl
) == -1) {
209 syslog(LOG_ERR
, "connect: %m\n");
213 (void) ioctl(fd
, F_SETFL
, ioctl(fd
, F_GETFL
, 0)|O_NONBLOCK
);
214 (void) ioctl(0, F_SETFL
, ioctl(fd
, F_GETFL
, 0)|O_NONBLOCK
);
215 (void) ioctl(1, F_SETFL
, ioctl(fd
, F_GETFL
, 0)|O_NONBLOCK
);
217 syslog(LOG_NOTICE
, "connected to %s,%d\n", inet_ntoa(sin
.sin_addr
),
218 ntohs(sin
.sin_port
));
219 if (relay(0, 1, fd
) == -1) {
223 syslog(LOG_ERR
, "relay: %m\n");