Various changes. Add configuration grammar to help text. Change to
[fwd] / forward.c
CommitLineData
e82f7154 1/* -*-c-*-
2 *
3 * $Id: forward.c,v 1.1 1999/07/01 08:56:23 mdw Exp $
4 *
5 * Port forwarding
6 *
7 * (c) 1999 Mark Wooding
8 */
9
10/*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of the `fw' port forwarder.
13 *
14 * `fw' is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * `fw' is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with `fw'; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29/*----- Revision history --------------------------------------------------*
30 *
31 * $Log: forward.c,v $
32 * Revision 1.1 1999/07/01 08:56:23 mdw
33 * Initial revision
34 *
35 */
36
37/*----- Header files ------------------------------------------------------*/
38
39#include "config.h"
40
41#include <errno.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45
46#include <sys/types.h>
47#include <sys/time.h>
48#include <unistd.h>
49
50#include <sys/socket.h>
51#include <netinet/in.h>
52#include <arpa/inet.h>
53
54#include <mLib/alloc.h>
55#include <mLib/conn.h>
56#include <mLib/sel.h>
57
58#include "chan.h"
59#include "forward.h"
60#include "fw.h"
61
62/*----- Data structures ---------------------------------------------------*/
63
64/* --- Port forwarding data --- */
65
66typedef struct fw {
67 int fd_a; /* Client's file descriptor */
68 int fd_b; /* Server's file descriptor */
69 unsigned state; /* Current state of the world */
70 conn c; /* Nonblocking connect to server */
71 chan ab; /* Channel from @a@ to @b@ */
72 chan ba; /* Channel from @b@ to @a@ */
73} fw;
74
75#define S_AB 1u /* Channel from @a@ to @b@ open */
76#define S_BA 2u /* Channel from @b@ to @a@ open */
77#define S_NOTCONN 4u /* Not connected to @b@ yet */
78#define S_NOTID 8u /* Not finished identification */
79
80/*----- Main code ---------------------------------------------------------*/
81
82/* --- @done@ --- *
83 *
84 * Arguments: @fw *f@ = pointer to forwarder
85 *
86 * Returns: ---
87 *
88 * Use: Tidies up a forwarder that nobody wants any more.
89 */
90
91static void done(fw *f)
92{
93 close(f->fd_a);
94 close(f->fd_b);
95 free(f);
96}
97
98/* --- @ident@ --- *
99 *
100 * Arguments: @void *vp@ = pointer to forwarder
101 *
102 * Returns: ---
103 *
104 * Use: Handles completion of client identification.
105 */
106
107static void ident(void *vp)
108{
109 fw *f = vp;
110 f->state &= ~S_NOTID;
111 if (!f->state)
112 done(f);
113}
114
115/* --- @closeba@ --- *
116 *
117 * Arguments: @void *vp@ = pointer to forwarder
118 *
119 * Returns: ---
120 *
121 * Use: Handles the closing of the %$b \rightarrow a$% channel.
122 */
123
124static void closeba(void *vp)
125{
126 fw *f = vp;
127 f->state &= ~S_BA;
128 if (!f->state)
129 done(f);
130}
131
132/* --- @closeab@ --- *
133 *
134 * Arguments: @void *vp@ = pointer to forwarder
135 *
136 * Returns: ---
137 *
138 * Use: Handles the closing of the %$a \rightarrow b$% channel.
139 */
140
141static void closeab(void *vp)
142{
143 fw *f = vp;
144 f->state &= ~S_AB;
145 if (!f->state)
146 done(f);
147}
148
149/* --- @go@ --- *
150 *
151 * Arguments: @int fd@ = newly connected socket
152 * @void *vp@ = pointer to forwarder
153 *
154 * Returns: ---
155 *
156 * Use: Completes the forwarder once the outbound connection is set
157 * up.
158 */
159
160static void go(int fd, void *vp)
161{
162 fw *f = vp;
163
164 /* --- If it all went tits-up, deal with that --- */
165
166 if (fd == -1) {
167 chan_close(&f->ab);
168 close(f->fd_a);
169 free(f);
170 return;
171 }
172
173 /* --- OK, finish configuring the forwarder --- */
174
175 f->fd_b = fd;
176 chan_dest(&f->ab, fd);
177 chan_open(&f->ba, fd, f->fd_a, closeba, f);
178 f->state |= S_BA;
179 f->state &= ~S_NOTCONN;
180}
181
182/* --- @forward@ --- *
183 *
184 * Arguments: @int fd@ = file descriptor attached to client
185 * @struct sockaddr_in *sin@ = pointer to destination address
186 * @const id_req *q@ = pointer to identification request block
187 *
188 * Returns: ---
189 *
190 * Use: Start a port forwarding job.
191 */
192
193void forward(int fd, struct sockaddr_in *sin, const id_req *q)
194{
195 fw *f;
196 int nfd;
197
198 /* --- Set up the new socket --- */
199
200 if ((nfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
201 return;
202
203 {
204 int opt = 1;
205 setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt));
206 setsockopt(nfd, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt));
207 }
208
209 /* --- Initialize the easy bits --- */
210
211 f = xmalloc(sizeof(*f));
212 f->fd_a = fd;
213 f->fd_b = -1;
214 f->state = S_NOTCONN | S_AB | S_NOTID;
215
216 /* --- Open the %$a \rightarrow b$% channel --- */
217
218 chan_open(&f->ab, fd, -1, closeab, f);
219 conn_init(&f->c, sel, nfd, (struct sockaddr *)sin, sizeof(*sin), go, f);
220 identify(q, ident, f);
221}
222
223/*----- That's all, folks -------------------------------------------------*/