]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ipfilter/relay.c
This commit was generated by cvs2svn to compensate for changes in r49187,
[FreeBSD/FreeBSD.git] / contrib / ipfilter / relay.c
1 /*
2  * Sample program to be used as a transparent proxy.
3  *
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)
7  */
8 #include <unistd.h>
9 #include <stdio.h>
10 #include <fcntl.h>
11 #include <sys/types.h>
12 #include <sys/time.h>
13 #include <sys/errno.h>
14 #include <sys/syslog.h>
15 #include <sys/ioctl.h>
16 #include <netinet/in.h>
17 #include <net/if.h>
18 #include <sys/socket.h>
19 #include "ip_nat.h"
20
21 #define RELAY_BUFSZ     8192
22
23 char    ibuff[RELAY_BUFSZ];
24 char    obuff[RELAY_BUFSZ];
25
26 int relay(ifd, ofd, rfd)
27 int ifd, ofd, rfd;
28 {
29         fd_set  rfds, wfds;
30         char    *irh, *irt, *rrh, *rrt;
31         char    *iwh, *iwt, *rwh, *rwt;
32         int     nfd, n, rw;
33
34         irh = irt = ibuff;
35         iwh = iwt = obuff;
36         nfd = ifd;
37         if (nfd < ofd)
38                 nfd = ofd;
39         if (nfd < rfd)
40                 nfd = rfd;
41
42         while (1) {
43                 FD_ZERO(&rfds);
44                 FD_ZERO(&wfds);
45                 if (irh > irt)
46                         FD_SET(rfd, &wfds);
47                 if (irh < (ibuff + RELAY_BUFSZ))
48                         FD_SET(ifd, &rfds);
49                 if (iwh > iwt)
50                         FD_SET(ofd, &wfds);
51                 if (iwh < (obuff + RELAY_BUFSZ))
52                         FD_SET(rfd, &rfds);
53
54                 switch ((n = select(nfd + 1, &rfds, &wfds, NULL, NULL)))
55                 {
56                 case -1 :
57                 case 0 :
58                         return -1;
59                 default :
60                         if (FD_ISSET(ifd, &rfds)) {
61                                 rw = read(ifd, irh, ibuff + RELAY_BUFSZ - irh);
62                                 if (rw == -1)
63                                         return -1;
64                                 if (rw == 0)
65                                         return 0;
66                                 irh += rw;
67                                 n--;
68                         }
69                         if (n && FD_ISSET(ofd, &wfds)) {
70                                 rw = write(ofd, iwt, iwh  - iwt);
71                                 if (rw == -1)
72                                         return -1;
73                                 iwt += rw;
74                                 n--;
75                         }
76                         if (n && FD_ISSET(rfd, &rfds)) {
77                                 rw = read(rfd, iwh, obuff + RELAY_BUFSZ - iwh);
78                                 if (rw == -1)
79                                         return -1;
80                                 if (rw == 0)
81                                         return 0;
82                                 iwh += rw;
83                                 n--;
84                         }
85                         if (n && FD_ISSET(rfd, &wfds)) {
86                                 rw = write(rfd, irt, irh  - irt);
87                                 if (rw == -1)
88                                         return -1;
89                                 irt += rw;
90                                 n--;
91                         }
92                         if (irh == irt)
93                                 irh = irt = ibuff;
94                         if (iwh == iwt)
95                                 iwh = iwt = obuff;
96                 }
97         }
98 }
99
100 main(argc, argv)
101 int argc;
102 char *argv[];
103 {
104         struct  sockaddr_in     sin;
105         natlookup_t     nl;
106         int     fd, sl = sizeof(sl), se;
107
108         openlog(argv[0], LOG_PID|LOG_NDELAY, LOG_DAEMON);
109         if ((fd = open("/dev/ipl", O_RDONLY)) == -1) {
110                 se = errno;
111                 perror("open");
112                 errno = se;
113                 syslog(LOG_ERR, "open: %m\n");
114                 exit(-1);
115         }
116
117         bzero(&sin, sizeof(sin));
118         sin.sin_family = AF_INET;
119         sl = sizeof(sin);
120         if (getsockname(0, (struct sockaddr *)&sin, &sl) == -1) {
121                 se = errno;
122                 perror("getsockname");
123                 errno = se;
124                 syslog(LOG_ERR, "getsockname: %m\n");
125                 exit(-1);
126         } else {
127                 nl.nl_inip.s_addr = sin.sin_addr.s_addr;
128                 nl.nl_inport = sin.sin_port;
129         }
130
131         bzero(&sin, sizeof(sin));
132         sin.sin_family = AF_INET;
133         sl = sizeof(sin);
134         if (getpeername(0, (struct sockaddr *)&sin, &sl) == -1) {
135                 se = errno;
136                 perror("getpeername");
137                 errno = se;
138                 syslog(LOG_ERR, "getpeername: %m\n");
139                 exit(-1);
140         } else {
141                 nl.nl_outip.s_addr = sin.sin_addr.s_addr;
142                 nl.nl_outport = sin.sin_port;
143         }
144
145         if (ioctl(fd, SIOCGNATL, &nl) == -1) {
146                 se = errno;
147                 perror("ioctl");
148                 errno = se;
149                 syslog(LOG_ERR, "ioctl: %m\n");
150                 exit(-1);
151         }
152
153         sin.sin_port = nl.nl_inport;
154         sin.sin_addr = nl.nl_inip;
155         sl = sizeof(sin);
156
157         fd = socket(AF_INET, SOCK_STREAM, 0);
158         if (connect(fd, (struct sockaddr *)&sin, sl) == -1) {
159                 se = errno;
160                 perror("connect");
161                 errno = se;
162                 syslog(LOG_ERR, "connect: %m\n");
163                 exit(-1);
164         }
165
166         (void) ioctl(fd, F_SETFL, ioctl(fd, F_GETFL, 0)|O_NONBLOCK);
167         (void) ioctl(0, F_SETFL, ioctl(fd, F_GETFL, 0)|O_NONBLOCK);
168         (void) ioctl(1, F_SETFL, ioctl(fd, F_GETFL, 0)|O_NONBLOCK);
169
170         syslog(LOG_NOTICE, "connected to %s,%d\n", inet_ntoa(sin.sin_addr),
171                 ntohs(sin.sin_port));
172         if (relay(0, 1, fd) == -1) {
173                 se = errno;
174                 perror("relay");
175                 errno = se;
176                 syslog(LOG_ERR, "relay: %m\n");
177                 exit(-1);
178         }
179         exit(0);
180 }