VirtualBox

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

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

Move proxy sources from Devices/Network/lwip-new/vbox
to NetworkServices/NAT where they belong.

  • Property svn:eol-style set to native
File size: 5.9 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 "proxytest.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 *, SOCKET);
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
129int
130fwspec_set(struct fwspec *fwspec, int sdom, int stype,
131 const char *src_addr_str, uint16_t src_port,
132 const char *dst_addr_str, uint16_t dst_port)
133{
134 int status;
135 int saf;
136 void *src_addr, *dst_addr;
137
138 LWIP_ASSERT1(sdom == PF_INET || sdom == PF_INET6);
139 LWIP_ASSERT1(stype == SOCK_STREAM || stype == SOCK_DGRAM);
140
141 fwspec->sdom = sdom;
142 fwspec->stype = stype;
143
144 if (sdom == PF_INET) {
145 struct sockaddr_in *src = &fwspec->src.sin;
146 struct sockaddr_in *dst = &fwspec->dst.sin;
147
148 saf = AF_INET;
149
150 src->sin_family = saf;
151#if HAVE_SA_LEN
152 src->sin_len = sizeof(*src);
153#endif
154 src->sin_port = htons(src_port);
155 src_addr = &src->sin_addr;
156
157 dst->sin_family = saf;
158#if HAVE_SA_LEN
159 dst->sin_len = sizeof(*dst);
160#endif
161 dst->sin_port = htons(dst_port);
162 dst_addr = &dst->sin_addr;
163 }
164 else { /* PF_INET6 */
165 struct sockaddr_in6 *src = &fwspec->src.sin6;
166 struct sockaddr_in6 *dst = &fwspec->dst.sin6;
167
168 saf = AF_INET6;
169
170 src->sin6_family = saf;
171#if HAVE_SA_LEN
172 src->sin6_len = sizeof(*src);
173#endif
174 src->sin6_port = htons(src_port);
175 src_addr = &src->sin6_addr;
176
177 dst->sin6_family = saf;
178#if HAVE_SA_LEN
179 dst->sin6_len = sizeof(*dst);
180#endif
181 dst->sin6_port = htons(dst_port);
182 dst_addr = &dst->sin6_addr;
183 }
184
185 status = inet_pton(saf, src_addr_str, src_addr);
186 LWIP_ASSERT1(status >= 0);
187 if (status == 0) {
188 DPRINTF(("bad address: %s\n", src_addr_str));
189 return -1;
190 }
191
192 status = inet_pton(saf, dst_addr_str, dst_addr);
193 LWIP_ASSERT1(status >= 0);
194 if (status == 0) {
195 DPRINTF(("bad address: %s\n", dst_addr_str));
196 return -1;
197 }
198
199 return 0;
200}
201
202
203int
204fwspec_equal(struct fwspec *a, struct fwspec *b)
205{
206 LWIP_ASSERT1(a != NULL);
207 LWIP_ASSERT1(b != NULL);
208
209 if (a->sdom != b->sdom || a->stype != b->stype) {
210 return 0;
211 }
212
213 if (a->sdom == PF_INET) {
214 return a->src.sin.sin_port == b->src.sin.sin_port
215 && a->dst.sin.sin_port == b->dst.sin.sin_port
216 && a->src.sin.sin_addr.s_addr == b->src.sin.sin_addr.s_addr
217 && a->dst.sin.sin_addr.s_addr == b->dst.sin.sin_addr.s_addr;
218 }
219 else { /* PF_INET6 */
220 return a->src.sin6.sin6_port == b->src.sin6.sin6_port
221 && a->dst.sin6.sin6_port == b->dst.sin6.sin6_port
222 && IN6_ARE_ADDR_EQUAL(&a->src.sin6.sin6_addr, &b->src.sin6.sin6_addr)
223 && IN6_ARE_ADDR_EQUAL(&a->dst.sin6.sin6_addr, &b->dst.sin6.sin6_addr);
224 }
225}
226
227
228/**
229 * Set fwdsrc to the IP address of the peer.
230 *
231 * For port-forwarded connections originating from hosts loopback the
232 * source address is set to the address of one of lwIP interfaces.
233 *
234 * Currently we only have one interface so there's not much logic
235 * here. In the future we might need to additionally consult fwspec
236 * and routing table to determine which netif is used for connections
237 * to the specified guest.
238 */
239int
240fwany_ipX_addr_set_src(ipX_addr_t *fwdsrc, const struct sockaddr *peer)
241{
242 int mapping;
243
244 if (peer->sa_family == AF_INET) {
245 const struct sockaddr_in *peer4 = (const struct sockaddr_in *)peer;
246 ip_addr_t peerip4;
247
248 peerip4.addr = peer4->sin_addr.s_addr;
249 mapping = pxremap_inbound_ip4(&fwdsrc->ip4, &peerip4);
250 }
251 else if (peer->sa_family == AF_INET6) {
252 const struct sockaddr_in6 *peer6 = (const struct sockaddr_in6 *)peer;
253 ip6_addr_t peerip6;
254
255 memcpy(&peerip6, &peer6->sin6_addr, sizeof(ip6_addr_t));
256 mapping = pxremap_inbound_ip6(&fwdsrc->ip6, &peerip6);
257 }
258 else {
259 mapping = PXREMAP_FAILED;
260 }
261
262 return mapping;
263}
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