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 <stdio.h> 18#include <errno.h> 19 20#include <sys/socket.h> 21#include <sys/select.h> 22#include <sys/time.h> 23#include <sys/types.h> 24#include <sys/un.h> 25 26#include <linux/netlink.h> 27#include <linux/rtnetlink.h> 28 29#define LOG_TAG "Netd" 30 31#include <cutils/log.h> 32 33#include <netlink/attr.h> 34#include <netlink/genl/genl.h> 35#include <netlink/handlers.h> 36#include <netlink/msg.h> 37 38#include <linux/netfilter/nfnetlink.h> 39#include <linux/netfilter/nfnetlink_log.h> 40#include <linux/netfilter/nfnetlink_compat.h> 41 42#include <arpa/inet.h> 43 44#include "NetlinkManager.h" 45#include "NetlinkHandler.h" 46 47#include "pcap-netfilter-linux-android.h" 48 49namespace android { 50namespace net { 51 52const int NetlinkManager::NFLOG_QUOTA_GROUP = 1; 53const int NetlinkManager::NETFILTER_STRICT_GROUP = 2; 54 55NetlinkManager *NetlinkManager::sInstance = NULL; 56 57NetlinkManager *NetlinkManager::Instance() { 58 if (!sInstance) 59 sInstance = new NetlinkManager(); 60 return sInstance; 61} 62 63NetlinkManager::NetlinkManager() { 64 mBroadcaster = NULL; 65} 66 67NetlinkManager::~NetlinkManager() { 68} 69 70NetlinkHandler *NetlinkManager::setupSocket(int *sock, int netlinkFamily, 71 int groups, int format, bool configNflog) { 72 73 struct sockaddr_nl nladdr; 74 int sz = 64 * 1024; 75 int on = 1; 76 77 memset(&nladdr, 0, sizeof(nladdr)); 78 nladdr.nl_family = AF_NETLINK; 79 nladdr.nl_pid = getpid(); 80 nladdr.nl_groups = groups; 81 82 if ((*sock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, netlinkFamily)) < 0) { 83 ALOGE("Unable to create netlink socket: %s", strerror(errno)); 84 return NULL; 85 } 86 87 if (setsockopt(*sock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) { 88 ALOGE("Unable to set uevent socket SO_RCVBUFFORCE option: %s", strerror(errno)); 89 close(*sock); 90 return NULL; 91 } 92 93 if (setsockopt(*sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) { 94 SLOGE("Unable to set uevent socket SO_PASSCRED option: %s", strerror(errno)); 95 close(*sock); 96 return NULL; 97 } 98 99 if (bind(*sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) { 100 ALOGE("Unable to bind netlink socket: %s", strerror(errno)); 101 close(*sock); 102 return NULL; 103 } 104 105 if (configNflog) { 106 if (android_nflog_send_config_cmd(*sock, 0, NFULNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) { 107 ALOGE("Failed NFULNL_CFG_CMD_PF_UNBIND: %s", strerror(errno)); 108 return NULL; 109 } 110 if (android_nflog_send_config_cmd(*sock, 0, NFULNL_CFG_CMD_PF_BIND, AF_INET) < 0) { 111 ALOGE("Failed NFULNL_CFG_CMD_PF_BIND: %s", strerror(errno)); 112 return NULL; 113 } 114 if (android_nflog_send_config_cmd(*sock, 0, NFULNL_CFG_CMD_BIND, AF_UNSPEC) < 0) { 115 ALOGE("Failed NFULNL_CFG_CMD_BIND: %s", strerror(errno)); 116 return NULL; 117 } 118 } 119 120 NetlinkHandler *handler = new NetlinkHandler(this, *sock, format); 121 if (handler->start()) { 122 ALOGE("Unable to start NetlinkHandler: %s", strerror(errno)); 123 close(*sock); 124 return NULL; 125 } 126 127 return handler; 128} 129 130int NetlinkManager::start() { 131 if ((mUeventHandler = setupSocket(&mUeventSock, NETLINK_KOBJECT_UEVENT, 132 0xffffffff, NetlinkListener::NETLINK_FORMAT_ASCII, false)) == NULL) { 133 return -1; 134 } 135 136 if ((mRouteHandler = setupSocket(&mRouteSock, NETLINK_ROUTE, 137 RTMGRP_LINK | 138 RTMGRP_IPV4_IFADDR | 139 RTMGRP_IPV6_IFADDR | 140 RTMGRP_IPV6_ROUTE | 141 (1 << (RTNLGRP_ND_USEROPT - 1)), 142 NetlinkListener::NETLINK_FORMAT_BINARY, false)) == NULL) { 143 return -1; 144 } 145 146 if ((mQuotaHandler = setupSocket(&mQuotaSock, NETLINK_NFLOG, 147 NFLOG_QUOTA_GROUP, NetlinkListener::NETLINK_FORMAT_BINARY, false)) == NULL) { 148 ALOGW("Unable to open qlog quota socket, check if xt_quota2 can send via UeventHandler"); 149 // TODO: return -1 once the emulator gets a new kernel. 150 } 151 152 if ((mStrictHandler = setupSocket(&mStrictSock, NETLINK_NETFILTER, 153 0, NetlinkListener::NETLINK_FORMAT_BINARY_UNICAST, true)) == NULL) { 154 ALOGE("Unable to open strict socket"); 155 // TODO: return -1 once the emulator gets a new kernel. 156 } 157 158 return 0; 159} 160 161int NetlinkManager::stop() { 162 int status = 0; 163 164 if (mUeventHandler->stop()) { 165 ALOGE("Unable to stop uevent NetlinkHandler: %s", strerror(errno)); 166 status = -1; 167 } 168 169 delete mUeventHandler; 170 mUeventHandler = NULL; 171 172 close(mUeventSock); 173 mUeventSock = -1; 174 175 if (mRouteHandler->stop()) { 176 ALOGE("Unable to stop route NetlinkHandler: %s", strerror(errno)); 177 status = -1; 178 } 179 180 delete mRouteHandler; 181 mRouteHandler = NULL; 182 183 close(mRouteSock); 184 mRouteSock = -1; 185 186 if (mQuotaHandler) { 187 if (mQuotaHandler->stop()) { 188 ALOGE("Unable to stop quota NetlinkHandler: %s", strerror(errno)); 189 status = -1; 190 } 191 192 delete mQuotaHandler; 193 mQuotaHandler = NULL; 194 195 close(mQuotaSock); 196 mQuotaSock = -1; 197 } 198 199 if (mStrictHandler) { 200 if (mStrictHandler->stop()) { 201 ALOGE("Unable to stop strict NetlinkHandler: %s", strerror(errno)); 202 status = -1; 203 } 204 205 delete mStrictHandler; 206 mStrictHandler = NULL; 207 208 close(mStrictSock); 209 mStrictSock = -1; 210 } 211 212 return status; 213} 214 215} // namespace net 216} // namespace android 217