VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/NAT/fwtcp.c@ 49016

Last change on this file since 49016 was 49016, checked in by vboxsync, 11 years ago

Change vestigial names proxytest.* to proxy.*

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 7.6 KB
Line 
1/* -*- indent-tabs-mode: nil; -*- */
2#include "winutils.h"
3#include "proxy.h"
4#include "proxy_pollmgr.h"
5#include "portfwd.h"
6#include "pxtcp.h"
7
8#ifndef RT_OS_WINDOWS
9#include <sys/types.h>
10#include <sys/socket.h>
11#include <arpa/inet.h>
12#include <stdio.h>
13#include <poll.h>
14
15#include <err.h> /* BSD'ism */
16#else
17#include <stdio.h>
18#include "winpoll.h"
19#endif
20
21#include "lwip/opt.h"
22
23#include "lwip/sys.h"
24#include "lwip/tcpip.h"
25
26
27/**
28 */
29struct fwtcp {
30 /**
31 * Our poll manager handler.
32 */
33 struct pollmgr_handler pmhdl;
34
35 /**
36 * Forwarding specification.
37 */
38 struct fwspec fwspec;
39
40 /**
41 * Listening socket.
42 */
43 SOCKET sock;
44
45 /**
46 * Mailbox for new inbound connections.
47 *
48 * XXX: since we have single producer and single consumer we can
49 * use lockless ringbuf like for pxtcp.
50 */
51 sys_mbox_t connmbox;
52
53 struct tcpip_msg msg_connect;
54 struct tcpip_msg msg_delete;
55
56 /**
57 * Linked list entry.
58 */
59 struct fwtcp *next;
60};
61
62
63static struct fwtcp *fwtcp_create(struct fwspec *);
64
65/* poll manager callback for fwtcp listening socket */
66static int fwtcp_pmgr_listen(struct pollmgr_handler *, SOCKET, int);
67
68/* lwip thread callbacks called via proxy_lwip_post() */
69static void fwtcp_pcb_connect(void *);
70static void fwtcp_pcb_delete(void *);
71
72
73/**
74 * Linked list of active fwtcp forwarders.
75 */
76struct fwtcp *fwtcp_list = NULL;
77
78
79void
80fwtcp_init(void)
81{
82#if 0
83 struct fwspec fw_echo;
84 struct fwspec fw_daytime;
85 struct fwspec fw_chargen;
86 struct fwspec fw_ssh;
87
88
89#define FWSPEC_INIT_TCP4(fwspec, dst_port) do { \
90 int __status; \
91 __status = fwspec_set((fwspec), PF_INET, SOCK_STREAM, \
92 "0.0.0.0", 30000 + (dst_port), \
93 PROXY_GUEST_IPV4, (dst_port)); \
94 LWIP_ASSERT1(__status == 0); \
95 LWIP_UNUSED_ARG(__status); \
96 } while (0)
97
98 FWSPEC_INIT_TCP4(&fw_echo, 7);
99 FWSPEC_INIT_TCP4(&fw_daytime, 13);
100 FWSPEC_INIT_TCP4(&fw_chargen, 19);
101 FWSPEC_INIT_TCP4(&fw_ssh, 22);
102
103#undef FWSPEC_INIT_TCP4
104
105 fwtcp_add(&fw_echo);
106 fwtcp_add(&fw_daytime);
107 fwtcp_add(&fw_chargen);
108 fwtcp_add(&fw_ssh);
109#endif
110}
111
112
113void
114fwtcp_add(struct fwspec *fwspec)
115{
116 struct fwtcp *fwtcp;
117
118 fwtcp = fwtcp_create(fwspec);
119 if (fwtcp == NULL) {
120 DPRINTF0(("%s: failed to add rule for TCP ...\n", __func__));
121 return;
122 }
123
124 DPRINTF0(("%s\n", __func__));
125 /* fwtcp_create has put fwtcp on the linked list */
126}
127
128
129void
130fwtcp_del(struct fwspec *fwspec)
131{
132 struct fwtcp *fwtcp;
133 struct fwtcp **pprev;
134
135 for (pprev = &fwtcp_list; (fwtcp = *pprev) != NULL; pprev = &fwtcp->next) {
136 if (fwspec_equal(&fwtcp->fwspec, fwspec)) {
137 *pprev = fwtcp->next;
138 fwtcp->next = NULL;
139 break;
140 }
141 }
142
143 if (fwtcp == NULL) {
144 DPRINTF0(("%s: not found\n", __func__));
145 return;
146 }
147
148 DPRINTF0(("%s\n", __func__));
149
150 pollmgr_del_slot(fwtcp->pmhdl.slot);
151 fwtcp->pmhdl.slot = -1;
152
153 closesocket(fwtcp->sock);
154 fwtcp->sock = -1;
155
156 /* let pending msg_connect be processed before we delete fwtcp */
157 proxy_lwip_post(&fwtcp->msg_delete);
158}
159
160
161struct fwtcp *
162fwtcp_create(struct fwspec *fwspec)
163{
164 struct fwtcp *fwtcp;
165 SOCKET lsock;
166 int status;
167 err_t error;
168
169 lsock = proxy_bound_socket(fwspec->sdom, fwspec->stype, &fwspec->src.sa);
170 if (lsock == INVALID_SOCKET) {
171 perror("socket");
172 return NULL;
173 }
174
175 fwtcp = (struct fwtcp *)malloc(sizeof(*fwtcp));
176 if (fwtcp == NULL) {
177 closesocket(lsock);
178 return NULL;
179 }
180
181 fwtcp->pmhdl.callback = fwtcp_pmgr_listen;
182 fwtcp->pmhdl.data = (void *)fwtcp;
183 fwtcp->pmhdl.slot = -1;
184
185 fwtcp->sock = lsock;
186 fwtcp->fwspec = *fwspec; /* struct copy */
187
188 error = sys_mbox_new(&fwtcp->connmbox, 16);
189 if (error != ERR_OK) {
190 closesocket(lsock);
191 free(fwtcp);
192 return (NULL);
193 }
194
195#define CALLBACK_MSG(MSG, FUNC) \
196 do { \
197 fwtcp->MSG.type = TCPIP_MSG_CALLBACK_STATIC; \
198 fwtcp->MSG.sem = NULL; \
199 fwtcp->MSG.msg.cb.function = FUNC; \
200 fwtcp->MSG.msg.cb.ctx = (void *)fwtcp; \
201 } while (0)
202
203 CALLBACK_MSG(msg_connect, fwtcp_pcb_connect);
204 CALLBACK_MSG(msg_delete, fwtcp_pcb_delete);
205
206#undef CALLBACK_MSG
207
208 status = pollmgr_add(&fwtcp->pmhdl, fwtcp->sock, POLLIN);
209 if (status < 0) {
210 sys_mbox_free(&fwtcp->connmbox);
211 closesocket(lsock);
212 free(fwtcp);
213 return NULL;
214 }
215
216 fwtcp->next = fwtcp_list;
217 fwtcp_list = fwtcp;
218
219 return fwtcp;
220}
221
222
223int
224fwtcp_pmgr_listen(struct pollmgr_handler *handler, SOCKET fd, int revents)
225{
226 struct fwtcp *fwtcp;
227 struct sockaddr_storage ss;
228 socklen_t sslen;
229 void *peer_addr;
230 uint16_t peer_port;
231 struct pxtcp *pxtcp;
232 SOCKET newsock;
233 int status;
234 err_t error;
235
236 fwtcp = (struct fwtcp *)handler->data;
237 pxtcp = NULL;
238
239 LWIP_ASSERT1(fwtcp != NULL);
240 LWIP_ASSERT1(fd == fwtcp->sock);
241 LWIP_ASSERT1(revents == POLLIN);
242 LWIP_UNUSED_ARG(fd);
243 LWIP_UNUSED_ARG(revents);
244
245 LWIP_ASSERT1(sys_mbox_valid(&fwtcp->connmbox));
246
247 sslen = sizeof(ss);
248 newsock = accept(fwtcp->sock, (struct sockaddr *)&ss, &sslen);
249 if (newsock == INVALID_SOCKET) {
250 return POLLIN;
251 }
252
253
254 if (ss.ss_family == PF_INET) {
255 struct sockaddr_in *peer4 = (struct sockaddr_in *)&ss;
256 peer_addr = &peer4->sin_addr;
257 peer_port = peer4->sin_port;
258 }
259 else { /* PF_INET6 */
260 struct sockaddr_in6 *peer6 = (struct sockaddr_in6 *)&ss;
261 peer_addr = &peer6->sin6_addr;
262 peer_port = peer6->sin6_port;
263 }
264 peer_port = ntohs(peer_port);
265
266#if PLEASE_ABSTAIN_FROM_DPRINFING > 1 /* DPRINTF */ && !defined(RT_OS_WINDOWS)
267 {
268 char addrbuf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
269 const char *addrstr;
270
271 addrstr = inet_ntop(ss.ss_family, peer_addr, addrbuf, sizeof(addrbuf));
272 DPRINTF(("<--- TCP %s%s%s:%d\n",
273 ss.ss_family == AF_INET6 ? "[" : "",
274 addrstr,
275 ss.ss_family == AF_INET6 ? "]" : "",
276 peer_port));
277 }
278#endif /* DPRINTF */
279
280
281 pxtcp = pxtcp_create_forwarded(newsock);
282 if (pxtcp == NULL) {
283 proxy_reset_socket(newsock);
284 return POLLIN;
285 }
286
287 status = pxtcp_pmgr_add(pxtcp);
288 if (status < 0) {
289 pxtcp_cancel_forwarded(pxtcp);
290 return POLLIN;
291 }
292
293 error = sys_mbox_trypost(&fwtcp->connmbox, (void *)pxtcp);
294 if (error != ERR_OK) {
295 pxtcp_pmgr_del(pxtcp);
296 pxtcp_cancel_forwarded(pxtcp);
297 return POLLIN;
298 }
299
300 proxy_lwip_post(&fwtcp->msg_connect);
301 return POLLIN;
302}
303
304
305void
306fwtcp_pcb_connect(void *arg)
307{
308 struct fwtcp *fwtcp = (struct fwtcp *)arg;
309 struct pxtcp *pxtcp;
310 u32_t timo;
311
312 if (!sys_mbox_valid(&fwtcp->connmbox)) {
313 return;
314 }
315
316 pxtcp = NULL;
317 timo = sys_mbox_tryfetch(&fwtcp->connmbox, (void **)&pxtcp);
318 if (timo == SYS_MBOX_EMPTY) {
319 return;
320 }
321
322 LWIP_ASSERT1(pxtcp != NULL);
323
324 /* hand off to pxtcp */
325 pxtcp_pcb_connect(pxtcp, &fwtcp->fwspec);
326}
327
328
329static void
330fwtcp_pcb_delete(void *arg)
331{
332 struct fwtcp *fwtcp = (struct fwtcp *)arg;
333 void *data;
334 u32_t timo;
335
336 timo = sys_mbox_tryfetch(&fwtcp->connmbox, &data);
337 LWIP_ASSERT1(timo == SYS_MBOX_EMPTY);
338 LWIP_UNUSED_ARG(timo); /* only in assert */
339
340 sys_mbox_free(&fwtcp->connmbox);
341 free(fwtcp);
342}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette