1 /******************************************************************************
2 *
3 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
4 * Use is subject to license terms.
5 *
6 * Copyright (C) 2005 Rusty Russell IBM Corporation
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation, version 2 of the
11 * License.
12 */
13
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <stdlib.h>
17 #include <stdarg.h>
18 #include <sys/mman.h>
19 #include <strings.h>
20 #include <ucred.h>
21 #include <stdio.h>
22
23 #include <xen/sys/xenbus.h>
24
25 #include "talloc.h"
26 #include "xenstored_core.h"
27 #include "xenstored_probes.h"
28
xenbus_evtchn(void)29 evtchn_port_t xenbus_evtchn(void)
30 {
31 int fd;
32 evtchn_port_t port;
33
34 fd = open("/dev/xen/xenbus", O_RDONLY);
35 if (fd == -1)
36 return -1;
37
38 port = ioctl(fd, IOCTL_XENBUS_XENSTORE_EVTCHN);
39
40 close(fd);
41 return port;
42 }
43
xenbus_map(void)44 void *xenbus_map(void)
45 {
46 int fd;
47 void *addr;
48
49 fd = open("/dev/xen/xenbus", O_RDWR);
50 if (fd == -1)
51 return NULL;
52
53 addr = mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE,
54 MAP_SHARED, fd, 0);
55
56 if (addr == MAP_FAILED)
57 addr = NULL;
58
59 close(fd);
60
61 return addr;
62 }
63
xenbus_notify_running(void)64 void xenbus_notify_running(void)
65 {
66 int fd;
67
68 fd = open("/dev/xen/xenbus", O_RDONLY);
69
70 (void) ioctl(fd, IOCTL_XENBUS_NOTIFY_UP);
71
72 close(fd);
73 }
74
cred(const struct connection * conn)75 static pid_t cred(const struct connection *conn)
76 {
77 ucred_t *ucred = NULL;
78 pid_t pid;
79
80 if (conn->domain)
81 return (0);
82
83 if (getpeerucred(conn->fd, &ucred) == -1)
84 return (0);
85
86 pid = ucred_getpid(ucred);
87
88 ucred_free(ucred);
89 return (pid);
90 }
91
92 /*
93 * The strings are often a number of nil-separated strings. We'll just
94 * replace the separators with spaces - not quite right, but good
95 * enough.
96 */
97 static char *
mangle(const struct connection * conn,const struct buffered_data * in)98 mangle(const struct connection *conn, const struct buffered_data *in)
99 {
100 char *str;
101 int i;
102
103 if (in->hdr.msg.len == 0)
104 return (talloc_strdup(conn, ""));
105
106 if ((str = talloc_zero_size(conn, in->hdr.msg.len + 1)) == NULL)
107 return (NULL);
108
109 memcpy(str, in->buffer, in->hdr.msg.len);
110
111 /*
112 * The protocol is absurdly inconsistent in whether the length
113 * includes the terminating nil or not; replace all nils that
114 * aren't the last one.
115 */
116 for (i = 0; i < (in->hdr.msg.len - 1); i++) {
117 if (str[i] == '\0')
118 str[i] = ' ';
119 }
120
121 return (str);
122 }
123
124 void
dtrace_io(const struct connection * conn,const struct buffered_data * in,int io_out)125 dtrace_io(const struct connection *conn, const struct buffered_data *in,
126 int io_out)
127 {
128 if (!io_out) {
129 if (XENSTORE_MSG_ENABLED()) {
130 char *mangled = mangle(conn, in);
131 XENSTORE_MSG(in->hdr.msg.tx_id, conn->id, cred(conn),
132 in->hdr.msg.type, mangled);
133 }
134
135 goto out;
136 }
137
138 switch (in->hdr.msg.type) {
139 case XS_ERROR:
140 if (XENSTORE_ERROR_ENABLED()) {
141 char *mangled = mangle(conn, in);
142 XENSTORE_ERROR(in->hdr.msg.tx_id, conn->id,
143 cred(conn), mangled);
144 }
145 break;
146
147 case XS_WATCH_EVENT:
148 if (XENSTORE_WATCH_EVENT_ENABLED()) {
149 char *mangled = mangle(conn, in);
150 XENSTORE_WATCH_EVENT(conn->id, cred(conn), mangled);
151 }
152 break;
153
154 default:
155 if (XENSTORE_REPLY_ENABLED()) {
156 char *mangled = mangle(conn, in);
157 XENSTORE_REPLY(in->hdr.msg.tx_id, conn->id, cred(conn),
158 in->hdr.msg.type, mangled);
159 }
160 break;
161 }
162
163 out:
164 /*
165 * 6589130 dtrace -G fails for certain tail-calls on x86
166 */
167 asm("nop");
168 }
169