23 #include <sys/types.h>
25 #include <sys/socket.h>
27 #if !defined(UNIX_PATH_MAX)
28 #define UNIX_PATH_MAX (size_t)sizeof(((struct sockaddr_un *) 0)->sun_path)
49 static int nodaemon = 0;
50 static GHashTable *clients = NULL;
54 #ifdef XENCTRL_HAS_XC_INTERFACE
56 static xc_interface *xce_handle = NULL;
57 #define XC_IF_INVALID (NULL)
60 static int xce_handle = -1;
61 #define XC_IF_INVALID (-1)
64 #if !defined(XC_EVTCHN_PORT_T)
65 #error "XC_EVTCHN_PORT_T undefined!"
67 static XC_EVTCHN_PORT_T dbg_port = -1;
80 g_hash_table_iter_init(&iter,clients);
81 while (g_hash_table_iter_next(&iter,&kp,&vp)) {
82 close((
int)(uintptr_t)kp);
85 g_hash_table_destroy(clients);
102 if (signo == SIGHUP || signo == SIGINT || SIGQUIT)
108 int main(
int argc,
char **argv) {
111 struct sockaddr_un sun,sun_client;
113 fd_set rfds,wfds,efds;
123 while ((opt = getopt(argc,argv,
"hd::w::l:p:")) > -1) {
148 verror(
"Usage: %s [-h] [-d [<level>]] [-w [<level>]]"
149 " [-l logflag1,logflag2,...]\n",argv[0]);
156 verror(
"daemon(): %s\n",strerror(errno));
163 signal(SIGQUIT,
sigh);
164 signal(SIGABRT,
sigh);
165 signal(SIGSEGV,
sigh);
168 signal(SIGALRM,SIG_IGN);
169 signal(SIGUSR1,SIG_IGN);
170 signal(SIGUSR2,SIG_IGN);
172 clients = g_hash_table_new_full(g_direct_hash,g_direct_equal,NULL,NULL);
178 if (stat(
"/var/run",&sbuf) == 0
179 && S_ISDIR(sbuf.st_mode) && access(
"/var/run",W_OK) == 0)
181 else if ((
path = getenv(
"TMPDIR"))
182 && stat(
path,&sbuf) == 0 && access(
path,W_OK) == 0) {
186 else if (stat(
"/tmp",&sbuf) == 0
187 && S_ISDIR(sbuf.st_mode) && access(
"/tmp",W_OK) == 0)
193 memset(&sun,0,
sizeof(sun));
194 sun.sun_family = AF_UNIX;
197 sfd = socket(AF_UNIX,SOCK_STREAM,0);
199 verror(
"socket(): %s\n",strerror(errno));
202 len = offsetof(
struct sockaddr_un,sun_path) + strlen(sun.sun_path);
203 if (bind(sfd,&sun,len) < 0) {
204 verror(
"bind(): %s\n",strerror(errno));
207 if (fchmod(sfd,S_IRUSR | S_IWUSR) < 0) {
208 verror(
"chmod(%s): %s\n",sun.sun_path,strerror(errno));
212 verror(
"listen(): %s\n",strerror(errno));
217 verror(
"could not attach to XC interfaces!\n");
222 verror(
"could not attach to VIRQ_DEBUGGER evtchn!\n");
226 xce_fd = xc_evtchn_fd(xce_handle);
249 g_hash_table_iter_init(&iter,clients);
250 while (g_hash_table_iter_next(&iter,&kp,&vp)) {
251 fd = (int)(uintptr_t)kp;
260 rc = select(max_fd + 1,&rfds,&wfds,&efds,NULL);
265 verror(
"select(): %s, exiting!\n",strerror(errno));
276 g_hash_table_iter_init(&iter,clients);
277 while (g_hash_table_iter_next(&iter,&kp,&vp)) {
278 fd = (int)(uintptr_t)kp;
279 if (FD_ISSET(fd,&rfds) || FD_ISSET(fd,&efds)) {
280 rc = read(fd,&req,
sizeof(req));
284 "Removing client %d (closed connection)\n",fd);
286 g_hash_table_iter_remove(&iter);
294 "Removing client %d (read error: %s)\n",
297 g_hash_table_iter_remove(&iter);
300 else if (rc !=
sizeof(req)) {
303 "Removing client %d (bad request length: %d)\n",fd,rc);
305 g_hash_table_iter_remove(&iter);
316 if (FD_ISSET(sfd,&rfds)) {
317 clen =
sizeof(sun_client);
318 fd = accept(sfd,&sun_client,&clen);
320 clen -= offsetof(
struct sockaddr_un,sun_path);
322 vwarn(
"bad sockaddr_un.sun_path length from accept()!\n");
326 if (clen < offsetof(
struct sockaddr_un,sun_path)
327 || clen >=
sizeof(sun_client.sun_path)) {
328 vwarn(
"ignoring new client with unbound unix socket!\n");
332 sun_client.sun_path[clen] =
'\0';
333 stat(sun_client.sun_path,&sbuf);
335 "accepting new client %d (pid %d, uid %d, path %s)\n",
336 fd,sbuf.st_rdev,sbuf.st_uid,sun_client.sun_path);
337 g_hash_table_insert(clients,(
void *)(uintptr_t)fd,NULL);
339 flags = fcntl(fd,F_GETFL);
340 fcntl(fd,F_SETFL,flags | O_NONBLOCK);
344 verror(
"accept(): %s, ignoring\n",strerror(errno));
354 if (FD_ISSET(
xce_fd,&rfds)) {
356 port = xc_evtchn_pending(xce_handle);
359 if (xc_evtchn_unmask(xce_handle,port) == -1) {
360 vwarn(
"failed to unmask event channel\n");
363 if (port != dbg_port)
366 g_hash_table_iter_init(&iter,clients);
367 while (g_hash_table_iter_next(&iter,&kp,&vp)) {
368 fd = (int)(uintptr_t)kp;
372 vwarn(
"Removing client %d (write error: %s)\n",
375 g_hash_table_iter_remove(&iter);
379 rc = write(fd,&resp,
sizeof(resp));
382 if (errno == EINTR) {
388 "Removing client %d (write error: %s)\n",
391 g_hash_table_iter_remove(&iter);
394 else if (rc !=
sizeof(resp)) {
396 "Removing client %d (incomplete write: %d)\n",
399 g_hash_table_iter_remove(&iter);
403 "Wrote %d bytes to client %d\n",rc,fd);
#define TARGET_XV_VMP_SOCKET_FILENAME
int xen_vm_virq_attach(int xce_handle, XC_EVTCHN_PORT_T *dbg_port)
void vmi_inc_log_level(void)
#define verror(format,...)
void vmi_set_log_level(int level)
#define vwarn(format,...)
int main(int argc, char **argv)
int vmi_set_log_area_flaglist(char *flaglist, char *separator)
void vmi_set_warn_level(int level)
void vmi_inc_warn_level(void)
#define vdebug(devel, areas, flags, format,...)
int unlink(const char *pathname)
int xen_vm_virq_detach(int xce_handle, XC_EVTCHN_PORT_T *dbg_port)
int xen_vm_xc_detach(int *xc_handle, int *xce_handle)
void * malloc(size_t size)
int xen_vm_xc_attach(int *xc_handle, int *xce_handle)