diff --git a/src/lxc/destroy.c b/src/lxc/destroy.c index 8311d3d85..e879a9cd5 100644 --- a/src/lxc/destroy.c +++ b/src/lxc/destroy.c @@ -96,8 +96,6 @@ int lxc_destroy(const char *name) snprintf(path, MAXPATHLEN, LXCPATH "/%s/init", name); unlink(path); - lxc_monitor_cleanup(name); - if (lxc_unconfigure(name)) { lxc_log_error("failed to cleanup %s", name); goto out_lock; diff --git a/src/lxc/lxc.h b/src/lxc/lxc.h index efe922176..601dfa202 100644 --- a/src/lxc/lxc.h +++ b/src/lxc/lxc.h @@ -118,10 +118,9 @@ extern int lxc_monitor(const char *name, int output_fd); /* * Open the monitoring mechanism for a specific container * The function will return an fd corresponding to the events - * @name : the name of the container * Returns a file descriptor on success, < 0 otherwise */ -extern int lxc_monitor_open(const char *name); +extern int lxc_monitor_open(); /* * Read the state of the container if this one has changed diff --git a/src/lxc/lxc_monitor.c b/src/lxc/lxc_monitor.c index 85ad25f80..daae48070 100644 --- a/src/lxc/lxc_monitor.c +++ b/src/lxc/lxc_monitor.c @@ -21,8 +21,10 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include #include #include +#include #include #include @@ -30,14 +32,16 @@ void usage(char *cmd) { fprintf(stderr, "%s \n", basename(cmd)); - fprintf(stderr, "\t -n : name of the container\n"); + fprintf(stderr, "\t -n : name of the container or regular expression\n"); _exit(1); } int main(int argc, char *argv[]) { char opt, *name = NULL; + char *regexp; struct lxc_msg msg; + regex_t preg; int fd; while ((opt = getopt(argc, argv, "n:")) != -1) { @@ -51,7 +55,16 @@ int main(int argc, char *argv[]) if (!name) usage(argv[0]); - fd = lxc_monitor_open(name); + regexp = malloc(strlen(name) + 3); + sprintf(regexp, "^%s$", name); + + if (regcomp(&preg, regexp, REG_NOSUB|REG_EXTENDED)) { + fprintf(stderr, "failed to compile the regex '%s'\n", + name); + return 1; + } + + fd = lxc_monitor_open(); if (fd < 0) { fprintf(stderr, "failed to open monitor for '%s'\n", name); return -1; @@ -65,21 +78,22 @@ int main(int argc, char *argv[]) return -1; } + if (regexec(&preg, msg.name, 0, NULL, 0)) + continue; + switch (msg.type) { case lxc_msg_state: printf("'%s' changed state to [%s]\n", - name, lxc_state2str(msg.value)); - break; - case lxc_msg_priority: - printf("'%s' changed priority to [%d]\n", - name, msg.value); + msg.name, lxc_state2str(msg.value)); break; default: - printf("invalid msg format\n"); + /* ignore garbage */ break; } } + regfree(&preg); + return 0; } diff --git a/src/lxc/lxc_wait.c b/src/lxc/lxc_wait.c index f7d49b2b3..b5ea2f3fc 100644 --- a/src/lxc/lxc_wait.c +++ b/src/lxc/lxc_wait.c @@ -82,7 +82,7 @@ int main(int argc, char *argv[]) } - fd = lxc_monitor_open(name); + fd = lxc_monitor_open(); if (fd < 0) { fprintf(stderr, "failed to open monitor for '%s'\n", name); return -1; @@ -96,10 +96,14 @@ int main(int argc, char *argv[]) return -1; } + if (strcmp(name, msg.name)) + continue; + switch (msg.type) { case lxc_msg_state: if (msg.value < 0 || msg.value >= MAX_STATE) { - fprintf(stderr, "Receive an invalid state number '%d'\n", msg.value); + fprintf(stderr, "Receive an invalid state number '%d'\n", + msg.value); return -1; } @@ -107,7 +111,7 @@ int main(int argc, char *argv[]) return 0; break; default: - printf("invalid msg format\n"); + /* just ignore garbage */ break; } } diff --git a/src/lxc/monitor.c b/src/lxc/monitor.c index 8175baba4..ff5e08ba5 100644 --- a/src/lxc/monitor.c +++ b/src/lxc/monitor.c @@ -31,9 +31,10 @@ #include #include #include -#include #include #include +#include +#include #include @@ -41,6 +42,15 @@ #define UNIX_PATH_MAX 108 #endif +#ifndef SOL_NETLINK +#define SOL_NETLINK 270 +#endif + +/* assuming this multicast group is not used by anyone else :/ + * otherwise a new genetlink family should be defined to own + * its multicast groups */ +#define MONITOR_MCGROUP RTNLGRP_MAX + int lxc_monitor(const char *name, int output_fd) { char path[MAXPATHLEN]; @@ -101,21 +111,22 @@ out: return err; } -static void lxc_monitor_send(const char *name, struct lxc_msg *msg) +static void lxc_monitor_send(struct lxc_msg *msg) { int fd; - struct sockaddr_un addr; + struct sockaddr_nl addr; - fd = socket(PF_UNIX, SOCK_DGRAM, 0); + fd = socket(PF_NETLINK, SOCK_RAW, 0); if (fd < 0) { lxc_log_syserror("failed to create notification socket"); return; } memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - snprintf(addr.sun_path, UNIX_PATH_MAX, - LXCPATH "/%s/notification", name); + + addr.nl_family = AF_NETLINK; + addr.nl_pid = 0; + addr.nl_groups = MONITOR_MCGROUP; sendto(fd, msg, sizeof(*msg), 0, (const struct sockaddr *)&addr, sizeof(addr)); @@ -127,22 +138,17 @@ void lxc_monitor_send_state(const char *name, lxc_state_t state) { struct lxc_msg msg = { .type = lxc_msg_state, .value = state }; - lxc_monitor_send(name, &msg); + strncpy(msg.name, name, sizeof(msg.name)); + + lxc_monitor_send(&msg); } -void lxc_monitor_cleanup(const char *name) -{ - char path[UNIX_PATH_MAX]; - snprintf(path, UNIX_PATH_MAX, LXCPATH "/%s/notification", name); - unlink(path); -} - -int lxc_monitor_open(const char *name) +int lxc_monitor_open(void) { int fd; - struct sockaddr_un addr; + struct sockaddr_nl addr; - fd = socket(PF_UNIX, SOCK_DGRAM, 0); + fd = socket(PF_NETLINK, SOCK_RAW, 0); if (fd < 0) { lxc_log_syserror("failed to create notification socket"); return -1; @@ -150,12 +156,13 @@ int lxc_monitor_open(const char *name) memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - snprintf(addr.sun_path, UNIX_PATH_MAX, LXCPATH "/%s/notification", name); - unlink(addr.sun_path); + addr.nl_family = AF_NETLINK; + addr.nl_pid = 0; + addr.nl_groups = MONITOR_MCGROUP; if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr))) { - lxc_log_syserror("failed to bind to '%s'", addr.sun_path); + lxc_log_syserror("failed to bind to multicast group '%d'", + addr.nl_groups); close(fd); return -1; } @@ -165,9 +172,12 @@ int lxc_monitor_open(const char *name) int lxc_monitor_read(int fd, struct lxc_msg *msg) { + struct sockaddr_nl from; + socklen_t len = sizeof(from); int ret; - ret = recv(fd, msg, sizeof(*msg), 0); + ret = recvfrom(fd, msg, sizeof(*msg), 0, + (struct sockaddr *)&from, &len); if (ret < 0) { lxc_log_syserror("failed to received state"); return -1; diff --git a/src/lxc/monitor.h b/src/lxc/monitor.h index 304450e5a..ab08f1060 100644 --- a/src/lxc/monitor.h +++ b/src/lxc/monitor.h @@ -23,6 +23,8 @@ #ifndef __monitor_h #define __monitor_h +#include + typedef enum { lxc_msg_state, lxc_msg_priority, @@ -30,6 +32,7 @@ typedef enum { struct lxc_msg { lxc_msg_type_t type; + char name[MAXPATHLEN]; int value; };