Add support for fd=name to tap and socket networking
This allows a program to initialize a host networking device using a file descriptor passed over a unix monitor socket. The program must first pass the file descriptor using SCM_RIGHTS ancillary data with the getfd monitor command. It then may do "host_net_add tap fd=name" to use the named file descriptor. Signed-off-by: Mark McLoughlin <markmc@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
9bab7711ca
commit
413fb2412d
42
net.c
42
net.c
@ -2411,6 +2411,23 @@ void qemu_check_nic_model_list(NICInfo *nd, const char * const *models,
|
|||||||
exit(exit_status);
|
exit(exit_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int net_handle_fd_param(Monitor *mon, const char *param)
|
||||||
|
{
|
||||||
|
if (!qemu_isdigit(param[0])) {
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = monitor_get_fd(mon, param);
|
||||||
|
if (fd == -1) {
|
||||||
|
config_error(mon, "No file descriptor named %s found", param);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
} else {
|
||||||
|
return strtol(param, NULL, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int net_client_init(Monitor *mon, const char *device, const char *p)
|
int net_client_init(Monitor *mon, const char *device, const char *p)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
@ -2651,14 +2668,20 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
|
|||||||
static const char * const fd_params[] = {
|
static const char * const fd_params[] = {
|
||||||
"vlan", "name", "fd", "sndbuf", NULL
|
"vlan", "name", "fd", "sndbuf", NULL
|
||||||
};
|
};
|
||||||
|
ret = -1;
|
||||||
if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) {
|
if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) {
|
||||||
config_error(mon, "invalid parameter '%s' in '%s'\n", chkbuf, p);
|
config_error(mon, "invalid parameter '%s' in '%s'\n", chkbuf, p);
|
||||||
ret = -1;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
fd = strtol(buf, NULL, 0);
|
fd = net_handle_fd_param(mon, buf);
|
||||||
|
if (fd == -1) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
fcntl(fd, F_SETFL, O_NONBLOCK);
|
fcntl(fd, F_SETFL, O_NONBLOCK);
|
||||||
s = net_tap_fd_init(vlan, device, name, fd);
|
s = net_tap_fd_init(vlan, device, name, fd);
|
||||||
|
if (!s) {
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
static const char * const tap_params[] = {
|
static const char * const tap_params[] = {
|
||||||
"vlan", "name", "ifname", "script", "downscript", "sndbuf", NULL
|
"vlan", "name", "ifname", "script", "downscript", "sndbuf", NULL
|
||||||
@ -2698,15 +2721,20 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
|
|||||||
"vlan", "name", "fd", NULL
|
"vlan", "name", "fd", NULL
|
||||||
};
|
};
|
||||||
int fd;
|
int fd;
|
||||||
|
ret = -1;
|
||||||
if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) {
|
if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) {
|
||||||
config_error(mon, "invalid parameter '%s' in '%s'\n", chkbuf, p);
|
config_error(mon, "invalid parameter '%s' in '%s'\n", chkbuf, p);
|
||||||
ret = -1;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
fd = strtol(buf, NULL, 0);
|
fd = net_handle_fd_param(mon, buf);
|
||||||
ret = -1;
|
if (fd == -1) {
|
||||||
if (net_socket_fd_init(vlan, device, name, fd, 1))
|
goto out;
|
||||||
ret = 0;
|
}
|
||||||
|
if (!net_socket_fd_init(vlan, device, name, fd, 1)) {
|
||||||
|
close(fd);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
} else if (get_param_value(buf, sizeof(buf), "listen", p) > 0) {
|
} else if (get_param_value(buf, sizeof(buf), "listen", p) > 0) {
|
||||||
static const char * const listen_params[] = {
|
static const char * const listen_params[] = {
|
||||||
"vlan", "name", "listen", NULL
|
"vlan", "name", "listen", NULL
|
||||||
|
Loading…
Reference in New Issue
Block a user