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