NetworkController.cpp revision a561e121c724e9163b2e256e15eef660e3a326da
1/*
2 * Copyright (C) 2014 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// THREAD-SAFETY
18// -------------
19// The methods in this file are called from multiple threads (from CommandListener, FwmarkServer
20// and DnsProxyListener). So, all accesses to shared state are guarded by a lock.
21//
22// In some cases, a single non-const method acquires and releases the lock several times, like so:
23//     if (isValidNetwork(...)) {  // isValidNetwork() acquires and releases the lock.
24//        setDefaultNetwork(...);  // setDefaultNetwork() also acquires and releases the lock.
25//
26// It might seem that this allows races where the state changes between the two statements, but in
27// fact there are no races because:
28//     1. This pattern only occurs in non-const methods (i.e., those that mutate state).
29//     2. Only CommandListener calls these non-const methods. The others call only const methods.
30//     3. CommandListener only processes one command at a time. I.e., it's serialized.
31// Thus, no other mutation can occur in between the two statements above.
32
33#include "NetworkController.h"
34
35#include "PermissionsController.h"
36#include "RouteController.h"
37
38#define LOG_TAG "NetworkController"
39
40#include <sys/socket.h>
41#include <linux/if.h>
42
43#include "cutils/log.h"
44#include "resolv_netid.h"
45
46namespace {
47
48// Keep these in sync with ConnectivityService.java.
49const unsigned int MIN_NET_ID = 10;
50const unsigned int MAX_NET_ID = 65535;
51
52}  // namespace
53
54NetworkController::NetworkController(PermissionsController* permissionsController,
55                                     RouteController* routeController)
56        : mDefaultNetId(NETID_UNSET),
57          mPermissionsController(permissionsController),
58          mRouteController(routeController) {
59}
60
61void NetworkController::clearNetworkPreference() {
62    android::RWLock::AutoWLock lock(mRWLock);
63    mUidMap.clear();
64}
65
66unsigned NetworkController::getDefaultNetwork() const {
67    android::RWLock::AutoRLock lock(mRWLock);
68    return mDefaultNetId;
69}
70
71bool NetworkController::setDefaultNetwork(unsigned newNetId) {
72    // newNetId must be either NETID_UNSET or a valid network. If it's NETID_UNSET, the caller is
73    // asking for there to be no default network, which is a request we support.
74    if (newNetId != NETID_UNSET && !isValidNetwork(newNetId)) {
75        ALOGE("invalid netId %u", newNetId);
76        errno = EINVAL;
77        return false;
78    }
79
80    unsigned oldNetId;
81    {
82        android::RWLock::AutoWLock lock(mRWLock);
83        oldNetId = mDefaultNetId;
84        mDefaultNetId = newNetId;
85    }
86
87    if (oldNetId == newNetId) {
88        return true;
89    }
90
91    bool status = true;
92    Permission permission;
93    InterfaceRange range;
94
95    // Add default network rules for the new netId.
96    permission = mPermissionsController->getPermissionForNetwork(newNetId);
97    range = mNetIdToInterfaces.equal_range(newNetId);
98    for (InterfaceIteratorConst iter = range.first; iter != range.second; ++iter) {
99        if (!mRouteController->addToDefaultNetwork(iter->second.c_str(), permission)) {
100            ALOGE("failed to add interface %s to default netId %u", iter->second.c_str(), newNetId);
101            status = false;
102        }
103    }
104
105    // Remove the old default network rules.
106    permission = mPermissionsController->getPermissionForNetwork(oldNetId);
107    range = mNetIdToInterfaces.equal_range(oldNetId);
108    for (InterfaceIteratorConst iter = range.first; iter != range.second; ++iter) {
109        if (!mRouteController->removeFromDefaultNetwork(iter->second.c_str(), permission)) {
110            ALOGE("failed to remove interface %s from default netId %u", iter->second.c_str(),
111                  oldNetId);
112            status = false;
113        }
114    }
115
116    return status;
117}
118
119bool NetworkController::setNetworkForUidRange(int uid_start, int uid_end, unsigned netId,
120                                              bool forward_dns) {
121    if (uid_start > uid_end || !isValidNetwork(netId)) {
122        errno = EINVAL;
123        return false;
124    }
125
126    android::RWLock::AutoWLock lock(mRWLock);
127    for (std::list<UidEntry>::iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
128        if (it->uid_start != uid_start || it->uid_end != uid_end || it->netId != netId)
129            continue;
130        it->forward_dns = forward_dns;
131        return true;
132    }
133
134    mUidMap.push_front(UidEntry(uid_start, uid_end, netId, forward_dns));
135    return true;
136}
137
138bool NetworkController::clearNetworkForUidRange(int uid_start, int uid_end, unsigned netId) {
139    if (uid_start > uid_end || !isValidNetwork(netId)) {
140        errno = EINVAL;
141        return false;
142    }
143
144    android::RWLock::AutoWLock lock(mRWLock);
145    for (std::list<UidEntry>::iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
146        if (it->uid_start != uid_start || it->uid_end != uid_end || it->netId != netId)
147            continue;
148        mUidMap.erase(it);
149        return true;
150    }
151
152    errno = ENOENT;
153    return false;
154}
155
156unsigned NetworkController::getNetwork(int uid, unsigned requested_netId, bool for_dns) const {
157    android::RWLock::AutoRLock lock(mRWLock);
158    for (std::list<UidEntry>::const_iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
159        if (uid < it->uid_start || it->uid_end < uid)
160            continue;
161        if (for_dns && !it->forward_dns)
162            break;
163        return it->netId;
164    }
165    if (mValidNetworks.find(requested_netId) != mValidNetworks.end())
166        return requested_netId;
167    return mDefaultNetId;
168}
169
170unsigned NetworkController::getNetworkId(const char* interface) const {
171    for (InterfaceIteratorConst iter = mNetIdToInterfaces.begin(); iter != mNetIdToInterfaces.end();
172         ++iter) {
173        if (iter->second == interface) {
174            return iter->first;
175        }
176    }
177    return NETID_UNSET;
178}
179
180bool NetworkController::createNetwork(unsigned netId, Permission permission) {
181    if (netId < MIN_NET_ID || netId > MAX_NET_ID) {
182        ALOGE("invalid netId %u", netId);
183        errno = EINVAL;
184        return false;
185    }
186
187    {
188        android::RWLock::AutoWLock lock(mRWLock);
189        if (!mValidNetworks.insert(netId).second) {
190            ALOGE("duplicate netId %u", netId);
191            errno = EEXIST;
192            return false;
193        }
194    }
195
196    mPermissionsController->setPermissionForNetwork(permission, netId);
197    return true;
198}
199
200bool NetworkController::addInterfaceToNetwork(unsigned netId, const char* interface) {
201    if (!isValidNetwork(netId) || !interface) {
202        ALOGE("invalid netId %u or interface null", netId);
203        errno = EINVAL;
204        return false;
205    }
206
207    unsigned existingNetId = getNetworkId(interface);
208    if (existingNetId != NETID_UNSET) {
209        ALOGE("interface %s already assigned to netId %u", interface, existingNetId);
210        errno = EBUSY;
211        return false;
212    }
213
214    Permission permission = mPermissionsController->getPermissionForNetwork(netId);
215    if (!mRouteController->addInterfaceToNetwork(netId, interface, permission)) {
216        ALOGE("failed to add interface %s to netId %u", interface, netId);
217        return false;
218    }
219
220    mNetIdToInterfaces.insert(std::pair<unsigned, std::string>(netId, interface));
221
222    if (netId == getDefaultNetwork() &&
223            !mRouteController->addToDefaultNetwork(interface, permission)) {
224        ALOGE("failed to add interface %s to default netId %u", interface, netId);
225        return false;
226    }
227
228    return true;
229}
230
231bool NetworkController::removeInterfaceFromNetwork(unsigned netId, const char* interface) {
232    if (!isValidNetwork(netId) || !interface) {
233        ALOGE("invalid netId %u or interface null", netId);
234        errno = EINVAL;
235        return false;
236    }
237
238    bool status = false;
239    InterfaceRange range = mNetIdToInterfaces.equal_range(netId);
240    for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
241        if (iter->second == interface) {
242            mNetIdToInterfaces.erase(iter);
243            status = true;
244            break;
245        }
246    }
247    if (!status) {
248        ALOGE("interface %s not assigned to netId %u", interface, netId);
249        errno = ENOENT;
250    }
251
252    Permission permission = mPermissionsController->getPermissionForNetwork(netId);
253    if (netId == getDefaultNetwork() &&
254            !mRouteController->removeFromDefaultNetwork(interface, permission)) {
255        ALOGE("failed to remove interface %s from default netId %u", interface, netId);
256        status = false;
257    }
258
259    if (!mRouteController->removeInterfaceFromNetwork(netId, interface, permission)) {
260        ALOGE("failed to remove interface %s from netId %u", interface, netId);
261        status = false;
262    }
263
264    return status;
265}
266
267bool NetworkController::destroyNetwork(unsigned netId) {
268    if (!isValidNetwork(netId)) {
269        ALOGE("invalid netId %u", netId);
270        errno = EINVAL;
271        return false;
272    }
273
274    // TODO: ioctl(SIOCKILLADDR, ...) to kill all sockets on the old network.
275
276    bool status = true;
277
278    InterfaceRange range = mNetIdToInterfaces.equal_range(netId);
279    for (InterfaceIteratorConst iter = range.first; iter != range.second; ) {
280        char interface[IFNAMSIZ];
281        strncpy(interface, iter->second.c_str(), sizeof(interface));
282        interface[sizeof(interface) - 1] = 0;
283        ++iter;
284        if (!removeInterfaceFromNetwork(netId, interface)) {
285            status = false;
286        }
287    }
288
289    if (netId == getDefaultNetwork()) {
290        setDefaultNetwork(NETID_UNSET);
291    }
292
293    {
294        android::RWLock::AutoWLock lock(mRWLock);
295        mValidNetworks.erase(netId);
296    }
297
298    mPermissionsController->setPermissionForNetwork(PERMISSION_NONE, netId);
299
300    _resolv_delete_cache_for_net(netId);
301    return status;
302}
303
304bool NetworkController::setPermissionForUser(Permission permission,
305                                             const std::vector<unsigned>& uid) {
306    for (size_t i = 0; i < uid.size(); ++i) {
307        mPermissionsController->setPermissionForUser(permission, uid[i]);
308    }
309    return true;
310}
311
312bool NetworkController::setPermissionForNetwork(Permission newPermission,
313                                                const std::vector<unsigned>& netId) {
314    bool status = true;
315
316    for (size_t i = 0; i < netId.size(); ++i) {
317        if (!isValidNetwork(netId[i])) {
318            ALOGE("invalid netId %u", netId[i]);
319            errno = EINVAL;
320            status = false;
321            continue;
322        }
323
324        Permission oldPermission = mPermissionsController->getPermissionForNetwork(netId[i]);
325        if (oldPermission == newPermission) {
326            continue;
327        }
328
329        // TODO: ioctl(SIOCKILLADDR, ...) to kill sockets on the network that don't have
330        // newPermission.
331
332        InterfaceRange range = mNetIdToInterfaces.equal_range(netId[i]);
333        for (InterfaceIteratorConst iter = range.first; iter != range.second; ++iter) {
334            if (!mRouteController->modifyNetworkPermission(netId[i], iter->second.c_str(),
335                                                           oldPermission, newPermission)) {
336                ALOGE("failed to change permission on interface %s of netId %u from %x to %x",
337                      iter->second.c_str(), netId[i], oldPermission, newPermission);
338                status = false;
339            }
340        }
341
342        mPermissionsController->setPermissionForNetwork(newPermission, netId[i]);
343    }
344
345    return status;
346}
347
348bool NetworkController::addRoute(unsigned netId, const char* interface, const char* destination,
349                                 const char* nexthop, bool legacy, unsigned uid) {
350    return modifyRoute(netId, interface, destination, nexthop, true, legacy, uid);
351}
352
353bool NetworkController::removeRoute(unsigned netId, const char* interface, const char* destination,
354                                    const char* nexthop, bool legacy, unsigned uid) {
355    return modifyRoute(netId, interface, destination, nexthop, false, legacy, uid);
356}
357
358bool NetworkController::isValidNetwork(unsigned netId) const {
359    if (netId == NETID_UNSET) {
360        return false;
361    }
362
363    android::RWLock::AutoRLock lock(mRWLock);
364    return mValidNetworks.find(netId) != mValidNetworks.end();
365}
366
367bool NetworkController::modifyRoute(unsigned netId, const char* interface, const char* destination,
368                                    const char* nexthop, bool add, bool legacy, unsigned uid) {
369    if (!isValidNetwork(netId)) {
370        ALOGE("invalid netId %u", netId);
371        errno = EINVAL;
372        return false;
373    }
374
375    if (getNetworkId(interface) != netId) {
376        ALOGE("netId %u has no such interface %s", netId, interface);
377        errno = ENOENT;
378        return false;
379    }
380
381    RouteController::TableType tableType;
382    if (legacy) {
383        if (mPermissionsController->getPermissionForUser(uid) & PERMISSION_CONNECTIVITY_INTERNAL) {
384            tableType = RouteController::PRIVILEGED_LEGACY;
385        } else {
386            tableType = RouteController::LEGACY;
387        }
388    } else {
389        tableType = RouteController::INTERFACE;
390    }
391
392    return add ? mRouteController->addRoute(interface, destination, nexthop, tableType, uid) :
393                 mRouteController->removeRoute(interface, destination, nexthop, tableType, uid);
394}
395
396NetworkController::UidEntry::UidEntry(int start, int end, unsigned netId, bool forward_dns)
397    : uid_start(start), uid_end(end), netId(netId), forward_dns(forward_dns) {
398}
399