1ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes/* 2ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * Copyright (C) 2015 The Android Open Source Project 3ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * All rights reserved. 4ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * 5ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * Redistribution and use in source and binary forms, with or without 6ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * modification, are permitted provided that the following conditions 7ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * are met: 8ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * * Redistributions of source code must retain the above copyright 9ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * notice, this list of conditions and the following disclaimer. 10ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * * Redistributions in binary form must reproduce the above copyright 11ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * notice, this list of conditions and the following disclaimer in 12ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * the documentation and/or other materials provided with the 13ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * distribution. 14ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * 15ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes * SUCH DAMAGE. 27ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes */ 28ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes 29ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes#include "bionic_netlink.h" 30ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes 31ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes#include <errno.h> 32ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes#include <linux/netlink.h> 33ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes#include <linux/rtnetlink.h> 34ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes#include <string.h> 35ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes#include <stdlib.h> 36ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes#include <sys/socket.h> 37ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes#include <unistd.h> 38ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes 39ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes#include "private/ErrnoRestorer.h" 40ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes 41ed57b98758176f0cccdec16cbed524e444039fe7Elliott HughesNetlinkConnection::NetlinkConnection() { 42ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes fd_ = -1; 43ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes 44ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes // The kernel keeps packets under 8KiB (NLMSG_GOODSIZE), 45ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes // but that's a bit too large to go on the stack. 46ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes size_ = 8192; 47ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes data_ = new char[size_]; 48ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes} 49ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes 50ed57b98758176f0cccdec16cbed524e444039fe7Elliott HughesNetlinkConnection::~NetlinkConnection() { 51ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes ErrnoRestorer errno_restorer; 52ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes if (fd_ != -1) close(fd_); 53ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes delete[] data_; 54ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes} 55ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes 56ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughesbool NetlinkConnection::SendRequest(int type) { 57ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes // Rather than force all callers to check for the unlikely event of being 58ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes // unable to allocate 8KiB, check here. 59ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes if (data_ == nullptr) return false; 60ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes 61ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes // Did we open a netlink socket yet? 62ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes if (fd_ == -1) { 63ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes fd_ = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE); 64ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes } 65ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes 66ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes // Construct and send the message. 67ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes struct NetlinkMessage { 68ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes nlmsghdr hdr; 69ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes rtgenmsg msg; 70ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes } request; 71ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes memset(&request, 0, sizeof(request)); 72ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes request.hdr.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; 73ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes request.hdr.nlmsg_type = type; 74ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes request.hdr.nlmsg_len = sizeof(request); 75ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes request.msg.rtgen_family = AF_UNSPEC; // All families. 76ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes return (TEMP_FAILURE_RETRY(send(fd_, &request, sizeof(request), 0)) == sizeof(request)); 77ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes} 78ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes 79ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughesbool NetlinkConnection::ReadResponses(void callback(void*, nlmsghdr*), void* context) { 80ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes // Read through all the responses, handing interesting ones to the callback. 81ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes ssize_t bytes_read; 82ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes while ((bytes_read = TEMP_FAILURE_RETRY(recv(fd_, data_, size_, 0))) > 0) { 83ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes nlmsghdr* hdr = reinterpret_cast<nlmsghdr*>(data_); 84ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes for (; NLMSG_OK(hdr, static_cast<size_t>(bytes_read)); hdr = NLMSG_NEXT(hdr, bytes_read)) { 85ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes if (hdr->nlmsg_type == NLMSG_DONE) return true; 86ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes if (hdr->nlmsg_type == NLMSG_ERROR) return false; 87ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes callback(context, hdr); 88ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes } 89ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes } 90ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes 91ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes // We only get here if recv fails before we see a NLMSG_DONE. 92ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes return false; 93ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes} 94