VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/DrvNATlibslirp.h@ 105205

Last change on this file since 105205 was 105205, checked in by vboxsync, 8 months ago

Devices/Network, /Config.kmk: reenable libslirp on win. fix build issues. bugref:10268

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.3 KB
Line 
1/** @file
2 * DrvNATlibslirp - NATlibslirp network transport driver.
3 */
4
5/*
6 * Copyright (C) 2022-2023 Oracle and/or its affiliates.
7 *
8 * This file is part of VirtualBox base platform packages, as
9 * available from https://www.virtualbox.org.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation, in version 3 of the
14 * License.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <https://www.gnu.org/licenses>.
23 *
24 * SPDX-License-Identifier: GPL-3.0-only
25 */
26
27#ifndef VBOX_INCLUDED_SRC_Network_DrvNATlibslirp_h
28#define VBOX_INCLUDED_SRC_Network_DrvNATlibslirp_h
29#ifndef RT_WITHOUT_PRAGMA_ONCE
30# pragma once
31#endif
32#endif
33
34#define RTNET_INCL_IN_ADDR
35
36#include "VBoxDD.h"
37
38#ifdef RT_OS_WINDOWS
39# include <iprt/win/winsock2.h>
40# include <iprt/win/ws2tcpip.h>
41#endif
42
43#include <libslirp.h>
44
45#include <VBox/vmm/dbgf.h>
46#include <VBox/vmm/pdmdrv.h>
47#include <VBox/vmm/pdmnetifs.h>
48#include <VBox/vmm/pdmnetinline.h>
49
50#ifndef RT_OS_WINDOWS
51# include <unistd.h>
52# include <fcntl.h>
53# include <poll.h>
54# include <errno.h>
55#endif
56#ifdef RT_OS_FREEBSD
57# include <netinet/in.h>
58#endif
59
60#ifdef RT_OS_WINDOWS
61# include <iprt/win/winsock2.h>
62# define inet_aton(x, y) inet_pton(2, x, y)
63# define AF_INET6 23
64#endif
65
66#include <iprt/assert.h>
67#include <iprt/critsect.h>
68#include <iprt/cidr.h>
69#include <iprt/file.h>
70#include <iprt/mem.h>
71#include <iprt/net.h>
72#include <iprt/pipe.h>
73#include <iprt/string.h>
74#include <iprt/stream.h>
75#include <iprt/time.h>
76#include <iprt/uuid.h>
77
78#include <iprt/asm.h>
79
80#include <iprt/semaphore.h>
81#include <iprt/req.h>
82#ifdef RT_OS_DARWIN
83# include <SystemConfiguration/SystemConfiguration.h>
84# include <CoreFoundation/CoreFoundation.h>
85#endif
86
87#define COUNTERS_INIT
88#include "slirp/counters.h"
89
90/*********************************************************************************************************************************
91* Defined Constants And Macros *
92*********************************************************************************************************************************/
93
94#define DRVNAT_MAXFRAMESIZE (16 * 1024)
95
96/**
97 * @todo: This is a bad hack to prevent freezing the guest during high network
98 * activity. Windows host only. This needs to be fixed properly.
99 */
100#define VBOX_NAT_DELAY_HACK
101
102#define GET_EXTRADATA(pdrvins, node, name, rc, type, type_name, var) \
103do { \
104 (rc) = (pdrvins)->pHlpR3->pfnCFGMQuery ## type((node), name, &(var)); \
105 if (RT_FAILURE((rc)) && (rc) != VERR_CFGM_VALUE_NOT_FOUND) \
106 return PDMDrvHlpVMSetError((pdrvins), (rc), RT_SRC_POS, N_("NAT#%d: configuration query for \"" name "\" " #type_name " failed"), \
107 (pdrvins)->iInstance); \
108} while (0)
109
110#define GET_ED_STRICT(pdrvins, node, name, rc, type, type_name, var) \
111do { \
112 (rc) = (pdrvins)->pHlpR3->pfnCFGMQuery ## type((node), name, &(var)); \
113 if (RT_FAILURE((rc))) \
114 return PDMDrvHlpVMSetError((pdrvins), (rc), RT_SRC_POS, N_("NAT#%d: configuration query for \"" name "\" " #type_name " failed"), \
115 (pdrvins)->iInstance); \
116} while (0)
117
118#define GET_EXTRADATA_N(pdrvins, node, name, rc, type, type_name, var, var_size) \
119do { \
120 (rc) = (pdrvins)->pHlpR3->pfnCFGMQuery ## type((node), name, &(var), var_size); \
121 if (RT_FAILURE((rc)) && (rc) != VERR_CFGM_VALUE_NOT_FOUND) \
122 return PDMDrvHlpVMSetError((pdrvins), (rc), RT_SRC_POS, N_("NAT#%d: configuration query for \"" name "\" " #type_name " failed"), \
123 (pdrvins)->iInstance); \
124} while (0)
125
126#define GET_BOOL(rc, pdrvins, node, name, var) \
127 GET_EXTRADATA(pdrvins, node, name, (rc), Bool, bolean, (var))
128#define GET_STRING(rc, pdrvins, node, name, var, var_size) \
129 GET_EXTRADATA_N(pdrvins, node, name, (rc), String, string, (var), (var_size))
130#define GET_STRING_ALLOC(rc, pdrvins, node, name, var) \
131 GET_EXTRADATA(pdrvins, node, name, (rc), StringAlloc, string, (var))
132#define GET_S32(rc, pdrvins, node, name, var) \
133 GET_EXTRADATA(pdrvins, node, name, (rc), S32, int, (var))
134#define GET_S32_STRICT(rc, pdrvins, node, name, var) \
135 GET_ED_STRICT(pdrvins, node, name, (rc), S32, int, (var))
136
137#define DO_GET_IP(rc, node, instance, status, x) \
138do { \
139 char sz##x[32]; \
140 GET_STRING((rc), (node), (instance), #x, sz ## x[0], sizeof(sz ## x)); \
141 if (rc != VERR_CFGM_VALUE_NOT_FOUND) \
142 (status) = inet_aton(sz ## x, &x); \
143} while (0)
144
145#define GETIP_DEF(rc, node, instance, x, def) \
146do \
147{ \
148 int status = 0; \
149 DO_GET_IP((rc), (node), (instance), status, x); \
150 if (status == 0 || rc == VERR_CFGM_VALUE_NOT_FOUND) \
151 x.s_addr = def; \
152} while (0)
153
154/** Slirp Timer */
155typedef struct slirpTimer {
156 struct slirpTimer *next;
157 int64_t uTimeExpire;
158 SlirpTimerCb pHandler;
159 void *opaque;
160} SlirpTimer;
161
162/**
163 * Main state of Libslirp NAT
164 */
165typedef struct SlirpState
166{
167 unsigned int nsock;
168
169 Slirp *pSlirp;
170 struct pollfd *polls;
171
172 /** Num Polls (not bytes) */
173 unsigned int uPollCap = 0;
174
175 SlirpTimer *pTimerHead;
176} SlirpState;
177typedef SlirpState *pSlirpState;
178
179/**
180 * NAT network transport driver instance data.
181 *
182 * @implements PDMINETWORKUP
183 */
184typedef struct DRVNAT
185{
186 /** The network interface. */
187 PDMINETWORKUP INetworkUp;
188 /** The network NAT Engine configuration. */
189 PDMINETWORKNATCONFIG INetworkNATCfg;
190 /** The port we're attached to. */
191 PPDMINETWORKDOWN pIAboveNet;
192 /** The network config of the port we're attached to. */
193 PPDMINETWORKCONFIG pIAboveConfig;
194 /** Pointer to the driver instance. */
195 PPDMDRVINS pDrvIns;
196 /** Link state */
197 PDMNETWORKLINKSTATE enmLinkState;
198 /** NAT state */
199 pSlirpState pNATState;
200 /** TFTP directory prefix. */
201 char *pszTFTPPrefix;
202 /** Boot file name to provide in the DHCP server response. */
203 char *pszBootFile;
204 /** tftp server name to provide in the DHCP server response. */
205 char *pszNextServer;
206 /** Polling thread. */
207 PPDMTHREAD pSlirpThread;
208 /** Queue for NAT-thread-external events. */
209 RTREQQUEUE hSlirpReqQueue;
210 /** The guest IP for port-forwarding. */
211 uint32_t GuestIP;
212 /** Link state set when the VM is suspended. */
213 PDMNETWORKLINKSTATE enmLinkStateWant;
214
215#ifndef RT_OS_WINDOWS
216 /** The write end of the control pipe. */
217 RTPIPE hPipeWrite;
218 /** The read end of the control pipe. */
219 RTPIPE hPipeRead;
220# if HC_ARCH_BITS == 32
221 uint32_t u32Padding;
222# endif
223#else
224 /** for external notification */
225 HANDLE hWakeupEvent;
226#endif
227
228#define DRV_PROFILE_COUNTER(name, dsc) STAMPROFILE Stat ## name
229#define DRV_COUNTING_COUNTER(name, dsc) STAMCOUNTER Stat ## name
230#include "slirp/counters.h"
231 /** thread delivering packets for receiving by the guest */
232 PPDMTHREAD pRecvThread;
233 /** event to wakeup the guest receive thread */
234 RTSEMEVENT EventRecv;
235 /** Receive Req queue (deliver packets to the guest) */
236 RTREQQUEUE hRecvReqQueue;
237
238 /** makes access to device func RecvAvail and Recv atomical. */
239 RTCRITSECT DevAccessLock;
240 /** Number of in-flight packets. */
241 volatile uint32_t cPkts;
242
243 /** Transmit lock taken by BeginXmit and released by EndXmit. */
244 RTCRITSECT XmitLock;
245
246#ifdef RT_OS_DARWIN
247 /* Handle of the DNS watcher runloop source. */
248 CFRunLoopSourceRef hRunLoopSrcDnsWatcher;
249#endif /* !VBOX_INCLUDED_SRC_Network_DrvNATlibslirp_h */
250} DRVNAT;
251AssertCompileMemberAlignment(DRVNAT, StatNATRecvWakeups, 8);
252/** Pointer to the NAT driver instance data. */
253typedef DRVNAT *PDRVNAT;
254
255/**
256 * PDM Function Implementations
257 */
258static DECLCALLBACK(int) drvNATRecv(PPDMDRVINS, PPDMTHREAD);
259static DECLCALLBACK(int) drvNATRecvWakeup(PPDMDRVINS, PPDMTHREAD);
260static DECLCALLBACK(void) drvNATRecvWorker(PDRVNAT, void *, int);
261static void drvNATFreeSgBuf(PDRVNAT, PPDMSCATTERGATHER);
262static DECLCALLBACK(void) drvNATSendWorker(PDRVNAT, PPDMSCATTERGATHER);
263static DECLCALLBACK(int) drvNATNetworkUp_BeginXmit(PPDMINETWORKUP, bool);
264static DECLCALLBACK(int) drvNATNetworkUp_AllocBuf(PPDMINETWORKUP, size_t,
265 PCPDMNETWORKGSO, PPPDMSCATTERGATHER);
266static DECLCALLBACK(int) drvNATNetworkUp_FreeBuf(PPDMINETWORKUP, PPDMSCATTERGATHER);
267static DECLCALLBACK(int) drvNATNetworkUp_SendBuf(PPDMINETWORKUP, PPDMSCATTERGATHER, bool);
268static DECLCALLBACK(void) drvNATNetworkUp_EndXmit(PPDMINETWORKUP);
269static void drvNATNotifyNATThread(PDRVNAT pThis, const char *);
270static DECLCALLBACK(void) drvNATNetworkUp_SetPromiscuousMode(PPDMINETWORKUP, bool);
271static DECLCALLBACK(void) drvNATNotifyLinkChangedWorker(PDRVNAT, PDMNETWORKLINKSTATE);
272static DECLCALLBACK(void) drvNATNetworkUp_NotifyLinkChanged(PPDMINETWORKUP, PDMNETWORKLINKSTATE);
273static DECLCALLBACK(int) drvNATAsyncIoThread(PPDMDRVINS, PPDMTHREAD);
274static DECLCALLBACK(int) drvNATAsyncIoWakeup(PPDMDRVINS, PPDMTHREAD);
275static DECLCALLBACK(void *) drvNATQueryInterface(PPDMIBASE, const char *);
276static DECLCALLBACK(void) drvNATInfo(PPDMDRVINS, PCDBGFINFOHLP, const char *);
277static int drvNATConstructRedir(unsigned, PDRVNAT, PCFGMNODE, PRTNETADDRIPV4);
278static DECLCALLBACK(void) drvNATNotifyApplyPortForwardCommand(PDRVNAT, bool, bool, const char *,
279 uint16_t, const char *, uint16_t);
280static DECLCALLBACK(int) drvNATNetworkNatConfigRedirect(PPDMINETWORKNATCONFIG, bool, bool,
281 const char *, uint16_t, const char *, uint16_t);
282
283/**
284 * Libslirp Utility Functions
285 */
286static void drvNAT_UpdateTimeout(uint32_t *, void *);
287static void drvNAT_CheckTimeout(void *);
288static int drvNAT_PollEventSlirpToHost(int);
289static int drvNAT_PollEventHostToSlirp(int);
290
291/**
292 * Libslirp Callback Functions
293 */
294static DECLCALLBACK(ssize_t) drvNAT_SendPacketCb(const void *, size_t, void *);
295static DECLCALLBACK(void) drvNAT_GuestErrorCb(const char *, void *);
296static DECLCALLBACK(int64_t) drvNAT_ClockGetNsCb(void *);
297static DECLCALLBACK(void *) drvNAT_TimerNewCb(SlirpTimerCb, void *, void *);
298static DECLCALLBACK(void) drvNAT_TimerFreeCb(void *, void *);
299static DECLCALLBACK(void) drvNAT_TimerModCb(void *, int64_t, void *);
300static DECLCALLBACK(void) drvNAT_NotifyCb(void *);
301static DECLCALLBACK(void) drvNAT_RegisterPoll(int, void *);
302static DECLCALLBACK(void) drvNAT_UnregisterPoll(int, void *);
303
304static DECLCALLBACK(int) drvNAT_AddPollCb(int, int, void *);
305static DECLCALLBACK(int) drvNAT_GetREventsCb(int, void *);
306
307/**
308 * Contructor/Destructor
309 */
310static DECLCALLBACK(void) drvNATDestruct(PPDMDRVINS);
311static DECLCALLBACK(int) drvNATConstruct(PPDMDRVINS, PCFGMNODE, uint32_t);
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