mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-27 12:38:11 +00:00
tap-vsockd: support daemonization via a --daemon arg
We daemonize after checking the command-line and binding/connecting the socket and creating the tap device. Only the ethernet frame processing happens afterwards. This patch also includes a new well-known service GUID for the VPN-proxy ethernet service. Signed-off-by: David Scott <dave.scott@docker.com>
This commit is contained in:
parent
f636321b81
commit
a1d91d2a3d
@ -27,10 +27,12 @@
|
|||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
|
|
||||||
int debug_flag = 0;
|
int daemon_flag = 0;
|
||||||
int listen_flag = 0;
|
int listen_flag = 0;
|
||||||
int connect_flag = 0;
|
int connect_flag = 0;
|
||||||
|
|
||||||
|
char *default_sid = "30D48B34-7D27-4B0B-AAAF-BBBED334DD59";
|
||||||
|
|
||||||
int alloc_tap(const char *dev) {
|
int alloc_tap(const char *dev) {
|
||||||
int fd;
|
int fd;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
@ -219,7 +221,7 @@ static void* tap_to_vmnet(void *arg)
|
|||||||
/* Handle a connection. Handshake with the com.docker.slirp process and start
|
/* Handle a connection. Handshake with the com.docker.slirp process and start
|
||||||
* exchanging ethernet frames between the socket and the tap device.
|
* exchanging ethernet frames between the socket and the tap device.
|
||||||
*/
|
*/
|
||||||
static void handle(SOCKET fd, const char *tap)
|
static void handle(SOCKET fd, char *tap, int tapfd)
|
||||||
{
|
{
|
||||||
struct connection connection;
|
struct connection connection;
|
||||||
pthread_t v2t, t2v;
|
pthread_t v2t, t2v;
|
||||||
@ -231,7 +233,6 @@ static void handle(SOCKET fd, const char *tap)
|
|||||||
connection.vif.mac[3], connection.vif.mac[4], connection.vif.mac[5]
|
connection.vif.mac[3], connection.vif.mac[4], connection.vif.mac[5]
|
||||||
);
|
);
|
||||||
|
|
||||||
int tapfd = alloc_tap(tap);
|
|
||||||
set_macaddr(tap, &connection.vif.mac[0]);
|
set_macaddr(tap, &connection.vif.mac[0]);
|
||||||
connection.tapfd = tapfd;
|
connection.tapfd = tapfd;
|
||||||
|
|
||||||
@ -311,17 +312,11 @@ static int connect_socket(GUID serviceid) {
|
|||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int accept_socket(SOCKET lsock) {
|
||||||
/* Server:
|
|
||||||
* accept() in an endless loop, handle a connection at a time
|
|
||||||
*/
|
|
||||||
static void accept_forever(SOCKET lsock, const char *tap)
|
|
||||||
{
|
|
||||||
SOCKET csock = INVALID_SOCKET;
|
SOCKET csock = INVALID_SOCKET;
|
||||||
SOCKADDR_HV sac;
|
SOCKADDR_HV sac;
|
||||||
socklen_t socklen = sizeof(sac);
|
socklen_t socklen = sizeof(sac);
|
||||||
|
|
||||||
while(1) {
|
|
||||||
csock = accept(lsock, (struct sockaddr *)&sac, &socklen);
|
csock = accept(lsock, (struct sockaddr *)&sac, &socklen);
|
||||||
if (csock == INVALID_SOCKET) {
|
if (csock == INVALID_SOCKET) {
|
||||||
sockerr("accept()");
|
sockerr("accept()");
|
||||||
@ -331,10 +326,7 @@ static void accept_forever(SOCKET lsock, const char *tap)
|
|||||||
|
|
||||||
printf("Connect from: "GUID_FMT":"GUID_FMT"\n",
|
printf("Connect from: "GUID_FMT":"GUID_FMT"\n",
|
||||||
GUID_ARGS(sac.VmId), GUID_ARGS(sac.ServiceId));
|
GUID_ARGS(sac.VmId), GUID_ARGS(sac.ServiceId));
|
||||||
|
return csock;
|
||||||
handle(csock, tap);
|
|
||||||
closesocket(csock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_pidfile(const char *pidfile) {
|
void write_pidfile(const char *pidfile) {
|
||||||
@ -362,16 +354,44 @@ void write_pidfile(const char *pidfile) {
|
|||||||
free(pid_s);
|
free(pid_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void daemonize(const char *pidfile){
|
||||||
|
pid_t pid = fork ();
|
||||||
|
if (pid == -1) {
|
||||||
|
syslog(LOG_CRIT, "Failed to fork()");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
else if (pid != 0)
|
||||||
|
exit(0);
|
||||||
|
if (setsid () == -1) {
|
||||||
|
syslog(LOG_CRIT, "Failed to setsid()");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (chdir ("/") == -1) {
|
||||||
|
syslog(LOG_CRIT, "Failed to chdir()");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
int null = open("/dev/null", O_RDWR);
|
||||||
|
dup2(null, STDIN_FILENO);
|
||||||
|
dup2(null, STDOUT_FILENO);
|
||||||
|
dup2(null, STDERR_FILENO);
|
||||||
|
close(null);
|
||||||
|
if (pidfile) write_pidfile(pidfile);
|
||||||
|
}
|
||||||
|
|
||||||
void usage(char *name)
|
void usage(char *name)
|
||||||
{
|
{
|
||||||
printf("%s: [--debug] [--tap <name>] [--serviceid <guid>] [--pid <file>]\n", name);
|
printf("%s usage:\n", name);
|
||||||
|
printf("\t[--daemon] [--tap <name>] [--serviceid <guid>] [--pid <file>]\n");
|
||||||
printf("\t[--listen | --connect]\n\n");
|
printf("\t[--listen | --connect]\n\n");
|
||||||
printf("--debug: log to stderr as well as syslog\n");
|
printf("where\n");
|
||||||
printf("--tap <name>: create a tap device with the given name (defaults to eth1)\n");
|
printf("\t--daemonize: run as a background daemon\n");
|
||||||
printf("--serviceid <guid>: use <guid> as the well-known service GUID\n");
|
printf("\t--tap <name>: create a tap device with the given name\n");
|
||||||
printf("--pid <file>: write a pid to the given file\n");
|
printf("\t (defaults to eth1)\n");
|
||||||
printf("--listen: listen forever for incoming AF_HVSOCK connections\n");
|
printf("\t--serviceid <guid>: use <guid> as the well-known service GUID\n");
|
||||||
printf("--connect: connect to the parent partition\n");
|
printf("\t (defaults to %s)\n", default_sid);
|
||||||
|
printf("\t--pid <file>: write a pid to the given file\n");
|
||||||
|
printf("\t--listen: listen forever for incoming AF_HVSOCK connections\n");
|
||||||
|
printf("\t--connect: connect to the parent partition\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int __cdecl main(int argc, char **argv)
|
int __cdecl main(int argc, char **argv)
|
||||||
@ -380,7 +400,7 @@ int __cdecl main(int argc, char **argv)
|
|||||||
GUID sid;
|
GUID sid;
|
||||||
int c;
|
int c;
|
||||||
/* Defaults to a testing GUID */
|
/* Defaults to a testing GUID */
|
||||||
char *serviceid = "3049197C-9A4E-4FBF-9367-97F792F16994";
|
char *serviceid = default_sid;
|
||||||
char *tap = "eth1";
|
char *tap = "eth1";
|
||||||
char *pidfile = NULL;
|
char *pidfile = NULL;
|
||||||
|
|
||||||
@ -388,7 +408,7 @@ int __cdecl main(int argc, char **argv)
|
|||||||
while (1) {
|
while (1) {
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
/* These options set a flag. */
|
/* These options set a flag. */
|
||||||
{"debug", no_argument, &debug_flag, 1},
|
{"daemon", no_argument, &daemon_flag, 1},
|
||||||
{"serviceid", required_argument, NULL, 's'},
|
{"serviceid", required_argument, NULL, 's'},
|
||||||
{"tap", required_argument, NULL, 't'},
|
{"tap", required_argument, NULL, 't'},
|
||||||
{"pidfile", required_argument, NULL, 'p'},
|
{"pidfile", required_argument, NULL, 'p'},
|
||||||
@ -403,7 +423,7 @@ int __cdecl main(int argc, char **argv)
|
|||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'd':
|
case 'd':
|
||||||
debug_flag = 1;
|
daemon_flag = 1;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
serviceid = optarg;
|
serviceid = optarg;
|
||||||
@ -425,8 +445,12 @@ int __cdecl main(int argc, char **argv)
|
|||||||
fprintf(stderr, "Please supply either the --listen or --connect flag, but not both.\n");
|
fprintf(stderr, "Please supply either the --listen or --connect flag, but not both.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
if (daemon_flag && !pidfile){
|
||||||
|
fprintf(stderr, "For daemon mode, please supply a --pidfile argument.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
int log_flags = LOG_CONS | LOG_NDELAY;
|
int log_flags = LOG_CONS | LOG_NDELAY;
|
||||||
if (debug_flag) {
|
if (!daemon_flag) {
|
||||||
log_flags |= LOG_PERROR;
|
log_flags |= LOG_PERROR;
|
||||||
}
|
}
|
||||||
openlog(argv[0], log_flags, LOG_DAEMON);
|
openlog(argv[0], log_flags, LOG_DAEMON);
|
||||||
@ -438,14 +462,19 @@ int __cdecl main(int argc, char **argv)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SOCKET sock = INVALID_SOCKET;
|
||||||
if (listen_flag) {
|
if (listen_flag) {
|
||||||
syslog(LOG_INFO, "starting in listening mode with serviceid=%s and tap=%s", serviceid, tap);
|
syslog(LOG_INFO, "starting in listening mode with serviceid=%s and tap=%s", serviceid, tap);
|
||||||
int socket = create_listening_socket(sid);
|
SOCKET lsocket = create_listening_socket(sid);
|
||||||
accept_forever(socket, tap);
|
sock = accept_socket(lsocket);
|
||||||
exit(0);
|
} else {
|
||||||
}
|
|
||||||
syslog(LOG_INFO, "starting in connect mode with serviceid=%s and tap=%s", serviceid, tap);
|
syslog(LOG_INFO, "starting in connect mode with serviceid=%s and tap=%s", serviceid, tap);
|
||||||
int socket = connect_socket(sid);
|
sock = connect_socket(sid);
|
||||||
handle(socket, tap);
|
}
|
||||||
return 0;
|
/* Bring up the tap device before we daemonize */
|
||||||
|
int tapfd = alloc_tap(tap);
|
||||||
|
if (daemon_flag) daemonize(pidfile);
|
||||||
|
|
||||||
|
handle(sock, tap, tapfd);
|
||||||
|
exit(0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user