monitor_netlink.c revision fa6c70fabb8dc2fab580a014cdcf1b0dd3e99554
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek SSSD - Service monitor - netlink support
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek Jakub Hrozek <jhrozek@redhat.com>
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek Parts of this code were borrowed from NetworkManager
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek Copyright (C) 2010 Red Hat
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek This program is free software; you can redistribute it and/or modify
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek it under the terms of the GNU General Public License as published by
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek the Free Software Foundation; either version 3 of the License, or
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek (at your option) any later version.
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek This program is distributed in the hope that it will be useful,
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek but WITHOUT ANY WARRANTY; without even the implied warranty of
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek GNU General Public License for more details.
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek You should have received a copy of the GNU General Public License
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek along with this program. If not, see <http://www.gnu.org/licenses/>.
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek/* Linux header file confusion causes this to be undefined. */
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek#define OBJ_CAST(ptr) ((struct nl_object *) (ptr))
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek#define nlw_recvmsgs_default nl_recvmsgs_default
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek nlctx = talloc_get_type(ptr, struct netlink_ctx);
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek/*******************************************************************
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek * Wrappers for different capabilities of different libnl versions
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek *******************************************************************/
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozekstatic bool nlw_accept_message(struct nl_handle *nlh,
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek return false;
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek /* Accept any messages from the kernel */
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek /* And any multicast message directed to our netlink PID, since multicast
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek * currently requires CAP_ADMIN to use.
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek if ((hdr->nlmsg_pid == local_port) && snl->nl_groups) {
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek if (accept_msg == false) {
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek DEBUG(9, ("ignoring netlink message from PID %d",
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozekstatic bool nlw_is_link_object(struct nl_object *obj)
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek /* Ensure it's a link object */
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek if (!nlw_object_match(obj, OBJ_CAST(filter))) {
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozekstatic int nlw_enable_passcred(struct nl_handle *nlh)
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek return EOK; /* not available in this version */
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek return nl_set_passcred(nlh, 1); /* 1 = enabled */
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozekstatic int nlw_group_subscribe(struct nl_handle *nlh)
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek ret = nl_socket_add_membership(nlh, RTNLGRP_LINK);
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek DEBUG(1, ("Unable to add membership: %s\n", nl_geterror()));
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek ret = setsockopt(nlfd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek DEBUG(1, ("setsockopt failed (%d): %s\n", ret, strerror(ret)));
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek/*******************************************************************
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek * Callbacks for validating and receiving messages
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek *******************************************************************/
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozekstatic int event_msg_recv(struct sockaddr_nl *nla, struct nlmsghdr *hdr,
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek struct netlink_ctx *ctx = (struct netlink_ctx *) arg;
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozekstatic int event_msg_recv(struct nl_msg *msg, void *arg)
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek struct netlink_ctx *ctx = (struct netlink_ctx *) arg;
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek DEBUG(9, ("Ignoring netlink message from UID %d",
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozekstatic void link_msg_handler(struct nl_object *obj, void *arg);
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozekstatic int event_msg_ready(struct sockaddr_nl *nla, struct nlmsghdr *hdr,
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozekstatic int event_msg_ready(struct nl_msg *msg, void *arg)
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozekstatic int nlw_set_callbacks(struct nl_handle *nlh, void *data)
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek ret = nl_cb_set(cb, NL_CB_MSG_IN, NL_CB_CUSTOM, event_msg_recv, data);
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek ret = nl_socket_modify_cb(nlh, NL_CB_MSG_IN, NL_CB_CUSTOM, event_msg_recv, data);
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek DEBUG(1, ("Unable to set validation callback\n"));
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek ret = nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, event_msg_ready, data);
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek ret = nl_socket_modify_cb(nlh, NL_CB_VALID, NL_CB_CUSTOM, event_msg_ready, data);
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek DEBUG(1, ("Unable to set receive callback\n"));
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozekstatic void link_msg_handler(struct nl_object *obj, void *arg)
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek struct netlink_ctx *ctx = (struct netlink_ctx *) arg;
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek DEBUG(8, ("netlink link message: iface idx %d flags 0x%X\n", ifidx, flags));
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek /* IFF_LOWER_UP is the indicator of carrier status */
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozekstatic void netlink_fd_handler(struct tevent_context *ev, struct tevent_fd *fde,
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek struct netlink_ctx *nlctx = talloc_get_type(data, struct netlink_ctx);
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek DEBUG(1, ("Invalid netlink handle, this is most likely a bug!\n"));
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek DEBUG(1, ("Error while reading from netlink fd\n"));
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek/*******************************************************************
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek * Set up the netlink library
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek *******************************************************************/
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozekint setup_netlink(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek nlctx = talloc_zero(mem_ctx, struct netlink_ctx);
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek talloc_set_destructor((TALLOC_CTX *) nlctx, netlink_ctx_destructor);
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek /* allocate the libnl handle and register the default filter set */
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek DEBUG(1, (("unable to allocate netlink handle: %s"),
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek /* Register our custom message validation filter */
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek /* Try to start talking to netlink */
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek DEBUG(1, ("Unable to connect to netlink: %s\n", nl_geterror()));
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek DEBUG(1, ("Cannot enable credential passing: %s\n", nl_geterror()));
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek /* Subscribe to the LINK group for internal carrier signals */
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek DEBUG(1, ("Unable to subscribe to netlink monitor\n"));
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek ret = fcntl(nlfd, F_SETFL, flags | O_NONBLOCK);
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek DEBUG(1, ("Cannot set the netlink fd to nonblocking\n"));
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek nlctx->tefd = tevent_add_fd(ev, nlctx, nlfd, TEVENT_FD_READ,
90acbcf20b5f896ca8f631923afe946c90d90de7Jakub Hrozek#else /* HAVE_LIBNL not defined */