-
Notifications
You must be signed in to change notification settings - Fork 0
/
vnet.h
454 lines (388 loc) · 12.3 KB
/
vnet.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
/*********************************************************
* Copyright (C) 1998 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#ifndef _VNET_H
#define _VNET_H
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMK_MODULE
#include "includeCheck.h"
#include "vm_basic_types.h"
#include "vm_atomic.h"
#include "monitorAction_exported.h"
#define VNET_PVN_ABI_ID_LEN (256 / 8) // bytes used on ioctl()
#define VNET_PVN_ID_LEN (160 / 8) // actual length used
#define VNET_BIND_VERSION 0x1
#define VNET_BIND_TO_VNET 0x1
#define VNET_BIND_TO_PVN 0x2
typedef struct VNet_Bind {
uint32 version; // VNET_BIND_VERSION
uint32 bindType; // VNET_BIND_TO_xxx
int32 number; // used for VNET_BIND_TO_VNET
uint8 id[VNET_PVN_ABI_ID_LEN]; // used for VNET_BIND_TO_PVN
} VNet_Bind;
/*
* We define customized ioctl commands by adding 0x1000
* to the standard Linux definitions.
*
* See comments in iocontrols.h
*/
#define VNET_FIRST_CMD 0x99F2
// #define SIOCSKEEP 0x99F0 // not used
// #define SIOCGKEEP 0x99F1 // not used
#define SIOCSLADRF 0x99F2
#define SIOCPORT 0x99F3
#define SIOCBRIDGE 0x99F4
#define SIOCNETIF 0x99F5
#define SIOCSETMACADDR 0x99F6
#define SIOCSSWITCHMAP 0x99F7
#define SIOCSETNOTIFY 0x99F8
#define SIOCUNSETNOTIFY 0x99F9
// #define SIOCSETCLUSTERSIZE 0x99FA // obsolete
#define SIOCSETNOTIFY2 0x99FB
#define SIOCGETAPIVERSION 0x99FC
#define SIOCINJECTLINKSTATE 0x99FD
#define VNET_NOTIFY_VERSION 5
#define VNET_LAST_CMD 0x99FD
#if defined __linux__ || defined __APPLE__
#define SIOCGETAPIVERSION2 _IOWR(0x99, 0xE0, uint32)
#define SIOCGBRSTATUS _IOR(0x99, 0xFD, uint32)
#define SIOCSPEER _IOW(0x99, 0xFE, char[8])
#define SIOCSPEER2 _IOW(0x99, 0xFE, char[32])
#define SIOCSBIND _IOW(0x99, 0xFF, VNet_Bind)
#define SIOCSFILTERRULES _IOW(0x99, 0xE1, VNet_RuleHeader)
#define SIOCSUSERLISTENER _IOW(0x99, 0xE2, VNet_SetUserListener)
#define SIOCSMCASTFILTER _IOW(0x99, 0xE3, VNetMcastFilter)
#endif
#if defined __linux__
#define VNET_BRFLAG_FORCE_SMAC 0x00000001
typedef
#include "vmware_pack_begin.h"
struct VNet_BridgeParams {
char name[32];
uint32 flags;
}
#include "vmware_pack_end.h"
VNet_BridgeParams;
#define SIOCSPEER3 _IOW(0x99, 0xE4, VNet_BridgeParams)
#endif
#ifdef __APPLE__
#define VMNET_KEXT_NAME_BASE "com.vmware.kext.vmnet"
#ifdef VMX86_DEVEL
#define VMNET_KEXT_NAME VMNET_KEXT_NAME_BASE ".devel"
#else
#define VMNET_KEXT_NAME VMNET_KEXT_NAME_BASE
#endif
/*
* We use [gs]etsockopt on Mac OS instead of ioctls for operations on vmnet
*/
enum VMNetSockOpt {
VMNET_SO_APIVERSION = 0, // Must come first, should never change
VMNET_SO_BRSTATUS,
VMNET_SO_PEER,
VMNET_SO_BINDTOHUB,
VMNET_SO_IFADDR,
VMNET_SO_NETIFCREATE,
VMNET_SO_IFFLAGS,
VMNET_SO_LADRF,
VMNET_SO_BRCREATE,
VMNET_SO_SETNOTIFY,
VMNET_SO_READDATA,
VMNET_SO_UNSETNOTIFY,
VMNET_SO_SETUSERLISTENER,
VMNET_SO_MCASTFILTER,
VMNET_SO_INJECTLINKSTATE,
};
/*
* This magic value is populated in VNet_Notify.actionID and VNet_Notify.pollMask
* to request the driver to clear the Notify pollPtr if the receive queue is empty.
*/
#define VNET_NOTIFY_CLR_MAGIC 0xDECAFBAD
typedef struct VNet_NetIf {
char name[16]; // The BSD name of the interface
uint8 instance; // The "unit number" of the interface
} VNet_NetIf;
typedef
#include "vmware_pack_begin.h"
struct {
char name[16]; // IN: BSD name of the interface to bridge.
int media; // IN: Media of the interface to bridge.
}
#include "vmware_pack_end.h"
VNet_Bridge;
#ifdef LATER
typedef struct VNet_Read {
VA uAddr; // Buffer to read into
size_t len; // Max number of bytes to read
} VNet_Read;
#endif
#endif
/*
* VMnet driver version.
*
* Increment major version when you make an incompatible change.
* Compatibility goes both ways (old driver with new executable
* as well as new driver with old executable).
*/
#ifdef linux
#define VNET_API_VERSION (3 << 16 | 0)
#elif defined __APPLE__
#define VNET_API_VERSION (6 << 16 | 0)
#else
#define VNET_API_VERSION (5 << 16 | 0)
#endif
#define VNET_API_VERSION_MAJOR(v) ((uint32) (v) >> 16)
#define VNET_API_VERSION_MINOR(v) ((uint16) (v))
/* version 1 structure */
typedef struct VNet_SetMacAddrIOCTL {
int version;
unsigned char addr[6];
unsigned flags;
} VNet_SetMacAddrIOCTL;
typedef
#include "vmware_pack_begin.h"
struct VNet_Notify {
uint32 version;
uint32 actionVersion; /* Version of monitor action logic */
VA64 actPtr; /* User VA of a MonitorActionIntr */
VA64 pollPtr; /* User VA of a volatile uint32 */
VA64 recvClusterPtr; /* User VA of a uint32 */
MonitorIdemAction actionID;
uint32 pollMask;
}
#include "vmware_pack_end.h"
VNet_Notify;
#define VNET_SETMACADDRF_UNIQUE 0x01
/*
* The latest 802.3 standard sort of says that the length field ought to
* be less than 1536 (for VLAN tagging support). I am choosing 1532
* as our max VNET_MTU size, as I'd rather keep it a multiple of 4 and
* VLAN tagging uses only upto 1518 bytes.
*/
#define VNET_MTU 1532
#define VNET_BUF_TOO_SMALL (-1)
/*
* vlan switch stuff
*/
#define VNET_MAX_VLANS 255
struct VNetSwitchMap {
int trunk;
int vlan;
int connect;
int vnet;
};
/*
* The upper limit of exact multicast filter
* length used by vmnet layer. It should be
* equal to MAC_MAX_EXACT_FILTER_LEN.
*/
#define VNET_MAX_EXACT_FILTER_LEN 32
/* multicast filter in Vmnet layer */
typedef
#include "vmware_pack_begin.h"
struct VNetMcastFilter {
uint32 exactFilterLen;
uint32 ladrf[2];
uint8 exactFilter[VNET_MAX_EXACT_FILTER_LEN][6];
}
#include "vmware_pack_end.h"
VNetMcastFilter;
/*
*----------------------------------------------------------------------------
* VNetEvent
*----------------------------------------------------------------------------
*/
/* the current version */
#define VNET_EVENT_VERSION 1
/* event classes */
#define VNET_EVENT_CLASS_UPLINK 1
/* event types */
#define VNET_EVENT_TYPE_LINK_STATE 0
/* parameter for SIOCSUSERLISTENER */
typedef
#include "vmware_pack_begin.h"
struct VNet_SetUserListener {
uint32 version;
uint32 classMask;
}
#include "vmware_pack_end.h"
VNet_SetUserListener;
/* the event header */
typedef
#include "vmware_pack_begin.h"
struct VNet_EventHeader {
uint32 size;
uint32 senderId;
uint32 eventId;
uint32 classSet;
uint32 type;
}
#include "vmware_pack_end.h"
VNet_EventHeader;
/*
* the link state event
* header = { sizeof(VNet_LinkStateEvent), ?, ?, VNET_EVENT_CLASS_BRIDGE,
* VNET_EVENT_TYPE_LINK_STATE }
*/
typedef
#include "vmware_pack_begin.h"
struct VNet_LinkStateEvent {
VNet_EventHeader header;
uint32 adapter;
Bool up;
char _pad[3];
}
#include "vmware_pack_end.h"
VNet_LinkStateEvent;
/*
*----------------------------------------------------------------------------
*/
#if defined __APPLE__ && !defined KERNEL
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/kern_control.h>
#include <sys/socket.h>
#include <sys/sys_domain.h>
#include "str.h"
/*
*----------------------------------------------------------------------------
*
* VMNetOpen --
*
* Create a socket connected to the vmnet kernel control extension, bind
* it to a vmnet hub. Optionally make the socket non-blocking. Optionally
* set the interface MAC address. Optionally set interface flags.
*
* Results:
* Connected and bound socket on success.
* -1 on failure, returns error message in the "error" parameter.
*
* Side Effects:
* Allocates memory for returning "error" message to caller. Caller should
* remember to free(error).
*
*----------------------------------------------------------------------------
*/
static INLINE int
VMNetOpen(int hubNum, // IN: hub number to bind to
Bool nonBlocking, // IN: make socket non-blocking
VNet_SetMacAddrIOCTL *ifAddr, // IN: optional MAC address
uint32 flags, // IN: optional interface flags
char **error) // OUT: error message on failures
{
int fd;
struct sockaddr_ctl addr;
struct ctl_info info;
socklen_t optlen;
uint32 apiVersion;
fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
if (fd == -1) {
if (error) {
*error = Str_Asprintf(NULL, "Failed to create control socket: "
"errno %d\n", errno);
}
return -1;
}
bzero(&addr, sizeof addr);
addr.sc_len = sizeof addr;
addr.sc_family = AF_SYSTEM;
addr.ss_sysaddr = AF_SYS_CONTROL;
memset(&info, 0, sizeof info);
strncpy(info.ctl_name, VMNET_KEXT_NAME, sizeof info.ctl_name);
if (ioctl(fd, CTLIOCGINFO, &info)) {
if (error) {
*error = Str_Asprintf(NULL, "ioctl(CTLIOCGINFO) failed: errno %d\n",
errno);
}
goto exit_failure;
}
addr.sc_id = info.ctl_id;
if (connect(fd, (struct sockaddr *)&addr, sizeof addr) < 0) {
if (error) {
*error = Str_Asprintf(NULL, "Connect to vmnet kext failed: errno %d\n",
errno);
}
goto exit_failure;
}
/* Optionally make socket non-blocking */
if (nonBlocking) {
int fFlags;
fFlags = fcntl(fd, F_GETFL);
if (fFlags == -1 || fcntl(fd, F_SETFL, fFlags | O_NONBLOCK) < 0) {
if (error) {
*error = Str_Asprintf(NULL, "Couldn't make socket non-blocking: "
"errno %d\n", errno);
}
goto exit_failure;
}
}
optlen = sizeof apiVersion;
if (getsockopt(fd, SYSPROTO_CONTROL, VMNET_SO_APIVERSION, &apiVersion,
&optlen) < 0) {
if (error) {
*error = Str_Asprintf(NULL, "getsockopt(VMNET_SO_APIVERSION) failed: "
"errno %d\n", errno);
}
goto exit_failure;
}
if (VNET_API_VERSION_MAJOR(apiVersion) !=
VNET_API_VERSION_MAJOR(VNET_API_VERSION)) {
if (error) {
*error = Str_Asprintf(NULL, "Module version mismatch. Please update "
"host.\n");
}
goto exit_failure;
}
if (setsockopt(fd, SYSPROTO_CONTROL, VMNET_SO_BINDTOHUB, &hubNum,
sizeof hubNum) < 0) {
if (error) {
*error = Str_Asprintf(NULL, "Could not bind to hub %d: errno %d\n",
hubNum, errno);
}
goto exit_failure;
}
/* Optionally set MAC address */
if (ifAddr) {
if (setsockopt(fd, SYSPROTO_CONTROL, VMNET_SO_IFADDR, ifAddr,
sizeof (*ifAddr)) < 0) {
if (error) {
*error = Str_Asprintf(NULL, "Could not set MAC address: errno %d\n",
errno);
}
goto exit_failure;
}
}
/* Optionally set interface flags */
if (flags) {
if (setsockopt(fd, SYSPROTO_CONTROL, VMNET_SO_IFFLAGS, &flags,
sizeof flags) < 0) {
if (error) {
*error = Str_Asprintf(NULL, "Could not set interface flags to 0x%x: "
"errno %d\n", flags, errno);
}
goto exit_failure;
}
}
/* Return success */
return fd;
exit_failure:
/* Return failure */
close(fd);
return -1;
}
#endif // __APPLE__ && ! KERNEL
#endif