Add NETLINK_ROUTE socket creation and event propagation
Change-Id: I8cc8788661640600bceadeba8169e239bba98dec
diff --git a/NetlinkManager.cpp b/NetlinkManager.cpp
index 634fd4d..fabf011 100644
--- a/NetlinkManager.cpp
+++ b/NetlinkManager.cpp
@@ -24,6 +24,7 @@
#include <sys/un.h>
#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
#define LOG_TAG "Netd"
@@ -47,49 +48,81 @@
NetlinkManager::~NetlinkManager() {
}
-int NetlinkManager::start() {
+NetlinkHandler *NetlinkManager::setupSocket(int *sock, int socketType,
+ int groups, int format) {
+
struct sockaddr_nl nladdr;
int sz = 64 * 1024;
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = getpid();
- nladdr.nl_groups = 0xffffffff;
+ nladdr.nl_groups = groups;
- if ((mSock = socket(PF_NETLINK,
- SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) {
- LOGE("Unable to create uevent socket: %s", strerror(errno));
- return -1;
+ if ((*sock = socket(PF_NETLINK, SOCK_DGRAM, socketType)) < 0) {
+ LOGE("Unable to create netlink socket: %s", strerror(errno));
+ return NULL;
}
- if (setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) {
- LOGE("Unable to set uevent socket options: %s", strerror(errno));
- return -1;
+ if (setsockopt(*sock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) {
+ LOGE("Unable to set netlink socket options: %s", strerror(errno));
+ close(*sock);
+ return NULL;
}
- if (bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
- LOGE("Unable to bind uevent socket: %s", strerror(errno));
- return -1;
+ if (bind(*sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
+ LOGE("Unable to bind netlink socket: %s", strerror(errno));
+ close(*sock);
+ return NULL;
}
- mHandler = new NetlinkHandler(this, mSock);
- if (mHandler->start()) {
+ NetlinkHandler *handler = new NetlinkHandler(this, *sock, format);
+ if (handler->start()) {
LOGE("Unable to start NetlinkHandler: %s", strerror(errno));
+ close(*sock);
+ return NULL;
+ }
+
+ return handler;
+}
+
+int NetlinkManager::start() {
+ if ((mUeventHandler = setupSocket(&mUeventSock, NETLINK_KOBJECT_UEVENT,
+ 0xffffffff, NetlinkListener::NETLINK_FORMAT_ASCII)) == NULL) {
+ return -1;
+ }
+
+ if ((mRouteHandler = setupSocket(&mRouteSock, NETLINK_ROUTE, RTMGRP_LINK,
+ NetlinkListener::NETLINK_FORMAT_BINARY)) == NULL) {
return -1;
}
return 0;
}
int NetlinkManager::stop() {
- if (mHandler->stop()) {
- LOGE("Unable to stop NetlinkHandler: %s", strerror(errno));
- return -1;
+ int status = 0;
+
+ if (mUeventHandler->stop()) {
+ LOGE("Unable to stop uevent NetlinkHandler: %s", strerror(errno));
+ status = -1;
}
- delete mHandler;
- mHandler = NULL;
- close(mSock);
- mSock = -1;
+ delete mUeventHandler;
+ mUeventHandler = NULL;
- return 0;
+ close(mUeventSock);
+ mUeventSock = -1;
+
+ if (mRouteHandler->stop()) {
+ LOGE("Unable to stop route NetlinkHandler: %s", strerror(errno));
+ status = -1;
+ }
+
+ delete mRouteHandler;
+ mRouteHandler = NULL;
+
+ close(mRouteSock);
+ mRouteSock = -1;
+
+ return status;
}