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