1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <errno.h> 18#include <stdio.h> 19#include <string.h> 20 21#include <sys/socket.h> 22#include <sys/select.h> 23#include <sys/time.h> 24#include <sys/types.h> 25#include <sys/un.h> 26 27#include <linux/netlink.h> 28#include <linux/rtnetlink.h> 29 30#define LOG_TAG "Netd" 31 32#include <cutils/log.h> 33 34#include <linux/netfilter/nfnetlink.h> 35#include <linux/netfilter/nfnetlink_log.h> 36#include <linux/netfilter/nfnetlink_compat.h> 37 38#include <arpa/inet.h> 39 40#include "NetlinkManager.h" 41#include "NetlinkHandler.h" 42 43#include "pcap-netfilter-linux-android.h" 44 45namespace android { 46namespace net { 47 48const int NetlinkManager::NFLOG_QUOTA_GROUP = 1; 49const int NetlinkManager::NETFILTER_STRICT_GROUP = 2; 50const int NetlinkManager::NFLOG_WAKEUP_GROUP = 3; 51 52NetlinkManager *NetlinkManager::sInstance = NULL; 53 54NetlinkManager *NetlinkManager::Instance() { 55 if (!sInstance) 56 sInstance = new NetlinkManager(); 57 return sInstance; 58} 59 60NetlinkManager::NetlinkManager() { 61 mBroadcaster = NULL; 62} 63 64NetlinkManager::~NetlinkManager() { 65} 66 67NetlinkHandler *NetlinkManager::setupSocket(int *sock, int netlinkFamily, 68 int groups, int format, bool configNflog) { 69 70 struct sockaddr_nl nladdr; 71 int sz = 64 * 1024; 72 int on = 1; 73 74 memset(&nladdr, 0, sizeof(nladdr)); 75 nladdr.nl_family = AF_NETLINK; 76 // Kernel will assign a unique nl_pid if set to zero. 77 nladdr.nl_pid = 0; 78 nladdr.nl_groups = groups; 79 80 if ((*sock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, netlinkFamily)) < 0) { 81 ALOGE("Unable to create netlink socket: %s", strerror(errno)); 82 return NULL; 83 } 84 85 // When running in a net/user namespace, SO_RCVBUFFORCE will fail because 86 // it will check for the CAP_NET_ADMIN capability in the root namespace. 87 // Try using SO_RCVBUF if that fails. 88 if (setsockopt(*sock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0 && 89 setsockopt(*sock, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)) < 0) { 90 ALOGE("Unable to set uevent socket SO_RCVBUF option: %s", strerror(errno)); 91 close(*sock); 92 return NULL; 93 } 94 95 if (setsockopt(*sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) { 96 SLOGE("Unable to set uevent socket SO_PASSCRED option: %s", strerror(errno)); 97 close(*sock); 98 return NULL; 99 } 100 101 if (bind(*sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) { 102 ALOGE("Unable to bind netlink socket: %s", strerror(errno)); 103 close(*sock); 104 return NULL; 105 } 106 107 if (configNflog) { 108 if (android_nflog_send_config_cmd(*sock, 0, NFULNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) { 109 ALOGE("Failed NFULNL_CFG_CMD_PF_UNBIND: %s", strerror(errno)); 110 return NULL; 111 } 112 if (android_nflog_send_config_cmd(*sock, 0, NFULNL_CFG_CMD_PF_BIND, AF_INET) < 0) { 113 ALOGE("Failed NFULNL_CFG_CMD_PF_BIND: %s", strerror(errno)); 114 return NULL; 115 } 116 if (android_nflog_send_config_cmd(*sock, 0, NFULNL_CFG_CMD_BIND, AF_UNSPEC) < 0) { 117 ALOGE("Failed NFULNL_CFG_CMD_BIND: %s", strerror(errno)); 118 return NULL; 119 } 120 } 121 122 NetlinkHandler *handler = new NetlinkHandler(this, *sock, format); 123 if (handler->start()) { 124 ALOGE("Unable to start NetlinkHandler: %s", strerror(errno)); 125 close(*sock); 126 return NULL; 127 } 128 129 return handler; 130} 131 132int NetlinkManager::start() { 133 if ((mUeventHandler = setupSocket(&mUeventSock, NETLINK_KOBJECT_UEVENT, 134 0xffffffff, NetlinkListener::NETLINK_FORMAT_ASCII, false)) == NULL) { 135 return -1; 136 } 137 138 if ((mRouteHandler = setupSocket(&mRouteSock, NETLINK_ROUTE, 139 RTMGRP_LINK | 140 RTMGRP_IPV4_IFADDR | 141 RTMGRP_IPV6_IFADDR | 142 RTMGRP_IPV6_ROUTE | 143 (1 << (RTNLGRP_ND_USEROPT - 1)), 144 NetlinkListener::NETLINK_FORMAT_BINARY, false)) == NULL) { 145 return -1; 146 } 147 148 if ((mQuotaHandler = setupSocket(&mQuotaSock, NETLINK_NFLOG, 149 NFLOG_QUOTA_GROUP, NetlinkListener::NETLINK_FORMAT_BINARY, false)) == NULL) { 150 ALOGW("Unable to open qlog quota socket, check if xt_quota2 can send via UeventHandler"); 151 // TODO: return -1 once the emulator gets a new kernel. 152 } 153 154 if ((mStrictHandler = setupSocket(&mStrictSock, NETLINK_NETFILTER, 155 0, NetlinkListener::NETLINK_FORMAT_BINARY_UNICAST, true)) == NULL) { 156 ALOGE("Unable to open strict socket"); 157 // TODO: return -1 once the emulator gets a new kernel. 158 } 159 160 return 0; 161} 162 163int NetlinkManager::stop() { 164 int status = 0; 165 166 if (mUeventHandler->stop()) { 167 ALOGE("Unable to stop uevent NetlinkHandler: %s", strerror(errno)); 168 status = -1; 169 } 170 171 delete mUeventHandler; 172 mUeventHandler = NULL; 173 174 close(mUeventSock); 175 mUeventSock = -1; 176 177 if (mRouteHandler->stop()) { 178 ALOGE("Unable to stop route NetlinkHandler: %s", strerror(errno)); 179 status = -1; 180 } 181 182 delete mRouteHandler; 183 mRouteHandler = NULL; 184 185 close(mRouteSock); 186 mRouteSock = -1; 187 188 if (mQuotaHandler) { 189 if (mQuotaHandler->stop()) { 190 ALOGE("Unable to stop quota NetlinkHandler: %s", strerror(errno)); 191 status = -1; 192 } 193 194 delete mQuotaHandler; 195 mQuotaHandler = NULL; 196 197 close(mQuotaSock); 198 mQuotaSock = -1; 199 } 200 201 if (mStrictHandler) { 202 if (mStrictHandler->stop()) { 203 ALOGE("Unable to stop strict NetlinkHandler: %s", strerror(errno)); 204 status = -1; 205 } 206 207 delete mStrictHandler; 208 mStrictHandler = NULL; 209 210 close(mStrictSock); 211 mStrictSock = -1; 212 } 213 214 return status; 215} 216 217} // namespace net 218} // namespace android 219