mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 14:15:28 +00:00
cleanup: make nlComm commonly available
In a first cleanup step, make nlComm from macvtap.c commonly available for other code to use. Since nlComm uses Linux-specific structures as parameters it's prototype is only visible on Linux.
This commit is contained in:
parent
50a6a1267a
commit
6a5978833a
@ -101,6 +101,7 @@ src/util/interface.c
|
||||
src/util/iptables.c
|
||||
src/util/json.c
|
||||
src/util/macvtap.c
|
||||
src/util/netlink.c
|
||||
src/util/network.c
|
||||
src/util/pci.c
|
||||
src/util/processinfo.c
|
||||
|
@ -63,6 +63,7 @@ UTIL_SOURCES = \
|
||||
util/logging.c util/logging.h \
|
||||
util/macvtap.c util/macvtap.h \
|
||||
util/memory.c util/memory.h \
|
||||
util/netlink.c util/netlink.h \
|
||||
util/pci.c util/pci.h \
|
||||
util/processinfo.c util/processinfo.h \
|
||||
util/hostusb.c util/hostusb.h \
|
||||
|
@ -670,6 +670,10 @@ virResizeN;
|
||||
virShrinkN;
|
||||
|
||||
|
||||
#netlink.h
|
||||
nlComm;
|
||||
|
||||
|
||||
# network.h
|
||||
virSocketAddrBroadcast;
|
||||
virSocketAddrBroadcastByPrefix;
|
||||
|
@ -39,12 +39,8 @@
|
||||
# include <sys/ioctl.h>
|
||||
|
||||
# include <linux/if.h>
|
||||
# include <linux/netlink.h>
|
||||
# include <linux/rtnetlink.h>
|
||||
# include <linux/if_tun.h>
|
||||
|
||||
# include <netlink/msg.h>
|
||||
|
||||
/* Older kernels lacked this enum value. */
|
||||
# if !HAVE_DECL_MACVLAN_MODE_PASSTHRU
|
||||
# define MACVLAN_MODE_PASSTHRU 8
|
||||
@ -69,6 +65,7 @@ VIR_ENUM_IMPL(virMacvtapMode, VIR_MACVTAP_MODE_LAST,
|
||||
# include "virterror_internal.h"
|
||||
# include "uuid.h"
|
||||
# include "files.h"
|
||||
# include "netlink.h"
|
||||
|
||||
# define VIR_FROM_THIS VIR_FROM_NET
|
||||
|
||||
@ -84,8 +81,6 @@ VIR_ENUM_IMPL(virMacvtapMode, VIR_MACVTAP_MODE_LAST,
|
||||
# define NLMSGBUF_SIZE 256
|
||||
# define RATTBUF_SIZE 64
|
||||
|
||||
# define NETLINK_ACK_TIMEOUT_S 2
|
||||
|
||||
# define STATUS_POLL_TIMEOUT_USEC (10 * MICROSEC_PER_SEC)
|
||||
# define STATUS_POLL_INTERVL_USEC (MICROSEC_PER_SEC / 8)
|
||||
|
||||
@ -101,97 +96,6 @@ enum virVirtualPortOp {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* nlComm:
|
||||
* @nlmsg: pointer to netlink message
|
||||
* @respbuf: pointer to pointer where response buffer will be allocated
|
||||
* @respbuflen: pointer to integer holding the size of the response buffer
|
||||
* on return of the function.
|
||||
* @nl_pid: the pid of the process to talk to, i.e., pid = 0 for kernel
|
||||
*
|
||||
* Send the given message to the netlink layer and receive response.
|
||||
* Returns 0 on success, -1 on error. In case of error, no response
|
||||
* buffer will be returned.
|
||||
*/
|
||||
static
|
||||
int nlComm(struct nl_msg *nl_msg,
|
||||
unsigned char **respbuf, unsigned int *respbuflen,
|
||||
int nl_pid)
|
||||
{
|
||||
int rc = 0;
|
||||
struct sockaddr_nl nladdr = {
|
||||
.nl_family = AF_NETLINK,
|
||||
.nl_pid = nl_pid,
|
||||
.nl_groups = 0,
|
||||
};
|
||||
ssize_t nbytes;
|
||||
struct timeval tv = {
|
||||
.tv_sec = NETLINK_ACK_TIMEOUT_S,
|
||||
};
|
||||
fd_set readfds;
|
||||
int fd;
|
||||
int n;
|
||||
struct nlmsghdr *nlmsg = nlmsg_hdr(nl_msg);
|
||||
struct nl_handle *nlhandle = nl_handle_alloc();
|
||||
|
||||
if (!nlhandle) {
|
||||
virReportSystemError(errno,
|
||||
"%s", _("cannot allocate nlhandle for netlink"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nl_connect(nlhandle, NETLINK_ROUTE) < 0) {
|
||||
virReportSystemError(errno,
|
||||
"%s", _("cannot connect to netlink socket"));
|
||||
rc = -1;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
nlmsg_set_dst(nl_msg, &nladdr);
|
||||
|
||||
nlmsg->nlmsg_pid = getpid();
|
||||
|
||||
nbytes = nl_send_auto_complete(nlhandle, nl_msg);
|
||||
if (nbytes < 0) {
|
||||
virReportSystemError(errno,
|
||||
"%s", _("cannot send to netlink socket"));
|
||||
rc = -1;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
fd = nl_socket_get_fd(nlhandle);
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(fd, &readfds);
|
||||
|
||||
n = select(fd + 1, &readfds, NULL, NULL, &tv);
|
||||
if (n <= 0) {
|
||||
if (n < 0)
|
||||
virReportSystemError(errno, "%s",
|
||||
_("error in select call"));
|
||||
if (n == 0)
|
||||
virReportSystemError(ETIMEDOUT, "%s",
|
||||
_("no valid netlink response was received"));
|
||||
rc = -1;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
*respbuflen = nl_recv(nlhandle, &nladdr, respbuf, NULL);
|
||||
if (*respbuflen <= 0) {
|
||||
virReportSystemError(errno,
|
||||
"%s", _("nl_recv failed"));
|
||||
rc = -1;
|
||||
}
|
||||
err_exit:
|
||||
if (rc == -1) {
|
||||
VIR_FREE(*respbuf);
|
||||
*respbuf = NULL;
|
||||
*respbuflen = 0;
|
||||
}
|
||||
|
||||
nl_handle_destroy(nlhandle);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
# if WITH_MACVTAP
|
||||
|
150
src/util/netlink.c
Normal file
150
src/util/netlink.c
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
||||
* Copyright (C) 2010 IBM Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors:
|
||||
* Stefan Berger <stefanb@us.ibm.com>
|
||||
*
|
||||
* Notes:
|
||||
* netlink: http://lovezutto.googlepages.com/netlink.pdf
|
||||
* iproute2 package
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "netlink.h"
|
||||
#include "memory.h"
|
||||
#include "virterror_internal.h"
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_NET
|
||||
|
||||
#define netlinkError(code, ...) \
|
||||
virReportErrorHelper(VIR_FROM_NET, code, __FILE__, \
|
||||
__FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
|
||||
#define NETLINK_ACK_TIMEOUT_S 2
|
||||
|
||||
/**
|
||||
* nlComm:
|
||||
* @nlmsg: pointer to netlink message
|
||||
* @respbuf: pointer to pointer where response buffer will be allocated
|
||||
* @respbuflen: pointer to integer holding the size of the response buffer
|
||||
* on return of the function.
|
||||
* @nl_pid: the pid of the process to talk to, i.e., pid = 0 for kernel
|
||||
*
|
||||
* Send the given message to the netlink layer and receive response.
|
||||
* Returns 0 on success, -1 on error. In case of error, no response
|
||||
* buffer will be returned.
|
||||
*/
|
||||
#if __linux__
|
||||
int nlComm(struct nl_msg *nl_msg,
|
||||
unsigned char **respbuf, unsigned int *respbuflen,
|
||||
int nl_pid)
|
||||
{
|
||||
int rc = 0;
|
||||
struct sockaddr_nl nladdr = {
|
||||
.nl_family = AF_NETLINK,
|
||||
.nl_pid = nl_pid,
|
||||
.nl_groups = 0,
|
||||
};
|
||||
ssize_t nbytes;
|
||||
struct timeval tv = {
|
||||
.tv_sec = NETLINK_ACK_TIMEOUT_S,
|
||||
};
|
||||
fd_set readfds;
|
||||
int fd;
|
||||
int n;
|
||||
struct nlmsghdr *nlmsg = nlmsg_hdr(nl_msg);
|
||||
struct nl_handle *nlhandle = nl_handle_alloc();
|
||||
|
||||
if (!nlhandle) {
|
||||
virReportSystemError(errno,
|
||||
"%s", _("cannot allocate nlhandle for netlink"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nl_connect(nlhandle, NETLINK_ROUTE) < 0) {
|
||||
virReportSystemError(errno,
|
||||
"%s", _("cannot connect to netlink socket"));
|
||||
rc = -1;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
nlmsg_set_dst(nl_msg, &nladdr);
|
||||
|
||||
nlmsg->nlmsg_pid = getpid();
|
||||
|
||||
nbytes = nl_send_auto_complete(nlhandle, nl_msg);
|
||||
if (nbytes < 0) {
|
||||
virReportSystemError(errno,
|
||||
"%s", _("cannot send to netlink socket"));
|
||||
rc = -1;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
fd = nl_socket_get_fd(nlhandle);
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(fd, &readfds);
|
||||
|
||||
n = select(fd + 1, &readfds, NULL, NULL, &tv);
|
||||
if (n <= 0) {
|
||||
if (n < 0)
|
||||
virReportSystemError(errno, "%s",
|
||||
_("error in select call"));
|
||||
if (n == 0)
|
||||
virReportSystemError(ETIMEDOUT, "%s",
|
||||
_("no valid netlink response was received"));
|
||||
rc = -1;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
*respbuflen = nl_recv(nlhandle, &nladdr, respbuf, NULL);
|
||||
if (*respbuflen <= 0) {
|
||||
virReportSystemError(errno,
|
||||
"%s", _("nl_recv failed"));
|
||||
rc = -1;
|
||||
}
|
||||
err_exit:
|
||||
if (rc == -1) {
|
||||
VIR_FREE(*respbuf);
|
||||
*respbuf = NULL;
|
||||
*respbuflen = 0;
|
||||
}
|
||||
|
||||
nl_handle_destroy(nlhandle);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int nlComm(struct nl_msg *nl_msg ATTRIBUTE_UNUSED,
|
||||
unsigned char **respbuf ATTRIBUTE_UNUSED,
|
||||
unsigned int *respbuflen ATTRIBUTE_UNUSED,
|
||||
int nl_pid ATTRIBUTE_UNUSED)
|
||||
{
|
||||
netlinkError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("nlComm is not supported on non-linux platforms"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* __linux__ */
|
18
src/util/netlink.h
Normal file
18
src/util/netlink.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef __VIR_NETLINK_H__
|
||||
# define __VIR_NETLINK_H__
|
||||
|
||||
# if __linux__
|
||||
|
||||
# include <netlink/msg.h>
|
||||
|
||||
# else
|
||||
|
||||
struct nl_msg;
|
||||
|
||||
# endif /* __linux__ */
|
||||
|
||||
int nlComm(struct nl_msg *nl_msg,
|
||||
unsigned char **respbuf, unsigned int *respbuflen,
|
||||
int nl_pid);
|
||||
|
||||
#endif /* __VIR_NETLINK_H__ */
|
Loading…
Reference in New Issue
Block a user