mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
c82f6a8faf
Signed-off-by: John Howard <jhoward@microsoft.com>
129 lines
3 KiB
C
129 lines
3 KiB
C
// vsockexec opens vsock connections for the specified stdio descriptors and
|
|
// then execs the specified process.
|
|
|
|
#include <errno.h>
|
|
#include <sys/socket.h>
|
|
#include <linux/vm_sockets.h>
|
|
#include <netinet/in.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#ifdef USE_TCP
|
|
static const int tcpmode = 1;
|
|
#else
|
|
static const int tcpmode;
|
|
#endif
|
|
|
|
static int openvsock(unsigned int cid, unsigned int port)
|
|
{
|
|
int s = socket(AF_VSOCK, SOCK_STREAM, 0);
|
|
if (s < 0) {
|
|
perror("socket: AF_VSOCK");
|
|
return -1;
|
|
}
|
|
|
|
struct sockaddr_vm addr = {0};
|
|
addr.svm_family = AF_VSOCK;
|
|
addr.svm_port = port;
|
|
addr.svm_cid = cid;
|
|
if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
fprintf(stderr, "connect: port %u: %s", port, strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
static int opentcp(unsigned short port)
|
|
{
|
|
int s = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (s < 0) {
|
|
perror("socket: AF_INET");
|
|
return -1;
|
|
}
|
|
|
|
struct sockaddr_in addr = {0};
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_port = htons(port);
|
|
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
|
if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
fprintf(stderr, "connect: port %u: %s\n", port, strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
_Noreturn static void usage(const char *argv0)
|
|
{
|
|
fprintf(stderr, "%s [-i port] [-o port] [-e port] -- program [args...]\n", argv0);
|
|
exit(1);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
unsigned int ports[3] = {0};
|
|
int sockets[3] = {-1, -1, -1};
|
|
int c;
|
|
while ((c = getopt(argc, argv, "+i:o:e:")) != -1) {
|
|
switch (c) {
|
|
case 'i':
|
|
ports[0] = strtoul(optarg, NULL, 10);
|
|
break;
|
|
|
|
case 'o':
|
|
ports[1] = strtoul(optarg, NULL, 10);
|
|
break;
|
|
|
|
case 'e':
|
|
ports[2] = strtoul(optarg, NULL, 10);
|
|
break;
|
|
|
|
default:
|
|
usage(argv[0]);
|
|
}
|
|
}
|
|
|
|
if (optind == argc) {
|
|
fprintf(stderr, "%s: missing program argument\n", argv[0]);
|
|
usage(argv[0]);
|
|
}
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
if (ports[i] != 0) {
|
|
int j;
|
|
for (j = 0; j < i; j++) {
|
|
if (ports[i] == ports[j]) {
|
|
int s = dup(sockets[j]);
|
|
if (s < 0) {
|
|
perror("dup");
|
|
return 1;
|
|
}
|
|
sockets[i] = s;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (j == i) {
|
|
int s = tcpmode ? opentcp(ports[i]) : openvsock(VMADDR_CID_HOST, ports[i]);
|
|
if (s < 0) {
|
|
return 1;
|
|
}
|
|
sockets[i] = s;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
if (sockets[i] >= 0) {
|
|
dup2(sockets[i], i);
|
|
close(sockets[i]);
|
|
}
|
|
}
|
|
|
|
execvp(argv[optind], argv + optind);
|
|
fprintf(stderr, "execvp: %s: %s\n", argv[optind], strerror(errno));
|
|
return 1;
|
|
}
|