1d18304287dbabc7835be771400b85d4ae8b63de6San Mehat/*
2d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * Copyright (C) 2008 The Android Open Source Project
3d18304287dbabc7835be771400b85d4ae8b63de6San Mehat *
4d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * Licensed under the Apache License, Version 2.0 (the "License");
5d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * you may not use this file except in compliance with the License.
6d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * You may obtain a copy of the License at
7d18304287dbabc7835be771400b85d4ae8b63de6San Mehat *
8d18304287dbabc7835be771400b85d4ae8b63de6San Mehat *      http://www.apache.org/licenses/LICENSE-2.0
9d18304287dbabc7835be771400b85d4ae8b63de6San Mehat *
10d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * Unless required by applicable law or agreed to in writing, software
11d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * distributed under the License is distributed on an "AS IS" BASIS,
12d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * See the License for the specific language governing permissions and
14d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * limitations under the License.
15d18304287dbabc7835be771400b85d4ae8b63de6San Mehat */
16d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
17d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <stdio.h>
18d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <errno.h>
19d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
20d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sys/socket.h>
21d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sys/select.h>
22d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sys/time.h>
23d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sys/types.h>
24d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sys/un.h>
25d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
26d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <linux/netlink.h>
27564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen#include <linux/rtnetlink.h>
28d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
29d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#define LOG_TAG "Netd"
30d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
31d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <cutils/log.h>
32d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
33d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include "NetlinkManager.h"
34d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include "NetlinkHandler.h"
35d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
36e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrallconst int NetlinkManager::NFLOG_QUOTA_GROUP = 1;
37e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrall
38d18304287dbabc7835be771400b85d4ae8b63de6San MehatNetlinkManager *NetlinkManager::sInstance = NULL;
39d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
40d18304287dbabc7835be771400b85d4ae8b63de6San MehatNetlinkManager *NetlinkManager::Instance() {
41d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    if (!sInstance)
42d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        sInstance = new NetlinkManager();
43d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    return sInstance;
44d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
45d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
46d18304287dbabc7835be771400b85d4ae8b63de6San MehatNetlinkManager::NetlinkManager() {
47d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    mBroadcaster = NULL;
48d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
49d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
50d18304287dbabc7835be771400b85d4ae8b63de6San MehatNetlinkManager::~NetlinkManager() {
51d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
52d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
53e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP AbgrallNetlinkHandler *NetlinkManager::setupSocket(int *sock, int netlinkFamily,
54564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    int groups, int format) {
55564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen
56d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    struct sockaddr_nl nladdr;
57d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    int sz = 64 * 1024;
5879b579c92afc08ab12c0a5788d61f2dd2934836fNick Kralevich    int on = 1;
59d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
60d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    memset(&nladdr, 0, sizeof(nladdr));
61d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    nladdr.nl_family = AF_NETLINK;
62d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    nladdr.nl_pid = getpid();
63564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    nladdr.nl_groups = groups;
64d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
65e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrall    if ((*sock = socket(PF_NETLINK, SOCK_DGRAM, netlinkFamily)) < 0) {
66564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen        LOGE("Unable to create netlink socket: %s", strerror(errno));
67564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen        return NULL;
68d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    }
69d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
70564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    if (setsockopt(*sock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) {
7179b579c92afc08ab12c0a5788d61f2dd2934836fNick Kralevich        LOGE("Unable to set uevent socket SO_RCVBUFFORCE option: %s", strerror(errno));
72564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen        close(*sock);
73564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen        return NULL;
7479b579c92afc08ab12c0a5788d61f2dd2934836fNick Kralevich    }
7579b579c92afc08ab12c0a5788d61f2dd2934836fNick Kralevich
76564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    if (setsockopt(*sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
7779b579c92afc08ab12c0a5788d61f2dd2934836fNick Kralevich        SLOGE("Unable to set uevent socket SO_PASSCRED option: %s", strerror(errno));
78564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen        close(*sock);
79564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen        return NULL;
80d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    }
81d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
82564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    if (bind(*sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
83564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen        LOGE("Unable to bind netlink socket: %s", strerror(errno));
84564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen        close(*sock);
85564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen        return NULL;
86d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    }
87d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
88564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    NetlinkHandler *handler = new NetlinkHandler(this, *sock, format);
89564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    if (handler->start()) {
90d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        LOGE("Unable to start NetlinkHandler: %s", strerror(errno));
91564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen        close(*sock);
92564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen        return NULL;
93564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    }
94564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen
95564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    return handler;
96564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen}
97564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen
98564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chenint NetlinkManager::start() {
99564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    if ((mUeventHandler = setupSocket(&mUeventSock, NETLINK_KOBJECT_UEVENT,
100564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen         0xffffffff, NetlinkListener::NETLINK_FORMAT_ASCII)) == NULL) {
101564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen        return -1;
102564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    }
103564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen
104564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    if ((mRouteHandler = setupSocket(&mRouteSock, NETLINK_ROUTE, RTMGRP_LINK,
105564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen         NetlinkListener::NETLINK_FORMAT_BINARY)) == NULL) {
106d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        return -1;
107d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    }
108e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrall
109e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrall    if ((mQuotaHandler = setupSocket(&mQuotaSock, NETLINK_NFLOG,
110e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrall        NFLOG_QUOTA_GROUP, NetlinkListener::NETLINK_FORMAT_BINARY)) == NULL) {
111e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrall        LOGE("Unable to open quota2 logging socket");
1128a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall        // TODO: return -1 once the emulator gets a new kernel.
113e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrall    }
114d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    return 0;
115d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
116d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
117d18304287dbabc7835be771400b85d4ae8b63de6San Mehatint NetlinkManager::stop() {
118564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    int status = 0;
119564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen
120564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    if (mUeventHandler->stop()) {
121564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen        LOGE("Unable to stop uevent NetlinkHandler: %s", strerror(errno));
122564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen        status = -1;
123d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    }
124d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
125564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    delete mUeventHandler;
126564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    mUeventHandler = NULL;
127d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
128564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    close(mUeventSock);
129564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    mUeventSock = -1;
130564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen
131564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    if (mRouteHandler->stop()) {
132564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen        LOGE("Unable to stop route NetlinkHandler: %s", strerror(errno));
133564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen        status = -1;
134564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    }
135564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen
136564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    delete mRouteHandler;
137564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    mRouteHandler = NULL;
138564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen
139564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    close(mRouteSock);
140564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    mRouteSock = -1;
141564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen
1428a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall    if (mQuotaHandler) {
1438a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall        if (mQuotaHandler->stop()) {
1448a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall            LOGE("Unable to stop quota NetlinkHandler: %s", strerror(errno));
1458a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall            status = -1;
1468a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall        }
147e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrall
1488a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall        delete mQuotaHandler;
1498a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall        mQuotaHandler = NULL;
150e0ebc46c0aa38ce4f35bd3b60c0fcb9204d4c35eJP Abgrall
1518a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall        close(mQuotaSock);
1528a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall        mQuotaSock = -1;
1538a41209c0188560a3b29c88fab7bd8a480c03892JP Abgrall    }
154564df4efc87f3d04c3570836d38134fd949c4cafMike J. Chen    return status;
155d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
156