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