NetlinkManager.cpp revision 6337b88ce4438d224819e9b381ddaf2873bbfdda
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 "NetlinkManager.h" 34#include "NetlinkHandler.h" 35 36const int NetlinkManager::NFLOG_QUOTA_GROUP = 1; 37const int NetlinkManager::IDLETIMER_GROUP = 1; 38 39NetlinkManager *NetlinkManager::sInstance = NULL; 40 41NetlinkManager *NetlinkManager::Instance() { 42 if (!sInstance) 43 sInstance = new NetlinkManager(); 44 return sInstance; 45} 46 47NetlinkManager::NetlinkManager() { 48 mBroadcaster = NULL; 49} 50 51NetlinkManager::~NetlinkManager() { 52} 53 54NetlinkHandler *NetlinkManager::setupSocket(int *sock, int netlinkFamily, 55 int groups, int format) { 56 57 struct sockaddr_nl nladdr; 58 int sz = 64 * 1024; 59 int on = 1; 60 61 memset(&nladdr, 0, sizeof(nladdr)); 62 nladdr.nl_family = AF_NETLINK; 63 nladdr.nl_pid = getpid(); 64 nladdr.nl_groups = groups; 65 66 if ((*sock = socket(PF_NETLINK, SOCK_DGRAM, netlinkFamily)) < 0) { 67 ALOGE("Unable to create netlink socket: %s", strerror(errno)); 68 return NULL; 69 } 70 71 if (setsockopt(*sock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) { 72 ALOGE("Unable to set uevent socket SO_RCVBUFFORCE option: %s", strerror(errno)); 73 close(*sock); 74 return NULL; 75 } 76 77 if (setsockopt(*sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) { 78 SLOGE("Unable to set uevent socket SO_PASSCRED option: %s", strerror(errno)); 79 close(*sock); 80 return NULL; 81 } 82 83 if (bind(*sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) { 84 ALOGE("Unable to bind netlink socket: %s", strerror(errno)); 85 close(*sock); 86 return NULL; 87 } 88 89 NetlinkHandler *handler = new NetlinkHandler(this, *sock, format); 90 if (handler->start()) { 91 ALOGE("Unable to start NetlinkHandler: %s", strerror(errno)); 92 close(*sock); 93 return NULL; 94 } 95 96 return handler; 97} 98 99int NetlinkManager::start() { 100 if ((mUeventHandler = setupSocket(&mUeventSock, NETLINK_KOBJECT_UEVENT, 101 0xffffffff, NetlinkListener::NETLINK_FORMAT_ASCII)) == NULL) { 102 return -1; 103 } 104 105 if ((mRouteHandler = setupSocket(&mRouteSock, NETLINK_ROUTE, RTMGRP_LINK, 106 NetlinkListener::NETLINK_FORMAT_BINARY)) == NULL) { 107 return -1; 108 } 109 110 if ((mQuotaHandler = setupSocket(&mQuotaSock, NETLINK_NFLOG, 111 NFLOG_QUOTA_GROUP, NetlinkListener::NETLINK_FORMAT_BINARY)) == NULL) { 112 ALOGE("Unable to open quota2 logging socket"); 113 // TODO: return -1 once the emulator gets a new kernel. 114 } 115 116 if ((mIfaceIdleTimerHandler = setupSocket(&mIfaceIdleTimerSock, NETLINK_IDLETIMER, 117 IDLETIMER_GROUP, NetlinkListener::NETLINK_FORMAT_BINARY)) == NULL) { 118 // TODO: switch back to using NETLINK_NFLOG with a custom type. 119 ALOGE("Unable to open iface idletimer socket"); 120 } 121 return 0; 122} 123 124int NetlinkManager::stop() { 125 int status = 0; 126 127 if (mUeventHandler->stop()) { 128 ALOGE("Unable to stop uevent NetlinkHandler: %s", strerror(errno)); 129 status = -1; 130 } 131 132 delete mUeventHandler; 133 mUeventHandler = NULL; 134 135 close(mUeventSock); 136 mUeventSock = -1; 137 138 if (mRouteHandler->stop()) { 139 ALOGE("Unable to stop route NetlinkHandler: %s", strerror(errno)); 140 status = -1; 141 } 142 143 delete mRouteHandler; 144 mRouteHandler = NULL; 145 146 close(mRouteSock); 147 mRouteSock = -1; 148 149 if (mQuotaHandler) { 150 if (mQuotaHandler->stop()) { 151 ALOGE("Unable to stop quota NetlinkHandler: %s", strerror(errno)); 152 status = -1; 153 } 154 155 delete mQuotaHandler; 156 mQuotaHandler = NULL; 157 158 close(mQuotaSock); 159 mQuotaSock = -1; 160 } 161 162 if (mIfaceIdleTimerHandler) { 163 if (mIfaceIdleTimerHandler->stop()) { 164 ALOGE("Unable to stop iface IDLETIMER NetlinkHandler: %s", strerror(errno)); 165 status = -1; 166 } 167 168 delete mIfaceIdleTimerHandler; 169 mIfaceIdleTimerHandler = NULL; 170 171 close(mIfaceIdleTimerSock); 172 mIfaceIdleTimerSock = -1; 173 } 174 175 return status; 176} 177