VirtualBox

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

Last change on this file since 105070 was 105070, checked in by vboxsync, 7 months ago

Devices/Network: code cleanup. bugref:10268

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.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#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#define GET_EXTRADATA(pdrvins, node, name, rc, type, type_name, var) \
106do { \
107 (rc) = (pdrvins)->pHlpR3->pfnCFGMQuery ## type((node), name, &(var)); \
108 if (RT_FAILURE((rc)) && (rc) != VERR_CFGM_VALUE_NOT_FOUND) \
109 return PDMDrvHlpVMSetError((pdrvins), (rc), RT_SRC_POS, N_("NAT#%d: configuration query for \"" name "\" " #type_name " failed"), \
110 (pdrvins)->iInstance); \
111} while (0)
112
113#define GET_ED_STRICT(pdrvins, node, name, rc, type, type_name, var) \
114do { \
115 (rc) = (pdrvins)->pHlpR3->pfnCFGMQuery ## type((node), name, &(var)); \
116 if (RT_FAILURE((rc))) \
117 return PDMDrvHlpVMSetError((pdrvins), (rc), RT_SRC_POS, N_("NAT#%d: configuration query for \"" name "\" " #type_name " failed"), \
118 (pdrvins)->iInstance); \
119} while (0)
120
121#define GET_EXTRADATA_N(pdrvins, node, name, rc, type, type_name, var, var_size) \
122do { \
123 (rc) = (pdrvins)->pHlpR3->pfnCFGMQuery ## type((node), name, &(var), var_size); \
124 if (RT_FAILURE((rc)) && (rc) != VERR_CFGM_VALUE_NOT_FOUND) \
125 return PDMDrvHlpVMSetError((pdrvins), (rc), RT_SRC_POS, N_("NAT#%d: configuration query for \"" name "\" " #type_name " failed"), \
126 (pdrvins)->iInstance); \
127} while (0)
128
129#define GET_BOOL(rc, pdrvins, node, name, var) \
130 GET_EXTRADATA(pdrvins, node, name, (rc), Bool, bolean, (var))
131#define GET_STRING(rc, pdrvins, node, name, var, var_size) \
132 GET_EXTRADATA_N(pdrvins, node, name, (rc), String, string, (var), (var_size))
133#define GET_STRING_ALLOC(rc, pdrvins, node, name, var) \
134 GET_EXTRADATA(pdrvins, node, name, (rc), StringAlloc, string, (var))
135#define GET_S32(rc, pdrvins, node, name, var) \
136 GET_EXTRADATA(pdrvins, node, name, (rc), S32, int, (var))
137#define GET_S32_STRICT(rc, pdrvins, node, name, var) \
138 GET_ED_STRICT(pdrvins, node, name, (rc), S32, int, (var))
139
140#define DO_GET_IP(rc, node, instance, status, x) \
141do { \
142 char sz##x[32]; \
143 GET_STRING((rc), (node), (instance), #x, sz ## x[0], sizeof(sz ## x)); \
144 if (rc != VERR_CFGM_VALUE_NOT_FOUND) \
145 (status) = inet_aton(sz ## x, &x); \
146} while (0)
147
148#define GETIP_DEF(rc, node, instance, x, def) \
149do \
150{ \
151 int status = 0; \
152 DO_GET_IP((rc), (node), (instance), status, x); \
153 if (status == 0 || rc == VERR_CFGM_VALUE_NOT_FOUND) \
154 x.s_addr = def; \
155} while (0)
156
157/** Slirp Timer */
158typedef struct slirpTimer {
159 struct slirpTimer *next;
160 int64_t uTimeExpire;
161 SlirpTimerCb pHandler;
162 void *opaque;
163} SlirpTimer;
164
165/**
166 * Main state of Libslirp NAT
167 */
168typedef struct SlirpState
169{
170 unsigned int nsock;
171
172 Slirp *pSlirp;
173 struct pollfd *polls;
174
175 /** Num Polls (not bytes) */
176 unsigned int uPollCap = 0;
177
178 SlirpTimer *pTimerHead;
179} SlirpState;
180typedef SlirpState *pSlirpState;
181
182/**
183 * NAT network transport driver instance data.
184 *
185 * @implements PDMINETWORKUP
186 */
187typedef struct DRVNAT
188{
189 /** The network interface. */
190 PDMINETWORKUP INetworkUp;
191 /** The network NAT Engine configuration. */
192 PDMINETWORKNATCONFIG INetworkNATCfg;
193 /** The port we're attached to. */
194 PPDMINETWORKDOWN pIAboveNet;
195 /** The network config of the port we're attached to. */
196 PPDMINETWORKCONFIG pIAboveConfig;
197 /** Pointer to the driver instance. */
198 PPDMDRVINS pDrvIns;
199 /** Link state */
200 PDMNETWORKLINKSTATE enmLinkState;
201 /** NAT state */
202 pSlirpState pNATState;
203 /** TFTP directory prefix. */
204 char *pszTFTPPrefix;
205 /** Boot file name to provide in the DHCP server response. */
206 char *pszBootFile;
207 /** tftp server name to provide in the DHCP server response. */
208 char *pszNextServer;
209 /** Polling thread. */
210 PPDMTHREAD pSlirpThread;
211 /** Queue for NAT-thread-external events. */
212 RTREQQUEUE hSlirpReqQueue;
213 /** The guest IP for port-forwarding. */
214 uint32_t GuestIP;
215 /** Link state set when the VM is suspended. */
216 PDMNETWORKLINKSTATE enmLinkStateWant;
217
218#ifndef RT_OS_WINDOWS
219 /** The write end of the control pipe. */
220 RTPIPE hPipeWrite;
221 /** The read end of the control pipe. */
222 RTPIPE hPipeRead;
223# if HC_ARCH_BITS == 32
224 uint32_t u32Padding;
225# endif
226#else
227 /** for external notification */
228 HANDLE hWakeupEvent;
229#endif
230
231#define DRV_PROFILE_COUNTER(name, dsc) STAMPROFILE Stat ## name
232#define DRV_COUNTING_COUNTER(name, dsc) STAMCOUNTER Stat ## name
233#include "slirp/counters.h"
234 /** thread delivering packets for receiving by the guest */
235 PPDMTHREAD pRecvThread;
236 /** event to wakeup the guest receive thread */
237 RTSEMEVENT EventRecv;
238 /** Receive Req queue (deliver packets to the guest) */
239 RTREQQUEUE hRecvReqQueue;
240
241 /** makes access to device func RecvAvail and Recv atomical. */
242 RTCRITSECT DevAccessLock;
243 /** Number of in-flight packets. */
244 volatile uint32_t cPkts;
245
246 /** Transmit lock taken by BeginXmit and released by EndXmit. */
247 RTCRITSECT XmitLock;
248
249#ifdef RT_OS_DARWIN
250 /* Handle of the DNS watcher runloop source. */
251 CFRunLoopSourceRef hRunLoopSrcDnsWatcher;
252#endif /* !VBOX_INCLUDED_SRC_Network_DrvNATlibslirp_h */
253} DRVNAT;
254AssertCompileMemberAlignment(DRVNAT, StatNATRecvWakeups, 8);
255/** Pointer to the NAT driver instance data. */
256typedef DRVNAT *PDRVNAT;
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_AllocBuf(PPDMINETWORKUP, size_t,
264 PCPDMNETWORKGSO, PPPDMSCATTERGATHER);
265static DECLCALLBACK(int) drvNATNetworkUp_FreeBuf(PPDMINETWORKUP, PPDMSCATTERGATHER);
266static DECLCALLBACK(int) drvNATNetworkUp_SendBuf(PPDMINETWORKUP, PPDMSCATTERGATHER, bool);
267static DECLCALLBACK(void) drvNATNetworkUp_EndXmit(PPDMINETWORKUP );
268static void drvNATNotifyNATThread(PDRVNAT pThis, const char *);
269static DECLCALLBACK(void) drvNATNetworkUp_SetPromiscuousMode(PPDMINETWORKUP, bool);
270static DECLCALLBACK(void) drvNATNotifyLinkChangedWorker(PDRVNAT, PDMNETWORKLINKSTATE);
271static DECLCALLBACK(void) drvNATNetworkUp_NotifyLinkChanged(PPDMINETWORKUP, PDMNETWORKLINKSTATE);
272static DECLCALLBACK(int) drvNATAsyncIoThread(PPDMDRVINS, PPDMTHREAD);
273static DECLCALLBACK(int) drvNATAsyncIoWakeup(PPDMDRVINS, PPDMTHREAD);
274static DECLCALLBACK(void *) drvNATQueryInterface(PPDMIBASE, const char *);
275static DECLCALLBACK(void) drvNATInfo(PPDMDRVINS, PCDBGFINFOHLP, const char *);
276
277static void slirpUpdateTimeout(uint32_t *, void *);
278static void slirpCheckTimeout(void *);
279
280static DECLCALLBACK(ssize_t) slirpSendPacketCb(const void *, size_t, void *);
281static DECLCALLBACK(void) slirpGuestErrorCb(const char *, void *);
282static DECLCALLBACK(int64_t) slirpClockGetNsCb(void *);
283static DECLCALLBACK(void *) slirpTimerNewCb(SlirpTimerCb, void *, void *);
284static DECLCALLBACK(void) slirpTimerFreeCb(void *, void *);
285static DECLCALLBACK(void) slirpTimerModCb(void *, int64_t, void *);
286
287static DECLCALLBACK(void) drvNATDestruct(PPDMDRVINS);
288static 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