VirtualBox

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

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

NAT/Net: #define LOG_GROUP LOG_GROUP_NAT_SERVICE

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