Skip to content

Commit

Permalink
handle hashed command socket names (v2)
Browse files Browse the repository at this point in the history
With the new hashed command socket names (e858984), it's possible to
have something like below;

[caglar@qop:~/go/src/github.com/lxc/go-lxc(master)] cat /proc/net/unix | grep lxc
0000000000000000: 00000002 00000000 00010000 0001 01 53465 @lxc/d086e835c86f4b8d/command
[...]

list_active_containers reads /proc/net/unix to find all running
containers but this new format no longer includes the container name or
its lxcpath.

This patch introduces two new commands (LXC_CMD_GET_NAME and
LXC_CMD_GET_LXCPATH) and starts to use those in list_active_containers
call.

changes since v1:
 - added sanity check proposed by Serge

Signed-off-by: S.Çağlar Onur <caglar@10ur.org>
Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
  • Loading branch information
caglar10ur authored and stgraber committed Sep 20, 2014
1 parent f3116a8 commit b656b42
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 18 deletions.
118 changes: 102 additions & 16 deletions src/lxc/commands.c
Expand Up @@ -75,23 +75,31 @@
lxc_log_define(lxc_commands, lxc);

static int fill_sock_name(char *path, int len, const char *name,
const char *lxcpath)
const char *lxcpath, const char *hashed_sock_name)
{
char *tmppath;
size_t tmplen;
uint64_t hash;
int ret;

if (hashed_sock_name != NULL) {
ret = snprintf(path, len, "lxc/%s/command", hashed_sock_name);
if (ret < 0 || ret >= len) {
ERROR("Error writing to command sock path");
return -1;
}
return 0;
}

if (!lxcpath) {
lxcpath = lxc_global_config_value("lxc.lxcpath");
if (!lxcpath) {
ERROR("Out of memory getting lxcpath");
return -1;
}
}

ret = snprintf(path, len, "%s/%s/command", lxcpath, name);

ret = snprintf(path, len, "%s/%s/command", lxcpath, name);
if (ret < 0) {
ERROR("Error writing to command sock path");
return -1;
Expand All @@ -108,7 +116,7 @@ static int fill_sock_name(char *path, int len, const char *name,
return -1;
}
hash = fnv_64a_buf(tmppath, ret, FNV1A_64_INIT);
ret = snprintf(path, len, "lxc/%016" PRIx64 "/cmd_sock", hash);
ret = snprintf(path, len, "lxc/%016" PRIx64 "/command", hash);
if (ret < 0 || ret >= len) {
ERROR("Command socket name too long");
return -1;
Expand All @@ -127,6 +135,8 @@ static const char *lxc_cmd_str(lxc_cmd_t cmd)
[LXC_CMD_GET_CLONE_FLAGS] = "get_clone_flags",
[LXC_CMD_GET_CGROUP] = "get_cgroup",
[LXC_CMD_GET_CONFIG_ITEM] = "get_config_item",
[LXC_CMD_GET_NAME] = "get_name",
[LXC_CMD_GET_LXCPATH] = "get_lxcpath",
};

if (cmd >= LXC_CMD_MAX)
Expand Down Expand Up @@ -259,7 +269,7 @@ static int lxc_cmd_rsp_send(int fd, struct lxc_cmd_rsp *rsp)
* returned in the cmd response structure.
*/
static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
const char *lxcpath)
const char *lxcpath, const char *hashed_sock_name)
{
int sock, ret = -1;
char path[sizeof(((struct sockaddr_un *)0)->sun_path)] = { 0 };
Expand All @@ -270,7 +280,7 @@ static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
*stopped = 0;

len = sizeof(path)-1;
if (fill_sock_name(offset, len, name, lxcpath))
if (fill_sock_name(offset, len, name, lxcpath, hashed_sock_name))
return -1;

sock = lxc_abstract_unix_connect(path);
Expand Down Expand Up @@ -329,7 +339,7 @@ int lxc_try_cmd(const char *name, const char *lxcpath)
.req = { .cmd = LXC_CMD_GET_INIT_PID },
};

ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);

if (stopped)
return 0;
Expand Down Expand Up @@ -369,7 +379,7 @@ pid_t lxc_cmd_get_init_pid(const char *name, const char *lxcpath)
.req = { .cmd = LXC_CMD_GET_INIT_PID },
};

ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
if (ret < 0)
return ret;

Expand Down Expand Up @@ -399,7 +409,7 @@ int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath)
.req = { .cmd = LXC_CMD_GET_CLONE_FLAGS },
};

ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
if (ret < 0)
return ret;

Expand Down Expand Up @@ -438,7 +448,7 @@ char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
},
};

ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
if (ret < 0)
return NULL;

Expand Down Expand Up @@ -497,7 +507,7 @@ char *lxc_cmd_get_config_item(const char *name, const char *item,
},
};

ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
if (ret < 0)
return NULL;

Expand Down Expand Up @@ -548,7 +558,7 @@ lxc_state_t lxc_cmd_get_state(const char *name, const char *lxcpath)
.req = { .cmd = LXC_CMD_GET_STATE }
};

ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
if (ret < 0 && stopped)
return STOPPED;

Expand Down Expand Up @@ -589,7 +599,7 @@ int lxc_cmd_stop(const char *name, const char *lxcpath)
.req = { .cmd = LXC_CMD_STOP },
};

ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
if (ret < 0) {
if (stopped) {
INFO("'%s' is already stopped", name);
Expand Down Expand Up @@ -650,7 +660,7 @@ int lxc_cmd_console_winch(const char *name, const char *lxcpath)
.req = { .cmd = LXC_CMD_CONSOLE_WINCH },
};

ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
if (ret < 0)
return ret;

Expand Down Expand Up @@ -685,7 +695,7 @@ int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
.req = { .cmd = LXC_CMD_CONSOLE, .data = INT_TO_PTR(*ttynum) },
};

ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
if (ret < 0)
return ret;

Expand Down Expand Up @@ -744,7 +754,81 @@ static int lxc_cmd_console_callback(int fd, struct lxc_cmd_req *req,
return 1;
}

/*
* lxc_cmd_get_name: Returns the name of the container
*
* @hashed_sock_name: hashed socket name
*
* Returns the name on success, NULL on failure.
*/
char *lxc_cmd_get_name(const char *hashed_sock_name)
{
int ret, stopped;
struct lxc_cmd_rr cmd = {
.req = { .cmd = LXC_CMD_GET_NAME},
};

ret = lxc_cmd(NULL, &cmd, &stopped, NULL, hashed_sock_name);
if (ret < 0) {
return NULL;
}

if (cmd.rsp.ret == 0)
return cmd.rsp.data;
return NULL;
}

static int lxc_cmd_get_name_callback(int fd, struct lxc_cmd_req *req,
struct lxc_handler *handler)
{
struct lxc_cmd_rsp rsp;

memset(&rsp, 0, sizeof(rsp));

rsp.data = handler->name;
rsp.datalen = strlen(handler->name) + 1;
rsp.ret = 0;

return lxc_cmd_rsp_send(fd, &rsp);
}

/*
* lxc_cmd_get_lxcpath: Returns the lxcpath of the container
*
* @hashed_sock_name: hashed socket name
*
* Returns the lxcpath on success, NULL on failure.
*/
char *lxc_cmd_get_lxcpath(const char *hashed_sock_name)
{
int ret, stopped;
struct lxc_cmd_rr cmd = {
.req = { .cmd = LXC_CMD_GET_LXCPATH},
};

ret = lxc_cmd(NULL, &cmd, &stopped, NULL, hashed_sock_name);
if (ret < 0) {
return NULL;
}

if (cmd.rsp.ret == 0)
return cmd.rsp.data;
return NULL;
}

static int lxc_cmd_get_lxcpath_callback(int fd, struct lxc_cmd_req *req,
struct lxc_handler *handler)
{
struct lxc_cmd_rsp rsp;

memset(&rsp, 0, sizeof(rsp));

rsp.data = (char *)handler->lxcpath;
rsp.datalen = strlen(handler->lxcpath) + 1;
rsp.ret = 0;

return lxc_cmd_rsp_send(fd, &rsp);
}

static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
struct lxc_handler *handler)
Expand All @@ -760,6 +844,8 @@ static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
[LXC_CMD_GET_CLONE_FLAGS] = lxc_cmd_get_clone_flags_callback,
[LXC_CMD_GET_CGROUP] = lxc_cmd_get_cgroup_callback,
[LXC_CMD_GET_CONFIG_ITEM] = lxc_cmd_get_config_item_callback,
[LXC_CMD_GET_NAME] = lxc_cmd_get_name_callback,
[LXC_CMD_GET_LXCPATH] = lxc_cmd_get_lxcpath_callback,
};

if (req->cmd >= LXC_CMD_MAX) {
Expand Down Expand Up @@ -887,7 +973,7 @@ int lxc_cmd_init(const char *name, struct lxc_handler *handler,
int len;

len = sizeof(path)-1;
if (fill_sock_name(offset, len, name, lxcpath))
if (fill_sock_name(offset, len, name, lxcpath, NULL))
return -1;

fd = lxc_abstract_unix_open(path, SOCK_STREAM, 0);
Expand Down
4 changes: 4 additions & 0 deletions src/lxc/commands.h
Expand Up @@ -41,6 +41,8 @@ typedef enum {
LXC_CMD_GET_CLONE_FLAGS,
LXC_CMD_GET_CGROUP,
LXC_CMD_GET_CONFIG_ITEM,
LXC_CMD_GET_NAME,
LXC_CMD_GET_LXCPATH,
LXC_CMD_MAX,
} lxc_cmd_t;

Expand Down Expand Up @@ -77,6 +79,8 @@ extern char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
const char *subsystem);
extern int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath);
extern char *lxc_cmd_get_config_item(const char *name, const char *item, const char *lxcpath);
extern char *lxc_cmd_get_name(const char *hashed_sock);
extern char *lxc_cmd_get_lxcpath(const char *hashed_sock);
extern pid_t lxc_cmd_get_init_pid(const char *name, const char *lxcpath);
extern lxc_state_t lxc_cmd_get_state(const char *name, const char *lxcpath);
extern int lxc_cmd_stop(const char *name, const char *lxcpath);
Expand Down
20 changes: 18 additions & 2 deletions src/lxc/lxccontainer.c
Expand Up @@ -3571,6 +3571,7 @@ int list_active_containers(const char *lxcpath, char ***nret,
char **ct_name = NULL;
size_t len = 0;
struct lxc_container *c;
bool is_hashed;

if (!lxcpath)
lxcpath = lxc_global_config_value("lxc.lxcpath");
Expand All @@ -3586,16 +3587,25 @@ int list_active_containers(const char *lxcpath, char ***nret,
return -1;

while (getline(&line, &len, f) != -1) {

char *p = strrchr(line, ' '), *p2;
if (!p)
continue;
p++;
if (*p != 0x40)
continue;
p++;
if (strncmp(p, lxcpath, lxcpath_len) != 0)

is_hashed = false;
if (strncmp(p, lxcpath, lxcpath_len) == 0) {
p += lxcpath_len;
} else if (strncmp(p, "lxc/", 4) == 0) {
p += 4;
is_hashed = true;
} else {
continue;
p += lxcpath_len;
}

while (*p == '/')
p++;

Expand All @@ -3605,6 +3615,12 @@ int list_active_containers(const char *lxcpath, char ***nret,
continue;
*p2 = '\0';

if (is_hashed) {
if (strncmp(lxcpath, lxc_cmd_get_lxcpath(p), lxcpath_len) != 0)
continue;
p = lxc_cmd_get_name(p);
}

if (array_contains(&ct_name, p, ct_name_cnt))
continue;

Expand Down

0 comments on commit b656b42

Please sign in to comment.