Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
lxc
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
lxc
Commits
b07d3445
Unverified
Commit
b07d3445
authored
Oct 22, 2017
by
Christian Brauner
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
commands: non-functional changes
Signed-off-by:
Christian Brauner
<
christian.brauner@ubuntu.com
>
parent
51d1ec4f
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
193 additions
and
205 deletions
+193
-205
commands.c
src/lxc/commands.c
+193
-205
No files found.
src/lxc/commands.c
View file @
b07d3445
...
...
@@ -21,53 +21,54 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include "config.h"
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <malloc.h>
#include <poll.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/param.h>
#include <malloc.h>
#include <stdlib.h>
#include "log.h"
#include "lxc.h"
#include "conf.h"
#include "start.h"
/* for struct lxc_handler */
#include "utils.h"
#include "af_unix.h"
#include "cgroup.h"
#include "commands.h"
#include "commands_utils.h"
#include "con
sole
.h"
#include "con
f
.h"
#include "confile.h"
#include "console.h"
#include "log.h"
#include "lxc.h"
#include "lxclock.h"
#include "mainloop.h"
#include "monitor.h"
#include "
af_unix
.h"
#include "
config
.h"
#include "
start
.h"
#include "
utils
.h"
/*
* This file provides the different functions for clients to
*
query/command the server. The client is typically some lxc
*
tool and the server is typically the
container (ie. lxc-start).
* This file provides the different functions for clients to
query/command the
*
server. The client is typically some lxc tool and the server is typically the
* container (ie. lxc-start).
*
* Each command is transactional, the clients send a request to
* the server an
d the server answers the request with a message
*
giving the request's status (zero or a negative errno value).
*
Both the request and response may contain
additional data.
* Each command is transactional, the clients send a request to
the server and
* the server an
swers the request with a message giving the request's status
*
(zero or a negative errno value). Both the request and response may contain
* additional data.
*
* Each command is wrapped in a ancillary message in order to pass
*
a credential making possible to the server to check if the client
*
is allowed to ask for
this command or not.
* Each command is wrapped in a ancillary message in order to pass
a credential
*
making possible to the server to check if the client is allowed to ask for
* this command or not.
*
* IMPORTANTLY: Note that semantics for current commands are fixed.
If you
*
wish to make any changes to how, say, LXC_CMD_GET_CONFIG_ITEM works by
*
adding
information to the end of cmd.data, then you must introduce a new
* LXC_CMD_GET_CONFIG_ITEM_V2 define with a new number.
You may wish t
o
*
also
mark LXC_CMD_GET_CONFIG_ITEM deprecated in commands.h.
* IMPORTANTLY: Note that semantics for current commands are fixed.
If you wish
*
to make any changes to how, say, LXC_CMD_GET_CONFIG_ITEM works by adding
* information to the end of cmd.data, then you must introduce a new
* LXC_CMD_GET_CONFIG_ITEM_V2 define with a new number.
You may wish to als
o
* mark LXC_CMD_GET_CONFIG_ITEM deprecated in commands.h.
*
* This is necessary in order to avoid having a newly compiled lxc command
* communicating with a running (old) monitor from crashing the running
...
...
@@ -78,7 +79,7 @@ lxc_log_define(lxc_commands, lxc);
static
const
char
*
lxc_cmd_str
(
lxc_cmd_t
cmd
)
{
static
const
char
*
const
cmdname
[
LXC_CMD_MAX
]
=
{
static
const
char
*
const
cmdname
[
LXC_CMD_MAX
]
=
{
[
LXC_CMD_CONSOLE
]
=
"console"
,
[
LXC_CMD_CONSOLE_WINCH
]
=
"console_winch"
,
[
LXC_CMD_STOP
]
=
"stop"
,
...
...
@@ -94,6 +95,7 @@ static const char *lxc_cmd_str(lxc_cmd_t cmd)
if
(
cmd
>=
LXC_CMD_MAX
)
return
"Unknown cmd"
;
return
cmdname
[
cmd
];
}
...
...
@@ -121,11 +123,11 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
ret
=
lxc_abstract_unix_recv_fds
(
sock
,
&
rspfd
,
1
,
rsp
,
sizeof
(
*
rsp
));
if
(
ret
<
0
)
{
WARN
(
"
Command %s failed to receive response: %s.
"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
),
strerror
(
errno
));
WARN
(
"
%s - Failed to receive response for command
\"
%s
\"
"
,
strerror
(
errno
),
lxc_cmd_str
(
cmd
->
req
.
cmd
));
return
-
1
;
}
TRACE
(
"Command
\"
%s received response"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
));
TRACE
(
"Command
\"
%s
\"
received response"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
));
if
(
cmd
->
req
.
cmd
==
LXC_CMD_CONSOLE
)
{
struct
lxc_cmd_console_rsp_data
*
rspdata
;
...
...
@@ -138,9 +140,9 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
rspdata
=
malloc
(
sizeof
(
*
rspdata
));
if
(
!
rspdata
)
{
ERROR
(
"
Command %s couldn't allocate response buffer.
"
,
ERROR
(
"
Failed to allocate response buffer for command
\"
%s
\"
"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
));
return
-
1
;
return
-
ENOMEM
;
}
rspdata
->
masterfd
=
rspfd
;
rspdata
->
ttynum
=
PTR_TO_INT
(
rsp
->
data
);
...
...
@@ -148,26 +150,30 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
}
if
(
rsp
->
datalen
==
0
)
{
DEBUG
(
"
command %s response data length
is 0"
,
DEBUG
(
"
Response data length for command
\"
%s
\"
is 0"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
));
return
ret
;
}
if
(
rsp
->
datalen
>
LXC_CMD_DATA_MAX
)
{
ERROR
(
"Command %s response data %d too long."
,
lxc_cmd_str
(
cmd
->
req
.
cmd
),
rsp
->
datalen
);
errno
=
EFBIG
;
return
-
1
;
ERROR
(
"%s - Response data for command
\"
%s
\"
is too long: %d "
"bytes > %d"
,
strerror
(
errno
),
lxc_cmd_str
(
cmd
->
req
.
cmd
),
rsp
->
datalen
,
LXC_CMD_DATA_MAX
);
return
-
EFBIG
;
}
rsp
->
data
=
malloc
(
rsp
->
datalen
);
if
(
!
rsp
->
data
)
{
ERROR
(
"Command %s was unable to allocate response buffer."
,
lxc_cmd_str
(
cmd
->
req
.
cmd
));
return
-
1
;
errno
=
ENOMEM
;
ERROR
(
"%s - Failed to allocate response buffer for command "
"
\"
%s
\"
"
,
strerror
(
errno
),
lxc_cmd_str
(
cmd
->
req
.
cmd
));
return
-
ENOMEM
;
}
ret
=
recv
(
sock
,
rsp
->
data
,
rsp
->
datalen
,
0
);
if
(
ret
!=
rsp
->
datalen
)
{
ERROR
(
"
Command %s failed to receive response data: %s.
"
,
ERROR
(
"
%s - Failed to receive response data for command
\"
%s
\"
"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
),
strerror
(
errno
));
if
(
ret
>=
0
)
ret
=
-
1
;
...
...
@@ -186,43 +192,45 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
*/
static
int
lxc_cmd_rsp_send
(
int
fd
,
struct
lxc_cmd_rsp
*
rsp
)
{
in
t
ret
;
ssize_
t
ret
;
ret
=
send
(
fd
,
rsp
,
sizeof
(
*
rsp
),
0
);
if
(
ret
!=
sizeof
(
*
rsp
))
{
ERROR
(
"
Failed to send command response %d: %s."
,
ret
,
strerror
(
errno
));
if
(
ret
<
0
||
(
size_t
)
ret
!=
sizeof
(
*
rsp
))
{
ERROR
(
"
%s - Failed to send command response %zd"
,
strerror
(
errno
)
,
ret
);
return
-
1
;
}
if
(
rsp
->
datalen
>
0
)
{
ret
=
send
(
fd
,
rsp
->
data
,
rsp
->
datalen
,
0
);
if
(
ret
!=
rsp
->
datalen
)
{
WARN
(
"Failed to send command response data %d: %s."
,
ret
,
strerror
(
errno
));
return
-
1
;
}
if
(
rsp
->
datalen
<=
0
)
return
0
;
ret
=
send
(
fd
,
rsp
->
data
,
rsp
->
datalen
,
0
);
if
(
ret
<
0
||
ret
!=
(
ssize_t
)
rsp
->
datalen
)
{
WARN
(
"%s - Failed to send command response data %zd"
,
strerror
(
errno
),
ret
);
return
-
1
;
}
return
0
;
}
static
int
lxc_cmd_send
(
const
char
*
name
,
struct
lxc_cmd_rr
*
cmd
,
const
char
*
lxcpath
,
const
char
*
hashed_sock_name
)
const
char
*
lxcpath
,
const
char
*
hashed_sock_name
)
{
int
client_fd
;
in
t
ret
=
-
1
;
ssize_
t
ret
=
-
1
;
client_fd
=
lxc_cmd_connect
(
name
,
lxcpath
,
hashed_sock_name
);
if
(
client_fd
<
0
&&
client_fd
==
-
ECONNREFUSED
)
return
-
ECONNREFUSED
;
else
if
(
client_fd
<
0
)
return
-
1
;
if
(
client_fd
<
0
)
{
if
(
client_fd
==
-
ECONNREFUSED
)
return
-
ECONNREFUSED
;
TRACE
(
"Command
\"
%s
\"
connected to command socket"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
));
return
-
1
;
}
ret
=
lxc_abstract_unix_send_credential
(
client_fd
,
&
cmd
->
req
,
sizeof
(
cmd
->
req
));
if
(
ret
!=
sizeof
(
cmd
->
req
))
{
ret
=
lxc_abstract_unix_send_credential
(
client_fd
,
&
cmd
->
req
,
sizeof
(
cmd
->
req
));
if
(
ret
<
0
||
(
size_t
)
ret
!=
sizeof
(
cmd
->
req
))
{
close
(
client_fd
);
if
(
errno
==
EPIPE
)
...
...
@@ -234,22 +242,20 @@ static int lxc_cmd_send(const char *name, struct lxc_cmd_rr *cmd,
return
-
1
;
}
TRACE
(
"Command
\"
%s
\"
requested data of length %d"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
),
cmd
->
req
.
datalen
)
;
if
(
cmd
->
req
.
datalen
<=
0
)
return
client_fd
;
if
(
cmd
->
req
.
datalen
>
0
)
{
ret
=
send
(
client_fd
,
cmd
->
req
.
data
,
cmd
->
req
.
datalen
,
MSG_NOSIGNAL
);
if
(
ret
!=
cmd
->
req
.
datalen
)
{
close
(
client_fd
);
ret
=
send
(
client_fd
,
cmd
->
req
.
data
,
cmd
->
req
.
datalen
,
MSG_NOSIGNAL
);
if
(
ret
<
0
||
ret
!=
(
ssize_t
)
cmd
->
req
.
datalen
)
{
close
(
client_fd
);
if
(
errno
==
EPIPE
)
return
-
EPIPE
;
if
(
errno
==
EPIPE
)
return
-
EPIPE
;
if
(
ret
>=
0
)
return
-
EMSGSIZE
;
if
(
ret
>=
0
)
return
-
EMSGSIZE
;
return
-
1
;
}
return
-
1
;
}
return
client_fd
;
...
...
@@ -277,7 +283,8 @@ static int lxc_cmd_send(const char *name, struct lxc_cmd_rr *cmd,
static
int
lxc_cmd
(
const
char
*
name
,
struct
lxc_cmd_rr
*
cmd
,
int
*
stopped
,
const
char
*
lxcpath
,
const
char
*
hashed_sock_name
)
{
int
client_fd
,
ret
=
-
1
;
int
client_fd
;
int
ret
=
-
1
;
bool
stay_connected
=
false
;
if
(
cmd
->
req
.
cmd
==
LXC_CMD_CONSOLE
||
...
...
@@ -286,13 +293,10 @@ static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
*
stopped
=
0
;
TRACE
(
"command %s tries to connect command socket"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
));
client_fd
=
lxc_cmd_send
(
name
,
cmd
,
lxcpath
,
hashed_sock_name
);
if
(
client_fd
<
0
)
{
TRACE
(
"
command %s failed to connect command socket: %s
"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
),
strerror
(
errno
));
TRACE
(
"
%s - Command
\"
%s
\"
failed to connect command socket
"
,
strerror
(
errno
),
lxc_cmd_str
(
cmd
->
req
.
cmd
));
if
(
client_fd
==
-
ECONNREFUSED
)
{
*
stopped
=
1
;
return
-
1
;
...
...
@@ -308,6 +312,7 @@ static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
out:
if
(
!
stay_connected
||
ret
<=
0
)
close
(
client_fd
);
if
(
stay_connected
&&
ret
>
0
)
cmd
->
rsp
.
ret
=
client_fd
;
...
...
@@ -326,7 +331,6 @@ int lxc_try_cmd(const char *name, const char *lxcpath)
};
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
stopped
)
return
0
;
if
(
ret
>
0
&&
cmd
.
rsp
.
ret
<
0
)
{
...
...
@@ -336,14 +340,11 @@ int lxc_try_cmd(const char *name, const char *lxcpath)
if
(
ret
>
0
)
return
0
;
/*
* At this point we weren't denied access, and the
* container *was* started. There was some inexplicable
* error in the protocol.
* I'm not clear on whether we should return -1 here, but
* we didn't receive a -EACCES, so technically it's not that
* we're not allowed to control the container - it's just not
* behaving.
/* At this point we weren't denied access, and the container *was*
* started. There was some inexplicable error in the protocol. I'm not
* clear on whether we should return -1 here, but we didn't receive a
* -EACCES, so technically it's not that we're not allowed to control
* the container - it's just not behaving.
*/
return
0
;
}
...
...
@@ -423,37 +424,26 @@ static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req,
* returned path.
*/
char
*
lxc_cmd_get_cgroup_path
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
subsystem
)
const
char
*
subsystem
)
{
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_CGROUP
,
.
datalen
=
strlen
(
subsystem
)
+
1
,
.
datalen
=
strlen
(
subsystem
)
+
1
,
.
data
=
subsystem
,
},
};
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
{
TRACE
(
"command %s failed for container
\"
%s
\"
: %s."
,
lxc_cmd_str
(
cmd
.
req
.
cmd
),
name
,
strerror
(
errno
));
if
(
ret
<
0
)
return
NULL
;
}
if
(
!
ret
)
{
WARN
(
"container
\"
%s
\"
has stopped before sending its state"
,
name
);
if
(
ret
==
0
)
return
NULL
;
}
if
(
cmd
.
rsp
.
ret
<
0
||
cmd
.
rsp
.
datalen
<
0
)
{
ERROR
(
"command %s failed for container
\"
%s
\"
: %s"
,
lxc_cmd_str
(
cmd
.
req
.
cmd
),
name
,
strerror
(
-
cmd
.
rsp
.
ret
));
if
(
cmd
.
rsp
.
ret
<
0
||
cmd
.
rsp
.
datalen
<
0
)
return
NULL
;
}
TRACE
(
"command %s successful for container
\"
%s
\"
"
,
lxc_cmd_str
(
cmd
.
req
.
cmd
),
name
);
return
cmd
.
rsp
.
data
;
}
...
...
@@ -461,8 +451,8 @@ char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
static
int
lxc_cmd_get_cgroup_callback
(
int
fd
,
struct
lxc_cmd_req
*
req
,
struct
lxc_handler
*
handler
)
{
struct
lxc_cmd_rsp
rsp
;
const
char
*
path
;
struct
lxc_cmd_rsp
rsp
;
if
(
req
->
datalen
<
1
)
return
-
1
;
...
...
@@ -470,9 +460,10 @@ static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
path
=
cgroup_get_cgroup
(
handler
,
req
->
data
);
if
(
!
path
)
return
-
1
;
rsp
.
datalen
=
strlen
(
path
)
+
1
,
rsp
.
data
=
(
char
*
)
path
;
rsp
.
ret
=
0
;
rsp
.
datalen
=
strlen
(
path
)
+
1
;
rsp
.
data
=
(
char
*
)
path
;
return
lxc_cmd_rsp_send
(
fd
,
&
rsp
);
}
...
...
@@ -494,7 +485,7 @@ char *lxc_cmd_get_config_item(const char *name, const char *item,
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_CONFIG_ITEM
,
.
data
=
item
,
.
datalen
=
strlen
(
item
)
+
1
,
.
datalen
=
strlen
(
item
)
+
1
,
},
};
...
...
@@ -504,6 +495,7 @@ char *lxc_cmd_get_config_item(const char *name, const char *item,
if
(
cmd
.
rsp
.
ret
==
0
)
return
cmd
.
rsp
.
data
;
return
NULL
;
}
...
...
@@ -511,9 +503,9 @@ static int lxc_cmd_get_config_item_callback(int fd, struct lxc_cmd_req *req,
struct
lxc_handler
*
handler
)
{
int
cilen
;
struct
lxc_cmd_rsp
rsp
;
char
*
cidata
;
struct
lxc_config_t
*
item
;
struct
lxc_cmd_rsp
rsp
;
memset
(
&
rsp
,
0
,
sizeof
(
rsp
));
item
=
lxc_getconfig
(
req
->
data
);
...
...
@@ -526,6 +518,7 @@ static int lxc_cmd_get_config_item_callback(int fd, struct lxc_cmd_req *req,
cidata
=
alloca
(
cilen
+
1
);
if
(
item
->
get
(
req
->
data
,
cidata
,
cilen
+
1
,
handler
->
conf
)
!=
cilen
)
goto
err1
;
cidata
[
cilen
]
=
'\0'
;
rsp
.
data
=
cidata
;
rsp
.
datalen
=
cilen
+
1
;
...
...
@@ -561,12 +554,13 @@ int lxc_cmd_get_state(const char *name, const char *lxcpath)
return
-
1
;
if
(
!
ret
)
{
WARN
(
"Container
\"
%s
\"
has stopped before sending its state
.
"
,
name
);
WARN
(
"Container
\"
%s
\"
has stopped before sending its state"
,
name
);
return
-
1
;
}
DEBUG
(
"Container
\"
%s
\"
is in
\"
%s
\"
state
.
"
,
name
,
DEBUG
(
"Container
\"
%s
\"
is in
\"
%s
\"
state"
,
name
,
lxc_state2str
(
PTR_TO_INT
(
cmd
.
rsp
.
data
)));
return
PTR_TO_INT
(
cmd
.
rsp
.
data
);
}
...
...
@@ -597,22 +591,23 @@ int lxc_cmd_stop(const char *name, const char *lxcpath)
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
{
if
(
stopped
)
{
INFO
(
"Container
\"
%s
\"
is already stopped
.
"
,
name
);
INFO
(
"Container
\"
%s
\"
is already stopped"
,
name
);
return
0
;
}
return
-
1
;
}
/*
w
e do not expect any answer, because we wait for the connection to be
* closed
/*
W
e do not expect any answer, because we wait for the connection to be
* closed
.
*/
if
(
ret
>
0
)
{
ERROR
(
"
Failed to stop container
\"
%s
\"
: %s."
,
name
,
strerror
(
-
cmd
.
rsp
.
ret
));
ERROR
(
"
%s - Failed to stop container
\"
%s
\"
"
,
strerror
(
-
cmd
.
rsp
.
ret
)
,
name
);
return
-
1
;
}
INFO
(
"Container
\"
%s
\"
has stopped
.
"
,
name
);
INFO
(
"Container
\"
%s
\"
has stopped"
,
name
);
return
0
;
}
...
...
@@ -627,14 +622,15 @@ static int lxc_cmd_stop_callback(int fd, struct lxc_cmd_req *req,
memset
(
&
rsp
,
0
,
sizeof
(
rsp
));
rsp
.
ret
=
kill
(
handler
->
pid
,
stopsignal
);
if
(
!
rsp
.
ret
)
{
/*
w
e can't just use lxc_unfreeze() since we are already in the
/*
W
e can't just use lxc_unfreeze() since we are already in the
* context of handling the STOP cmd in lxc-start, and calling
* lxc_unfreeze() would do another cmd (GET_CGROUP) which would
* deadlock us
* deadlock us
.
*/
if
(
cgroup_unfreeze
(
handler
))
return
0
;
ERROR
(
"Failed to unfreeze container
\"
%s
\"
."
,
handler
->
name
);
ERROR
(
"Failed to unfreeze container
\"
%s
\"
"
,
handler
->
name
);
rsp
.
ret
=
-
1
;
}
...
...
@@ -669,6 +665,7 @@ static int lxc_cmd_console_winch_callback(int fd, struct lxc_cmd_req *req,
struct
lxc_cmd_rsp
rsp
=
{
.
data
=
0
};
lxc_console_sigwinch
(
SIGWINCH
);
return
lxc_cmd_rsp_send
(
fd
,
&
rsp
);
}
...
...
@@ -696,27 +693,28 @@ int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
return
ret
;
if
(
cmd
.
rsp
.
ret
<
0
)
{
ERROR
(
"
Console access denied: %s.
"
,
strerror
(
-
cmd
.
rsp
.
ret
));
ERROR
(
"
%s - Denied access to tty
"
,
strerror
(
-
cmd
.
rsp
.
ret
));
ret
=
-
1
;
goto
out
;
}
if
(
ret
==
0
)
{
ERROR
(
"
Console %d invalid, busy or all consoles busy.
"
,
*
ttynum
);
ERROR
(
"
tty number %d invalid, busy or all ttys busy
"
,
*
ttynum
);
ret
=
-
1
;
goto
out
;
}
rspdata
=
cmd
.
rsp
.
data
;
if
(
rspdata
->
masterfd
<
0
)
{
ERROR
(
"Unable to allocate fd for tty %d
.
"
,
rspdata
->
ttynum
);
ERROR
(
"Unable to allocate fd for tty %d"
,
rspdata
->
ttynum
);
goto
out
;
}
ret
=
cmd
.
rsp
.
ret
;
/* sock
fd */
ret
=
cmd
.
rsp
.
ret
;
/* socket
fd */
*
fd
=
rspdata
->
masterfd
;
*
ttynum
=
rspdata
->
ttynum
;
INFO
(
"tty %d allocated fd %d sock %d."
,
rspdata
->
ttynum
,
*
fd
,
ret
);
INFO
(
"Alloced fd %d for tty %d via socket %d"
,
*
fd
,
rspdata
->
ttynum
,
ret
);
out:
free
(
cmd
.
rsp
.
data
);
return
ret
;
...
...
@@ -725,9 +723,9 @@ out:
static
int
lxc_cmd_console_callback
(
int
fd
,
struct
lxc_cmd_req
*
req
,
struct
lxc_handler
*
handler
)
{
int
ttynum
=
PTR_TO_INT
(
req
->
data
);
int
masterfd
;
int
masterfd
,
ret
;
struct
lxc_cmd_rsp
rsp
;
int
ttynum
=
PTR_TO_INT
(
req
->
data
);
masterfd
=
lxc_console_allocate
(
handler
->
conf
,
fd
,
&
ttynum
);
if
(
masterfd
<
0
)
...
...
@@ -735,8 +733,9 @@ static int lxc_cmd_console_callback(int fd, struct lxc_cmd_req *req,
memset
(
&
rsp
,
0
,
sizeof
(
rsp
));
rsp
.
data
=
INT_TO_PTR
(
ttynum
);
if
(
lxc_abstract_unix_send_fds
(
fd
,
&
masterfd
,
1
,
&
rsp
,
sizeof
(
rsp
))
<
0
)
{
ERROR
(
"Failed to send tty to client."
);
ret
=
lxc_abstract_unix_send_fds
(
fd
,
&
masterfd
,
1
,
&
rsp
,
sizeof
(
rsp
));
if
(
ret
<
0
)
{
ERROR
(
"Failed to send tty to client"
);
lxc_console_free
(
handler
->
conf
,
fd
);
goto
out_close
;
}
...
...
@@ -744,8 +743,8 @@ static int lxc_cmd_console_callback(int fd, struct lxc_cmd_req *req,
return
0
;
out_close:
/*
s
pecial indicator to lxc_cmd_handler() to close the fd and do
* related cleanup
/*
S
pecial indicator to lxc_cmd_handler() to close the fd and do
* related cleanup
.
*/
return
1
;
}
...
...
@@ -765,17 +764,17 @@ char *lxc_cmd_get_name(const char *hashed_sock_name)
};
ret
=
lxc_cmd
(
NULL
,
&
cmd
,
&
stopped
,
NULL
,
hashed_sock_name
);
if
(
ret
<
0
)
{
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_handler
*
handler
)
{
struct
lxc_cmd_rsp
rsp
;
...
...
@@ -803,12 +802,12 @@ char *lxc_cmd_get_lxcpath(const char *hashed_sock_name)
};
ret
=
lxc_cmd
(
NULL
,
&
cmd
,
&
stopped
,
NULL
,
hashed_sock_name
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
return
NULL
;
}
if
(
cmd
.
rsp
.
ret
==
0
)
return
cmd
.
rsp
.
data
;
return
NULL
;
}
...
...
@@ -819,9 +818,9 @@ static int lxc_cmd_get_lxcpath_callback(int fd, struct lxc_cmd_req *req,
memset
(
&
rsp
,
0
,
sizeof
(
rsp
));
rsp
.
ret
=
0
;
rsp
.
data
=
(
char
*
)
handler
->
lxcpath
;
rsp
.
datalen
=
strlen
(
handler
->
lxcpath
)
+
1
;
rsp
.
ret
=
0
;
return
lxc_cmd_rsp_send
(
fd
,
&
rsp
);
}
...
...
@@ -849,53 +848,49 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
state
=
lxc_getstate
(
name
,
lxcpath
);
if
(
state
<
0
)
{
process_unlock
();
TRACE
(
"failed to retrieve state of container: %s"
,
strerror
(
errno
));
TRACE
(
"%s - Failed to retrieve state of container"
,
strerror
(
errno
));
return
-
1
;
}
else
if
(
states
[
state
])
{
process_unlock
();
TRACE
(
"
c
ontainer is %s state"
,
lxc_state2str
(
state
));
TRACE
(
"
C
ontainer is %s state"
,
lxc_state2str
(
state
));
return
state
;
}
if
((
state
==
STARTING
)
&&
!
states
[
RUNNING
]
&&
!
states
[
STOPPING
]
&&
!
states
[
STOPPED
])
{
process_unlock
();
TRACE
(
"container is in %s state and caller requested to be "
"informed about a previous state"
,
lxc_state2str
(
state
));
TRACE
(
"Container is in %s state and caller requested to be "
"informed about a previous state"
,
lxc_state2str
(
state
));
return
state
;
}
else
if
((
state
==
RUNNING
)
&&
!
states
[
STOPPING
]
&&
!
states
[
STOPPED
])
{
process_unlock
();
TRACE
(
"container is in %s state and caller requested to be "
"informed about a previous state"
,
lxc_state2str
(
state
));
TRACE
(
"Container is in %s state and caller requested to be "
"informed about a previous state"
,
lxc_state2str
(
state
));
return
state
;
}
else
if
((
state
==
STOPPING
)
&&
!
states
[
STOPPED
])
{
process_unlock
();
TRACE
(
"container is in %s state and caller requested to be "
"informed about a previous state"
,
lxc_state2str
(
state
));
TRACE
(
"Container is in %s state and caller requested to be "
"informed about a previous state"
,
lxc_state2str
(
state
));
return
state
;
}
else
if
((
state
==
STOPPED
)
||
(
state
==
ABORTING
))
{
process_unlock
();
TRACE
(
"container is in %s state and caller requested to be "
"informed about a previous state"
,
lxc_state2str
(
state
));
TRACE
(
"Container is in %s state and caller requested to be "
"informed about a previous state"
,
lxc_state2str
(
state
));
return
state
;
}
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
process_unlock
();
if
(
ret
<
0
)
{
ERROR
(
"
failed to execute command: %s
"
,
strerror
(
errno
));
ERROR
(
"
%s - Failed to execute command
"
,
strerror
(
errno
));
return
-
1
;
}
/* We should now be guaranteed to get an answer from the state sending
* function.
*/
if
(
cmd
.
rsp
.
ret
<
0
)
{
ERROR
(
"
f
ailed to receive socket fd"
);
ERROR
(
"
F
ailed to receive socket fd"
);
return
-
1
;
}
...
...
@@ -908,20 +903,14 @@ static int lxc_cmd_add_state_client_callback(int fd, struct lxc_cmd_req *req,
{
struct
lxc_cmd_rsp
rsp
=
{
0
};
if
(
req
->
datalen
<
0
)
{
TRACE
(
"Requested datalen was < 0"
);
if
(
req
->
datalen
<
0
)
return
-
1
;
}
if
(
req
->
datalen
>
(
sizeof
(
lxc_state_t
)
*
MAX_STATE
))
{
TRACE
(
"Requested datalen was too large"
);
if
(
req
->
datalen
>
(
sizeof
(
lxc_state_t
)
*
MAX_STATE
))
return
-
1
;
}
if
(
!
req
->
data
)
{
TRACE
(
"No states requested"
);
if
(
!
req
->
data
)
return
-
1
;
}
rsp
.
ret
=
lxc_add_state_client
(
fd
,
handler
,
(
lxc_state_t
*
)
req
->
data
);
if
(
rsp
.
ret
<
0
)
...
...
@@ -952,7 +941,7 @@ static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
};
if
(
req
->
cmd
>=
LXC_CMD_MAX
)
{
ERROR
(
"Undefined command id %d
received.
"
,
req
->
cmd
);
ERROR
(
"Undefined command id %d"
,
req
->
cmd
);
return
-
1
;
}
return
cb
[
req
->
cmd
](
fd
,
req
,
handler
);
...
...
@@ -975,38 +964,34 @@ static int lxc_cmd_handler(int fd, uint32_t events, void *data,
ret
=
lxc_abstract_unix_rcv_credential
(
fd
,
&
req
,
sizeof
(
req
));
if
(
ret
==
-
EACCES
)
{
/*
we don't care for the peer, just send and close
*/
struct
lxc_cmd_rsp
rsp
=
{
.
ret
=
ret
};
/*
We don't care for the peer, just send and close.
*/
struct
lxc_cmd_rsp
rsp
=
{
.
ret
=
ret
};
lxc_cmd_rsp_send
(
fd
,
&
rsp
);
goto
out_close
;
}
TRACE
(
"Processing
\"
%s
\"
command"
,
lxc_cmd_str
(
req
.
cmd
));
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to receive data on command socket for
\"
%s
\"
"
,
lxc_cmd_str
(
req
.
cmd
));
SYSERROR
(
"Failed to receive data on command socket for
command "
"
\"
%s
\"
"
,
lxc_cmd_str
(
req
.
cmd
));
goto
out_close
;
}
if
(
!
ret
)
{
DEBUG
(
"Peer has disconnected for
\"
%s
\"
"
,
lxc_cmd_str
(
req
.
cmd
));
if
(
ret
==
0
)
goto
out_close
;
}
if
(
ret
!=
sizeof
(
req
))
{
WARN
(
"Failed to receive full command request. Ignoring request "
"for
\"
%s
\"
"
,
lxc_cmd_str
(
req
.
cmd
));
"for
\"
%s
\"
"
,
lxc_cmd_str
(
req
.
cmd
));
ret
=
-
1
;
goto
out_close
;
}
if
(
req
.
datalen
>
LXC_CMD_DATA_MAX
)
{
ERROR
(
"Received command data length %d is too large for "
"command
\"
%s
\"
"
,
req
.
datalen
,
lxc_cmd_str
(
req
.
cmd
))
;
ret
=
-
1
;
"command
\"
%s
\"
"
,
req
.
datalen
,
lxc_cmd_str
(
req
.
cmd
));
errno
=
EFBIG
;
ret
=
-
EFBIG
;
goto
out_close
;
}
...
...
@@ -1017,23 +1002,24 @@ static int lxc_cmd_handler(int fd, uint32_t events, void *data,
ret
=
recv
(
fd
,
reqdata
,
req
.
datalen
,
0
);
if
(
ret
!=
req
.
datalen
)
{
WARN
(
"Failed to receive full command request. Ignoring "
"request for
\"
%s
\"
"
,
lxc_cmd_str
(
req
.
cmd
));
"request for
\"
%s
\"
"
,
lxc_cmd_str
(
req
.
cmd
));
ret
=
-
1
;
goto
out_close
;
}
req
.
data
=
reqdata
;
}
ret
=
lxc_cmd_process
(
fd
,
&
req
,
handler
);
if
(
ret
)
{
/*
this is not an error, but only a request to close fd
*/
/*
This is not an error, but only a request to close fd.
*/
ret
=
0
;
goto
out_close
;
}
out:
return
ret
;
out_close:
lxc_cmd_fd_cleanup
(
fd
,
handler
,
descr
);
goto
out
;
...
...
@@ -1042,7 +1028,8 @@ out_close:
static
int
lxc_cmd_accept
(
int
fd
,
uint32_t
events
,
void
*
data
,
struct
lxc_epoll_descr
*
descr
)
{
int
opt
=
1
,
ret
=
-
1
,
connection
;
int
connection
;
int
opt
=
1
,
ret
=
-
1
;
connection
=
accept
(
fd
,
NULL
,
0
);
if
(
connection
<
0
)
{
...
...
@@ -1050,20 +1037,21 @@ static int lxc_cmd_accept(int fd, uint32_t events, void *data,
return
-
1
;
}
if
(
fcntl
(
connection
,
F_SETFD
,
FD_CLOEXEC
))
{
SYSERROR
(
"Failed to set close-on-exec on incoming command connection."
);
ret
=
fcntl
(
connection
,
F_SETFD
,
FD_CLOEXEC
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to set close-on-exec on incoming command connection"
);
goto
out_close
;
}
if
(
setsockopt
(
connection
,
SOL_SOCKET
,
SO_PASSCRED
,
&
opt
,
sizeof
(
opt
))
)
{
SYSERROR
(
"Failed to enable necessary credentials on command socket
.
"
);
ret
=
setsockopt
(
connection
,
SOL_SOCKET
,
SO_PASSCRED
,
&
opt
,
sizeof
(
opt
));
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to enable necessary credentials on command socket"
);
goto
out_close
;
}
ret
=
lxc_mainloop_add_handler
(
descr
,
connection
,
lxc_cmd_handler
,
data
);
if
(
ret
)
{
ERROR
(
"Failed to add command handler
.
"
);
ERROR
(
"Failed to add command handler"
);
goto
out_close
;
}
...
...
@@ -1078,10 +1066,9 @@ out_close:
int
lxc_cmd_init
(
const
char
*
name
,
struct
lxc_handler
*
handler
,
const
char
*
lxcpath
)
{
int
fd
;
char
path
[
sizeof
(((
struct
sockaddr_un
*
)
0
)
->
sun_path
)]
=
{
0
};
int
fd
,
len
,
ret
;
char
path
[
sizeof
(((
struct
sockaddr_un
*
)
0
)
->
sun_path
)]
=
{
0
};
char
*
offset
=
&
path
[
1
];
int
len
;
/* -2 here because this is an abstract unix socket so it needs a
* leading \0, and we null terminate, so it needs a trailing \0.
...
...
@@ -1089,21 +1076,22 @@ int lxc_cmd_init(const char *name, struct lxc_handler *handler,
* because we print the sockname out sometimes.
*/
len
=
sizeof
(
path
)
-
2
;
if
(
lxc_make_abstract_socket_name
(
offset
,
len
,
name
,
lxcpath
,
NULL
,
"command"
)
)
ret
=
lxc_make_abstract_socket_name
(
offset
,
len
,
name
,
lxcpath
,
NULL
,
"command"
);
if
(
ret
<
0
)
return
-
1
;
fd
=
lxc_abstract_unix_open
(
path
,
SOCK_STREAM
,
0
);
if
(
fd
<
0
)
{
ERROR
(
"
Failed to create the command service point %s: %s.
"
,
offset
,
strerror
(
errno
)
);
ERROR
(
"
%s - Failed to create command socket %s
"
,
strerror
(
errno
),
offset
);
if
(
errno
==
EADDRINUSE
)
ERROR
(
"Container
\"
%s
\"
appears to be already running
!
"
,
name
);
ERROR
(
"Container
\"
%s
\"
appears to be already running"
,
name
);
return
-
1
;
}
if
(
fcntl
(
fd
,
F_SETFD
,
FD_CLOEXEC
))
{
SYSERROR
(
"Failed to set FD_CLOEXEC on signal file descriptor."
);
ret
=
fcntl
(
fd
,
F_SETFD
,
FD_CLOEXEC
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to set FD_CLOEXEC on command socket file descriptor"
);
close
(
fd
);
return
-
1
;
}
...
...
@@ -1112,15 +1100,15 @@ int lxc_cmd_init(const char *name, struct lxc_handler *handler,
return
0
;
}
int
lxc_cmd_mainloop_add
(
const
char
*
name
,
struct
lxc_epoll_descr
*
descr
,
int
lxc_cmd_mainloop_add
(
const
char
*
name
,
struct
lxc_epoll_descr
*
descr
,
struct
lxc_handler
*
handler
)
{
int
ret
,
fd
=
handler
->
conf
->
maincmd_fd
;
int
ret
;
int
fd
=
handler
->
conf
->
maincmd_fd
;
ret
=
lxc_mainloop_add_handler
(
descr
,
fd
,
lxc_cmd_accept
,
handler
);
if
(
ret
)
{
ERROR
(
"Failed to add handler for command socket
.
"
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to add handler for command socket"
);
close
(
fd
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment