VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/NAT/portfwd.c@ 49024

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

portfwd.c: typo: portfwd_rule_add_del(, SOCKET -> int) parameter used in term of bool to add (2) isn't 0 and to delete otherwise, not as file descriptor.

  • 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 "portfwd.h"
4
5#ifndef RT_OS_WINDOWS
6#include <arpa/inet.h>
7#include <poll.h>
8#else
9# include "winpoll.h"
10#endif
11#include <stdio.h>
12#include <string.h>
13
14#include "proxy.h"
15#include "proxy_pollmgr.h"
16#include "pxremap.h"
17
18#include "lwip/netif.h"
19
20
21struct portfwd_msg {
22 struct fwspec *fwspec;
23 int add;
24};
25
26
27static int portfwd_chan_send(struct portfwd_msg *);
28static int portfwd_rule_add_del(struct fwspec *, int);
29static int portfwd_pmgr_chan(struct pollmgr_handler *, SOCKET, int);
30
31
32static struct pollmgr_handler portfwd_pmgr_chan_hdl;
33
34
35void
36portfwd_init(void)
37{
38 portfwd_pmgr_chan_hdl.callback = portfwd_pmgr_chan;
39 portfwd_pmgr_chan_hdl.data = NULL;
40 portfwd_pmgr_chan_hdl.slot = -1;
41 pollmgr_add_chan(POLLMGR_CHAN_PORTFWD, &portfwd_pmgr_chan_hdl);
42
43 /* add preconfigured forwarders */
44 fwtcp_init();
45 fwudp_init();
46}
47
48
49static int
50portfwd_chan_send(struct portfwd_msg *msg)
51{
52 ssize_t nsent;
53
54 nsent = pollmgr_chan_send(POLLMGR_CHAN_PORTFWD, &msg, sizeof(msg));
55 if (nsent < 0) {
56 free(msg);
57 return -1;
58 }
59
60 return 0;
61}
62
63
64static int
65portfwd_rule_add_del(struct fwspec *fwspec, int add)
66{
67 struct portfwd_msg *msg;
68
69 msg = (struct portfwd_msg *)malloc(sizeof(*msg));
70 if (msg == NULL) {
71 return -1;
72 }
73
74 msg->fwspec = fwspec;
75 msg->add = add;
76
77 return portfwd_chan_send(msg);
78}
79
80
81int
82portfwd_rule_add(struct fwspec *fwspec)
83{
84 return portfwd_rule_add_del(fwspec, 1);
85}
86
87
88int
89portfwd_rule_del(struct fwspec *fwspec)
90{
91 return portfwd_rule_add_del(fwspec, 0);
92}
93
94
95/**
96 * POLLMGR_CHAN_PORTFWD handler.
97 */
98static int
99portfwd_pmgr_chan(struct pollmgr_handler *handler, SOCKET fd, int revents)
100{
101 void *ptr = pollmgr_chan_recv_ptr(handler, fd, revents);
102 struct portfwd_msg *msg = (struct portfwd_msg *)ptr;
103
104 if (msg->fwspec->stype == SOCK_STREAM) {
105 if (msg->add) {
106 fwtcp_add(msg->fwspec);
107 }
108 else {
109 fwtcp_del(msg->fwspec);
110 }
111 }
112 else { /* SOCK_DGRAM */
113 if (msg->add) {
114 fwudp_add(msg->fwspec);
115 }
116 else {
117 fwudp_del(msg->fwspec);
118 }
119 }
120
121 free(msg->fwspec);
122 free(msg);
123
124 return POLLIN;
125}
126
127
128
129#ifndef RT_OS_WINDOWS
130int
131fwspec_set(struct fwspec *fwspec, int sdom, int stype,
132 const char *src_addr_str, uint16_t src_port,
133 const char *dst_addr_str, uint16_t dst_port)
134{
135 int status;
136 int saf;
137 void *src_addr, *dst_addr;
138
139 LWIP_ASSERT1(sdom == PF_INET || sdom == PF_INET6);
140 LWIP_ASSERT1(stype == SOCK_STREAM || stype == SOCK_DGRAM);
141
142 fwspec->sdom = sdom;
143 fwspec->stype = stype;
144
145 if (sdom == PF_INET) {
146 struct sockaddr_in *src = &fwspec->src.sin;
147 struct sockaddr_in *dst = &fwspec->dst.sin;
148
149 saf = AF_INET;
150
151 src->sin_family = saf;
152#if HAVE_SA_LEN
153 src->sin_len = sizeof(*src);
154#endif
155 src->sin_port = htons(src_port);
156 src_addr = &src->sin_addr;
157
158 dst->sin_family = saf;
159#if HAVE_SA_LEN
160 dst->sin_len = sizeof(*dst);
161#endif
162 dst->sin_port = htons(dst_port);
163 dst_addr = &dst->sin_addr;
164 }
165 else { /* PF_INET6 */
166 struct sockaddr_in6 *src = &fwspec->src.sin6;
167 struct sockaddr_in6 *dst = &fwspec->dst.sin6;
168
169 saf = AF_INET6;
170
171 src->sin6_family = saf;
172#if HAVE_SA_LEN
173 src->sin6_len = sizeof(*src);
174#endif
175 src->sin6_port = htons(src_port);
176 src_addr = &src->sin6_addr;
177
178 dst->sin6_family = saf;
179#if HAVE_SA_LEN
180 dst->sin6_len = sizeof(*dst);
181#endif
182 dst->sin6_port = htons(dst_port);
183 dst_addr = &dst->sin6_addr;
184 }
185
186 status = inet_pton(saf, src_addr_str, src_addr);
187 LWIP_ASSERT1(status >= 0);
188 if (status == 0) {
189 DPRINTF(("bad address: %s\n", src_addr_str));
190 return -1;
191 }
192
193 status = inet_pton(saf, dst_addr_str, dst_addr);
194 LWIP_ASSERT1(status >= 0);
195 if (status == 0) {
196 DPRINTF(("bad address: %s\n", dst_addr_str));
197 return -1;
198 }
199
200 return 0;
201}
202#else /* RT_OS_WINDOWS */
203/**
204 * Windows only provides inet_pton() since Vista, but XP already has
205 * WSAStringToAddressA() that does what we want (NB: its AddressString
206 * argument is not declared const).
207 */
208int
209fwspec_set(struct fwspec *fwspec, int sdom, int stype,
210 const char *src_addr_str, uint16_t src_port,
211 const char *dst_addr_str, uint16_t dst_port)
212{
213 int saf;
214 int socklen;
215 int status;
216
217 LWIP_ASSERT1(sdom == PF_INET || sdom == PF_INET6);
218 LWIP_ASSERT1(stype == SOCK_STREAM || stype == SOCK_DGRAM);
219
220 fwspec->sdom = sdom;
221 fwspec->stype = stype;
222
223 saf = (sdom == PF_INET) ? AF_INET : AF_INET6;
224
225 socklen = sizeof(fwspec->src);
226 fwspec->src.sa.sa_family = saf; /* see "Remarks" WSAStringToAddress */
227 status = WSAStringToAddressA((char *)src_addr_str, saf, NULL,
228 &fwspec->src.sa, &socklen);
229 if (status == SOCKET_ERROR) {
230 return -1;
231 }
232
233 if (fwspec->src.sa.sa_family != saf) {
234 return -1;
235 }
236
237 fwspec->dst.sa.sa_family = saf;
238 socklen = sizeof(fwspec->dst);
239 status = WSAStringToAddressA((char *)dst_addr_str, saf, NULL,
240 &fwspec->dst.sa, &socklen);
241 if (status == SOCKET_ERROR) {
242 return -1;
243 }
244 if (fwspec->dst.sa.sa_family != saf) {
245 return -1;
246 }
247
248 if (sdom == PF_INET) {
249 fwspec->src.sin.sin_port = htons(src_port);
250 fwspec->dst.sin.sin_port = htons(dst_port);
251 }
252 else { /* PF_INET6 */
253 fwspec->src.sin6.sin6_port = htons(src_port);
254 fwspec->dst.sin6.sin6_port = htons(dst_port);
255 }
256
257 return 0;
258}
259#endif /* RT_OS_WINDOWS */
260
261
262int
263fwspec_equal(struct fwspec *a, struct fwspec *b)
264{
265 LWIP_ASSERT1(a != NULL);
266 LWIP_ASSERT1(b != NULL);
267
268 if (a->sdom != b->sdom || a->stype != b->stype) {
269 return 0;
270 }
271
272 if (a->sdom == PF_INET) {
273 return a->src.sin.sin_port == b->src.sin.sin_port
274 && a->dst.sin.sin_port == b->dst.sin.sin_port
275 && a->src.sin.sin_addr.s_addr == b->src.sin.sin_addr.s_addr
276 && a->dst.sin.sin_addr.s_addr == b->dst.sin.sin_addr.s_addr;
277 }
278 else { /* PF_INET6 */
279 return a->src.sin6.sin6_port == b->src.sin6.sin6_port
280 && a->dst.sin6.sin6_port == b->dst.sin6.sin6_port
281 && IN6_ARE_ADDR_EQUAL(&a->src.sin6.sin6_addr, &b->src.sin6.sin6_addr)
282 && IN6_ARE_ADDR_EQUAL(&a->dst.sin6.sin6_addr, &b->dst.sin6.sin6_addr);
283 }
284}
285
286
287/**
288 * Set fwdsrc to the IP address of the peer.
289 *
290 * For port-forwarded connections originating from hosts loopback the
291 * source address is set to the address of one of lwIP interfaces.
292 *
293 * Currently we only have one interface so there's not much logic
294 * here. In the future we might need to additionally consult fwspec
295 * and routing table to determine which netif is used for connections
296 * to the specified guest.
297 */
298int
299fwany_ipX_addr_set_src(ipX_addr_t *fwdsrc, const struct sockaddr *peer)
300{
301 int mapping;
302
303 if (peer->sa_family == AF_INET) {
304 const struct sockaddr_in *peer4 = (const struct sockaddr_in *)peer;
305 ip_addr_t peerip4;
306
307 peerip4.addr = peer4->sin_addr.s_addr;
308 mapping = pxremap_inbound_ip4(&fwdsrc->ip4, &peerip4);
309 }
310 else if (peer->sa_family == AF_INET6) {
311 const struct sockaddr_in6 *peer6 = (const struct sockaddr_in6 *)peer;
312 ip6_addr_t peerip6;
313
314 memcpy(&peerip6, &peer6->sin6_addr, sizeof(ip6_addr_t));
315 mapping = pxremap_inbound_ip6(&fwdsrc->ip6, &peerip6);
316 }
317 else {
318 mapping = PXREMAP_FAILED;
319 }
320
321 return mapping;
322}
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