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 33 static const char *kUpdated = "updated"; 34 static const char *kRemoved = "removed"; 35 36 NetlinkHandler::NetlinkHandler(NetlinkManager *nm, int listenerSocket, 37 int format) : 38 NetlinkListener(listenerSocket, format) { 39 mNm = nm; 40 } 41 42 NetlinkHandler::~NetlinkHandler() { 43 } 44 45 int NetlinkHandler::start() { 46 return this->startListener(); 47 } 48 49 int NetlinkHandler::stop() { 50 return this->stopListener(); 51 } 52 53 void 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 127 void 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 140 void NetlinkHandler::notifyInterfaceAdded(const char *name) { 141 notify(ResponseCode::InterfaceChange, "Iface added %s", name); 142 } 143 144 void NetlinkHandler::notifyInterfaceRemoved(const char *name) { 145 notify(ResponseCode::InterfaceChange, "Iface removed %s", name); 146 } 147 148 void NetlinkHandler::notifyInterfaceChanged(const char *name, bool isUp) { 149 notify(ResponseCode::InterfaceChange, 150 "Iface changed %s %s", name, (isUp ? "up" : "down")); 151 } 152 153 void NetlinkHandler::notifyInterfaceLinkChanged(const char *name, bool isUp) { 154 notify(ResponseCode::InterfaceChange, 155 "Iface linkstate %s %s", name, (isUp ? "up" : "down")); 156 } 157 158 void NetlinkHandler::notifyQuotaLimitReached(const char *name, const char *iface) { 159 notify(ResponseCode::BandwidthControl, "limit alert %s %s", name, iface); 160 } 161 162 void 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 172 void 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 181 void 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 188 void 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