2011-06-22 21:42:51 +00:00
|
|
|
/*
|
2015-03-17 18:27:21 +00:00
|
|
|
* Copyright (C) 2010-2013, 2015 Red Hat, Inc.
|
2012-02-03 14:13:19 +00:00
|
|
|
* Copyright (C) 2010-2012 IBM Corporation
|
2011-06-22 21:42:51 +00:00
|
|
|
*
|
|
|
|
* 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
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2011-06-22 21:42:51 +00:00
|
|
|
*/
|
|
|
|
|
2018-12-13 14:53:50 +00:00
|
|
|
#ifndef LIBVIRT_VIRNETLINK_H
|
|
|
|
# define LIBVIRT_VIRNETLINK_H
|
2011-06-22 18:17:36 +00:00
|
|
|
|
2012-02-22 13:17:13 +00:00
|
|
|
# include "internal.h"
|
2012-07-17 12:07:59 +00:00
|
|
|
# include "virmacaddr.h"
|
2018-08-09 04:12:10 +00:00
|
|
|
# include "viralloc.h"
|
2011-06-23 15:54:11 +00:00
|
|
|
|
|
|
|
# if defined(__linux__) && defined(HAVE_LIBNL)
|
2011-06-22 18:17:36 +00:00
|
|
|
|
build: work with older libnl1 headers
Ubuntu 10.04 shipped with out-of-the-box libnl1 headers, which
assumed the old gcc semantics of 'extern inline' as a C89 extension:
the function will _always_ be inline if it is used, and that
it may be declared extern inline in headers without a definition,
as long as the definition occurs before any use. But when C99
added 'extern inline' as a mandatory feature of the language, with
slightly different semantics than gcc (the function MUST have
external linkage, and the inline definition MUST be present
alongside any declaration, where the compiler can then choose
which of the two versions to use), this rendered the use of
'inline' in libnl's header obsolete. Most distros already solved
this by removing 'inline' (the resulting 'extern' is correct,
regardless of gcc semantics), and libnl-3 does not have the
problem (where it has switched to 'static inline' instead, again
with the definition present, and again, our hack will result in
plain 'static' with no ill effects). But for the case of building
out of the box, we hack around the broken Ubuntu header.
* src/util/virnetlink.h: Work around libnl issue.
2012-08-27 21:00:59 +00:00
|
|
|
/* Work around a bug where older libnl-1 headers expected older gcc
|
|
|
|
* semantics of 'extern inline' that conflict with C99 semantics. */
|
2012-08-28 10:01:50 +00:00
|
|
|
# ifdef HAVE_LIBNL1
|
|
|
|
# define inline
|
|
|
|
# endif
|
2011-06-22 18:17:36 +00:00
|
|
|
# include <netlink/msg.h>
|
2012-08-28 10:01:50 +00:00
|
|
|
# ifdef HAVE_LIBNL1
|
|
|
|
# undef inline
|
|
|
|
# endif
|
2011-06-22 18:17:36 +00:00
|
|
|
|
2018-08-14 10:08:51 +00:00
|
|
|
typedef struct nl_msg virNetlinkMsg;
|
2019-02-07 17:18:52 +00:00
|
|
|
VIR_DEFINE_AUTOPTR_FUNC(virNetlinkMsg, nlmsg_free);
|
2018-08-14 10:08:51 +00:00
|
|
|
|
2011-06-22 18:17:36 +00:00
|
|
|
# else
|
|
|
|
|
|
|
|
struct nl_msg;
|
2012-02-22 13:17:13 +00:00
|
|
|
struct sockaddr_nl;
|
2012-03-06 01:12:34 +00:00
|
|
|
struct nlattr;
|
2013-04-03 13:09:19 +00:00
|
|
|
struct nlmsghdr;
|
2011-06-22 18:17:36 +00:00
|
|
|
|
|
|
|
# endif /* __linux__ */
|
|
|
|
|
2018-09-07 07:17:25 +00:00
|
|
|
# define NETLINK_MSG_NEST_START(msg, container, attrtype) \
|
|
|
|
do { \
|
|
|
|
container = nla_nest_start(msg, attrtype); \
|
|
|
|
if (!container) \
|
|
|
|
goto buffer_too_small; \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
# define NETLINK_MSG_NEST_END(msg, container) \
|
|
|
|
do { nla_nest_end(msg, container); } while(0)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* we need to use an intermediary pointer to @data as compilers may sometimes
|
|
|
|
* complain about @data not being a pointer type:
|
|
|
|
* error: the address of 'foo' will always evaluate as 'true' [-Werror=address]
|
|
|
|
*/
|
|
|
|
# define NETLINK_MSG_PUT(msg, attrtype, datalen, data) \
|
|
|
|
do { \
|
|
|
|
const void *dataptr = data; \
|
|
|
|
if (dataptr && nla_put(msg, attrtype, datalen, dataptr) < 0) \
|
|
|
|
goto buffer_too_small; \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
|
2012-05-03 14:39:04 +00:00
|
|
|
int virNetlinkStartup(void);
|
|
|
|
void virNetlinkShutdown(void);
|
|
|
|
|
2012-02-03 14:13:19 +00:00
|
|
|
int virNetlinkCommand(struct nl_msg *nl_msg,
|
2013-04-03 13:09:19 +00:00
|
|
|
struct nlmsghdr **resp, unsigned int *respbuflen,
|
2012-08-22 04:10:23 +00:00
|
|
|
uint32_t src_pid, uint32_t dst_pid,
|
|
|
|
unsigned int protocol, unsigned int groups);
|
util: fallback to ioctl(SIOCBRDELBR) if netlink RTM_DELLINK fails
commit 09778e09 switched from using ioctl(SIOCBRDELBR) for bridge
device deletion to using a netlink RTM_DELLINK message, which is the
more modern way to delete a bridge (and also doesn't require the
bridge to be ~IFF_UP to succeed). However, although older kernels
(e.g. 2.6.32, in RHEL6/CentOS6) support deleting *some* link types
with RTM_NEWLINK, they don't support deleting bridges, and there is no
compile-time way to figure this out.
This patch moves the body of the SIOCBRDELBR version of
virNetDevBridgeDelete() into a static function, calls the new function
from the original, and also calls the new function from the
RTM_DELLINK version if the RTM_DELLINK message generates an EOPNOTSUPP
error. Since RTM_DELLINK is done from the subordinate function
virNetlinkDelLink, which is also called for other purposes (deleting a
macvtap interface), a function pointer called "fallback" has been
added to the arglist of virNetlinkDelLink() - if that arg != NULL, the
provided function will be called when (and only when) RTM_DELLINK
fails with EOPNOTSUPP.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1252780 (part 2)
2015-08-26 03:19:03 +00:00
|
|
|
|
2019-01-06 22:35:47 +00:00
|
|
|
typedef int (*virNetlinkDumpCallback)(struct nlmsghdr *resp,
|
2017-03-03 11:22:50 +00:00
|
|
|
void *data);
|
|
|
|
|
|
|
|
int virNetlinkDumpCommand(struct nl_msg *nl_msg,
|
|
|
|
virNetlinkDumpCallback callback,
|
|
|
|
uint32_t src_pid, uint32_t dst_pid,
|
|
|
|
unsigned int protocol, unsigned int groups,
|
|
|
|
void *opaque);
|
|
|
|
|
2018-09-07 07:17:24 +00:00
|
|
|
typedef struct _virNetlinkNewLinkData virNetlinkNewLinkData;
|
|
|
|
typedef virNetlinkNewLinkData *virNetlinkNewLinkDataPtr;
|
|
|
|
struct _virNetlinkNewLinkData {
|
|
|
|
const int *ifindex; /* The index for the 'link' device */
|
|
|
|
const virMacAddr *mac; /* The MAC address of the device */
|
|
|
|
const uint32_t *macvlan_mode; /* The mode of macvlan */
|
|
|
|
};
|
|
|
|
|
|
|
|
int virNetlinkNewLink(const char *ifname,
|
|
|
|
const char *type,
|
|
|
|
virNetlinkNewLinkDataPtr data,
|
|
|
|
int *error);
|
|
|
|
|
util: fallback to ioctl(SIOCBRDELBR) if netlink RTM_DELLINK fails
commit 09778e09 switched from using ioctl(SIOCBRDELBR) for bridge
device deletion to using a netlink RTM_DELLINK message, which is the
more modern way to delete a bridge (and also doesn't require the
bridge to be ~IFF_UP to succeed). However, although older kernels
(e.g. 2.6.32, in RHEL6/CentOS6) support deleting *some* link types
with RTM_NEWLINK, they don't support deleting bridges, and there is no
compile-time way to figure this out.
This patch moves the body of the SIOCBRDELBR version of
virNetDevBridgeDelete() into a static function, calls the new function
from the original, and also calls the new function from the
RTM_DELLINK version if the RTM_DELLINK message generates an EOPNOTSUPP
error. Since RTM_DELLINK is done from the subordinate function
virNetlinkDelLink, which is also called for other purposes (deleting a
macvtap interface), a function pointer called "fallback" has been
added to the arglist of virNetlinkDelLink() - if that arg != NULL, the
provided function will be called when (and only when) RTM_DELLINK
fails with EOPNOTSUPP.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1252780 (part 2)
2015-08-26 03:19:03 +00:00
|
|
|
typedef int (*virNetlinkDelLinkFallback)(const char *ifname);
|
|
|
|
|
|
|
|
int virNetlinkDelLink(const char *ifname, virNetlinkDelLinkFallback fallback);
|
2011-06-22 18:17:36 +00:00
|
|
|
|
2014-08-05 17:15:11 +00:00
|
|
|
int virNetlinkGetErrorCode(struct nlmsghdr *resp, unsigned int recvbuflen);
|
|
|
|
|
2016-06-13 11:59:12 +00:00
|
|
|
int virNetlinkDumpLink(const char *ifname, int ifindex,
|
|
|
|
void **nlData, struct nlattr **tb,
|
|
|
|
uint32_t src_pid, uint32_t dst_pid)
|
|
|
|
ATTRIBUTE_RETURN_CHECK;
|
2018-03-08 07:11:55 +00:00
|
|
|
int
|
|
|
|
virNetlinkGetNeighbor(void **nlData, uint32_t src_pid, uint32_t dst_pid);
|
2016-06-13 11:59:12 +00:00
|
|
|
|
2013-04-03 13:09:19 +00:00
|
|
|
typedef void (*virNetlinkEventHandleCallback)(struct nlmsghdr *,
|
|
|
|
unsigned int length,
|
|
|
|
struct sockaddr_nl *peer,
|
|
|
|
bool *handled,
|
|
|
|
void *opaque);
|
2012-02-22 13:17:13 +00:00
|
|
|
|
2013-10-05 19:41:44 +00:00
|
|
|
typedef void (*virNetlinkEventRemoveCallback)(int watch,
|
|
|
|
const virMacAddr *macaddr,
|
|
|
|
void *opaque);
|
2012-02-22 13:17:13 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* stopNetlinkEventServer: stop the monitor to receive netlink messages for libvirtd
|
|
|
|
*/
|
2012-08-22 04:10:23 +00:00
|
|
|
int virNetlinkEventServiceStop(unsigned int protocol);
|
2012-02-22 13:17:13 +00:00
|
|
|
|
2012-08-22 04:10:24 +00:00
|
|
|
/**
|
|
|
|
* stopNetlinkEventServerAll: stop all the monitors to receive netlink messages for libvirtd
|
|
|
|
*/
|
|
|
|
int virNetlinkEventServiceStopAll(void);
|
|
|
|
|
2012-02-22 13:17:13 +00:00
|
|
|
/**
|
|
|
|
* startNetlinkEventServer: start a monitor to receive netlink messages for libvirtd
|
|
|
|
*/
|
2012-08-22 04:10:23 +00:00
|
|
|
int virNetlinkEventServiceStart(unsigned int protocol, unsigned int groups);
|
2012-02-22 13:17:13 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* virNetlinkEventServiceIsRunning: returns if the netlink event service is running.
|
|
|
|
*/
|
2012-08-22 04:10:23 +00:00
|
|
|
bool virNetlinkEventServiceIsRunning(unsigned int protocol);
|
2012-02-22 13:17:13 +00:00
|
|
|
|
2012-05-04 17:19:51 +00:00
|
|
|
/**
|
|
|
|
* virNetlinkEventServiceLocalPid: returns nl_pid used to bind() netlink socket
|
|
|
|
*/
|
2012-08-22 04:10:23 +00:00
|
|
|
int virNetlinkEventServiceLocalPid(unsigned int protocol);
|
2012-05-04 17:19:51 +00:00
|
|
|
|
2012-02-22 13:17:13 +00:00
|
|
|
/**
|
|
|
|
* virNetlinkEventAddClient: register a callback for handling of netlink messages
|
|
|
|
*/
|
|
|
|
int virNetlinkEventAddClient(virNetlinkEventHandleCallback handleCB,
|
|
|
|
virNetlinkEventRemoveCallback removeCB,
|
2013-10-05 19:41:44 +00:00
|
|
|
void *opaque, const virMacAddr *macaddr,
|
2012-08-22 04:10:23 +00:00
|
|
|
unsigned int protocol);
|
2012-02-22 13:17:13 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* virNetlinkEventRemoveClient: unregister a callback from a netlink monitor
|
|
|
|
*/
|
2013-10-05 19:41:44 +00:00
|
|
|
int virNetlinkEventRemoveClient(int watch, const virMacAddr *macaddr,
|
2012-08-22 04:10:23 +00:00
|
|
|
unsigned int protocol);
|
2012-02-22 13:17:13 +00:00
|
|
|
|
2018-12-13 14:53:50 +00:00
|
|
|
#endif /* LIBVIRT_VIRNETLINK_H */
|