VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/NAT/pxremap.c@ 49016

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

Change vestigial names proxytest.* to proxy.*

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 7.9 KB
Line 
1/** -*- indent-tabs-mode: nil; -*-
2 *
3 * This file contains functions pertinent to magic address remapping.
4 *
5 * We want to expose host's loopback interfaces to the guest by
6 * mapping them to the addresses from the same prefix/subnet, so if,
7 * for example proxy interface is 10.0.2.1, we redirect traffic to
8 * 10.0.2.2 to host's 127.0.0.1 loopback. If need be, we may extend
9 * this to provide additional mappings, e.g. 127.0.1.1 loopback
10 * address is used on Ubuntu 12.10+ for NetworkManager's dnsmasq.
11 *
12 * Ditto for IPv6, except that IPv6 only has one loopback address.
13 */
14#include "winutils.h"
15#include "pxremap.h"
16#include "proxy.h"
17
18#include "lwip/netif.h"
19#include "netif/etharp.h" /* proxy arp hook */
20
21#include "lwip/ip4.h" /* IPv4 divert hook */
22#include "lwip/ip6.h" /* IPv6 divert hook */
23
24#include <string.h>
25
26
27/**
28 * Check if "dst" is an IPv4 address that proxy remaps to host's
29 * loopback.
30 */
31static int
32proxy_ip4_is_mapped_loopback(struct netif *netif, const ip_addr_t *dst, ip_addr_t *lo)
33{
34 ip_addr_t net;
35 u32_t off;
36 const struct ip4_lomap *lomap;
37 size_t i;
38
39 LWIP_ASSERT1(dst != NULL);
40
41 if (g_proxy_options->lomap_desc == NULL) {
42 return 0;
43 }
44
45 if (!ip_addr_netcmp(dst, &netif->ip_addr, &netif->netmask)) {
46 return 0;
47 }
48
49 /* XXX: TODO: check netif is a proxying netif! */
50
51 off = ntohl(ip4_addr_get_u32(dst) & ~ip4_addr_get_u32(&netif->netmask));
52 lomap = g_proxy_options->lomap_desc->lomap;
53 for (i = 0; i < g_proxy_options->lomap_desc->num_lomap; ++i) {
54 if (off == lomap[i].off) {
55 if (lo != NULL) {
56 ip_addr_copy(*lo, lomap[i].loaddr);
57 }
58 return 1;
59 }
60 }
61 return 0;
62}
63
64
65#if ARP_PROXY
66/**
67 * Hook function for etharp_arp_input() - returns true to cause proxy
68 * ARP reply to be generated for "dst".
69 */
70int
71pxremap_proxy_arp(struct netif *netif, ip_addr_t *dst)
72{
73 return proxy_ip4_is_mapped_loopback(netif, dst, NULL);
74}
75#endif /* ARP_PROXY */
76
77
78/**
79 * Hook function for ip_forward() - returns true to divert packets to
80 * "dst" to proxy (instead of forwarding them via "netif" or dropping).
81 */
82int
83pxremap_ip4_divert(struct netif *netif, ip_addr_t *dst)
84{
85 return proxy_ip4_is_mapped_loopback(netif, dst, NULL);
86}
87
88
89/**
90 * Mapping from local network to loopback for outbound connections.
91 *
92 * Copy "src" to "dst" with ip_addr_set(dst, src), but if "src" is a
93 * local network address that maps host's loopback address, copy
94 * loopback address to "dst".
95 */
96int
97pxremap_outbound_ip4(ip_addr_t *dst, ip_addr_t *src)
98{
99 struct netif *netif;
100
101 LWIP_ASSERT1(dst != NULL);
102 LWIP_ASSERT1(src != NULL);
103
104 for (netif = netif_list; netif != NULL; netif = netif->next) {
105 if (netif_is_up(netif) /* && this is a proxy netif */) {
106 if (proxy_ip4_is_mapped_loopback(netif, src, dst)) {
107 return PXREMAP_MAPPED;
108 }
109 }
110 }
111
112 /* not remapped, just copy src */
113 ip_addr_set(dst, src);
114 return PXREMAP_ASIS;
115}
116
117
118/**
119 * Mapping from loopback to local network for inbound (port-forwarded)
120 * connections.
121 *
122 * Copy "src" to "dst" with ip_addr_set(dst, src), but if "src" is a
123 * host's loopback address, copy local network address that maps it to
124 * "dst".
125 */
126int
127pxremap_inbound_ip4(ip_addr_t *dst, ip_addr_t *src)
128{
129 struct netif *netif;
130 const struct ip4_lomap *lomap;
131 unsigned int i;
132
133 if (ip4_addr1(src) != IP_LOOPBACKNET) {
134 ip_addr_set(dst, src);
135 return PXREMAP_ASIS;
136 }
137
138 if (g_proxy_options->lomap_desc == NULL) {
139 return PXREMAP_FAILED;
140 }
141
142#if 0 /* ?TODO: with multiple interfaces we need to consider fwspec::dst */
143 netif = ip_route(target);
144 if (netif == NULL) {
145 return PXREMAP_FAILED;
146 }
147#else
148 netif = netif_list;
149 LWIP_ASSERT1(netif != NULL);
150 LWIP_ASSERT1(netif->next == NULL);
151#endif
152
153 lomap = g_proxy_options->lomap_desc->lomap;
154 for (i = 0; i < g_proxy_options->lomap_desc->num_lomap; ++i) {
155 if (ip_addr_cmp(src, &lomap[i].loaddr)) {
156 ip_addr_t net;
157
158 ip_addr_get_network(&net, &netif->ip_addr, &netif->netmask);
159 ip4_addr_set_u32(dst,
160 htonl(ntohl(ip4_addr_get_u32(&net))
161 + lomap[i].off));
162 return PXREMAP_MAPPED;
163 }
164 }
165
166 return PXREMAP_FAILED;
167}
168
169
170static int
171proxy_ip6_is_mapped_loopback(struct netif *netif, ip6_addr_t *dst)
172{
173 int i;
174
175 /* XXX: TODO: check netif is a proxying netif! */
176
177 LWIP_ASSERT1(dst != NULL);
178
179 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) {
180 if (ip6_addr_ispreferred(netif_ip6_addr_state(netif, i))
181 && ip6_addr_isuniquelocal(netif_ip6_addr(netif, i)))
182 {
183 ip6_addr_t *ifaddr = netif_ip6_addr(netif, i);
184 if (memcmp(dst, ifaddr, sizeof(ip6_addr_t) - 1) == 0
185 && ((IP6_ADDR_BLOCK8(dst) & 0xff)
186 == (IP6_ADDR_BLOCK8(ifaddr) & 0xff) + 1))
187 {
188 return 1;
189 }
190 }
191 }
192
193 return 0;
194}
195
196
197/**
198 * Hook function for nd6_input() - returns true to cause proxy NA
199 * reply to be generated for "dst".
200 */
201int
202pxremap_proxy_na(struct netif *netif, ip6_addr_t *dst)
203{
204 return proxy_ip6_is_mapped_loopback(netif, dst);
205}
206
207
208/**
209 * Hook function for ip6_forward() - returns true to divert packets to
210 * "dst" to proxy (instead of forwarding them via "netif" or dropping).
211 */
212int
213pxremap_ip6_divert(struct netif *netif, ip6_addr_t *dst)
214{
215 return proxy_ip6_is_mapped_loopback(netif, dst);
216}
217
218
219/**
220 * Mapping from local network to loopback for outbound connections.
221 *
222 * Copy "src" to "dst" with ip6_addr_set(dst, src), but if "src" is a
223 * local network address that maps host's loopback address, copy IPv6
224 * loopback address to "dst".
225 */
226int
227pxremap_outbound_ip6(ip6_addr_t *dst, ip6_addr_t *src)
228{
229 struct netif *netif;
230 int i;
231
232 LWIP_ASSERT1(dst != NULL);
233 LWIP_ASSERT1(src != NULL);
234
235 for (netif = netif_list; netif != NULL; netif = netif->next) {
236 if (!netif_is_up(netif) /* || this is not a proxy netif */) {
237 continue;
238 }
239
240 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) {
241 if (ip6_addr_ispreferred(netif_ip6_addr_state(netif, i))
242 && ip6_addr_isuniquelocal(netif_ip6_addr(netif, i)))
243 {
244 ip6_addr_t *ifaddr = netif_ip6_addr(netif, i);
245 if (memcmp(src, ifaddr, sizeof(ip6_addr_t) - 1) == 0
246 && ((IP6_ADDR_BLOCK8(src) & 0xff)
247 == (IP6_ADDR_BLOCK8(ifaddr) & 0xff) + 1))
248 {
249 ip6_addr_set_loopback(dst);
250 return PXREMAP_MAPPED;
251 }
252 }
253 }
254 }
255
256 /* not remapped, just copy src */
257 ip6_addr_set(dst, src);
258 return PXREMAP_ASIS;
259}
260
261
262/**
263 * Mapping from loopback to local network for inbound (port-forwarded)
264 * connections.
265 *
266 * Copy "src" to "dst" with ip6_addr_set(dst, src), but if "src" is a
267 * host's loopback address, copy local network address that maps it to
268 * "dst".
269 */
270int
271pxremap_inbound_ip6(ip6_addr_t *dst, ip6_addr_t *src)
272{
273 ip6_addr_t loopback;
274 struct netif *netif;
275 int i;
276
277 ip6_addr_set_loopback(&loopback);
278 if (!ip6_addr_cmp(src, &loopback)) {
279 ip6_addr_set(dst, src);
280 return PXREMAP_ASIS;
281 }
282
283#if 0 /* ?TODO: with multiple interfaces we need to consider fwspec::dst */
284 netif = ip6_route_fwd(target);
285 if (netif == NULL) {
286 return PXREMAP_FAILED;
287 }
288#else
289 netif = netif_list;
290 LWIP_ASSERT1(netif != NULL);
291 LWIP_ASSERT1(netif->next == NULL);
292#endif
293
294 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) {
295 ip6_addr_t *ifaddr = netif_ip6_addr(netif, i);
296 if (ip6_addr_ispreferred(netif_ip6_addr_state(netif, i))
297 && ip6_addr_isuniquelocal(ifaddr))
298 {
299 ip6_addr_set(dst, ifaddr);
300 ++((u8_t *)&dst->addr[3])[3];
301 return PXREMAP_MAPPED;
302 }
303 }
304
305 return PXREMAP_FAILED;
306}
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