Merge changes I255cca69,Ice9ec7f0,I4e97ac98
* changes:
Workaround Motorola ril.so incompatiblity with Netlink changes
Cleanup NetlinkListener and NetlinkEvent
Revert "Revert "Add NETLINK_ROUTE processing to the netlink client code, so that Ethernet""
diff --git a/include/sysutils/NetlinkEvent.h b/include/sysutils/NetlinkEvent.h
index b329b09..25a56f7 100644
--- a/include/sysutils/NetlinkEvent.h
+++ b/include/sysutils/NetlinkEvent.h
@@ -16,6 +16,8 @@
#ifndef _NETLINKEVENT_H
#define _NETLINKEVENT_H
+#include <sysutils/NetlinkListener.h>
+
#define NL_PARAMS_MAX 32
class NetlinkEvent {
@@ -30,17 +32,23 @@
const static int NlActionAdd;
const static int NlActionRemove;
const static int NlActionChange;
+ const static int NlActionLinkDown;
+ const static int NlActionLinkUp;
NetlinkEvent();
virtual ~NetlinkEvent();
- bool decode(char *buffer, int size);
+ bool decode(char *buffer, int size, int format = NetlinkListener::NETLINK_FORMAT_ASCII);
const char *findParam(const char *paramName);
const char *getSubsystem() { return mSubsystem; }
int getAction() { return mAction; }
void dump();
+
+ protected:
+ bool parseBinaryNetlinkMessage(char *buffer, int size);
+ bool parseAsciiNetlinkMessage(char *buffer, int size);
};
#endif
diff --git a/include/sysutils/NetlinkListener.h b/include/sysutils/NetlinkListener.h
index 2880046..beb8bda 100644
--- a/include/sysutils/NetlinkListener.h
+++ b/include/sysutils/NetlinkListener.h
@@ -22,13 +22,27 @@
class NetlinkListener : public SocketListener {
char mBuffer[64 * 1024];
+ int mFormat;
public:
+ static const int NETLINK_FORMAT_ASCII = 0;
+ static const int NETLINK_FORMAT_BINARY = 1;
+
+#if 1
+ /* temporary version until we can get Motorola to update their
+ * ril.so. Their prebuilt ril.so is using this private class
+ * so changing the NetlinkListener() constructor breaks their ril.
+ */
NetlinkListener(int socket);
+ NetlinkListener(int socket, int format);
+#else
+ NetlinkListener(int socket, int format = NETLINK_FORMAT_ASCII);
+#endif
virtual ~NetlinkListener() {}
protected:
virtual bool onDataAvailable(SocketClient *cli);
virtual void onEvent(NetlinkEvent *evt) = 0;
};
+
#endif
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index c8d3b1f..f2eb664 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -21,10 +21,17 @@
#include <sysutils/NetlinkEvent.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <linux/rtnetlink.h>
+#include <linux/if.h>
+
const int NetlinkEvent::NlActionUnknown = 0;
const int NetlinkEvent::NlActionAdd = 1;
const int NetlinkEvent::NlActionRemove = 2;
const int NetlinkEvent::NlActionChange = 3;
+const int NetlinkEvent::NlActionLinkUp = 4;
+const int NetlinkEvent::NlActionLinkDown = 5;
NetlinkEvent::NetlinkEvent() {
mAction = NlActionUnknown;
@@ -56,6 +63,51 @@
}
}
+/*
+ * Parse an binary message from a NETLINK_ROUTE netlink socket.
+ */
+bool NetlinkEvent::parseBinaryNetlinkMessage(char *buffer, int size) {
+ size_t sz = size;
+ const struct nlmsghdr *nh = (struct nlmsghdr *) buffer;
+
+ while (NLMSG_OK(nh, sz) && (nh->nlmsg_type != NLMSG_DONE)) {
+ if (nh->nlmsg_type == RTM_NEWLINK) {
+ int len = nh->nlmsg_len - sizeof(*nh);
+ struct ifinfomsg *ifi;
+
+ if (sizeof(*ifi) <= (size_t) len) {
+ ifi = (ifinfomsg *)NLMSG_DATA(nh);
+
+ if ((ifi->ifi_flags & IFF_LOOPBACK) == 0) {
+ struct rtattr *rta = (struct rtattr *)
+ ((char *) ifi + NLMSG_ALIGN(sizeof(*ifi)));
+ len = NLMSG_PAYLOAD(nh, sizeof(*ifi));
+
+ while(RTA_OK(rta, len)) {
+ switch(rta->rta_type) {
+ case IFLA_IFNAME:
+ char buffer[16 + IFNAMSIZ];
+ snprintf(buffer, sizeof(buffer), "INTERFACE=%s",
+ (char *) RTA_DATA(rta));
+ mParams[0] = strdup(buffer);
+ mAction = (ifi->ifi_flags & IFF_LOWER_UP) ?
+ NlActionLinkUp : NlActionLinkDown;
+ mSubsystem = strdup("net");
+ break;
+ }
+
+ rta = RTA_NEXT(rta, len);
+ }
+ }
+ }
+ }
+
+ nh = NLMSG_NEXT(nh, size);
+ }
+
+ return true;
+}
+
/* If the string between 'str' and 'end' begins with 'prefixlen' characters
* from the 'prefix' array, then return 'str + prefixlen', otherwise return
* NULL.
@@ -76,7 +128,11 @@
#define HAS_CONST_PREFIX(str,end,prefix) has_prefix((str),(end),prefix,CONST_STRLEN(prefix))
-bool NetlinkEvent::decode(char *buffer, int size) {
+/*
+ * Parse an ASCII-formatted message from a NETLINK_KOBJECT_UEVENT
+ * netlink socket.
+ */
+bool NetlinkEvent::parseAsciiNetlinkMessage(char *buffer, int size) {
const char *s = buffer;
const char *end;
int param_idx = 0;
@@ -123,6 +179,14 @@
return true;
}
+bool NetlinkEvent::decode(char *buffer, int size, int format) {
+ if (format == NetlinkListener::NETLINK_FORMAT_BINARY) {
+ return parseBinaryNetlinkMessage(buffer, size);
+ } else {
+ return parseAsciiNetlinkMessage(buffer, size);
+ }
+}
+
const char *NetlinkEvent::findParam(const char *paramName) {
size_t len = strlen(paramName);
for (int i = 0; i < NL_PARAMS_MAX && mParams[i] != NULL; ++i) {
diff --git a/libsysutils/src/NetlinkListener.cpp b/libsysutils/src/NetlinkListener.cpp
index adea077..e67b5c6 100644
--- a/libsysutils/src/NetlinkListener.cpp
+++ b/libsysutils/src/NetlinkListener.cpp
@@ -24,11 +24,21 @@
#include <cutils/log.h>
#include <cutils/uevent.h>
-#include <sysutils/NetlinkListener.h>
#include <sysutils/NetlinkEvent.h>
+#if 1
+/* temporary version until we can get Motorola to update their
+ * ril.so. Their prebuilt ril.so is using this private class
+ * so changing the NetlinkListener() constructor breaks their ril.
+ */
NetlinkListener::NetlinkListener(int socket) :
SocketListener(socket, false) {
+ mFormat = NETLINK_FORMAT_ASCII;
+}
+#endif
+
+NetlinkListener::NetlinkListener(int socket, int format) :
+ SocketListener(socket, false), mFormat(format) {
}
bool NetlinkListener::onDataAvailable(SocketClient *cli)
@@ -43,13 +53,12 @@
}
NetlinkEvent *evt = new NetlinkEvent();
- if (!evt->decode(mBuffer, count)) {
+ if (!evt->decode(mBuffer, count, mFormat)) {
SLOGE("Error decoding NetlinkEvent");
- goto out;
+ } else {
+ onEvent(evt);
}
- onEvent(evt);
-out:
delete evt;
return true;
}