VirtualBox

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

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

Few more missed -1 -> INVALID_SOCKET replacements.

  • 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#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 return;
83}
84
85
86void
87fwtcp_add(struct fwspec *fwspec)
88{
89 struct fwtcp *fwtcp;
90
91 fwtcp = fwtcp_create(fwspec);
92 if (fwtcp == NULL) {
93 DPRINTF0(("%s: failed to add rule for TCP ...\n", __func__));
94 return;
95 }
96
97 DPRINTF0(("%s\n", __func__));
98 /* fwtcp_create has put fwtcp on the linked list */
99}
100
101
102void
103fwtcp_del(struct fwspec *fwspec)
104{
105 struct fwtcp *fwtcp;
106 struct fwtcp **pprev;
107
108 for (pprev = &fwtcp_list; (fwtcp = *pprev) != NULL; pprev = &fwtcp->next) {
109 if (fwspec_equal(&fwtcp->fwspec, fwspec)) {
110 *pprev = fwtcp->next;
111 fwtcp->next = NULL;
112 break;
113 }
114 }
115
116 if (fwtcp == NULL) {
117 DPRINTF0(("%s: not found\n", __func__));
118 return;
119 }
120
121 DPRINTF0(("%s\n", __func__));
122
123 pollmgr_del_slot(fwtcp->pmhdl.slot);
124 fwtcp->pmhdl.slot = -1;
125
126 closesocket(fwtcp->sock);
127 fwtcp->sock = INVALID_SOCKET;
128
129 /* let pending msg_connect be processed before we delete fwtcp */
130 proxy_lwip_post(&fwtcp->msg_delete);
131}
132
133
134struct fwtcp *
135fwtcp_create(struct fwspec *fwspec)
136{
137 struct fwtcp *fwtcp;
138 SOCKET lsock;
139 int status;
140 err_t error;
141
142 lsock = proxy_bound_socket(fwspec->sdom, fwspec->stype, &fwspec->src.sa);
143 if (lsock == INVALID_SOCKET) {
144 perror("socket");
145 return NULL;
146 }
147
148 fwtcp = (struct fwtcp *)malloc(sizeof(*fwtcp));
149 if (fwtcp == NULL) {
150 closesocket(lsock);
151 return NULL;
152 }
153
154 fwtcp->pmhdl.callback = fwtcp_pmgr_listen;
155 fwtcp->pmhdl.data = (void *)fwtcp;
156 fwtcp->pmhdl.slot = -1;
157
158 fwtcp->sock = lsock;
159 fwtcp->fwspec = *fwspec; /* struct copy */
160
161 error = sys_mbox_new(&fwtcp->connmbox, 16);
162 if (error != ERR_OK) {
163 closesocket(lsock);
164 free(fwtcp);
165 return (NULL);
166 }
167
168#define CALLBACK_MSG(MSG, FUNC) \
169 do { \
170 fwtcp->MSG.type = TCPIP_MSG_CALLBACK_STATIC; \
171 fwtcp->MSG.sem = NULL; \
172 fwtcp->MSG.msg.cb.function = FUNC; \
173 fwtcp->MSG.msg.cb.ctx = (void *)fwtcp; \
174 } while (0)
175
176 CALLBACK_MSG(msg_connect, fwtcp_pcb_connect);
177 CALLBACK_MSG(msg_delete, fwtcp_pcb_delete);
178
179#undef CALLBACK_MSG
180
181 status = pollmgr_add(&fwtcp->pmhdl, fwtcp->sock, POLLIN);
182 if (status < 0) {
183 sys_mbox_free(&fwtcp->connmbox);
184 closesocket(lsock);
185 free(fwtcp);
186 return NULL;
187 }
188
189 fwtcp->next = fwtcp_list;
190 fwtcp_list = fwtcp;
191
192 return fwtcp;
193}
194
195
196int
197fwtcp_pmgr_listen(struct pollmgr_handler *handler, SOCKET fd, int revents)
198{
199 struct fwtcp *fwtcp;
200 struct sockaddr_storage ss;
201 socklen_t sslen;
202 void *peer_addr;
203 uint16_t peer_port;
204 struct pxtcp *pxtcp;
205 SOCKET newsock;
206 int status;
207 err_t error;
208
209 fwtcp = (struct fwtcp *)handler->data;
210 pxtcp = NULL;
211
212 LWIP_ASSERT1(fwtcp != NULL);
213 LWIP_ASSERT1(fd == fwtcp->sock);
214 LWIP_ASSERT1(revents == POLLIN);
215 LWIP_UNUSED_ARG(fd);
216 LWIP_UNUSED_ARG(revents);
217
218 LWIP_ASSERT1(sys_mbox_valid(&fwtcp->connmbox));
219
220 sslen = sizeof(ss);
221 newsock = accept(fwtcp->sock, (struct sockaddr *)&ss, &sslen);
222 if (newsock == INVALID_SOCKET) {
223 return POLLIN;
224 }
225
226
227 if (ss.ss_family == PF_INET) {
228 struct sockaddr_in *peer4 = (struct sockaddr_in *)&ss;
229 peer_addr = &peer4->sin_addr;
230 peer_port = peer4->sin_port;
231 }
232 else { /* PF_INET6 */
233 struct sockaddr_in6 *peer6 = (struct sockaddr_in6 *)&ss;
234 peer_addr = &peer6->sin6_addr;
235 peer_port = peer6->sin6_port;
236 }
237 peer_port = ntohs(peer_port);
238
239#if PLEASE_ABSTAIN_FROM_DPRINFING > 1 /* DPRINTF */ && !defined(RT_OS_WINDOWS)
240 {
241 char addrbuf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
242 const char *addrstr;
243
244 addrstr = inet_ntop(ss.ss_family, peer_addr, addrbuf, sizeof(addrbuf));
245 DPRINTF(("<--- TCP %s%s%s:%d\n",
246 ss.ss_family == AF_INET6 ? "[" : "",
247 addrstr,
248 ss.ss_family == AF_INET6 ? "]" : "",
249 peer_port));
250 }
251#endif /* DPRINTF */
252
253
254 pxtcp = pxtcp_create_forwarded(newsock);
255 if (pxtcp == NULL) {
256 proxy_reset_socket(newsock);
257 return POLLIN;
258 }
259
260 status = pxtcp_pmgr_add(pxtcp);
261 if (status < 0) {
262 pxtcp_cancel_forwarded(pxtcp);
263 return POLLIN;
264 }
265
266 error = sys_mbox_trypost(&fwtcp->connmbox, (void *)pxtcp);
267 if (error != ERR_OK) {
268 pxtcp_pmgr_del(pxtcp);
269 pxtcp_cancel_forwarded(pxtcp);
270 return POLLIN;
271 }
272
273 proxy_lwip_post(&fwtcp->msg_connect);
274 return POLLIN;
275}
276
277
278void
279fwtcp_pcb_connect(void *arg)
280{
281 struct fwtcp *fwtcp = (struct fwtcp *)arg;
282 struct pxtcp *pxtcp;
283 u32_t timo;
284
285 if (!sys_mbox_valid(&fwtcp->connmbox)) {
286 return;
287 }
288
289 pxtcp = NULL;
290 timo = sys_mbox_tryfetch(&fwtcp->connmbox, (void **)&pxtcp);
291 if (timo == SYS_MBOX_EMPTY) {
292 return;
293 }
294
295 LWIP_ASSERT1(pxtcp != NULL);
296
297 /* hand off to pxtcp */
298 pxtcp_pcb_connect(pxtcp, &fwtcp->fwspec);
299}
300
301
302static void
303fwtcp_pcb_delete(void *arg)
304{
305 struct fwtcp *fwtcp = (struct fwtcp *)arg;
306 void *data;
307 u32_t timo;
308
309 timo = sys_mbox_tryfetch(&fwtcp->connmbox, &data);
310 LWIP_ASSERT1(timo == SYS_MBOX_EMPTY);
311 LWIP_UNUSED_ARG(timo); /* only in assert */
312
313 sys_mbox_free(&fwtcp->connmbox);
314 free(fwtcp);
315}
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