NetlinkHandler.cpp revision af37dd3e6f40b9fc5a30ec462a8d2504380a3c9f
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 <stdarg.h> 18#include <stdio.h> 19#include <stdlib.h> 20#include <string.h> 21#include <errno.h> 22 23#define LOG_TAG "Netd" 24 25#include <cutils/log.h> 26 27#include <netutils/ifc.h> 28#include <sysutils/NetlinkEvent.h> 29#include "NetlinkHandler.h" 30#include "NetlinkManager.h" 31#include "ResponseCode.h" 32 33static const char *kUpdated = "updated"; 34static const char *kRemoved = "removed"; 35 36NetlinkHandler::NetlinkHandler(NetlinkManager *nm, int listenerSocket, 37 int format) : 38 NetlinkListener(listenerSocket, format) { 39 mNm = nm; 40} 41 42NetlinkHandler::~NetlinkHandler() { 43} 44 45int NetlinkHandler::start() { 46 return this->startListener(); 47} 48 49int NetlinkHandler::stop() { 50 return this->stopListener(); 51} 52 53void NetlinkHandler::onEvent(NetlinkEvent *evt) { 54 const char *subsys = evt->getSubsystem(); 55 if (!subsys) { 56 ALOGW("No subsystem found in netlink event"); 57 return; 58 } 59 60 if (!strcmp(subsys, "net")) { 61 int action = evt->getAction(); 62 const char *iface = evt->findParam("INTERFACE"); 63 64 if (action == evt->NlActionAdd) { 65 notifyInterfaceAdded(iface); 66 } else if (action == evt->NlActionRemove) { 67 notifyInterfaceRemoved(iface); 68 } else if (action == evt->NlActionChange) { 69 evt->dump(); 70 notifyInterfaceChanged("nana", true); 71 } else if (action == evt->NlActionLinkUp) { 72 notifyInterfaceLinkChanged(iface, true); 73 } else if (action == evt->NlActionLinkDown) { 74 notifyInterfaceLinkChanged(iface, false); 75 } else if (action == evt->NlActionAddressUpdated || 76 action == evt->NlActionAddressRemoved) { 77 const char *address = evt->findParam("ADDRESS"); 78 const char *flags = evt->findParam("FLAGS"); 79 const char *scope = evt->findParam("SCOPE"); 80 if (action == evt->NlActionAddressRemoved && iface && address) { 81 int resetMask = strchr(address, ':') ? RESET_IPV6_ADDRESSES : RESET_IPV4_ADDRESSES; 82 resetMask |= RESET_IGNORE_INTERFACE_ADDRESS; 83 if (int ret = ifc_reset_connections(iface, resetMask)) { 84 ALOGE("ifc_reset_connections failed on iface %s for address %s (%s)", iface, 85 address, strerror(ret)); 86 } 87 } 88 if (iface && flags && scope) { 89 notifyAddressChanged(action, address, iface, flags, scope); 90 } 91 } else if (action == evt->NlActionRdnss) { 92 const char *lifetime = evt->findParam("LIFETIME"); 93 const char *servers = evt->findParam("SERVERS"); 94 if (lifetime && servers) { 95 notifyInterfaceDnsServers(iface, lifetime, servers); 96 } 97 } else if (action == evt->NlActionRouteUpdated || 98 action == evt->NlActionRouteRemoved) { 99 const char *route = evt->findParam("ROUTE"); 100 const char *gateway = evt->findParam("GATEWAY"); 101 const char *iface = evt->findParam("INTERFACE"); 102 if (route && (gateway || iface)) { 103 notifyRouteChange(action, route, gateway, iface); 104 } 105 } 106 107 } else if (!strcmp(subsys, "qlog")) { 108 const char *alertName = evt->findParam("ALERT_NAME"); 109 const char *iface = evt->findParam("INTERFACE"); 110 notifyQuotaLimitReached(alertName, iface); 111 112 } else if (!strcmp(subsys, "xt_idletimer")) { 113 const char *label = evt->findParam("INTERFACE"); 114 const char *state = evt->findParam("STATE"); 115 const char *timestamp = evt->findParam("TIME_NS"); 116 if (state) 117 notifyInterfaceClassActivity(label, !strcmp("active", state), timestamp); 118 119#if !LOG_NDEBUG 120 } else if (strcmp(subsys, "platform") && strcmp(subsys, "backlight")) { 121 /* It is not a VSYNC or a backlight event */ 122 ALOGV("unexpected event from subsystem %s", subsys); 123#endif 124 } 125} 126 127void NetlinkHandler::notify(int code, const char *format, ...) { 128 char *msg; 129 va_list args; 130 va_start(args, format); 131 if (vasprintf(&msg, format, args) >= 0) { 132 mNm->getBroadcaster()->sendBroadcast(code, msg, false); 133 free(msg); 134 } else { 135 SLOGE("Failed to send notification: vasprintf: %s", strerror(errno)); 136 } 137 va_end(args); 138} 139 140void NetlinkHandler::notifyInterfaceAdded(const char *name) { 141 notify(ResponseCode::InterfaceChange, "Iface added %s", name); 142} 143 144void NetlinkHandler::notifyInterfaceRemoved(const char *name) { 145 notify(ResponseCode::InterfaceChange, "Iface removed %s", name); 146} 147 148void NetlinkHandler::notifyInterfaceChanged(const char *name, bool isUp) { 149 notify(ResponseCode::InterfaceChange, 150 "Iface changed %s %s", name, (isUp ? "up" : "down")); 151} 152 153void NetlinkHandler::notifyInterfaceLinkChanged(const char *name, bool isUp) { 154 notify(ResponseCode::InterfaceChange, 155 "Iface linkstate %s %s", name, (isUp ? "up" : "down")); 156} 157 158void NetlinkHandler::notifyQuotaLimitReached(const char *name, const char *iface) { 159 notify(ResponseCode::BandwidthControl, "limit alert %s %s", name, iface); 160} 161 162void NetlinkHandler::notifyInterfaceClassActivity(const char *name, 163 bool isActive, const char *timestamp) { 164 if (timestamp == NULL) 165 notify(ResponseCode::InterfaceClassActivity, 166 "IfaceClass %s %s", isActive ? "active" : "idle", name); 167 else 168 notify(ResponseCode::InterfaceClassActivity, 169 "IfaceClass %s %s %s", isActive ? "active" : "idle", name, timestamp); 170} 171 172void NetlinkHandler::notifyAddressChanged(int action, const char *addr, 173 const char *iface, const char *flags, 174 const char *scope) { 175 notify(ResponseCode::InterfaceAddressChange, 176 "Address %s %s %s %s %s", 177 (action == NetlinkEvent::NlActionAddressUpdated) ? kUpdated : kRemoved, 178 addr, iface, flags, scope); 179} 180 181void NetlinkHandler::notifyInterfaceDnsServers(const char *iface, 182 const char *lifetime, 183 const char *servers) { 184 notify(ResponseCode::InterfaceDnsInfo, "DnsInfo servers %s %s %s", 185 iface, lifetime, servers); 186} 187 188void NetlinkHandler::notifyRouteChange(int action, const char *route, 189 const char *gateway, const char *iface) { 190 notify(ResponseCode::RouteChange, 191 "Route %s %s%s%s%s%s", 192 (action == NetlinkEvent::NlActionRouteUpdated) ? kUpdated : kRemoved, 193 route, 194 *gateway ? " via " : "", 195 gateway, 196 *iface ? " dev " : "", 197 iface); 198} 199