VirtualBox

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

最後變更 在這個檔案從105069是 105069,由 vboxsync 提交於 9 月 前

Devices/Network: clean up code and comments. bugref:10268

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 13.0 KB
 
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.alldomusa.eu.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#include <libslirp.h>
39
40#include <VBox/vmm/dbgf.h>
41#include <VBox/vmm/pdmdrv.h>
42#include <VBox/vmm/pdmnetifs.h>
43#include <VBox/vmm/pdmnetinline.h>
44
45#ifndef RT_OS_WINDOWS
46# include <unistd.h>
47# include <fcntl.h>
48# include <poll.h>
49# include <errno.h>
50#endif
51#ifdef RT_OS_FREEBSD
52# include <netinet/in.h>
53#endif
54
55/** @todo r=jack: do we need to externally define inet* functions on win */
56#ifdef RT_OS_WINDOWS
57# include <iprt/win/winsock2.h>
58# ifdef __cplusplus
59extern "C" {
60# endif
61int inet_pton(int,const char *,void *);
62# ifdef __cplusplus
63}
64# endif
65# define inet_aton(x, y) inet_pton(2, x, y)
66# define AF_INET6 23
67#endif
68
69#include <iprt/assert.h>
70#include <iprt/critsect.h>
71#include <iprt/cidr.h>
72#include <iprt/file.h>
73#include <iprt/mem.h>
74#include <iprt/net.h>
75#include <iprt/pipe.h>
76#include <iprt/string.h>
77#include <iprt/stream.h>
78#include <iprt/time.h>
79#include <iprt/uuid.h>
80
81#include <iprt/asm.h>
82
83#include <iprt/semaphore.h>
84#include <iprt/req.h>
85#ifdef RT_OS_DARWIN
86# include <SystemConfiguration/SystemConfiguration.h>
87# include <CoreFoundation/CoreFoundation.h>
88#endif
89
90#define COUNTERS_INIT
91#include "slirp/counters.h"
92
93/*********************************************************************************************************************************
94* Defined Constants And Macros *
95*********************************************************************************************************************************/
96
97#define DRVNAT_MAXFRAMESIZE (16 * 1024)
98
99/**
100 * @todo: This is a bad hack to prevent freezing the guest during high network
101 * activity. Windows host only. This needs to be fixed properly.
102 */
103#define VBOX_NAT_DELAY_HACK
104
105/*
106 * ICMP handle state change
107 */
108# define VBOX_ICMP_EVENT_INDEX -1
109
110/**
111 * This event is for
112 * - slirp_input
113 * - slirp_link_up
114 * - slirp_link_down
115 * - wakeup
116 */
117# define VBOX_WAKEUP_EVENT_INDEX 0
118
119/*
120 * UDP/TCP socket state change (socket ready to receive, to send, ...)
121 */
122# define VBOX_SOCKET_EVENT_INDEX 1
123
124/*
125 * The number of events for WSAWaitForMultipleEvents().
126 */
127# define VBOX_EVENT_COUNT 2
128
129#define GET_EXTRADATA(pdrvins, node, name, rc, type, type_name, var) \
130do { \
131 (rc) = (pdrvins)->pHlpR3->pfnCFGMQuery ## type((node), name, &(var)); \
132 if (RT_FAILURE((rc)) && (rc) != VERR_CFGM_VALUE_NOT_FOUND) \
133 return PDMDrvHlpVMSetError((pdrvins), (rc), RT_SRC_POS, N_("NAT#%d: configuration query for \"" name "\" " #type_name " failed"), \
134 (pdrvins)->iInstance); \
135} while (0)
136
137#define GET_ED_STRICT(pdrvins, node, name, rc, type, type_name, var) \
138do { \
139 (rc) = (pdrvins)->pHlpR3->pfnCFGMQuery ## type((node), name, &(var)); \
140 if (RT_FAILURE((rc))) \
141 return PDMDrvHlpVMSetError((pdrvins), (rc), RT_SRC_POS, N_("NAT#%d: configuration query for \"" name "\" " #type_name " failed"), \
142 (pdrvins)->iInstance); \
143} while (0)
144
145#define GET_EXTRADATA_N(pdrvins, node, name, rc, type, type_name, var, var_size) \
146do { \
147 (rc) = (pdrvins)->pHlpR3->pfnCFGMQuery ## type((node), name, &(var), var_size); \
148 if (RT_FAILURE((rc)) && (rc) != VERR_CFGM_VALUE_NOT_FOUND) \
149 return PDMDrvHlpVMSetError((pdrvins), (rc), RT_SRC_POS, N_("NAT#%d: configuration query for \"" name "\" " #type_name " failed"), \
150 (pdrvins)->iInstance); \
151} while (0)
152
153#define GET_BOOL(rc, pdrvins, node, name, var) \
154 GET_EXTRADATA(pdrvins, node, name, (rc), Bool, bolean, (var))
155#define GET_STRING(rc, pdrvins, node, name, var, var_size) \
156 GET_EXTRADATA_N(pdrvins, node, name, (rc), String, string, (var), (var_size))
157#define GET_STRING_ALLOC(rc, pdrvins, node, name, var) \
158 GET_EXTRADATA(pdrvins, node, name, (rc), StringAlloc, string, (var))
159#define GET_S32(rc, pdrvins, node, name, var) \
160 GET_EXTRADATA(pdrvins, node, name, (rc), S32, int, (var))
161#define GET_S32_STRICT(rc, pdrvins, node, name, var) \
162 GET_ED_STRICT(pdrvins, node, name, (rc), S32, int, (var))
163
164#define DO_GET_IP(rc, node, instance, status, x) \
165do { \
166 char sz##x[32]; \
167 GET_STRING((rc), (node), (instance), #x, sz ## x[0], sizeof(sz ## x)); \
168 if (rc != VERR_CFGM_VALUE_NOT_FOUND) \
169 (status) = inet_aton(sz ## x, &x); \
170} while (0)
171
172#define GETIP_DEF(rc, node, instance, x, def) \
173do \
174{ \
175 int status = 0; \
176 DO_GET_IP((rc), (node), (instance), status, x); \
177 if (status == 0 || rc == VERR_CFGM_VALUE_NOT_FOUND) \
178 x.s_addr = def; \
179} while (0)
180
181// timer struct
182typedef struct slirpTimer {
183 struct slirpTimer *next;
184 int64_t uTimeExpire;
185 SlirpTimerCb pHandler;
186 void *opaque;
187} SlirpTimer;
188
189/**
190 * Main state of Libslirp NAT
191 */
192typedef struct SlirpState
193{
194 unsigned int nsock;
195# ifndef RT_OS_WINDOWS
196 /* counter of sockets needed for allocation enough room to
197 * process sockets with poll/epoll
198 *
199 * NSOCK_INC/DEC should be injected before every
200 * operation on socket queue (tcb, udb)
201 */
202# define NSOCK_INC() do {pData->nsock++;} while (0)
203# define NSOCK_DEC() do {pData->nsock--;} while (0)
204# define NSOCK_INC_EX(ex) do {ex->pData->nsock++;} while (0)
205# define NSOCK_DEC_EX(ex) do {ex->pData->nsock--;} while (0)
206# else
207# define NSOCK_INC() do {} while (0)
208# define NSOCK_DEC() do {} while (0)
209# define NSOCK_INC_EX(ex) do {} while (0)
210# define NSOCK_DEC_EX(ex) do {} while (0)
211# endif
212
213#if defined(RT_OS_WINDOWS)
214# define VBOX_SOCKET_EVENT (pData->phEvents[VBOX_SOCKET_EVENT_INDEX])
215 HANDLE phEvents[VBOX_EVENT_COUNT];
216#endif
217
218 Slirp *pSlirp;
219 struct pollfd *polls;
220
221 // Num Polls (not bytes)
222 unsigned int uPollCap = 0;
223
224 SlirpTimer *pTimerHead;
225} SlirpState;
226typedef SlirpState *pSlirpState;
227
228/**
229 * NAT network transport driver instance data.
230 *
231 * @implements PDMINETWORKUP
232 */
233typedef struct DRVNAT
234{
235 /** The network interface. */
236 PDMINETWORKUP INetworkUp;
237 /** The network NAT Engine configuration. */
238 PDMINETWORKNATCONFIG INetworkNATCfg;
239 /** The port we're attached to. */
240 PPDMINETWORKDOWN pIAboveNet;
241 /** The network config of the port we're attached to. */
242 PPDMINETWORKCONFIG pIAboveConfig;
243 /** Pointer to the driver instance. */
244 PPDMDRVINS pDrvIns;
245 /** Link state */
246 PDMNETWORKLINKSTATE enmLinkState;
247 /** NAT state */
248 pSlirpState pNATState;
249 /** TFTP directory prefix. */
250 char *pszTFTPPrefix;
251 /** Boot file name to provide in the DHCP server response. */
252 char *pszBootFile;
253 /** tftp server name to provide in the DHCP server response. */
254 char *pszNextServer;
255 /** Polling thread. */
256 PPDMTHREAD pSlirpThread;
257 /** Queue for NAT-thread-external events. */
258 RTREQQUEUE hSlirpReqQueue;
259 /** The guest IP for port-forwarding. */
260 uint32_t GuestIP;
261 /** Link state set when the VM is suspended. */
262 PDMNETWORKLINKSTATE enmLinkStateWant;
263
264#ifndef RT_OS_WINDOWS
265 /** The write end of the control pipe. */
266 RTPIPE hPipeWrite;
267 /** The read end of the control pipe. */
268 RTPIPE hPipeRead;
269# if HC_ARCH_BITS == 32
270 uint32_t u32Padding;
271# endif
272#else
273 /** for external notification */
274 HANDLE hWakeupEvent;
275#endif
276
277#define DRV_PROFILE_COUNTER(name, dsc) STAMPROFILE Stat ## name
278#define DRV_COUNTING_COUNTER(name, dsc) STAMCOUNTER Stat ## name
279#include "slirp/counters.h"
280 /** thread delivering packets for receiving by the guest */
281 PPDMTHREAD pRecvThread;
282 /** thread delivering urg packets for receiving by the guest */
283 PPDMTHREAD pUrgRecvThread;
284 /** event to wakeup the guest receive thread */
285 RTSEMEVENT EventRecv;
286 /** event to wakeup the guest urgent receive thread */
287 RTSEMEVENT EventUrgRecv;
288 /** Receive Req queue (deliver packets to the guest) */
289 RTREQQUEUE hRecvReqQueue;
290 /** Receive Urgent Req queue (deliver packets to the guest). */
291 RTREQQUEUE hUrgRecvReqQueue;
292
293 /** makes access to device func RecvAvail and Recv atomical. */
294 RTCRITSECT DevAccessLock;
295 /** Number of in-flight urgent packets. */
296 volatile uint32_t cUrgPkts;
297 /** Number of in-flight regular packets. */
298 volatile uint32_t cPkts;
299
300 /** Transmit lock taken by BeginXmit and released by EndXmit. */
301 RTCRITSECT XmitLock;
302
303#ifdef RT_OS_DARWIN
304 /* Handle of the DNS watcher runloop source. */
305 CFRunLoopSourceRef hRunLoopSrcDnsWatcher;
306#endif /* !VBOX_INCLUDED_SRC_Network_DrvNATlibslirp_h */
307} DRVNAT;
308// AssertCompileMemberAlignment(DRVNAT, StatNATRecvWakeups, 8);
309/** Pointer to the NAT driver instance data. */
310typedef DRVNAT *PDRVNAT;
311
312static DECLCALLBACK(int) drvNATRecv(PPDMDRVINS, PPDMTHREAD);
313static DECLCALLBACK(int) drvNATRecvWakeup(PPDMDRVINS, PPDMTHREAD);
314static DECLCALLBACK(int) drvNATUrgRecvWakeup(PPDMDRVINS, PPDMTHREAD);
315static DECLCALLBACK(void) drvNATRecvWorker(PDRVNAT, void *, int);
316static void drvNATFreeSgBuf(PDRVNAT, PPDMSCATTERGATHER);
317static DECLCALLBACK(void) drvNATSendWorker(PDRVNAT, PPDMSCATTERGATHER);
318static DECLCALLBACK(int) drvNATNetworkUp_AllocBuf(PPDMINETWORKUP, size_t,
319 PCPDMNETWORKGSO, PPPDMSCATTERGATHER);
320static DECLCALLBACK(int) drvNATNetworkUp_FreeBuf(PPDMINETWORKUP, PPDMSCATTERGATHER);
321static DECLCALLBACK(int) drvNATNetworkUp_SendBuf(PPDMINETWORKUP, PPDMSCATTERGATHER, bool);
322static DECLCALLBACK(void) drvNATNetworkUp_EndXmit(PPDMINETWORKUP );
323static void drvNATNotifyNATThread(PDRVNAT pThis, const char *);
324static DECLCALLBACK(void) drvNATNetworkUp_SetPromiscuousMode(PPDMINETWORKUP, bool);
325static DECLCALLBACK(void) drvNATNotifyLinkChangedWorker(PDRVNAT, PDMNETWORKLINKSTATE);
326static DECLCALLBACK(void) drvNATNetworkUp_NotifyLinkChanged(PPDMINETWORKUP, PDMNETWORKLINKSTATE);
327static DECLCALLBACK(int) drvNATAsyncIoThread(PPDMDRVINS, PPDMTHREAD);
328static DECLCALLBACK(int) drvNATAsyncIoWakeup(PPDMDRVINS, PPDMTHREAD);
329static DECLCALLBACK(void *) drvNATQueryInterface(PPDMIBASE, const char *);
330static DECLCALLBACK(void) drvNATInfo(PPDMDRVINS, PCDBGFINFOHLP, const char *);
331
332static void slirpUpdateTimeout(uint32_t *, void *);
333static void slirpCheckTimeout(void *);
334
335static DECLCALLBACK(ssize_t) slirpSendPacketCb(const void *, size_t, void *);
336static DECLCALLBACK(void) slirpGuestErrorCb(const char *, void *);
337static DECLCALLBACK(int64_t) slirpClockGetNsCb(void *);
338static DECLCALLBACK(void *) slirpTimerNewCb(SlirpTimerCb, void *, void *);
339static DECLCALLBACK(void) slirpTimerFreeCb(void *, void *);
340static DECLCALLBACK(void) slirpTimerModCb(void *, int64_t, void *);
341
342static DECLCALLBACK(void) drvNATDestruct(PPDMDRVINS);
343static DECLCALLBACK(int) drvNATConstruct(PPDMDRVINS, PCFGMNODE, uint32_t);
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette