VirtualBox

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

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