VirtualBox

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

Last change on this file since 105013 was 105013, checked in by vboxsync, 5 months ago

Devices/Network: scm fixes. bugref:10268

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