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:
Mark McLoughlin 2009-07-22 09:11:42 +01:00 committed by Anthony Liguori
parent 9bab7711ca
commit 413fb2412d

42
net.c
View File

@ -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