2
2
#include <stdlib.h>
3
3
#include <string.h>
4
4
5
+ #include <arpa/inet.h>
5
6
#include <getopt.h>
6
7
7
8
#include <availability.h>
12
13
#define VERSION "UNKNOWN"
13
14
#endif
14
15
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
+
15
22
static void print_usage (const char * argv0 ) {
16
23
printf ("Usage: %s [OPTION]... VDESWITCH\n" , argv0 );
17
24
printf ("vmnet.framework support for rootless QEMU.\n" );
18
25
printf ("vde_vmnet does not require QEMU to run as the root user, but "
19
26
"vde_vmnet itself has to run as the root, in most cases.\n" );
20
27
printf ("\n" );
21
28
printf ("--vde-group=GROUP VDE group name (default: "
22
- "\"staff \")\n" );
29
+ "\"" CLI_DEFAULT_VDE_GROUP " \")\n" );
23
30
printf (
24
31
"--vmnet-mode=(host|shared|bridged) vmnet mode (default: \"shared\")\n" );
25
32
printf ("--vmnet-interface=INTERFACE interface used for "
26
33
"--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" );
27
37
printf ("-h, --help display this help and exit\n" );
28
38
printf ("-v, --version display version information and "
29
39
"exit\n" );
@@ -36,20 +46,20 @@ static void print_version() { puts(VERSION); }
36
46
#define CLI_OPTIONS_ID_VDE_GROUP -42
37
47
#define CLI_OPTIONS_ID_VMNET_MODE -43
38
48
#define CLI_OPTIONS_ID_VMNET_INTERFACE -44
49
+ #define CLI_OPTIONS_ID_VMNET_GATEWAY -45
39
50
struct cli_options * cli_options_parse (int argc , char * argv []) {
40
51
struct cli_options * res = malloc (sizeof (* res ));
41
52
if (res == NULL ) {
42
53
goto error ;
43
54
}
44
55
memset (res , 0 , sizeof (* res ));
45
- res -> vde_group = strdup ("staff" ); /* use strdup to make it freeable */
46
- res -> vmnet_mode = VMNET_SHARED_MODE ;
47
56
48
57
const struct option longopts [] = {
49
58
{"vde-group" , required_argument , NULL , CLI_OPTIONS_ID_VDE_GROUP },
50
59
{"vmnet-mode" , required_argument , NULL , CLI_OPTIONS_ID_VMNET_MODE },
51
60
{"vmnet-interface" , required_argument , NULL ,
52
61
CLI_OPTIONS_ID_VMNET_INTERFACE },
62
+ {"vmnet-gateway" , required_argument , NULL , CLI_OPTIONS_ID_VMNET_GATEWAY },
53
63
{"help" , no_argument , NULL , 'h' },
54
64
{"version" , no_argument , NULL , 'v' },
55
65
{0 , 0 , 0 , 0 },
@@ -66,13 +76,7 @@ struct cli_options *cli_options_parse(int argc, char *argv[]) {
66
76
} else if (strcmp (optarg , "shared" ) == 0 ) {
67
77
res -> vmnet_mode = VMNET_SHARED_MODE ;
68
78
} else if (strcmp (optarg , "bridged" ) == 0 ) {
69
- #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
70
79
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
76
80
} else {
77
81
fprintf (stderr , "Unknown vmnet mode \"%s\"\n" , optarg );
78
82
goto error ;
@@ -81,6 +85,9 @@ struct cli_options *cli_options_parse(int argc, char *argv[]) {
81
85
case CLI_OPTIONS_ID_VMNET_INTERFACE :
82
86
res -> vmnet_interface = strdup (optarg );
83
87
break ;
88
+ case CLI_OPTIONS_ID_VMNET_GATEWAY :
89
+ res -> vmnet_gateway = strdup (optarg );
90
+ break ;
84
91
case 'h' :
85
92
print_usage (argv [0 ]);
86
93
cli_options_destroy (res );
@@ -102,14 +109,41 @@ struct cli_options *cli_options_parse(int argc, char *argv[]) {
102
109
goto error ;
103
110
}
104
111
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 */
106
121
if (res -> vmnet_mode == VMNET_BRIDGED_MODE && res -> vmnet_interface == NULL ) {
107
122
fprintf (
108
123
stderr ,
109
124
"vmnet mode \"bridged\" require --vmnet-interface to be specified\n" );
110
125
goto error ;
111
126
}
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
+ }
113
147
return res ;
114
148
error :
115
149
print_usage (argv [0 ]);
@@ -127,5 +161,7 @@ void cli_options_destroy(struct cli_options *x) {
127
161
free (x -> vde_switch );
128
162
if (x -> vmnet_interface != NULL )
129
163
free (x -> vmnet_interface );
164
+ if (x -> vmnet_gateway != NULL )
165
+ free (x -> vmnet_gateway );
130
166
free (x );
131
167
}
0 commit comments