mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-03 14:34:25 +00:00
vtysh: receive file descriptors from daemons
The other half of yielding back a file descriptor from a daemon to vtysh. Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
parent
e960eedd98
commit
12d25fa69a
@ -182,6 +182,53 @@ static void vclient_close(struct vtysh_client *vclient)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t vtysh_client_receive(struct vtysh_client *vclient,
|
||||||
|
char *buf, size_t bufsz, int *pass_fd)
|
||||||
|
{
|
||||||
|
struct iovec iov[1] = {
|
||||||
|
{
|
||||||
|
.iov_base = buf,
|
||||||
|
.iov_len = bufsz,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
uint8_t buf[CMSG_SPACE(sizeof(int))];
|
||||||
|
struct cmsghdr align;
|
||||||
|
} u;
|
||||||
|
struct msghdr mh = {
|
||||||
|
.msg_iov = iov,
|
||||||
|
.msg_iovlen = array_size(iov),
|
||||||
|
.msg_control = u.buf,
|
||||||
|
.msg_controllen = sizeof(u.buf),
|
||||||
|
};
|
||||||
|
struct cmsghdr *cmh = CMSG_FIRSTHDR(&mh);
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
cmh->cmsg_level = SOL_SOCKET;
|
||||||
|
cmh->cmsg_type = SCM_RIGHTS;
|
||||||
|
cmh->cmsg_len = CMSG_LEN(sizeof(int));
|
||||||
|
memset(CMSG_DATA(cmh), -1, sizeof(int));
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = recvmsg(vclient->fd, &mh, 0);
|
||||||
|
if (ret < 0 && (errno == EINTR || errno == EAGAIN))
|
||||||
|
continue;
|
||||||
|
} while (false);
|
||||||
|
|
||||||
|
if (cmh->cmsg_len == CMSG_LEN(sizeof(int))) {
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
memcpy(&fd, CMSG_DATA(cmh), sizeof(int));
|
||||||
|
if (fd != -1) {
|
||||||
|
if (pass_fd)
|
||||||
|
*pass_fd = fd;
|
||||||
|
else
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send a CLI command to a client and read the response.
|
* Send a CLI command to a client and read the response.
|
||||||
*
|
*
|
||||||
@ -205,7 +252,8 @@ static void vclient_close(struct vtysh_client *vclient)
|
|||||||
* a status code
|
* a status code
|
||||||
*/
|
*/
|
||||||
static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
|
static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
|
||||||
void (*callback)(void *, const char *), void *cbarg)
|
void (*callback)(void *, const char *), void *cbarg,
|
||||||
|
int *pass_fd)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char stackbuf[4096];
|
char stackbuf[4096];
|
||||||
@ -239,8 +287,11 @@ static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
|
|||||||
|
|
||||||
bufvalid = buf;
|
bufvalid = buf;
|
||||||
do {
|
do {
|
||||||
ssize_t nread =
|
ssize_t nread;
|
||||||
read(vclient->fd, bufvalid, buf + bufsz - bufvalid - 1);
|
|
||||||
|
nread = vtysh_client_receive(vclient, bufvalid,
|
||||||
|
buf + bufsz - bufvalid - 1,
|
||||||
|
pass_fd);
|
||||||
|
|
||||||
if (nread < 0 && (errno == EINTR || errno == EAGAIN))
|
if (nread < 0 && (errno == EINTR || errno == EAGAIN))
|
||||||
continue;
|
continue;
|
||||||
@ -382,7 +433,7 @@ static int vtysh_client_run_all(struct vtysh_client *head_client,
|
|||||||
int correct_instance = 0, wrong_instance = 0;
|
int correct_instance = 0, wrong_instance = 0;
|
||||||
|
|
||||||
for (client = head_client; client; client = client->next) {
|
for (client = head_client; client; client = client->next) {
|
||||||
rc = vtysh_client_run(client, line, callback, cbarg);
|
rc = vtysh_client_run(client, line, callback, cbarg, NULL);
|
||||||
if (rc == CMD_NOT_MY_INSTANCE) {
|
if (rc == CMD_NOT_MY_INSTANCE) {
|
||||||
wrong_instance++;
|
wrong_instance++;
|
||||||
continue;
|
continue;
|
||||||
|
Loading…
Reference in New Issue
Block a user