diff options
Diffstat (limited to 'daemon/guestfsd.c')
-rw-r--r-- | daemon/guestfsd.c | 99 |
1 files changed, 91 insertions, 8 deletions
diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index b09f74e1..eedd3cca 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -112,9 +112,6 @@ int autosync_umount = 1; /* Not used explicitly, but required by the gnulib 'error' module. */ const char *program_name = "guestfsd"; -/* Name of the virtio-serial channel. */ -#define VIRTIO_SERIAL_CHANNEL "/dev/virtio-ports/org.libguestfs.channel.0" - static void usage (void) { @@ -133,6 +130,7 @@ main (int argc, char *argv[]) }; int c; char *cmdline; + char *vmchannel = NULL; ignore_value (chdir ("/")); @@ -204,8 +202,6 @@ main (int argc, char *argv[]) printf ("could not read linux command line\n"); } - free (cmdline); - #ifndef WIN32 /* Make sure SIGPIPE doesn't kill us. */ struct sigaction sa; @@ -247,9 +243,94 @@ main (int argc, char *argv[]) */ copy_lvm (); - /* Connect to virtio-serial channel. */ - int sock = open (VIRTIO_SERIAL_CHANNEL, O_RDWR|O_CLOEXEC); + /* Get the vmchannel string. + * + * Sources: + * --channel/-c option on the command line + * guestfs_vmchannel=... from the kernel command line + * guestfs=... from the kernel command line + * built-in default + * + * At the moment we expect this to contain "tcp:ip:port" but in + * future it might contain a device name, eg. "/dev/vcon4" for + * virtio-console vmchannel. + */ + if (cmdline) { + char *p; + size_t len; + + p = strstr (cmdline, "guestfs_vmchannel="); + if (p) { + len = strcspn (p + 18, " \t\n"); + vmchannel = strndup (p + 18, len); + if (!vmchannel) { + perror ("strndup"); + exit (EXIT_FAILURE); + } + } + } + + /* Default vmchannel. */ + if (vmchannel == NULL) + goto no_vmchannel; + + if (verbose) + printf ("vmchannel: %s\n", vmchannel); + + /* Connect to vmchannel. */ + int sock = -1; + + if (STREQLEN (vmchannel, "tcp:", 4)) { + /* Resolve the hostname. */ + struct addrinfo *res, *rr; + struct addrinfo hints; + int r; + char *host, *port; + + host = vmchannel+4; + port = strchr (host, ':'); + if (port) { + port[0] = '\0'; + port++; + } else { + fprintf (stderr, "vmchannel: expecting \"tcp:<ip>:<port>\": %s\n", + vmchannel); + exit (EXIT_FAILURE); + } + + memset (&hints, 0, sizeof hints); + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_ADDRCONFIG; + r = getaddrinfo (host, port, &hints, &res); + if (r != 0) { + fprintf (stderr, "%s:%s: %s\n", + host, port, gai_strerror (r)); + exit (EXIT_FAILURE); + } + + /* Connect to the given TCP socket. */ + for (rr = res; rr != NULL; rr = rr->ai_next) { + sock = socket (rr->ai_family, rr->ai_socktype, rr->ai_protocol); + if (sock != -1) { + if (connect (sock, rr->ai_addr, rr->ai_addrlen) == 0) + break; + perror ("connect"); + + close (sock); + sock = -1; + } + } + freeaddrinfo (res); + } else { + fprintf (stderr, + "unknown vmchannel connection type: %s\n" + "expecting \"tcp:<ip>:<port>\"\n", + vmchannel); + exit (EXIT_FAILURE); + } + if (sock == -1) { + no_vmchannel: fprintf (stderr, "\n" "Failed to connect to virtio-serial channel.\n" @@ -263,7 +344,7 @@ main (int argc, char *argv[]) "output to the libguestfs developers, either in a bug report\n" "or on the libguestfs redhat com mailing list.\n" "\n"); - perror (VIRTIO_SERIAL_CHANNEL); + perror ("last error"); exit (EXIT_FAILURE); } @@ -283,6 +364,8 @@ main (int argc, char *argv[]) xdr_destroy (&xdr); + free (cmdline); + /* Enter the main loop, reading and performing actions. */ main_loop (sock); |