Skip to content
This repository was archived by the owner on May 4, 2024. It is now read-only.

Commit db729b7

Browse files
authored
Merge pull request #8 from AkihiroSuda/dev
support --vmnet-gateway=IP, e.g., 192.168.105.1 + drop support for macOS 10.14
2 parents 97a1ef6 + 5c15182 commit db729b7

File tree

7 files changed

+110
-26
lines changed

7 files changed

+110
-26
lines changed

README.md

+6-8
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
## Install
1010

11+
Requires macOS 10.15 or later.
12+
1113
```console
1214
brew install vde
1315

@@ -20,12 +22,10 @@ The following files will be installed:
2022
- `/usr/local/bin/vde_vmnet`
2123
- `/Library/LaunchDaemons/io.github.virtualsquare.vde-2.vde_switch.plist`
2224
- `/Library/LaunchDaemons/io.github.AkihiroSuda.vde_vmnet.plist`
25+
- Configured to use `192.168.105.0/24`. Modifiy the file if it conflicts with your local network.
2326

2427
See ["Testing without launchd"](#testing-without-launchd) if you don't prefer to use launchd.
2528

26-
27-
:warning: Known to conflict with VMware Fusion. See issue [#7](https://github.com/AkihiroSuda/vde_vmnet/issues/7).
28-
2929
## Usage
3030

3131
```console
@@ -58,8 +58,6 @@ The following additional files will be installed:
5858

5959
Use `/var/run/vde.bridged.en0.ctl` as the VDE socket path.
6060

61-
Needs macOS 10.15 or later.
62-
6361
## Advanced usage
6462

6563
### Testing without launchd
@@ -75,7 +73,7 @@ vde_switch --unix /tmp/vde.ctl
7573
```
7674

7775
```console
78-
sudo vde_vmnet /tmp/vde.ctl
76+
sudo vde_vmnet --vmnet-gateway=192.168.105.1 /tmp/vde.ctl
7977
```
8078

8179
Note: make sure to run `vde_vmnet` with root (`sudo`). See [FAQs](#FAQs) for the reason.
@@ -125,14 +123,14 @@ On the other hand, `vde_vmnet` does not require the entire QEMU process to run a
125123

126124
- Decide a unique MAC address for the VM, e.g. `de:ad:be:ef:00:01`.
127125

128-
- Decide a static IP address, e.g., "192.168.60.100"
126+
- Decide a static IP address, e.g., "192.168.105.100"
129127

130128
- Create `/etc/bootptab` like this. Make sure not to drop the "%%" header.
131129
```
132130
# bootptab
133131
%%
134132
# hostname hwtype hwaddr ipaddr bootfile
135-
tmp-vm01 1 de:ad:be:ef:00:01 192.168.60.100
133+
tmp-vm01 1 de:ad:be:ef:00:01 192.168.105.100
136134
```
137135

138136
- Reload the DHCP daemon.

cli.c

+47-11
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <stdlib.h>
33
#include <string.h>
44

5+
#include <arpa/inet.h>
56
#include <getopt.h>
67

78
#include <availability.h>
@@ -12,18 +13,27 @@
1213
#define VERSION "UNKNOWN"
1314
#endif
1415

16+
#if __MAC_OS_X_VERSION_MAX_ALLOWED < 101500
17+
#error "Requires macOS 10.15 or later"
18+
#endif
19+
20+
#define CLI_DEFAULT_VDE_GROUP "staff"
21+
1522
static void print_usage(const char *argv0) {
1623
printf("Usage: %s [OPTION]... VDESWITCH\n", argv0);
1724
printf("vmnet.framework support for rootless QEMU.\n");
1825
printf("vde_vmnet does not require QEMU to run as the root user, but "
1926
"vde_vmnet itself has to run as the root, in most cases.\n");
2027
printf("\n");
2128
printf("--vde-group=GROUP VDE group name (default: "
22-
"\"staff\")\n");
29+
"\"" CLI_DEFAULT_VDE_GROUP "\")\n");
2330
printf(
2431
"--vmnet-mode=(host|shared|bridged) vmnet mode (default: \"shared\")\n");
2532
printf("--vmnet-interface=INTERFACE interface used for "
2633
"--vmnet=bridged, e.g., \"en0\"\n");
34+
printf("--vmnet-gateway=IP gateway used for "
35+
"--vmnet=(host|shared), e.g., \"192.168.105.1\" (default: decided by "
36+
"macOS)\n");
2737
printf("-h, --help display this help and exit\n");
2838
printf("-v, --version display version information and "
2939
"exit\n");
@@ -36,20 +46,20 @@ static void print_version() { puts(VERSION); }
3646
#define CLI_OPTIONS_ID_VDE_GROUP -42
3747
#define CLI_OPTIONS_ID_VMNET_MODE -43
3848
#define CLI_OPTIONS_ID_VMNET_INTERFACE -44
49+
#define CLI_OPTIONS_ID_VMNET_GATEWAY -45
3950
struct cli_options *cli_options_parse(int argc, char *argv[]) {
4051
struct cli_options *res = malloc(sizeof(*res));
4152
if (res == NULL) {
4253
goto error;
4354
}
4455
memset(res, 0, sizeof(*res));
45-
res->vde_group = strdup("staff"); /* use strdup to make it freeable */
46-
res->vmnet_mode = VMNET_SHARED_MODE;
4756

4857
const struct option longopts[] = {
4958
{"vde-group", required_argument, NULL, CLI_OPTIONS_ID_VDE_GROUP},
5059
{"vmnet-mode", required_argument, NULL, CLI_OPTIONS_ID_VMNET_MODE},
5160
{"vmnet-interface", required_argument, NULL,
5261
CLI_OPTIONS_ID_VMNET_INTERFACE},
62+
{"vmnet-gateway", required_argument, NULL, CLI_OPTIONS_ID_VMNET_GATEWAY},
5363
{"help", no_argument, NULL, 'h'},
5464
{"version", no_argument, NULL, 'v'},
5565
{0, 0, 0, 0},
@@ -66,13 +76,7 @@ struct cli_options *cli_options_parse(int argc, char *argv[]) {
6676
} else if (strcmp(optarg, "shared") == 0) {
6777
res->vmnet_mode = VMNET_SHARED_MODE;
6878
} else if (strcmp(optarg, "bridged") == 0) {
69-
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
7079
res->vmnet_mode = VMNET_BRIDGED_MODE;
71-
#else
72-
fprintf(stderr,
73-
"vmnet mode \"bridged\" requires macOS 10.15 or later\n");
74-
goto error;
75-
#endif
7680
} else {
7781
fprintf(stderr, "Unknown vmnet mode \"%s\"\n", optarg);
7882
goto error;
@@ -81,6 +85,9 @@ struct cli_options *cli_options_parse(int argc, char *argv[]) {
8185
case CLI_OPTIONS_ID_VMNET_INTERFACE:
8286
res->vmnet_interface = strdup(optarg);
8387
break;
88+
case CLI_OPTIONS_ID_VMNET_GATEWAY:
89+
res->vmnet_gateway = strdup(optarg);
90+
break;
8491
case 'h':
8592
print_usage(argv[0]);
8693
cli_options_destroy(res);
@@ -102,14 +109,41 @@ struct cli_options *cli_options_parse(int argc, char *argv[]) {
102109
goto error;
103110
}
104111
res->vde_switch = strdup(argv[optind]);
105-
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
112+
113+
/* fill default */
114+
if (res->vde_group == NULL)
115+
res->vde_group =
116+
strdup(CLI_DEFAULT_VDE_GROUP); /* use strdup to make it freeable */
117+
if (res->vmnet_mode == 0)
118+
res->vmnet_mode = VMNET_SHARED_MODE;
119+
120+
/* validate */
106121
if (res->vmnet_mode == VMNET_BRIDGED_MODE && res->vmnet_interface == NULL) {
107122
fprintf(
108123
stderr,
109124
"vmnet mode \"bridged\" require --vmnet-interface to be specified\n");
110125
goto error;
111126
}
112-
#endif
127+
if (res->vmnet_gateway == NULL) {
128+
if (res->vmnet_mode != VMNET_BRIDGED_MODE) {
129+
fprintf(stderr,
130+
"WARNING: --vmnet-gateway=IP should be explicitly specified to "
131+
"avoid conflicting with other applications\n");
132+
}
133+
} else {
134+
if (res->vmnet_mode == VMNET_BRIDGED_MODE) {
135+
fprintf(stderr,
136+
"vmnet mode \"bridged\" conflicts with --vmnet-gateway\n");
137+
goto error;
138+
}
139+
struct in_addr dummy;
140+
if (!inet_aton(res->vmnet_gateway, &dummy)) {
141+
fprintf(stderr,
142+
"invalid address \"%s\" was specified for --vmnet-gateway\n",
143+
res->vmnet_gateway);
144+
goto error;
145+
}
146+
}
113147
return res;
114148
error:
115149
print_usage(argv[0]);
@@ -127,5 +161,7 @@ void cli_options_destroy(struct cli_options *x) {
127161
free(x->vde_switch);
128162
if (x->vmnet_interface != NULL)
129163
free(x->vmnet_interface);
164+
if (x->vmnet_gateway != NULL)
165+
free(x->vmnet_gateway);
130166
free(x);
131167
}

cli.h

+10-4
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,16 @@
44
#include <vmnet/vmnet.h>
55

66
struct cli_options {
7-
char *vde_group; // --vde-group
8-
operating_modes_t vmnet_mode; // --vmnet-mode
9-
char *vmnet_interface; // --vmnet-interface
10-
char *vde_switch; // arg
7+
// --vde-group
8+
char *vde_group;
9+
// --vmnet-mode, corresponds to vmnet_operation_mode_key
10+
operating_modes_t vmnet_mode;
11+
// --vmnet-interface, corresponds to vmnet_shared_interface_name_key
12+
char *vmnet_interface;
13+
// --vmnet-gateway, corresponds to vmnet_start_address_key
14+
char *vmnet_gateway;
15+
// arg
16+
char *vde_switch;
1117
};
1218

1319
struct cli_options *cli_options_parse(int argc, char *argv[]);

launchd/io.github.AkihiroSuda.vde_vmnet.plist

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<key>ProgramArguments</key>
1010
<array>
1111
<string>/usr/local/bin/vde_vmnet</string>
12+
<string>--vmnet-gateway=192.168.105.1</string>
1213
<string>/var/run/vde.ctl</string>
1314
</array>
1415
<key>StandardErrorPath</key>
@@ -28,4 +29,4 @@
2829
</dict>
2930
</dict>
3031
</dict>
31-
</plist>
32+
</plist>

main.c

+32
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,18 @@
33
#include <stdlib.h>
44
#include <sys/uio.h>
55

6+
#include <arpa/inet.h>
7+
68
#include <vmnet/vmnet.h>
79

810
#include <libvdeplug.h>
911

1012
#include "cli.h"
1113

14+
#if __MAC_OS_X_VERSION_MAX_ALLOWED < 101500
15+
#error "Requires macOS 10.15 or later"
16+
#endif
17+
1218
static bool debug = false;
1319

1420
#define DEBUGF(fmt, ...) \
@@ -159,6 +165,32 @@ static interface_ref start(VDECONN *vdeconn, struct cli_options *cliopt) {
159165
xpc_dictionary_set_string(dict, vmnet_shared_interface_name_key,
160166
cliopt->vmnet_interface);
161167
}
168+
if (cliopt->vmnet_gateway != NULL) {
169+
/* Set vmnet_start_address_key */
170+
xpc_dictionary_set_string(dict, vmnet_start_address_key,
171+
cliopt->vmnet_gateway);
172+
173+
/* Set vmnet_end_address_key with .254 */
174+
struct in_addr sin;
175+
if (!inet_aton(cliopt->vmnet_gateway, &sin)) {
176+
perror("inet_aton(cliopt->vmnet_gateway)");
177+
return NULL;
178+
}
179+
uint32_t h = ntohl(sin.s_addr);
180+
h &= 0xFFFFFF00;
181+
h |= 0x000000FE;
182+
sin.s_addr = htonl(h);
183+
184+
const char *end = inet_ntoa(sin); /* static storage, do not free */
185+
if (end == NULL) {
186+
perror("inet_ntoa");
187+
return NULL;
188+
}
189+
xpc_dictionary_set_string(dict, vmnet_end_address_key, end);
190+
191+
/* Set vmnet_subnet_mask_key */
192+
xpc_dictionary_set_string(dict, vmnet_subnet_mask_key, "255.255.255.0");
193+
}
162194

163195
uuid_t uuid;
164196
// TODO: support deterministic UUID and MAC address

test/test.ipxe

+7-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ show netmask
1010
show dns
1111
show dhcp-server
1212
echo </vde_vmnet:iPXE-testing>
13-
# sleep for flushing the serial console
13+
14+
echo [testing Internet connection]
15+
imgfetch http://google.com/
16+
17+
echo [sleeping for flushing the serial console]
1418
sleep 1
19+
20+
echo [exiting]
1521
reboot

test/test.sh

+6-1
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,14 @@ if ! grep -q "net0/mac:hex = 52:54:00:12:34:56" serial.log; then
2929
exit 1
3030
fi
3131

32-
if ! grep -q "net0.dhcp/ip:ipv4 = 192.168." serial.log; then
32+
if ! grep -q "net0.dhcp/ip:ipv4 = 192.168.105." serial.log; then
3333
echo >&2 "ERROR: net0.dhcp/ip:ipv4 not found"
3434
exit 1
3535
fi
3636

37+
if ! grep -q "net0.dhcp/gateway:ipv4 = 192.168.105.1" serial.log; then
38+
echo >&2 "ERROR: net0.dhcp/gateway:ipv4 not found"
39+
exit 1
40+
fi
41+
3742
rm -f serial.log

0 commit comments

Comments
 (0)