1d18304287dbabc7835be771400b85d4ae8b63de6San Mehat/* 2d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * Copyright (C) 2008 The Android Open Source Project 3d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * 4d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * Licensed under the Apache License, Version 2.0 (the "License"); 5d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * you may not use this file except in compliance with the License. 6d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * You may obtain a copy of the License at 7d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * 8d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * http://www.apache.org/licenses/LICENSE-2.0 9d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * 10d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * Unless required by applicable law or agreed to in writing, software 11d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * distributed under the License is distributed on an "AS IS" BASIS, 12d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * See the License for the specific language governing permissions and 14d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * limitations under the License. 15d18304287dbabc7835be771400b85d4ae8b63de6San Mehat */ 16d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 17d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <stdio.h> 18d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <errno.h> 19d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 20d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sys/socket.h> 21d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sys/select.h> 22d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sys/time.h> 23d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sys/types.h> 24d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sys/un.h> 25d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 26d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <linux/netlink.h> 27564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen#include <linux/rtnetlink.h> 28d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 29d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#define LOG_TAG "Netd" 30d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 31d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <cutils/log.h> 32d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 33d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include "NetlinkManager.h" 34d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include "NetlinkHandler.h" 35d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 36e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrallconst int NetlinkManager::NFLOG_QUOTA_GROUP = 1; 37e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrall 38d18304287dbabc7835be771400b85d4ae8b63de6San MehatNetlinkManager *NetlinkManager::sInstance = NULL; 39d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 40d18304287dbabc7835be771400b85d4ae8b63de6San MehatNetlinkManager *NetlinkManager::Instance() { 41d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (!sInstance) 42d18304287dbabc7835be771400b85d4ae8b63de6San Mehat sInstance = new NetlinkManager(); 43d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return sInstance; 44d18304287dbabc7835be771400b85d4ae8b63de6San Mehat} 45d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 46d18304287dbabc7835be771400b85d4ae8b63de6San MehatNetlinkManager::NetlinkManager() { 47d18304287dbabc7835be771400b85d4ae8b63de6San Mehat mBroadcaster = NULL; 48d18304287dbabc7835be771400b85d4ae8b63de6San Mehat} 49d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 50d18304287dbabc7835be771400b85d4ae8b63de6San MehatNetlinkManager::~NetlinkManager() { 51d18304287dbabc7835be771400b85d4ae8b63de6San Mehat} 52d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 53e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP AbgrallNetlinkHandler *NetlinkManager::setupSocket(int *sock, int netlinkFamily, 54564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen int groups, int format) { 55564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen 56d18304287dbabc7835be771400b85d4ae8b63de6San Mehat struct sockaddr_nl nladdr; 57d18304287dbabc7835be771400b85d4ae8b63de6San Mehat int sz = 64 * 1024; 5879b579c92afc08ab12c0a5788d61f2dd2934836fNick Kralevich int on = 1; 59d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 60d18304287dbabc7835be771400b85d4ae8b63de6San Mehat memset(&nladdr, 0, sizeof(nladdr)); 61d18304287dbabc7835be771400b85d4ae8b63de6San Mehat nladdr.nl_family = AF_NETLINK; 62d18304287dbabc7835be771400b85d4ae8b63de6San Mehat nladdr.nl_pid = getpid(); 63564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen nladdr.nl_groups = groups; 64d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 65e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrall if ((*sock = socket(PF_NETLINK, SOCK_DGRAM, netlinkFamily)) < 0) { 66564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen LOGE("Unable to create netlink socket: %s", strerror(errno)); 67564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen return NULL; 68d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 69d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 70564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen if (setsockopt(*sock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) { 7179b579c92afc08ab12c0a5788d61f2dd2934836fNick Kralevich LOGE("Unable to set uevent socket SO_RCVBUFFORCE option: %s", strerror(errno)); 72564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen close(*sock); 73564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen return NULL; 7479b579c92afc08ab12c0a5788d61f2dd2934836fNick Kralevich } 7579b579c92afc08ab12c0a5788d61f2dd2934836fNick Kralevich 76564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen if (setsockopt(*sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) { 7779b579c92afc08ab12c0a5788d61f2dd2934836fNick Kralevich SLOGE("Unable to set uevent socket SO_PASSCRED option: %s", strerror(errno)); 78564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen close(*sock); 79564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen return NULL; 80d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 81d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 82564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen if (bind(*sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) { 83564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen LOGE("Unable to bind netlink socket: %s", strerror(errno)); 84564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen close(*sock); 85564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen return NULL; 86d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 87d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 88564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen NetlinkHandler *handler = new NetlinkHandler(this, *sock, format); 89564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen if (handler->start()) { 90d18304287dbabc7835be771400b85d4ae8b63de6San Mehat LOGE("Unable to start NetlinkHandler: %s", strerror(errno)); 91564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen close(*sock); 92564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen return NULL; 93564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen } 94564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen 95564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen return handler; 96564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen} 97564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen 98564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chenint NetlinkManager::start() { 99564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen if ((mUeventHandler = setupSocket(&mUeventSock, NETLINK_KOBJECT_UEVENT, 100564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen 0xffffffff, NetlinkListener::NETLINK_FORMAT_ASCII)) == NULL) { 101564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen return -1; 102564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen } 103564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen 104564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen if ((mRouteHandler = setupSocket(&mRouteSock, NETLINK_ROUTE, RTMGRP_LINK, 105564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen NetlinkListener::NETLINK_FORMAT_BINARY)) == NULL) { 106d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return -1; 107d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 108e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrall 109e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrall if ((mQuotaHandler = setupSocket(&mQuotaSock, NETLINK_NFLOG, 110e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrall NFLOG_QUOTA_GROUP, NetlinkListener::NETLINK_FORMAT_BINARY)) == NULL) { 111e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrall LOGE("Unable to open quota2 logging socket"); 1128a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall // TODO: return -1 once the emulator gets a new kernel. 113e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrall } 114d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return 0; 115d18304287dbabc7835be771400b85d4ae8b63de6San Mehat} 116d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 117d18304287dbabc7835be771400b85d4ae8b63de6San Mehatint NetlinkManager::stop() { 118564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen int status = 0; 119564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen 120564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen if (mUeventHandler->stop()) { 121564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen LOGE("Unable to stop uevent NetlinkHandler: %s", strerror(errno)); 122564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen status = -1; 123d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 124d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 125564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen delete mUeventHandler; 126564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen mUeventHandler = NULL; 127d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 128564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen close(mUeventSock); 129564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen mUeventSock = -1; 130564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen 131564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen if (mRouteHandler->stop()) { 132564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen LOGE("Unable to stop route NetlinkHandler: %s", strerror(errno)); 133564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen status = -1; 134564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen } 135564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen 136564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen delete mRouteHandler; 137564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen mRouteHandler = NULL; 138564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen 139564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen close(mRouteSock); 140564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen mRouteSock = -1; 141564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen 1428a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall if (mQuotaHandler) { 1438a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall if (mQuotaHandler->stop()) { 1448a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall LOGE("Unable to stop quota NetlinkHandler: %s", strerror(errno)); 1458a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall status = -1; 1468a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall } 147e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrall 1488a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall delete mQuotaHandler; 1498a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall mQuotaHandler = NULL; 150e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrall 1518a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall close(mQuotaSock); 1528a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall mQuotaSock = -1; 1538a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall } 154564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen return status; 155d18304287dbabc7835be771400b85d4ae8b63de6San Mehat} 156