1*8542734aSAndroid Build Coastguard Worker /*
2*8542734aSAndroid Build Coastguard Worker * Copyright (C) 2008 The Android Open Source Project
3*8542734aSAndroid Build Coastguard Worker *
4*8542734aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*8542734aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*8542734aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*8542734aSAndroid Build Coastguard Worker *
8*8542734aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*8542734aSAndroid Build Coastguard Worker *
10*8542734aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*8542734aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*8542734aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8542734aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*8542734aSAndroid Build Coastguard Worker * limitations under the License.
15*8542734aSAndroid Build Coastguard Worker */
16*8542734aSAndroid Build Coastguard Worker
17*8542734aSAndroid Build Coastguard Worker #include <errno.h>
18*8542734aSAndroid Build Coastguard Worker #include <stdio.h>
19*8542734aSAndroid Build Coastguard Worker #include <string.h>
20*8542734aSAndroid Build Coastguard Worker #include <unistd.h>
21*8542734aSAndroid Build Coastguard Worker
22*8542734aSAndroid Build Coastguard Worker #include <sys/socket.h>
23*8542734aSAndroid Build Coastguard Worker #include <sys/time.h>
24*8542734aSAndroid Build Coastguard Worker #include <sys/types.h>
25*8542734aSAndroid Build Coastguard Worker #include <sys/un.h>
26*8542734aSAndroid Build Coastguard Worker
27*8542734aSAndroid Build Coastguard Worker #include <linux/netlink.h>
28*8542734aSAndroid Build Coastguard Worker #include <linux/rtnetlink.h>
29*8542734aSAndroid Build Coastguard Worker
30*8542734aSAndroid Build Coastguard Worker #define LOG_TAG "Netd"
31*8542734aSAndroid Build Coastguard Worker
32*8542734aSAndroid Build Coastguard Worker #include <log/log.h>
33*8542734aSAndroid Build Coastguard Worker
34*8542734aSAndroid Build Coastguard Worker #include <linux/netfilter/nfnetlink.h>
35*8542734aSAndroid Build Coastguard Worker #include <linux/netfilter/nfnetlink_log.h>
36*8542734aSAndroid Build Coastguard Worker #include <linux/netfilter/nfnetlink_compat.h>
37*8542734aSAndroid Build Coastguard Worker
38*8542734aSAndroid Build Coastguard Worker #include <arpa/inet.h>
39*8542734aSAndroid Build Coastguard Worker
40*8542734aSAndroid Build Coastguard Worker #include "NetlinkManager.h"
41*8542734aSAndroid Build Coastguard Worker #include "NetlinkHandler.h"
42*8542734aSAndroid Build Coastguard Worker
43*8542734aSAndroid Build Coastguard Worker #include "pcap-netfilter-linux-android.h"
44*8542734aSAndroid Build Coastguard Worker
45*8542734aSAndroid Build Coastguard Worker namespace android {
46*8542734aSAndroid Build Coastguard Worker namespace net {
47*8542734aSAndroid Build Coastguard Worker
48*8542734aSAndroid Build Coastguard Worker const int NetlinkManager::NFLOG_QUOTA_GROUP = 1;
49*8542734aSAndroid Build Coastguard Worker const int NetlinkManager::NETFILTER_STRICT_GROUP = 2;
50*8542734aSAndroid Build Coastguard Worker const int NetlinkManager::NFLOG_WAKEUP_GROUP = 3;
51*8542734aSAndroid Build Coastguard Worker
52*8542734aSAndroid Build Coastguard Worker NetlinkManager *NetlinkManager::sInstance = nullptr;
53*8542734aSAndroid Build Coastguard Worker
Instance()54*8542734aSAndroid Build Coastguard Worker NetlinkManager *NetlinkManager::Instance() {
55*8542734aSAndroid Build Coastguard Worker if (!sInstance)
56*8542734aSAndroid Build Coastguard Worker sInstance = new NetlinkManager();
57*8542734aSAndroid Build Coastguard Worker return sInstance;
58*8542734aSAndroid Build Coastguard Worker }
59*8542734aSAndroid Build Coastguard Worker
NetlinkManager()60*8542734aSAndroid Build Coastguard Worker NetlinkManager::NetlinkManager() {
61*8542734aSAndroid Build Coastguard Worker mBroadcaster = nullptr;
62*8542734aSAndroid Build Coastguard Worker }
63*8542734aSAndroid Build Coastguard Worker
~NetlinkManager()64*8542734aSAndroid Build Coastguard Worker NetlinkManager::~NetlinkManager() {
65*8542734aSAndroid Build Coastguard Worker }
66*8542734aSAndroid Build Coastguard Worker
setupSocket(int * sock,int netlinkFamily,int groups,int format,bool configNflog)67*8542734aSAndroid Build Coastguard Worker NetlinkHandler *NetlinkManager::setupSocket(int *sock, int netlinkFamily,
68*8542734aSAndroid Build Coastguard Worker int groups, int format, bool configNflog) {
69*8542734aSAndroid Build Coastguard Worker
70*8542734aSAndroid Build Coastguard Worker struct sockaddr_nl nladdr;
71*8542734aSAndroid Build Coastguard Worker int sz = 64 * 1024;
72*8542734aSAndroid Build Coastguard Worker int on = 1;
73*8542734aSAndroid Build Coastguard Worker
74*8542734aSAndroid Build Coastguard Worker memset(&nladdr, 0, sizeof(nladdr));
75*8542734aSAndroid Build Coastguard Worker nladdr.nl_family = AF_NETLINK;
76*8542734aSAndroid Build Coastguard Worker // Kernel will assign a unique nl_pid if set to zero.
77*8542734aSAndroid Build Coastguard Worker nladdr.nl_pid = 0;
78*8542734aSAndroid Build Coastguard Worker nladdr.nl_groups = groups;
79*8542734aSAndroid Build Coastguard Worker
80*8542734aSAndroid Build Coastguard Worker if ((*sock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, netlinkFamily)) < 0) {
81*8542734aSAndroid Build Coastguard Worker ALOGE("Unable to create netlink socket for family %d: %s", netlinkFamily, strerror(errno));
82*8542734aSAndroid Build Coastguard Worker return nullptr;
83*8542734aSAndroid Build Coastguard Worker }
84*8542734aSAndroid Build Coastguard Worker
85*8542734aSAndroid Build Coastguard Worker // When running in a net/user namespace, SO_RCVBUFFORCE will fail because
86*8542734aSAndroid Build Coastguard Worker // it will check for the CAP_NET_ADMIN capability in the root namespace.
87*8542734aSAndroid Build Coastguard Worker // Try using SO_RCVBUF if that fails.
88*8542734aSAndroid Build Coastguard Worker if (setsockopt(*sock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0 &&
89*8542734aSAndroid Build Coastguard Worker setsockopt(*sock, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)) < 0) {
90*8542734aSAndroid Build Coastguard Worker ALOGE("Unable to set uevent socket SO_RCVBUF option: %s", strerror(errno));
91*8542734aSAndroid Build Coastguard Worker close(*sock);
92*8542734aSAndroid Build Coastguard Worker return nullptr;
93*8542734aSAndroid Build Coastguard Worker }
94*8542734aSAndroid Build Coastguard Worker
95*8542734aSAndroid Build Coastguard Worker if (setsockopt(*sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
96*8542734aSAndroid Build Coastguard Worker SLOGE("Unable to set uevent socket SO_PASSCRED option: %s", strerror(errno));
97*8542734aSAndroid Build Coastguard Worker close(*sock);
98*8542734aSAndroid Build Coastguard Worker return nullptr;
99*8542734aSAndroid Build Coastguard Worker }
100*8542734aSAndroid Build Coastguard Worker
101*8542734aSAndroid Build Coastguard Worker if (bind(*sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
102*8542734aSAndroid Build Coastguard Worker ALOGE("Unable to bind netlink socket: %s", strerror(errno));
103*8542734aSAndroid Build Coastguard Worker close(*sock);
104*8542734aSAndroid Build Coastguard Worker return nullptr;
105*8542734aSAndroid Build Coastguard Worker }
106*8542734aSAndroid Build Coastguard Worker
107*8542734aSAndroid Build Coastguard Worker if (configNflog) {
108*8542734aSAndroid Build Coastguard Worker if (android_nflog_send_config_cmd(*sock, 0, NFULNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) {
109*8542734aSAndroid Build Coastguard Worker ALOGE("Failed NFULNL_CFG_CMD_PF_UNBIND: %s", strerror(errno));
110*8542734aSAndroid Build Coastguard Worker return nullptr;
111*8542734aSAndroid Build Coastguard Worker }
112*8542734aSAndroid Build Coastguard Worker if (android_nflog_send_config_cmd(*sock, 0, NFULNL_CFG_CMD_PF_BIND, AF_INET) < 0) {
113*8542734aSAndroid Build Coastguard Worker ALOGE("Failed NFULNL_CFG_CMD_PF_BIND: %s", strerror(errno));
114*8542734aSAndroid Build Coastguard Worker return nullptr;
115*8542734aSAndroid Build Coastguard Worker }
116*8542734aSAndroid Build Coastguard Worker if (android_nflog_send_config_cmd(*sock, 0, NFULNL_CFG_CMD_BIND, AF_UNSPEC) < 0) {
117*8542734aSAndroid Build Coastguard Worker ALOGE("Failed NFULNL_CFG_CMD_BIND: %s", strerror(errno));
118*8542734aSAndroid Build Coastguard Worker return nullptr;
119*8542734aSAndroid Build Coastguard Worker }
120*8542734aSAndroid Build Coastguard Worker }
121*8542734aSAndroid Build Coastguard Worker
122*8542734aSAndroid Build Coastguard Worker NetlinkHandler *handler = new NetlinkHandler(this, *sock, format);
123*8542734aSAndroid Build Coastguard Worker if (handler->start()) {
124*8542734aSAndroid Build Coastguard Worker ALOGE("Unable to start NetlinkHandler: %s", strerror(errno));
125*8542734aSAndroid Build Coastguard Worker close(*sock);
126*8542734aSAndroid Build Coastguard Worker return nullptr;
127*8542734aSAndroid Build Coastguard Worker }
128*8542734aSAndroid Build Coastguard Worker
129*8542734aSAndroid Build Coastguard Worker return handler;
130*8542734aSAndroid Build Coastguard Worker }
131*8542734aSAndroid Build Coastguard Worker
start()132*8542734aSAndroid Build Coastguard Worker int NetlinkManager::start() {
133*8542734aSAndroid Build Coastguard Worker if ((mUeventHandler = setupSocket(&mUeventSock, NETLINK_KOBJECT_UEVENT,
134*8542734aSAndroid Build Coastguard Worker 0xffffffff, NetlinkListener::NETLINK_FORMAT_ASCII, false)) == nullptr) {
135*8542734aSAndroid Build Coastguard Worker return -1;
136*8542734aSAndroid Build Coastguard Worker }
137*8542734aSAndroid Build Coastguard Worker
138*8542734aSAndroid Build Coastguard Worker if ((mRouteHandler = setupSocket(&mRouteSock, NETLINK_ROUTE,
139*8542734aSAndroid Build Coastguard Worker RTMGRP_LINK |
140*8542734aSAndroid Build Coastguard Worker RTMGRP_IPV4_IFADDR |
141*8542734aSAndroid Build Coastguard Worker RTMGRP_IPV6_IFADDR |
142*8542734aSAndroid Build Coastguard Worker RTMGRP_IPV6_ROUTE |
143*8542734aSAndroid Build Coastguard Worker (1 << (RTNLGRP_ND_USEROPT - 1)),
144*8542734aSAndroid Build Coastguard Worker NetlinkListener::NETLINK_FORMAT_BINARY, false)) == nullptr) {
145*8542734aSAndroid Build Coastguard Worker return -1;
146*8542734aSAndroid Build Coastguard Worker }
147*8542734aSAndroid Build Coastguard Worker
148*8542734aSAndroid Build Coastguard Worker if ((mQuotaHandler = setupSocket(&mQuotaSock, NETLINK_NFLOG,
149*8542734aSAndroid Build Coastguard Worker NFLOG_QUOTA_GROUP, NetlinkListener::NETLINK_FORMAT_BINARY, false)) == nullptr) {
150*8542734aSAndroid Build Coastguard Worker ALOGW("Unable to open qlog quota socket, check if xt_quota2 can send via UeventHandler");
151*8542734aSAndroid Build Coastguard Worker // TODO: return -1 once the emulator gets a new kernel.
152*8542734aSAndroid Build Coastguard Worker }
153*8542734aSAndroid Build Coastguard Worker
154*8542734aSAndroid Build Coastguard Worker if ((mStrictHandler = setupSocket(&mStrictSock, NETLINK_NETFILTER,
155*8542734aSAndroid Build Coastguard Worker 0, NetlinkListener::NETLINK_FORMAT_BINARY_UNICAST, true)) == nullptr) {
156*8542734aSAndroid Build Coastguard Worker ALOGE("Unable to open strict socket");
157*8542734aSAndroid Build Coastguard Worker // TODO: return -1 once the emulator gets a new kernel.
158*8542734aSAndroid Build Coastguard Worker }
159*8542734aSAndroid Build Coastguard Worker
160*8542734aSAndroid Build Coastguard Worker return 0;
161*8542734aSAndroid Build Coastguard Worker }
162*8542734aSAndroid Build Coastguard Worker
stop()163*8542734aSAndroid Build Coastguard Worker int NetlinkManager::stop() {
164*8542734aSAndroid Build Coastguard Worker int status = 0;
165*8542734aSAndroid Build Coastguard Worker
166*8542734aSAndroid Build Coastguard Worker if (mUeventHandler->stop()) {
167*8542734aSAndroid Build Coastguard Worker ALOGE("Unable to stop uevent NetlinkHandler: %s", strerror(errno));
168*8542734aSAndroid Build Coastguard Worker status = -1;
169*8542734aSAndroid Build Coastguard Worker }
170*8542734aSAndroid Build Coastguard Worker
171*8542734aSAndroid Build Coastguard Worker delete mUeventHandler;
172*8542734aSAndroid Build Coastguard Worker mUeventHandler = nullptr;
173*8542734aSAndroid Build Coastguard Worker
174*8542734aSAndroid Build Coastguard Worker close(mUeventSock);
175*8542734aSAndroid Build Coastguard Worker mUeventSock = -1;
176*8542734aSAndroid Build Coastguard Worker
177*8542734aSAndroid Build Coastguard Worker if (mRouteHandler->stop()) {
178*8542734aSAndroid Build Coastguard Worker ALOGE("Unable to stop route NetlinkHandler: %s", strerror(errno));
179*8542734aSAndroid Build Coastguard Worker status = -1;
180*8542734aSAndroid Build Coastguard Worker }
181*8542734aSAndroid Build Coastguard Worker
182*8542734aSAndroid Build Coastguard Worker delete mRouteHandler;
183*8542734aSAndroid Build Coastguard Worker mRouteHandler = nullptr;
184*8542734aSAndroid Build Coastguard Worker
185*8542734aSAndroid Build Coastguard Worker close(mRouteSock);
186*8542734aSAndroid Build Coastguard Worker mRouteSock = -1;
187*8542734aSAndroid Build Coastguard Worker
188*8542734aSAndroid Build Coastguard Worker if (mQuotaHandler) {
189*8542734aSAndroid Build Coastguard Worker if (mQuotaHandler->stop()) {
190*8542734aSAndroid Build Coastguard Worker ALOGE("Unable to stop quota NetlinkHandler: %s", strerror(errno));
191*8542734aSAndroid Build Coastguard Worker status = -1;
192*8542734aSAndroid Build Coastguard Worker }
193*8542734aSAndroid Build Coastguard Worker
194*8542734aSAndroid Build Coastguard Worker delete mQuotaHandler;
195*8542734aSAndroid Build Coastguard Worker mQuotaHandler = nullptr;
196*8542734aSAndroid Build Coastguard Worker
197*8542734aSAndroid Build Coastguard Worker close(mQuotaSock);
198*8542734aSAndroid Build Coastguard Worker mQuotaSock = -1;
199*8542734aSAndroid Build Coastguard Worker }
200*8542734aSAndroid Build Coastguard Worker
201*8542734aSAndroid Build Coastguard Worker if (mStrictHandler) {
202*8542734aSAndroid Build Coastguard Worker if (mStrictHandler->stop()) {
203*8542734aSAndroid Build Coastguard Worker ALOGE("Unable to stop strict NetlinkHandler: %s", strerror(errno));
204*8542734aSAndroid Build Coastguard Worker status = -1;
205*8542734aSAndroid Build Coastguard Worker }
206*8542734aSAndroid Build Coastguard Worker
207*8542734aSAndroid Build Coastguard Worker delete mStrictHandler;
208*8542734aSAndroid Build Coastguard Worker mStrictHandler = nullptr;
209*8542734aSAndroid Build Coastguard Worker
210*8542734aSAndroid Build Coastguard Worker close(mStrictSock);
211*8542734aSAndroid Build Coastguard Worker mStrictSock = -1;
212*8542734aSAndroid Build Coastguard Worker }
213*8542734aSAndroid Build Coastguard Worker
214*8542734aSAndroid Build Coastguard Worker return status;
215*8542734aSAndroid Build Coastguard Worker }
216*8542734aSAndroid Build Coastguard Worker
217*8542734aSAndroid Build Coastguard Worker } // namespace net
218*8542734aSAndroid Build Coastguard Worker } // namespace android
219