2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #define LOG_TAG "Netd"
25 #include <cutils/log.h>
27 #include <netutils/ifc.h>
28 #include <sysutils/NetlinkEvent.h>
29 #include "NetlinkHandler.h"
30 #include "NetlinkManager.h"
31 #include "ResponseCode.h"
33 static const char *kUpdated = "updated";
34 static const char *kRemoved = "removed";
36 NetlinkHandler::NetlinkHandler(NetlinkManager *nm, int listenerSocket,
38 NetlinkListener(listenerSocket, format) {
42 NetlinkHandler::~NetlinkHandler() {
45 int NetlinkHandler::start() {
46 return this->startListener();
49 int NetlinkHandler::stop() {
50 return this->stopListener();
53 void NetlinkHandler::onEvent(NetlinkEvent *evt) {
54 const char *subsys = evt->getSubsystem();
56 ALOGW("No subsystem found in netlink event");
60 if (!strcmp(subsys, "net")) {
61 int action = evt->getAction();
62 const char *iface = evt->findParam("INTERFACE");
64 if (action == evt->NlActionAdd) {
65 notifyInterfaceAdded(iface);
66 } else if (action == evt->NlActionRemove) {
67 notifyInterfaceRemoved(iface);
68 } else if (action == evt->NlActionChange) {
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));
88 if (iface && flags && scope) {
89 notifyAddressChanged(action, address, iface, flags, scope);
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);
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);
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);
112 } else if (!strcmp(subsys, "strict")) {
113 const char *uid = evt->findParam("UID");
114 const char *hex = evt->findParam("HEX");
115 notifyStrictCleartext(uid, hex);
117 } else if (!strcmp(subsys, "xt_idletimer")) {
118 const char *label = evt->findParam("INTERFACE");
119 const char *state = evt->findParam("STATE");
120 const char *timestamp = evt->findParam("TIME_NS");
122 notifyInterfaceClassActivity(label, !strcmp("active", state), timestamp);
125 } else if (strcmp(subsys, "platform") && strcmp(subsys, "backlight")) {
126 /* It is not a VSYNC or a backlight event */
127 ALOGV("unexpected event from subsystem %s", subsys);
132 void NetlinkHandler::notify(int code, const char *format, ...) {
135 va_start(args, format);
136 if (vasprintf(&msg, format, args) >= 0) {
137 mNm->getBroadcaster()->sendBroadcast(code, msg, false);
140 SLOGE("Failed to send notification: vasprintf: %s", strerror(errno));
145 void NetlinkHandler::notifyInterfaceAdded(const char *name) {
146 notify(ResponseCode::InterfaceChange, "Iface added %s", name);
149 void NetlinkHandler::notifyInterfaceRemoved(const char *name) {
150 notify(ResponseCode::InterfaceChange, "Iface removed %s", name);
153 void NetlinkHandler::notifyInterfaceChanged(const char *name, bool isUp) {
154 notify(ResponseCode::InterfaceChange,
155 "Iface changed %s %s", name, (isUp ? "up" : "down"));
158 void NetlinkHandler::notifyInterfaceLinkChanged(const char *name, bool isUp) {
159 notify(ResponseCode::InterfaceChange,
160 "Iface linkstate %s %s", name, (isUp ? "up" : "down"));
163 void NetlinkHandler::notifyQuotaLimitReached(const char *name, const char *iface) {
164 notify(ResponseCode::BandwidthControl, "limit alert %s %s", name, iface);
167 void NetlinkHandler::notifyInterfaceClassActivity(const char *name,
168 bool isActive, const char *timestamp) {
169 if (timestamp == NULL)
170 notify(ResponseCode::InterfaceClassActivity,
171 "IfaceClass %s %s", isActive ? "active" : "idle", name);
173 notify(ResponseCode::InterfaceClassActivity,
174 "IfaceClass %s %s %s", isActive ? "active" : "idle", name, timestamp);
177 void NetlinkHandler::notifyAddressChanged(int action, const char *addr,
178 const char *iface, const char *flags,
180 notify(ResponseCode::InterfaceAddressChange,
181 "Address %s %s %s %s %s",
182 (action == NetlinkEvent::NlActionAddressUpdated) ? kUpdated : kRemoved,
183 addr, iface, flags, scope);
186 void NetlinkHandler::notifyInterfaceDnsServers(const char *iface,
187 const char *lifetime,
188 const char *servers) {
189 notify(ResponseCode::InterfaceDnsInfo, "DnsInfo servers %s %s %s",
190 iface, lifetime, servers);
193 void NetlinkHandler::notifyRouteChange(int action, const char *route,
194 const char *gateway, const char *iface) {
195 notify(ResponseCode::RouteChange,
196 "Route %s %s%s%s%s%s",
197 (action == NetlinkEvent::NlActionRouteUpdated) ? kUpdated : kRemoved,
199 *gateway ? " via " : "",
201 *iface ? " dev " : "",
205 void NetlinkHandler::notifyStrictCleartext(const char* uid, const char* hex) {
206 notify(ResponseCode::StrictCleartext, "%s %s", uid, hex);