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");