Refactor the fwmark stuff to use an explicit union of bit-fields.
This is a pure refactor. There's no effect on any functionality.
Change-Id: I99d1f3fb76781cf84f67c2dff44eaf3a2cf50a9f
diff --git a/Android.mk b/Android.mk
index 66903d7..89392ff 100644
--- a/Android.mk
+++ b/Android.mk
@@ -8,7 +8,6 @@
CommandListener.cpp \
DnsProxyListener.cpp \
FirewallController.cpp \
- Fwmark.cpp \
IdletimerController.cpp \
InterfaceController.cpp \
MDnsSdListener.cpp \
diff --git a/DnsProxyListener.cpp b/DnsProxyListener.cpp
index 7379788..3a8e475 100644
--- a/DnsProxyListener.cpp
+++ b/DnsProxyListener.cpp
@@ -53,10 +53,13 @@
}
uint32_t DnsProxyListener::calcMark(SocketClient *c, unsigned netId) const {
+ Fwmark fwmark;
+ fwmark.netId = netId;
// If netd's UID is forced into a VPN that isn't the intended network,
// use VPN protect bit to force it into the desired network.
- bool vpnProtect = mNetCtrl->getNetwork(getuid(), netId, true) != netId;
- return getFwmark(netId, false, vpnProtect, mPermCtrl->getPermissionForUser(c->getUid()));
+ fwmark.protectedFromVpn = mNetCtrl->getNetwork(getuid(), netId, true) != netId;
+ fwmark.permission = mPermCtrl->getPermissionForUser(c->getUid());
+ return fwmark.intValue;
}
DnsProxyListener::GetAddrInfoHandler::GetAddrInfoHandler(SocketClient *c,
diff --git a/Fwmark.cpp b/Fwmark.cpp
deleted file mode 100644
index 52c8606..0000000
--- a/Fwmark.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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 "Fwmark.h"
-
-namespace {
-
-const uint32_t FWMARK_MASK_NET_ID = 0xffff;
-const uint32_t FWMARK_MASK_EXPLICIT = 0x10000;
-const uint32_t FWMARK_MASK_PROTECT = 0x20000;
-const uint32_t FWMARK_MASK_CHANGE_NETWORK_STATE = 0x40000;
-const uint32_t FWMARK_MASK_CONNECTIVITY_INTERNAL = 0x80000;
-
-} // namespace
-
-uint32_t getFwmark(unsigned netId, bool exp, bool protect, Permission permission) {
- uint32_t fwmark = netId & FWMARK_MASK_NET_ID;
- if (exp) {
- fwmark |= FWMARK_MASK_EXPLICIT;
- }
- if (protect) {
- fwmark |= FWMARK_MASK_PROTECT;
- }
- if (permission & PERMISSION_CHANGE_NETWORK_STATE) {
- fwmark |= FWMARK_MASK_CHANGE_NETWORK_STATE;
- }
- if (permission & PERMISSION_CONNECTIVITY_INTERNAL) {
- fwmark |= FWMARK_MASK_CONNECTIVITY_INTERNAL;
- }
- return fwmark;
-}
-
-uint32_t getFwmarkMask(bool netId, bool exp, bool protect, Permission permission) {
- return getFwmark(netId ? FWMARK_MASK_NET_ID : 0, exp, protect, permission);
-}
diff --git a/Fwmark.h b/Fwmark.h
index ee3bed0..d358f81 100644
--- a/Fwmark.h
+++ b/Fwmark.h
@@ -19,15 +19,27 @@
#include "Permission.h"
+#include <utils/Debug.h>
#include <stdint.h>
-// Composes a fwmark comprising of |netId|, along with bits representing:
-// |exp|: true if the |netId| is being explicitly requested
-// |protect|: true if VPNs should be bypassed
-// |permission|: != PERMISSION_NONE to assert that |permission| is held
-uint32_t getFwmark(unsigned netId, bool exp, bool protect, Permission permission);
+union Fwmark {
+ Fwmark() : intValue(0) {}
+ uint32_t intValue;
+ struct {
+ unsigned netId : 16;
+ bool explicitlySelected : 1;
+ bool protectedFromVpn : 1;
+ Permission permission : 2;
+ };
+};
-// Composes a mask to test parts of the fwmark (see getFwmark() for details).
-uint32_t getFwmarkMask(bool netId, bool exp, bool protect, Permission permission);
+static const unsigned FWMARK_NET_ID_MASK = 0xffff;
+
+namespace android {
+
+// Ensure that all the fwmark fields fit into 32 bits.
+COMPILE_TIME_ASSERT(sizeof(Fwmark) == sizeof(uint32_t));
+
+} // namespace android
#endif // SYSTEM_NETD_FWMARK_H
diff --git a/RouteController.cpp b/RouteController.cpp
index 05170b8..a58f02d 100644
--- a/RouteController.cpp
+++ b/RouteController.cpp
@@ -32,10 +32,6 @@
const uint32_t RULE_PRIORITY_MAIN = 20000;
const uint32_t RULE_PRIORITY_UNREACHABLE = 21000;
-const bool FWMARK_USE_NET_ID = true;
-const bool FWMARK_USE_EXPLICIT = true;
-const bool FWMARK_USE_PROTECT = true;
-
uint32_t getRouteTableForInterface(const char* interface) {
uint32_t index = if_nametoindex(interface);
return index ? index + RouteController::ROUTE_TABLE_OFFSET_FROM_INDEX : 0;
@@ -127,27 +123,18 @@
const char* action = add ? ADD : DEL;
- // A rule to route traffic based on an explicitly chosen network.
- //
- // Supports apps that use the multinetwork APIs to restrict their traffic to a network.
- //
- // We don't really need to check the permission bits of the fwmark here, as they would've been
- // checked at the time the netId was set into the fwmark, but we do so to be consistent.
- uint32_t fwmark = getFwmark(netId, FWMARK_USE_EXPLICIT, !FWMARK_USE_PROTECT, permission);
- uint32_t mask = getFwmarkMask(FWMARK_USE_NET_ID, FWMARK_USE_EXPLICIT, !FWMARK_USE_PROTECT,
- permission);
- if (!runIpRuleCommand(action, RULE_PRIORITY_PER_NETWORK_EXPLICIT, table, fwmark, mask, NULL)) {
- return false;
- }
+ Fwmark fwmark;
+ fwmark.permission = permission;
+
+ Fwmark mask;
+ mask.permission = permission;
// A rule to route traffic based on a chosen outgoing interface.
//
// Supports apps that use SO_BINDTODEVICE or IP_PKTINFO options and the kernel that already
// knows the outgoing interface (typically for link-local communications).
- fwmark = getFwmark(0, !FWMARK_USE_EXPLICIT, !FWMARK_USE_PROTECT, permission);
- mask = getFwmark(!FWMARK_USE_NET_ID, !FWMARK_USE_EXPLICIT, !FWMARK_USE_PROTECT, permission);
- if (!runIpRuleCommand(action, RULE_PRIORITY_PER_NETWORK_INTERFACE, table, fwmark, mask,
- interface)) {
+ if (!runIpRuleCommand(action, RULE_PRIORITY_PER_NETWORK_INTERFACE, table, fwmark.intValue,
+ mask.intValue, interface)) {
return false;
}
@@ -156,9 +143,23 @@
// This is for sockets that have not explicitly requested a particular network, but have been
// bound to one when they called connect(). This ensures that sockets connected on a particular
// network stay on that network even if the default network changes.
- fwmark = getFwmark(netId, !FWMARK_USE_EXPLICIT, !FWMARK_USE_PROTECT, permission);
- mask = getFwmarkMask(FWMARK_USE_NET_ID, !FWMARK_USE_EXPLICIT, !FWMARK_USE_PROTECT, permission);
- if (!runIpRuleCommand(action, RULE_PRIORITY_PER_NETWORK_NORMAL, table, fwmark, mask, NULL)) {
+ fwmark.netId = netId;
+ mask.netId = FWMARK_NET_ID_MASK;
+ if (!runIpRuleCommand(action, RULE_PRIORITY_PER_NETWORK_NORMAL, table, fwmark.intValue,
+ mask.intValue, NULL)) {
+ return false;
+ }
+
+ // A rule to route traffic based on an explicitly chosen network.
+ //
+ // Supports apps that use the multinetwork APIs to restrict their traffic to a network.
+ //
+ // We don't really need to check the permission bits of the fwmark here, as they would've been
+ // checked at the time the netId was set into the fwmark, but we do so to be consistent.
+ fwmark.explicitlySelected = true;
+ mask.explicitlySelected = true;
+ if (!runIpRuleCommand(action, RULE_PRIORITY_PER_NETWORK_EXPLICIT, table, fwmark.intValue,
+ mask.intValue, NULL)) {
return false;
}
@@ -188,11 +189,16 @@
return false;
}
- uint32_t fwmark = getFwmark(0, !FWMARK_USE_EXPLICIT, !FWMARK_USE_PROTECT, permission);
- uint32_t mask = getFwmarkMask(FWMARK_USE_NET_ID, !FWMARK_USE_EXPLICIT, !FWMARK_USE_PROTECT,
- permission);
+ Fwmark fwmark;
+ fwmark.netId = 0;
+ fwmark.permission = permission;
- return runIpRuleCommand(action, RULE_PRIORITY_DEFAULT_NETWORK, table, fwmark, mask, NULL);
+ Fwmark mask;
+ mask.netId = FWMARK_NET_ID_MASK;
+ mask.permission = permission;
+
+ return runIpRuleCommand(action, RULE_PRIORITY_DEFAULT_NETWORK, table, fwmark.intValue,
+ mask.intValue, NULL);
}
bool modifyRoute(const char* interface, const char* destination, const char* nexthop,
@@ -238,10 +244,13 @@
// default route, the rule we're adding will never be used for normal routing lookups. However,
// the kernel may fall-through to it to find directly-connected routes when it validates that a
// nexthop (in a route being added) is reachable.
- uint32_t fwmark = getFwmark(0, !FWMARK_USE_EXPLICIT, !FWMARK_USE_PROTECT, PERMISSION_NONE);
- uint32_t mask = getFwmarkMask(FWMARK_USE_NET_ID, !FWMARK_USE_EXPLICIT, !FWMARK_USE_PROTECT,
- PERMISSION_NONE);
- runIpRuleCommand(ADD, RULE_PRIORITY_MAIN, RT_TABLE_MAIN, fwmark, mask, NULL);
+ Fwmark fwmark;
+ fwmark.netId = 0;
+
+ Fwmark mask;
+ mask.netId = FWMARK_NET_ID_MASK;
+
+ runIpRuleCommand(ADD, RULE_PRIORITY_MAIN, RT_TABLE_MAIN, fwmark.intValue, mask.intValue, NULL);
// TODO: Uncomment once we are sure everything works.
#if 0