diff --git a/po/POTFILES.in b/po/POTFILES.in index 81de425a6f603b0a4ac912504df3e08586cb8772..4ea1b782f820ee38003254a5af2bc83dbf546385 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -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 diff --git a/src/Makefile.am b/src/Makefile.am index 4f9bfc9a97b86bf7bd27811240794aea45c5b593..b292f9f284fafabc3d13dba0961f2d5fbe36880d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 6f253ab30fd8b4f611b341bb13326efe164d49b8..a0fd92215c6462e68d9fe718d778b1cbbafe59e6 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -670,6 +670,10 @@ virResizeN; virShrinkN; +#netlink.h +nlComm; + + # network.h virSocketAddrBroadcast; virSocketAddrBroadcastByPrefix; diff --git a/src/util/macvtap.c b/src/util/macvtap.c index ad1e3f3e4ed8547923bc3c608337d5669ace43c0..d651f7b1ac8f1aa1ab535c05f7458a291d19a1c8 100644 --- a/src/util/macvtap.c +++ b/src/util/macvtap.c @@ -39,12 +39,8 @@ # include # include -# include -# include # include -# include - /* 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 diff --git a/src/util/netlink.c b/src/util/netlink.c new file mode 100644 index 0000000000000000000000000000000000000000..411fa5be9ebe9779e307f5684cd0709e09aaedeb --- /dev/null +++ b/src/util/netlink.c @@ -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 + * + * Notes: + * netlink: http://lovezutto.googlepages.com/netlink.pdf + * iproute2 package + * + */ + +#include + +#include +#include +#include + +#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__ */ diff --git a/src/util/netlink.h b/src/util/netlink.h new file mode 100644 index 0000000000000000000000000000000000000000..dc634aaad43953cb314121d86ede1ce862a74bdb --- /dev/null +++ b/src/util/netlink.h @@ -0,0 +1,18 @@ +#ifndef __VIR_NETLINK_H__ +# define __VIR_NETLINK_H__ + +# if __linux__ + +# include + +# 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__ */