26
26
#define DEFAULT_VDHCPSTART_OFFSET (15) // 10.0.2.15
27
27
#define DEFAULT_VNAMESERVER_OFFSET (3) // 10.0.2.3
28
28
#define DEFAULT_RECOMMENDED_VGUEST_OFFSET (100) // 10.0.2.100
29
+ #define DEFAULT_NETNS_TYPE ("pid")
29
30
#define NETWORK_PREFIX_MIN (1)
30
31
// >=26 is not supported because the recommended guest IP is set to network addr + 100 .
31
32
#define NETWORK_PREFIX_MAX (25)
32
33
33
- static int nsenter (pid_t target_pid )
34
+ static int nsenter (pid_t target_pid , char * netns , char * userns )
34
35
{
35
- char userns [32 ], netns [32 ];
36
36
int usernsfd , netnsfd ;
37
- snprintf (userns , sizeof (userns ), "/proc/%d/ns/user" , target_pid );
38
- snprintf (netns , sizeof (netns ), "/proc/%d/ns/net" , target_pid );
39
- if ((usernsfd = open (userns , O_RDONLY )) < 0 ) {
40
- perror (userns );
41
- return usernsfd ;
37
+ if (!netns ) {
38
+ if (asprintf (& netns , "/proc/%d/ns/net" , target_pid ) < 0 ) {
39
+ perror ("cannot get netns path" );
40
+ return -1 ;
41
+ }
42
+ }
43
+ if (!userns ) {
44
+ if (asprintf (& userns , "/proc/%d/ns/user" , target_pid ) < 0 ) {
45
+ perror ("cannot get userns path" );
46
+ return -1 ;
47
+ }
42
48
}
43
49
if ((netnsfd = open (netns , O_RDONLY )) < 0 ) {
44
50
perror (netns );
45
51
return netnsfd ;
46
52
}
53
+ if ((usernsfd = open (userns , O_RDONLY )) < 0 ) {
54
+ perror (userns );
55
+ return usernsfd ;
56
+ }
47
57
setns (usernsfd , CLONE_NEWUSER );
48
58
if (setns (netnsfd , CLONE_NEWNET ) < 0 ) {
49
59
perror ("setns(CLONE_NEWNET)" );
50
60
return -1 ;
51
61
}
52
62
close (usernsfd );
53
63
close (netnsfd );
64
+ free (netns );
65
+ free (userns );
54
66
return 0 ;
55
67
}
56
68
@@ -165,11 +177,11 @@ static int configure_network(const char *tapname, struct slirp4netns_config *cfg
165
177
return 0 ;
166
178
}
167
179
168
- static int child (int sock , pid_t target_pid , bool do_config_network , const char * tapname , int ready_fd ,
180
+ static int child (int sock , pid_t target_pid , bool do_config_network , const char * tapname , int ready_fd , char * netns_path , char * userns_path ,
169
181
struct slirp4netns_config * cfg )
170
182
{
171
183
int rc , tapfd ;
172
- if ((rc = nsenter (target_pid )) < 0 ) {
184
+ if ((rc = nsenter (target_pid , netns_path , userns_path )) < 0 ) {
173
185
return rc ;
174
186
}
175
187
if ((tapfd = open_tap (tapname )) < 0 ) {
@@ -261,14 +273,16 @@ static int parent(int sock, int exit_fd, const char *api_socket, struct slirp4ne
261
273
262
274
static void usage (const char * argv0 )
263
275
{
264
- printf ("Usage: %s [OPTION]... PID TAPNAME\n" , argv0 );
276
+ printf ("Usage: %s [OPTION]... PID|PATH TAPNAME\n" , argv0 );
265
277
printf ("User-mode networking for unprivileged network namespaces.\n\n" );
266
278
printf ("-c, --configure bring up the interface\n" );
267
279
printf ("-e, --exit-fd=FD specify the FD for terminating slirp4netns\n" );
268
280
printf ("-r, --ready-fd=FD specify the FD to write to when the network is configured\n" );
269
281
printf ("-m, --mtu=MTU specify MTU (default=%d, max=65521)\n" , DEFAULT_MTU );
270
282
printf ("--cidr=CIDR specify network address CIDR (default=%s)\n" , DEFAULT_CIDR );
271
283
printf ("--disable-host-loopback prohibit connecting to 127.0.0.1:* on the host namespace\n" );
284
+ printf ("--netns-type=TYPE specify network namespace type ([path|pid], default=%s)\n" , DEFAULT_NETNS_TYPE );
285
+ printf ("--userns-path=PATH specify user namespace path\n" );
272
286
printf ("-a, --api-socket=PATH specify API socket path\n" );
273
287
printf ("-6, --enable-ipv6 enable IPv6 (experimental)\n" );
274
288
printf ("-h, --help show this help and exit\n" );
@@ -295,6 +309,9 @@ struct options {
295
309
char * cidr ; // --cidr
296
310
bool enable_ipv6 ; // -6
297
311
char * api_socket ; // -a
312
+ char * netns_type ; // argv[1]
313
+ char * netns_path ; // --netns-path
314
+ char * userns_path ; // --userns-path
298
315
};
299
316
300
317
static void options_init (struct options * options )
@@ -318,6 +335,12 @@ static void options_destroy(struct options *options)
318
335
free (options -> api_socket );
319
336
options -> api_socket = NULL ;
320
337
}
338
+ if (options -> netns_type != NULL ) {
339
+ free (options -> netns_type );
340
+ options -> netns_type = NULL ;
341
+ }
342
+ // options->netns_path and options->userns_path are
343
+ // getting freed in the nsenter function
321
344
// options itself is not freed, because it can be on the stack.
322
345
}
323
346
@@ -329,6 +352,8 @@ static void parse_args(int argc, char *const argv[], struct options *options)
329
352
int opt ;
330
353
#define CIDR -42
331
354
#define DISABLE_HOST_LOOPBACK -43
355
+ #define NETNS_TYPE -44
356
+ #define USERNS_PATH -45
332
357
#define _DEPRECATED_NO_HOST_LOOPBACK -10043 // deprecated in favor of disable-host-loopback
333
358
const struct option longopts [] = {
334
359
{"configure" , no_argument , NULL , 'c' },
@@ -338,6 +363,8 @@ static void parse_args(int argc, char *const argv[], struct options *options)
338
363
{"cidr" , required_argument , NULL , CIDR },
339
364
{"disable-host-loopback" , no_argument , NULL , DISABLE_HOST_LOOPBACK },
340
365
{"no-host-loopback" , no_argument , NULL , _DEPRECATED_NO_HOST_LOOPBACK },
366
+ {"netns-type" , required_argument , NULL , NETNS_TYPE },
367
+ {"userns-path" , required_argument , NULL , USERNS_PATH },
341
368
{"api-socket" , required_argument , NULL , 'a' },
342
369
{"enable-ipv6" , no_argument , NULL , '6' },
343
370
{"help" , no_argument , NULL , 'h' },
@@ -389,6 +416,17 @@ static void parse_args(int argc, char *const argv[], struct options *options)
389
416
case DISABLE_HOST_LOOPBACK :
390
417
options -> disable_host_loopback = true;
391
418
break ;
419
+ case NETNS_TYPE :
420
+ options -> netns_type = strdup (optarg );
421
+ break ;
422
+ case USERNS_PATH :
423
+ options -> userns_path = strdup (optarg );
424
+ if (access (options -> userns_path , F_OK ) == -1 ) {
425
+ fprintf (stderr , "userns path doesn't exist: %s\n" , options -> userns_path );
426
+ usage (argv [0 ]);
427
+ exit (EXIT_FAILURE );
428
+ }
429
+ break ;
392
430
case 'a' :
393
431
options -> api_socket = strdup (optarg );
394
432
break ;
@@ -409,6 +447,8 @@ static void parse_args(int argc, char *const argv[], struct options *options)
409
447
}
410
448
#undef CIDR
411
449
#undef DISABLE_HOST_LOOPBACK
450
+ #undef NETNS_TYPE
451
+ #undef USERNS_PATH
412
452
#undef _DEPRECATED_NO_HOST_LOOPBACK
413
453
if (options -> ready_fd >= 0 && !options -> do_config_network ) {
414
454
fprintf (stderr , "the option -r FD requires -c\n" );
@@ -422,12 +462,21 @@ static void parse_args(int argc, char *const argv[], struct options *options)
422
462
usage (argv [0 ]);
423
463
exit (EXIT_FAILURE );
424
464
}
425
- errno = 0 ;
426
- options -> target_pid = strtol (argv [optind ], NULL , 10 );
427
- if (errno != 0 ) {
428
- perror ("strtol" );
429
- usage (argv [0 ]);
430
- exit (EXIT_FAILURE );
465
+ if (!options -> netns_type || strcmp (options -> netns_type , DEFAULT_NETNS_TYPE ) == 0 ) {
466
+ errno = 0 ;
467
+ options -> target_pid = strtol (argv [optind ], NULL , 10 );
468
+ if (errno != 0 ) {
469
+ perror ("strtol" );
470
+ usage (argv [0 ]);
471
+ exit (EXIT_FAILURE );
472
+ }
473
+ } else {
474
+ options -> netns_path = strdup (argv [optind ]);
475
+ if (access (options -> netns_path , F_OK ) == -1 ) {
476
+ perror ("existing path expected when --netns-type=path" );
477
+ usage (argv [0 ]);
478
+ exit (EXIT_FAILURE );
479
+ }
431
480
}
432
481
options -> tapname = strdup (argv [optind + 1 ]);
433
482
}
@@ -555,7 +604,7 @@ int main(int argc, char *const argv[])
555
604
goto finish ;
556
605
}
557
606
if (child_pid == 0 ) {
558
- if (child (sv [1 ], options .target_pid , options .do_config_network , options .tapname , options .ready_fd ,
607
+ if (child (sv [1 ], options .target_pid , options .do_config_network , options .tapname , options .ready_fd , options . netns_path , options . userns_path ,
559
608
& slirp4netns_config ) < 0 ) {
560
609
exit_status = EXIT_FAILURE ;
561
610
goto finish ;
0 commit comments