VirtualBox

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

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

fwspec_set: use LogRel to log gai_strerror().

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 5.7 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 <netdb.h>
8#include <poll.h>
9#else
10# include "winpoll.h"
11#endif
12#include <stdio.h>
13#include <string.h>
14
15#include "proxy.h"
16#include "proxy_pollmgr.h"
17#include "pxremap.h"
18
19#include "lwip/netif.h"
20
21
22struct portfwd_msg {
23 struct fwspec *fwspec;
24 int add;
25};
26
27
28static int portfwd_chan_send(struct portfwd_msg *);
29static int portfwd_rule_add_del(struct fwspec *, int);
30static int portfwd_pmgr_chan(struct pollmgr_handler *, SOCKET, int);
31
32
33static struct pollmgr_handler portfwd_pmgr_chan_hdl;
34
35
36void
37portfwd_init(void)
38{
39 portfwd_pmgr_chan_hdl.callback = portfwd_pmgr_chan;
40 portfwd_pmgr_chan_hdl.data = NULL;
41 portfwd_pmgr_chan_hdl.slot = -1;
42 pollmgr_add_chan(POLLMGR_CHAN_PORTFWD, &portfwd_pmgr_chan_hdl);
43
44 /* add preconfigured forwarders */
45 fwtcp_init();
46 fwudp_init();
47}
48
49
50static int
51portfwd_chan_send(struct portfwd_msg *msg)
52{
53 ssize_t nsent;
54
55 nsent = pollmgr_chan_send(POLLMGR_CHAN_PORTFWD, &msg, sizeof(msg));
56 if (nsent < 0) {
57 free(msg);
58 return -1;
59 }
60
61 return 0;
62}
63
64
65static int
66portfwd_rule_add_del(struct fwspec *fwspec, int add)
67{
68 struct portfwd_msg *msg;
69
70 msg = (struct portfwd_msg *)malloc(sizeof(*msg));
71 if (msg == NULL) {
72 return -1;
73 }
74
75 msg->fwspec = fwspec;
76 msg->add = add;
77
78 return portfwd_chan_send(msg);
79}
80
81
82int
83portfwd_rule_add(struct fwspec *fwspec)
84{
85 return portfwd_rule_add_del(fwspec, 1);
86}
87
88
89int
90portfwd_rule_del(struct fwspec *fwspec)
91{
92 return portfwd_rule_add_del(fwspec, 0);
93}
94
95
96/**
97 * POLLMGR_CHAN_PORTFWD handler.
98 */
99static int
100portfwd_pmgr_chan(struct pollmgr_handler *handler, SOCKET fd, int revents)
101{
102 void *ptr = pollmgr_chan_recv_ptr(handler, fd, revents);
103 struct portfwd_msg *msg = (struct portfwd_msg *)ptr;
104
105 if (msg->fwspec->stype == SOCK_STREAM) {
106 if (msg->add) {
107 fwtcp_add(msg->fwspec);
108 }
109 else {
110 fwtcp_del(msg->fwspec);
111 }
112 }
113 else { /* SOCK_DGRAM */
114 if (msg->add) {
115 fwudp_add(msg->fwspec);
116 }
117 else {
118 fwudp_del(msg->fwspec);
119 }
120 }
121
122 free(msg->fwspec);
123 free(msg);
124
125 return POLLIN;
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 struct addrinfo hints;
135 struct addrinfo *ai;
136 int status;
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 memset(&hints, 0, sizeof(hints));
145 hints.ai_family = (sdom == PF_INET) ? AF_INET : AF_INET6;
146 hints.ai_socktype = stype;
147 hints.ai_flags = AI_NUMERICHOST;
148
149 status = getaddrinfo(src_addr_str, NULL, &hints, &ai);
150 if (status != 0) {
151 LogRel(("\"%s\": %s\n", src_addr_str, gai_strerror(status)));
152 return -1;
153 }
154 LWIP_ASSERT1(ai != NULL);
155 LWIP_ASSERT1(ai->ai_addrlen <= sizeof(fwspec->src));
156 memcpy(&fwspec->src, ai->ai_addr, ai->ai_addrlen);
157 freeaddrinfo(ai);
158 ai = NULL;
159
160 status = getaddrinfo(dst_addr_str, NULL, &hints, &ai);
161 if (status != 0) {
162 LogRel(("\"%s\": %s\n", dst_addr_str, gai_strerror(status)));
163 return -1;
164 }
165 LWIP_ASSERT1(ai != NULL);
166 LWIP_ASSERT1(ai->ai_addrlen <= sizeof(fwspec->dst));
167 memcpy(&fwspec->dst, ai->ai_addr, ai->ai_addrlen);
168 freeaddrinfo(ai);
169 ai = NULL;
170
171 if (sdom == PF_INET) {
172 fwspec->src.sin.sin_port = htons(src_port);
173 fwspec->dst.sin.sin_port = htons(dst_port);
174 }
175 else { /* PF_INET6 */
176 fwspec->src.sin6.sin6_port = htons(src_port);
177 fwspec->dst.sin6.sin6_port = htons(dst_port);
178 }
179
180 return 0;
181}
182
183
184int
185fwspec_equal(struct fwspec *a, struct fwspec *b)
186{
187 LWIP_ASSERT1(a != NULL);
188 LWIP_ASSERT1(b != NULL);
189
190 if (a->sdom != b->sdom || a->stype != b->stype) {
191 return 0;
192 }
193
194 if (a->sdom == PF_INET) {
195 return a->src.sin.sin_port == b->src.sin.sin_port
196 && a->dst.sin.sin_port == b->dst.sin.sin_port
197 && a->src.sin.sin_addr.s_addr == b->src.sin.sin_addr.s_addr
198 && a->dst.sin.sin_addr.s_addr == b->dst.sin.sin_addr.s_addr;
199 }
200 else { /* PF_INET6 */
201 return a->src.sin6.sin6_port == b->src.sin6.sin6_port
202 && a->dst.sin6.sin6_port == b->dst.sin6.sin6_port
203 && IN6_ARE_ADDR_EQUAL(&a->src.sin6.sin6_addr, &b->src.sin6.sin6_addr)
204 && IN6_ARE_ADDR_EQUAL(&a->dst.sin6.sin6_addr, &b->dst.sin6.sin6_addr);
205 }
206}
207
208
209/**
210 * Set fwdsrc to the IP address of the peer.
211 *
212 * For port-forwarded connections originating from hosts loopback the
213 * source address is set to the address of one of lwIP interfaces.
214 *
215 * Currently we only have one interface so there's not much logic
216 * here. In the future we might need to additionally consult fwspec
217 * and routing table to determine which netif is used for connections
218 * to the specified guest.
219 */
220int
221fwany_ipX_addr_set_src(ipX_addr_t *fwdsrc, const struct sockaddr *peer)
222{
223 int mapping;
224
225 if (peer->sa_family == AF_INET) {
226 const struct sockaddr_in *peer4 = (const struct sockaddr_in *)peer;
227 ip_addr_t peerip4;
228
229 peerip4.addr = peer4->sin_addr.s_addr;
230 mapping = pxremap_inbound_ip4(&fwdsrc->ip4, &peerip4);
231 }
232 else if (peer->sa_family == AF_INET6) {
233 const struct sockaddr_in6 *peer6 = (const struct sockaddr_in6 *)peer;
234 ip6_addr_t peerip6;
235
236 memcpy(&peerip6, &peer6->sin6_addr, sizeof(ip6_addr_t));
237 mapping = pxremap_inbound_ip6(&fwdsrc->ip6, &peerip6);
238 }
239 else {
240 mapping = PXREMAP_FAILED;
241 }
242
243 return mapping;
244}
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