* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
+#include <string.h>
#include <libgen.h>
#include <unistd.h>
+#include <regex.h>
#include <sys/types.h>
#include <lxc/lxc.h>
void usage(char *cmd)
{
fprintf(stderr, "%s <command>\n", basename(cmd));
- fprintf(stderr, "\t -n <name> : name of the container\n");
+ fprintf(stderr, "\t -n <name> : 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) {
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;
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;
}
#include <sys/param.h>
#include <sys/inotify.h>
#include <sys/socket.h>
-#include <sys/un.h>
#include <netinet/in.h>
#include <net/if.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
#include <lxc/lxc.h>
#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];
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));
{
struct lxc_msg msg = { .type = lxc_msg_state,
.value = state };
- lxc_monitor_send(name, &msg);
-}
+ strncpy(msg.name, name, sizeof(msg.name));
-void lxc_monitor_cleanup(const char *name)
-{
- char path[UNIX_PATH_MAX];
- snprintf(path, UNIX_PATH_MAX, LXCPATH "/%s/notification", name);
- unlink(path);
+ lxc_monitor_send(&msg);
}
-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;
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;
}
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;