|
46 | 46 | #define TRANS_FD "fd"
|
47 | 47 | #define TRANS_FD_LEN strlen(TRANS_FD)
|
48 | 48 |
|
| 49 | +#define TRANS_VDE "vde" |
| 50 | +#define TRANS_VDE_LEN strlen(TRANS_VDE) |
| 51 | + |
49 | 52 | #define VNET_HDR_FAIL "could not enable vnet headers on fd %d"
|
50 | 53 | #define TUN_GET_F_FAIL "tapraw: TUNGETFEATURES failed: %s"
|
51 | 54 | #define L2TPV3_BIND_FAIL "l2tpv3_open : could not bind socket err=%i"
|
@@ -434,6 +437,84 @@ static struct vector_fds *user_init_fd_fds(struct arglist *ifspec)
|
434 | 437 | return NULL;
|
435 | 438 | }
|
436 | 439 |
|
| 440 | +/* enough char to store an int type */ |
| 441 | +#define ENOUGH(type) ((CHAR_BIT * sizeof(type) - 1) / 3 + 2) |
| 442 | +#define ENOUGH_OCTAL(type) ((CHAR_BIT * sizeof(type) + 2) / 3) |
| 443 | +/* vde_plug --descr xx --port2 xx --mod2 xx --group2 xx seqpacket://NN vnl (NULL) */ |
| 444 | +#define VDE_MAX_ARGC 12 |
| 445 | +#define VDE_SEQPACKET_HEAD "seqpacket://" |
| 446 | +#define VDE_SEQPACKET_HEAD_LEN (sizeof(VDE_SEQPACKET_HEAD) - 1) |
| 447 | +#define VDE_DEFAULT_DESCRIPTION "UML" |
| 448 | + |
| 449 | +static struct vector_fds *user_init_vde_fds(struct arglist *ifspec) |
| 450 | +{ |
| 451 | + char seqpacketvnl[VDE_SEQPACKET_HEAD_LEN + ENOUGH(int) + 1]; |
| 452 | + char *argv[VDE_MAX_ARGC] = {"vde_plug"}; |
| 453 | + int argc = 1; |
| 454 | + int rv; |
| 455 | + int sv[2]; |
| 456 | + struct vector_fds *result = NULL; |
| 457 | + |
| 458 | + char *vnl = uml_vector_fetch_arg(ifspec,"vnl"); |
| 459 | + char *descr = uml_vector_fetch_arg(ifspec,"descr"); |
| 460 | + char *port = uml_vector_fetch_arg(ifspec,"port"); |
| 461 | + char *mode = uml_vector_fetch_arg(ifspec,"mode"); |
| 462 | + char *group = uml_vector_fetch_arg(ifspec,"group"); |
| 463 | + if (descr == NULL) descr = VDE_DEFAULT_DESCRIPTION; |
| 464 | + |
| 465 | + argv[argc++] = "--descr"; |
| 466 | + argv[argc++] = descr; |
| 467 | + if (port != NULL) { |
| 468 | + argv[argc++] = "--port2"; |
| 469 | + argv[argc++] = port; |
| 470 | + } |
| 471 | + if (mode != NULL) { |
| 472 | + argv[argc++] = "--mod2"; |
| 473 | + argv[argc++] = mode; |
| 474 | + } |
| 475 | + if (group != NULL) { |
| 476 | + argv[argc++] = "--group2"; |
| 477 | + argv[argc++] = group; |
| 478 | + } |
| 479 | + argv[argc++] = seqpacketvnl; |
| 480 | + argv[argc++] = vnl; |
| 481 | + argv[argc++] = NULL; |
| 482 | + |
| 483 | + rv = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sv); |
| 484 | + if (rv < 0) { |
| 485 | + printk(UM_KERN_ERR "vde: seqpacket socketpair err %d", -errno); |
| 486 | + return NULL; |
| 487 | + } |
| 488 | + rv = os_set_exec_close(sv[0]); |
| 489 | + if (rv < 0) { |
| 490 | + printk(UM_KERN_ERR "vde: seqpacket socketpair cloexec err %d", -errno); |
| 491 | + goto vde_cleanup_sv; |
| 492 | + } |
| 493 | + snprintf(seqpacketvnl, sizeof(seqpacketvnl), VDE_SEQPACKET_HEAD "%d", sv[1]); |
| 494 | + |
| 495 | + run_helper(NULL, NULL, argv); |
| 496 | + |
| 497 | + close(sv[1]); |
| 498 | + |
| 499 | + result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL); |
| 500 | + if (result == NULL) { |
| 501 | + printk(UM_KERN_ERR "fd open: allocation failed"); |
| 502 | + goto vde_cleanup; |
| 503 | + } |
| 504 | + |
| 505 | + result->rx_fd = sv[0]; |
| 506 | + result->tx_fd = sv[0]; |
| 507 | + result->remote_addr_size = 0; |
| 508 | + result->remote_addr = NULL; |
| 509 | + return result; |
| 510 | + |
| 511 | +vde_cleanup_sv: |
| 512 | + close(sv[1]); |
| 513 | +vde_cleanup: |
| 514 | + close(sv[0]); |
| 515 | + return NULL; |
| 516 | +} |
| 517 | + |
437 | 518 | static struct vector_fds *user_init_raw_fds(struct arglist *ifspec)
|
438 | 519 | {
|
439 | 520 | int rxfd = -1, txfd = -1;
|
@@ -673,6 +754,8 @@ struct vector_fds *uml_vector_user_open(
|
673 | 754 | return user_init_unix_fds(parsed, ID_BESS);
|
674 | 755 | if (strncmp(transport, TRANS_FD, TRANS_FD_LEN) == 0)
|
675 | 756 | return user_init_fd_fds(parsed);
|
| 757 | + if (strncmp(transport, TRANS_VDE, TRANS_VDE_LEN) == 0) |
| 758 | + return user_init_vde_fds(parsed); |
676 | 759 | return NULL;
|
677 | 760 | }
|
678 | 761 |
|
|
0 commit comments