Add UID range support to VPNs.
This adds the necessary routing rules.
Future CLs will add the ability to select the right netId for connect(),
setNetworkForSocket(), DNS resolutions, etc.
Bug: 15409918
Change-Id: I88a67660d49cecda834dd72ab947fbfed250f09d
diff --git a/server/UidRanges.cpp b/server/UidRanges.cpp
new file mode 100644
index 0000000..d752cbf
--- /dev/null
+++ b/server/UidRanges.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "UidRanges.h"
+
+#include "NetdConstants.h"
+
+#include <stdlib.h>
+
+const std::vector<std::pair<uid_t, uid_t>>& UidRanges::getRanges() const {
+ return mRanges;
+}
+
+bool UidRanges::parseFrom(int argc, char* argv[]) {
+ mRanges.clear();
+ for (int i = 0; i < argc; ++i) {
+ if (!*argv[i]) {
+ // The UID string is empty.
+ return false;
+ }
+ char* endPtr;
+ uid_t uidStart = strtoul(argv[i], &endPtr, 0);
+ uid_t uidEnd;
+ if (!*endPtr) {
+ // Found a single UID. The range contains just the one UID.
+ uidEnd = uidStart;
+ } else if (*endPtr == '-') {
+ if (!*++endPtr) {
+ // Unexpected end of string.
+ return false;
+ }
+ uidEnd = strtoul(endPtr, &endPtr, 0);
+ if (*endPtr) {
+ // Illegal trailing chars.
+ return false;
+ }
+ if (uidEnd < uidStart) {
+ // Invalid order.
+ return false;
+ }
+ } else {
+ // Not a single uid, not a range. Found some other illegal char.
+ return false;
+ }
+ if (uidStart == INVALID_UID || uidEnd == INVALID_UID) {
+ // Invalid UIDs.
+ return false;
+ }
+ mRanges.push_back(std::pair<uid_t, uid_t>(uidStart, uidEnd));
+ }
+ std::sort(mRanges.begin(), mRanges.end());
+ return true;
+}
+
+void UidRanges::add(const UidRanges& other) {
+ auto middle = mRanges.insert(mRanges.end(), other.mRanges.begin(), other.mRanges.end());
+ std::inplace_merge(mRanges.begin(), middle, mRanges.end());
+}
+
+void UidRanges::remove(const UidRanges& other) {
+ auto end = std::set_difference(mRanges.begin(), mRanges.end(), other.mRanges.begin(),
+ other.mRanges.end(), mRanges.begin());
+ mRanges.erase(end, mRanges.end());
+}