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
c01c2be6
Unverified
Commit
c01c2be6
authored
Jul 03, 2017
by
Christian Brauner
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
commands: abstract cmd socket handling + logging
Signed-off-by:
Christian Brauner
<
christian.brauner@ubuntu.com
>
parent
86a78f17
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
178 additions
and
72 deletions
+178
-72
commands.c
src/lxc/commands.c
+91
-72
commands_utils.c
src/lxc/commands_utils.c
+59
-0
commands_utils.h
src/lxc/commands_utils.h
+28
-0
No files found.
src/lxc/commands.c
View file @
c01c2be6
...
...
@@ -206,6 +206,60 @@ static int lxc_cmd_rsp_send(int fd, struct lxc_cmd_rsp *rsp)
return
0
;
}
static
int
lxc_cmd_send
(
const
char
*
name
,
struct
lxc_cmd_rr
*
cmd
,
const
char
*
lxcpath
,
const
char
*
hashed_sock_name
)
{
int
client_fd
;
int
ret
=
-
1
;
/* -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.
* Although null termination isn't required by the API, we do it anyway
* because we print the sockname out sometimes.
*/
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
;
TRACE
(
"Command
\"
%s
\"
connected to command socket"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
));
ret
=
lxc_abstract_unix_send_credential
(
client_fd
,
&
cmd
->
req
,
sizeof
(
cmd
->
req
));
if
(
ret
!=
sizeof
(
cmd
->
req
))
{
close
(
client_fd
);
if
(
errno
==
EPIPE
)
return
-
EPIPE
;
if
(
ret
>=
0
)
return
-
EMSGSIZE
;
return
-
1
;
}
TRACE
(
"Command
\"
%s
\"
requested data of length %d"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
),
cmd
->
req
.
datalen
);
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
);
if
(
errno
==
EPIPE
)
return
-
EPIPE
;
if
(
ret
>=
0
)
return
-
EMSGSIZE
;
return
-
1
;
}
}
return
client_fd
;
}
/*
* lxc_cmd: Connect to the specified running container, send it a command
* request and collect the response
...
...
@@ -228,10 +282,7 @@ static int lxc_cmd_rsp_send(int fd, struct lxc_cmd_rsp *rsp)
static
int
lxc_cmd
(
const
char
*
name
,
struct
lxc_cmd_rr
*
cmd
,
int
*
stopped
,
const
char
*
lxcpath
,
const
char
*
hashed_sock_name
)
{
int
sock
,
ret
=
-
1
;
char
path
[
sizeof
(((
struct
sockaddr_un
*
)
0
)
->
sun_path
)]
=
{
0
};
char
*
offset
=
&
path
[
1
];
size_t
len
;
int
client_fd
,
ret
=
-
1
;
bool
stay_connected
=
false
;
if
(
cmd
->
req
.
cmd
==
LXC_CMD_CONSOLE
||
...
...
@@ -245,64 +296,34 @@ static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
* Although null termination isn't required by the API, we do it anyway
* because we print the sockname out sometimes.
*/
len
=
sizeof
(
path
)
-
2
;
if
(
lxc_make_abstract_socket_name
(
offset
,
len
,
name
,
lxcpath
,
hashed_sock_name
,
"command"
))
return
-
1
;
TRACE
(
"command %s tries to connect command socket"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
));
sock
=
lxc_abstract_unix_connect
(
path
);
TRACE
(
"command %s tries to connect to
\"
@%s
\"
"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
),
offset
);
if
(
sock
<
0
)
{
if
(
errno
==
ECONNREFUSED
)
{
TRACE
(
"command %s failed to connect to
\"
@%s
\"
: %s"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
),
offset
,
strerror
(
errno
));
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
));
if
(
client_fd
==
-
ECONNREFUSED
)
{
*
stopped
=
1
;
}
else
{
SYSERROR
(
"command %s failed to connect to
\"
@%s
\"
: %s"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
),
offset
,
strerror
(
errno
));
return
-
1
;
}
return
-
1
;
}
ret
=
lxc_abstract_unix_send_credential
(
sock
,
&
cmd
->
req
,
sizeof
(
cmd
->
req
));
if
(
ret
!=
sizeof
(
cmd
->
req
))
{
if
(
errno
==
EPIPE
)
if
(
client_fd
==
-
EPIPE
)
goto
epipe
;
SYSERROR
(
"Command %s failed to send req to
\"
@%s
\"
%d."
,
lxc_cmd_str
(
cmd
->
req
.
cmd
),
offset
,
ret
);
if
(
ret
>=
0
)
ret
=
-
1
;
goto
out
;
}
if
(
cmd
->
req
.
datalen
>
0
)
{
ret
=
send
(
sock
,
cmd
->
req
.
data
,
cmd
->
req
.
datalen
,
MSG_NOSIGNAL
);
if
(
ret
!=
cmd
->
req
.
datalen
)
{
if
(
errno
==
EPIPE
)
goto
epipe
;
SYSERROR
(
"Command %s failed to send request data to
\"
@%s
\"
%d."
,
lxc_cmd_str
(
cmd
->
req
.
cmd
),
offset
,
ret
);
if
(
ret
>=
0
)
ret
=
-
1
;
goto
out
;
}
goto
out
;
}
ret
=
lxc_cmd_rsp_recv
(
sock
,
cmd
);
ret
=
lxc_cmd_rsp_recv
(
client_fd
,
cmd
);
out:
if
(
!
stay_connected
||
ret
<=
0
)
close
(
sock
);
close
(
client_fd
);
if
(
stay_connected
&&
ret
>
0
)
cmd
->
rsp
.
ret
=
sock
;
cmd
->
rsp
.
ret
=
client_fd
;
return
ret
;
epipe:
close
(
sock
);
*
stopped
=
1
;
return
0
;
}
...
...
@@ -896,37 +917,27 @@ static int lxc_cmd_add_state_client_callback(int fd, struct lxc_cmd_req *req,
struct
lxc_handler
*
handler
)
{
struct
lxc_cmd_rsp
rsp
=
{
0
};
struct
state_client
*
newclient
;
struct
lxc_list
*
tmplist
;
if
(
req
->
datalen
<
0
)
{
TRACE
(
"
r
equested datalen was < 0"
);
TRACE
(
"
R
equested datalen was < 0"
);
return
-
1
;
}
if
(
!
req
->
data
)
{
TRACE
(
"
no states requested
"
);
if
(
req
->
datalen
>
(
sizeof
(
lxc_state_t
)
*
MAX_STATE
)
)
{
TRACE
(
"
Requested datalen was too large
"
);
return
-
1
;
}
newclient
=
malloc
(
sizeof
(
*
newclient
));
if
(
!
newclient
)
return
-
1
;
/* copy requested states */
memcpy
(
newclient
->
states
,
req
->
data
,
sizeof
(
newclient
->
states
));
newclient
->
clientfd
=
fd
;
tmplist
=
malloc
(
sizeof
(
*
tmplist
));
if
(
!
tmplist
)
{
free
(
newclient
);
if
(
!
req
->
data
)
{
TRACE
(
"No states requested"
);
return
-
1
;
}
lxc_list_add_elem
(
tmplist
,
newclient
);
lxc_list_add_tail
(
&
handler
->
state_clients
,
tmplist
);
TRACE
(
"added state client %d to state client list"
,
fd
);
rsp
.
ret
=
lxc_add_state_client
(
fd
,
handler
,
(
lxc_state_t
*
)
req
->
data
);
if
(
rsp
.
ret
<
0
)
ERROR
(
"Failed to add state client %d to state client list"
,
fd
);
else
TRACE
(
"Added state client %d to state client list"
,
fd
);
return
lxc_cmd_rsp_send
(
fd
,
&
rsp
);
}
...
...
@@ -981,24 +992,30 @@ static int lxc_cmd_handler(int fd, uint32_t events, void *data,
goto
out_close
;
}
TRACE
(
"Processing
\"
%s
\"
command"
,
lxc_cmd_str
(
req
.
cmd
));
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to receive data on command socket."
);
SYSERROR
(
"Failed to receive data on command socket for
\"
%s
\"
"
,
lxc_cmd_str
(
req
.
cmd
));
goto
out_close
;
}
if
(
!
ret
)
{
DEBUG
(
"Peer has disconnected
."
);
DEBUG
(
"Peer has disconnected
for
\"
%s
\"
"
,
lxc_cmd_str
(
req
.
cmd
)
);
goto
out_close
;
}
if
(
ret
!=
sizeof
(
req
))
{
WARN
(
"Failed to receive full command request. Ignoring request."
);
WARN
(
"Failed to receive full command request. Ignoring request "
"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."
,
req
.
datalen
);
ERROR
(
"Received command data length %d is too large for "
"command
\"
%s
\"
"
,
req
.
datalen
,
lxc_cmd_str
(
req
.
cmd
));
ret
=
-
1
;
goto
out_close
;
}
...
...
@@ -1009,7 +1026,9 @@ static int lxc_cmd_handler(int fd, uint32_t events, void *data,
reqdata
=
alloca
(
req
.
datalen
);
ret
=
recv
(
fd
,
reqdata
,
req
.
datalen
,
0
);
if
(
ret
!=
req
.
datalen
)
{
WARN
(
"Failed to receive full command request. Ignoring request."
);
WARN
(
"Failed to receive full command request. Ignoring "
"request for
\"
%s
\"
"
,
lxc_cmd_str
(
req
.
cmd
));
ret
=
-
1
;
goto
out_close
;
}
...
...
src/lxc/commands_utils.c
View file @
c01c2be6
...
...
@@ -28,8 +28,10 @@
#include <sys/socket.h>
#include <sys/un.h>
#include "af_unix.h"
#include "commands.h"
#include "commands_utils.h"
#include "initutils.h"
#include "log.h"
#include "monitor.h"
#include "state.h"
...
...
@@ -153,3 +155,60 @@ int lxc_make_abstract_socket_name(char *path, int len, const char *lxcname,
return
0
;
}
int
lxc_cmd_connect
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
hashed_sock_name
)
{
int
ret
,
client_fd
;
char
path
[
sizeof
(((
struct
sockaddr_un
*
)
0
)
->
sun_path
)]
=
{
0
};
char
*
offset
=
&
path
[
1
];
size_t
len
=
sizeof
(
path
)
-
2
;
/* -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.
* Although null termination isn't required by the API, we do it anyway
* because we print the sockname out sometimes.
*/
ret
=
lxc_make_abstract_socket_name
(
offset
,
len
,
name
,
lxcpath
,
hashed_sock_name
,
"command"
);
if
(
ret
<
0
)
return
-
1
;
/* Get new client fd. */
client_fd
=
lxc_abstract_unix_connect
(
path
);
if
(
client_fd
<
0
)
{
if
(
errno
==
ECONNREFUSED
)
return
-
ECONNREFUSED
;
return
-
1
;
}
return
client_fd
;
}
int
lxc_add_state_client
(
int
state_client_fd
,
struct
lxc_handler
*
handler
,
lxc_state_t
states
[
MAX_STATE
])
{
struct
state_client
*
newclient
;
struct
lxc_list
*
tmplist
;
newclient
=
malloc
(
sizeof
(
*
newclient
));
if
(
!
newclient
)
return
-
ENOMEM
;
/* copy requested states */
memcpy
(
newclient
->
states
,
states
,
sizeof
(
newclient
->
states
));
newclient
->
clientfd
=
state_client_fd
;
tmplist
=
malloc
(
sizeof
(
*
tmplist
));
if
(
!
tmplist
)
{
free
(
newclient
);
return
-
ENOMEM
;
}
lxc_list_add_elem
(
tmplist
,
newclient
);
lxc_list_add_tail
(
&
handler
->
state_clients
,
tmplist
);
TRACE
(
"added state client %d to state client list"
,
state_client_fd
);
return
0
;
}
src/lxc/commands_utils.h
View file @
c01c2be6
...
...
@@ -23,6 +23,7 @@
#include <stdio.h>
#include "state.h"
#include "commands.h"
int
lxc_make_abstract_socket_name
(
char
*
path
,
int
len
,
const
char
*
lxcname
,
const
char
*
lxcpath
,
...
...
@@ -53,4 +54,31 @@ extern int lxc_cmd_sock_get_state(const char *name, const char *lxcpath,
*/
extern
int
lxc_cmd_sock_rcv_state
(
int
state_client_fd
,
int
timeout
);
/* lxc_add_state_client Add a new state client to the container's
* in-memory handler.
*
* @param[int] state_client_fd The state client fd to add.
* @param[int] handler The container's in-memory handler.
* @param[in] states The states to wait for.
*
* @return Return < 0 on error
* 0 on success
*/
extern
int
lxc_add_state_client
(
int
state_client_fd
,
struct
lxc_handler
*
handler
,
lxc_state_t
states
[
MAX_STATE
]);
/* lxc_cmd_connect Connect to the container's command socket.
*
* @param[in] name Name of container to connect to.
* @param[in] lxcpath The lxcpath in which the container is running.
* @param[in] hashed_sock_name The hashed name of the socket (optional). Can be
* NULL.
*
* @return Return < 0 on error
* >= 0 client fd
*/
extern
int
lxc_cmd_connect
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
hashed_sock_name
);
#endif
/* __LXC_COMMANDS_UTILS_H */
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