Merge "Move #nativeWaitForService into CommonConnectivityJni" into main
diff --git a/OWNERS_core_networking b/OWNERS_core_networking
index 4b73639..492ebd6 100644
--- a/OWNERS_core_networking
+++ b/OWNERS_core_networking
@@ -11,4 +11,4 @@
yuyanghuang@google.com
martinwu@google.com #{LAST_RESORT_SUGGESTION}
-satk@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
+larsberg@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
diff --git a/OWNERS_core_networking_xts b/OWNERS_core_networking_xts
index 60ca885..294b6e6 100644
--- a/OWNERS_core_networking_xts
+++ b/OWNERS_core_networking_xts
@@ -1,5 +1,5 @@
lorenzo@google.com
-satk@google.com #{LAST_RESORT_SUGGESTION}
+larsberg@google.com #{LAST_RESORT_SUGGESTION}
# For cherry-picks of CLs that are already merged in aosp/master, flaky test
# fixes, or no-op refactors.
diff --git a/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java b/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java
index 9b6097d..23e0545 100644
--- a/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java
+++ b/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java
@@ -33,6 +33,7 @@
import com.android.net.module.util.IBpfMap;
import com.android.net.module.util.IBpfMap.ThrowingBiConsumer;
import com.android.net.module.util.SharedLog;
+import com.android.net.module.util.Struct.S32;
import com.android.net.module.util.bpf.Tether4Key;
import com.android.net.module.util.bpf.Tether4Value;
import com.android.net.module.util.bpf.TetherStatsKey;
@@ -42,10 +43,7 @@
import com.android.networkstack.tethering.BpfCoordinator.Ipv6UpstreamRule;
import com.android.networkstack.tethering.BpfUtils;
import com.android.networkstack.tethering.Tether6Value;
-import com.android.networkstack.tethering.TetherDevKey;
-import com.android.networkstack.tethering.TetherDevValue;
import com.android.networkstack.tethering.TetherDownstream6Key;
-import com.android.networkstack.tethering.TetherLimitKey;
import com.android.networkstack.tethering.TetherLimitValue;
import com.android.networkstack.tethering.TetherUpstream6Key;
@@ -89,11 +87,11 @@
// BPF map of per-interface quota for tethering offload.
@Nullable
- private final IBpfMap<TetherLimitKey, TetherLimitValue> mBpfLimitMap;
+ private final IBpfMap<S32, TetherLimitValue> mBpfLimitMap;
// BPF map of interface index mapping for XDP.
@Nullable
- private final IBpfMap<TetherDevKey, TetherDevValue> mBpfDevMap;
+ private final IBpfMap<S32, S32> mBpfDevMap;
// Tracking IPv4 rule count while any rule is using the given upstream interfaces. Used for
// reducing the BPF map iteration query. The count is increased or decreased when the rule is
@@ -305,7 +303,7 @@
if (newLimit < rxBytes + txBytes) newLimit = QUOTA_UNLIMITED;
try {
- mBpfLimitMap.updateEntry(new TetherLimitKey(ifIndex), new TetherLimitValue(newLimit));
+ mBpfLimitMap.updateEntry(new S32(ifIndex), new TetherLimitValue(newLimit));
} catch (ErrnoException e) {
mLog.e("Fail to set quota " + quotaBytes + " for interface index " + ifIndex + ": ", e);
return false;
@@ -350,7 +348,7 @@
}
try {
- mBpfLimitMap.deleteEntry(new TetherLimitKey(ifIndex));
+ mBpfLimitMap.deleteEntry(new S32(ifIndex));
} catch (ErrnoException e) {
mLog.e("Could not delete limit for interface index " + ifIndex + ": ", e);
return null;
@@ -470,7 +468,7 @@
@Override
public boolean addDevMap(int ifIndex) {
try {
- mBpfDevMap.updateEntry(new TetherDevKey(ifIndex), new TetherDevValue(ifIndex));
+ mBpfDevMap.updateEntry(new S32(ifIndex), new S32(ifIndex));
} catch (ErrnoException e) {
mLog.e("Could not add interface " + ifIndex + ": " + e);
return false;
@@ -481,7 +479,7 @@
@Override
public boolean removeDevMap(int ifIndex) {
try {
- mBpfDevMap.deleteEntry(new TetherDevKey(ifIndex));
+ mBpfDevMap.deleteEntry(new S32(ifIndex));
} catch (ErrnoException e) {
mLog.e("Could not delete interface " + ifIndex + ": " + e);
return false;
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
index 57b7255..ef26e3b 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
@@ -460,11 +460,11 @@
}
/** Get limit BPF map. */
- @Nullable public IBpfMap<TetherLimitKey, TetherLimitValue> getBpfLimitMap() {
+ @Nullable public IBpfMap<S32, TetherLimitValue> getBpfLimitMap() {
if (!isAtLeastS()) return null;
try {
return new BpfMap<>(TETHER_LIMIT_MAP_PATH,
- TetherLimitKey.class, TetherLimitValue.class);
+ S32.class, TetherLimitValue.class);
} catch (ErrnoException e) {
Log.e(TAG, "Cannot create limit map: " + e);
return null;
@@ -472,11 +472,11 @@
}
/** Get dev BPF map. */
- @Nullable public IBpfMap<TetherDevKey, TetherDevValue> getBpfDevMap() {
+ @Nullable public IBpfMap<S32, S32> getBpfDevMap() {
if (!isAtLeastS()) return null;
try {
return new BpfMap<>(TETHER_DEV_MAP_PATH,
- TetherDevKey.class, TetherDevValue.class);
+ S32.class, S32.class);
} catch (ErrnoException e) {
Log.e(TAG, "Cannot create dev map: " + e);
return null;
@@ -1636,7 +1636,7 @@
}
private void dumpDevmap(@NonNull IndentingPrintWriter pw) {
- try (IBpfMap<TetherDevKey, TetherDevValue> map = mDeps.getBpfDevMap()) {
+ try (IBpfMap<S32, S32> map = mDeps.getBpfDevMap()) {
if (map == null) {
pw.println("No devmap support");
return;
@@ -1651,8 +1651,8 @@
// Only get upstream interface name. Just do the best to make the index readable.
// TODO: get downstream interface name because the index is either upstream or
// downstream interface in dev map.
- pw.println(String.format("%d (%s) -> %d (%s)", k.ifIndex, getIfName(k.ifIndex),
- v.ifIndex, getIfName(v.ifIndex)));
+ pw.println(String.format("%d (%s) -> %d (%s)", k.val, getIfName(k.val),
+ v.val, getIfName(v.val)));
});
} catch (ErrnoException | IOException e) {
pw.println("Error dumping dev map: " + e);
diff --git a/Tethering/src/com/android/networkstack/tethering/TetherDevKey.java b/Tethering/src/com/android/networkstack/tethering/TetherDevKey.java
deleted file mode 100644
index 997080c..0000000
--- a/Tethering/src/com/android/networkstack/tethering/TetherDevKey.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2021 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.
- */
-
-package com.android.networkstack.tethering;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/** The key of BpfMap which is used for mapping interface index. */
-public class TetherDevKey extends Struct {
- @Field(order = 0, type = Type.S32)
- public final int ifIndex; // interface index
-
- public TetherDevKey(final int ifIndex) {
- this.ifIndex = ifIndex;
- }
-}
diff --git a/Tethering/src/com/android/networkstack/tethering/TetherDevValue.java b/Tethering/src/com/android/networkstack/tethering/TetherDevValue.java
deleted file mode 100644
index b6e0c73..0000000
--- a/Tethering/src/com/android/networkstack/tethering/TetherDevValue.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2021 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.
- */
-
-package com.android.networkstack.tethering;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/** The key of BpfMap which is used for mapping interface index. */
-public class TetherDevValue extends Struct {
- @Field(order = 0, type = Type.S32)
- public final int ifIndex; // interface index
-
- public TetherDevValue(final int ifIndex) {
- this.ifIndex = ifIndex;
- }
-}
diff --git a/Tethering/src/com/android/networkstack/tethering/TetherLimitKey.java b/Tethering/src/com/android/networkstack/tethering/TetherLimitKey.java
deleted file mode 100644
index 68d694a..0000000
--- a/Tethering/src/com/android/networkstack/tethering/TetherLimitKey.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-package com.android.networkstack.tethering;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/** The key of BpfMap which is used for tethering per-interface limit. */
-public class TetherLimitKey extends Struct {
- @Field(order = 0, type = Type.S32)
- public final int ifindex; // upstream interface index
-
- public TetherLimitKey(final int ifindex) {
- this.ifindex = ifindex;
- }
-}
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
index 8183256..48332ce 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
@@ -482,10 +482,10 @@
spy(new TestBpfMap<>(TetherUpstream6Key.class, Tether6Value.class));
private final IBpfMap<TetherStatsKey, TetherStatsValue> mBpfStatsMap =
spy(new TestBpfMap<>(TetherStatsKey.class, TetherStatsValue.class));
- private final IBpfMap<TetherLimitKey, TetherLimitValue> mBpfLimitMap =
- spy(new TestBpfMap<>(TetherLimitKey.class, TetherLimitValue.class));
- private final IBpfMap<TetherDevKey, TetherDevValue> mBpfDevMap =
- spy(new TestBpfMap<>(TetherDevKey.class, TetherDevValue.class));
+ private final IBpfMap<S32, TetherLimitValue> mBpfLimitMap =
+ spy(new TestBpfMap<>(S32.class, TetherLimitValue.class));
+ private final IBpfMap<S32, S32> mBpfDevMap =
+ spy(new TestBpfMap<>(S32.class, S32.class));
private final IBpfMap<S32, S32> mBpfErrorMap =
spy(new TestBpfMap<>(S32.class, S32.class));
private BpfCoordinator.Dependencies mDeps =
@@ -559,12 +559,12 @@
}
@Nullable
- public IBpfMap<TetherLimitKey, TetherLimitValue> getBpfLimitMap() {
+ public IBpfMap<S32, TetherLimitValue> getBpfLimitMap() {
return mBpfLimitMap;
}
@Nullable
- public IBpfMap<TetherDevKey, TetherDevValue> getBpfDevMap() {
+ public IBpfMap<S32, S32> getBpfDevMap() {
return mBpfDevMap;
}
@@ -932,7 +932,7 @@
0L /* rxPackets */, 0L /* rxBytes */, 0L /* rxErrors */,
0L /* txPackets */, 0L /* txBytes */, 0L /* txErrors */));
}
- verifyWithOrder(inOrder, mBpfLimitMap).updateEntry(new TetherLimitKey(ifIndex),
+ verifyWithOrder(inOrder, mBpfLimitMap).updateEntry(new S32(ifIndex),
new TetherLimitValue(quotaBytes));
} else {
verifyWithOrder(inOrder, mNetd).tetherOffloadSetInterfaceQuota(ifIndex, quotaBytes);
@@ -955,7 +955,7 @@
if (mDeps.isAtLeastS()) {
inOrder.verify(mBpfStatsMap).getValue(new TetherStatsKey(ifIndex));
inOrder.verify(mBpfStatsMap).deleteEntry(new TetherStatsKey(ifIndex));
- inOrder.verify(mBpfLimitMap).deleteEntry(new TetherLimitKey(ifIndex));
+ inOrder.verify(mBpfLimitMap).deleteEntry(new S32(ifIndex));
} else {
inOrder.verify(mNetd).tetherOffloadGetAndClearStats(ifIndex);
}
@@ -1972,10 +1972,10 @@
dispatchIpv6UpstreamChanged(
coordinator, mIpServer, UPSTREAM_IFINDEX, UPSTREAM_IFACE, UPSTREAM_PREFIXES);
- verify(mBpfDevMap).updateEntry(eq(new TetherDevKey(UPSTREAM_IFINDEX)),
- eq(new TetherDevValue(UPSTREAM_IFINDEX)));
- verify(mBpfDevMap).updateEntry(eq(new TetherDevKey(DOWNSTREAM_IFINDEX)),
- eq(new TetherDevValue(DOWNSTREAM_IFINDEX)));
+ verify(mBpfDevMap).updateEntry(eq(new S32(UPSTREAM_IFINDEX)),
+ eq(new S32(UPSTREAM_IFINDEX)));
+ verify(mBpfDevMap).updateEntry(eq(new S32(DOWNSTREAM_IFINDEX)),
+ eq(new S32(DOWNSTREAM_IFINDEX)));
clearInvocations(mBpfDevMap);
// Adding the second downstream, only the second downstream ifindex is added to DevMap,
@@ -1983,10 +1983,10 @@
coordinator.addIpServer(mIpServer2);
dispatchIpv6UpstreamChanged(
coordinator, mIpServer2, UPSTREAM_IFINDEX, UPSTREAM_IFACE, UPSTREAM_PREFIXES);
- verify(mBpfDevMap).updateEntry(eq(new TetherDevKey(DOWNSTREAM_IFINDEX2)),
- eq(new TetherDevValue(DOWNSTREAM_IFINDEX2)));
- verify(mBpfDevMap, never()).updateEntry(eq(new TetherDevKey(UPSTREAM_IFINDEX)),
- eq(new TetherDevValue(UPSTREAM_IFINDEX)));
+ verify(mBpfDevMap).updateEntry(eq(new S32(DOWNSTREAM_IFINDEX2)),
+ eq(new S32(DOWNSTREAM_IFINDEX2)));
+ verify(mBpfDevMap, never()).updateEntry(eq(new S32(UPSTREAM_IFINDEX)),
+ eq(new S32(UPSTREAM_IFINDEX)));
}
@Test
@@ -1999,10 +1999,10 @@
.setMsgType(IPCTNL_MSG_CT_NEW)
.setProto(IPPROTO_TCP)
.build());
- verify(mBpfDevMap).updateEntry(eq(new TetherDevKey(UPSTREAM_IFINDEX)),
- eq(new TetherDevValue(UPSTREAM_IFINDEX)));
- verify(mBpfDevMap).updateEntry(eq(new TetherDevKey(DOWNSTREAM_IFINDEX)),
- eq(new TetherDevValue(DOWNSTREAM_IFINDEX)));
+ verify(mBpfDevMap).updateEntry(eq(new S32(UPSTREAM_IFINDEX)),
+ eq(new S32(UPSTREAM_IFINDEX)));
+ verify(mBpfDevMap).updateEntry(eq(new S32(DOWNSTREAM_IFINDEX)),
+ eq(new S32(DOWNSTREAM_IFINDEX)));
clearInvocations(mBpfDevMap);
mConsumer.accept(new TestConntrackEvent.Builder()
@@ -2737,8 +2737,8 @@
// dumpDevmap
coordinator.maybeAddUpstreamToLookupTable(UPSTREAM_IFINDEX, UPSTREAM_IFACE);
mBpfDevMap.insertEntry(
- new TetherDevKey(UPSTREAM_IFINDEX),
- new TetherDevValue(UPSTREAM_IFINDEX));
+ new S32(UPSTREAM_IFINDEX),
+ new S32(UPSTREAM_IFINDEX));
// dumpCounters
// The error code is defined in packages/modules/Connectivity/bpf_progs/offload.h.
diff --git a/bpf/loader/NetBpfLoad.cpp b/bpf/loader/NetBpfLoad.cpp
index c8eb53c..93547a9 100644
--- a/bpf/loader/NetBpfLoad.cpp
+++ b/bpf/loader/NetBpfLoad.cpp
@@ -107,61 +107,9 @@
return getBuildType() == "userdebug";
}
-#define BPF_FS_PATH "/sys/fs/bpf/"
-
static unsigned int page_size = static_cast<unsigned int>(getpagesize());
typedef struct {
- const char* name;
- enum bpf_prog_type type;
- enum bpf_attach_type attach_type;
-} sectionType;
-
-/*
- * Map section name prefixes to program types, the section name will be:
- * SECTION(<prefix>/<name-of-program>)
- * For example:
- * SECTION("tracepoint/sched_switch_func") where sched_switch_funcs
- * is the name of the program, and tracepoint is the type.
- *
- * However, be aware that you should not be directly using the SECTION() macro.
- * Instead use the DEFINE_(BPF|XDP)_(PROG|MAP)... & LICENSE macros.
- *
- * Programs shipped inside the tethering apex should be limited to networking stuff,
- * as KPROBE, PERF_EVENT, TRACEPOINT are dangerous to use from mainline updatable code,
- * since they are less stable abi/api and may conflict with platform uses of bpf.
- */
-sectionType sectionNameTypes[] = {
- {"bind4/", BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_BIND},
- {"bind6/", BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_BIND},
- {"cgroupskb/", BPF_PROG_TYPE_CGROUP_SKB},
- {"cgroupsock/", BPF_PROG_TYPE_CGROUP_SOCK},
- {"cgroupsockcreate/", BPF_PROG_TYPE_CGROUP_SOCK, BPF_CGROUP_INET_SOCK_CREATE},
- {"cgroupsockrelease/", BPF_PROG_TYPE_CGROUP_SOCK, BPF_CGROUP_INET_SOCK_RELEASE},
- {"connect4/", BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_CONNECT},
- {"connect6/", BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_CONNECT},
- {"egress/", BPF_PROG_TYPE_CGROUP_SKB, BPF_CGROUP_INET_EGRESS},
- {"getsockopt/", BPF_PROG_TYPE_CGROUP_SOCKOPT, BPF_CGROUP_GETSOCKOPT},
- {"ingress/", BPF_PROG_TYPE_CGROUP_SKB, BPF_CGROUP_INET_INGRESS},
- {"postbind4/", BPF_PROG_TYPE_CGROUP_SOCK, BPF_CGROUP_INET4_POST_BIND},
- {"postbind6/", BPF_PROG_TYPE_CGROUP_SOCK, BPF_CGROUP_INET6_POST_BIND},
- {"recvmsg4/", BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP4_RECVMSG},
- {"recvmsg6/", BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_RECVMSG},
- {"schedact/", BPF_PROG_TYPE_SCHED_ACT},
- {"schedcls/", BPF_PROG_TYPE_SCHED_CLS},
- {"sendmsg4/", BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP4_SENDMSG},
- {"sendmsg6/", BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_SENDMSG},
- {"setsockopt/", BPF_PROG_TYPE_CGROUP_SOCKOPT, BPF_CGROUP_SETSOCKOPT},
- {"skfilter/", BPF_PROG_TYPE_SOCKET_FILTER},
- {"sockops/", BPF_PROG_TYPE_SOCK_OPS, BPF_CGROUP_SOCK_OPS},
- {"sysctl", BPF_PROG_TYPE_CGROUP_SYSCTL, BPF_CGROUP_SYSCTL},
- {"xdp/", BPF_PROG_TYPE_XDP},
-};
-
-typedef struct {
- enum bpf_prog_type type;
- enum bpf_attach_type attach_type;
- string name; // The canonicalized section name.
string program_name;
vector<char> data;
vector<char> rel_data;
@@ -404,37 +352,35 @@
entries = shTable.size();
vector<struct bpf_prog_def> pd;
- ret = elfObj.readSectionByName("progs", pd);
+ ret = elfObj.readSectionByName(".android_progs", pd);
if (ret) return ret;
vector<string> progDefNames;
- ret = elfObj.getSectionSymNames("progs", progDefNames);
+ ret = elfObj.getSectionSymNames(".android_progs", progDefNames);
if (!pd.empty() && ret) return ret;
for (int i = 0; i < entries; i++) {
string name;
codeSection cs_temp;
- cs_temp.type = BPF_PROG_TYPE_UNSPEC;
ret = elfObj.getSymName(shTable[i].sh_name, name);
if (ret) return ret;
- // This must be done before '/' is replaced with '_'.
- for (auto& snt : sectionNameTypes) {
- if (StartsWith(name, snt.name)) {
- cs_temp.type = snt.type;
- cs_temp.attach_type = snt.attach_type;
- break;
- }
- }
+ // all we want to process is sections FOO/BAR, but:
+ // - section 0 has an empty name (experimentally observed)
+ // - .relFOO/BAR would break us later (relocations)
+ // - 'license' is special, but doesn't have a /
+ if (name[0] == '.') continue;
- if (cs_temp.type == BPF_PROG_TYPE_UNSPEC) continue;
+ // Find the first slash
+ size_t first_slash_pos = name.find('/');
+
+ // Ignore sections without a / (basically 'license' section)
+ if (first_slash_pos == std::string::npos) continue;
string oldName = name;
+ name[first_slash_pos] = '_';
- // convert all slashes to underscores
- std::replace(name.begin(), name.end(), '/', '_');
-
- cs_temp.name = name;
+ if (name.find('/') != std::string::npos) abort(); // There should only be one!
ret = elfObj.readSectionByIdx(i, cs_temp.data);
if (ret) return ret;
@@ -451,6 +397,8 @@
}
}
+ if (!cs_temp.prog_def) abort();
+
// Check for rel section
if (cs_temp.data.size() > 0 && i < entries) {
ret = elfObj.getSymName(shTable[i + 1].sh_name, name);
@@ -1013,8 +961,7 @@
}
}
-static int pinProg(const borrowed_fd& fd, const struct bpf_prog_def& progDef,
- const string& progPinLoc) {
+static int pinProg(const borrowed_fd& fd, const struct bpf_prog_def& progDef) {
int ret;
if (progDef.create_location[0]) {
ret = bpfFdPin(fd, progDef.create_location);
@@ -1024,37 +971,37 @@
return -err;
}
ret = renameat2(AT_FDCWD, progDef.create_location,
- AT_FDCWD, progPinLoc.c_str(), RENAME_NOREPLACE);
+ AT_FDCWD, progDef.pin_location, RENAME_NOREPLACE);
if (ret) {
const int err = errno;
- ALOGE("rename %s %s -> %d [%d:%s]", progDef.create_location, progPinLoc.c_str(), ret,
+ ALOGE("rename %s %s -> %d [%d:%s]", progDef.create_location, progDef.pin_location, ret,
err, strerror(err));
return -err;
}
} else {
- ret = bpfFdPin(fd, progPinLoc.c_str());
+ ret = bpfFdPin(fd, progDef.pin_location);
if (ret) {
const int err = errno;
- ALOGE("create %s -> %d [%d:%s]", progPinLoc.c_str(), ret, err, strerror(err));
+ ALOGE("create %s -> %d [%d:%s]", progDef.pin_location, ret, err, strerror(err));
return -err;
}
}
- if (chmod(progPinLoc.c_str(), 0440)) {
+ if (chmod(progDef.pin_location, 0440)) {
const int err = errno;
- ALOGE("chmod %s 0440 -> [%d:%s]", progPinLoc.c_str(), err, strerror(err));
+ ALOGE("chmod %s 0440 -> [%d:%s]", progDef.pin_location, err, strerror(err));
return -err;
}
- if (chown(progPinLoc.c_str(), (uid_t)progDef.uid,
+ if (chown(progDef.pin_location, (uid_t)progDef.uid,
(gid_t)progDef.gid)) {
const int err = errno;
- ALOGE("chown %s %d %d -> [%d:%s]", progPinLoc.c_str(), progDef.uid,
+ ALOGE("chown %s %d %d -> [%d:%s]", progDef.pin_location, progDef.uid,
progDef.gid, err, strerror(err));
return -err;
}
return 0;
}
-static int validateProg(const borrowed_fd& fd, string& progPinLoc,
+static int validateProg(const borrowed_fd& fd, const char* const progPinLoc,
const unsigned int bpfloader_ver) {
if (!isAtLeastKernelVersion(4, 14, 0)) {
return 0;
@@ -1079,10 +1026,10 @@
ALOGE("bpfGetFdXlatProgLen failed, ret: %d", err);
return -err;
}
- ALOGI("prog %s id %d len jit:%d xlat:%d", progPinLoc.c_str(), progId, jitLen, xlatLen);
+ ALOGI("prog %s id %d len jit:%d xlat:%d", progPinLoc, progId, jitLen, xlatLen);
if (!jitLen && bpfloader_ver >= BPFLOADER_MAINLINE_25Q2_VERSION) {
- ALOGE("Kernel eBPF JIT failure for %s", progPinLoc.c_str());
+ ALOGE("Kernel eBPF JIT failure for %s", progPinLoc);
return -ENOTSUP;
}
return 0;
@@ -1100,55 +1047,48 @@
for (int i = 0; i < (int)cs.size(); i++) {
unique_fd& fd = cs[i].prog_fd;
int ret;
- string name = cs[i].name;
if (!cs[i].prog_def.has_value()) {
- ALOGE("[%d] '%s' missing program definition! bad bpf.o build?", i, name.c_str());
+ ALOGE("[%d] missing program definition! bad bpf.o build?", i);
return -EINVAL;
}
unsigned min_kver = cs[i].prog_def->min_kver;
unsigned max_kver = cs[i].prog_def->max_kver;
- ALOGD("cs[%d].name:%s min_kver:%x .max_kver:%x (kvers:%x)", i, name.c_str(), min_kver,
- max_kver, kvers);
+ ALOGD("cs[%d].name:%s min_kver:%x .max_kver:%x (kvers:%x)",
+ i, cs[i].prog_def->name(), min_kver, max_kver, kvers);
if (kvers < min_kver) continue;
if (kvers >= max_kver) continue;
unsigned bpfMinVer = cs[i].prog_def->bpfloader_min_ver;
unsigned bpfMaxVer = cs[i].prog_def->bpfloader_max_ver;
- ALOGD("cs[%d].name:%s requires bpfloader version [0x%05x,0x%05x)", i, name.c_str(),
- bpfMinVer, bpfMaxVer);
+ ALOGD("cs[%d].name:%s requires bpfloader version [0x%05x,0x%05x)",
+ i, cs[i].prog_def->name(), bpfMinVer, bpfMaxVer);
if (bpfloader_ver < bpfMinVer) continue;
if (bpfloader_ver >= bpfMaxVer) continue;
- // strip any potential $foo suffix
- // this can be used to provide duplicate programs
- // conditionally loaded based on running kernel version
- name = name.substr(0, name.find_last_of('$'));
-
bool reuse = false;
- string progPinLoc = string(cs[i].prog_def->pin_prefix) + name;
- if (access(progPinLoc.c_str(), F_OK) == 0) {
- fd.reset(retrieveProgram(progPinLoc.c_str()));
- ALOGD("New bpf prog load reusing prog %s, ret: %d (%s)", progPinLoc.c_str(), fd.get(),
+ if (access(cs[i].prog_def->pin_location, F_OK) == 0) {
+ fd.reset(retrieveProgram(cs[i].prog_def->pin_location));
+ ALOGD("New bpf prog load reusing prog %s, ret: %d (%s)", cs[i].prog_def->pin_location, fd.get(),
!fd.ok() ? std::strerror(errno) : "ok");
reuse = true;
} else {
static char log_buf[1 << 20]; // 1 MiB logging buffer
union bpf_attr req = {
- .prog_type = cs[i].type,
+ .prog_type = cs[i].prog_def->type,
.insn_cnt = static_cast<__u32>(cs[i].data.size() / sizeof(struct bpf_insn)),
.insns = ptr_to_u64(cs[i].data.data()),
.license = ptr_to_u64(license.c_str()),
.log_level = 1,
.log_size = sizeof(log_buf),
.log_buf = ptr_to_u64(log_buf),
- .expected_attach_type = cs[i].attach_type,
+ .expected_attach_type = cs[i].prog_def->attach_type,
};
if (isAtLeastKernelVersion(4, 15, 0))
- strlcpy(req.prog_name, cs[i].name.c_str(), sizeof(req.prog_name));
+ strlcpy(req.prog_name, cs[i].prog_def->name(), sizeof(req.prog_name));
fd.reset(bpf(BPF_PROG_LOAD, req));
// Kernel should have NULL terminated the log buffer, but force it anyway for safety
@@ -1161,7 +1101,7 @@
bool log_oneline = !strchr(log_buf, '\n');
ALOGD("BPF_PROG_LOAD call for %s (%s) returned '%s' fd: %d (%s)", elfObj.path,
- cs[i].name.c_str(), log_oneline ? log_buf : "{multiline}",
+ cs[i].prog_def->name(), log_oneline ? log_buf : "{multiline}",
fd.get(), !fd.ok() ? std::strerror(errno) : "ok");
if (!fd.ok()) {
@@ -1176,20 +1116,20 @@
if (cs[i].prog_def->optional) {
ALOGW("failed program %s is marked optional - continuing...",
- cs[i].name.c_str());
+ cs[i].prog_def->name());
continue;
}
- ALOGE("non-optional program %s failed to load.", cs[i].name.c_str());
+ ALOGE("non-optional program %s failed to load.", cs[i].prog_def->name());
}
}
if (!fd.ok()) return fd.get();
if (!reuse) {
- ret = pinProg(fd, cs[i].prog_def.value(), progPinLoc);
+ ret = pinProg(fd, cs[i].prog_def.value());
if (ret) return ret;
}
- ret = validateProg(fd, progPinLoc, bpfloader_ver);
+ ret = validateProg(fd, cs[i].prog_def->pin_location, bpfloader_ver);
if (ret) return ret;
}
@@ -1239,9 +1179,8 @@
unsigned kvers = kernelVersion();
for (int i = 0; i < (int)cs.size(); i++) {
- string name = cs[i].name;
if (!cs[i].prog_def.has_value()) {
- ALOGE("[%d] '%s' missing program definition! bad bpf.o build?", i, name.c_str());
+ ALOGE("[%d] missing program definition! bad bpf.o build?", i);
return -EINVAL;
}
string program_name = cs[i].program_name;
@@ -1255,7 +1194,7 @@
unsigned max_kver = cs[i].prog_def->max_kver;
if (kvers < min_kver || kvers >= max_kver) {
ALOGD("skipping prog %s: kernel version 0x%x is outside required range [0x%x, 0x%x)",
- name.c_str(), kvers, min_kver, max_kver);
+ cs[i].prog_def->name(), kvers, min_kver, max_kver);
bpf_program__set_autoload(prog, false);
continue;
}
@@ -1264,7 +1203,7 @@
unsigned bpfMaxVer = cs[i].prog_def->bpfloader_max_ver;
if (bpfloader_ver < bpfMinVer || bpfloader_ver >= bpfMaxVer) {
ALOGD("skipping prog %s: bpfloader 0x%05x is outside required range [0x%05x, 0x%05x)",
- name.c_str(), bpfloader_ver, bpfMinVer, bpfMaxVer);
+ cs[i].prog_def->name(), bpfloader_ver, bpfMinVer, bpfMaxVer);
bpf_program__set_autoload(prog, false);
continue;
}
@@ -1275,8 +1214,8 @@
return -1;
}
- bpf_program__set_type(prog, cs[i].type);
- bpf_program__set_expected_attach_type(prog, cs[i].attach_type);
+ bpf_program__set_type(prog, cs[i].prog_def->type);
+ bpf_program__set_expected_attach_type(prog, cs[i].prog_def->attach_type);
}
return 0;
}
@@ -1316,19 +1255,16 @@
// This program was skipped
if (!bpf_program__autoload(prog)) continue;
- string name = cs[i].name;
- name = name.substr(0, name.find_last_of('$'));
- string progPinLoc = string(cs[i].prog_def->pin_prefix) + name;
- if (access(progPinLoc.c_str(), F_OK) == 0) {
+ if (access(cs[i].prog_def->pin_location, F_OK) == 0) {
// TODO: Skip loading lower priority program
- ALOGI("Higher priority program is already pinned, skip pinning %s", cs[i].name.c_str());
+ ALOGI("Higher priority program is already pinned, skip pinning %s", cs[i].prog_def->name());
continue;
}
int fd = bpf_program__fd(prog);
- ret = pinProg(fd, cs[i].prog_def.value(), progPinLoc);
+ ret = pinProg(fd, cs[i].prog_def.value());
if (ret) return ret;
- ret = validateProg(fd, progPinLoc, bpfloader_ver);
+ ret = validateProg(fd, cs[i].prog_def->pin_location, bpfloader_ver);
if (ret) return ret;
}
return 0;
@@ -1426,47 +1362,30 @@
abort(); // can only hit this if permissions (likely selinux) are screwed up
}
+static bool loadObject(const unsigned int bpfloader_ver,
+ const char* const progPath, const bool useLibbpf = false) {
+ if (useLibbpf ? loadProgByLibbpf(progPath, bpfloader_ver) :
+ loadProg(progPath, bpfloader_ver)) {
+ ALOGE("Failed to load object: %s, libbpf: %d", progPath, useLibbpf);
+ return false;
+ }
+ ALOGD("Loaded object: %s, libbpf: %d", progPath, useLibbpf);
+ return true;
+}
+
#define APEXROOT "/apex/com.android.tethering"
#define BPFROOT APEXROOT "/etc/bpf/mainline/"
-static int loadObject(const unsigned int bpfloader_ver,
- const char* const fname, const bool useLibbpf = false) {
- string progPath = string(BPFROOT) + fname;
- int ret = useLibbpf ? loadProgByLibbpf(progPath.c_str(), bpfloader_ver) :
- loadProg(progPath.c_str(), bpfloader_ver);
- if (ret) {
- ALOGE("Failed to load object: %s, ret: %s, libbpf: %d",
- progPath.c_str(), std::strerror(-ret), useLibbpf);
- return 1;
- }
- ALOGD("Loaded object: %s, libbpf: %d", progPath.c_str(), useLibbpf);
- return 0;
-}
-
-static int loadAllObjects(const unsigned int bpfloader_ver) {
- // S+ Tethering mainline module (network_stack): tether offload
- // loads under /sys/fs/bpf/tethering:
- if (loadObject(bpfloader_ver, "offload.o")) return 1;
- if (loadObject(bpfloader_ver, "test.o", isAtLeast25Q3)) return 1;
+static bool loadAllObjects(const unsigned int bpfloader_ver) {
+ bool libbpf = isAtLeast25Q3;
+ if (!loadObject(bpfloader_ver, BPFROOT "offload.o")) return false;
+ if (!loadObject(bpfloader_ver, BPFROOT "test.o", libbpf)) return false;
if (isAtLeastT) {
- // T+ Tethering mainline module loads under:
- // /sys/fs/bpf/net_shared: shared with netd & system server
- if (loadObject(bpfloader_ver, "clatd.o", isAtLeast25Q3)) return 1;
- if (loadObject(bpfloader_ver, "dscpPolicy.o", isAtLeast25Q3)) return 1;
-
- // /sys/fs/bpf/netd_shared: shared with netd & system server
- // - netutils_wrapper (for iptables xt_bpf) has access to programs
-
- // WARNING: Android T+ non-updatable netd depends on both of the
- // 'netd_shared' & 'netd' strings for xt_bpf programs it loads
- if (loadObject(bpfloader_ver, "netd.o", isAtLeast25Q3)) return 1;
-
- // /sys/fs/bpf/netd_readonly: shared with netd & system server
- // - netutils_wrapper has no access, netd has read only access
-
- // /sys/fs/bpf/net_private: not shared, just network_stack
+ if (!loadObject(bpfloader_ver, BPFROOT "clatd.o", libbpf)) return false;
+ if (!loadObject(bpfloader_ver, BPFROOT "dscpPolicy.o", libbpf)) return false;
+ if (!loadObject(bpfloader_ver, BPFROOT "netd.o", libbpf)) return false;
}
- return 0;
+ return true;
}
static bool createDir(const char* const dir) {
@@ -1952,7 +1871,7 @@
}
// Load all ELF objects, create programs and maps, and pin them
- if (loadAllObjects(bpfloader_ver)) {
+ if (!loadAllObjects(bpfloader_ver)) {
ALOGE("=== CRITICAL FAILURE LOADING BPF PROGRAMS ===");
ALOGE("If this triggers reliably, you're probably missing kernel options or patches.");
ALOGE("If this triggers randomly, you might be hitting some memory allocation "
diff --git a/bpf/progs/bpf_net_helpers.h b/bpf/progs/bpf_net_helpers.h
index 4085ed4..a41d8af 100644
--- a/bpf/progs/bpf_net_helpers.h
+++ b/bpf/progs/bpf_net_helpers.h
@@ -92,15 +92,15 @@
static uint32_t (*bpf_get_socket_uid)(struct __sk_buff* skb) = (void*)BPF_FUNC_get_socket_uid;
-static int (*bpf_skb_pull_data)(struct __sk_buff* skb, __u32 len) = (void*)BPF_FUNC_skb_pull_data;
+static long (*bpf_skb_pull_data)(struct __sk_buff* skb, __u32 len) = (void*)BPF_FUNC_skb_pull_data;
-static int (*bpf_skb_load_bytes)(const struct __sk_buff* skb, int off, void* to,
- int len) = (void*)BPF_FUNC_skb_load_bytes;
+static long (*bpf_skb_load_bytes)(const struct __sk_buff* skb, int off, void* to,
+ int len) = (void*)BPF_FUNC_skb_load_bytes;
-static int (*bpf_skb_load_bytes_relative)(const struct __sk_buff* skb, int off, void* to, int len,
- int start_hdr) = (void*)BPF_FUNC_skb_load_bytes_relative;
+static long (*bpf_skb_load_bytes_relative)(const struct __sk_buff* skb, int off, void* to, int len,
+ int start_hdr) = (void*)BPF_FUNC_skb_load_bytes_relative;
-static int (*bpf_skb_store_bytes)(struct __sk_buff* skb, __u32 offset, const void* from, __u32 len,
+static long (*bpf_skb_store_bytes)(struct __sk_buff* skb, __u32 offset, const void* from, __u32 len,
__u64 flags) = (void*)BPF_FUNC_skb_store_bytes;
static int64_t (*bpf_csum_diff)(__be32* from, __u32 from_size, __be32* to, __u32 to_size,
@@ -108,20 +108,20 @@
static int64_t (*bpf_csum_update)(struct __sk_buff* skb, __wsum csum) = (void*)BPF_FUNC_csum_update;
-static int (*bpf_skb_change_proto)(struct __sk_buff* skb, __be16 proto,
- __u64 flags) = (void*)BPF_FUNC_skb_change_proto;
-static int (*bpf_l3_csum_replace)(struct __sk_buff* skb, __u32 offset, __u64 from, __u64 to,
- __u64 flags) = (void*)BPF_FUNC_l3_csum_replace;
-static int (*bpf_l4_csum_replace)(struct __sk_buff* skb, __u32 offset, __u64 from, __u64 to,
- __u64 flags) = (void*)BPF_FUNC_l4_csum_replace;
-static int (*bpf_redirect)(__u32 ifindex, __u64 flags) = (void*)BPF_FUNC_redirect;
-static int (*bpf_redirect_map)(const struct bpf_map_def* map, __u32 key,
- __u64 flags) = (void*)BPF_FUNC_redirect_map;
+static long (*bpf_skb_change_proto)(struct __sk_buff* skb, __be16 proto,
+ __u64 flags) = (void*)BPF_FUNC_skb_change_proto;
+static long (*bpf_l3_csum_replace)(struct __sk_buff* skb, __u32 offset, __u64 from, __u64 to,
+ __u64 flags) = (void*)BPF_FUNC_l3_csum_replace;
+static long (*bpf_l4_csum_replace)(struct __sk_buff* skb, __u32 offset, __u64 from, __u64 to,
+ __u64 flags) = (void*)BPF_FUNC_l4_csum_replace;
+static long (*bpf_redirect)(__u32 ifindex, __u64 flags) = (void*)BPF_FUNC_redirect;
+static long (*bpf_redirect_map)(const struct bpf_map_def* map, __u32 key,
+ __u64 flags) = (void*)BPF_FUNC_redirect_map;
-static int (*bpf_skb_change_head)(struct __sk_buff* skb, __u32 head_room,
- __u64 flags) = (void*)BPF_FUNC_skb_change_head;
-static int (*bpf_skb_adjust_room)(struct __sk_buff* skb, __s32 len_diff, __u32 mode,
- __u64 flags) = (void*)BPF_FUNC_skb_adjust_room;
+static long (*bpf_skb_change_head)(struct __sk_buff* skb, __u32 head_room,
+ __u64 flags) = (void*)BPF_FUNC_skb_change_head;
+static long (*bpf_skb_adjust_room)(struct __sk_buff* skb, __s32 len_diff, __u32 mode,
+ __u64 flags) = (void*)BPF_FUNC_skb_adjust_room;
// Android only supports little endian architectures
#define htons(x) (__builtin_constant_p(x) ? ___constant_swab16(x) : __builtin_bswap16(x))
diff --git a/bpf/progs/clatd.c b/bpf/progs/clatd.c
index 0560774..017d742 100644
--- a/bpf/progs/clatd.c
+++ b/bpf/progs/clatd.c
@@ -247,29 +247,29 @@
return TC_ACT_PIPE;
}
-DEFINE_BPF_PROG_KVER("schedcls/ingress6/clat_ether$4_14", AID_ROOT, AID_SYSTEM, sched_cls_ingress6_clat_ether_4_14, KVER_4_14)
+DEFINE_BPF_PROG_KVER(schedcls, ingress6_clat_ether, 4_14, AID_SYSTEM, 4_14)
(struct __sk_buff* skb) {
return nat64(skb, ETHER, KVER_4_14);
}
-DEFINE_BPF_PROG_KVER_RANGE("schedcls/ingress6/clat_ether$4_9", AID_ROOT, AID_SYSTEM, sched_cls_ingress6_clat_ether_4_9, KVER_NONE, KVER_4_14)
+DEFINE_BPF_PROG_KVER_RANGE(schedcls, ingress6_clat_ether, 4_9, AID_SYSTEM, 4_9, 4_14)
(struct __sk_buff* skb) {
- return nat64(skb, ETHER, KVER_NONE);
+ return nat64(skb, ETHER, KVER_4_9);
}
-DEFINE_BPF_PROG_KVER("schedcls/ingress6/clat_rawip$4_14", AID_ROOT, AID_SYSTEM, sched_cls_ingress6_clat_rawip_4_14, KVER_4_14)
+DEFINE_BPF_PROG_KVER(schedcls, ingress6_clat_rawip, 4_14, AID_SYSTEM, 4_14)
(struct __sk_buff* skb) {
return nat64(skb, RAWIP, KVER_4_14);
}
-DEFINE_BPF_PROG_KVER_RANGE("schedcls/ingress6/clat_rawip$4_9", AID_ROOT, AID_SYSTEM, sched_cls_ingress6_clat_rawip_4_9, KVER_NONE, KVER_4_14)
+DEFINE_BPF_PROG_KVER_RANGE(schedcls, ingress6_clat_rawip, 4_9, AID_SYSTEM, 4_9, 4_14)
(struct __sk_buff* skb) {
- return nat64(skb, RAWIP, KVER_NONE);
+ return nat64(skb, RAWIP, KVER_4_9);
}
DEFINE_BPF_MAP_GRW(clat_egress4_map, HASH, ClatEgress4Key, ClatEgress4Value, 16, AID_SYSTEM)
-DEFINE_BPF_PROG("schedcls/egress4/clat_rawip", AID_ROOT, AID_SYSTEM, sched_cls_egress4_clat_rawip)
+DEFINE_BPF_PROG(schedcls, egress4_clat_rawip, , AID_SYSTEM)
(struct __sk_buff* skb) {
// Must be meta-ethernet IPv4 frame
if (skb->protocol != htons(ETH_P_IP)) return TC_ACT_PIPE;
diff --git a/bpf/progs/dscpPolicy.c b/bpf/progs/dscpPolicy.c
index 3305aad..8b98b78 100644
--- a/bpf/progs/dscpPolicy.c
+++ b/bpf/progs/dscpPolicy.c
@@ -264,8 +264,7 @@
return;
}
-DEFINE_BPF_PROG_KVER("schedcls/set_dscp_ether", AID_ROOT, AID_SYSTEM, schedcls_set_dscp_ether,
- KVER_5_15)
+DEFINE_BPF_PROG_KVER(schedcls, set_dscp_ether, , AID_SYSTEM, 5_15)
(struct __sk_buff* skb) {
if (skb->pkt_type != PACKET_HOST) return TC_ACT_PIPE;
diff --git a/bpf/progs/include/bpf_helpers.h b/bpf/progs/include/bpf_helpers.h
index a0c12d0..b68ad2b 100644
--- a/bpf/progs/include/bpf_helpers.h
+++ b/bpf/progs/include/bpf_helpers.h
@@ -61,7 +61,6 @@
struct kver_uint { unsigned int kver; };
#define KVER_(v) ((struct kver_uint){ .kver = (v) })
#define KVER(a, b, c) KVER_(((a) << 24) + ((b) << 16) + (c))
-#define KVER_NONE KVER_(0)
#define KVER_4_9 KVER(4, 9, 0)
#define KVER_4_14 KVER(4, 14, 0)
#define KVER_4_19 KVER(4, 19, 0)
@@ -207,13 +206,13 @@
*/
static void* (*bpf_map_lookup_elem_unsafe)(const void* map,
const void* key) = (void*)BPF_FUNC_map_lookup_elem;
-static int (*bpf_map_update_elem_unsafe)(const void* map, const void* key,
- const void* value, unsigned long long flags) = (void*)
+static long (*bpf_map_update_elem_unsafe)(const void* map, const void* key,
+ const void* value, unsigned long long flags) = (void*)
BPF_FUNC_map_update_elem;
-static int (*bpf_map_delete_elem_unsafe)(const void* map,
- const void* key) = (void*)BPF_FUNC_map_delete_elem;
-static int (*bpf_ringbuf_output_unsafe)(const void* ringbuf,
- const void* data, __u64 size, __u64 flags) = (void*)
+static long (*bpf_map_delete_elem_unsafe)(const void* map,
+ const void* key) = (void*)BPF_FUNC_map_delete_elem;
+static long (*bpf_ringbuf_output_unsafe)(const void* ringbuf,
+ const void* data, __u64 size, __u64 flags) = (void*)
BPF_FUNC_ringbuf_output;
static void* (*bpf_ringbuf_reserve_unsafe)(const void* ringbuf,
__u64 size, __u64 flags) = (void*)
@@ -223,8 +222,8 @@
static void* (*bpf_sk_storage_get_unsafe) (const void* sk_storage, const void* sk,
const void* value, unsigned long long flags) = (void*)
BPF_FUNC_sk_storage_get;
-static int (*bpf_sk_storage_delete_unsafe) (const void* sk_storage,
- const void* sk) = (void*) BPF_FUNC_sk_storage_delete;
+static long (*bpf_sk_storage_delete_unsafe) (const void* sk_storage,
+ const void* sk) = (void*) BPF_FUNC_sk_storage_delete;
#define BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \
struct ____btf_map_##name { \
@@ -244,26 +243,26 @@
type == BPF_MAP_TYPE_SK_STORAGE) ? BPF_F_NO_PREALLOC : 0) \
)
-#define DEFINE_BPF_MAP_BASE(the_map, TYPE, keysize, valuesize, num_entries, usr, grp, md, \
- selinux, pindir, minkver, maxkver, minloader, maxloader, mapflags) \
- VALIDATE_SELINUX_CONTEXT(minloader, selinux); \
- VALIDATE_PIN_DIR(minloader, pindir); \
- const struct bpf_map_def SECTION(".android_maps") the_map##_def = { \
- .type = BPF_MAP_TYPE_##TYPE, \
- .key_size = (keysize), \
- .value_size = (valuesize), \
- .max_entries = ABSOLUTE(num_entries), \
- .map_flags = DEFAULT_BPF_MAP_FLAGS(BPF_MAP_TYPE_##TYPE, num_entries, mapflags), \
- .uid = (usr), \
- .gid = (grp), \
- .mode = (md), \
- .bpfloader_min_ver = (minloader), \
- .bpfloader_max_ver = (maxloader), \
- .min_kver = (minkver).kver, \
- .max_kver = (maxkver).kver, \
- .create_location = CREATE_LOCATION(selinux), \
- .pin_location = "/sys/fs/bpf/" pindir "/map_" BPF_OBJ_NAME "_" #the_map, \
- .name_idx = __builtin_strlen("/sys/fs/bpf/" pindir "/map_" BPF_OBJ_NAME "_"), \
+#define DEFINE_BPF_MAP_BASE(the_map, TYPE, keysize, valuesize, num_entries, usr, grp, md, \
+ selinux, pindir, minkver, maxkver, minloader, maxloader, mapflags) \
+ VALIDATE_SELINUX_CONTEXT(minloader, selinux); \
+ VALIDATE_PIN_DIR(minloader, pindir); \
+ const struct bpf_map_def SECTION(".android_maps") the_map##_def = { \
+ .type = BPF_MAP_TYPE_##TYPE, \
+ .key_size = (keysize), \
+ .value_size = (valuesize), \
+ .max_entries = ABSOLUTE(num_entries), \
+ .map_flags = DEFAULT_BPF_MAP_FLAGS(BPF_MAP_TYPE_##TYPE, num_entries, mapflags), \
+ .uid = (usr), \
+ .gid = (grp), \
+ .mode = (md), \
+ .bpfloader_min_ver = (minloader), \
+ .bpfloader_max_ver = (maxloader), \
+ .min_kver = (minkver).kver, \
+ .max_kver = (maxkver).kver, \
+ .create_location = CREATE_LOCATION(selinux), \
+ .pin_location = "/sys/fs/bpf/" pindir "/map_" BPF_OBJ_NAME "_" #the_map "\0", \
+ .name_idx = __builtin_strlen("/sys/fs/bpf/" pindir "/map_" BPF_OBJ_NAME "_"), \
};
#define __uint(name, val) int (*name)[val]
@@ -371,7 +370,7 @@
selinux, pindir, min_loader, max_loader, mapFlags) \
DEFINE_BPF_MAP_BASE(the_map, TYPE, sizeof(KeyType), sizeof(ValueType), \
num_entries, usr, grp, md, selinux, pindir, \
- KVER_NONE, KVER_INF, min_loader, max_loader, mapFlags); \
+ KVER_4_9, KVER_INF, min_loader, max_loader, mapFlags); \
DEFINE_LIBBPF_MAP(the_map, TYPE, KeyType, ValueType, num_entries); \
BPF_MAP_ASSERT_OK(BPF_MAP_TYPE_##TYPE, (num_entries), (md)); \
_Static_assert(sizeof(KeyType) < 1024, "aosp/2370288 requires < 1024 byte keys"); \
@@ -459,10 +458,10 @@
unsigned long long load_half(void* skb, unsigned long long off) asm("llvm.bpf.load.half");
unsigned long long load_word(void* skb, unsigned long long off) asm("llvm.bpf.load.word");
-static int (*bpf_probe_read)(void* dst, int size, void* unsafe_ptr) = (void*) BPF_FUNC_probe_read;
-static int (*bpf_probe_read_str)(void* dst, int size, void* unsafe_ptr) = (void*) BPF_FUNC_probe_read_str;
-static int (*bpf_probe_read_user)(void* dst, int size, const void* unsafe_ptr) = (void*)BPF_FUNC_probe_read_user;
-static int (*bpf_probe_read_user_str)(void* dst, int size, const void* unsafe_ptr) = (void*) BPF_FUNC_probe_read_user_str;
+static long (*bpf_probe_read)(void* dst, int size, void* unsafe_ptr) = (void*) BPF_FUNC_probe_read;
+static long (*bpf_probe_read_str)(void* dst, int size, void* unsafe_ptr) = (void*) BPF_FUNC_probe_read_str;
+static long (*bpf_probe_read_user)(void* dst, int size, const void* unsafe_ptr) = (void*)BPF_FUNC_probe_read_user;
+static long (*bpf_probe_read_user_str)(void* dst, int size, const void* unsafe_ptr) = (void*) BPF_FUNC_probe_read_user_str;
static unsigned long long (*bpf_ktime_get_ns)(void) = (void*) BPF_FUNC_ktime_get_ns;
static unsigned long long (*bpf_ktime_get_boot_ns)(void) = (void*)BPF_FUNC_ktime_get_boot_ns;
static unsigned long long (*bpf_get_current_pid_tgid)(void) = (void*) BPF_FUNC_get_current_pid_tgid;
@@ -474,33 +473,87 @@
static struct bpf_sock* (*bpf_sk_fullsock)(struct bpf_sock* sk) = (void*) BPF_FUNC_sk_fullsock;
// GPL only:
-static int (*bpf_trace_printk)(const char* fmt, int fmt_size, ...) = (void*) BPF_FUNC_trace_printk;
+static long (*bpf_trace_printk)(const char* fmt, int fmt_size, ...) = (void*) BPF_FUNC_trace_printk;
#define bpf_printf(s, n...) bpf_trace_printk(s, sizeof(s), ## n)
// Note: bpf only supports up to 3 arguments, log via: bpf_printf("msg %d %d %d", 1, 2, 3);
// and read via the blocking: sudo cat /sys/kernel/debug/tracing/trace_pipe
-#define DEFINE_BPF_PROG_EXT(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, max_kv, \
- min_loader, max_loader, opt, selinux, pindir) \
- VALIDATE_SELINUX_CONTEXT(min_loader, selinux); \
- VALIDATE_PIN_DIR(min_loader, pindir); \
- const struct bpf_prog_def SECTION("progs") the_prog##_def = { \
- .uid = (prog_uid), \
- .gid = (prog_gid), \
- .min_kver = (min_kv).kver, \
- .max_kver = (max_kv).kver, \
- .optional = (opt).optional, \
- .bpfloader_min_ver = (min_loader), \
- .bpfloader_max_ver = (max_loader), \
- .create_location = CREATE_LOCATION(selinux), \
- .pin_prefix = "/sys/fs/bpf/" pindir "/prog_" BPF_OBJ_NAME "_", \
- }; \
- SECTION(SECTION_NAME) \
- int the_prog
+#define BPF_PROG_TYPE_bind4 BPF_PROG_TYPE_CGROUP_SOCK_ADDR
+#define BPF_PROG_TYPE_bind6 BPF_PROG_TYPE_CGROUP_SOCK_ADDR
+#define BPF_PROG_TYPE_cgroupskb BPF_PROG_TYPE_CGROUP_SKB
+#define BPF_PROG_TYPE_cgroupsock BPF_PROG_TYPE_CGROUP_SOCK
+#define BPF_PROG_TYPE_cgroupsockcreate BPF_PROG_TYPE_CGROUP_SOCK
+#define BPF_PROG_TYPE_cgroupsockrelease BPF_PROG_TYPE_CGROUP_SOCK
+#define BPF_PROG_TYPE_connect4 BPF_PROG_TYPE_CGROUP_SOCK_ADDR
+#define BPF_PROG_TYPE_connect6 BPF_PROG_TYPE_CGROUP_SOCK_ADDR
+#define BPF_PROG_TYPE_egress BPF_PROG_TYPE_CGROUP_SKB
+#define BPF_PROG_TYPE_getsockopt BPF_PROG_TYPE_CGROUP_SOCKOPT
+#define BPF_PROG_TYPE_ingress BPF_PROG_TYPE_CGROUP_SKB
+#define BPF_PROG_TYPE_postbind4 BPF_PROG_TYPE_CGROUP_SOCK
+#define BPF_PROG_TYPE_postbind6 BPF_PROG_TYPE_CGROUP_SOCK
+#define BPF_PROG_TYPE_recvmsg4 BPF_PROG_TYPE_CGROUP_SOCK_ADDR
+#define BPF_PROG_TYPE_recvmsg6 BPF_PROG_TYPE_CGROUP_SOCK_ADDR
+#define BPF_PROG_TYPE_schedact BPF_PROG_TYPE_SCHED_ACT
+#define BPF_PROG_TYPE_schedcls BPF_PROG_TYPE_SCHED_CLS
+#define BPF_PROG_TYPE_sendmsg4 BPF_PROG_TYPE_CGROUP_SOCK_ADDR
+#define BPF_PROG_TYPE_sendmsg6 BPF_PROG_TYPE_CGROUP_SOCK_ADDR
+#define BPF_PROG_TYPE_setsockopt BPF_PROG_TYPE_CGROUP_SOCKOPT
+#define BPF_PROG_TYPE_skfilter BPF_PROG_TYPE_SOCKET_FILTER
+#define BPF_PROG_TYPE_sockops BPF_PROG_TYPE_SOCK_OPS
+#define BPF_PROG_TYPE_sysctl BPF_PROG_TYPE_CGROUP_SYSCTL
+#define BPF_PROG_TYPE_xdp BPF_PROG_TYPE_XDP
-#define DEFINE_BPF_PROG_KVER_RANGE_OPT(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, max_kv, \
- opt) \
- DEFINE_BPF_PROG_EXT(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, max_kv, \
- BPFLOADER_MIN_VER, BPFLOADER_MAX_VER, opt, \
+#define BPF_PROG_ATTACH_TYPE_DEFAULT BPF_CGROUP_INET_INGRESS
+
+#define BPF_PROG_ATTACH_TYPE_bind4 BPF_CGROUP_INET4_BIND
+#define BPF_PROG_ATTACH_TYPE_bind6 BPF_CGROUP_INET6_BIND
+#define BPF_PROG_ATTACH_TYPE_cgroupskb BPF_PROG_ATTACH_TYPE_DEFAULT
+#define BPF_PROG_ATTACH_TYPE_cgroupsock BPF_PROG_ATTACH_TYPE_DEFAULT
+#define BPF_PROG_ATTACH_TYPE_cgroupsockcreate BPF_CGROUP_INET_SOCK_CREATE
+#define BPF_PROG_ATTACH_TYPE_cgroupsockrelease BPF_CGROUP_INET_SOCK_RELEASE
+#define BPF_PROG_ATTACH_TYPE_connect4 BPF_CGROUP_INET4_CONNECT
+#define BPF_PROG_ATTACH_TYPE_connect6 BPF_CGROUP_INET6_CONNECT
+#define BPF_PROG_ATTACH_TYPE_egress BPF_CGROUP_INET_EGRESS
+#define BPF_PROG_ATTACH_TYPE_getsockopt BPF_CGROUP_GETSOCKOPT
+#define BPF_PROG_ATTACH_TYPE_ingress BPF_CGROUP_INET_INGRESS
+#define BPF_PROG_ATTACH_TYPE_postbind4 BPF_CGROUP_INET4_POST_BIND
+#define BPF_PROG_ATTACH_TYPE_postbind6 BPF_CGROUP_INET6_POST_BIND
+#define BPF_PROG_ATTACH_TYPE_recvmsg4 BPF_CGROUP_UDP4_RECVMSG
+#define BPF_PROG_ATTACH_TYPE_recvmsg6 BPF_CGROUP_UDP6_RECVMSG
+#define BPF_PROG_ATTACH_TYPE_schedact BPF_PROG_ATTACH_TYPE_DEFAULT
+#define BPF_PROG_ATTACH_TYPE_schedcls BPF_PROG_ATTACH_TYPE_DEFAULT
+#define BPF_PROG_ATTACH_TYPE_sendmsg4 BPF_CGROUP_UDP4_SENDMSG
+#define BPF_PROG_ATTACH_TYPE_sendmsg6 BPF_CGROUP_UDP6_SENDMSG
+#define BPF_PROG_ATTACH_TYPE_setsockopt BPF_CGROUP_SETSOCKOPT
+#define BPF_PROG_ATTACH_TYPE_skfilter BPF_PROG_ATTACH_TYPE_DEFAULT
+#define BPF_PROG_ATTACH_TYPE_sockops BPF_CGROUP_SOCK_OPS
+#define BPF_PROG_ATTACH_TYPE_sysctl BPF_CGROUP_SYSCTL
+#define BPF_PROG_ATTACH_TYPE_xdp BPF_PROG_ATTACH_TYPE_DEFAULT
+
+#define DEFINE_BPF_PROG_EXT(TYPE, NAME, VER, prog_uid, prog_gid, min_kv, max_kv, \
+ min_loader, max_loader, opt, selinux, pindir) \
+ VALIDATE_SELINUX_CONTEXT(min_loader, selinux); \
+ VALIDATE_PIN_DIR(min_loader, pindir); \
+ const struct bpf_prog_def SECTION(".android_progs") TYPE##_##NAME##_##VER##_def = { \
+ .type = BPF_PROG_TYPE_##TYPE, \
+ .attach_type = BPF_PROG_ATTACH_TYPE_##TYPE, \
+ .uid = (prog_uid), \
+ .gid = (prog_gid), \
+ .min_kver = (KVER_##min_kv).kver, \
+ .max_kver = (KVER_##max_kv).kver, \
+ .optional = (opt).optional, \
+ .bpfloader_min_ver = (min_loader), \
+ .bpfloader_max_ver = (max_loader), \
+ .create_location = CREATE_LOCATION(selinux), \
+ .pin_location = "/sys/fs/bpf/" pindir "/prog_" BPF_OBJ_NAME "_" #TYPE "_" #NAME "\0", \
+ .name_idx = __builtin_strlen("/sys/fs/bpf/" pindir "/prog_" BPF_OBJ_NAME "_"), \
+ }; \
+ SECTION(#TYPE "/" #NAME "$" #VER) \
+ long TYPE##_##NAME##_##VER
+
+#define DEFINE_BPF_PROG_KVER_RANGE_OPT(TYPE, NAME, VER, prog_gid, min_kv, max_kv, opt) \
+ DEFINE_BPF_PROG_EXT(TYPE, NAME, VER, AID_ROOT, prog_gid, min_kv, max_kv, \
+ BPFLOADER_MIN_VER, BPFLOADER_MAX_VER, opt, \
DEFAULT_BPF_MAP_SELINUX_CONTEXT, DEFAULT_BPF_PIN_SUBDIR)
// Programs (here used in the sense of functions/sections) marked optional are allowed to fail
@@ -515,26 +568,19 @@
// ie. a non-optional program in a critical .o is mandatory for kernels matching the min/max kver.
// programs requiring a kernel version >= min_kv && < max_kv
-#define DEFINE_BPF_PROG_KVER_RANGE(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, max_kv) \
- DEFINE_BPF_PROG_KVER_RANGE_OPT(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, max_kv, \
- MANDATORY)
-#define DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, \
- max_kv) \
- DEFINE_BPF_PROG_KVER_RANGE_OPT(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, max_kv, \
- OPTIONAL)
+#define DEFINE_BPF_PROG_KVER_RANGE(TYPE, NAME, VER, prog_gid, min_kv, max_kv) \
+ DEFINE_BPF_PROG_KVER_RANGE_OPT(TYPE, NAME, VER, prog_gid, min_kv, max_kv, MANDATORY)
+#define DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE(TYPE, NAME, VER, prog_gid, min_kv, max_kv) \
+ DEFINE_BPF_PROG_KVER_RANGE_OPT(TYPE, NAME, VER, prog_gid, min_kv, max_kv, OPTIONAL)
// programs requiring a kernel version >= min_kv
-#define DEFINE_BPF_PROG_KVER(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv) \
- DEFINE_BPF_PROG_KVER_RANGE_OPT(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, KVER_INF, \
- MANDATORY)
-#define DEFINE_OPTIONAL_BPF_PROG_KVER(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv) \
- DEFINE_BPF_PROG_KVER_RANGE_OPT(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, KVER_INF, \
- OPTIONAL)
+#define DEFINE_BPF_PROG_KVER(TYPE, NAME, VER, prog_gid, min_kv) \
+ DEFINE_BPF_PROG_KVER_RANGE_OPT(TYPE, NAME, VER, prog_gid, min_kv, INF, MANDATORY)
+#define DEFINE_OPTIONAL_BPF_PROG_KVER(TYPE, NAME, VER, prog_gid, min_kv) \
+ DEFINE_BPF_PROG_KVER_RANGE_OPT(TYPE, NAME, VER, prog_gid, min_kv, INF, OPTIONAL)
// programs with no kernel version requirements
-#define DEFINE_BPF_PROG(SECTION_NAME, prog_uid, prog_gid, the_prog) \
- DEFINE_BPF_PROG_KVER_RANGE_OPT(SECTION_NAME, prog_uid, prog_gid, the_prog, KVER_NONE, KVER_INF, \
- MANDATORY)
-#define DEFINE_OPTIONAL_BPF_PROG(SECTION_NAME, prog_uid, prog_gid, the_prog) \
- DEFINE_BPF_PROG_KVER_RANGE_OPT(SECTION_NAME, prog_uid, prog_gid, the_prog, KVER_NONE, KVER_INF, \
- OPTIONAL)
+#define DEFINE_BPF_PROG(TYPE, NAME, VER, prog_gid) \
+ DEFINE_BPF_PROG_KVER_RANGE_OPT(TYPE, NAME, VER, prog_gid, 4_9, INF, MANDATORY)
+#define DEFINE_OPTIONAL_BPF_PROG(TYPE, NAME, VER, prog_gid) \
+ DEFINE_BPF_PROG_KVER_RANGE_OPT(TYPE, NAME, VER, prog_gid, 4_9, INF, OPTIONAL)
diff --git a/bpf/progs/include/bpf_map_def.h b/bpf/progs/include/bpf_map_def.h
index 388d5ef..63c31ac 100644
--- a/bpf/progs/include/bpf_map_def.h
+++ b/bpf/progs/include/bpf_map_def.h
@@ -109,7 +109,7 @@
// Length of strings (incl. selinux_context and pin_subdir)
// in the bpf_map_def and bpf_prog_def structs.
-#define BPF_DEF_CHAR_ARRAY_SIZE 66 // must be even for alignment sanity
+#define BPF_DEF_CHAR_ARRAY_SIZE 70 // must be even for alignment sanity
/*
* Map structure to be used by Android eBPF C programs. The Android eBPF loader
@@ -167,6 +167,9 @@
_Static_assert(_Alignof(struct bpf_map_def) == 4, "_Alignof struct bpf_map_def != 4");
struct bpf_prog_def {
+ enum bpf_prog_type type;
+ enum bpf_attach_type attach_type;
+
unsigned int uid;
unsigned int gid;
@@ -182,11 +185,21 @@
unsigned int bpfloader_max_ver;
char create_location[BPF_DEF_CHAR_ARRAY_SIZE];
- char pin_prefix[BPF_DEF_CHAR_ARRAY_SIZE];
+ char pin_location[BPF_DEF_CHAR_ARRAY_SIZE];
+ unsigned int name_idx;
+
+#ifdef __cplusplus
+ const char * name() const { return this->pin_location + this->name_idx; }
+#endif
};
+#ifdef __cplusplus
+static_assert(std::is_pod_v<struct bpf_prog_def>);
+static_assert(std::is_standard_layout_v<struct bpf_prog_def>);
+#endif
+
// This needs to be updated whenever the above structure definition is expanded.
// These asserts are here to make sure we have cross-6-arch consistency.
-_Static_assert(sizeof(struct bpf_prog_def) == 28 + 2 * BPF_DEF_CHAR_ARRAY_SIZE, "wrong sizeof struct bpf_prog_def");
+_Static_assert(sizeof(struct bpf_prog_def) == 40 + 2 * BPF_DEF_CHAR_ARRAY_SIZE, "wrong sizeof struct bpf_prog_def");
_Static_assert(__alignof__(struct bpf_prog_def) == 4, "__alignof__ struct bpf_prog_def != 4");
_Static_assert(_Alignof(struct bpf_prog_def) == 4, "_Alignof struct bpf_prog_def != 4");
diff --git a/bpf/progs/netd.c b/bpf/progs/netd.c
index 7cb9905..f83a306 100644
--- a/bpf/progs/netd.c
+++ b/bpf/progs/netd.c
@@ -113,35 +113,35 @@
// program (see XT_BPF_MODE_PATH_PINNED) and then the iptables binary (or rather
// the kernel acting on behalf of it) must be able to retrieve the pinned program
// for the reload to succeed
-#define DEFINE_XTBPF_PROG(SECTION_NAME, the_prog) \
- DEFINE_BPF_PROG(SECTION_NAME, AID_ROOT, AID_NET_ADMIN, the_prog)
+#define DEFINE_XTBPF_PROG(TYPE, NAME, VER) \
+ DEFINE_BPF_PROG(TYPE, NAME, VER, AID_NET_ADMIN)
// programs that need to be usable by netd, but not by netutils_wrappers
// (this is because these are currently attached by the mainline provided libnetd_updatable .so
// which is loaded into netd and thus runs as netd uid/gid/selinux context)
-#define DEFINE_NETD_BPF_PROG_RANGES(SECTION_NAME, the_prog, minKV, maxKV, min_loader, max_loader) \
- DEFINE_BPF_PROG_EXT(SECTION_NAME, AID_ROOT, AID_ROOT, the_prog, \
- minKV, maxKV, min_loader, max_loader, MANDATORY, \
+#define DEFINE_NETD_BPF_PROG_RANGES(TYPE, NAME, VER, minKV, maxKV, min_loader, max_loader) \
+ DEFINE_BPF_PROG_EXT(TYPE, NAME, VER, AID_ROOT, AID_ROOT, \
+ minKV, maxKV, min_loader, max_loader, MANDATORY, \
"netd_readonly", DEFAULT_BPF_PIN_SUBDIR)
-#define DEFINE_NETD_BPF_PROG_KVER_RANGE(SECTION_NAME, the_prog, minKV, maxKV) \
- DEFINE_NETD_BPF_PROG_RANGES(SECTION_NAME, the_prog, minKV, maxKV, BPFLOADER_MIN_VER, BPFLOADER_MAX_VER)
+#define DEFINE_NETD_BPF_PROG_KVER_RANGE(TYPE, NAME, VER, minKV, maxKV) \
+ DEFINE_NETD_BPF_PROG_RANGES(TYPE, NAME, VER, minKV, maxKV, BPFLOADER_MIN_VER, BPFLOADER_MAX_VER)
-#define DEFINE_NETD_BPF_PROG_KVER(SECTION_NAME, the_prog, min_kv) \
- DEFINE_NETD_BPF_PROG_KVER_RANGE(SECTION_NAME, the_prog, min_kv, KVER_INF)
+#define DEFINE_NETD_BPF_PROG_KVER(TYPE, NAME, VER, min_kv) \
+ DEFINE_NETD_BPF_PROG_KVER_RANGE(TYPE, NAME, VER, min_kv, INF)
-#define DEFINE_NETD_BPF_PROG(SECTION_NAME, the_prog) \
- DEFINE_NETD_BPF_PROG_KVER(SECTION_NAME, the_prog, KVER_NONE)
+#define DEFINE_NETD_BPF_PROG(TYPE, NAME, VER) \
+ DEFINE_NETD_BPF_PROG_KVER(TYPE, NAME, VER, 4_9)
-#define DEFINE_NETD_V_BPF_PROG_KVER(SECTION_NAME, the_prog, minKV) \
- DEFINE_BPF_PROG_EXT(SECTION_NAME, AID_ROOT, AID_ROOT, the_prog, minKV, \
- KVER_INF, BPFLOADER_MAINLINE_V_VERSION, BPFLOADER_MAX_VER, MANDATORY, \
+#define DEFINE_NETD_V_BPF_PROG_KVER(TYPE, NAME, VER, minKV) \
+ DEFINE_BPF_PROG_EXT(TYPE, NAME, VER, AID_ROOT, AID_ROOT, minKV, INF, \
+ BPFLOADER_MAINLINE_V_VERSION, BPFLOADER_MAX_VER, MANDATORY, \
"netd_readonly", DEFAULT_BPF_PIN_SUBDIR)
// programs that only need to be usable by the system server
-#define DEFINE_SYS_BPF_PROG(SECTION_NAME, the_prog) \
- DEFINE_BPF_PROG_EXT(SECTION_NAME, AID_ROOT, AID_NET_ADMIN, the_prog, KVER_NONE, KVER_INF, \
- BPFLOADER_MIN_VER, BPFLOADER_MAX_VER, MANDATORY, \
+#define DEFINE_SYS_BPF_PROG(TYPE, NAME, VER) \
+ DEFINE_BPF_PROG_EXT(TYPE, NAME, VER, AID_ROOT, AID_NET_ADMIN, 4_9, INF, \
+ BPFLOADER_MIN_VER, BPFLOADER_MAX_VER, MANDATORY, \
"net_shared", DEFAULT_BPF_PIN_SUBDIR)
/*
@@ -608,101 +608,89 @@
// ----- cgroupskb/ingress/stats -----
// Android 25Q2+ 5.10+ (localnet protection + tracing)
-DEFINE_NETD_BPF_PROG_RANGES("cgroupskb/ingress/stats$5_10_25q2",
- bpf_cgroup_ingress_5_10_25q2, KVER_5_10, KVER_INF,
+DEFINE_NETD_BPF_PROG_RANGES(cgroupskb, ingress_stats, 5_10_25q2, 5_10, INF,
BPFLOADER_MAINLINE_25Q2_VERSION, BPFLOADER_MAX_VER)
(struct __sk_buff* skb) {
return bpf_traffic_account(skb, INGRESS, KVER_5_10, SDK_LEVEL_25Q2);
}
// Android 25Q2+ 5.4 (localnet protection)
-DEFINE_NETD_BPF_PROG_RANGES("cgroupskb/ingress/stats$5_4_25q2",
- bpf_cgroup_ingress_5_4_25q2, KVER_5_4, KVER_5_10,
+DEFINE_NETD_BPF_PROG_RANGES(cgroupskb, ingress_stats, 5_4_25q2, 5_4, 5_10,
BPFLOADER_MAINLINE_25Q2_VERSION, BPFLOADER_MAX_VER)
(struct __sk_buff* skb) {
return bpf_traffic_account(skb, INGRESS, KVER_5_4, SDK_LEVEL_25Q2);
}
// Android U/V 5.10+ (tracing)
-DEFINE_NETD_BPF_PROG_RANGES("cgroupskb/ingress/stats$5_10_u",
- bpf_cgroup_ingress_5_10_u, KVER_5_10, KVER_INF,
+DEFINE_NETD_BPF_PROG_RANGES(cgroupskb, ingress_stats, 5_10_u, 5_10, INF,
BPFLOADER_MAINLINE_U_VERSION, BPFLOADER_MAINLINE_25Q2_VERSION)
(struct __sk_buff* skb) {
return bpf_traffic_account(skb, INGRESS, KVER_5_10, SDK_LEVEL_U);
}
// Android T/U/V/25Q2 5.4 & T 5.10/5.15
-DEFINE_NETD_BPF_PROG_KVER_RANGE("cgroupskb/ingress/stats$5_4",
- bpf_cgroup_ingress_5_4, KVER_5_4, KVER_INF)
+DEFINE_NETD_BPF_PROG_KVER_RANGE(cgroupskb, ingress_stats, 5_4, 5_4, INF)
(struct __sk_buff* skb) {
return bpf_traffic_account(skb, INGRESS, KVER_5_4, SDK_LEVEL_T);
}
// Android T/U/V 4.19
-DEFINE_NETD_BPF_PROG_KVER_RANGE("cgroupskb/ingress/stats$4_19",
- bpf_cgroup_ingress_4_19, KVER_4_19, KVER_5_4)
+DEFINE_NETD_BPF_PROG_KVER_RANGE(cgroupskb, ingress_stats, 4_19, 4_19, 5_4)
(struct __sk_buff* skb) {
return bpf_traffic_account(skb, INGRESS, KVER_4_19, SDK_LEVEL_T);
}
// Android T 4.9 & T/U 4.14
-DEFINE_NETD_BPF_PROG_KVER_RANGE("cgroupskb/ingress/stats$4_9",
- bpf_cgroup_ingress_4_9, KVER_NONE, KVER_4_19)
+DEFINE_NETD_BPF_PROG_KVER_RANGE(cgroupskb, ingress_stats, 4_9, 4_9, 4_19)
(struct __sk_buff* skb) {
- return bpf_traffic_account(skb, INGRESS, KVER_NONE, SDK_LEVEL_T);
+ return bpf_traffic_account(skb, INGRESS, KVER_4_9, SDK_LEVEL_T);
}
// ----- cgroupskb/egress/stats -----
// Android 25Q2+ 5.10+ (localnet protection + tracing)
-DEFINE_NETD_BPF_PROG_RANGES("cgroupskb/egress/stats$5_10_25q2",
- bpf_cgroup_egress_5_10_25q2, KVER_5_10, KVER_INF,
+DEFINE_NETD_BPF_PROG_RANGES(cgroupskb, egress_stats, 5_10_25q2, 5_10, INF,
BPFLOADER_MAINLINE_25Q2_VERSION, BPFLOADER_MAX_VER)
(struct __sk_buff* skb) {
return bpf_traffic_account(skb, EGRESS, KVER_5_10, SDK_LEVEL_25Q2);
}
// Android 25Q2+ 5.4 (localnet protection)
-DEFINE_NETD_BPF_PROG_RANGES("cgroupskb/egress/stats$5_4_25q2",
- bpf_cgroup_egress_5_4_25q2, KVER_5_4, KVER_5_10,
+DEFINE_NETD_BPF_PROG_RANGES(cgroupskb, egress_stats, 5_4_25q2, 5_4, 5_10,
BPFLOADER_MAINLINE_25Q2_VERSION, BPFLOADER_MAX_VER)
(struct __sk_buff* skb) {
return bpf_traffic_account(skb, EGRESS, KVER_5_4, SDK_LEVEL_25Q2);
}
// Android U/V 5.10+ (tracing)
-DEFINE_NETD_BPF_PROG_RANGES("cgroupskb/egress/stats$5_10_u",
- bpf_cgroup_egress_5_10_u, KVER_5_10, KVER_INF,
+DEFINE_NETD_BPF_PROG_RANGES(cgroupskb, egress_stats, 5_10_u, 5_10, INF,
BPFLOADER_MAINLINE_U_VERSION, BPFLOADER_MAINLINE_25Q2_VERSION)
(struct __sk_buff* skb) {
return bpf_traffic_account(skb, EGRESS, KVER_5_10, SDK_LEVEL_U);
}
// Android T/U/V/25Q2 5.4 & T 5.10/5.15
-DEFINE_NETD_BPF_PROG_KVER_RANGE("cgroupskb/egress/stats$5_4",
- bpf_cgroup_egress_5_4, KVER_5_4, KVER_INF)
+DEFINE_NETD_BPF_PROG_KVER_RANGE(cgroupskb, egress_stats, 5_4, 5_4, INF)
(struct __sk_buff* skb) {
return bpf_traffic_account(skb, EGRESS, KVER_5_4, SDK_LEVEL_T);
}
// Android T/U/V 4.19
-DEFINE_NETD_BPF_PROG_KVER_RANGE("cgroupskb/egress/stats$4_19",
- bpf_cgroup_egress_4_19, KVER_4_19, KVER_5_4)
+DEFINE_NETD_BPF_PROG_KVER_RANGE(cgroupskb, egress_stats, 4_19, 4_19, 5_4)
(struct __sk_buff* skb) {
return bpf_traffic_account(skb, EGRESS, KVER_4_19, SDK_LEVEL_T);
}
// Android T 4.9 & T/U 4.14
-DEFINE_NETD_BPF_PROG_KVER_RANGE("cgroupskb/egress/stats$4_9",
- bpf_cgroup_egress_4_9, KVER_NONE, KVER_4_19)
+DEFINE_NETD_BPF_PROG_KVER_RANGE(cgroupskb, egress_stats, 4_9, 4_9, 4_19)
(struct __sk_buff* skb) {
- return bpf_traffic_account(skb, EGRESS, KVER_NONE, SDK_LEVEL_T);
+ return bpf_traffic_account(skb, EGRESS, KVER_4_9, SDK_LEVEL_T);
}
// -----
// WARNING: Android T's non-updatable netd depends on the name of this program.
-DEFINE_XTBPF_PROG("skfilter/egress/xtbpf", xt_bpf_egress_prog)
+DEFINE_XTBPF_PROG(skfilter, egress_xtbpf, )
(struct __sk_buff* skb) {
// Clat daemon does not generate new traffic, all its traffic is accounted for already
// on the v4-* interfaces (except for the 20 (or 28) extra bytes of IPv6 vs IPv4 overhead,
@@ -716,12 +704,12 @@
}
uint32_t key = skb->ifindex;
- update_iface_stats_map(skb, &key, EGRESS, KVER_NONE);
+ update_iface_stats_map(skb, &key, EGRESS, KVER_4_9);
return XTBPF_MATCH;
}
// WARNING: Android T's non-updatable netd depends on the name of this program.
-DEFINE_XTBPF_PROG("skfilter/ingress/xtbpf", xt_bpf_ingress_prog)
+DEFINE_XTBPF_PROG(skfilter, ingress_xtbpf, )
(struct __sk_buff* skb) {
// Clat daemon traffic is not accounted by virtue of iptables raw prerouting drop rule
// (in clat_raw_PREROUTING chain), which triggers before this (in bw_raw_PREROUTING chain).
@@ -729,23 +717,22 @@
// Keep that in mind when moving this out of iptables xt_bpf and into tc ingress (or xdp).
uint32_t key = skb->ifindex;
- update_iface_stats_map(skb, &key, INGRESS, KVER_NONE);
+ update_iface_stats_map(skb, &key, INGRESS, KVER_4_9);
return XTBPF_MATCH;
}
-DEFINE_SYS_BPF_PROG("schedact/ingress/account",
- tc_bpf_ingress_account_prog)
+DEFINE_SYS_BPF_PROG(schedact, ingress_account, )
(struct __sk_buff* skb) {
if (is_received_skb(skb)) {
// Account for ingress traffic before tc drops it.
uint32_t key = skb->ifindex;
- update_iface_stats_map(skb, &key, INGRESS, KVER_NONE);
+ update_iface_stats_map(skb, &key, INGRESS, KVER_4_9);
}
return TC_ACT_UNSPEC;
}
// WARNING: Android T's non-updatable netd depends on the name of this program.
-DEFINE_XTBPF_PROG("skfilter/allowlist/xtbpf", xt_bpf_allowlist_prog)
+DEFINE_XTBPF_PROG(skfilter, allowlist_xtbpf, )
(struct __sk_buff* skb) {
uint32_t sock_uid = bpf_get_socket_uid(skb);
if (is_system_uid(sock_uid)) return XTBPF_MATCH;
@@ -764,7 +751,7 @@
}
// WARNING: Android T's non-updatable netd depends on the name of this program.
-DEFINE_XTBPF_PROG("skfilter/denylist/xtbpf", xt_bpf_denylist_prog)
+DEFINE_XTBPF_PROG(skfilter, denylist_xtbpf, )
(struct __sk_buff* skb) {
uint32_t sock_uid = bpf_get_socket_uid(skb);
UidOwnerValue* denylistMatch = bpf_uid_owner_map_lookup_elem(&sock_uid);
@@ -796,18 +783,17 @@
return (get_app_permissions() & BPF_PERMISSION_INTERNET) ? BPF_ALLOW : BPF_DISALLOW;
}
-DEFINE_NETD_BPF_PROG_KVER("cgroupsock/inet_create$5_10", inet_socket_create_5_10, KVER_5_10)
+DEFINE_NETD_BPF_PROG_KVER(cgroupsock, inet_create, 5_10, 5_10)
(struct bpf_sock* sk) {
return inet_socket_create(sk, KVER_5_10);
}
-DEFINE_NETD_BPF_PROG_KVER_RANGE("cgroupsock/inet_create$4_14",
- inet_socket_create_4_14, KVER_4_14, KVER_5_10)
+DEFINE_NETD_BPF_PROG_KVER_RANGE(cgroupsock, inet_create, 4_14, 4_14, 5_10)
(struct bpf_sock* sk) {
return inet_socket_create(sk, KVER_4_14);
}
-DEFINE_NETD_BPF_PROG_KVER("cgroupsockrelease/inet_release", inet_socket_release, KVER_5_10)
+DEFINE_NETD_BPF_PROG_KVER(cgroupsockrelease, inet_release, , 5_10)
(struct bpf_sock* sk) {
uint64_t cookie = bpf_get_sk_cookie(sk);
if (cookie) bpf_cookie_tag_map_delete_elem(&cookie);
@@ -860,47 +846,47 @@
return BPF_ALLOW;
}
-DEFINE_NETD_BPF_PROG_KVER("bind4/inet4_bind", inet4_bind, KVER_4_19)
+DEFINE_NETD_BPF_PROG_KVER(bind4, inet4_bind, , 4_19)
(struct bpf_sock_addr *ctx) {
return block_port(ctx);
}
-DEFINE_NETD_BPF_PROG_KVER("bind6/inet6_bind", inet6_bind, KVER_4_19)
+DEFINE_NETD_BPF_PROG_KVER(bind6, inet6_bind, , 4_19)
(struct bpf_sock_addr *ctx) {
return block_port(ctx);
}
-DEFINE_NETD_V_BPF_PROG_KVER("connect4/inet4_connect", inet4_connect, KVER_4_19)
+DEFINE_NETD_V_BPF_PROG_KVER(connect4, inet4_connect, , 4_19)
(struct bpf_sock_addr *ctx) {
return check_localhost(ctx);
}
-DEFINE_NETD_V_BPF_PROG_KVER("connect6/inet6_connect", inet6_connect, KVER_4_19)
+DEFINE_NETD_V_BPF_PROG_KVER(connect6, inet6_connect, , 4_19)
(struct bpf_sock_addr *ctx) {
return check_localhost(ctx);
}
-DEFINE_NETD_V_BPF_PROG_KVER("recvmsg4/udp4_recvmsg", udp4_recvmsg, KVER_4_19)
+DEFINE_NETD_V_BPF_PROG_KVER(recvmsg4, udp4_recvmsg, , 4_19)
(struct bpf_sock_addr *ctx) {
return check_localhost(ctx);
}
-DEFINE_NETD_V_BPF_PROG_KVER("recvmsg6/udp6_recvmsg", udp6_recvmsg, KVER_4_19)
+DEFINE_NETD_V_BPF_PROG_KVER(recvmsg6, udp6_recvmsg, , 4_19)
(struct bpf_sock_addr *ctx) {
return check_localhost(ctx);
}
-DEFINE_NETD_V_BPF_PROG_KVER("sendmsg4/udp4_sendmsg", udp4_sendmsg, KVER_4_19)
+DEFINE_NETD_V_BPF_PROG_KVER(sendmsg4, udp4_sendmsg, , 4_19)
(struct bpf_sock_addr *ctx) {
return check_localhost(ctx);
}
-DEFINE_NETD_V_BPF_PROG_KVER("sendmsg6/udp6_sendmsg", udp6_sendmsg, KVER_4_19)
+DEFINE_NETD_V_BPF_PROG_KVER(sendmsg6, udp6_sendmsg, , 4_19)
(struct bpf_sock_addr *ctx) {
return check_localhost(ctx);
}
-DEFINE_NETD_V_BPF_PROG_KVER("getsockopt/prog", getsockopt_prog, KVER_5_4)
+DEFINE_NETD_V_BPF_PROG_KVER(getsockopt, prog, , 5_4)
(struct bpf_sockopt *ctx) {
// Tell kernel to return 'original' kernel reply (instead of the bpf modified buffer)
// This is important if the answer is larger than PAGE_SIZE (max size this bpf hook can provide)
@@ -908,7 +894,7 @@
return BPF_ALLOW;
}
-DEFINE_NETD_V_BPF_PROG_KVER("setsockopt/prog", setsockopt_prog, KVER_5_4)
+DEFINE_NETD_V_BPF_PROG_KVER(setsockopt, prog, , 5_4)
(struct bpf_sockopt *ctx) {
// Tell kernel to use/process original buffer provided by userspace.
// This is important if it is larger than PAGE_SIZE (max size this bpf hook can handle).
diff --git a/bpf/progs/offload.c b/bpf/progs/offload.c
index 0401d70..4e82d01 100644
--- a/bpf/progs/offload.c
+++ b/bpf/progs/offload.c
@@ -257,29 +257,25 @@
}
// implementation for 5.4+ (can use skb->gso_{segs,size})
-DEFINE_BPF_PROG_KVER("schedcls/tether_downstream6_ether$5_4", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_downstream6_ether_5_4, KVER_5_4)
+DEFINE_BPF_PROG_KVER(schedcls, tether_downstream6_ether, 5_4, AID_NETWORK_STACK, 5_4)
(struct __sk_buff* skb) {
return do_forward6(skb, ETHER, DOWNSTREAM, KVER_5_4);
}
-DEFINE_BPF_PROG_KVER("schedcls/tether_upstream6_ether$5_4", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_upstream6_ether_5_4, KVER_5_4)
+DEFINE_BPF_PROG_KVER(schedcls, tether_upstream6_ether, 5_4, AID_NETWORK_STACK, 5_4)
(struct __sk_buff* skb) {
return do_forward6(skb, ETHER, UPSTREAM, KVER_5_4);
}
// implementation for 4.9/4.14/4.19
-DEFINE_BPF_PROG_KVER_RANGE("schedcls/tether_downstream6_ether", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_downstream6_ether, KVER_NONE, KVER_5_4)
+DEFINE_BPF_PROG_KVER_RANGE(schedcls, tether_downstream6_ether, , AID_NETWORK_STACK, 4_9, 5_4)
(struct __sk_buff* skb) {
- return do_forward6(skb, ETHER, DOWNSTREAM, KVER_NONE);
+ return do_forward6(skb, ETHER, DOWNSTREAM, KVER_4_9);
}
-DEFINE_BPF_PROG_KVER_RANGE("schedcls/tether_upstream6_ether", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_upstream6_ether, KVER_NONE, KVER_5_4)
+DEFINE_BPF_PROG_KVER_RANGE(schedcls, tether_upstream6_ether, , AID_NETWORK_STACK, 4_9, 5_4)
(struct __sk_buff* skb) {
- return do_forward6(skb, ETHER, UPSTREAM, KVER_NONE);
+ return do_forward6(skb, ETHER, UPSTREAM, KVER_4_9);
}
// Note: section names must be unique to prevent programs from appending to each other,
@@ -296,40 +292,34 @@
// and in system/netd/tests/binder_test.cpp NetdBinderTest TetherOffloadForwarding.
//
// Hence, these mandatory (must load successfully) implementations for 5.4+ kernels:
-DEFINE_BPF_PROG_KVER("schedcls/tether_downstream6_rawip$5_4", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_downstream6_rawip_5_4, KVER_5_4)
+DEFINE_BPF_PROG_KVER(schedcls, tether_downstream6_rawip, 5_4, AID_NETWORK_STACK, 5_4)
(struct __sk_buff* skb) {
return do_forward6(skb, RAWIP, DOWNSTREAM, KVER_5_4);
}
-DEFINE_BPF_PROG_KVER("schedcls/tether_upstream6_rawip$5_4", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_upstream6_rawip_5_4, KVER_5_4)
+DEFINE_BPF_PROG_KVER(schedcls, tether_upstream6_rawip, 5_4, AID_NETWORK_STACK, 5_4)
(struct __sk_buff* skb) {
return do_forward6(skb, RAWIP, UPSTREAM, KVER_5_4);
}
// and for 4.14/4.19 kernels
-DEFINE_BPF_PROG_KVER_RANGE("schedcls/tether_downstream6_rawip$4_14", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_downstream6_rawip_4_14, KVER_4_14, KVER_5_4)
+DEFINE_BPF_PROG_KVER_RANGE(schedcls, tether_downstream6_rawip, 4_14, AID_NETWORK_STACK, 4_14, 5_4)
(struct __sk_buff* skb) {
return do_forward6(skb, RAWIP, DOWNSTREAM, KVER_4_14);
}
-DEFINE_BPF_PROG_KVER_RANGE("schedcls/tether_upstream6_rawip$4_14", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_upstream6_rawip_4_14, KVER_4_14, KVER_5_4)
+DEFINE_BPF_PROG_KVER_RANGE(schedcls, tether_upstream6_rawip, 4_14, AID_NETWORK_STACK, 4_14, 5_4)
(struct __sk_buff* skb) {
return do_forward6(skb, RAWIP, UPSTREAM, KVER_4_14);
}
// and define no-op stubs for pre-4.14 kernels.
-DEFINE_BPF_PROG_KVER_RANGE("schedcls/tether_downstream6_rawip$stub", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_downstream6_rawip_stub, KVER_NONE, KVER_4_14)
+DEFINE_BPF_PROG_KVER_RANGE(schedcls, tether_downstream6_rawip, stub, AID_NETWORK_STACK, 4_9, 4_14)
(__unused struct __sk_buff* skb) {
return TC_ACT_PIPE;
}
-DEFINE_BPF_PROG_KVER_RANGE("schedcls/tether_upstream6_rawip$stub", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_upstream6_rawip_stub, KVER_NONE, KVER_4_14)
+DEFINE_BPF_PROG_KVER_RANGE(schedcls, tether_upstream6_rawip, stub, AID_NETWORK_STACK, 4_9, 4_14)
(__unused struct __sk_buff* skb) {
return TC_ACT_PIPE;
}
@@ -644,26 +634,22 @@
// Full featured (required) implementations for 5.10+ kernels (these are S+ by definition)
-DEFINE_BPF_PROG_KVER("schedcls/tether_downstream4_rawip$5_10", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_downstream4_rawip_5_10, KVER_5_10)
+DEFINE_BPF_PROG_KVER(schedcls, tether_downstream4_rawip, 5_10, AID_NETWORK_STACK, 5_10)
(struct __sk_buff* skb) {
return do_forward4(skb, RAWIP, DOWNSTREAM, UPDATETIME, KVER_5_10);
}
-DEFINE_BPF_PROG_KVER("schedcls/tether_upstream4_rawip$5_10", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_upstream4_rawip_5_10, KVER_5_10)
+DEFINE_BPF_PROG_KVER(schedcls, tether_upstream4_rawip, 5_10, AID_NETWORK_STACK, 5_10)
(struct __sk_buff* skb) {
return do_forward4(skb, RAWIP, UPSTREAM, UPDATETIME, KVER_5_10);
}
-DEFINE_BPF_PROG_KVER("schedcls/tether_downstream4_ether$5_10", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_downstream4_ether_5_10, KVER_5_10)
+DEFINE_BPF_PROG_KVER(schedcls, tether_downstream4_ether, 5_10, AID_NETWORK_STACK, 5_10)
(struct __sk_buff* skb) {
return do_forward4(skb, ETHER, DOWNSTREAM, UPDATETIME, KVER_5_10);
}
-DEFINE_BPF_PROG_KVER("schedcls/tether_upstream4_ether$5_10", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_upstream4_ether_5_10, KVER_5_10)
+DEFINE_BPF_PROG_KVER(schedcls, tether_upstream4_ether, 5_10, AID_NETWORK_STACK, 5_10)
(struct __sk_buff* skb) {
return do_forward4(skb, ETHER, UPSTREAM, UPDATETIME, KVER_5_10);
}
@@ -671,34 +657,26 @@
// Full featured (optional) implementations for 5.4-S kernels
// (optional, because we need to be able to fallback for 5.4 pre-S kernels)
-DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE("schedcls/tether_downstream4_rawip$opt54",
- AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_downstream4_rawip_opt54,
- KVER_5_4, KVER_5_10)
+DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE(schedcls, tether_downstream4_rawip, opt54,
+ AID_NETWORK_STACK, 5_4, 5_10)
(struct __sk_buff* skb) {
return do_forward4(skb, RAWIP, DOWNSTREAM, UPDATETIME, KVER_5_4);
}
-DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE("schedcls/tether_upstream4_rawip$opt54",
- AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_upstream4_rawip_opt54,
- KVER_5_4, KVER_5_10)
+DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE(schedcls, tether_upstream4_rawip, opt54,
+ AID_NETWORK_STACK, 5_4, 5_10)
(struct __sk_buff* skb) {
return do_forward4(skb, RAWIP, UPSTREAM, UPDATETIME, KVER_5_4);
}
-DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE("schedcls/tether_downstream4_ether$opt54",
- AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_downstream4_ether_opt54,
- KVER_5_4, KVER_5_10)
+DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE(schedcls, tether_downstream4_ether, opt54,
+ AID_NETWORK_STACK, 5_4, 5_10)
(struct __sk_buff* skb) {
return do_forward4(skb, ETHER, DOWNSTREAM, UPDATETIME, KVER_5_4);
}
-DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE("schedcls/tether_upstream4_ether$opt54",
- AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_upstream4_ether_opt54,
- KVER_5_4, KVER_5_10)
+DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE(schedcls, tether_upstream4_ether, opt54,
+ AID_NETWORK_STACK, 5_4, 5_10)
(struct __sk_buff* skb) {
return do_forward4(skb, ETHER, UPSTREAM, UPDATETIME, KVER_5_4);
}
@@ -706,34 +684,26 @@
// Full featured (optional) implementations for 4.14-S & 4.19-S kernels
// (optional, because we need to be able to fallback for 4.14/4.19 pre-S kernels)
-DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE("schedcls/tether_downstream4_rawip$opt",
- AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_downstream4_rawip_opt,
- KVER_4_14, KVER_5_4)
+DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE(schedcls, tether_downstream4_rawip, opt,
+ AID_NETWORK_STACK, 4_14, 5_4)
(struct __sk_buff* skb) {
return do_forward4(skb, RAWIP, DOWNSTREAM, UPDATETIME, KVER_4_14);
}
-DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE("schedcls/tether_upstream4_rawip$opt",
- AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_upstream4_rawip_opt,
- KVER_4_14, KVER_5_4)
+DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE(schedcls, tether_upstream4_rawip, opt,
+ AID_NETWORK_STACK, 4_14, 5_4)
(struct __sk_buff* skb) {
return do_forward4(skb, RAWIP, UPSTREAM, UPDATETIME, KVER_4_14);
}
-DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE("schedcls/tether_downstream4_ether$opt",
- AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_downstream4_ether_opt,
- KVER_4_14, KVER_5_4)
+DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE(schedcls, tether_downstream4_ether, opt,
+ AID_NETWORK_STACK, 4_14, 5_4)
(struct __sk_buff* skb) {
return do_forward4(skb, ETHER, DOWNSTREAM, UPDATETIME, KVER_4_14);
}
-DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE("schedcls/tether_upstream4_ether$opt",
- AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_upstream4_ether_opt,
- KVER_4_14, KVER_5_4)
+DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE(schedcls, tether_upstream4_ether, opt,
+ AID_NETWORK_STACK, 4_14, 5_4)
(struct __sk_buff* skb) {
return do_forward4(skb, ETHER, UPSTREAM, UPDATETIME, KVER_4_14);
}
@@ -752,14 +722,12 @@
// RAWIP: Required for 5.4-R kernels -- which always support bpf_skb_change_head().
-DEFINE_BPF_PROG_KVER_RANGE("schedcls/tether_downstream4_rawip$5_4", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_downstream4_rawip_5_4, KVER_5_4, KVER_5_10)
+DEFINE_BPF_PROG_KVER_RANGE(schedcls, tether_downstream4_rawip, 5_4, AID_NETWORK_STACK, 5_4, 5_10)
(struct __sk_buff* skb) {
return do_forward4(skb, RAWIP, DOWNSTREAM, NO_UPDATETIME, KVER_5_4);
}
-DEFINE_BPF_PROG_KVER_RANGE("schedcls/tether_upstream4_rawip$5_4", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_upstream4_rawip_5_4, KVER_5_4, KVER_5_10)
+DEFINE_BPF_PROG_KVER_RANGE(schedcls, tether_upstream4_rawip, 5_4, AID_NETWORK_STACK, 5_4, 5_10)
(struct __sk_buff* skb) {
return do_forward4(skb, RAWIP, UPSTREAM, NO_UPDATETIME, KVER_5_4);
}
@@ -767,32 +735,26 @@
// RAWIP: Optional for 4.14/4.19 (R) kernels -- which support bpf_skb_change_head().
// [Note: fallback for 4.14/4.19 (P/Q) kernels is below in stub section]
-DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE("schedcls/tether_downstream4_rawip$4_14",
- AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_downstream4_rawip_4_14,
- KVER_4_14, KVER_5_4)
+DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE(schedcls, tether_downstream4_rawip, 4_14,
+ AID_NETWORK_STACK, 4_14, 5_4)
(struct __sk_buff* skb) {
return do_forward4(skb, RAWIP, DOWNSTREAM, NO_UPDATETIME, KVER_4_14);
}
-DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE("schedcls/tether_upstream4_rawip$4_14",
- AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_upstream4_rawip_4_14,
- KVER_4_14, KVER_5_4)
+DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE(schedcls, tether_upstream4_rawip, 4_14,
+ AID_NETWORK_STACK, 4_14, 5_4)
(struct __sk_buff* skb) {
return do_forward4(skb, RAWIP, UPSTREAM, NO_UPDATETIME, KVER_4_14);
}
// ETHER: Required for 4.14-Q/R, 4.19-Q/R & 5.4-R kernels.
-DEFINE_BPF_PROG_KVER_RANGE("schedcls/tether_downstream4_ether$4_14", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_downstream4_ether_4_14, KVER_4_14, KVER_5_10)
+DEFINE_BPF_PROG_KVER_RANGE(schedcls, tether_downstream4_ether, 4_14, AID_NETWORK_STACK, 4_14, 5_10)
(struct __sk_buff* skb) {
return do_forward4(skb, ETHER, DOWNSTREAM, NO_UPDATETIME, KVER_4_14);
}
-DEFINE_BPF_PROG_KVER_RANGE("schedcls/tether_upstream4_ether$4_14", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_upstream4_ether_4_14, KVER_4_14, KVER_5_10)
+DEFINE_BPF_PROG_KVER_RANGE(schedcls, tether_upstream4_ether, 4_14, AID_NETWORK_STACK, 4_14, 5_10)
(struct __sk_buff* skb) {
return do_forward4(skb, ETHER, UPSTREAM, NO_UPDATETIME, KVER_4_14);
}
@@ -801,28 +763,24 @@
// RAWIP: 4.9-P/Q, 4.14-P/Q & 4.19-Q kernels -- without bpf_skb_change_head() for tc programs
-DEFINE_BPF_PROG_KVER_RANGE("schedcls/tether_downstream4_rawip$stub", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_downstream4_rawip_stub, KVER_NONE, KVER_5_4)
+DEFINE_BPF_PROG_KVER_RANGE(schedcls, tether_downstream4_rawip, stub, AID_NETWORK_STACK, 4_9, 5_4)
(__unused struct __sk_buff* skb) {
return TC_ACT_PIPE;
}
-DEFINE_BPF_PROG_KVER_RANGE("schedcls/tether_upstream4_rawip$stub", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_upstream4_rawip_stub, KVER_NONE, KVER_5_4)
+DEFINE_BPF_PROG_KVER_RANGE(schedcls, tether_upstream4_rawip, stub, AID_NETWORK_STACK, 4_9, 5_4)
(__unused struct __sk_buff* skb) {
return TC_ACT_PIPE;
}
// ETHER: 4.9-P/Q kernel
-DEFINE_BPF_PROG_KVER_RANGE("schedcls/tether_downstream4_ether$stub", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_downstream4_ether_stub, KVER_NONE, KVER_4_14)
+DEFINE_BPF_PROG_KVER_RANGE(schedcls, tether_downstream4_ether, stub, AID_NETWORK_STACK, 4_9, 4_14)
(__unused struct __sk_buff* skb) {
return TC_ACT_PIPE;
}
-DEFINE_BPF_PROG_KVER_RANGE("schedcls/tether_upstream4_ether$stub", AID_ROOT, AID_NETWORK_STACK,
- sched_cls_tether_upstream4_ether_stub, KVER_NONE, KVER_4_14)
+DEFINE_BPF_PROG_KVER_RANGE(schedcls, tether_upstream4_ether, stub, AID_NETWORK_STACK, 4_9, 4_14)
(__unused struct __sk_buff* skb) {
return TC_ACT_PIPE;
}
diff --git a/bpf/progs/offload@mainline.c b/bpf/progs/offload@mainline.c
deleted file mode 120000
index 4092e0d..0000000
--- a/bpf/progs/offload@mainline.c
+++ /dev/null
@@ -1 +0,0 @@
-offload.c
\ No newline at end of file
diff --git a/bpf/progs/test@mainline.c b/bpf/progs/test@mainline.c
deleted file mode 120000
index aeebb26..0000000
--- a/bpf/progs/test@mainline.c
+++ /dev/null
@@ -1 +0,0 @@
-test.c
\ No newline at end of file
diff --git a/clatd/main.c b/clatd/main.c
index 8fc9eda..de1c36a 100644
--- a/clatd/main.c
+++ b/clatd/main.c
@@ -37,27 +37,11 @@
#include "config.h"
#include "logging.h"
-#define DEVICEPREFIX "v4-"
-
/* function: handle_sigterm
* signal handler: stop the event loop
*/
static void handle_sigterm(__attribute__((unused)) int unused) { sigterm = 1; };
-/* function: print_help
- * in case the user is running this on the command line
- */
-void print_help() {
- printf("android-clat arguments:\n");
- printf("-i [uplink interface]\n");
- printf("-p [plat prefix]\n");
- printf("-4 [IPv4 address]\n");
- printf("-6 [IPv6 address]\n");
- printf("-t [tun file descriptor number]\n");
- printf("-r [read socket descriptor number]\n");
- printf("-w [write socket descriptor number]\n");
-}
-
// Load the architecture identifier (AUDIT_ARCH_* constant)
#define BPF_SECCOMP_LOAD_AUDIT_ARCH \
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, arch))
@@ -139,6 +123,9 @@
BPF2_SECCOMP_ALLOW_IF_EQUAL(__NR_sendmsg), // 211
BPF2_SECCOMP_ALLOW_IF_EQUAL(__NR_recvmsg), // 212
BPF2_SECCOMP_ALLOW_IF_EQUAL(__NR_writev), // 66
+#if defined(__i386__)
+ BPF2_SECCOMP_ALLOW_IF_EQUAL(__NR_socketcall), // x86-32 only
+#endif
// logging: getuid writev
BPF2_SECCOMP_ALLOW_IF_EQUAL(__NR_getuid), // 174
@@ -187,13 +174,6 @@
* allocate and setup the tun device, then run the event loop
*/
int main(int argc, char **argv) {
- struct tun_data tunnel;
- int opt;
- char *uplink_interface = NULL, *plat_prefix = NULL;
- char *v4_addr = NULL, *v6_addr = NULL, *tunfd_str = NULL, *read_sock_str = NULL,
- *write_sock_str = NULL;
- unsigned len;
-
// Clatd binary is setuid/gid CLAT, thus when we reach here we have:
// $ adb shell ps | grep clat
// [pid] [ppid]
@@ -236,44 +216,23 @@
// Gid: 1029 1029 1029 1029
// Groups: 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1018 1021 1023 1024 1032 1065 3001 3002 3003 3005 3006 3007 3009 3010 3011 3012
- while ((opt = getopt(argc, argv, "i:p:4:6:t:r:w:h")) != -1) {
- switch (opt) {
- case 'i':
- uplink_interface = optarg;
- break;
- case 'p':
- plat_prefix = optarg;
- break;
- case '4':
- v4_addr = optarg;
- break;
- case '6':
- v6_addr = optarg;
- break;
- case 't':
- tunfd_str = optarg;
- break;
- case 'r':
- read_sock_str = optarg;
- break;
- case 'w':
- write_sock_str = optarg;
- break;
- case 'h':
- print_help();
- exit(0);
- default:
- logmsg(ANDROID_LOG_FATAL, "Unknown option -%c. Exiting.", (char)optopt);
- exit(1);
- }
- }
-
- if (uplink_interface == NULL) {
- logmsg(ANDROID_LOG_FATAL, "clatd called without an interface");
+ if (argc != 8) {
+ logmsg(ANDROID_LOG_FATAL, "incorrect arguments, expect: "
+ "uplink_interface plat_prefix IPv4_addr IPv6_addr tun_fd read_sock_fd write_sock_fd");
exit(1);
}
- if (tunfd_str != NULL && !parse_int(tunfd_str, &tunnel.fd4)) {
+ const char* const uplink_interface = argv[1];
+ const char* const plat_prefix = argv[2];
+ const char* const v4_addr = argv[3];
+ const char* const v6_addr = argv[4];
+ const char* const tunfd_str = argv[5];
+ const char* const read_sock_str = argv[6];
+ const char* const write_sock_str = argv[7];
+
+ struct tun_data tunnel;
+
+ if (!parse_int(tunfd_str, &tunnel.fd4)) {
logmsg(ANDROID_LOG_FATAL, "invalid tunfd %s", tunfd_str);
exit(1);
}
@@ -282,7 +241,7 @@
exit(1);
}
- if (read_sock_str != NULL && !parse_int(read_sock_str, &tunnel.read_fd6)) {
+ if (!parse_int(read_sock_str, &tunnel.read_fd6)) {
logmsg(ANDROID_LOG_FATAL, "invalid read socket %s", read_sock_str);
exit(1);
}
@@ -291,7 +250,7 @@
exit(1);
}
- if (write_sock_str != NULL && !parse_int(write_sock_str, &tunnel.write_fd6)) {
+ if (!parse_int(write_sock_str, &tunnel.write_fd6)) {
logmsg(ANDROID_LOG_FATAL, "invalid write socket %s", write_sock_str);
exit(1);
}
@@ -300,24 +259,24 @@
exit(1);
}
- len = snprintf(tunnel.device4, sizeof(tunnel.device4), "%s%s", DEVICEPREFIX, uplink_interface);
+ unsigned len = snprintf(tunnel.device4, sizeof(tunnel.device4), "v4-%s", uplink_interface);
if (len >= sizeof(tunnel.device4)) {
logmsg(ANDROID_LOG_FATAL, "interface name too long '%s'", tunnel.device4);
exit(1);
}
Global_Clatd_Config.native_ipv6_interface = uplink_interface;
- if (!plat_prefix || inet_pton(AF_INET6, plat_prefix, &Global_Clatd_Config.plat_subnet) <= 0) {
+ if (inet_pton(AF_INET6, plat_prefix, &Global_Clatd_Config.plat_subnet) <= 0) {
logmsg(ANDROID_LOG_FATAL, "invalid IPv6 address specified for plat prefix: %s", plat_prefix);
exit(1);
}
- if (!v4_addr || !inet_pton(AF_INET, v4_addr, &Global_Clatd_Config.ipv4_local_subnet.s_addr)) {
+ if (!inet_pton(AF_INET, v4_addr, &Global_Clatd_Config.ipv4_local_subnet.s_addr)) {
logmsg(ANDROID_LOG_FATAL, "Invalid IPv4 address %s", v4_addr);
exit(1);
}
- if (!v6_addr || !inet_pton(AF_INET6, v6_addr, &Global_Clatd_Config.ipv6_local_subnet)) {
+ if (!inet_pton(AF_INET6, v6_addr, &Global_Clatd_Config.ipv6_local_subnet)) {
logmsg(ANDROID_LOG_FATAL, "Invalid source address %s", v6_addr);
exit(1);
}
diff --git a/framework/src/android/net/connectivity/ConnectivityInternalApiUtil.java b/framework/src/android/net/connectivity/ConnectivityInternalApiUtil.java
index 9478e91..dfb7844 100644
--- a/framework/src/android/net/connectivity/ConnectivityInternalApiUtil.java
+++ b/framework/src/android/net/connectivity/ConnectivityInternalApiUtil.java
@@ -20,6 +20,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
import android.annotation.SuppressLint;
import android.content.Context;
@@ -86,12 +87,15 @@
public static NetworkAgent buildTetheringNetworkAgent(@NonNull Context ctx,
@NonNull Looper looper, @NonNull String logTag, int transportType,
@NonNull LinkProperties lp) {
+ // LINT.IfChange
final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder()
.addCapability(NET_CAPABILITY_NOT_METERED)
.addCapability(NET_CAPABILITY_NOT_ROAMING)
.addCapability(NET_CAPABILITY_NOT_CONGESTED)
.addCapability(NET_CAPABILITY_NOT_SUSPENDED)
+ .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
.addTransportType(transportType);
+ // LINT.ThenChange(../../../../../service/src/com/android/metrics/SatisfiedByLocalNetworkMetrics.java)
// TODO: Change to use the constant definition. Flags.netCapabilityLocalNetwork() was not
// fully rolled out but the service will still process this capability, set it anyway.
builder.addCapability(36 /* NET_CAPABILITY_LOCAL_NETWORK */);
diff --git a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
index 622fba8..70991eb 100644
--- a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
+++ b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
@@ -397,13 +397,13 @@
// clang-format off
const char* args[] = {progname.c_str(),
- "-i", ifaceStr.c_str(),
- "-p", pfx96Str.c_str(),
- "-4", v4Str.c_str(),
- "-6", v6Str.c_str(),
- "-t", tunFdStr,
- "-r", sockReadStr,
- "-w", sockWriteStr,
+ ifaceStr.c_str(),
+ pfx96Str.c_str(),
+ v4Str.c_str(),
+ v6Str.c_str(),
+ tunFdStr,
+ sockReadStr,
+ sockWriteStr,
nullptr};
// clang-format on
diff --git a/service/src/com/android/metrics/SatisfiedByLocalNetworkMetrics.java b/service/src/com/android/metrics/SatisfiedByLocalNetworkMetrics.java
index b256a19..d45116e 100644
--- a/service/src/com/android/metrics/SatisfiedByLocalNetworkMetrics.java
+++ b/service/src/com/android/metrics/SatisfiedByLocalNetworkMetrics.java
@@ -21,6 +21,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
import static com.android.net.module.util.FrameworkConnectivityStatsLog.SATISFIED_BY_LOCAL_NETWORK_REQUESTS;
import static com.android.net.module.util.FrameworkConnectivityStatsLog.SATISFIED_BY_LOCAL_NETWORK_REQUESTS__TYPE__NETWORK_REQUEST_TYPE_BACKGROUND_REQUEST;
@@ -107,6 +108,7 @@
.addCapability(NET_CAPABILITY_NOT_ROAMING)
.addCapability(NET_CAPABILITY_NOT_CONGESTED)
.addCapability(NET_CAPABILITY_NOT_SUSPENDED)
+ .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addTransportType(NetworkCapabilities.TRANSPORT_USB)
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
@@ -218,4 +220,3 @@
pw.println("SatisfiedByLocalNetworkMetrics: " + mSatisfiedRequestsPerTypeAndUid);
}
}
-
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index ed74289..57f2ad4 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -112,6 +112,7 @@
import static android.net.NetworkCapabilities.RES_ID_MATCH_ALL_RESERVATIONS;
import static android.net.NetworkCapabilities.RES_ID_UNSET;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_SATELLITE;
import static android.net.NetworkCapabilities.TRANSPORT_TEST;
import static android.net.NetworkCapabilities.TRANSPORT_THREAD;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
@@ -169,6 +170,7 @@
import static com.android.server.connectivity.ConnectivityFlags.QUEUE_NETWORK_AGENT_EVENTS_IN_SYSTEM_SERVER;
import static com.android.server.connectivity.ConnectivityFlags.REQUEST_RESTRICTED_WIFI;
import static com.android.server.connectivity.ConnectivityFlags.SATISFIED_BY_LOCAL_NETWORK_METRICS;
+import static com.android.server.connectivity.ConnectivityFlags.USE_SATELLITE_REPORTED_SUSPENDED_AND_ROAMING;
import static com.android.server.connectivity.ConnectivityFlags.WIFI_DATA_INACTIVITY_TIMEOUT;
import android.Manifest;
@@ -360,6 +362,7 @@
import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult;
import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
import com.android.net.module.util.LocationPermissionChecker;
+import com.android.net.module.util.NetdUtils;
import com.android.net.module.util.PerUidCounter;
import com.android.net.module.util.PermissionUtils;
import com.android.net.module.util.RoutingCoordinatorService;
@@ -572,6 +575,7 @@
// Flag for early link properties update
private final boolean mSupportEarlyLinkPropertiesUpdateForVPN;
private final boolean mConstrainedDataSatelliteMetrics;
+ private final boolean mUseSatelliteReportedSuspendedAndRoaming;
/**
* Uids ConnectivityService tracks blocked status of to send blocked status callbacks.
@@ -1588,6 +1592,15 @@
}
/**
+ * Register a content observer. This method exists because ContentResolver#registerObserver
+ * is final and cannot be overridden by tests.
+ */
+ public void registerContentObserver(ContentResolver cr, Uri uri,
+ boolean notifyForDescendants, ContentObserver observer) {
+ cr.registerContentObserver(uri, notifyForDescendants, observer);
+ }
+
+ /**
* Get a reference to the ModuleNetworkStackClient.
*/
public NetworkStackClientBase getNetworkStack() {
@@ -2249,7 +2262,7 @@
loge("Error registering event listener :" + e);
}
- mSettingsObserver = new SettingsObserver(mContext, mHandler);
+ mSettingsObserver = new SettingsObserver(mContext, mHandler, mDeps);
registerSettingsCallbacks();
mKeepaliveTracker = mDeps.makeAutomaticOnOffKeepaliveTracker(mContext, mHandler);
@@ -2358,6 +2371,9 @@
} else {
mQuicConnectionCloser = null;
}
+
+ mUseSatelliteReportedSuspendedAndRoaming = mDeps.isFeatureNotChickenedOut(
+ context, USE_SATELLITE_REPORTED_SUSPENDED_AND_ROAMING);
}
/**
@@ -2426,33 +2442,6 @@
return new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId(), type);
}
- // Used only for testing.
- // TODO: Delete this and either:
- // 1. Give FakeSettingsProvider the ability to send settings change notifications (requires
- // changing ContentResolver to make registerContentObserver non-final).
- // 2. Give FakeSettingsProvider an alternative notification mechanism and have the test use it
- // by subclassing SettingsObserver.
- @VisibleForTesting
- void updateAlwaysOnNetworks() {
- mHandler.sendEmptyMessage(EVENT_CONFIGURE_ALWAYS_ON_NETWORKS);
- }
-
- // See FakeSettingsProvider comment above.
- @VisibleForTesting
- void updatePrivateDnsSettings() {
- mHandler.sendEmptyMessage(EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
- }
-
- @VisibleForTesting
- public void updateMobileDataPreferredUids() {
- mHandler.sendEmptyMessage(EVENT_MOBILE_DATA_PREFERRED_UIDS_CHANGED);
- }
-
- @VisibleForTesting
- void updateIngressRateLimit() {
- mHandler.sendEmptyMessage(EVENT_INGRESS_RATE_LIMIT_CHANGED);
- }
-
@VisibleForTesting
void simulateUpdateProxyInfo(@Nullable final Network network,
@NonNull final ProxyInfo proxyInfo) {
@@ -4402,7 +4391,7 @@
// rules are applied before system ready. Normally, the empty uid list means to clear
// the uids rules on netd.
if (!ConnectivitySettingsManager.getMobileDataPreferredUids(mContext).isEmpty()) {
- updateMobileDataPreferredUids();
+ mHandler.sendEmptyMessage(EVENT_MOBILE_DATA_PREFERRED_UIDS_CHANGED);
}
if (mSatelliteAccessController != null) {
@@ -7685,21 +7674,22 @@
}
private static class SettingsObserver extends ContentObserver {
- final private HashMap<Uri, Integer> mUriEventMap;
- final private Context mContext;
- final private Handler mHandler;
+ private final HashMap<Uri, Integer> mUriEventMap;
+ private final Context mContext;
+ private final Handler mHandler;
+ private final Dependencies mDeps;
- SettingsObserver(Context context, Handler handler) {
+ SettingsObserver(Context context, Handler handler, Dependencies deps) {
super(null);
mUriEventMap = new HashMap<>();
mContext = context;
mHandler = handler;
+ mDeps = deps;
}
void observe(Uri uri, int what) {
mUriEventMap.put(uri, what);
- final ContentResolver resolver = mContext.getContentResolver();
- resolver.registerContentObserver(uri, false, this);
+ mDeps.registerContentObserver(mContext.getContentResolver(), uri, false, this);
}
@Override
@@ -10594,7 +10584,8 @@
if (route.hasGateway()) continue;
if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId);
try {
- mRoutingCoordinatorService.addRoute(netId, route);
+ mRoutingCoordinatorService.addRouteParcel(netId,
+ NetdUtils.toRouteInfoParcel(route));
} catch (Exception e) {
if ((route.getDestination().getAddress() instanceof Inet4Address) || VDBG) {
loge("Exception in addRoute for non-gateway: " + e);
@@ -10605,7 +10596,8 @@
if (!route.hasGateway()) continue;
if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId);
try {
- mRoutingCoordinatorService.addRoute(netId, route);
+ mRoutingCoordinatorService.addRouteParcel(netId,
+ NetdUtils.toRouteInfoParcel(route));
} catch (Exception e) {
if ((route.getGateway() instanceof Inet4Address) || VDBG) {
loge("Exception in addRoute for gateway: " + e);
@@ -10616,7 +10608,8 @@
for (RouteInfo route : routeDiff.removed) {
if (VDBG || DDBG) log("Removing Route [" + route + "] from network " + netId);
try {
- mRoutingCoordinatorService.removeRoute(netId, route);
+ mRoutingCoordinatorService.removeRouteParcel(netId,
+ NetdUtils.toRouteInfoParcel(route));
} catch (Exception e) {
loge("Exception in removeRoute: " + e);
}
@@ -10625,7 +10618,8 @@
for (RouteInfo route : routeDiff.updated) {
if (VDBG || DDBG) log("Updating Route [" + route + "] from network " + netId);
try {
- mRoutingCoordinatorService.updateRoute(netId, route);
+ mRoutingCoordinatorService.updateRouteParcel(netId,
+ NetdUtils.toRouteInfoParcel(route));
} catch (Exception e) {
loge("Exception in updateRoute: " + e);
}
@@ -10926,7 +10920,9 @@
newNc.setPrivateDnsBroken(nai.networkCapabilities.isPrivateDnsBroken());
// TODO : remove this once all factories are updated to send NOT_SUSPENDED and NOT_ROAMING
- if (!newNc.hasTransport(TRANSPORT_CELLULAR)) {
+ if (!newNc.hasTransport(TRANSPORT_CELLULAR)
+ && !(mUseSatelliteReportedSuspendedAndRoaming
+ && newNc.hasTransport(TRANSPORT_SATELLITE))) {
newNc.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
newNc.addCapability(NET_CAPABILITY_NOT_ROAMING);
}
diff --git a/service/src/com/android/server/connectivity/ConnectivityFlags.java b/service/src/com/android/server/connectivity/ConnectivityFlags.java
index 19ea0cc..20b3ce9 100644
--- a/service/src/com/android/server/connectivity/ConnectivityFlags.java
+++ b/service/src/com/android/server/connectivity/ConnectivityFlags.java
@@ -76,6 +76,9 @@
public static final String SATISFIED_BY_LOCAL_NETWORK_METRICS =
"satisfied_by_local_network_metrics";
+ public static final String USE_SATELLITE_REPORTED_SUSPENDED_AND_ROAMING =
+ "use_satellite_reported_suspended_and_roaming";
+
/**
* A feature flag to control whether the early link properties update for vpn should be enabled.
*
diff --git a/service/src/com/android/server/connectivity/MultinetworkPolicyTracker.java b/service/src/com/android/server/connectivity/MultinetworkPolicyTracker.java
index a614cc4..cde16d8 100644
--- a/service/src/com/android/server/connectivity/MultinetworkPolicyTracker.java
+++ b/service/src/com/android/server/connectivity/MultinetworkPolicyTracker.java
@@ -321,7 +321,11 @@
@TargetApi(Build.VERSION_CODES.S)
public void start() {
for (Uri uri : mSettingsUris) {
- mResolver.registerContentObserver(uri, true, mSettingObserver);
+ mResolver.registerContentObserver(
+ uri,
+ mAvoidBadWifiSource == FROM_CARRIER_CONFIG,
+ mSettingObserver
+ );
}
final IntentFilter intentFilter = new IntentFilter();
diff --git a/staticlibs/Android.bp b/staticlibs/Android.bp
index c657a74..8849eb3 100644
--- a/staticlibs/Android.bp
+++ b/staticlibs/Android.bp
@@ -618,6 +618,9 @@
visibility: [
"//system/tools/aidl/build",
],
+ imports: [
+ "netd_aidl_interface-V17", // For RouteInfoParcel.
+ ],
}
// Use a filegroup and not a library for telephony sources, as framework-annotations cannot be
diff --git a/staticlibs/device/com/android/net/module/util/IRoutingCoordinator.aidl b/staticlibs/device/com/android/net/module/util/IRoutingCoordinator.aidl
index 7688e6a..4baeaf9 100644
--- a/staticlibs/device/com/android/net/module/util/IRoutingCoordinator.aidl
+++ b/staticlibs/device/com/android/net/module/util/IRoutingCoordinator.aidl
@@ -21,6 +21,7 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.RouteInfo;
+import android.net.RouteInfoParcel;
import com.android.net.module.util.IIpv4PrefixRequest;
@@ -30,6 +31,7 @@
// invocation to an incorrect interface" when calling the IPC.
@Descriptor("value=no.jarjar.com.android.net.module.util.IRoutingCoordinator")
interface IRoutingCoordinator {
+
/**
* Add a route for specific network
*
@@ -38,7 +40,7 @@
* @throws ServiceSpecificException in case of failure, with an error code indicating the
* cause of the failure.
*/
- void addRoute(int netId, in RouteInfo route);
+ void addRouteParcel(int netId, in RouteInfoParcel route);
/**
* Remove a route for specific network
@@ -48,7 +50,7 @@
* @throws ServiceSpecificException in case of failure, with an error code indicating the
* cause of the failure.
*/
- void removeRoute(int netId, in RouteInfo route);
+ void removeRouteParcel(int netId, in RouteInfoParcel route);
/**
* Update a route for specific network
@@ -58,7 +60,7 @@
* @throws ServiceSpecificException in case of failure, with an error code indicating the
* cause of the failure.
*/
- void updateRoute(int netId, in RouteInfo route);
+ void updateRouteParcel(int netId, in RouteInfoParcel route);
/**
* Adds an interface to a network. The interface must not be assigned to any network, including
diff --git a/staticlibs/device/com/android/net/module/util/RoutingCoordinatorManager.java b/staticlibs/device/com/android/net/module/util/RoutingCoordinatorManager.java
index f5af30c..5234bc1 100644
--- a/staticlibs/device/com/android/net/module/util/RoutingCoordinatorManager.java
+++ b/staticlibs/device/com/android/net/module/util/RoutingCoordinatorManager.java
@@ -21,7 +21,6 @@
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
-import android.net.RouteInfo;
import android.os.IBinder;
import android.os.RemoteException;
@@ -51,54 +50,6 @@
}
/**
- * Add a route for specific network
- *
- * @param netId the network to add the route to
- * @param route the route to add
- * @throws ServiceSpecificException in case of failure, with an error code indicating the
- * cause of the failure.
- */
- public void addRoute(final int netId, final RouteInfo route) {
- try {
- mService.addRoute(netId, route);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Remove a route for specific network
- *
- * @param netId the network to remove the route from
- * @param route the route to remove
- * @throws ServiceSpecificException in case of failure, with an error code indicating the
- * cause of the failure.
- */
- public void removeRoute(final int netId, final RouteInfo route) {
- try {
- mService.removeRoute(netId, route);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Update a route for specific network
- *
- * @param netId the network to update the route for
- * @param route parcelable with route information
- * @throws ServiceSpecificException in case of failure, with an error code indicating the
- * cause of the failure.
- */
- public void updateRoute(final int netId, final RouteInfo route) {
- try {
- mService.updateRoute(netId, route);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Adds an interface to a network. The interface must not be assigned to any network, including
* the specified network.
*
diff --git a/staticlibs/device/com/android/net/module/util/RoutingCoordinatorService.java b/staticlibs/device/com/android/net/module/util/RoutingCoordinatorService.java
index 61e830f..1950535 100644
--- a/staticlibs/device/com/android/net/module/util/RoutingCoordinatorService.java
+++ b/staticlibs/device/com/android/net/module/util/RoutingCoordinatorService.java
@@ -16,17 +16,14 @@
package com.android.net.module.util;
-import static com.android.net.module.util.NetdUtils.toRouteInfoParcel;
-
import android.annotation.NonNull;
import android.content.Context;
import android.net.INetd;
-
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
-import android.net.RouteInfo;
+import android.net.RouteInfoParcel;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.util.ArraySet;
@@ -84,9 +81,9 @@
* cause of the failure.
*/
@Override
- public void addRoute(final int netId, final RouteInfo route)
+ public void addRouteParcel(int netId, RouteInfoParcel route)
throws ServiceSpecificException, RemoteException {
- mNetd.networkAddRouteParcel(netId, toRouteInfoParcel(route));
+ mNetd.networkAddRouteParcel(netId, route);
}
/**
@@ -98,9 +95,9 @@
* cause of the failure.
*/
@Override
- public void removeRoute(final int netId, final RouteInfo route)
+ public void removeRouteParcel(int netId, RouteInfoParcel route)
throws ServiceSpecificException, RemoteException {
- mNetd.networkRemoveRouteParcel(netId, toRouteInfoParcel(route));
+ mNetd.networkRemoveRouteParcel(netId, route);
}
/**
@@ -112,9 +109,9 @@
* cause of the failure.
*/
@Override
- public void updateRoute(final int netId, final RouteInfo route)
+ public void updateRouteParcel(int netId, RouteInfoParcel route)
throws ServiceSpecificException, RemoteException {
- mNetd.networkUpdateRouteParcel(netId, toRouteInfoParcel(route));
+ mNetd.networkUpdateRouteParcel(netId, route);
}
/**
diff --git a/staticlibs/device/com/android/net/module/util/dhcp6/Dhcp6AddrRegInformPacket.java b/staticlibs/device/com/android/net/module/util/dhcp6/Dhcp6AddrRegInformPacket.java
index 9fd1f96..4d5478c 100644
--- a/staticlibs/device/com/android/net/module/util/dhcp6/Dhcp6AddrRegInformPacket.java
+++ b/staticlibs/device/com/android/net/module/util/dhcp6/Dhcp6AddrRegInformPacket.java
@@ -40,7 +40,7 @@
/**
* Generates a ADDR-REG-INFORM packet with the specified parameters.
*/
- Dhcp6AddrRegInformPacket(int transId, int elapsedTime, @NonNull final byte[] clientDuid,
+ public Dhcp6AddrRegInformPacket(int transId, int elapsedTime, @NonNull final byte[] clientDuid,
@NonNull final Inet6Address iaAddress, long preferred, long valid) {
super(transId, elapsedTime, clientDuid, null /* serverDuid */, null /* iapd */);
mIaAddress = iaAddress;
diff --git a/staticlibs/native/netjniutils/netjniutils.cpp b/staticlibs/native/netjniutils/netjniutils.cpp
index 8b7f903..ef49cf6 100644
--- a/staticlibs/native/netjniutils/netjniutils.cpp
+++ b/staticlibs/native/netjniutils/netjniutils.cpp
@@ -19,7 +19,7 @@
#include <dlfcn.h>
#include <stdbool.h>
-#include <string.h>
+#include <stdlib.h>
#include <sys/system_properties.h>
#include <android/api-level.h>
@@ -28,10 +28,7 @@
namespace android {
namespace netjniutils {
-namespace {
-
-
-int GetNativeFileDescriptorWithoutNdk(JNIEnv* env, jobject javaFd) {
+static int GetNativeFileDescriptorWithoutNdk(JNIEnv* env, jobject javaFd) {
// Prior to Android S, we need to find the descriptor field in the FileDescriptor class. The
// symbol name has been stable in libcore, but is a private implementation detail.
// Older libnativehelper_compat_c++ versions had a jniGetFdFromFileDescriptor method, but this
@@ -43,14 +40,15 @@
env->DeleteLocalRef(cls);
if (fieldID == nullptr) {
__android_log_print(ANDROID_LOG_FATAL, LOG_TAG, "Failed to get descriptor field.");
+ abort();
}
return fieldID;
}();
- return javaFd != nullptr ? env->GetIntField(javaFd, descriptorFieldID) : -1;
+ return env->GetIntField(javaFd, descriptorFieldID);
}
-int GetNativeFileDescriptorWithNdk(JNIEnv* env, jobject javaFd) {
+static int GetNativeFileDescriptorWithNdk(JNIEnv* env, jobject javaFd) {
// Since Android S, there is an NDK API to get a file descriptor present in libnativehelper.so.
// libnativehelper is loaded into all processes by the zygote since the zygote uses it
// to load the Android Runtime and is also a public library (because of the NDK API).
@@ -62,18 +60,17 @@
__android_log_print(ANDROID_LOG_FATAL, LOG_TAG,
"Failed to dlsym(AFileDescriptor_getFd): %s", dlerror());
dlclose(handle);
+ abort();
}
return ndkGetFd;
}();
- return javaFd != nullptr ? ndkGetFd(env, javaFd) : -1;
+ return ndkGetFd(env, javaFd);
}
-} // namespace
-
int GetNativeFileDescriptor(JNIEnv* env, jobject javaFd) {
- static const bool preferNdkFileDescriptorApi = []() -> bool
- { return android::modules::sdklevel::IsAtLeastS(); }();
+ if (!javaFd) return -1;
+ static const bool preferNdkFileDescriptorApi = modules::sdklevel::IsAtLeastS();
if (preferNdkFileDescriptorApi) {
return GetNativeFileDescriptorWithNdk(env, javaFd);
} else {
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/ContentResolverWithFakeSettingsProvider.kt b/staticlibs/testutils/devicetests/com/android/testutils/ContentResolverWithFakeSettingsProvider.kt
index 4eff040..21e239b 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/ContentResolverWithFakeSettingsProvider.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/ContentResolverWithFakeSettingsProvider.kt
@@ -40,11 +40,13 @@
val callbackUser = p.second
val user = UserHandle(userId)
val currentUser = UserHandle.getUserHandleForUid(Process.myUid())
- if (callbackUser == UserHandle.ALL ||
- UserHandle.CURRENT.equals(callbackUser) && currentUser.equals(user) ||
- callbackUser.equals(user)
- ) {
+ if (callbackUser == UserHandle.CURRENT && currentUser == user) {
+ // Use the overload without the user parameter since it works on S.
+ // TODO: when S is no longer supported, remove this and always use the branch below.
Log.d(TAG, "Notifying change in $uri")
+ observer.onChange(false, Collections.singletonList(uri), 0)
+ } else if (callbackUser == UserHandle.ALL || callbackUser.equals(user)) {
+ Log.d(TAG, "Notifying change in $uri on user $user")
observer.onChange(false, Collections.singletonList(uri), 0, user)
}
}))
diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
index b2d988f..777b55a 100644
--- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
@@ -181,6 +181,8 @@
private const val QUEUE_NETWORK_AGENT_EVENTS_IN_SYSTEM_SERVER =
"queue_network_agent_events_in_system_server"
+private const val INGRESS_TO_VPN_ADDRESS_FILTERING =
+ "ingress_to_vpn_address_filtering"
// When waiting for a NetworkCallback to determine there was no timeout, waiting is the
// only possible thing (the relevant handler is the one in the real ConnectivityService,
@@ -2079,4 +2081,67 @@
} while (SystemClock.elapsedRealtime() < deadline)
fail("Binder Proxy is leaked: $startCount -> $endCount")
}
+
+ fun doTestIngressToVpnAddressFiltering(vpnType: Int, expectFiltering: Boolean) {
+ assumeTrue(mCM.isConnectivityServiceFeatureEnabledForTesting(
+ INGRESS_TO_VPN_ADDRESS_FILTERING
+ ))
+
+ val ifname = createTunInterface(listOf(LINK_ADDRESS)).interfaceName
+ val lp = makeTestLinkProperties(ifname)
+ val nc = makeTestNetworkCapabilities(transports = intArrayOf(TRANSPORT_VPN)).apply {
+ setTransportInfo(VpnTransportInfo(
+ vpnType,
+ "MySession12345",
+ /*bypassable=*/
+ false,
+ /*longLivedTcpConnectionsExpensive=*/
+ false
+ ))
+ }
+ val agent = createNetworkAgent(initialNc = nc, initialLp = lp)
+ agent.register()
+ agent.markConnected()
+
+ val cb = TestableNetworkCallback()
+ registerNetworkCallback(makeTestNetworkRequest(), cb)
+ cb.eventuallyExpect<LinkPropertiesChanged> {
+ it.network == agent.network
+ }
+
+ val ifIndex = Os.if_nametoindex(ifname)
+ val ruleString = "[" + LINK_ADDRESS.address + "]: " + ifIndex + "(" + ifname + ")"
+ assertEquals(
+ expectFiltering,
+ "dumpsys connectivity trafficcontroller".execute().contains(ruleString)
+ )
+ }
+
+ @Test
+ fun testIngressToVpnAddressFiltering_VpnPlatform() {
+ doTestIngressToVpnAddressFiltering(
+ vpnType = VpnManager.TYPE_VPN_PLATFORM,
+ expectFiltering = true
+ )
+ }
+
+ @Test
+ fun testIngressToVpnAddressFiltering_VpnOem() {
+ // Ingress to VPN address filtering rule should not be added because OEM VPNs might need to
+ // receive packets to VPN address via non-VPN interface.
+ doTestIngressToVpnAddressFiltering(
+ vpnType = VpnManager.TYPE_VPN_OEM,
+ expectFiltering = false
+ )
+ }
+
+ @Test
+ fun testIngressToVpnAddressFiltering_VpnLegacy() {
+ // Ingress to VPN address filtering rule should not be added because legacy VPNs might need
+ // to receive packets to VPN address via non-VPN interface.
+ doTestIngressToVpnAddressFiltering(
+ vpnType = VpnManager.TYPE_VPN_LEGACY,
+ expectFiltering = false
+ )
+ }
}
diff --git a/tests/unit/java/com/android/metrics/SatisfiedByLocalNetworkMetricsTest.kt b/tests/unit/java/com/android/metrics/SatisfiedByLocalNetworkMetricsTest.kt
index d664754..d6c378f 100644
--- a/tests/unit/java/com/android/metrics/SatisfiedByLocalNetworkMetricsTest.kt
+++ b/tests/unit/java/com/android/metrics/SatisfiedByLocalNetworkMetricsTest.kt
@@ -21,6 +21,7 @@
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED
+import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED
import android.net.NetworkCapabilities.TRANSPORT_WIFI
import android.net.NetworkRequest
import android.net.NetworkRequest.Type
@@ -66,7 +67,9 @@
// Simulate caps which can potentially be satisfied by non-thread
// local networks.
+ // Note that requests built by NetworkRequest normally have deduced NOT_VCN_MANAGED.
private val WIFI_CAPS = NetworkCapabilities.Builder()
+ .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
.addCapability(NET_CAPABILITY_NOT_METERED)
.addTransportType(TRANSPORT_WIFI)
.build()
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index d88d15c..86e0c34 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -254,7 +254,6 @@
import android.compat.testing.PlatformCompatChangeRule;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
-import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -267,6 +266,7 @@
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.content.res.Resources;
+import android.database.ContentObserver;
import android.location.LocationManager;
import android.net.CaptivePortal;
import android.net.CaptivePortalData;
@@ -373,7 +373,6 @@
import android.telephony.TelephonyManager;
import android.telephony.data.EpsBearerQosSessionAttributes;
import android.telephony.data.NrQosSessionAttributes;
-import android.test.mock.MockContentResolver;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
@@ -429,6 +428,7 @@
import com.android.server.connectivity.TcpKeepaliveController;
import com.android.server.connectivity.UidRangeUtils;
import com.android.server.net.NetworkPinner;
+import com.android.testutils.ContentResolverWithFakeSettingsProvider;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
import com.android.testutils.FunctionalUtils.Function3;
@@ -686,7 +686,7 @@
}
private class MockContext extends BroadcastInterceptingContext {
- private final MockContentResolver mContentResolver;
+ private final ContentResolverWithFakeSettingsProvider mContentResolver;
@Spy private Resources mInternalResources;
private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
@@ -703,7 +703,7 @@
}).when(mInternalResources).getString(resId);
}
- MockContext(Context base, ContentProvider settingsProvider) {
+ MockContext(Context base) {
super(base);
mInternalResources = spy(base.getResources());
@@ -727,8 +727,7 @@
mockStringResource(resId);
}
- mContentResolver = new MockContentResolver();
- mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
+ mContentResolver = new ContentResolverWithFakeSettingsProvider();
}
@Override
@@ -1908,8 +1907,7 @@
doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt());
FakeSettingsProvider.clearSettingsProvider();
- mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
- new FakeSettingsProvider());
+ mServiceContext = new MockContext(InstrumentationRegistry.getContext());
mServiceContext.setUseRegisteredHandlers(true);
mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
@@ -2032,6 +2030,13 @@
}
@Override
+ public void registerContentObserver(ContentResolver cr, Uri uri,
+ boolean notifyForDescendants, ContentObserver observer) {
+ ((ContentResolverWithFakeSettingsProvider) mServiceContext.getContentResolver())
+ .registerContentObserver(uri, observer);
+ }
+
+ @Override
public NetworkStackClientBase getNetworkStack() {
return mNetworkStack;
}
@@ -2237,6 +2242,7 @@
case ConnectivityFlags.EARLY_LINK_PROPERTIES_UPDATE_FOR_VPN:
case ConnectivityFlags.CONSTRAINED_DATA_SATELLITE_METRICS:
case ConnectivityFlags.SATISFIED_BY_LOCAL_NETWORK_METRICS:
+ case ConnectivityFlags.USE_SATELLITE_REPORTED_SUSPENDED_AND_ROAMING:
return true;
default:
throw new UnsupportedOperationException("Unknown flag " + name
@@ -5889,21 +5895,18 @@
ContentResolver cr = mServiceContext.getContentResolver();
Settings.Global.putInt(cr, ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON,
enable ? 1 : 0);
- mService.updateAlwaysOnNetworks();
waitForIdle();
}
private void setPrivateDnsSettings(int mode, String specifier) {
ConnectivitySettingsManager.setPrivateDnsMode(mServiceContext, mode);
ConnectivitySettingsManager.setPrivateDnsHostname(mServiceContext, specifier);
- mService.updatePrivateDnsSettings();
waitForIdle();
}
private void setIngressRateLimit(int rateLimitInBytesPerSec) {
ConnectivitySettingsManager.setIngressRateLimitInBytesPerSecond(mServiceContext,
rateLimitInBytesPerSec);
- mService.updateIngressRateLimit();
waitForIdle();
}
@@ -18119,7 +18122,6 @@
private void setAndUpdateMobileDataPreferredUids(Set<Integer> uids) {
ConnectivitySettingsManager.setMobileDataPreferredUids(mServiceContext, uids);
- mService.updateMobileDataPreferredUids();
waitForIdle();
}
@@ -18323,19 +18325,17 @@
*/
@Test
public void testMobileDataPreferredUidsChangedCountsRequestsCorrectlyOnSet() throws Exception {
- ConnectivitySettingsManager.setMobileDataPreferredUids(mServiceContext,
- Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID)));
+ Set uids = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID));
+ ConnectivitySettingsManager.setMobileDataPreferredUids(mServiceContext, uids);
// Leave one request available so MDO preference set up above can be set.
withRequestCountersAcquired(1 /* countToLeaveAvailable */, () ->
withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
Process.myPid(), Process.myUid(), () -> {
// Set initially to test the limit prior to having existing requests.
- mService.updateMobileDataPreferredUids();
- waitForIdle();
+ setAndUpdateMobileDataPreferredUids(uids);
// re-set so as to test the limit as part of replacing existing requests
- mService.updateMobileDataPreferredUids();
- waitForIdle();
+ setAndUpdateMobileDataPreferredUids(uids);
}));
}
diff --git a/tests/unit/java/com/android/server/connectivityservice/CSBlockedReasonsTest.kt b/tests/unit/java/com/android/server/connectivityservice/CSBlockedReasonsTest.kt
index c33dc69..707df7f 100644
--- a/tests/unit/java/com/android/server/connectivityservice/CSBlockedReasonsTest.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/CSBlockedReasonsTest.kt
@@ -336,7 +336,6 @@
// CS must send correct blocked reasons after per app default network change
ConnectivitySettingsManager.setMobileDataPreferredUids(context, setOf(Process.myUid()))
- service.updateMobileDataPreferredUids()
cb.expectAvailableCallbacks(
cellAgent.network,
validated = false,
@@ -345,7 +344,6 @@
// Remove per app default network request
ConnectivitySettingsManager.setMobileDataPreferredUids(context, setOf())
- service.updateMobileDataPreferredUids()
cb.expectAvailableCallbacks(
wifiAgent.network,
validated = false,
diff --git a/tests/unit/java/com/android/server/connectivityservice/CSQueuedCallbacksTest.kt b/tests/unit/java/com/android/server/connectivityservice/CSQueuedCallbacksTest.kt
index 4f15b1a..e96a3ef 100644
--- a/tests/unit/java/com/android/server/connectivityservice/CSQueuedCallbacksTest.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/CSQueuedCallbacksTest.kt
@@ -592,7 +592,6 @@
private fun setMobileDataPreferredUids(uids: Set<Int>) {
ConnectivitySettingsManager.setMobileDataPreferredUids(context, uids)
- service.updateMobileDataPreferredUids()
waitForIdle()
}
}
diff --git a/tests/unit/java/com/android/server/connectivityservice/CSSatelliteNetworkTest.kt b/tests/unit/java/com/android/server/connectivityservice/CSSatelliteNetworkTest.kt
index 31f70fd..5e2cfa0 100644
--- a/tests/unit/java/com/android/server/connectivityservice/CSSatelliteNetworkTest.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/CSSatelliteNetworkTest.kt
@@ -48,8 +48,11 @@
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import com.android.testutils.DevSdkIgnoreRunner
import com.android.testutils.TestableNetworkCallback
+import com.android.testutils.TestableNetworkCallback.Event.CapabilitiesChanged
import com.android.testutils.TestableNetworkCallback.Event.Losing
import com.android.testutils.TestableNetworkCallback.Event.Lost
+import com.android.testutils.TestableNetworkCallback.Event.Resumed
+import com.android.testutils.TestableNetworkCallback.Event.Suspended
import com.android.testutils.runAsShell
import com.android.testutils.visibleOnHandlerThread
import kotlin.test.assertEquals
@@ -301,6 +304,46 @@
otherUidCb.assertNoCallback()
}
+ @Test
+ fun testSuspendAndRoam() {
+ val agent = createSatelliteAgent(
+ name = "satellite0",
+ restricted = false,
+ keepConnected = true
+ )
+ agent.connect()
+ val nr = NetworkRequest.Builder()
+ .clearCapabilities()
+ .addTransportType(TRANSPORT_SATELLITE)
+ .build()
+ val cb = TestableNetworkCallback()
+ cm.registerNetworkCallback(nr, cb)
+ cb.eventuallyExpect<CapabilitiesChanged> {it.network == agent.network &&
+ it.caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED) &&
+ it.caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)
+ }
+
+ // Suspend satellite network
+ val nc1 = satelliteNc(restricted = false)
+ .removeCapability(NET_CAPABILITY_NOT_SUSPENDED)
+ .removeCapability(NET_CAPABILITY_NOT_ROAMING)
+ agent.sendNetworkCapabilities(nc1)
+ cb.eventuallyExpect<CapabilitiesChanged> {it.network == agent.network &&
+ !it.caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED) &&
+ !it.caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)
+ }
+ cb.expect<Suspended>(agent)
+
+ // Resume satellite network
+ val nc2 = satelliteNc(restricted = false)
+ agent.sendNetworkCapabilities(nc2)
+ cb.expect<CapabilitiesChanged> {it.network == agent.network &&
+ it.caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED) &&
+ it.caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)
+ }
+ cb.expect<Resumed>(agent)
+ }
+
private fun assertCreateMultiLayerNrisFromSatelliteNetworkPreferredUids(uids: Set<Int>) {
val nris =
service.createMultiLayerNrisFromSatelliteNetworkFallbackUids(uids, emptySet())
diff --git a/tests/unit/java/com/android/server/connectivityservice/base/CSTest.kt b/tests/unit/java/com/android/server/connectivityservice/base/CSTest.kt
index 5cb2442..68b05dc 100644
--- a/tests/unit/java/com/android/server/connectivityservice/base/CSTest.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/base/CSTest.kt
@@ -21,12 +21,14 @@
import android.app.AppOpsManager
import android.bluetooth.BluetoothManager
import android.content.BroadcastReceiver
+import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.content.pm.UserInfo
import android.content.res.Resources
+import android.database.ContentObserver
import android.net.ConnectivityManager
import android.net.IDnsResolver
import android.net.INetd
@@ -48,6 +50,7 @@
import android.net.NetworkScore
import android.net.NetworkScore.KEEP_CONNECTED_FOR_TEST
import android.net.PacProxyManager
+import android.net.Uri
import android.net.connectivity.ConnectivityCompatChanges.ENABLE_MATCH_LOCAL_NETWORK
import android.net.networkstack.NetworkStackClientBase
import android.os.BatteryStatsManager
@@ -66,6 +69,7 @@
import androidx.test.platform.app.InstrumentationRegistry
import com.android.internal.app.IBatteryStats
import com.android.internal.util.test.BroadcastInterceptingContext
+import com.android.internal.util.test.FakeSettingsProvider
import com.android.metrics.DefaultNetworkRematchMetrics
import com.android.metrics.SatelliteCoarseUsageMetricsCollector
import com.android.metrics.SatisfiedByLocalNetworkMetrics
@@ -88,6 +92,7 @@
import com.android.server.connectivity.ProxyTracker
import com.android.server.connectivity.QuicConnectionCloser
import com.android.server.connectivity.SatelliteAccessController
+import com.android.testutils.ContentResolverWithFakeSettingsProvider
import com.android.testutils.visibleOnHandlerThread
import com.android.testutils.waitForIdle
import java.net.InetAddress
@@ -168,7 +173,11 @@
val instrumentationContext =
TestableContext(InstrumentationRegistry.getInstrumentation().context)
- val context = CSContext(instrumentationContext)
+ val context = CSContext(instrumentationContext).also {
+ // TestableContext uses its own fake settings provider. Reset it so that
+ // the code uses the ContentResolverWithFakeSettingsProvider initialized later.
+ FakeSettingsProvider.clearSettingsProvider()
+ }
// See constructor for default-enabled features. All queried features must be either enabled
// or disabled, because the test can't hold READ_DEVICE_CONFIG and device config utils query
@@ -189,13 +198,14 @@
it[ConnectivityFlags.EARLY_LINK_PROPERTIES_UPDATE_FOR_VPN] = true
it[ConnectivityFlags.CONSTRAINED_DATA_SATELLITE_METRICS] = true
it[ConnectivityFlags.SATISFIED_BY_LOCAL_NETWORK_METRICS] = true
+ it[ConnectivityFlags.USE_SATELLITE_REPORTED_SUSPENDED_AND_ROAMING] = true
}
fun setFeatureEnabled(flag: String, enabled: Boolean) = enabledFeatures.set(flag, enabled)
// When adding new members, consider if it's not better to build the object in CSTestHelpers
// to keep this file clean of implementation details. Generally, CSTestHelpers should only
// need changes when new details of instrumentation are needed.
- val contentResolver = makeMockContentResolver(context)
+ val contentResolver = ContentResolverWithFakeSettingsProvider()
val PRIMARY_USER = 0
val PRIMARY_USER_INFO = UserInfo(
@@ -340,6 +350,14 @@
override fun makeMulticastRoutingCoordinatorService(handler: Handler) =
this@CSTest.multicastRoutingCoordinatorService
+ override fun registerContentObserver(
+ cr: ContentResolver,
+ uri: Uri,
+ notifyForDescendants: Boolean,
+ observer: ContentObserver
+ ) =
+ (cr as ContentResolverWithFakeSettingsProvider).registerContentObserver(uri, observer)
+
override fun makeCarrierPrivilegeAuthenticator(
context: Context,
tm: TelephonyManager,
diff --git a/tests/unit/java/com/android/server/connectivityservice/base/CSTestHelpers.kt b/tests/unit/java/com/android/server/connectivityservice/base/CSTestHelpers.kt
index 69ff193..b3dada5 100644
--- a/tests/unit/java/com/android/server/connectivityservice/base/CSTestHelpers.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/base/CSTestHelpers.kt
@@ -47,11 +47,8 @@
import android.os.SystemConfigManager
import android.os.UserHandle
import android.os.UserManager
-import android.provider.Settings
-import android.test.mock.MockContentResolver
import com.android.connectivity.resources.R
import com.android.internal.util.WakeupMessage
-import com.android.internal.util.test.FakeSettingsProvider
import com.android.modules.utils.build.SdkLevel
import com.android.server.ConnectivityService.Dependencies
import com.android.server.connectivity.ConnectivityResources
@@ -103,10 +100,6 @@
addRoute(RouteInfo(IpPrefix("0.0.0.0/0"), null, null))
}
-internal fun makeMockContentResolver(context: Context) = MockContentResolver(context).apply {
- addProvider(Settings.AUTHORITY, FakeSettingsProvider())
-}
-
internal fun makeMockUserManager(info: UserInfo, handle: UserHandle) = mock<UserManager>().also {
doReturn(listOf(info)).`when`(it).getAliveUsers()
doReturn(listOf(handle)).`when`(it).getUserHandles(ArgumentMatchers.anyBoolean())