VirtualBox

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

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

NAT/Net: #define LOG_GROUP LOG_GROUP_NAT_SERVICE

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