1b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran/*
2b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran * Copyright (C) 2014 The Android Open Source Project
3b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran *
4b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran * Licensed under the Apache License, Version 2.0 (the "License");
5b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran * you may not use this file except in compliance with the License.
6b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran * You may obtain a copy of the License at
7b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran *
8b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran *      http://www.apache.org/licenses/LICENSE-2.0
9b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran *
10b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran * Unless required by applicable law or agreed to in writing, software
11b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran * distributed under the License is distributed on an "AS IS" BASIS,
12b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran * See the License for the specific language governing permissions and
14b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran * limitations under the License.
15b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran */
16b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran
17b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran#include "UidRanges.h"
18b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran
19b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran#include "NetdConstants.h"
20b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran
21b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran#include <stdlib.h>
22b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran
23fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti#include <android-base/stringprintf.h>
24fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
25fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colittiusing android::base::StringAppendF;
26fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
27e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranbool UidRanges::hasUid(uid_t uid) const {
28e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    auto iter = std::lower_bound(mRanges.begin(), mRanges.end(), Range(uid, uid));
29e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    return (iter != mRanges.end() && iter->first == uid) ||
30e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran           (iter != mRanges.begin() && (--iter)->second >= uid);
31e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran}
32e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran
33e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranconst std::vector<UidRanges::Range>& UidRanges::getRanges() const {
34b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    return mRanges;
35b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran}
36b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran
37b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandranbool UidRanges::parseFrom(int argc, char* argv[]) {
38b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    mRanges.clear();
39b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    for (int i = 0; i < argc; ++i) {
40b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        if (!*argv[i]) {
41b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            // The UID string is empty.
42b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            return false;
43b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        }
44b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        char* endPtr;
45b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        uid_t uidStart = strtoul(argv[i], &endPtr, 0);
46b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        uid_t uidEnd;
47b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        if (!*endPtr) {
48b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            // Found a single UID. The range contains just the one UID.
49b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            uidEnd = uidStart;
50b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        } else if (*endPtr == '-') {
51b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            if (!*++endPtr) {
52b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran                // Unexpected end of string.
53b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran                return false;
54b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            }
55b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            uidEnd = strtoul(endPtr, &endPtr, 0);
56b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            if (*endPtr) {
57b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran                // Illegal trailing chars.
58b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran                return false;
59b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            }
60b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            if (uidEnd < uidStart) {
61b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran                // Invalid order.
62b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran                return false;
63b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            }
64b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        } else {
65b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            // Not a single uid, not a range. Found some other illegal char.
66b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            return false;
67b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        }
68b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        if (uidStart == INVALID_UID || uidEnd == INVALID_UID) {
69b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            // Invalid UIDs.
70b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            return false;
71b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        }
72e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran        mRanges.push_back(Range(uidStart, uidEnd));
73b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    }
74b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    std::sort(mRanges.begin(), mRanges.end());
75b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    return true;
76b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran}
77b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran
78563d98b27d02a1d694fc4ed82b5554fd534c9dafLorenzo ColittiUidRanges::UidRanges(const std::vector<android::net::UidRange>& ranges) {
79b8087363143050d214d48e5620a330776ca95a69Robin Lee    mRanges.resize(ranges.size());
80b8087363143050d214d48e5620a330776ca95a69Robin Lee    std::transform(ranges.begin(), ranges.end(), mRanges.begin(),
81b8087363143050d214d48e5620a330776ca95a69Robin Lee            [](const android::net::UidRange& range) {
82b8087363143050d214d48e5620a330776ca95a69Robin Lee                return Range(range.getStart(), range.getStop());
83b8087363143050d214d48e5620a330776ca95a69Robin Lee            });
84b8087363143050d214d48e5620a330776ca95a69Robin Lee    std::sort(mRanges.begin(), mRanges.end());
85b8087363143050d214d48e5620a330776ca95a69Robin Lee}
86b8087363143050d214d48e5620a330776ca95a69Robin Lee
87b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandranvoid UidRanges::add(const UidRanges& other) {
88b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    auto middle = mRanges.insert(mRanges.end(), other.mRanges.begin(), other.mRanges.end());
89b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    std::inplace_merge(mRanges.begin(), middle, mRanges.end());
90b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran}
91b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran
92b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandranvoid UidRanges::remove(const UidRanges& other) {
93b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    auto end = std::set_difference(mRanges.begin(), mRanges.end(), other.mRanges.begin(),
94b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran                                   other.mRanges.end(), mRanges.begin());
95b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    mRanges.erase(end, mRanges.end());
96b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran}
97fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
98fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colittistd::string UidRanges::toString() const {
99fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    std::string s("UidRanges{ ");
100fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    for (Range range : mRanges) {
101fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti        if (range.first != range.second) {
102fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti            StringAppendF(&s, "%u-%u ", range.first, range.second);
103fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti        } else {
104fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti            StringAppendF(&s, "%u ", range.first);
105fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti        }
106fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    }
107fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    StringAppendF(&s, "}");
108fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    return s;
109fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti}
110