From 15dbb6973a7af11b81df047194228ea86d46939b Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Fri, 3 Apr 2009 01:14:44 +0100 Subject: [PATCH] Add the first version of the guestfsd daemon. --- .gitignore | 1 + daemon/Makefile.am | 7 +- daemon/guestfsd.c | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 daemon/guestfsd.c diff --git a/.gitignore b/.gitignore index ebfc2a3..a9bd0d6 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ config.sub config.log config.status configure +daemon/guestfsd daemon/install-sh daemon/missing depcomp diff --git a/daemon/Makefile.am b/daemon/Makefile.am index a5c1637..6a5a4ee 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -15,4 +15,9 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -ACLOCAL_AMFLAGS = -I m4 \ No newline at end of file +ACLOCAL_AMFLAGS = -I m4 + +noinst_PROGRAMS = guestfsd +guestfsd_SOURCES = guestfsd.c + +guestfsd_CFLAGS = -Wall -Werror \ No newline at end of file diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c new file mode 100644 index 0000000..c27d1b6 --- /dev/null +++ b/daemon/guestfsd.c @@ -0,0 +1,205 @@ +/* libguestfs - the guestfsd daemon + * Copyright (C) 2009 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static void xwrite (int sock, const void *buf, size_t len); +static void usage (void); + +/* Also in guestfs.c */ +#define VMCHANNEL_PORT "6666" +#define VMCHANNEL_ADDR "10.0.2.4" + +int +main (int argc, char *argv[]) +{ + static const char *options = "fh:p:?"; + static struct option long_options[] = { + { "foreground", 0, 0, 'f' }, + { "help", 0, 0, '?' }, + { "host", 1, 0, 'h' }, + { "port", 1, 0, 'p' }, + { 0, 0, 0, 0 } + }; + int c, n, r; + int dont_fork = 0; + const char *host = NULL; + const char *port = NULL; + FILE *fp; + char buf[4096]; + char *p, *p2; + int sock; + struct addrinfo *res, *rr; + struct addrinfo hints; + XDR xdr; + unsigned len; + + for (;;) { + c = getopt_long (argc, argv, options, long_options, NULL); + if (c == -1) break; + + switch (c) { + case 'f': + dont_fork = 1; + break; + + case 'h': + host = optarg; + break; + + case 'p': + port = optarg; + break; + + case '?': + usage (); + exit (0); + + default: + fprintf (stderr, "guestfsd: unexpected command line option 0x%x\n", c); + exit (1); + } + } + + if (optind < argc) { + usage (); + exit (1); + } + + /* If host and port aren't set yet, try /proc/cmdline. */ + if (!host || !port) { + fp = fopen ("/proc/cmdline", "r"); + if (fp == NULL) { + perror ("/proc/cmdline"); + goto next; + } + n = fread (buf, 1, sizeof buf - 1, fp); + fclose (fp); + buf[n] = '\0'; + + p = strstr (buf, "guestfs="); + + if (p) { + p += 8; + p2 = strchr (p, ':'); + if (p2) { + *p2++ = '\0'; + host = p; + r = strcspn (p2, " \n"); + p2[r] = '\0'; + port = p2; + } + } + } + + next: + /* Can't parse /proc/cmdline, so use built-in defaults. */ + if (!host || !port) { + host = VMCHANNEL_ADDR; + port = VMCHANNEL_PORT; + } + + /* Resolve the hostname. */ + 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 (1); + } + + /* Connect to the given TCP socket. */ + sock = -1; + 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); + + if (sock == -1) { + fprintf (stderr, "connection to %s:%s failed\n", host, port); + exit (1); + } + + /* Send the magic length message which indicates that + * userspace is up inside the guest. + */ + len = 0xf5f55ff5; + xdrmem_create (&xdr, buf, sizeof buf, XDR_ENCODE); + if (!xdr_uint32_t (&xdr, &len)) { + fprintf (stderr, "xdr_uint32_t failed\n"); + exit (1); + } + + xwrite (sock, buf, xdr_getpos (&xdr)); + + xdr_destroy (&xdr); + + /* XXX Fork into the background. */ + + + + + + + + + + sleep (1000000); + + exit (0); +} + +static void +xwrite (int sock, const void *buf, size_t len) +{ + int r; + + while (len > 0) { + r = write (sock, buf, len); + if (r == -1) { + perror ("write"); + exit (1); + } + buf += r; + len -= r; + } +} + +static void +usage (void) +{ + fprintf (stderr, "guestfsd [-f] [-h host -p port]\n"); +} -- 1.8.3.1