NetlinkManager.cpp revision 564df4efc87f3d04c3570836d38134fd949c4caf
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 36NetlinkManager *NetlinkManager::sInstance = NULL; 37 38NetlinkManager *NetlinkManager::Instance() { 39 if (!sInstance) 40 sInstance = new NetlinkManager(); 41 return sInstance; 42} 43 44NetlinkManager::NetlinkManager() { 45 mBroadcaster = NULL; 46} 47 48NetlinkManager::~NetlinkManager() { 49} 50 51NetlinkHandler *NetlinkManager::setupSocket(int *sock, int socketType, 52 int groups, int format) { 53 54 struct sockaddr_nl nladdr; 55 int sz = 64 * 1024; 56 int on = 1; 57 58 memset(&nladdr, 0, sizeof(nladdr)); 59 nladdr.nl_family = AF_NETLINK; 60 nladdr.nl_pid = getpid(); 61 nladdr.nl_groups = groups; 62 63 if ((*sock = socket(PF_NETLINK, SOCK_DGRAM, socketType)) < 0) { 64 LOGE("Unable to create netlink socket: %s", strerror(errno)); 65 return NULL; 66 } 67 68 if (setsockopt(*sock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) { 69 LOGE("Unable to set uevent socket SO_RCVBUFFORCE option: %s", strerror(errno)); 70 close(*sock); 71 return NULL; 72 } 73 74 if (setsockopt(*sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) { 75 SLOGE("Unable to set uevent socket SO_PASSCRED option: %s", strerror(errno)); 76 close(*sock); 77 return NULL; 78 } 79 80 if (bind(*sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) { 81 LOGE("Unable to bind netlink socket: %s", strerror(errno)); 82 close(*sock); 83 return NULL; 84 } 85 86 NetlinkHandler *handler = new NetlinkHandler(this, *sock, format); 87 if (handler->start()) { 88 LOGE("Unable to start NetlinkHandler: %s", strerror(errno)); 89 close(*sock); 90 return NULL; 91 } 92 93 return handler; 94} 95 96int NetlinkManager::start() { 97 if ((mUeventHandler = setupSocket(&mUeventSock, NETLINK_KOBJECT_UEVENT, 98 0xffffffff, NetlinkListener::NETLINK_FORMAT_ASCII)) == NULL) { 99 return -1; 100 } 101 102 if ((mRouteHandler = setupSocket(&mRouteSock, NETLINK_ROUTE, RTMGRP_LINK, 103 NetlinkListener::NETLINK_FORMAT_BINARY)) == NULL) { 104 return -1; 105 } 106 return 0; 107} 108 109int NetlinkManager::stop() { 110 int status = 0; 111 112 if (mUeventHandler->stop()) { 113 LOGE("Unable to stop uevent NetlinkHandler: %s", strerror(errno)); 114 status = -1; 115 } 116 117 delete mUeventHandler; 118 mUeventHandler = NULL; 119 120 close(mUeventSock); 121 mUeventSock = -1; 122 123 if (mRouteHandler->stop()) { 124 LOGE("Unable to stop route NetlinkHandler: %s", strerror(errno)); 125 status = -1; 126 } 127 128 delete mRouteHandler; 129 mRouteHandler = NULL; 130 131 close(mRouteSock); 132 mRouteSock = -1; 133 134 return status; 135} 136