ia64/xen-unstable

view tools/xenstore/xenstored_core.c @ 8740:3d7ea7972b39

Update patches for linux 2.6.15.

Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Thu Feb 02 17:16:00 2006 +0000 (2006-02-02)
parents 6afcef051257
children 47013962e411
line source
1 /*
2 Simple prototype Xen Store Daemon providing simple tree-like database.
3 Copyright (C) 2005 Rusty Russell IBM Corporation
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <sys/socket.h>
23 #include <sys/select.h>
24 #include <sys/un.h>
25 #include <sys/time.h>
26 #include <time.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <stdbool.h>
30 #include <stdio.h>
31 #include <stdarg.h>
32 #include <stdlib.h>
33 #include <syslog.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <dirent.h>
37 #include <getopt.h>
38 #include <signal.h>
39 #include <assert.h>
40 #include <setjmp.h>
42 //#define DEBUG
43 #include "utils.h"
44 #include "list.h"
45 #include "talloc.h"
46 #include "xs_lib.h"
47 #include "xenstored_core.h"
48 #include "xenstored_watch.h"
49 #include "xenstored_transaction.h"
50 #include "xenstored_domain.h"
51 #include "xenctrl.h"
52 #include "tdb.h"
54 extern int eventchn_fd; /* in xenstored_domain.c */
56 static bool verbose;
57 LIST_HEAD(connections);
58 static int tracefd = -1;
59 static int reopen_log_pipe[2];
60 static char *tracefile = NULL;
61 static TDB_CONTEXT *tdb_ctx;
63 #ifdef TESTING
64 static bool failtest = false;
66 /* We override talloc's malloc. */
67 void *test_malloc(size_t size)
68 {
69 /* 1 in 20 means only about 50% of connections establish. */
70 if (failtest && (random() % 32) == 0)
71 return NULL;
72 return malloc(size);
73 }
75 static void stop_failtest(int signum __attribute__((unused)))
76 {
77 failtest = false;
78 }
80 /* Need these before we #define away write_all/mkdir in testing.h */
81 bool test_write_all(int fd, void *contents, unsigned int len);
82 bool test_write_all(int fd, void *contents, unsigned int len)
83 {
84 if (failtest && (random() % 8) == 0) {
85 if (len)
86 len = random() % len;
87 write(fd, contents, len);
88 errno = ENOSPC;
89 return false;
90 }
91 return xs_write_all(fd, contents, len);
92 }
94 int test_mkdir(const char *dir, int perms);
95 int test_mkdir(const char *dir, int perms)
96 {
97 if (failtest && (random() % 8) == 0) {
98 errno = ENOSPC;
99 return -1;
100 }
101 return mkdir(dir, perms);
102 }
103 #endif /* TESTING */
105 #include "xenstored_test.h"
107 /* FIXME: Ideally, this should never be called. Some can be eliminated. */
108 /* Something is horribly wrong: shutdown immediately. */
109 void __attribute__((noreturn)) corrupt(struct connection *conn,
110 const char *fmt, ...)
111 {
112 va_list arglist;
113 char *str;
114 int saved_errno = errno;
116 va_start(arglist, fmt);
117 str = talloc_vasprintf(NULL, fmt, arglist);
118 va_end(arglist);
120 trace("xenstored corruption: connection id %i: err %s: %s",
121 conn ? (int)conn->id : -1, strerror(saved_errno), str);
122 eprintf("xenstored corruption: connection id %i: err %s: %s",
123 conn ? (int)conn->id : -1, strerror(saved_errno), str);
124 #ifdef TESTING
125 /* Allow them to attach debugger. */
126 sleep(30);
127 #endif
128 syslog(LOG_DAEMON,
129 "xenstored corruption: connection id %i: err %s: %s",
130 conn ? (int)conn->id : -1, strerror(saved_errno), str);
131 _exit(2);
132 }
134 TDB_CONTEXT *tdb_context(struct connection *conn)
135 {
136 /* conn = NULL used in manual_node at setup. */
137 if (!conn || !conn->transaction)
138 return tdb_ctx;
139 return tdb_transaction_context(conn->transaction);
140 }
142 bool replace_tdb(const char *newname, TDB_CONTEXT *newtdb)
143 {
144 if (rename(newname, xs_daemon_tdb()) != 0)
145 return false;
146 tdb_close(tdb_ctx);
147 tdb_ctx = talloc_steal(talloc_autofree_context(), newtdb);
148 return true;
149 }
151 static char *sockmsg_string(enum xsd_sockmsg_type type)
152 {
153 switch (type) {
154 case XS_DEBUG: return "DEBUG";
155 case XS_DIRECTORY: return "DIRECTORY";
156 case XS_READ: return "READ";
157 case XS_GET_PERMS: return "GET_PERMS";
158 case XS_WATCH: return "WATCH";
159 case XS_UNWATCH: return "UNWATCH";
160 case XS_TRANSACTION_START: return "TRANSACTION_START";
161 case XS_TRANSACTION_END: return "TRANSACTION_END";
162 case XS_INTRODUCE: return "INTRODUCE";
163 case XS_RELEASE: return "RELEASE";
164 case XS_GET_DOMAIN_PATH: return "GET_DOMAIN_PATH";
165 case XS_WRITE: return "WRITE";
166 case XS_MKDIR: return "MKDIR";
167 case XS_RM: return "RM";
168 case XS_SET_PERMS: return "SET_PERMS";
169 case XS_WATCH_EVENT: return "WATCH_EVENT";
170 case XS_ERROR: return "ERROR";
171 case XS_IS_DOMAIN_INTRODUCED: return "XS_IS_DOMAIN_INTRODUCED";
172 default:
173 return "**UNKNOWN**";
174 }
175 }
177 void trace(const char *fmt, ...)
178 {
179 va_list arglist;
180 char *str;
181 char sbuf[1024];
182 int ret;
184 if (tracefd < 0)
185 return;
187 /* try to use a static buffer */
188 va_start(arglist, fmt);
189 ret = vsnprintf(sbuf, 1024, fmt, arglist);
190 va_end(arglist);
192 if (ret <= 1024) {
193 write(tracefd, sbuf, ret);
194 return;
195 }
197 /* fail back to dynamic allocation */
198 va_start(arglist, fmt);
199 str = talloc_vasprintf(NULL, fmt, arglist);
200 va_end(arglist);
201 write(tracefd, str, strlen(str));
202 talloc_free(str);
203 }
205 static void trace_io(const struct connection *conn,
206 const char *prefix,
207 const struct buffered_data *data)
208 {
209 unsigned int i;
210 time_t now;
211 struct tm *tm;
213 if (tracefd < 0)
214 return;
216 now = time(NULL);
217 tm = localtime(&now);
219 trace("%s %p %02d:%02d:%02d %s (", prefix, conn,
220 tm->tm_hour, tm->tm_min, tm->tm_sec,
221 sockmsg_string(data->hdr.msg.type));
223 for (i = 0; i < data->hdr.msg.len; i++)
224 trace("%c", (data->buffer[i] != '\0') ? data->buffer[i] : ' ');
225 trace(")\n");
226 }
228 void trace_create(const void *data, const char *type)
229 {
230 trace("CREATE %s %p\n", type, data);
231 }
233 void trace_destroy(const void *data, const char *type)
234 {
235 trace("DESTROY %s %p\n", type, data);
236 }
238 /**
239 * Signal handler for SIGHUP, which requests that the trace log is reopened
240 * (in the main loop). A single byte is written to reopen_log_pipe, to awaken
241 * the select() in the main loop.
242 */
243 static void trigger_reopen_log(int signal __attribute__((unused)))
244 {
245 char c = 'A';
246 write(reopen_log_pipe[1], &c, 1);
247 }
250 static void reopen_log()
251 {
252 if (tracefile) {
253 if (tracefd > 0)
254 close(tracefd);
256 tracefd = open(tracefile, O_WRONLY|O_CREAT|O_APPEND, 0600);
258 if (tracefd < 0)
259 perror("Could not open tracefile");
260 else
261 trace("\n***\n");
262 }
263 }
266 static bool write_messages(struct connection *conn)
267 {
268 int ret;
269 struct buffered_data *out;
271 out = list_top(&conn->out_list, struct buffered_data, list);
272 if (out == NULL)
273 return true;
275 if (out->inhdr) {
276 if (verbose)
277 xprintf("Writing msg %s (%.*s) out to %p\n",
278 sockmsg_string(out->hdr.msg.type),
279 out->hdr.msg.len,
280 out->buffer, conn);
281 ret = conn->write(conn, out->hdr.raw + out->used,
282 sizeof(out->hdr) - out->used);
283 if (ret < 0)
284 return false;
286 out->used += ret;
287 if (out->used < sizeof(out->hdr))
288 return true;
290 out->inhdr = false;
291 out->used = 0;
293 /* Second write might block if non-zero. */
294 if (out->hdr.msg.len && !conn->domain)
295 return true;
296 }
298 ret = conn->write(conn, out->buffer + out->used,
299 out->hdr.msg.len - out->used);
300 if (ret < 0)
301 return false;
303 out->used += ret;
304 if (out->used != out->hdr.msg.len)
305 return true;
307 trace_io(conn, "OUT", out);
309 list_del(&out->list);
310 talloc_free(out);
312 return true;
313 }
315 static int destroy_conn(void *_conn)
316 {
317 struct connection *conn = _conn;
319 /* Flush outgoing if possible, but don't block. */
320 if (!conn->domain) {
321 fd_set set;
322 struct timeval none;
324 FD_ZERO(&set);
325 FD_SET(conn->fd, &set);
326 none.tv_sec = none.tv_usec = 0;
328 while (!list_empty(&conn->out_list)
329 && select(conn->fd+1, NULL, &set, NULL, &none) == 1)
330 if (!write_messages(conn))
331 break;
332 close(conn->fd);
333 }
334 list_del(&conn->list);
335 trace_destroy(conn, "connection");
336 return 0;
337 }
340 static void set_fd(int fd, fd_set *set, int *max)
341 {
342 FD_SET(fd, set);
343 if (fd > *max)
344 *max = fd;
345 }
348 static int initialize_set(fd_set *inset, fd_set *outset, int sock, int ro_sock)
349 {
350 struct connection *i;
351 int max = -1;
353 FD_ZERO(inset);
354 FD_ZERO(outset);
356 set_fd(sock, inset, &max);
357 set_fd(ro_sock, inset, &max);
358 set_fd(eventchn_fd, inset, &max);
359 set_fd(reopen_log_pipe[0], inset, &max);
360 list_for_each_entry(i, &connections, list) {
361 if (i->domain)
362 continue;
363 set_fd(i->fd, inset, &max);
364 if (!list_empty(&i->out_list))
365 FD_SET(i->fd, outset);
366 }
367 return max;
368 }
370 static int destroy_fd(void *_fd)
371 {
372 int *fd = _fd;
373 close(*fd);
374 return 0;
375 }
377 /* Return a pointer to an fd, self-closing and attached to this pathname. */
378 int *talloc_open(const char *pathname, int flags, int mode)
379 {
380 int *fd;
382 fd = talloc(pathname, int);
383 *fd = open(pathname, flags, mode);
384 if (*fd < 0) {
385 int saved_errno = errno;
386 talloc_free(fd);
387 errno = saved_errno;
388 return NULL;
389 }
390 talloc_set_destructor(fd, destroy_fd);
391 return fd;
392 }
394 /* Is child a subnode of parent, or equal? */
395 bool is_child(const char *child, const char *parent)
396 {
397 unsigned int len = strlen(parent);
399 /* / should really be "" for this algorithm to work, but that's a
400 * usability nightmare. */
401 if (streq(parent, "/"))
402 return true;
404 if (strncmp(child, parent, len) != 0)
405 return false;
407 return child[len] == '/' || child[len] == '\0';
408 }
410 /* If it fails, returns NULL and sets errno. */
411 static struct node *read_node(struct connection *conn, const char *name)
412 {
413 TDB_DATA key, data;
414 uint32_t *p;
415 struct node *node;
417 key.dptr = (void *)name;
418 key.dsize = strlen(name);
419 data = tdb_fetch(tdb_context(conn), key);
421 if (data.dptr == NULL) {
422 if (tdb_error(tdb_context(conn)) == TDB_ERR_NOEXIST)
423 errno = ENOENT;
424 else
425 errno = EIO;
426 return NULL;
427 }
429 node = talloc(name, struct node);
430 node->name = talloc_strdup(node, name);
431 node->parent = NULL;
432 node->tdb = tdb_context(conn);
433 talloc_steal(node, data.dptr);
435 /* Datalen, childlen, number of permissions */
436 p = (uint32_t *)data.dptr;
437 node->num_perms = p[0];
438 node->datalen = p[1];
439 node->childlen = p[2];
441 /* Permissions are struct xs_permissions. */
442 node->perms = (void *)&p[3];
443 /* Data is binary blob (usually ascii, no nul). */
444 node->data = node->perms + node->num_perms;
445 /* Children is strings, nul separated. */
446 node->children = node->data + node->datalen;
448 return node;
449 }
451 static bool write_node(struct connection *conn, const struct node *node)
452 {
453 TDB_DATA key, data;
454 void *p;
456 key.dptr = (void *)node->name;
457 key.dsize = strlen(node->name);
459 data.dsize = 3*sizeof(uint32_t)
460 + node->num_perms*sizeof(node->perms[0])
461 + node->datalen + node->childlen;
462 data.dptr = talloc_size(node, data.dsize);
463 ((uint32_t *)data.dptr)[0] = node->num_perms;
464 ((uint32_t *)data.dptr)[1] = node->datalen;
465 ((uint32_t *)data.dptr)[2] = node->childlen;
466 p = data.dptr + 3 * sizeof(uint32_t);
468 memcpy(p, node->perms, node->num_perms*sizeof(node->perms[0]));
469 p += node->num_perms*sizeof(node->perms[0]);
470 memcpy(p, node->data, node->datalen);
471 p += node->datalen;
472 memcpy(p, node->children, node->childlen);
474 /* TDB should set errno, but doesn't even set ecode AFAICT. */
475 if (tdb_store(tdb_context(conn), key, data, TDB_REPLACE) != 0) {
476 errno = ENOSPC;
477 return false;
478 }
479 return true;
480 }
482 static enum xs_perm_type perm_for_conn(struct connection *conn,
483 struct xs_permissions *perms,
484 unsigned int num)
485 {
486 unsigned int i;
487 enum xs_perm_type mask = XS_PERM_READ|XS_PERM_WRITE|XS_PERM_OWNER;
489 if (!conn->can_write)
490 mask &= ~XS_PERM_WRITE;
492 /* Owners and tools get it all... */
493 if (!conn->id || perms[0].id == conn->id)
494 return (XS_PERM_READ|XS_PERM_WRITE|XS_PERM_OWNER) & mask;
496 for (i = 1; i < num; i++)
497 if (perms[i].id == conn->id)
498 return perms[i].perms & mask;
500 return perms[0].perms & mask;
501 }
503 static char *get_parent(const char *node)
504 {
505 char *slash = strrchr(node + 1, '/');
506 if (!slash)
507 return talloc_strdup(node, "/");
508 return talloc_asprintf(node, "%.*s", (int)(slash - node), node);
509 }
511 /* What do parents say? */
512 static enum xs_perm_type ask_parents(struct connection *conn, const char *name)
513 {
514 struct node *node;
516 do {
517 name = get_parent(name);
518 node = read_node(conn, name);
519 if (node)
520 break;
521 } while (!streq(name, "/"));
523 /* No permission at root? We're in trouble. */
524 if (!node)
525 corrupt(conn, "No permissions file at root");
527 return perm_for_conn(conn, node->perms, node->num_perms);
528 }
530 /* We have a weird permissions system. You can allow someone into a
531 * specific node without allowing it in the parents. If it's going to
532 * fail, however, we don't want the errno to indicate any information
533 * about the node. */
534 static int errno_from_parents(struct connection *conn, const char *node,
535 int errnum, enum xs_perm_type perm)
536 {
537 /* We always tell them about memory failures. */
538 if (errnum == ENOMEM)
539 return errnum;
541 if (ask_parents(conn, node) & perm)
542 return errnum;
543 return EACCES;
544 }
546 /* If it fails, returns NULL and sets errno. */
547 struct node *get_node(struct connection *conn,
548 const char *name,
549 enum xs_perm_type perm)
550 {
551 struct node *node;
553 if (!name || !is_valid_nodename(name)) {
554 errno = EINVAL;
555 return NULL;
556 }
557 node = read_node(conn, name);
558 /* If we don't have permission, we don't have node. */
559 if (node) {
560 if ((perm_for_conn(conn, node->perms, node->num_perms) & perm)
561 != perm)
562 node = NULL;
563 }
564 /* Clean up errno if they weren't supposed to know. */
565 if (!node)
566 errno = errno_from_parents(conn, name, errno, perm);
567 return node;
568 }
570 static struct buffered_data *new_buffer(void *ctx)
571 {
572 struct buffered_data *data;
574 data = talloc(ctx, struct buffered_data);
575 if (data == NULL)
576 return NULL;
578 data->inhdr = true;
579 data->used = 0;
580 data->buffer = NULL;
582 return data;
583 }
585 /* Return length of string (including nul) at this offset. */
586 static unsigned int get_string(const struct buffered_data *data,
587 unsigned int offset)
588 {
589 const char *nul;
591 if (offset >= data->used)
592 return 0;
594 nul = memchr(data->buffer + offset, 0, data->used - offset);
595 if (!nul)
596 return 0;
598 return nul - (data->buffer + offset) + 1;
599 }
601 /* Break input into vectors, return the number, fill in up to num of them. */
602 unsigned int get_strings(struct buffered_data *data,
603 char *vec[], unsigned int num)
604 {
605 unsigned int off, i, len;
607 off = i = 0;
608 while ((len = get_string(data, off)) != 0) {
609 if (i < num)
610 vec[i] = data->buffer + off;
611 i++;
612 off += len;
613 }
614 return i;
615 }
617 void send_reply(struct connection *conn, enum xsd_sockmsg_type type,
618 const void *data, unsigned int len)
619 {
620 struct buffered_data *bdata;
622 /* Message is a child of the connection context for auto-cleanup. */
623 bdata = new_buffer(conn);
624 bdata->buffer = talloc_array(bdata, char, len);
626 /* Echo request header in reply unless this is an async watch event. */
627 if (type != XS_WATCH_EVENT) {
628 memcpy(&bdata->hdr.msg, &conn->in->hdr.msg,
629 sizeof(struct xsd_sockmsg));
630 } else {
631 memset(&bdata->hdr.msg, 0, sizeof(struct xsd_sockmsg));
632 }
634 /* Update relevant header fields and fill in the message body. */
635 bdata->hdr.msg.type = type;
636 bdata->hdr.msg.len = len;
637 memcpy(bdata->buffer, data, len);
639 /* Queue for later transmission. */
640 list_add_tail(&bdata->list, &conn->out_list);
641 }
643 /* Some routines (write, mkdir, etc) just need a non-error return */
644 void send_ack(struct connection *conn, enum xsd_sockmsg_type type)
645 {
646 send_reply(conn, type, "OK", sizeof("OK"));
647 }
649 void send_error(struct connection *conn, int error)
650 {
651 unsigned int i;
653 for (i = 0; error != xsd_errors[i].errnum; i++) {
654 if (i == ARRAY_SIZE(xsd_errors) - 1) {
655 eprintf("xenstored: error %i untranslatable", error);
656 i = 0; /* EINVAL */
657 break;
658 }
659 }
660 send_reply(conn, XS_ERROR, xsd_errors[i].errstring,
661 strlen(xsd_errors[i].errstring) + 1);
662 }
664 static bool valid_chars(const char *node)
665 {
666 /* Nodes can have lots of crap. */
667 return (strspn(node,
668 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
669 "abcdefghijklmnopqrstuvwxyz"
670 "0123456789-/_@") == strlen(node));
671 }
673 bool is_valid_nodename(const char *node)
674 {
675 /* Must start in /. */
676 if (!strstarts(node, "/"))
677 return false;
679 /* Cannot end in / (unless it's just "/"). */
680 if (strends(node, "/") && !streq(node, "/"))
681 return false;
683 /* No double //. */
684 if (strstr(node, "//"))
685 return false;
687 return valid_chars(node);
688 }
690 /* We expect one arg in the input: return NULL otherwise. */
691 static const char *onearg(struct buffered_data *in)
692 {
693 if (!in->used || get_string(in, 0) != in->used)
694 return NULL;
695 return in->buffer;
696 }
698 static char *perms_to_strings(const void *ctx,
699 struct xs_permissions *perms, unsigned int num,
700 unsigned int *len)
701 {
702 unsigned int i;
703 char *strings = NULL;
704 char buffer[MAX_STRLEN(unsigned int) + 1];
706 for (*len = 0, i = 0; i < num; i++) {
707 if (!xs_perm_to_string(&perms[i], buffer))
708 return NULL;
710 strings = talloc_realloc(ctx, strings, char,
711 *len + strlen(buffer) + 1);
712 strcpy(strings + *len, buffer);
713 *len += strlen(buffer) + 1;
714 }
715 return strings;
716 }
718 char *canonicalize(struct connection *conn, const char *node)
719 {
720 const char *prefix;
722 if (!node || strstarts(node, "/"))
723 return (char *)node;
724 prefix = get_implicit_path(conn);
725 if (prefix)
726 return talloc_asprintf(node, "%s/%s", prefix, node);
727 return (char *)node;
728 }
730 bool check_event_node(const char *node)
731 {
732 if (!node || !strstarts(node, "@")) {
733 errno = EINVAL;
734 return false;
735 }
736 return true;
737 }
739 static void send_directory(struct connection *conn, const char *name)
740 {
741 struct node *node;
743 name = canonicalize(conn, name);
744 node = get_node(conn, name, XS_PERM_READ);
745 if (!node) {
746 send_error(conn, errno);
747 return;
748 }
750 send_reply(conn, XS_DIRECTORY, node->children, node->childlen);
751 }
753 static void do_read(struct connection *conn, const char *name)
754 {
755 struct node *node;
757 name = canonicalize(conn, name);
758 node = get_node(conn, name, XS_PERM_READ);
759 if (!node) {
760 send_error(conn, errno);
761 return;
762 }
764 send_reply(conn, XS_READ, node->data, node->datalen);
765 }
767 static void delete_node_single(struct connection *conn, struct node *node)
768 {
769 TDB_DATA key;
771 key.dptr = (void *)node->name;
772 key.dsize = strlen(node->name);
774 if (tdb_delete(tdb_context(conn), key) != 0)
775 corrupt(conn, "Could not delete '%s'", node->name);
776 }
778 /* Must not be / */
779 static char *basename(const char *name)
780 {
781 return strrchr(name, '/') + 1;
782 }
784 static struct node *construct_node(struct connection *conn, const char *name)
785 {
786 const char *base;
787 unsigned int baselen;
788 struct node *parent, *node;
789 char *children, *parentname = get_parent(name);
791 /* If parent doesn't exist, create it. */
792 parent = read_node(conn, parentname);
793 if (!parent)
794 parent = construct_node(conn, parentname);
795 if (!parent)
796 return NULL;
798 /* Add child to parent. */
799 base = basename(name);
800 baselen = strlen(base) + 1;
801 children = talloc_array(name, char, parent->childlen + baselen);
802 memcpy(children, parent->children, parent->childlen);
803 memcpy(children + parent->childlen, base, baselen);
804 parent->children = children;
805 parent->childlen += baselen;
807 /* Allocate node */
808 node = talloc(name, struct node);
809 node->tdb = tdb_context(conn);
810 node->name = talloc_strdup(node, name);
812 /* Inherit permissions, except domains own what they create */
813 node->num_perms = parent->num_perms;
814 node->perms = talloc_memdup(node, parent->perms,
815 node->num_perms * sizeof(node->perms[0]));
816 if (conn && conn->id)
817 node->perms[0].id = conn->id;
819 /* No children, no data */
820 node->children = node->data = NULL;
821 node->childlen = node->datalen = 0;
822 node->parent = parent;
823 return node;
824 }
826 static int destroy_node(void *_node)
827 {
828 struct node *node = _node;
829 TDB_DATA key;
831 if (streq(node->name, "/"))
832 corrupt(NULL, "Destroying root node!");
834 key.dptr = (void *)node->name;
835 key.dsize = strlen(node->name);
837 tdb_delete(node->tdb, key);
838 return 0;
839 }
841 /* Be careful: create heirarchy, put entry in existing parent *last*.
842 * This helps fsck if we die during this. */
843 static struct node *create_node(struct connection *conn,
844 const char *name,
845 void *data, unsigned int datalen)
846 {
847 struct node *node, *i;
849 node = construct_node(conn, name);
850 if (!node)
851 return NULL;
853 node->data = data;
854 node->datalen = datalen;
856 /* We write out the nodes down, setting destructor in case
857 * something goes wrong. */
858 for (i = node; i; i = i->parent) {
859 if (!write_node(conn, i))
860 return NULL;
861 talloc_set_destructor(i, destroy_node);
862 }
864 /* OK, now remove destructors so they stay around */
865 for (i = node; i; i = i->parent)
866 talloc_set_destructor(i, NULL);
867 return node;
868 }
870 /* path, data... */
871 static void do_write(struct connection *conn, struct buffered_data *in)
872 {
873 unsigned int offset, datalen;
874 struct node *node;
875 char *vec[1] = { NULL }; /* gcc4 + -W + -Werror fucks code. */
876 char *name;
878 /* Extra "strings" can be created by binary data. */
879 if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec)) {
880 send_error(conn, EINVAL);
881 return;
882 }
884 offset = strlen(vec[0]) + 1;
885 datalen = in->used - offset;
887 name = canonicalize(conn, vec[0]);
888 node = get_node(conn, name, XS_PERM_WRITE);
889 if (!node) {
890 /* No permissions, invalid input? */
891 if (errno != ENOENT) {
892 send_error(conn, errno);
893 return;
894 }
895 node = create_node(conn, name, in->buffer + offset, datalen);
896 if (!node) {
897 send_error(conn, errno);
898 return;
899 }
900 } else {
901 node->data = in->buffer + offset;
902 node->datalen = datalen;
903 if (!write_node(conn, node)){
904 send_error(conn, errno);
905 return;
906 }
907 }
909 add_change_node(conn->transaction, name, false);
910 fire_watches(conn, name, false);
911 send_ack(conn, XS_WRITE);
912 }
914 static void do_mkdir(struct connection *conn, const char *name)
915 {
916 struct node *node;
918 name = canonicalize(conn, name);
919 node = get_node(conn, name, XS_PERM_WRITE);
921 /* If it already exists, fine. */
922 if (!node) {
923 /* No permissions? */
924 if (errno != ENOENT) {
925 send_error(conn, errno);
926 return;
927 }
928 node = create_node(conn, name, NULL, 0);
929 if (!node) {
930 send_error(conn, errno);
931 return;
932 }
933 add_change_node(conn->transaction, name, false);
934 fire_watches(conn, name, false);
935 }
936 send_ack(conn, XS_MKDIR);
937 }
939 static void delete_node(struct connection *conn, struct node *node)
940 {
941 unsigned int i;
943 /* Delete self, then delete children. If something goes wrong,
944 * consistency check will clean up this way. */
945 delete_node_single(conn, node);
947 /* Delete children, too. */
948 for (i = 0; i < node->childlen; i += strlen(node->children+i) + 1) {
949 struct node *child;
951 child = read_node(conn,
952 talloc_asprintf(node, "%s/%s", node->name,
953 node->children + i));
954 if (!child)
955 corrupt(conn, "No child '%s' found", child);
956 delete_node(conn, child);
957 }
958 }
960 /* Delete memory using memmove. */
961 static void memdel(void *mem, unsigned off, unsigned len, unsigned total)
962 {
963 memmove(mem + off, mem + off + len, total - off - len);
964 }
966 static bool delete_child(struct connection *conn,
967 struct node *node, const char *childname)
968 {
969 unsigned int i;
971 for (i = 0; i < node->childlen; i += strlen(node->children+i) + 1) {
972 if (streq(node->children+i, childname)) {
973 memdel(node->children, i, strlen(childname) + 1,
974 node->childlen);
975 node->childlen -= strlen(childname) + 1;
976 return write_node(conn, node);
977 }
978 }
979 corrupt(conn, "Can't find child '%s' in %s", childname, node->name);
980 }
983 static int _rm(struct connection *conn, struct node *node, const char *name)
984 {
985 /* Delete from parent first, then if something explodes fsck cleans. */
986 struct node *parent = read_node(conn, get_parent(name));
987 if (!parent) {
988 send_error(conn, EINVAL);
989 return 0;
990 }
992 if (!delete_child(conn, parent, basename(name))) {
993 send_error(conn, EINVAL);
994 return 0;
995 }
997 delete_node(conn, node);
998 return 1;
999 }
1002 static void internal_rm(const char *name)
1004 char *tname = talloc_strdup(talloc_autofree_context(), name);
1005 struct node *node = read_node(NULL, tname);
1006 if (node)
1007 _rm(NULL, node, tname);
1011 static void do_rm(struct connection *conn, const char *name)
1013 struct node *node;
1015 name = canonicalize(conn, name);
1016 node = get_node(conn, name, XS_PERM_WRITE);
1017 if (!node) {
1018 /* Didn't exist already? Fine, if parent exists. */
1019 if (errno == ENOENT) {
1020 node = read_node(conn, get_parent(name));
1021 if (node) {
1022 send_ack(conn, XS_RM);
1023 return;
1025 /* Restore errno, just in case. */
1026 errno = ENOENT;
1028 send_error(conn, errno);
1029 return;
1032 if (streq(name, "/")) {
1033 send_error(conn, EINVAL);
1034 return;
1037 if (_rm(conn, node, name)) {
1038 add_change_node(conn->transaction, name, true);
1039 fire_watches(conn, name, true);
1040 send_ack(conn, XS_RM);
1045 static void do_get_perms(struct connection *conn, const char *name)
1047 struct node *node;
1048 char *strings;
1049 unsigned int len;
1051 name = canonicalize(conn, name);
1052 node = get_node(conn, name, XS_PERM_READ);
1053 if (!node) {
1054 send_error(conn, errno);
1055 return;
1058 strings = perms_to_strings(node, node->perms, node->num_perms, &len);
1059 if (!strings)
1060 send_error(conn, errno);
1061 else
1062 send_reply(conn, XS_GET_PERMS, strings, len);
1065 static void do_set_perms(struct connection *conn, struct buffered_data *in)
1067 unsigned int num;
1068 char *name, *permstr;
1069 struct node *node;
1071 num = xs_count_strings(in->buffer, in->used);
1072 if (num < 2) {
1073 send_error(conn, EINVAL);
1074 return;
1077 /* First arg is node name. */
1078 name = canonicalize(conn, in->buffer);
1079 permstr = in->buffer + strlen(in->buffer) + 1;
1080 num--;
1082 /* We must own node to do this (tools can do this too). */
1083 node = get_node(conn, name, XS_PERM_WRITE|XS_PERM_OWNER);
1084 if (!node) {
1085 send_error(conn, errno);
1086 return;
1089 node->perms = talloc_array(node, struct xs_permissions, num);
1090 node->num_perms = num;
1091 if (!xs_strings_to_perms(node->perms, num, permstr)) {
1092 send_error(conn, errno);
1093 return;
1095 if (!write_node(conn, node)) {
1096 send_error(conn, errno);
1097 return;
1100 add_change_node(conn->transaction, name, false);
1101 fire_watches(conn, name, false);
1102 send_ack(conn, XS_SET_PERMS);
1105 /* Process "in" for conn: "in" will vanish after this conversation, so
1106 * we can talloc off it for temporary variables. May free "conn".
1107 */
1108 static void process_message(struct connection *conn, struct buffered_data *in)
1110 struct transaction *trans;
1112 trans = transaction_lookup(conn, in->hdr.msg.tx_id);
1113 if (IS_ERR(trans)) {
1114 send_error(conn, -PTR_ERR(trans));
1115 return;
1118 assert(conn->transaction == NULL);
1119 conn->transaction = trans;
1121 switch (in->hdr.msg.type) {
1122 case XS_DIRECTORY:
1123 send_directory(conn, onearg(in));
1124 break;
1126 case XS_READ:
1127 do_read(conn, onearg(in));
1128 break;
1130 case XS_WRITE:
1131 do_write(conn, in);
1132 break;
1134 case XS_MKDIR:
1135 do_mkdir(conn, onearg(in));
1136 break;
1138 case XS_RM:
1139 do_rm(conn, onearg(in));
1140 break;
1142 case XS_GET_PERMS:
1143 do_get_perms(conn, onearg(in));
1144 break;
1146 case XS_SET_PERMS:
1147 do_set_perms(conn, in);
1148 break;
1150 case XS_DEBUG:
1151 if (streq(in->buffer, "print"))
1152 xprintf("debug: %s", in->buffer + get_string(in, 0));
1153 #ifdef TESTING
1154 /* For testing, we allow them to set id. */
1155 if (streq(in->buffer, "setid")) {
1156 conn->id = atoi(in->buffer + get_string(in, 0));
1157 send_ack(conn, XS_DEBUG);
1158 } else if (streq(in->buffer, "failtest")) {
1159 if (get_string(in, 0) < in->used)
1160 srandom(atoi(in->buffer + get_string(in, 0)));
1161 send_ack(conn, XS_DEBUG);
1162 failtest = true;
1164 #endif /* TESTING */
1165 break;
1167 case XS_WATCH:
1168 do_watch(conn, in);
1169 break;
1171 case XS_UNWATCH:
1172 do_unwatch(conn, in);
1173 break;
1175 case XS_TRANSACTION_START:
1176 do_transaction_start(conn, in);
1177 break;
1179 case XS_TRANSACTION_END:
1180 do_transaction_end(conn, onearg(in));
1181 break;
1183 case XS_INTRODUCE:
1184 do_introduce(conn, in);
1185 break;
1187 case XS_IS_DOMAIN_INTRODUCED:
1188 do_is_domain_introduced(conn, onearg(in));
1189 break;
1191 case XS_RELEASE:
1192 do_release(conn, onearg(in));
1193 break;
1195 case XS_GET_DOMAIN_PATH:
1196 do_get_domain_path(conn, onearg(in));
1197 break;
1199 default:
1200 eprintf("Client unknown operation %i", in->hdr.msg.type);
1201 send_error(conn, ENOSYS);
1202 break;
1205 conn->transaction = NULL;
1208 static int out_of_mem(void *data)
1210 longjmp(*(jmp_buf *)data, 1);
1213 static void consider_message(struct connection *conn)
1215 jmp_buf talloc_fail;
1217 if (verbose)
1218 xprintf("Got message %s len %i from %p\n",
1219 sockmsg_string(conn->in->hdr.msg.type),
1220 conn->in->hdr.msg.len, conn);
1222 /* For simplicity, we kill the connection on OOM. */
1223 talloc_set_fail_handler(out_of_mem, &talloc_fail);
1224 if (setjmp(talloc_fail)) {
1225 talloc_free(conn);
1226 goto end;
1229 process_message(conn, conn->in);
1231 talloc_free(conn->in);
1232 conn->in = new_buffer(conn);
1234 end:
1235 talloc_set_fail_handler(NULL, NULL);
1236 if (talloc_total_blocks(NULL)
1237 != talloc_total_blocks(talloc_autofree_context()) + 1) {
1238 talloc_report_full(NULL, stderr);
1239 abort();
1243 /* Errors in reading or allocating here mean we get out of sync, so we
1244 * drop the whole client connection. */
1245 static void handle_input(struct connection *conn)
1247 int bytes;
1248 struct buffered_data *in = conn->in;
1250 /* Not finished header yet? */
1251 if (in->inhdr) {
1252 bytes = conn->read(conn, in->hdr.raw + in->used,
1253 sizeof(in->hdr) - in->used);
1254 if (bytes <= 0)
1255 goto bad_client;
1256 in->used += bytes;
1257 if (in->used != sizeof(in->hdr))
1258 return;
1260 if (in->hdr.msg.len > PATH_MAX) {
1261 #ifndef TESTING
1262 syslog(LOG_DAEMON, "Client tried to feed us %i",
1263 in->hdr.msg.len);
1264 #endif
1265 goto bad_client;
1268 in->buffer = talloc_array(in, char, in->hdr.msg.len);
1269 if (!in->buffer)
1270 goto bad_client;
1271 in->used = 0;
1272 in->inhdr = false;
1273 return;
1276 bytes = conn->read(conn, in->buffer + in->used,
1277 in->hdr.msg.len - in->used);
1278 if (bytes < 0)
1279 goto bad_client;
1281 in->used += bytes;
1282 if (in->used != in->hdr.msg.len)
1283 return;
1285 trace_io(conn, "IN ", in);
1286 consider_message(conn);
1287 return;
1289 bad_client:
1290 /* Kill it. */
1291 talloc_free(conn);
1294 static void handle_output(struct connection *conn)
1296 if (!write_messages(conn))
1297 talloc_free(conn);
1300 struct connection *new_connection(connwritefn_t *write, connreadfn_t *read)
1302 struct connection *new;
1304 new = talloc_zero(talloc_autofree_context(), struct connection);
1305 if (!new)
1306 return NULL;
1308 new->fd = -1;
1309 new->write = write;
1310 new->read = read;
1311 new->can_write = true;
1312 INIT_LIST_HEAD(&new->out_list);
1313 INIT_LIST_HEAD(&new->watches);
1314 INIT_LIST_HEAD(&new->transaction_list);
1316 new->in = new_buffer(new);
1317 if (new->in == NULL) {
1318 talloc_free(new);
1319 return NULL;
1322 list_add_tail(&new->list, &connections);
1323 talloc_set_destructor(new, destroy_conn);
1324 trace_create(new, "connection");
1325 return new;
1328 static int writefd(struct connection *conn, const void *data, unsigned int len)
1330 return write(conn->fd, data, len);
1333 static int readfd(struct connection *conn, void *data, unsigned int len)
1335 return read(conn->fd, data, len);
1338 static void accept_connection(int sock, bool canwrite)
1340 int fd;
1341 struct connection *conn;
1343 fd = accept(sock, NULL, NULL);
1344 if (fd < 0)
1345 return;
1347 conn = new_connection(writefd, readfd);
1348 if (conn) {
1349 conn->fd = fd;
1350 conn->can_write = canwrite;
1351 } else
1352 close(fd);
1355 #ifdef TESTING
1356 /* Valgrind can check our writes better if we don't use mmap */
1357 #define TDB_FLAGS TDB_NOMMAP
1358 /* Useful for running under debugger. */
1359 void dump_connection(void)
1361 struct connection *i;
1363 list_for_each_entry(i, &connections, list) {
1364 printf("Connection %p:\n", i);
1365 printf(" state = %s\n",
1366 list_empty(&i->out_list) ? "OK" : "BUSY");
1367 if (i->id)
1368 printf(" id = %i\n", i->id);
1369 if (!i->in->inhdr || i->in->used)
1370 printf(" got %i bytes of %s\n",
1371 i->in->used, i->in->inhdr ? "header" : "data");
1372 #if 0
1373 if (i->out)
1374 printf(" sending message %s (%s) out\n",
1375 sockmsg_string(i->out->hdr.msg.type),
1376 i->out->buffer);
1377 if (i->transaction)
1378 dump_transaction(i);
1379 if (i->domain)
1380 dump_domain(i);
1381 #endif
1382 dump_watches(i);
1385 #else
1386 #define TDB_FLAGS 0
1387 #endif
1389 /* We create initial nodes manually. */
1390 static void manual_node(const char *name, const char *child)
1392 struct node *node;
1393 struct xs_permissions perms = { .id = 0, .perms = XS_PERM_NONE };
1395 node = talloc(NULL, struct node);
1396 node->name = name;
1397 node->perms = &perms;
1398 node->num_perms = 1;
1399 node->data = NULL;
1400 node->datalen = 0;
1401 node->children = (char *)child;
1402 if (child)
1403 node->childlen = strlen(child) + 1;
1404 else
1405 node->childlen = 0;
1407 if (!write_node(NULL, node))
1408 barf_perror("Could not create initial node %s", name);
1409 talloc_free(node);
1412 static void setup_structure(void)
1414 char *tdbname;
1415 tdbname = talloc_strdup(talloc_autofree_context(), xs_daemon_tdb());
1416 tdb_ctx = tdb_open(tdbname, 0, TDB_FLAGS, O_RDWR, 0);
1418 if (tdb_ctx) {
1419 /* XXX When we make xenstored able to restart, this will have
1420 to become cleverer, checking for existing domains and not
1421 removing the corresponding entries, but for now xenstored
1422 cannot be restarted without losing all the registered
1423 watches, which breaks all the backend drivers anyway. We
1424 can therefore get away with just clearing /local and
1425 expecting Xend to put the appropriate entries back in.
1427 When this change is made it is important to note that
1428 dom0's entries must be cleaned up on reboot _before_ this
1429 daemon starts, otherwise the backend drivers and dom0's
1430 balloon driver will pick up stale entries. In the case of
1431 the balloon driver, this can be fatal.
1432 */
1433 char *tlocal = talloc_strdup(talloc_autofree_context(),
1434 "/local");
1435 internal_rm("/local");
1436 create_node(NULL, tlocal, NULL, 0);
1438 else {
1439 tdb_ctx = tdb_open(tdbname, 7919, TDB_FLAGS, O_RDWR|O_CREAT,
1440 0640);
1441 if (!tdb_ctx)
1442 barf_perror("Could not create tdb file %s", tdbname);
1444 manual_node("/", "tool");
1445 manual_node("/tool", "xenstored");
1446 manual_node("/tool/xenstored", NULL);
1449 /* FIXME: Fsck */
1452 static void write_pidfile(const char *pidfile)
1454 char buf[100];
1455 int len;
1456 int fd;
1458 fd = open(pidfile, O_RDWR | O_CREAT, 0600);
1459 if (fd == -1)
1460 barf_perror("Opening pid file %s", pidfile);
1462 /* We exit silently if daemon already running. */
1463 if (lockf(fd, F_TLOCK, 0) == -1)
1464 exit(0);
1466 len = sprintf(buf, "%d\n", getpid());
1467 write(fd, buf, len);
1470 /* Stevens. */
1471 static void daemonize(void)
1473 pid_t pid;
1475 /* Separate from our parent via fork, so init inherits us. */
1476 if ((pid = fork()) < 0)
1477 barf_perror("Failed to fork daemon");
1478 if (pid != 0)
1479 exit(0);
1481 /* Session leader so ^C doesn't whack us. */
1482 setsid();
1484 /* Let session leader exit so child cannot regain CTTY */
1485 if ((pid = fork()) < 0)
1486 barf_perror("Failed to fork daemon");
1487 if (pid != 0)
1488 exit(0);
1490 #ifndef TESTING /* Relative paths for socket names */
1491 /* Move off any mount points we might be in. */
1492 chdir("/");
1493 #endif
1494 /* Discard our parent's old-fashioned umask prejudices. */
1495 umask(0);
1499 static void usage(void)
1501 fprintf(stderr,
1502 "Usage:\n"
1503 "\n"
1504 " xenstored <options>\n"
1505 "\n"
1506 "where options may include:\n"
1507 "\n"
1508 " --no-domain-init to state that xenstored should not initialise dom0,\n"
1509 " --pid-file <file> giving a file for the daemon's pid to be written,\n"
1510 " --help to output this message,\n"
1511 " --no-fork to request that the daemon does not fork,\n"
1512 " --output-pid to request that the pid of the daemon is output,\n"
1513 " --trace-file <file> giving the file for logging, and\n"
1514 " --verbose to request verbose execution.\n");
1518 static struct option options[] = {
1519 { "no-domain-init", 0, NULL, 'D' },
1520 { "pid-file", 1, NULL, 'F' },
1521 { "help", 0, NULL, 'H' },
1522 { "no-fork", 0, NULL, 'N' },
1523 { "output-pid", 0, NULL, 'P' },
1524 { "trace-file", 1, NULL, 'T' },
1525 { "verbose", 0, NULL, 'V' },
1526 { NULL, 0, NULL, 0 } };
1528 extern void dump_conn(struct connection *conn);
1530 int main(int argc, char *argv[])
1532 int opt, *sock, *ro_sock, max;
1533 struct sockaddr_un addr;
1534 fd_set inset, outset;
1535 bool dofork = true;
1536 bool outputpid = false;
1537 bool no_domain_init = false;
1538 const char *pidfile = NULL;
1540 while ((opt = getopt_long(argc, argv, "DF:HNPT:V", options,
1541 NULL)) != -1) {
1542 switch (opt) {
1543 case 'D':
1544 no_domain_init = true;
1545 break;
1546 case 'F':
1547 pidfile = optarg;
1548 break;
1549 case 'H':
1550 usage();
1551 return 0;
1552 case 'N':
1553 dofork = false;
1554 break;
1555 case 'P':
1556 outputpid = true;
1557 break;
1558 case 'T':
1559 tracefile = optarg;
1560 break;
1561 case 'V':
1562 verbose = true;
1563 break;
1566 if (optind != argc)
1567 barf("%s: No arguments desired", argv[0]);
1569 reopen_log();
1571 if (dofork) {
1572 openlog("xenstored", 0, LOG_DAEMON);
1573 daemonize();
1575 if (pidfile)
1576 write_pidfile(pidfile);
1578 talloc_enable_leak_report_full();
1580 /* Create sockets for them to listen to. */
1581 sock = talloc(talloc_autofree_context(), int);
1582 *sock = socket(PF_UNIX, SOCK_STREAM, 0);
1583 if (*sock < 0)
1584 barf_perror("Could not create socket");
1585 ro_sock = talloc(talloc_autofree_context(), int);
1586 *ro_sock = socket(PF_UNIX, SOCK_STREAM, 0);
1587 if (*ro_sock < 0)
1588 barf_perror("Could not create socket");
1589 talloc_set_destructor(sock, destroy_fd);
1590 talloc_set_destructor(ro_sock, destroy_fd);
1592 /* Don't kill us with SIGPIPE. */
1593 signal(SIGPIPE, SIG_IGN);
1595 /* FIXME: Be more sophisticated, don't mug running daemon. */
1596 unlink(xs_daemon_socket());
1597 unlink(xs_daemon_socket_ro());
1599 addr.sun_family = AF_UNIX;
1600 strcpy(addr.sun_path, xs_daemon_socket());
1601 if (bind(*sock, (struct sockaddr *)&addr, sizeof(addr)) != 0)
1602 barf_perror("Could not bind socket to %s", xs_daemon_socket());
1603 strcpy(addr.sun_path, xs_daemon_socket_ro());
1604 if (bind(*ro_sock, (struct sockaddr *)&addr, sizeof(addr)) != 0)
1605 barf_perror("Could not bind socket to %s",
1606 xs_daemon_socket_ro());
1607 if (chmod(xs_daemon_socket(), 0600) != 0
1608 || chmod(xs_daemon_socket_ro(), 0660) != 0)
1609 barf_perror("Could not chmod sockets");
1611 if (listen(*sock, 1) != 0
1612 || listen(*ro_sock, 1) != 0)
1613 barf_perror("Could not listen on sockets");
1615 if (pipe(reopen_log_pipe)) {
1616 barf_perror("pipe");
1619 /* Setup the database */
1620 setup_structure();
1622 /* Listen to hypervisor. */
1623 if (!no_domain_init)
1624 domain_init();
1626 /* Restore existing connections. */
1627 restore_existing_connections();
1629 if (outputpid) {
1630 printf("%i\n", getpid());
1631 fflush(stdout);
1634 /* close stdin/stdout now we're ready to accept connections */
1635 if (dofork) {
1636 close(STDIN_FILENO);
1637 close(STDOUT_FILENO);
1638 close(STDERR_FILENO);
1641 signal(SIGHUP, trigger_reopen_log);
1643 #ifdef TESTING
1644 signal(SIGUSR1, stop_failtest);
1645 #endif
1647 /* Get ready to listen to the tools. */
1648 max = initialize_set(&inset, &outset, *sock, *ro_sock);
1650 /* Main loop. */
1651 /* FIXME: Rewrite so noone can starve. */
1652 for (;;) {
1653 struct connection *i;
1655 if (select(max+1, &inset, &outset, NULL, NULL) < 0) {
1656 if (errno == EINTR)
1657 continue;
1658 barf_perror("Select failed");
1661 if (FD_ISSET(reopen_log_pipe[0], &inset)) {
1662 char c;
1663 read(reopen_log_pipe[0], &c, 1);
1664 reopen_log();
1667 if (FD_ISSET(*sock, &inset))
1668 accept_connection(*sock, true);
1670 if (FD_ISSET(*ro_sock, &inset))
1671 accept_connection(*ro_sock, false);
1673 if (FD_ISSET(eventchn_fd, &inset))
1674 handle_event();
1676 list_for_each_entry(i, &connections, list) {
1677 if (i->domain)
1678 continue;
1680 /* Operations can delete themselves or others
1681 * (xs_release): list is not safe after input,
1682 * so break. */
1683 if (FD_ISSET(i->fd, &inset)) {
1684 handle_input(i);
1685 break;
1687 if (FD_ISSET(i->fd, &outset)) {
1688 handle_output(i);
1689 break;
1693 /* Handle all possible I/O for domain connections. */
1694 more:
1695 list_for_each_entry(i, &connections, list) {
1696 if (!i->domain)
1697 continue;
1699 if (domain_can_read(i)) {
1700 handle_input(i);
1701 goto more;
1704 if (domain_can_write(i) && !list_empty(&i->out_list)) {
1705 handle_output(i);
1706 goto more;
1710 max = initialize_set(&inset, &outset, *sock, *ro_sock);
1714 /*
1715 * Local variables:
1716 * c-file-style: "linux"
1717 * indent-tabs-mode: t
1718 * c-indent-level: 8
1719 * c-basic-offset: 8
1720 * tab-width: 8
1721 * End:
1722 */