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 49 const int NetlinkManager::NFLOG_QUOTA_GROUP = 1; 50 const int NetlinkManager::NETFILTER_STRICT_GROUP = 2; 51 52 NetlinkManager *NetlinkManager::sInstance = NULL; 53 54 NetlinkManager *NetlinkManager::Instance() { 55 if (!sInstance) 56 sInstance = new NetlinkManager(); 57 return sInstance; 58 } 59 60 NetlinkManager::NetlinkManager() { 61 mBroadcaster = NULL; 62 } 63 64 NetlinkManager::~NetlinkManager() { 65 } 66 67 NetlinkHandler *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 nladdr.nl_pid = getpid(); 77 nladdr.nl_groups = groups; 78 79 if ((*sock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, netlinkFamily)) < 0) { 80 ALOGE("Unable to create netlink socket: %s", strerror(errno)); 81 return NULL; 82 } 83 84 if (setsockopt(*sock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) { 85 ALOGE("Unable to set uevent socket SO_RCVBUFFORCE option: %s", strerror(errno)); 86 close(*sock); 87 return NULL; 88 } 89 90 if (setsockopt(*sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) { 91 SLOGE("Unable to set uevent socket SO_PASSCRED option: %s", strerror(errno)); 92 close(*sock); 93 return NULL; 94 } 95 96 if (bind(*sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) { 97 ALOGE("Unable to bind netlink socket: %s", strerror(errno)); 98 close(*sock); 99 return NULL; 100 } 101 102 if (configNflog) { 103 if (android_nflog_send_config_cmd(*sock, 0, NFULNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) { 104 ALOGE("Failed NFULNL_CFG_CMD_PF_UNBIND: %s", strerror(errno)); 105 return NULL; 106 } 107 if (android_nflog_send_config_cmd(*sock, 0, NFULNL_CFG_CMD_PF_BIND, AF_INET) < 0) { 108 ALOGE("Failed NFULNL_CFG_CMD_PF_BIND: %s", strerror(errno)); 109 return NULL; 110 } 111 if (android_nflog_send_config_cmd(*sock, 0, NFULNL_CFG_CMD_BIND, AF_UNSPEC) < 0) { 112 ALOGE("Failed NFULNL_CFG_CMD_BIND: %s", strerror(errno)); 113 return NULL; 114 } 115 } 116 117 NetlinkHandler *handler = new NetlinkHandler(this, *sock, format); 118 if (handler->start()) { 119 ALOGE("Unable to start NetlinkHandler: %s", strerror(errno)); 120 close(*sock); 121 return NULL; 122 } 123 124 return handler; 125 } 126 127 int NetlinkManager::start() { 128 if ((mUeventHandler = setupSocket(&mUeventSock, NETLINK_KOBJECT_UEVENT, 129 0xffffffff, NetlinkListener::NETLINK_FORMAT_ASCII, false)) == NULL) { 130 return -1; 131 } 132 133 if ((mRouteHandler = setupSocket(&mRouteSock, NETLINK_ROUTE, 134 RTMGRP_LINK | 135 RTMGRP_IPV4_IFADDR | 136 RTMGRP_IPV6_IFADDR | 137 RTMGRP_IPV6_ROUTE | 138 (1 << (RTNLGRP_ND_USEROPT - 1)), 139 NetlinkListener::NETLINK_FORMAT_BINARY, false)) == NULL) { 140 return -1; 141 } 142 143 if ((mQuotaHandler = setupSocket(&mQuotaSock, NETLINK_NFLOG, 144 NFLOG_QUOTA_GROUP, NetlinkListener::NETLINK_FORMAT_BINARY, false)) == NULL) { 145 ALOGW("Unable to open qlog quota socket, check if xt_quota2 can send via UeventHandler"); 146 // TODO: return -1 once the emulator gets a new kernel. 147 } 148 149 if ((mStrictHandler = setupSocket(&mStrictSock, NETLINK_NETFILTER, 150 0, NetlinkListener::NETLINK_FORMAT_BINARY_UNICAST, true)) == NULL) { 151 ALOGE("Unable to open strict socket"); 152 // TODO: return -1 once the emulator gets a new kernel. 153 } 154 155 return 0; 156 } 157 158 int NetlinkManager::stop() { 159 int status = 0; 160 161 if (mUeventHandler->stop()) { 162 ALOGE("Unable to stop uevent NetlinkHandler: %s", strerror(errno)); 163 status = -1; 164 } 165 166 delete mUeventHandler; 167 mUeventHandler = NULL; 168 169 close(mUeventSock); 170 mUeventSock = -1; 171 172 if (mRouteHandler->stop()) { 173 ALOGE("Unable to stop route NetlinkHandler: %s", strerror(errno)); 174 status = -1; 175 } 176 177 delete mRouteHandler; 178 mRouteHandler = NULL; 179 180 close(mRouteSock); 181 mRouteSock = -1; 182 183 if (mQuotaHandler) { 184 if (mQuotaHandler->stop()) { 185 ALOGE("Unable to stop quota NetlinkHandler: %s", strerror(errno)); 186 status = -1; 187 } 188 189 delete mQuotaHandler; 190 mQuotaHandler = NULL; 191 192 close(mQuotaSock); 193 mQuotaSock = -1; 194 } 195 196 if (mStrictHandler) { 197 if (mStrictHandler->stop()) { 198 ALOGE("Unable to stop strict NetlinkHandler: %s", strerror(errno)); 199 status = -1; 200 } 201 202 delete mStrictHandler; 203 mStrictHandler = NULL; 204 205 close(mStrictSock); 206 mStrictSock = -1; 207 } 208 209 return status; 210 } 211