ia64/xen-unstable

changeset 5966:94a4626c2c44

This is the first patch to move the console code out of Xend and into a
separate daemon. In this patch I've included the daemon and a
front-end. I've also have the console code removed from Xend locally
but I wanted to clarify a few things first before submitting that.

Here's how it works:

1) Daemon sits on control channel (via xcs) waiting for console messages
2) Buffers all console data received
3) Publishes the location of a tty that can be used for reading in
/console/<domid>/tty
4) Reads a value from the store to determine what the limit of console
data should be (/console/<domid>/limit) to prevent DoS attacks

Using it is quite simple, just run consoled and use the xc_console
program to connect to the console. It uses syslog for logging.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue Aug 02 12:18:47 2005 +0000 (2005-08-02)
parents 1640c137c847
children 2f743309f21a
files tools/consoled/Makefile tools/consoled/consoled tools/consoled/io.c tools/consoled/io.h tools/consoled/main.c tools/consoled/utils.c tools/consoled/utils.h tools/consoled/xc_console tools/consoled/xc_console.c
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/tools/consoled/Makefile	Tue Aug 02 12:18:47 2005 +0000
     1.3 @@ -0,0 +1,48 @@
     1.4 +# Makefile for consoled
     1.5 +# based on xcs Makefile
     1.6 +# Anthony Liguori 2005
     1.7 +
     1.8 +XEN_ROOT=../..
     1.9 +include $(XEN_ROOT)/tools/Rules.mk
    1.10 +
    1.11 +CONSOLED_INSTALL_DIR = /usr/sbin
    1.12 +XC_CONSOLE_INSTALL_DIR = /usr/libexec/xen
    1.13 +
    1.14 +INSTALL         = install
    1.15 +INSTALL_PROG    = $(INSTALL) -m0755
    1.16 +INSTALL_DIR     = $(INSTALL) -d -m0755
    1.17 +
    1.18 +CC       = gcc
    1.19 +CFLAGS   = -Wall -Werror -g3
    1.20 +
    1.21 +CFLAGS  += -I $(XEN_XCS)
    1.22 +CFLAGS  += -I $(XEN_LIBXC)
    1.23 +CFLAGS  += -I $(XEN_XENSTORE)
    1.24 +
    1.25 +SRCS    :=
    1.26 +SRCS    += main.c utils.c io.c
    1.27 +
    1.28 +HDRS     = $(wildcard *.h)
    1.29 +OBJS     = $(patsubst %.c,%.o,$(SRCS))
    1.30 +BIN      = consoled
    1.31 +
    1.32 +all: $(BIN) xc_console
    1.33 +
    1.34 +clean:
    1.35 +	$(RM) *.a *.so *.o *.rpm $(BIN) xc_console
    1.36 +
    1.37 +$(BIN): $(OBJS)
    1.38 +	$(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -L$(XEN_XENSTORE) \
    1.39 +              -lxc -lxenstore
    1.40 +
    1.41 +xc_console: xc_console.o
    1.42 +	$(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -L$(XEN_XENSTORE) \
    1.43 +	      -lxc -lxenstore
    1.44 +
    1.45 +$(OBJS): $(HDRS)
    1.46 +
    1.47 +install: $(BIN)
    1.48 +	$(INSTALL_DIR) -p $(DESTDIR)/$(CONSOLED_INSTALL_DIR)
    1.49 +	$(INSTALL_PROG) $(BIN) $(DESTDIR)/$(CONSOLED_INSTALL_DIR)
    1.50 +	$(INSTALL_DIR) -p $(DESTDIR)/$(XC_CONSOLE_INSTALL_DIR)
    1.51 +	$(INSTALL_PROG) xc_console $(DESTDIR)/$(XC_CONSOLE_INSTALL_DIR)
     2.1 Binary file tools/consoled/consoled has changed
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/consoled/io.c	Tue Aug 02 12:18:47 2005 +0000
     3.3 @@ -0,0 +1,328 @@
     3.4 +/*\
     3.5 + *  Copyright (C) International Business Machines  Corp., 2005
     3.6 + *  Author(s): Anthony Liguori <aliguori@us.ibm.com>
     3.7 + *
     3.8 + *  Xen Console Daemon
     3.9 + *
    3.10 + *  This program is free software; you can redistribute it and/or modify
    3.11 + *  it under the terms of the GNU General Public License as published by
    3.12 + *  the Free Software Foundation; under version 2 of the License.
    3.13 + * 
    3.14 + *  This program is distributed in the hope that it will be useful,
    3.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.17 + *  GNU General Public License for more details.
    3.18 + * 
    3.19 + *  You should have received a copy of the GNU General Public License
    3.20 + *  along with this program; if not, write to the Free Software
    3.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    3.22 +\*/
    3.23 +
    3.24 +#define _GNU_SOURCE
    3.25 +
    3.26 +#include "utils.h"
    3.27 +#include "io.h"
    3.28 +
    3.29 +#include "xc.h"
    3.30 +#include "xs.h"
    3.31 +#include "xen/io/domain_controller.h"
    3.32 +#include "xcs_proto.h"
    3.33 +
    3.34 +#include <malloc.h>
    3.35 +#include <stdlib.h>
    3.36 +#include <errno.h>
    3.37 +#include <string.h>
    3.38 +#include <sys/select.h>
    3.39 +#include <fcntl.h>
    3.40 +#include <unistd.h>
    3.41 +#include <termios.h>
    3.42 +
    3.43 +#define MAX(a, b) (((a) > (b)) ? (a) : (b))
    3.44 +#define MIN(a, b) (((a) < (b)) ? (a) : (b))
    3.45 +
    3.46 +struct buffer
    3.47 +{
    3.48 +	char *data;
    3.49 +	size_t size;
    3.50 +	size_t capacity;
    3.51 +	size_t max_capacity;
    3.52 +};
    3.53 +
    3.54 +void buffer_append(struct buffer *buffer, const void *data, size_t size)
    3.55 +{
    3.56 +	if ((buffer->capacity - buffer->size) < size) {
    3.57 +		buffer->capacity += (size + 1024);
    3.58 +		buffer->data = realloc(buffer->data, buffer->capacity);
    3.59 +		if (buffer->data == NULL) {
    3.60 +			dolog(LOG_ERR, "Memory allocation failed");
    3.61 +			exit(ENOMEM);
    3.62 +		}
    3.63 +	}
    3.64 +
    3.65 +	memcpy(buffer->data + buffer->size, data, size);
    3.66 +	buffer->size += size;
    3.67 +
    3.68 +	if (buffer->max_capacity &&
    3.69 +	    buffer->size > buffer->max_capacity) {
    3.70 +		memmove(buffer->data + (buffer->size - buffer->max_capacity),
    3.71 +			buffer->data, buffer->max_capacity);
    3.72 +		buffer->data = realloc(buffer->data, buffer->max_capacity);
    3.73 +		buffer->capacity = buffer->max_capacity;
    3.74 +	}
    3.75 +}
    3.76 +
    3.77 +bool buffer_empty(struct buffer *buffer)
    3.78 +{
    3.79 +	return buffer->size == 0;
    3.80 +}
    3.81 +
    3.82 +void buffer_advance(struct buffer *buffer, size_t size)
    3.83 +{
    3.84 +	size = MIN(size, buffer->size);
    3.85 +	memmove(buffer->data, buffer + size, buffer->size - size);
    3.86 +	buffer->size -= size;
    3.87 +}
    3.88 +
    3.89 +struct domain
    3.90 +{
    3.91 +	int domid;
    3.92 +	int tty_fd;
    3.93 +	struct buffer buffer;
    3.94 +	struct domain *next;
    3.95 +};
    3.96 +
    3.97 +static struct domain *dom_head;
    3.98 +
    3.99 +bool domain_is_valid(int domid)
   3.100 +{
   3.101 +	bool ret;
   3.102 +	xc_dominfo_t info;
   3.103 +
   3.104 +	ret = (xc_domain_getinfo(xc, domid, 1, &info) == 1 &&
   3.105 +	       info.domid == domid);
   3.106 +		
   3.107 +	return ret;
   3.108 +}
   3.109 +
   3.110 +int domain_create_tty(int domid)
   3.111 +{
   3.112 +	char path[1024];
   3.113 +	int master;
   3.114 +
   3.115 +	if ((master = getpt()) == -1 ||
   3.116 +	    grantpt(master) == -1 || unlockpt(master) == -1) {
   3.117 +		dolog(LOG_ERR, "Failed to create tty for domain-%d", domid);
   3.118 +		master = -1;
   3.119 +	} else {
   3.120 +		const char *slave = ptsname(master);
   3.121 +		struct termios term;
   3.122 +
   3.123 +		if (tcgetattr(master, &term) != -1) {
   3.124 +			cfmakeraw(&term);
   3.125 +			tcsetattr(master, TCSAFLUSH, &term);
   3.126 +		}
   3.127 +
   3.128 +		xs_mkdir(xs, "/console");
   3.129 +		snprintf(path, sizeof(path), "/console/%d", domid);
   3.130 +		xs_mkdir(xs, path);
   3.131 +		strcat(path, "/tty");
   3.132 +
   3.133 +		xs_write(xs, path, slave, strlen(slave), O_CREAT);
   3.134 +	}
   3.135 +
   3.136 +	return master;
   3.137 +}
   3.138 +
   3.139 +struct domain *create_domain(int domid)
   3.140 +{
   3.141 +	struct domain *dom;
   3.142 +	char *data;
   3.143 +	unsigned int len;
   3.144 +	char path[1024];
   3.145 +
   3.146 +	dom = (struct domain *)malloc(sizeof(struct domain));
   3.147 +	if (dom == NULL) {
   3.148 +		dolog(LOG_ERR, "Out of memory %s:%s():L%d",
   3.149 +		      __FILE__, __FUNCTION__, __LINE__);
   3.150 +		exit(ENOMEM);
   3.151 +	}
   3.152 +
   3.153 +	dom->domid = domid;
   3.154 +	dom->tty_fd = domain_create_tty(domid);
   3.155 +	dom->buffer.data = 0;
   3.156 +	dom->buffer.size = 0;
   3.157 +	dom->buffer.capacity = 0;
   3.158 +	dom->buffer.max_capacity = 0;
   3.159 +
   3.160 +	snprintf(path, sizeof(path), "/console/%d/limit", domid);
   3.161 +	data = xs_read(xs, path, &len);
   3.162 +	if (data) {
   3.163 +		dom->buffer.max_capacity = strtoul(data, 0, 0);
   3.164 +		free(data);
   3.165 +	}
   3.166 +
   3.167 +	dolog(LOG_DEBUG, "New domain %d", domid);
   3.168 +
   3.169 +	return dom;
   3.170 +}
   3.171 +
   3.172 +struct domain *lookup_domain(int domid)
   3.173 +{
   3.174 +	struct domain **pp;
   3.175 +
   3.176 +	for (pp = &dom_head; *pp; pp = &(*pp)->next) {
   3.177 +		struct domain *dom = *pp;
   3.178 +
   3.179 +		if (dom->domid == domid) {
   3.180 +			return dom;
   3.181 +		} else if (dom->domid > domid) {
   3.182 +			*pp = create_domain(domid);
   3.183 +			(*pp)->next = dom;
   3.184 +			return *pp;
   3.185 +		}
   3.186 +	}
   3.187 +
   3.188 +	*pp = create_domain(domid);
   3.189 +	return *pp;
   3.190 +}
   3.191 +
   3.192 +void remove_domain(struct domain *dom)
   3.193 +{
   3.194 +	struct domain **pp;
   3.195 +
   3.196 +	dolog(LOG_DEBUG, "Removing domain-%d", dom->domid);
   3.197 +
   3.198 +	for (pp = &dom_head; *pp; pp = &(*pp)->next) {
   3.199 +		struct domain *d = *pp;
   3.200 +
   3.201 +		if (dom->domid == d->domid) {
   3.202 +			*pp = d->next;
   3.203 +			free(d);
   3.204 +			break;
   3.205 +		}
   3.206 +	}
   3.207 +}
   3.208 +
   3.209 +void handle_tty_read(struct domain *dom)
   3.210 +{
   3.211 +	ssize_t len;
   3.212 +	xcs_msg_t msg;
   3.213 +
   3.214 +	msg.type = XCS_REQUEST;
   3.215 +	msg.u.control.remote_dom = dom->domid;
   3.216 +	msg.u.control.msg.type = CMSG_CONSOLE;
   3.217 +	msg.u.control.msg.subtype = CMSG_CONSOLE_DATA;
   3.218 +	msg.u.control.msg.id = 1;
   3.219 +
   3.220 +	len = read(dom->tty_fd, msg.u.control.msg.msg, 60);
   3.221 +	if (len < 1) {
   3.222 +		close(dom->tty_fd);
   3.223 +
   3.224 +		if (domain_is_valid(dom->domid)) {
   3.225 +			dom->tty_fd = domain_create_tty(dom->domid);
   3.226 +		} else {
   3.227 +			remove_domain(dom);
   3.228 +		}
   3.229 +	} else if (domain_is_valid(dom->domid)) {
   3.230 +		msg.u.control.msg.length = len;
   3.231 +
   3.232 +		if (!write_sync(xcs_data_fd, &msg, sizeof(msg))) {
   3.233 +			dolog(LOG_ERR, "Write to xcs failed: %m");
   3.234 +		}
   3.235 +	} else {
   3.236 +		close(dom->tty_fd);
   3.237 +		remove_domain(dom);
   3.238 +	}
   3.239 +}
   3.240 +
   3.241 +void handle_tty_write(struct domain *dom)
   3.242 +{
   3.243 +	ssize_t len;
   3.244 +
   3.245 +	len = write(dom->tty_fd, dom->buffer.data, dom->buffer.size);
   3.246 +	if (len < 1) {
   3.247 +		close(dom->tty_fd);
   3.248 +
   3.249 +		if (domain_is_valid(dom->domid)) {
   3.250 +			dom->tty_fd = domain_create_tty(dom->domid);
   3.251 +		} else {
   3.252 +			remove_domain(dom);
   3.253 +		}
   3.254 +	} else {
   3.255 +		buffer_advance(&dom->buffer, len);
   3.256 +	}
   3.257 +}
   3.258 +
   3.259 +void handle_xcs_msg(int fd)
   3.260 +{
   3.261 +	xcs_msg_t msg;
   3.262 +
   3.263 +	if (!read_sync(fd, &msg, sizeof(msg))) {
   3.264 +		dolog(LOG_ERR, "read from xcs failed! %m");
   3.265 +	} else if (msg.type == XCS_REQUEST) {
   3.266 +		struct domain *dom;
   3.267 +
   3.268 +		dom = lookup_domain(msg.u.control.remote_dom);
   3.269 +		buffer_append(&dom->buffer,
   3.270 +			      msg.u.control.msg.msg,
   3.271 +			      msg.u.control.msg.length);
   3.272 +	}
   3.273 +}
   3.274 +
   3.275 +static void enum_domains(void)
   3.276 +{
   3.277 +	int domid = 0;
   3.278 +	xc_dominfo_t dominfo;
   3.279 +
   3.280 +	while (xc_domain_getinfo(xc, domid, 1, &dominfo) == 1) {
   3.281 +		lookup_domain(dominfo.domid);
   3.282 +		domid = dominfo.domid + 1;
   3.283 +	}
   3.284 +}
   3.285 +
   3.286 +void handle_io(void)
   3.287 +{
   3.288 +	fd_set readfds, writefds;
   3.289 +	int ret;
   3.290 +	int max_fd = -1;
   3.291 +
   3.292 +	do {
   3.293 +		struct domain *d;
   3.294 +		struct timeval tv = { 1, 0 };
   3.295 +
   3.296 +		FD_ZERO(&readfds);
   3.297 +		FD_ZERO(&writefds);
   3.298 +
   3.299 +		FD_SET(xcs_data_fd, &readfds);
   3.300 +		max_fd = MAX(xcs_data_fd, max_fd);
   3.301 +
   3.302 +		for (d = dom_head; d; d = d->next) {
   3.303 +			if (d->tty_fd != -1) {
   3.304 +				FD_SET(d->tty_fd, &readfds);
   3.305 +			}
   3.306 +
   3.307 +			if (d->tty_fd != -1 && !buffer_empty(&d->buffer)) {
   3.308 +				FD_SET(d->tty_fd, &writefds);
   3.309 +			}
   3.310 +
   3.311 +			max_fd = MAX(d->tty_fd, max_fd);
   3.312 +		}
   3.313 +
   3.314 +		ret = select(max_fd + 1, &readfds, &writefds, 0, &tv);
   3.315 +		enum_domains();
   3.316 +
   3.317 +		if (FD_ISSET(xcs_data_fd, &readfds)) {
   3.318 +			handle_xcs_msg(xcs_data_fd);
   3.319 +		}
   3.320 +
   3.321 +		for (d = dom_head; d; d = d->next) {
   3.322 +			if (FD_ISSET(d->tty_fd, &readfds)) {
   3.323 +				handle_tty_read(d);
   3.324 +			}
   3.325 +
   3.326 +			if (FD_ISSET(d->tty_fd, &writefds)) {
   3.327 +				handle_tty_write(d);
   3.328 +			}
   3.329 +		}
   3.330 +	} while (ret > -1);
   3.331 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/consoled/io.h	Tue Aug 02 12:18:47 2005 +0000
     4.3 @@ -0,0 +1,26 @@
     4.4 +/*\
     4.5 + *  Copyright (C) International Business Machines  Corp., 2005
     4.6 + *  Author(s): Anthony Liguori <aliguori@us.ibm.com>
     4.7 + *
     4.8 + *  Xen Console Daemon
     4.9 + *
    4.10 + *  This program is free software; you can redistribute it and/or modify
    4.11 + *  it under the terms of the GNU General Public License as published by
    4.12 + *  the Free Software Foundation; under version 2 of the License.
    4.13 + * 
    4.14 + *  This program is distributed in the hope that it will be useful,
    4.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.17 + *  GNU General Public License for more details.
    4.18 + * 
    4.19 + *  You should have received a copy of the GNU General Public License
    4.20 + *  along with this program; if not, write to the Free Software
    4.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    4.22 +\*/
    4.23 +
    4.24 +#ifndef CONSOLED_IO_H
    4.25 +#define CONSOLED_IO_H
    4.26 +
    4.27 +void handle_io(void);
    4.28 +
    4.29 +#endif
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/consoled/main.c	Tue Aug 02 12:18:47 2005 +0000
     5.3 @@ -0,0 +1,93 @@
     5.4 +/*\
     5.5 + *  Copyright (C) International Business Machines  Corp., 2005
     5.6 + *  Author(s): Anthony Liguori <aliguori@us.ibm.com>
     5.7 + *
     5.8 + *  Xen Console Daemon
     5.9 + *
    5.10 + *  This program is free software; you can redistribute it and/or modify
    5.11 + *  it under the terms of the GNU General Public License as published by
    5.12 + *  the Free Software Foundation; under version 2 of the License.
    5.13 + * 
    5.14 + *  This program is distributed in the hope that it will be useful,
    5.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.17 + *  GNU General Public License for more details.
    5.18 + * 
    5.19 + *  You should have received a copy of the GNU General Public License
    5.20 + *  along with this program; if not, write to the Free Software
    5.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    5.22 +\*/
    5.23 +
    5.24 +#include <getopt.h>
    5.25 +#include <stdlib.h>
    5.26 +#include <stdio.h>
    5.27 +#include <errno.h>
    5.28 +#include <unistd.h>
    5.29 +#include <sys/types.h>
    5.30 +
    5.31 +#include "xc.h"
    5.32 +#include "xen/io/domain_controller.h"
    5.33 +#include "xcs_proto.h"
    5.34 +
    5.35 +#include "utils.h"
    5.36 +#include "io.h"
    5.37 +
    5.38 +int main(int argc, char **argv)
    5.39 +{
    5.40 +	const char *sopts = "hVvi";
    5.41 +	struct option lopts[] = {
    5.42 +		{ "help", 0, 0, 'h' },
    5.43 +		{ "version", 0, 0, 'V' },
    5.44 +		{ "verbose", 0, 0, 'v' },
    5.45 +		{ "interactive", 0, 0, 'i' },
    5.46 +		{ 0 },
    5.47 +	};
    5.48 +	bool is_interactive = false;
    5.49 +	int ch;
    5.50 +	int syslog_option = LOG_CONS;
    5.51 +	int syslog_mask = LOG_WARNING;
    5.52 +	int opt_ind = 0;
    5.53 +
    5.54 +	while ((ch = getopt_long(argc, argv, sopts, lopts, &opt_ind)) != -1) {
    5.55 +		switch (ch) {
    5.56 +		case 'h':
    5.57 +			//usage(argv[0]);
    5.58 +			exit(0);
    5.59 +		case 'V':
    5.60 +			//version(argv[0]);
    5.61 +			exit(0);
    5.62 +		case 'v':
    5.63 +			syslog_option |= LOG_PERROR;
    5.64 +			syslog_mask = LOG_DEBUG;
    5.65 +			break;
    5.66 +		case 'i':
    5.67 +			is_interactive = true;
    5.68 +			break;
    5.69 +		case '?':
    5.70 +			fprintf(stderr,
    5.71 +				"Try `%s --help' for more information\n",
    5.72 +				argv[0]);
    5.73 +			exit(EINVAL);
    5.74 +		}
    5.75 +	}
    5.76 +
    5.77 +	if (geteuid() != 0) {
    5.78 +		fprintf(stderr, "%s requires root to run.\n", argv[0]);
    5.79 +		exit(EPERM);
    5.80 +	}
    5.81 +
    5.82 +	openlog("consoled", syslog_option, LOG_DAEMON);
    5.83 +	setlogmask(syslog_mask);
    5.84 +
    5.85 +	if (!is_interactive) {
    5.86 +		daemonize("/var/run/consoled.pid");
    5.87 +	}
    5.88 +
    5.89 +	xen_setup();
    5.90 +
    5.91 +	handle_io();
    5.92 +
    5.93 +	closelog();
    5.94 +
    5.95 +	return 0;
    5.96 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/consoled/utils.c	Tue Aug 02 12:18:47 2005 +0000
     6.3 @@ -0,0 +1,251 @@
     6.4 +/*\
     6.5 + *  Copyright (C) International Business Machines  Corp., 2005
     6.6 + *  Author(s): Anthony Liguori <aliguori@us.ibm.com>
     6.7 + *
     6.8 + *  Xen Console Daemon
     6.9 + *
    6.10 + *  This program is free software; you can redistribute it and/or modify
    6.11 + *  it under the terms of the GNU General Public License as published by
    6.12 + *  the Free Software Foundation; under version 2 of the License.
    6.13 + * 
    6.14 + *  This program is distributed in the hope that it will be useful,
    6.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.17 + *  GNU General Public License for more details.
    6.18 + * 
    6.19 + *  You should have received a copy of the GNU General Public License
    6.20 + *  along with this program; if not, write to the Free Software
    6.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    6.22 +\*/
    6.23 +
    6.24 +#include <sys/types.h>
    6.25 +#include <sys/stat.h>
    6.26 +#include <sys/wait.h>
    6.27 +#include <unistd.h>
    6.28 +#include <stdlib.h>
    6.29 +#include <fcntl.h>
    6.30 +#include <err.h>
    6.31 +#include <errno.h>
    6.32 +#include <stdio.h>
    6.33 +#include <getopt.h>
    6.34 +#include <stdbool.h>
    6.35 +#include <sys/socket.h>
    6.36 +#include <sys/un.h>
    6.37 +#include <string.h>
    6.38 +
    6.39 +#include "xc.h"
    6.40 +#include "xen/io/domain_controller.h"
    6.41 +#include "xcs_proto.h"
    6.42 +
    6.43 +#include "utils.h"
    6.44 +
    6.45 +struct xs_handle *xs;
    6.46 +int xc;
    6.47 +
    6.48 +int xcs_ctrl_fd = -1;
    6.49 +int xcs_data_fd = -1;
    6.50 +
    6.51 +bool _read_write_sync(int fd, void *data, size_t size, bool do_read)
    6.52 +{
    6.53 +	size_t offset = 0;
    6.54 +	ssize_t len;
    6.55 +
    6.56 +	while (offset < size) {
    6.57 +		if (do_read) {
    6.58 +			len = read(fd, data + offset, size - offset);
    6.59 +		} else {
    6.60 +			len = write(fd, data + offset, size - offset);
    6.61 +		}
    6.62 +
    6.63 +		if (len < 1) {
    6.64 +			if (len == -1 && (errno == EAGAIN || errno == EINTR)) {
    6.65 +				return false;
    6.66 +			}
    6.67 +		} else {
    6.68 +			offset += len;
    6.69 +		}
    6.70 +	}
    6.71 +
    6.72 +	return true;
    6.73 +}
    6.74 +
    6.75 +static int open_domain_socket(const char *path)
    6.76 +{
    6.77 +	struct sockaddr_un addr;
    6.78 +	int sock;
    6.79 +	size_t addr_len;
    6.80 +
    6.81 +	if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
    6.82 +		goto out;
    6.83 +	}
    6.84 +
    6.85 +	addr.sun_family = AF_UNIX;
    6.86 +	strcpy(addr.sun_path, path);
    6.87 +	addr_len = sizeof(addr.sun_family) + strlen(XCS_SUN_PATH) + 1;
    6.88 +
    6.89 +	if (connect(sock, (struct sockaddr *)&addr, addr_len) == -1) {
    6.90 +		goto out_close_sock;
    6.91 +	}
    6.92 +
    6.93 +	return sock;
    6.94 +
    6.95 + out_close_sock:
    6.96 +	close(sock);
    6.97 + out:
    6.98 +	return -1;
    6.99 +}
   6.100 +
   6.101 +static void child_exit(int sig)
   6.102 +{
   6.103 +	while (waitpid(-1, NULL, WNOHANG) > 0);
   6.104 +}
   6.105 +
   6.106 +void daemonize(const char *pidfile)
   6.107 +{
   6.108 +	pid_t pid;
   6.109 +	int fd;
   6.110 +	int len;
   6.111 +	int i;
   6.112 +	char buf[100];
   6.113 +
   6.114 +	if (getppid() == 1) {
   6.115 +		return;
   6.116 +	}
   6.117 +
   6.118 +	if ((pid = fork()) > 0) {
   6.119 +		exit(0);
   6.120 +	} else if (pid == -1) {
   6.121 +		err(errno, "fork() failed");
   6.122 +	}
   6.123 +
   6.124 +	setsid();
   6.125 +
   6.126 +	/* redirect fd 0,1,2 to /dev/null */
   6.127 +	if ((fd = open("/dev/null",O_RDWR)) == -1) {
   6.128 +		exit(1);
   6.129 +	}
   6.130 +
   6.131 +	for (i = 0; i <= 2; i++) {
   6.132 +		close(i);
   6.133 +		dup2(fd, i);
   6.134 +	}
   6.135 +
   6.136 +	close(fd);
   6.137 +
   6.138 +	umask(027);
   6.139 +	chdir("/");
   6.140 +
   6.141 +	fd = open(pidfile, O_RDWR | O_CREAT);
   6.142 +	if (fd == -1) {
   6.143 +		exit(1);
   6.144 +	}
   6.145 +
   6.146 +	if (lockf(fd, F_TLOCK, 0) == -1) {
   6.147 +		exit(1);
   6.148 +	}
   6.149 +
   6.150 +	len = sprintf(buf, "%d\n", getpid());
   6.151 +	write(fd, buf, len);
   6.152 +
   6.153 +	signal(SIGCHLD, child_exit);
   6.154 +	signal(SIGTSTP, SIG_IGN);
   6.155 +	signal(SIGTTOU, SIG_IGN);
   6.156 +	signal(SIGTTIN, SIG_IGN);
   6.157 +}
   6.158 +
   6.159 +/* synchronized send/recv strictly for setting up xcs */
   6.160 +/* always use asychronize callbacks any other time */
   6.161 +static bool xcs_send_recv(int fd, xcs_msg_t *msg)
   6.162 +{
   6.163 +	bool ret = false;
   6.164 +
   6.165 +	if (!write_sync(fd, msg, sizeof(*msg))) {
   6.166 +		dolog(LOG_ERR, "Write failed at %s:%s():L%d?  Possible bug.",
   6.167 +		       __FILE__, __FUNCTION__, __LINE__);
   6.168 +		goto out;
   6.169 +	}
   6.170 +
   6.171 +	if (!read_sync(fd, msg, sizeof(*msg))) {
   6.172 +		dolog(LOG_ERR, "Read failed at %s:%s():L%d?  Possible bug.",
   6.173 +		       __FILE__, __FUNCTION__, __LINE__);
   6.174 +		goto out;
   6.175 +	}
   6.176 +
   6.177 +	ret = true;
   6.178 +
   6.179 + out:
   6.180 +	return ret;
   6.181 +}
   6.182 +
   6.183 +bool xen_setup(void)
   6.184 +{
   6.185 +	int sock;
   6.186 +	xcs_msg_t msg;
   6.187 +	
   6.188 +	xs = xs_daemon_open();
   6.189 +	if (xs == NULL) {
   6.190 +		dolog(LOG_ERR,
   6.191 +		      "Failed to contact xenstore (%m).  Is it running?");
   6.192 +		goto out;
   6.193 +	}
   6.194 +
   6.195 +	xc = xc_interface_open();
   6.196 +	if (xc == -1) {
   6.197 +		dolog(LOG_ERR, "Failed to contact hypervisor (%m)");
   6.198 +		goto out;
   6.199 +	}
   6.200 +
   6.201 +	sock = open_domain_socket(XCS_SUN_PATH);
   6.202 +	if (sock == -1) {
   6.203 +		dolog(LOG_ERR, "Failed to contact xcs (%m).  Is it running?");
   6.204 +		goto out_close_store;
   6.205 +	}
   6.206 +
   6.207 +	xcs_ctrl_fd = sock;
   6.208 +
   6.209 +	sock = open_domain_socket(XCS_SUN_PATH);
   6.210 +	if (sock == -1) {
   6.211 +		dolog(LOG_ERR, "Failed to contact xcs (%m).  Is it running?");
   6.212 +		goto out_close_ctrl;
   6.213 +	}
   6.214 +	
   6.215 +	xcs_data_fd = sock;
   6.216 +
   6.217 +	memset(&msg, 0, sizeof(msg));
   6.218 +	msg.type = XCS_CONNECT_CTRL;
   6.219 +	if (!xcs_send_recv(xcs_ctrl_fd, &msg) || msg.result != XCS_RSLT_OK) {
   6.220 +		dolog(LOG_ERR, "xcs control connect failed.  Possible bug.");
   6.221 +		goto out_close_data;
   6.222 +	}
   6.223 +
   6.224 +	msg.type = XCS_CONNECT_DATA;
   6.225 +	if (!xcs_send_recv(xcs_data_fd, &msg) || msg.result != XCS_RSLT_OK) {
   6.226 +		dolog(LOG_ERR, "xcs data connect failed.  Possible bug.");
   6.227 +		goto out_close_data;
   6.228 +	}
   6.229 +
   6.230 +	/* Since the vast majority of control messages are console messages
   6.231 +	   it's just easier to ignore other messages that try to bind to 
   6.232 +	   a specific type. */
   6.233 +	msg.type = XCS_MSG_BIND;
   6.234 +	msg.u.bind.port = PORT_WILDCARD;
   6.235 +	msg.u.bind.type = TYPE_WILDCARD;
   6.236 +	if (!xcs_send_recv(xcs_ctrl_fd, &msg) || msg.result != XCS_RSLT_OK) {
   6.237 +		dolog(LOG_ERR, "xcs vind failed.  Possible bug.");
   6.238 +		goto out_close_data;
   6.239 +	}
   6.240 +	
   6.241 +	return true;
   6.242 +
   6.243 + out_close_data:
   6.244 +	close(xcs_ctrl_fd);
   6.245 +	xcs_data_fd = -1;
   6.246 + out_close_ctrl:
   6.247 +	close(xcs_ctrl_fd);
   6.248 +	xcs_ctrl_fd = -1;
   6.249 + out_close_store:
   6.250 +	xs_daemon_close(xs);
   6.251 + out:
   6.252 +	return false;
   6.253 +}
   6.254 +
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/consoled/utils.h	Tue Aug 02 12:18:47 2005 +0000
     7.3 @@ -0,0 +1,47 @@
     7.4 +/*\
     7.5 + *  Copyright (C) International Business Machines  Corp., 2005
     7.6 + *  Author(s): Anthony Liguori <aliguori@us.ibm.com>
     7.7 + *
     7.8 + *  Xen Console Daemon
     7.9 + *
    7.10 + *  This program is free software; you can redistribute it and/or modify
    7.11 + *  it under the terms of the GNU General Public License as published by
    7.12 + *  the Free Software Foundation; under version 2 of the License.
    7.13 + * 
    7.14 + *  This program is distributed in the hope that it will be useful,
    7.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.17 + *  GNU General Public License for more details.
    7.18 + * 
    7.19 + *  You should have received a copy of the GNU General Public License
    7.20 + *  along with this program; if not, write to the Free Software
    7.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    7.22 +\*/
    7.23 +
    7.24 +#ifndef CONSOLED_UTILS_H
    7.25 +#define CONSOLED_UTILS_H
    7.26 +
    7.27 +#include <stdbool.h>
    7.28 +#include <syslog.h>
    7.29 +#include <stdio.h>
    7.30 +
    7.31 +#include "xs.h"
    7.32 +
    7.33 +void daemonize(const char *pidfile);
    7.34 +bool xen_setup(void);
    7.35 +#define read_sync(fd, buffer, size) _read_write_sync(fd, buffer, size, true)
    7.36 +#define write_sync(fd, buffer, size) _read_write_sync(fd, buffer, size, false)
    7.37 +bool _read_write_sync(int fd, void *data, size_t size, bool do_read);
    7.38 +
    7.39 +extern int xcs_ctrl_fd;
    7.40 +extern int xcs_data_fd;
    7.41 +extern struct xs_handle *xs;
    7.42 +extern int xc;
    7.43 +
    7.44 +#if 1
    7.45 +#define dolog(val, fmt, ...) syslog(val, fmt, ## __VA_ARGS__)
    7.46 +#else
    7.47 +#define dolog(val, fmt, ...) fprintf(stderr, fmt "\n", ## __VA_ARGS__)
    7.48 +#endif
    7.49 +
    7.50 +#endif
     8.1 Binary file tools/consoled/xc_console has changed
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/consoled/xc_console.c	Tue Aug 02 12:18:47 2005 +0000
     9.3 @@ -0,0 +1,236 @@
     9.4 +/*\
     9.5 + *  Copyright (C) International Business Machines  Corp., 2005
     9.6 + *  Author(s): Anthony Liguori <aliguori@us.ibm.com>
     9.7 + *
     9.8 + *  Xen Console Daemon
     9.9 + *
    9.10 + *  This program is free software; you can redistribute it and/or modify
    9.11 + *  it under the terms of the GNU General Public License as published by
    9.12 + *  the Free Software Foundation; under version 2 of the License.
    9.13 + * 
    9.14 + *  This program is distributed in the hope that it will be useful,
    9.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.17 + *  GNU General Public License for more details.
    9.18 + * 
    9.19 + *  You should have received a copy of the GNU General Public License
    9.20 + *  along with this program; if not, write to the Free Software
    9.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    9.22 +\*/
    9.23 +
    9.24 +#include <sys/types.h>
    9.25 +#include <sys/socket.h>
    9.26 +#include <sys/un.h>
    9.27 +#include <stdio.h>
    9.28 +#include <unistd.h>
    9.29 +#include <errno.h>
    9.30 +#include <stdlib.h>
    9.31 +#include <time.h>
    9.32 +#include <fcntl.h>
    9.33 +#include <sys/wait.h>
    9.34 +#include <termios.h>
    9.35 +#include <signal.h>
    9.36 +#include <getopt.h>
    9.37 +#include <sys/select.h>
    9.38 +#include <err.h>
    9.39 +#include <errno.h>
    9.40 +#include <pty.h>
    9.41 +
    9.42 +#include "xc.h"
    9.43 +#include "xs.h"
    9.44 +
    9.45 +#define ESCAPE_CHARACTER 0x1d
    9.46 +
    9.47 +static volatile sig_atomic_t received_signal = 0;
    9.48 +
    9.49 +static void sighandler(int signum)
    9.50 +{
    9.51 +	received_signal = 1;
    9.52 +}
    9.53 +
    9.54 +static bool write_sync(int fd, const void *data, size_t size)
    9.55 +{
    9.56 +	size_t offset = 0;
    9.57 +	ssize_t len;
    9.58 +
    9.59 +	while (offset < size) {
    9.60 +		len = write(fd, data + offset, size - offset);
    9.61 +		if (len < 1) {
    9.62 +			return false;
    9.63 +		}
    9.64 +		offset += len;
    9.65 +	}
    9.66 +
    9.67 +	return true;
    9.68 +}
    9.69 +
    9.70 +static void usage(const char *program) {
    9.71 +	printf("Usage: %s [OPTION] DOMID\n"
    9.72 +	       "Attaches to a virtual domain console\n"
    9.73 +	       "\n"
    9.74 +	       "  -h, --help       display this help and exit\n"
    9.75 +	       , program);
    9.76 +}
    9.77 +
    9.78 +/* don't worry too much if setting terminal attributes fail */
    9.79 +static void init_term(int fd, struct termios *old)
    9.80 +{
    9.81 +	struct termios new_term;
    9.82 +
    9.83 +	if (tcgetattr(fd, old) == -1) {
    9.84 +		perror("tcgetattr() failed");
    9.85 +		return;
    9.86 +	}
    9.87 +
    9.88 +	new_term = *old;
    9.89 +	cfmakeraw(&new_term);
    9.90 +
    9.91 +	if (tcsetattr(fd, TCSAFLUSH, &new_term) == -1) {
    9.92 +		perror("tcsetattr() failed");
    9.93 +	}
    9.94 +}
    9.95 +
    9.96 +static void restore_term(int fd, struct termios *old)
    9.97 +{
    9.98 +	if (tcsetattr(fd, TCSAFLUSH, old) == -1) {
    9.99 +		perror("tcsetattr() failed");
   9.100 +	}
   9.101 +}
   9.102 +
   9.103 +static int console_loop(int xc_handle, domid_t domid, int fd)
   9.104 +{
   9.105 +	int ret;
   9.106 +
   9.107 +	do {
   9.108 +		fd_set fds;
   9.109 +
   9.110 +		FD_ZERO(&fds);
   9.111 +		FD_SET(STDIN_FILENO, &fds);
   9.112 +		FD_SET(fd, &fds);
   9.113 +
   9.114 +		ret = select(fd + 1, &fds, NULL, NULL, NULL);
   9.115 +		if (ret == -1) {
   9.116 +			if (errno == EINTR || errno == EAGAIN) {
   9.117 +				continue;
   9.118 +			}
   9.119 +			perror("select() failed");
   9.120 +			return -1;
   9.121 +		}
   9.122 +
   9.123 +		if (FD_ISSET(STDIN_FILENO, &fds)) {
   9.124 +			ssize_t len;
   9.125 +			char msg[60];
   9.126 +
   9.127 +			len = read(STDIN_FILENO, msg, sizeof(msg));
   9.128 +			if (len == 1 && msg[0] == ESCAPE_CHARACTER) {
   9.129 +				return 0;
   9.130 +			} 
   9.131 +
   9.132 +			if (len == 0 && len == -1) {
   9.133 +				if (len == -1 &&
   9.134 +				    (errno == EINTR || errno == EAGAIN)) {
   9.135 +					continue;
   9.136 +				}
   9.137 +				perror("select() failed");
   9.138 +				return -1;
   9.139 +			}
   9.140 +
   9.141 +			if (!write_sync(fd, msg, len)) {
   9.142 +				perror("write() failed");
   9.143 +				return -1;
   9.144 +			}
   9.145 +		}
   9.146 +
   9.147 +		if (FD_ISSET(fd, &fds)) {
   9.148 +			ssize_t len;
   9.149 +			char msg[512];
   9.150 +
   9.151 +			len = read(fd, msg, sizeof(msg));
   9.152 +			if (len == 0 || len == -1) {
   9.153 +				if (len == -1 &&
   9.154 +				    (errno == EINTR || errno == EAGAIN)) {
   9.155 +					continue;
   9.156 +				}
   9.157 +				perror("select() failed");
   9.158 +				return -1;
   9.159 +			}
   9.160 +
   9.161 +			if (!write_sync(STDOUT_FILENO, msg, len)) {
   9.162 +				perror("write() failed");
   9.163 +				return -1;
   9.164 +			}
   9.165 +		}
   9.166 +	} while (received_signal == 0);
   9.167 +
   9.168 +	return 0;
   9.169 +}
   9.170 +
   9.171 +int main(int argc, char **argv)
   9.172 +{
   9.173 +	struct termios attr;
   9.174 +	int domid;
   9.175 +	int xc_handle;
   9.176 +	char *sopt = "hf:pc";
   9.177 +	int ch;
   9.178 +	int opt_ind=0;
   9.179 +	struct option lopt[] = {
   9.180 +		{ "help",    0, 0, 'h' },
   9.181 +		{ "file",    1, 0, 'f' },
   9.182 +		{ "pty",     0, 0, 'p' },
   9.183 +		{ "ctty",    0, 0, 'c' },
   9.184 +		{ 0 },
   9.185 +
   9.186 +	};
   9.187 +	char *str_pty;
   9.188 +	char path[1024];
   9.189 +	int spty;
   9.190 +	unsigned int len = 0;
   9.191 +	struct xs_handle *xs;
   9.192 +
   9.193 +	while((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
   9.194 +		switch(ch) {
   9.195 +		case 'h':
   9.196 +			usage(argv[0]);
   9.197 +			exit(0);
   9.198 +			break;
   9.199 +		}
   9.200 +	}
   9.201 +	
   9.202 +	if ((argc - optind) != 1) {
   9.203 +		fprintf(stderr, "Invalid number of arguments\n");
   9.204 +		fprintf(stderr, "Try `%s --help' for more information.\n", 
   9.205 +			argv[0]);
   9.206 +		exit(EINVAL);
   9.207 +	}
   9.208 +	
   9.209 +	domid = atoi(argv[optind]);
   9.210 +
   9.211 +	xs = xs_daemon_open();
   9.212 +	if (xs == NULL) {
   9.213 +		err(errno, "Could not contact XenStore");
   9.214 +	}
   9.215 +
   9.216 +	xc_handle = xc_interface_open();
   9.217 +	if (xc_handle == -1) {
   9.218 +		err(errno, "xc_interface_open()");
   9.219 +	}
   9.220 +	
   9.221 +	signal(SIGTERM, sighandler);
   9.222 +
   9.223 +	snprintf(path, sizeof(path), "/console/%d/tty", domid);
   9.224 +	str_pty = xs_read(xs, path, &len);
   9.225 +	if (str_pty == NULL) {
   9.226 +		err(errno, "Could not read tty from store");
   9.227 +	}
   9.228 +	spty = open(str_pty, O_RDWR | O_NOCTTY);
   9.229 +	if (spty == -1) {
   9.230 +		err(errno, "Could not open tty `%s'", str_pty);
   9.231 +	}
   9.232 +	free(str_pty);
   9.233 +
   9.234 +	init_term(STDIN_FILENO, &attr);
   9.235 +	console_loop(xc_handle, domid, spty);
   9.236 +	restore_term(STDIN_FILENO, &attr);
   9.237 +
   9.238 +	return 0;
   9.239 + }