mirror of
https://github.com/okhsunrog/vpnhide.git
synced 2026-04-28 06:31:27 +00:00
style: add clang-format, ktlint, editorconfig and format all code
- Add .editorconfig with ktlint config (disable wildcard-import rule, allow PascalCase for @Composable functions) - Add kmod/.clang-format from upstream kernel tree - Run clang-format on vpnhide_kmod.c (kernel coding style) - Run ktlint --format on all Kotlin files (lsposed + test-app)
This commit is contained in:
parent
ca35183084
commit
e2d41dea13
7 changed files with 1065 additions and 284 deletions
14
.editorconfig
Normal file
14
.editorconfig
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.kt]
|
||||
# Compose @Composable functions use PascalCase by convention
|
||||
ktlint_function_naming_ignore_when_annotated_with = Composable
|
||||
# Wildcard imports are idiomatic for Compose (androidx.compose.*)
|
||||
ktlint_standard_no-wildcard-imports = disabled
|
||||
684
kmod/.clang-format
Normal file
684
kmod/.clang-format
Normal file
|
|
@ -0,0 +1,684 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# clang-format configuration file. Intended for clang-format >= 11.
|
||||
#
|
||||
# For more information, see:
|
||||
#
|
||||
# Documentation/process/clang-format.rst
|
||||
# https://clang.llvm.org/docs/ClangFormat.html
|
||||
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
#
|
||||
---
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: false
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: false
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: false
|
||||
|
||||
# Taken from:
|
||||
# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ tools/ \
|
||||
# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
|
||||
# | LC_ALL=C sort -u
|
||||
ForEachMacros:
|
||||
- '__ata_qc_for_each'
|
||||
- '__bio_for_each_bvec'
|
||||
- '__bio_for_each_segment'
|
||||
- '__evlist__for_each_entry'
|
||||
- '__evlist__for_each_entry_continue'
|
||||
- '__evlist__for_each_entry_from'
|
||||
- '__evlist__for_each_entry_reverse'
|
||||
- '__evlist__for_each_entry_safe'
|
||||
- '__for_each_mem_range'
|
||||
- '__for_each_mem_range_rev'
|
||||
- '__for_each_thread'
|
||||
- '__hlist_for_each_rcu'
|
||||
- '__map__for_each_symbol_by_name'
|
||||
- '__perf_evlist__for_each_entry'
|
||||
- '__perf_evlist__for_each_entry_reverse'
|
||||
- '__perf_evlist__for_each_entry_safe'
|
||||
- '__rq_for_each_bio'
|
||||
- '__shost_for_each_device'
|
||||
- 'apei_estatus_for_each_section'
|
||||
- 'ata_for_each_dev'
|
||||
- 'ata_for_each_link'
|
||||
- 'ata_qc_for_each'
|
||||
- 'ata_qc_for_each_raw'
|
||||
- 'ata_qc_for_each_with_internal'
|
||||
- 'ax25_for_each'
|
||||
- 'ax25_uid_for_each'
|
||||
- 'bio_for_each_bvec'
|
||||
- 'bio_for_each_bvec_all'
|
||||
- 'bio_for_each_folio_all'
|
||||
- 'bio_for_each_integrity_vec'
|
||||
- 'bio_for_each_segment'
|
||||
- 'bio_for_each_segment_all'
|
||||
- 'bio_list_for_each'
|
||||
- 'bip_for_each_vec'
|
||||
- 'bond_for_each_slave'
|
||||
- 'bond_for_each_slave_rcu'
|
||||
- 'bpf__perf_for_each_map'
|
||||
- 'bpf__perf_for_each_map_named'
|
||||
- 'bpf_for_each_spilled_reg'
|
||||
- 'bpf_object__for_each_map'
|
||||
- 'bpf_object__for_each_program'
|
||||
- 'bpf_object__for_each_safe'
|
||||
- 'bpf_perf_object__for_each'
|
||||
- 'btree_for_each_safe128'
|
||||
- 'btree_for_each_safe32'
|
||||
- 'btree_for_each_safe64'
|
||||
- 'btree_for_each_safel'
|
||||
- 'card_for_each_dev'
|
||||
- 'cgroup_taskset_for_each'
|
||||
- 'cgroup_taskset_for_each_leader'
|
||||
- 'cpufreq_for_each_efficient_entry_idx'
|
||||
- 'cpufreq_for_each_entry'
|
||||
- 'cpufreq_for_each_entry_idx'
|
||||
- 'cpufreq_for_each_valid_entry'
|
||||
- 'cpufreq_for_each_valid_entry_idx'
|
||||
- 'css_for_each_child'
|
||||
- 'css_for_each_descendant_post'
|
||||
- 'css_for_each_descendant_pre'
|
||||
- 'damon_for_each_region'
|
||||
- 'damon_for_each_region_safe'
|
||||
- 'damon_for_each_scheme'
|
||||
- 'damon_for_each_scheme_safe'
|
||||
- 'damon_for_each_target'
|
||||
- 'damon_for_each_target_safe'
|
||||
- 'data__for_each_file'
|
||||
- 'data__for_each_file_new'
|
||||
- 'data__for_each_file_start'
|
||||
- 'device_for_each_child_node'
|
||||
- 'displayid_iter_for_each'
|
||||
- 'dma_fence_array_for_each'
|
||||
- 'dma_fence_chain_for_each'
|
||||
- 'dma_fence_unwrap_for_each'
|
||||
- 'dma_resv_for_each_fence'
|
||||
- 'dma_resv_for_each_fence_unlocked'
|
||||
- 'do_for_each_ftrace_op'
|
||||
- 'drm_atomic_crtc_for_each_plane'
|
||||
- 'drm_atomic_crtc_state_for_each_plane'
|
||||
- 'drm_atomic_crtc_state_for_each_plane_state'
|
||||
- 'drm_atomic_for_each_plane_damage'
|
||||
- 'drm_client_for_each_connector_iter'
|
||||
- 'drm_client_for_each_modeset'
|
||||
- 'drm_connector_for_each_possible_encoder'
|
||||
- 'drm_for_each_bridge_in_chain'
|
||||
- 'drm_for_each_connector_iter'
|
||||
- 'drm_for_each_crtc'
|
||||
- 'drm_for_each_crtc_reverse'
|
||||
- 'drm_for_each_encoder'
|
||||
- 'drm_for_each_encoder_mask'
|
||||
- 'drm_for_each_fb'
|
||||
- 'drm_for_each_legacy_plane'
|
||||
- 'drm_for_each_plane'
|
||||
- 'drm_for_each_plane_mask'
|
||||
- 'drm_for_each_privobj'
|
||||
- 'drm_mm_for_each_hole'
|
||||
- 'drm_mm_for_each_node'
|
||||
- 'drm_mm_for_each_node_in_range'
|
||||
- 'drm_mm_for_each_node_safe'
|
||||
- 'dsa_switch_for_each_available_port'
|
||||
- 'dsa_switch_for_each_cpu_port'
|
||||
- 'dsa_switch_for_each_port'
|
||||
- 'dsa_switch_for_each_port_continue_reverse'
|
||||
- 'dsa_switch_for_each_port_safe'
|
||||
- 'dsa_switch_for_each_user_port'
|
||||
- 'dsa_tree_for_each_user_port'
|
||||
- 'dso__for_each_symbol'
|
||||
- 'dsos__for_each_with_build_id'
|
||||
- 'elf_hash_for_each_possible'
|
||||
- 'elf_section__for_each_rel'
|
||||
- 'elf_section__for_each_rela'
|
||||
- 'elf_symtab__for_each_symbol'
|
||||
- 'evlist__for_each_cpu'
|
||||
- 'evlist__for_each_entry'
|
||||
- 'evlist__for_each_entry_continue'
|
||||
- 'evlist__for_each_entry_from'
|
||||
- 'evlist__for_each_entry_reverse'
|
||||
- 'evlist__for_each_entry_safe'
|
||||
- 'flow_action_for_each'
|
||||
- 'for_each_acpi_dev_match'
|
||||
- 'for_each_active_dev_scope'
|
||||
- 'for_each_active_drhd_unit'
|
||||
- 'for_each_active_iommu'
|
||||
- 'for_each_aggr_pgid'
|
||||
- 'for_each_available_child_of_node'
|
||||
- 'for_each_bench'
|
||||
- 'for_each_bio'
|
||||
- 'for_each_board_func_rsrc'
|
||||
- 'for_each_btf_ext_rec'
|
||||
- 'for_each_btf_ext_sec'
|
||||
- 'for_each_bvec'
|
||||
- 'for_each_card_auxs'
|
||||
- 'for_each_card_auxs_safe'
|
||||
- 'for_each_card_components'
|
||||
- 'for_each_card_dapms'
|
||||
- 'for_each_card_pre_auxs'
|
||||
- 'for_each_card_prelinks'
|
||||
- 'for_each_card_rtds'
|
||||
- 'for_each_card_rtds_safe'
|
||||
- 'for_each_card_widgets'
|
||||
- 'for_each_card_widgets_safe'
|
||||
- 'for_each_cgroup_storage_type'
|
||||
- 'for_each_child_of_node'
|
||||
- 'for_each_clear_bit'
|
||||
- 'for_each_clear_bit_from'
|
||||
- 'for_each_clear_bitrange'
|
||||
- 'for_each_clear_bitrange_from'
|
||||
- 'for_each_cmd'
|
||||
- 'for_each_cmsghdr'
|
||||
- 'for_each_collection'
|
||||
- 'for_each_comp_order'
|
||||
- 'for_each_compatible_node'
|
||||
- 'for_each_component_dais'
|
||||
- 'for_each_component_dais_safe'
|
||||
- 'for_each_console'
|
||||
- 'for_each_cpu'
|
||||
- 'for_each_cpu_and'
|
||||
- 'for_each_cpu_not'
|
||||
- 'for_each_cpu_wrap'
|
||||
- 'for_each_dapm_widgets'
|
||||
- 'for_each_dedup_cand'
|
||||
- 'for_each_dev_addr'
|
||||
- 'for_each_dev_scope'
|
||||
- 'for_each_dma_cap_mask'
|
||||
- 'for_each_dpcm_be'
|
||||
- 'for_each_dpcm_be_rollback'
|
||||
- 'for_each_dpcm_be_safe'
|
||||
- 'for_each_dpcm_fe'
|
||||
- 'for_each_drhd_unit'
|
||||
- 'for_each_dss_dev'
|
||||
- 'for_each_efi_memory_desc'
|
||||
- 'for_each_efi_memory_desc_in_map'
|
||||
- 'for_each_element'
|
||||
- 'for_each_element_extid'
|
||||
- 'for_each_element_id'
|
||||
- 'for_each_endpoint_of_node'
|
||||
- 'for_each_event'
|
||||
- 'for_each_event_tps'
|
||||
- 'for_each_evictable_lru'
|
||||
- 'for_each_fib6_node_rt_rcu'
|
||||
- 'for_each_fib6_walker_rt'
|
||||
- 'for_each_free_mem_pfn_range_in_zone'
|
||||
- 'for_each_free_mem_pfn_range_in_zone_from'
|
||||
- 'for_each_free_mem_range'
|
||||
- 'for_each_free_mem_range_reverse'
|
||||
- 'for_each_func_rsrc'
|
||||
- 'for_each_group_evsel'
|
||||
- 'for_each_group_member'
|
||||
- 'for_each_hstate'
|
||||
- 'for_each_if'
|
||||
- 'for_each_inject_fn'
|
||||
- 'for_each_insn'
|
||||
- 'for_each_insn_prefix'
|
||||
- 'for_each_intid'
|
||||
- 'for_each_iommu'
|
||||
- 'for_each_ip_tunnel_rcu'
|
||||
- 'for_each_irq_nr'
|
||||
- 'for_each_lang'
|
||||
- 'for_each_link_codecs'
|
||||
- 'for_each_link_cpus'
|
||||
- 'for_each_link_platforms'
|
||||
- 'for_each_lru'
|
||||
- 'for_each_matching_node'
|
||||
- 'for_each_matching_node_and_match'
|
||||
- 'for_each_mem_pfn_range'
|
||||
- 'for_each_mem_range'
|
||||
- 'for_each_mem_range_rev'
|
||||
- 'for_each_mem_region'
|
||||
- 'for_each_member'
|
||||
- 'for_each_memory'
|
||||
- 'for_each_migratetype_order'
|
||||
- 'for_each_missing_reg'
|
||||
- 'for_each_net'
|
||||
- 'for_each_net_continue_reverse'
|
||||
- 'for_each_net_rcu'
|
||||
- 'for_each_netdev'
|
||||
- 'for_each_netdev_continue'
|
||||
- 'for_each_netdev_continue_rcu'
|
||||
- 'for_each_netdev_continue_reverse'
|
||||
- 'for_each_netdev_feature'
|
||||
- 'for_each_netdev_in_bond_rcu'
|
||||
- 'for_each_netdev_rcu'
|
||||
- 'for_each_netdev_reverse'
|
||||
- 'for_each_netdev_safe'
|
||||
- 'for_each_new_connector_in_state'
|
||||
- 'for_each_new_crtc_in_state'
|
||||
- 'for_each_new_mst_mgr_in_state'
|
||||
- 'for_each_new_plane_in_state'
|
||||
- 'for_each_new_plane_in_state_reverse'
|
||||
- 'for_each_new_private_obj_in_state'
|
||||
- 'for_each_new_reg'
|
||||
- 'for_each_node'
|
||||
- 'for_each_node_by_name'
|
||||
- 'for_each_node_by_type'
|
||||
- 'for_each_node_mask'
|
||||
- 'for_each_node_state'
|
||||
- 'for_each_node_with_cpus'
|
||||
- 'for_each_node_with_property'
|
||||
- 'for_each_nonreserved_multicast_dest_pgid'
|
||||
- 'for_each_of_allnodes'
|
||||
- 'for_each_of_allnodes_from'
|
||||
- 'for_each_of_cpu_node'
|
||||
- 'for_each_of_pci_range'
|
||||
- 'for_each_old_connector_in_state'
|
||||
- 'for_each_old_crtc_in_state'
|
||||
- 'for_each_old_mst_mgr_in_state'
|
||||
- 'for_each_old_plane_in_state'
|
||||
- 'for_each_old_private_obj_in_state'
|
||||
- 'for_each_oldnew_connector_in_state'
|
||||
- 'for_each_oldnew_crtc_in_state'
|
||||
- 'for_each_oldnew_mst_mgr_in_state'
|
||||
- 'for_each_oldnew_plane_in_state'
|
||||
- 'for_each_oldnew_plane_in_state_reverse'
|
||||
- 'for_each_oldnew_private_obj_in_state'
|
||||
- 'for_each_online_cpu'
|
||||
- 'for_each_online_node'
|
||||
- 'for_each_online_pgdat'
|
||||
- 'for_each_path'
|
||||
- 'for_each_pci_bridge'
|
||||
- 'for_each_pci_dev'
|
||||
- 'for_each_pcm_streams'
|
||||
- 'for_each_physmem_range'
|
||||
- 'for_each_populated_zone'
|
||||
- 'for_each_possible_cpu'
|
||||
- 'for_each_present_cpu'
|
||||
- 'for_each_prime_number'
|
||||
- 'for_each_prime_number_from'
|
||||
- 'for_each_probe_cache_entry'
|
||||
- 'for_each_process'
|
||||
- 'for_each_process_thread'
|
||||
- 'for_each_prop_codec_conf'
|
||||
- 'for_each_prop_dai_codec'
|
||||
- 'for_each_prop_dai_cpu'
|
||||
- 'for_each_prop_dlc_codecs'
|
||||
- 'for_each_prop_dlc_cpus'
|
||||
- 'for_each_prop_dlc_platforms'
|
||||
- 'for_each_property_of_node'
|
||||
- 'for_each_reg'
|
||||
- 'for_each_reg_filtered'
|
||||
- 'for_each_registered_fb'
|
||||
- 'for_each_requested_gpio'
|
||||
- 'for_each_requested_gpio_in_range'
|
||||
- 'for_each_reserved_mem_range'
|
||||
- 'for_each_reserved_mem_region'
|
||||
- 'for_each_rtd_codec_dais'
|
||||
- 'for_each_rtd_components'
|
||||
- 'for_each_rtd_cpu_dais'
|
||||
- 'for_each_rtd_dais'
|
||||
- 'for_each_script'
|
||||
- 'for_each_sec'
|
||||
- 'for_each_set_bit'
|
||||
- 'for_each_set_bit_from'
|
||||
- 'for_each_set_bitrange'
|
||||
- 'for_each_set_bitrange_from'
|
||||
- 'for_each_set_clump8'
|
||||
- 'for_each_sg'
|
||||
- 'for_each_sg_dma_page'
|
||||
- 'for_each_sg_page'
|
||||
- 'for_each_sgtable_dma_page'
|
||||
- 'for_each_sgtable_dma_sg'
|
||||
- 'for_each_sgtable_page'
|
||||
- 'for_each_sgtable_sg'
|
||||
- 'for_each_shell_test'
|
||||
- 'for_each_sibling_event'
|
||||
- 'for_each_subelement'
|
||||
- 'for_each_subelement_extid'
|
||||
- 'for_each_subelement_id'
|
||||
- 'for_each_sublist'
|
||||
- 'for_each_subsystem'
|
||||
- 'for_each_supported_activate_fn'
|
||||
- 'for_each_supported_inject_fn'
|
||||
- 'for_each_test'
|
||||
- 'for_each_thread'
|
||||
- 'for_each_token'
|
||||
- 'for_each_unicast_dest_pgid'
|
||||
- 'for_each_vsi'
|
||||
- 'for_each_wakeup_source'
|
||||
- 'for_each_zone'
|
||||
- 'for_each_zone_zonelist'
|
||||
- 'for_each_zone_zonelist_nodemask'
|
||||
- 'func_for_each_insn'
|
||||
- 'fwnode_for_each_available_child_node'
|
||||
- 'fwnode_for_each_child_node'
|
||||
- 'fwnode_graph_for_each_endpoint'
|
||||
- 'gadget_for_each_ep'
|
||||
- 'genradix_for_each'
|
||||
- 'genradix_for_each_from'
|
||||
- 'hash_for_each'
|
||||
- 'hash_for_each_possible'
|
||||
- 'hash_for_each_possible_rcu'
|
||||
- 'hash_for_each_possible_rcu_notrace'
|
||||
- 'hash_for_each_possible_safe'
|
||||
- 'hash_for_each_rcu'
|
||||
- 'hash_for_each_safe'
|
||||
- 'hashmap__for_each_entry'
|
||||
- 'hashmap__for_each_entry_safe'
|
||||
- 'hashmap__for_each_key_entry'
|
||||
- 'hashmap__for_each_key_entry_safe'
|
||||
- 'hctx_for_each_ctx'
|
||||
- 'hists__for_each_format'
|
||||
- 'hists__for_each_sort_list'
|
||||
- 'hlist_bl_for_each_entry'
|
||||
- 'hlist_bl_for_each_entry_rcu'
|
||||
- 'hlist_bl_for_each_entry_safe'
|
||||
- 'hlist_for_each'
|
||||
- 'hlist_for_each_entry'
|
||||
- 'hlist_for_each_entry_continue'
|
||||
- 'hlist_for_each_entry_continue_rcu'
|
||||
- 'hlist_for_each_entry_continue_rcu_bh'
|
||||
- 'hlist_for_each_entry_from'
|
||||
- 'hlist_for_each_entry_from_rcu'
|
||||
- 'hlist_for_each_entry_rcu'
|
||||
- 'hlist_for_each_entry_rcu_bh'
|
||||
- 'hlist_for_each_entry_rcu_notrace'
|
||||
- 'hlist_for_each_entry_safe'
|
||||
- 'hlist_for_each_entry_srcu'
|
||||
- 'hlist_for_each_safe'
|
||||
- 'hlist_nulls_for_each_entry'
|
||||
- 'hlist_nulls_for_each_entry_from'
|
||||
- 'hlist_nulls_for_each_entry_rcu'
|
||||
- 'hlist_nulls_for_each_entry_safe'
|
||||
- 'i3c_bus_for_each_i2cdev'
|
||||
- 'i3c_bus_for_each_i3cdev'
|
||||
- 'idr_for_each_entry'
|
||||
- 'idr_for_each_entry_continue'
|
||||
- 'idr_for_each_entry_continue_ul'
|
||||
- 'idr_for_each_entry_ul'
|
||||
- 'in_dev_for_each_ifa_rcu'
|
||||
- 'in_dev_for_each_ifa_rtnl'
|
||||
- 'inet_bind_bucket_for_each'
|
||||
- 'inet_lhash2_for_each_icsk'
|
||||
- 'inet_lhash2_for_each_icsk_continue'
|
||||
- 'inet_lhash2_for_each_icsk_rcu'
|
||||
- 'intlist__for_each_entry'
|
||||
- 'intlist__for_each_entry_safe'
|
||||
- 'kcore_copy__for_each_phdr'
|
||||
- 'key_for_each'
|
||||
- 'key_for_each_safe'
|
||||
- 'klp_for_each_func'
|
||||
- 'klp_for_each_func_safe'
|
||||
- 'klp_for_each_func_static'
|
||||
- 'klp_for_each_object'
|
||||
- 'klp_for_each_object_safe'
|
||||
- 'klp_for_each_object_static'
|
||||
- 'kunit_suite_for_each_test_case'
|
||||
- 'kvm_for_each_memslot'
|
||||
- 'kvm_for_each_memslot_in_gfn_range'
|
||||
- 'kvm_for_each_vcpu'
|
||||
- 'libbpf_nla_for_each_attr'
|
||||
- 'list_for_each'
|
||||
- 'list_for_each_codec'
|
||||
- 'list_for_each_codec_safe'
|
||||
- 'list_for_each_continue'
|
||||
- 'list_for_each_entry'
|
||||
- 'list_for_each_entry_continue'
|
||||
- 'list_for_each_entry_continue_rcu'
|
||||
- 'list_for_each_entry_continue_reverse'
|
||||
- 'list_for_each_entry_from'
|
||||
- 'list_for_each_entry_from_rcu'
|
||||
- 'list_for_each_entry_from_reverse'
|
||||
- 'list_for_each_entry_lockless'
|
||||
- 'list_for_each_entry_rcu'
|
||||
- 'list_for_each_entry_reverse'
|
||||
- 'list_for_each_entry_safe'
|
||||
- 'list_for_each_entry_safe_continue'
|
||||
- 'list_for_each_entry_safe_from'
|
||||
- 'list_for_each_entry_safe_reverse'
|
||||
- 'list_for_each_entry_srcu'
|
||||
- 'list_for_each_from'
|
||||
- 'list_for_each_prev'
|
||||
- 'list_for_each_prev_safe'
|
||||
- 'list_for_each_safe'
|
||||
- 'llist_for_each'
|
||||
- 'llist_for_each_entry'
|
||||
- 'llist_for_each_entry_safe'
|
||||
- 'llist_for_each_safe'
|
||||
- 'map__for_each_symbol'
|
||||
- 'map__for_each_symbol_by_name'
|
||||
- 'map_for_each_event'
|
||||
- 'map_for_each_metric'
|
||||
- 'maps__for_each_entry'
|
||||
- 'maps__for_each_entry_safe'
|
||||
- 'mci_for_each_dimm'
|
||||
- 'media_device_for_each_entity'
|
||||
- 'media_device_for_each_intf'
|
||||
- 'media_device_for_each_link'
|
||||
- 'media_device_for_each_pad'
|
||||
- 'msi_for_each_desc'
|
||||
- 'nanddev_io_for_each_page'
|
||||
- 'netdev_for_each_lower_dev'
|
||||
- 'netdev_for_each_lower_private'
|
||||
- 'netdev_for_each_lower_private_rcu'
|
||||
- 'netdev_for_each_mc_addr'
|
||||
- 'netdev_for_each_uc_addr'
|
||||
- 'netdev_for_each_upper_dev_rcu'
|
||||
- 'netdev_hw_addr_list_for_each'
|
||||
- 'nft_rule_for_each_expr'
|
||||
- 'nla_for_each_attr'
|
||||
- 'nla_for_each_nested'
|
||||
- 'nlmsg_for_each_attr'
|
||||
- 'nlmsg_for_each_msg'
|
||||
- 'nr_neigh_for_each'
|
||||
- 'nr_neigh_for_each_safe'
|
||||
- 'nr_node_for_each'
|
||||
- 'nr_node_for_each_safe'
|
||||
- 'of_for_each_phandle'
|
||||
- 'of_property_for_each_string'
|
||||
- 'of_property_for_each_u32'
|
||||
- 'pci_bus_for_each_resource'
|
||||
- 'pci_doe_for_each_off'
|
||||
- 'pcl_for_each_chunk'
|
||||
- 'pcl_for_each_segment'
|
||||
- 'pcm_for_each_format'
|
||||
- 'perf_config_items__for_each_entry'
|
||||
- 'perf_config_sections__for_each_entry'
|
||||
- 'perf_config_set__for_each_entry'
|
||||
- 'perf_cpu_map__for_each_cpu'
|
||||
- 'perf_evlist__for_each_entry'
|
||||
- 'perf_evlist__for_each_entry_reverse'
|
||||
- 'perf_evlist__for_each_entry_safe'
|
||||
- 'perf_evlist__for_each_evsel'
|
||||
- 'perf_evlist__for_each_mmap'
|
||||
- 'perf_hpp_list__for_each_format'
|
||||
- 'perf_hpp_list__for_each_format_safe'
|
||||
- 'perf_hpp_list__for_each_sort_list'
|
||||
- 'perf_hpp_list__for_each_sort_list_safe'
|
||||
- 'perf_pmu__for_each_hybrid_pmu'
|
||||
- 'ping_portaddr_for_each_entry'
|
||||
- 'ping_portaddr_for_each_entry_rcu'
|
||||
- 'plist_for_each'
|
||||
- 'plist_for_each_continue'
|
||||
- 'plist_for_each_entry'
|
||||
- 'plist_for_each_entry_continue'
|
||||
- 'plist_for_each_entry_safe'
|
||||
- 'plist_for_each_safe'
|
||||
- 'pnp_for_each_card'
|
||||
- 'pnp_for_each_dev'
|
||||
- 'protocol_for_each_card'
|
||||
- 'protocol_for_each_dev'
|
||||
- 'queue_for_each_hw_ctx'
|
||||
- 'radix_tree_for_each_slot'
|
||||
- 'radix_tree_for_each_tagged'
|
||||
- 'rb_for_each'
|
||||
- 'rbtree_postorder_for_each_entry_safe'
|
||||
- 'rdma_for_each_block'
|
||||
- 'rdma_for_each_port'
|
||||
- 'rdma_umem_for_each_dma_block'
|
||||
- 'resort_rb__for_each_entry'
|
||||
- 'resource_list_for_each_entry'
|
||||
- 'resource_list_for_each_entry_safe'
|
||||
- 'rhl_for_each_entry_rcu'
|
||||
- 'rhl_for_each_rcu'
|
||||
- 'rht_for_each'
|
||||
- 'rht_for_each_entry'
|
||||
- 'rht_for_each_entry_from'
|
||||
- 'rht_for_each_entry_rcu'
|
||||
- 'rht_for_each_entry_rcu_from'
|
||||
- 'rht_for_each_entry_safe'
|
||||
- 'rht_for_each_from'
|
||||
- 'rht_for_each_rcu'
|
||||
- 'rht_for_each_rcu_from'
|
||||
- 'rq_for_each_bvec'
|
||||
- 'rq_for_each_segment'
|
||||
- 'rq_list_for_each'
|
||||
- 'rq_list_for_each_safe'
|
||||
- 'scsi_for_each_prot_sg'
|
||||
- 'scsi_for_each_sg'
|
||||
- 'sctp_for_each_hentry'
|
||||
- 'sctp_skb_for_each'
|
||||
- 'sec_for_each_insn'
|
||||
- 'sec_for_each_insn_continue'
|
||||
- 'sec_for_each_insn_from'
|
||||
- 'shdma_for_each_chan'
|
||||
- 'shost_for_each_device'
|
||||
- 'sk_for_each'
|
||||
- 'sk_for_each_bound'
|
||||
- 'sk_for_each_entry_offset_rcu'
|
||||
- 'sk_for_each_from'
|
||||
- 'sk_for_each_rcu'
|
||||
- 'sk_for_each_safe'
|
||||
- 'sk_nulls_for_each'
|
||||
- 'sk_nulls_for_each_from'
|
||||
- 'sk_nulls_for_each_rcu'
|
||||
- 'snd_array_for_each'
|
||||
- 'snd_pcm_group_for_each_entry'
|
||||
- 'snd_soc_dapm_widget_for_each_path'
|
||||
- 'snd_soc_dapm_widget_for_each_path_safe'
|
||||
- 'snd_soc_dapm_widget_for_each_sink_path'
|
||||
- 'snd_soc_dapm_widget_for_each_source_path'
|
||||
- 'strlist__for_each_entry'
|
||||
- 'strlist__for_each_entry_safe'
|
||||
- 'sym_for_each_insn'
|
||||
- 'sym_for_each_insn_continue_reverse'
|
||||
- 'symbols__for_each_entry'
|
||||
- 'tb_property_for_each'
|
||||
- 'tcf_act_for_each_action'
|
||||
- 'tcf_exts_for_each_action'
|
||||
- 'udp_portaddr_for_each_entry'
|
||||
- 'udp_portaddr_for_each_entry_rcu'
|
||||
- 'usb_hub_for_each_child'
|
||||
- 'v4l2_device_for_each_subdev'
|
||||
- 'v4l2_m2m_for_each_dst_buf'
|
||||
- 'v4l2_m2m_for_each_dst_buf_safe'
|
||||
- 'v4l2_m2m_for_each_src_buf'
|
||||
- 'v4l2_m2m_for_each_src_buf_safe'
|
||||
- 'virtio_device_for_each_vq'
|
||||
- 'while_for_each_ftrace_op'
|
||||
- 'xa_for_each'
|
||||
- 'xa_for_each_marked'
|
||||
- 'xa_for_each_range'
|
||||
- 'xa_for_each_start'
|
||||
- 'xas_for_each'
|
||||
- 'xas_for_each_conflict'
|
||||
- 'xas_for_each_marked'
|
||||
- 'xbc_array_for_each_value'
|
||||
- 'xbc_for_each_key_value'
|
||||
- 'xbc_node_for_each_array_value'
|
||||
- 'xbc_node_for_each_child'
|
||||
- 'xbc_node_for_each_key_value'
|
||||
- 'xbc_node_for_each_subkey'
|
||||
- 'zorro_for_each_dev'
|
||||
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IndentCaseLabels: false
|
||||
IndentGotoLabels: false
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 8
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 8
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
|
||||
# Taken from git's rules
|
||||
PenaltyBreakAssignment: 10
|
||||
PenaltyBreakBeforeFirstCallParameter: 30
|
||||
PenaltyBreakComment: 10
|
||||
PenaltyBreakFirstLessLess: 0
|
||||
PenaltyBreakString: 10
|
||||
PenaltyExcessCharacter: 100
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
|
||||
PointerAlignment: Right
|
||||
ReflowComments: false
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: false
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatementsExceptForEachMacros
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp03
|
||||
TabWidth: 8
|
||||
UseTab: Always
|
||||
...
|
||||
|
|
@ -43,7 +43,7 @@
|
|||
/* VPN interface name matching */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static const char * const vpn_prefixes[] = {
|
||||
static const char *const vpn_prefixes[] = {
|
||||
"tun", "ppp", "tap", "wg", "ipsec", "xfrm", "utun", "l2tp", "gre",
|
||||
};
|
||||
|
||||
|
|
@ -55,8 +55,8 @@ static bool is_vpn_ifname(const char *name)
|
|||
return false;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(vpn_prefixes); i++) {
|
||||
if (strncmp(name, vpn_prefixes[i],
|
||||
strlen(vpn_prefixes[i])) == 0)
|
||||
if (strncmp(name, vpn_prefixes[i], strlen(vpn_prefixes[i])) ==
|
||||
0)
|
||||
return true;
|
||||
}
|
||||
if (strstr(name, "vpn") || strstr(name, "VPN"))
|
||||
|
|
@ -158,10 +158,10 @@ static int targets_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
|
||||
static const struct proc_ops targets_proc_ops = {
|
||||
.proc_open = targets_open,
|
||||
.proc_read = seq_read,
|
||||
.proc_write = targets_write,
|
||||
.proc_lseek = seq_lseek,
|
||||
.proc_open = targets_open,
|
||||
.proc_read = seq_read,
|
||||
.proc_write = targets_write,
|
||||
.proc_lseek = seq_lseek,
|
||||
.proc_release = single_release,
|
||||
};
|
||||
|
||||
|
|
@ -183,8 +183,7 @@ struct dev_ioctl_data {
|
|||
struct ifreq *kifr; /* kernel pointer, saved from x2 */
|
||||
};
|
||||
|
||||
static int dev_ioctl_entry(struct kretprobe_instance *ri,
|
||||
struct pt_regs *regs)
|
||||
static int dev_ioctl_entry(struct kretprobe_instance *ri, struct pt_regs *regs)
|
||||
{
|
||||
struct dev_ioctl_data *data = (void *)ri->data;
|
||||
|
||||
|
|
@ -197,8 +196,7 @@ static int dev_ioctl_entry(struct kretprobe_instance *ri,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dev_ioctl_ret(struct kretprobe_instance *ri,
|
||||
struct pt_regs *regs)
|
||||
static int dev_ioctl_ret(struct kretprobe_instance *ri, struct pt_regs *regs)
|
||||
{
|
||||
struct dev_ioctl_data *data = (void *)ri->data;
|
||||
char name[IFNAMSIZ];
|
||||
|
|
@ -227,11 +225,11 @@ static int dev_ioctl_ret(struct kretprobe_instance *ri,
|
|||
}
|
||||
|
||||
static struct kretprobe dev_ioctl_krp = {
|
||||
.handler = dev_ioctl_ret,
|
||||
.entry_handler = dev_ioctl_entry,
|
||||
.data_size = sizeof(struct dev_ioctl_data),
|
||||
.maxactive = 20,
|
||||
.kp.symbol_name = "dev_ioctl",
|
||||
.handler = dev_ioctl_ret,
|
||||
.entry_handler = dev_ioctl_entry,
|
||||
.data_size = sizeof(struct dev_ioctl_data),
|
||||
.maxactive = 20,
|
||||
.kp.symbol_name = "dev_ioctl",
|
||||
};
|
||||
|
||||
/* ================================================================== */
|
||||
|
|
@ -249,8 +247,7 @@ struct dev_ifconf_data {
|
|||
bool target;
|
||||
};
|
||||
|
||||
static int dev_ifconf_entry(struct kretprobe_instance *ri,
|
||||
struct pt_regs *regs)
|
||||
static int dev_ifconf_entry(struct kretprobe_instance *ri, struct pt_regs *regs)
|
||||
{
|
||||
struct dev_ifconf_data *data = (void *)ri->data;
|
||||
|
||||
|
|
@ -259,8 +256,7 @@ static int dev_ifconf_entry(struct kretprobe_instance *ri,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dev_ifconf_ret(struct kretprobe_instance *ri,
|
||||
struct pt_regs *regs)
|
||||
static int dev_ifconf_ret(struct kretprobe_instance *ri, struct pt_regs *regs)
|
||||
{
|
||||
struct dev_ifconf_data *data = (void *)ri->data;
|
||||
struct ifconf ifc;
|
||||
|
|
@ -304,11 +300,11 @@ static int dev_ifconf_ret(struct kretprobe_instance *ri,
|
|||
}
|
||||
|
||||
static struct kretprobe dev_ifconf_krp = {
|
||||
.handler = dev_ifconf_ret,
|
||||
.entry_handler = dev_ifconf_entry,
|
||||
.data_size = sizeof(struct dev_ifconf_data),
|
||||
.maxactive = 20,
|
||||
.kp.symbol_name = "dev_ifconf",
|
||||
.handler = dev_ifconf_ret,
|
||||
.entry_handler = dev_ifconf_entry,
|
||||
.data_size = sizeof(struct dev_ifconf_data),
|
||||
.maxactive = 20,
|
||||
.kp.symbol_name = "dev_ifconf",
|
||||
};
|
||||
|
||||
/* ================================================================== */
|
||||
|
|
@ -325,8 +321,7 @@ struct rtnl_fill_data {
|
|||
bool should_filter;
|
||||
};
|
||||
|
||||
static int rtnl_fill_entry(struct kretprobe_instance *ri,
|
||||
struct pt_regs *regs)
|
||||
static int rtnl_fill_entry(struct kretprobe_instance *ri, struct pt_regs *regs)
|
||||
{
|
||||
struct rtnl_fill_data *data = (void *)ri->data;
|
||||
struct net_device *dev;
|
||||
|
|
@ -351,8 +346,7 @@ static int rtnl_fill_entry(struct kretprobe_instance *ri,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rtnl_fill_ret(struct kretprobe_instance *ri,
|
||||
struct pt_regs *regs)
|
||||
static int rtnl_fill_ret(struct kretprobe_instance *ri, struct pt_regs *regs)
|
||||
{
|
||||
struct rtnl_fill_data *data = (void *)ri->data;
|
||||
|
||||
|
|
@ -363,11 +357,11 @@ static int rtnl_fill_ret(struct kretprobe_instance *ri,
|
|||
}
|
||||
|
||||
static struct kretprobe rtnl_fill_krp = {
|
||||
.handler = rtnl_fill_ret,
|
||||
.entry_handler = rtnl_fill_entry,
|
||||
.data_size = sizeof(struct rtnl_fill_data),
|
||||
.maxactive = 20,
|
||||
.kp.symbol_name = "rtnl_fill_ifinfo",
|
||||
.handler = rtnl_fill_ret,
|
||||
.entry_handler = rtnl_fill_entry,
|
||||
.data_size = sizeof(struct rtnl_fill_data),
|
||||
.maxactive = 20,
|
||||
.kp.symbol_name = "rtnl_fill_ifinfo",
|
||||
};
|
||||
|
||||
/* ================================================================== */
|
||||
|
|
@ -393,8 +387,7 @@ struct inet6_fill_data {
|
|||
bool should_filter;
|
||||
};
|
||||
|
||||
static int inet6_fill_entry(struct kretprobe_instance *ri,
|
||||
struct pt_regs *regs)
|
||||
static int inet6_fill_entry(struct kretprobe_instance *ri, struct pt_regs *regs)
|
||||
{
|
||||
struct inet6_fill_data *data = (void *)ri->data;
|
||||
struct inet6_ifaddr *ifa;
|
||||
|
|
@ -422,8 +415,7 @@ static int inet6_fill_entry(struct kretprobe_instance *ri,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int inet6_fill_ret(struct kretprobe_instance *ri,
|
||||
struct pt_regs *regs)
|
||||
static int inet6_fill_ret(struct kretprobe_instance *ri, struct pt_regs *regs)
|
||||
{
|
||||
struct inet6_fill_data *data = (void *)ri->data;
|
||||
|
||||
|
|
@ -437,11 +429,11 @@ static int inet6_fill_ret(struct kretprobe_instance *ri,
|
|||
}
|
||||
|
||||
static struct kretprobe inet6_fill_krp = {
|
||||
.handler = inet6_fill_ret,
|
||||
.entry_handler = inet6_fill_entry,
|
||||
.data_size = sizeof(struct inet6_fill_data),
|
||||
.maxactive = 20,
|
||||
.kp.symbol_name = "inet6_fill_ifaddr",
|
||||
.handler = inet6_fill_ret,
|
||||
.entry_handler = inet6_fill_entry,
|
||||
.data_size = sizeof(struct inet6_fill_data),
|
||||
.maxactive = 20,
|
||||
.kp.symbol_name = "inet6_fill_ifaddr",
|
||||
};
|
||||
|
||||
/* ================================================================== */
|
||||
|
|
@ -459,8 +451,7 @@ struct inet_fill_data {
|
|||
bool should_filter;
|
||||
};
|
||||
|
||||
static int inet_fill_entry(struct kretprobe_instance *ri,
|
||||
struct pt_regs *regs)
|
||||
static int inet_fill_entry(struct kretprobe_instance *ri, struct pt_regs *regs)
|
||||
{
|
||||
struct inet_fill_data *data = (void *)ri->data;
|
||||
struct in_ifaddr *ifa;
|
||||
|
|
@ -484,8 +475,7 @@ static int inet_fill_entry(struct kretprobe_instance *ri,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int inet_fill_ret(struct kretprobe_instance *ri,
|
||||
struct pt_regs *regs)
|
||||
static int inet_fill_ret(struct kretprobe_instance *ri, struct pt_regs *regs)
|
||||
{
|
||||
struct inet_fill_data *data = (void *)ri->data;
|
||||
|
||||
|
|
@ -498,11 +488,11 @@ static int inet_fill_ret(struct kretprobe_instance *ri,
|
|||
}
|
||||
|
||||
static struct kretprobe inet_fill_krp = {
|
||||
.handler = inet_fill_ret,
|
||||
.entry_handler = inet_fill_entry,
|
||||
.data_size = sizeof(struct inet_fill_data),
|
||||
.maxactive = 20,
|
||||
.kp.symbol_name = "inet_fill_ifaddr",
|
||||
.handler = inet_fill_ret,
|
||||
.entry_handler = inet_fill_entry,
|
||||
.data_size = sizeof(struct inet_fill_data),
|
||||
.maxactive = 20,
|
||||
.kp.symbol_name = "inet_fill_ifaddr",
|
||||
};
|
||||
|
||||
/* ================================================================== */
|
||||
|
|
@ -522,8 +512,7 @@ struct fib_route_data {
|
|||
bool target;
|
||||
};
|
||||
|
||||
static int fib_route_entry(struct kretprobe_instance *ri,
|
||||
struct pt_regs *regs)
|
||||
static int fib_route_entry(struct kretprobe_instance *ri, struct pt_regs *regs)
|
||||
{
|
||||
struct fib_route_data *data = (void *)ri->data;
|
||||
|
||||
|
|
@ -549,8 +538,7 @@ static int fib_route_entry(struct kretprobe_instance *ri,
|
|||
* synchronously under its own fd context — no concurrent access to
|
||||
* the same seq_file is possible between our entry and return handlers.
|
||||
*/
|
||||
static int fib_route_ret(struct kretprobe_instance *ri,
|
||||
struct pt_regs *regs)
|
||||
static int fib_route_ret(struct kretprobe_instance *ri, struct pt_regs *regs)
|
||||
{
|
||||
struct fib_route_data *data = (void *)ri->data;
|
||||
struct seq_file *seq = data->seq;
|
||||
|
|
@ -583,7 +571,8 @@ static int fib_route_ret(struct kretprobe_instance *ri,
|
|||
|
||||
/* Extract the interface name (first field, tab-delimited) */
|
||||
for (j = 0; j < IFNAMSIZ - 1 && j < (int)line_len &&
|
||||
src[j] != '\t' && src[j] != '\n'; j++)
|
||||
src[j] != '\t' && src[j] != '\n';
|
||||
j++)
|
||||
ifname[j] = src[j];
|
||||
ifname[j] = '\0';
|
||||
|
||||
|
|
@ -605,11 +594,11 @@ static int fib_route_ret(struct kretprobe_instance *ri,
|
|||
}
|
||||
|
||||
static struct kretprobe fib_route_krp = {
|
||||
.handler = fib_route_ret,
|
||||
.entry_handler = fib_route_entry,
|
||||
.data_size = sizeof(struct fib_route_data),
|
||||
.maxactive = 20,
|
||||
.kp.symbol_name = "fib_route_seq_show",
|
||||
.handler = fib_route_ret,
|
||||
.entry_handler = fib_route_entry,
|
||||
.data_size = sizeof(struct fib_route_data),
|
||||
.maxactive = 20,
|
||||
.kp.symbol_name = "fib_route_seq_show",
|
||||
};
|
||||
|
||||
/* ================================================================== */
|
||||
|
|
@ -625,12 +614,12 @@ struct kretprobe_reg {
|
|||
};
|
||||
|
||||
static struct kretprobe_reg probes[] = {
|
||||
{ &dev_ioctl_krp, "dev_ioctl", false },
|
||||
{ &dev_ifconf_krp, "dev_ifconf", false },
|
||||
{ &rtnl_fill_krp, "rtnl_fill_ifinfo", false },
|
||||
{ &inet6_fill_krp, "inet6_fill_ifaddr", false },
|
||||
{ &inet_fill_krp, "inet_fill_ifaddr", false },
|
||||
{ &fib_route_krp, "fib_route_seq_show", false },
|
||||
{ &dev_ioctl_krp, "dev_ioctl", false },
|
||||
{ &dev_ifconf_krp, "dev_ifconf", false },
|
||||
{ &rtnl_fill_krp, "rtnl_fill_ifinfo", false },
|
||||
{ &inet6_fill_krp, "inet6_fill_ifaddr", false },
|
||||
{ &inet_fill_krp, "inet_fill_ifaddr", false },
|
||||
{ &fib_route_krp, "fib_route_seq_show", false },
|
||||
};
|
||||
|
||||
static int __init vpnhide_init(void)
|
||||
|
|
@ -656,13 +645,13 @@ static int __init vpnhide_init(void)
|
|||
}
|
||||
if (ok < ARRAY_SIZE(probes))
|
||||
pr_warn(MODNAME ": only %d/%zu kretprobes registered — "
|
||||
"some detection paths are not covered\n",
|
||||
"some detection paths are not covered\n",
|
||||
ok, ARRAY_SIZE(probes));
|
||||
|
||||
/* 0600: root-only read/write. UIDs are written here by service.sh
|
||||
* and WebUI (both root). Apps must not see the target list. */
|
||||
targets_entry = proc_create("vpnhide_targets", 0600, NULL,
|
||||
&targets_proc_ops);
|
||||
targets_entry =
|
||||
proc_create("vpnhide_targets", 0600, NULL, &targets_proc_ops);
|
||||
|
||||
pr_info(MODNAME ": loaded — write UIDs to /proc/vpnhide_targets\n");
|
||||
return 0;
|
||||
|
|
@ -679,7 +668,7 @@ static void __exit vpnhide_exit(void)
|
|||
if (probes[i].registered) {
|
||||
unregister_kretprobe(probes[i].krp);
|
||||
pr_info(MODNAME ": kretprobe(%s) unregistered "
|
||||
"(missed %d)\n",
|
||||
"(missed %d)\n",
|
||||
probes[i].name, probes[i].krp->nmissed);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,16 +34,16 @@ import java.util.concurrent.atomic.AtomicBoolean
|
|||
* Only "System Framework" needs to be in LSPosed scope.
|
||||
*/
|
||||
class HookEntry : IXposedHookLoadPackage {
|
||||
|
||||
private val hookInstalled = AtomicBoolean(false)
|
||||
|
||||
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
|
||||
// Only hook system_server. handleLoadPackage fires multiple times
|
||||
// in system_server (once per hosted package / APEX), so we use
|
||||
// compareAndSet to install hooks exactly once.
|
||||
val inSystemServer = hookInstalled.get() ||
|
||||
lpparam.processName == "android" ||
|
||||
android.os.Process.myUid() == 1000
|
||||
val inSystemServer =
|
||||
hookInstalled.get() ||
|
||||
lpparam.processName == "android" ||
|
||||
android.os.Process.myUid() == 1000
|
||||
|
||||
if (!inSystemServer) return
|
||||
|
||||
|
|
@ -53,7 +53,10 @@ class HookEntry : IXposedHookLoadPackage {
|
|||
}
|
||||
}
|
||||
|
||||
private inline fun tryHook(name: String, block: () -> Unit) {
|
||||
private inline fun tryHook(
|
||||
name: String,
|
||||
block: () -> Unit,
|
||||
) {
|
||||
try {
|
||||
block()
|
||||
} catch (t: Throwable) {
|
||||
|
|
@ -85,6 +88,7 @@ class HookEntry : IXposedHookLoadPackage {
|
|||
// ==================================================================
|
||||
|
||||
@Volatile private var systemServerTargetUids: Set<Int>? = null
|
||||
|
||||
@Volatile private var targetUidsFileObserver: android.os.FileObserver? = null
|
||||
private val uidLock = Any()
|
||||
|
||||
|
|
@ -135,7 +139,7 @@ class HookEntry : IXposedHookLoadPackage {
|
|||
tryHook("NC.writeToParcel") { hookNCWriteToParcel() }
|
||||
tryHook("NI.writeToParcel") { hookNIWriteToParcel() }
|
||||
tryHook("LP.writeToParcel") { hookLPWriteToParcel() }
|
||||
tryHook("FileObserver") { watchTargetUidsFile() }
|
||||
tryHook("FileObserver") { watchTargetUidsFile() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -146,17 +150,21 @@ class HookEntry : IXposedHookLoadPackage {
|
|||
private fun watchTargetUidsFile() {
|
||||
val dir = "/data/system"
|
||||
val filename = "vpnhide_uids.txt"
|
||||
val observer = object : android.os.FileObserver(
|
||||
File(dir),
|
||||
CREATE or CLOSE_WRITE or MOVED_TO or MODIFY
|
||||
) {
|
||||
override fun onEvent(event: Int, path: String?) {
|
||||
if (path == filename) {
|
||||
XposedBridge.log("VpnHide: $filename changed (event=$event), invalidating UID cache")
|
||||
systemServerTargetUids = null
|
||||
val observer =
|
||||
object : android.os.FileObserver(
|
||||
File(dir),
|
||||
CREATE or CLOSE_WRITE or MOVED_TO or MODIFY,
|
||||
) {
|
||||
override fun onEvent(
|
||||
event: Int,
|
||||
path: String?,
|
||||
) {
|
||||
if (path == filename) {
|
||||
XposedBridge.log("VpnHide: $filename changed (event=$event), invalidating UID cache")
|
||||
systemServerTargetUids = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
targetUidsFileObserver = observer
|
||||
observer.startWatching()
|
||||
XposedBridge.log("VpnHide: watching $dir for $filename changes (inotify)")
|
||||
|
|
@ -170,8 +178,10 @@ class HookEntry : IXposedHookLoadPackage {
|
|||
*/
|
||||
private fun hookNCWriteToParcel() {
|
||||
XposedHelpers.findAndHookMethod(
|
||||
NetworkCapabilities::class.java, "writeToParcel",
|
||||
android.os.Parcel::class.java, Integer.TYPE,
|
||||
NetworkCapabilities::class.java,
|
||||
"writeToParcel",
|
||||
android.os.Parcel::class.java,
|
||||
Integer.TYPE,
|
||||
object : XC_MethodHook() {
|
||||
private val savedTransport = ThreadLocal<Long>()
|
||||
private val savedCaps = ThreadLocal<Long>()
|
||||
|
|
@ -188,7 +198,12 @@ class HookEntry : IXposedHookLoadPackage {
|
|||
|
||||
// Read all original values before mutating anything
|
||||
val caps = XposedHelpers.getLongField(nc, "mNetworkCapabilities")
|
||||
val ti = try { XposedHelpers.getObjectField(nc, "mTransportInfo") } catch (_: Throwable) { null }
|
||||
val ti =
|
||||
try {
|
||||
XposedHelpers.getObjectField(nc, "mTransportInfo")
|
||||
} catch (_: Throwable) {
|
||||
null
|
||||
}
|
||||
|
||||
// Mutate — if any step fails, restore everything
|
||||
try {
|
||||
|
|
@ -226,9 +241,10 @@ class HookEntry : IXposedHookLoadPackage {
|
|||
XposedHelpers.setLongField(nc, "mTransportTypes", origTransport)
|
||||
if (origCaps != null) XposedHelpers.setLongField(nc, "mNetworkCapabilities", origCaps)
|
||||
XposedHelpers.setObjectField(nc, "mTransportInfo", origTi)
|
||||
} catch (_: Throwable) {}
|
||||
} catch (_: Throwable) {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
XposedBridge.log("VpnHide: hooked NetworkCapabilities.writeToParcel")
|
||||
}
|
||||
|
|
@ -241,8 +257,10 @@ class HookEntry : IXposedHookLoadPackage {
|
|||
*/
|
||||
private fun hookNIWriteToParcel() {
|
||||
XposedHelpers.findAndHookMethod(
|
||||
NetworkInfo::class.java, "writeToParcel",
|
||||
android.os.Parcel::class.java, Integer.TYPE,
|
||||
NetworkInfo::class.java,
|
||||
"writeToParcel",
|
||||
android.os.Parcel::class.java,
|
||||
Integer.TYPE,
|
||||
object : XC_MethodHook() {
|
||||
private val savedType = ThreadLocal<Int>()
|
||||
|
||||
|
|
@ -265,9 +283,10 @@ class HookEntry : IXposedHookLoadPackage {
|
|||
savedType.remove()
|
||||
try {
|
||||
XposedHelpers.setIntField(param.thisObject, "mNetworkType", origType)
|
||||
} catch (_: Throwable) {}
|
||||
} catch (_: Throwable) {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
XposedBridge.log("VpnHide: hooked NetworkInfo.writeToParcel")
|
||||
}
|
||||
|
|
@ -280,8 +299,10 @@ class HookEntry : IXposedHookLoadPackage {
|
|||
*/
|
||||
private fun hookLPWriteToParcel() {
|
||||
XposedHelpers.findAndHookMethod(
|
||||
LinkProperties::class.java, "writeToParcel",
|
||||
android.os.Parcel::class.java, Integer.TYPE,
|
||||
LinkProperties::class.java,
|
||||
"writeToParcel",
|
||||
android.os.Parcel::class.java,
|
||||
Integer.TYPE,
|
||||
object : XC_MethodHook() {
|
||||
private val savedIfname = ThreadLocal<String>()
|
||||
|
||||
|
|
@ -304,9 +325,10 @@ class HookEntry : IXposedHookLoadPackage {
|
|||
savedIfname.remove()
|
||||
try {
|
||||
XposedHelpers.setObjectField(param.thisObject, "mIfaceName", origIfname)
|
||||
} catch (_: Throwable) {}
|
||||
} catch (_: Throwable) {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
XposedBridge.log("VpnHide: hooked LinkProperties.writeToParcel")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@ class MainActivity : ComponentActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun suExec(cmd: String): Pair<Int, String> {
|
||||
return try {
|
||||
private fun suExec(cmd: String): Pair<Int, String> =
|
||||
try {
|
||||
val proc = Runtime.getRuntime().exec(arrayOf("su", "-c", cmd))
|
||||
try {
|
||||
// Drain stderr in the background to prevent the process from
|
||||
|
|
@ -73,21 +73,20 @@ private fun suExec(cmd: String): Pair<Int, String> {
|
|||
Log.e(TAG, "su exec failed: ${e.message}")
|
||||
-1 to ""
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun suExecAsync(cmd: String): Pair<Int, String> =
|
||||
withContext(Dispatchers.IO) { suExec(cmd) }
|
||||
private suspend fun suExecAsync(cmd: String): Pair<Int, String> = withContext(Dispatchers.IO) { suExec(cmd) }
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun VpnHideApp() {
|
||||
val darkTheme = isSystemInDarkTheme()
|
||||
val colorScheme = if (android.os.Build.VERSION.SDK_INT >= 31) {
|
||||
val context = LocalContext.current
|
||||
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
|
||||
} else {
|
||||
if (darkTheme) darkColorScheme() else lightColorScheme()
|
||||
}
|
||||
val colorScheme =
|
||||
if (android.os.Build.VERSION.SDK_INT >= 31) {
|
||||
val context = LocalContext.current
|
||||
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
|
||||
} else {
|
||||
if (darkTheme) darkColorScheme() else lightColorScheme()
|
||||
}
|
||||
|
||||
MaterialTheme(colorScheme = colorScheme) {
|
||||
val context = LocalContext.current
|
||||
|
|
@ -111,44 +110,56 @@ fun VpnHideApp() {
|
|||
|
||||
LaunchedEffect(Unit) {
|
||||
withContext(Dispatchers.IO) {
|
||||
val (_, targetsRaw) = suExec(
|
||||
"cat $KMOD_TARGETS 2>/dev/null || cat $ZYGISK_TARGETS 2>/dev/null || true"
|
||||
)
|
||||
val selected = targetsRaw.lines()
|
||||
.map { it.trim() }
|
||||
.filter { it.isNotEmpty() && !it.startsWith("#") }
|
||||
.toSet()
|
||||
val (_, targetsRaw) =
|
||||
suExec(
|
||||
"cat $KMOD_TARGETS 2>/dev/null || cat $ZYGISK_TARGETS 2>/dev/null || true",
|
||||
)
|
||||
val selected =
|
||||
targetsRaw
|
||||
.lines()
|
||||
.map { it.trim() }
|
||||
.filter { it.isNotEmpty() && !it.startsWith("#") }
|
||||
.toSet()
|
||||
|
||||
val installedApps = pm.getInstalledApplications(PackageManager.GET_META_DATA)
|
||||
val entries = installedApps.map { info ->
|
||||
val label = try {
|
||||
pm.getApplicationLabel(info).toString()
|
||||
} catch (_: Exception) { info.packageName }
|
||||
val icon = try {
|
||||
pm.getApplicationIcon(info)
|
||||
} catch (_: Exception) { null }
|
||||
val isSystem = (info.flags and ApplicationInfo.FLAG_SYSTEM) != 0
|
||||
AppEntry(
|
||||
packageName = info.packageName,
|
||||
label = label,
|
||||
icon = icon,
|
||||
isSystem = isSystem,
|
||||
selected = info.packageName in selected,
|
||||
)
|
||||
}.sortedWith(compareByDescending<AppEntry> { it.selected }.thenBy { it.label.lowercase() })
|
||||
val entries =
|
||||
installedApps
|
||||
.map { info ->
|
||||
val label =
|
||||
try {
|
||||
pm.getApplicationLabel(info).toString()
|
||||
} catch (_: Exception) {
|
||||
info.packageName
|
||||
}
|
||||
val icon =
|
||||
try {
|
||||
pm.getApplicationIcon(info)
|
||||
} catch (_: Exception) {
|
||||
null
|
||||
}
|
||||
val isSystem = (info.flags and ApplicationInfo.FLAG_SYSTEM) != 0
|
||||
AppEntry(
|
||||
packageName = info.packageName,
|
||||
label = label,
|
||||
icon = icon,
|
||||
isSystem = isSystem,
|
||||
selected = info.packageName in selected,
|
||||
)
|
||||
}.sortedWith(compareByDescending<AppEntry> { it.selected }.thenBy { it.label.lowercase() })
|
||||
|
||||
allApps = entries
|
||||
loading = false
|
||||
}
|
||||
}
|
||||
|
||||
val filteredApps = remember(allApps, searchQuery, showSystem) {
|
||||
val q = searchQuery.trim().lowercase()
|
||||
allApps.filter { app ->
|
||||
(showSystem || !app.isSystem || app.selected) &&
|
||||
(q.isEmpty() || app.label.lowercase().contains(q) || app.packageName.lowercase().contains(q))
|
||||
val filteredApps =
|
||||
remember(allApps, searchQuery, showSystem) {
|
||||
val q = searchQuery.trim().lowercase()
|
||||
allApps.filter { app ->
|
||||
(showSystem || !app.isSystem || app.selected) &&
|
||||
(q.isEmpty() || app.label.lowercase().contains(q) || app.packageName.lowercase().contains(q))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val selectedCount = remember(allApps) { allApps.count { it.selected } }
|
||||
|
||||
|
|
@ -157,19 +168,21 @@ fun VpnHideApp() {
|
|||
topBar = {
|
||||
TopAppBar(
|
||||
title = { Text("VPN Hide") },
|
||||
colors = TopAppBarDefaults.topAppBarColors(
|
||||
containerColor = MaterialTheme.colorScheme.primaryContainer,
|
||||
titleContentColor = MaterialTheme.colorScheme.onPrimaryContainer,
|
||||
)
|
||||
colors =
|
||||
TopAppBarDefaults.topAppBarColors(
|
||||
containerColor = MaterialTheme.colorScheme.primaryContainer,
|
||||
titleContentColor = MaterialTheme.colorScheme.onPrimaryContainer,
|
||||
),
|
||||
)
|
||||
},
|
||||
bottomBar = {
|
||||
Surface(tonalElevation = 3.dp) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.navigationBarsPadding()
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.navigationBarsPadding()
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
|
|
@ -189,18 +202,20 @@ fun VpnHideApp() {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
) { innerPadding ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(innerPadding)
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.padding(innerPadding),
|
||||
) {
|
||||
// Search + system toggle
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
OutlinedTextField(
|
||||
|
|
@ -231,11 +246,12 @@ fun VpnHideApp() {
|
|||
AppRow(
|
||||
app = app,
|
||||
onToggle = {
|
||||
allApps = allApps.map {
|
||||
if (it.packageName == app.packageName) it.copy(selected = !it.selected) else it
|
||||
}
|
||||
allApps =
|
||||
allApps.map {
|
||||
if (it.packageName == app.packageName) it.copy(selected = !it.selected) else it
|
||||
}
|
||||
dirty = true
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -247,9 +263,10 @@ fun VpnHideApp() {
|
|||
if (saving) {
|
||||
LaunchedEffect(Unit) {
|
||||
val selected = allApps.filter { it.selected }.map { it.packageName }.sorted()
|
||||
val body = "# Managed by VPN Hide app\n" +
|
||||
selected.joinToString("\n") +
|
||||
if (selected.isNotEmpty()) "\n" else ""
|
||||
val body =
|
||||
"# Managed by VPN Hide app\n" +
|
||||
selected.joinToString("\n") +
|
||||
if (selected.isNotEmpty()) "\n" else ""
|
||||
|
||||
try {
|
||||
val (exitCode, _) = suExecAsync(buildSaveCommand(body, selected))
|
||||
|
|
@ -269,7 +286,10 @@ fun VpnHideApp() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun buildSaveCommand(body: String, selectedPackages: List<String>): String {
|
||||
private fun buildSaveCommand(
|
||||
body: String,
|
||||
selectedPackages: List<String>,
|
||||
): String {
|
||||
val b64 = android.util.Base64.encodeToString(body.toByteArray(), android.util.Base64.NO_WRAP)
|
||||
|
||||
val parts = mutableListOf<String>()
|
||||
|
|
@ -287,21 +307,22 @@ private fun buildSaveCommand(body: String, selectedPackages: List<String>): Stri
|
|||
// Uses the same approach as kmod/service.sh — real newlines in $UIDS via heredoc-style
|
||||
// accumulation, not printf \n escapes.
|
||||
if (selectedPackages.isNotEmpty()) {
|
||||
val uidResolution = buildString {
|
||||
append("ALL_PKGS=\"\$(pm list packages -U 2>/dev/null)\"")
|
||||
append("; UIDS=\"\"")
|
||||
for (pkg in selectedPackages) {
|
||||
append("; U=\$(echo \"\$ALL_PKGS\" | grep '^package:$pkg ' | sed 's/.*uid://')")
|
||||
append("; if [ -n \"\$U\" ]; then if [ -z \"\$UIDS\" ]; then UIDS=\"\$U\"; else UIDS=\"\$UIDS")
|
||||
// Real newline in the shell string — not \n escape
|
||||
append("\n")
|
||||
append("\$U\"; fi; fi")
|
||||
val uidResolution =
|
||||
buildString {
|
||||
append("ALL_PKGS=\"\$(pm list packages -U 2>/dev/null)\"")
|
||||
append("; UIDS=\"\"")
|
||||
for (pkg in selectedPackages) {
|
||||
append("; U=\$(echo \"\$ALL_PKGS\" | grep '^package:$pkg ' | sed 's/.*uid://')")
|
||||
append("; if [ -n \"\$U\" ]; then if [ -z \"\$UIDS\" ]; then UIDS=\"\$U\"; else UIDS=\"\$UIDS")
|
||||
// Real newline in the shell string — not \n escape
|
||||
append("\n")
|
||||
append("\$U\"; fi; fi")
|
||||
}
|
||||
append("; if [ -n \"\$UIDS\" ]; then echo \"\$UIDS\" > $PROC_TARGETS 2>/dev/null; echo \"\$UIDS\" > $SS_UIDS_FILE")
|
||||
append("; else echo > $PROC_TARGETS 2>/dev/null; echo > $SS_UIDS_FILE; fi")
|
||||
append("; chmod 644 $SS_UIDS_FILE 2>/dev/null")
|
||||
append("; chcon u:object_r:system_data_file:s0 $SS_UIDS_FILE 2>/dev/null")
|
||||
}
|
||||
append("; if [ -n \"\$UIDS\" ]; then echo \"\$UIDS\" > $PROC_TARGETS 2>/dev/null; echo \"\$UIDS\" > $SS_UIDS_FILE")
|
||||
append("; else echo > $PROC_TARGETS 2>/dev/null; echo > $SS_UIDS_FILE; fi")
|
||||
append("; chmod 644 $SS_UIDS_FILE 2>/dev/null")
|
||||
append("; chcon u:object_r:system_data_file:s0 $SS_UIDS_FILE 2>/dev/null")
|
||||
}
|
||||
parts += uidResolution
|
||||
} else {
|
||||
// No targets — clear the UIDs files. echo -n writes a zero-length
|
||||
|
|
@ -314,12 +335,16 @@ private fun buildSaveCommand(body: String, selectedPackages: List<String>): Stri
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun AppRow(app: AppEntry, onToggle: () -> Unit) {
|
||||
private fun AppRow(
|
||||
app: AppEntry,
|
||||
onToggle: () -> Unit,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = onToggle)
|
||||
.padding(horizontal = 16.dp, vertical = 10.dp),
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = onToggle)
|
||||
.padding(horizontal = 16.dp, vertical = 10.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Checkbox(
|
||||
|
|
|
|||
|
|
@ -42,20 +42,21 @@ private val VPN_PREFIXES = listOf("tun", "wg", "ppp", "tap", "ipsec", "xfrm")
|
|||
|
||||
data class CheckResult(
|
||||
val name: String,
|
||||
val passed: Boolean?, // null = informational
|
||||
val detail: String
|
||||
val passed: Boolean?, // null = informational
|
||||
val detail: String,
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun VpnHideTestApp() {
|
||||
val darkTheme = isSystemInDarkTheme()
|
||||
val colorScheme = if (android.os.Build.VERSION.SDK_INT >= 31) {
|
||||
val context = LocalContext.current
|
||||
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
|
||||
} else {
|
||||
if (darkTheme) darkColorScheme() else lightColorScheme()
|
||||
}
|
||||
val colorScheme =
|
||||
if (android.os.Build.VERSION.SDK_INT >= 31) {
|
||||
val context = LocalContext.current
|
||||
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
|
||||
} else {
|
||||
if (darkTheme) darkColorScheme() else lightColorScheme()
|
||||
}
|
||||
|
||||
MaterialTheme(colorScheme = colorScheme) {
|
||||
val context = LocalContext.current
|
||||
|
|
@ -75,18 +76,20 @@ fun VpnHideTestApp() {
|
|||
topBar = {
|
||||
TopAppBar(
|
||||
title = { Text("VPNHide Diagnostics") },
|
||||
colors = TopAppBarDefaults.topAppBarColors(
|
||||
containerColor = MaterialTheme.colorScheme.primaryContainer,
|
||||
titleContentColor = MaterialTheme.colorScheme.onPrimaryContainer,
|
||||
)
|
||||
colors =
|
||||
TopAppBarDefaults.topAppBarColors(
|
||||
containerColor = MaterialTheme.colorScheme.primaryContainer,
|
||||
titleContentColor = MaterialTheme.colorScheme.onPrimaryContainer,
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
) { innerPadding ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(innerPadding)
|
||||
.padding(horizontal = 16.dp)
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.padding(innerPadding)
|
||||
.padding(horizontal = 16.dp),
|
||||
) {
|
||||
Spacer(Modifier.height(8.dp))
|
||||
|
||||
|
|
@ -94,7 +97,7 @@ fun VpnHideTestApp() {
|
|||
text = summary,
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.padding(bottom = 8.dp)
|
||||
modifier = Modifier.padding(bottom = 8.dp),
|
||||
)
|
||||
|
||||
Button(
|
||||
|
|
@ -106,7 +109,7 @@ fun VpnHideTestApp() {
|
|||
val passed = scored.count { it.passed == true }
|
||||
summary = "$passed/${scored.size} passed"
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
Text("Run All Checks")
|
||||
}
|
||||
|
|
@ -114,10 +117,11 @@ fun VpnHideTestApp() {
|
|||
Spacer(Modifier.height(8.dp))
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState()),
|
||||
verticalArrangement = Arrangement.spacedBy(6.dp)
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState()),
|
||||
verticalArrangement = Arrangement.spacedBy(6.dp),
|
||||
) {
|
||||
for (r in results) {
|
||||
CheckCard(r)
|
||||
|
|
@ -131,48 +135,58 @@ fun VpnHideTestApp() {
|
|||
|
||||
@Composable
|
||||
fun CheckCard(r: CheckResult) {
|
||||
val containerColor = when (r.passed) {
|
||||
true -> Color(0xFFE8F5E9)
|
||||
false -> Color(0xFFFFEBEE)
|
||||
null -> MaterialTheme.colorScheme.surfaceVariant
|
||||
}
|
||||
val darkTheme = isSystemInDarkTheme()
|
||||
val actualColor = if (darkTheme) {
|
||||
val containerColor =
|
||||
when (r.passed) {
|
||||
true -> Color(0xFF1B5E20).copy(alpha = 0.3f)
|
||||
false -> Color(0xFFB71C1C).copy(alpha = 0.3f)
|
||||
true -> Color(0xFFE8F5E9)
|
||||
false -> Color(0xFFFFEBEE)
|
||||
null -> MaterialTheme.colorScheme.surfaceVariant
|
||||
}
|
||||
} else containerColor
|
||||
val darkTheme = isSystemInDarkTheme()
|
||||
val actualColor =
|
||||
if (darkTheme) {
|
||||
when (r.passed) {
|
||||
true -> Color(0xFF1B5E20).copy(alpha = 0.3f)
|
||||
false -> Color(0xFFB71C1C).copy(alpha = 0.3f)
|
||||
null -> MaterialTheme.colorScheme.surfaceVariant
|
||||
}
|
||||
} else {
|
||||
containerColor
|
||||
}
|
||||
|
||||
val badgeColor = when (r.passed) {
|
||||
true -> Color(0xFF2E7D32)
|
||||
false -> Color(0xFFC62828)
|
||||
null -> MaterialTheme.colorScheme.onSurfaceVariant
|
||||
}
|
||||
val badgeColor =
|
||||
when (r.passed) {
|
||||
true -> Color(0xFF2E7D32)
|
||||
false -> Color(0xFFC62828)
|
||||
null -> MaterialTheme.colorScheme.onSurfaceVariant
|
||||
}
|
||||
|
||||
Card(
|
||||
shape = RoundedCornerShape(8.dp),
|
||||
colors = CardDefaults.cardColors(containerColor = actualColor),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
Column(modifier = Modifier.padding(12.dp)) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = r.name,
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.weight(1f)
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
Text(
|
||||
text = when (r.passed) { true -> "PASS"; false -> "FAIL"; null -> "INFO" },
|
||||
text =
|
||||
when (r.passed) {
|
||||
true -> "PASS"
|
||||
false -> "FAIL"
|
||||
null -> "INFO"
|
||||
},
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 13.sp,
|
||||
color = badgeColor
|
||||
color = badgeColor,
|
||||
)
|
||||
}
|
||||
Spacer(Modifier.height(4.dp))
|
||||
|
|
@ -180,7 +194,7 @@ fun CheckCard(r: CheckResult) {
|
|||
text = r.detail,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
fontFamily = FontFamily.Monospace,
|
||||
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.8f)
|
||||
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.8f),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -230,8 +244,11 @@ private fun runAllChecks(cm: ConnectivityManager): List<CheckResult> {
|
|||
return results
|
||||
}
|
||||
|
||||
private fun nativeCheck(name: String, block: () -> String): CheckResult {
|
||||
return try {
|
||||
private fun nativeCheck(
|
||||
name: String,
|
||||
block: () -> String,
|
||||
): CheckResult =
|
||||
try {
|
||||
val raw = block()
|
||||
val passed = raw.startsWith("PASS")
|
||||
Log.i(TAG, "[$name] ${if (passed) "PASS" else "FAIL"}: $raw")
|
||||
|
|
@ -241,23 +258,24 @@ private fun nativeCheck(name: String, block: () -> String): CheckResult {
|
|||
Log.e(TAG, "[$name] $detail", e)
|
||||
CheckResult(name, false, detail)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkHasTransportVpn(cm: ConnectivityManager): CheckResult {
|
||||
val name = "7. hasTransport(VPN)"
|
||||
Log.i(TAG, "=== CHECK: $name ===")
|
||||
val net = cm.activeNetwork
|
||||
if (net == null) return CheckResult(name, true, "PASS: no active network").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val caps = cm.getNetworkCapabilities(net)
|
||||
?: return CheckResult(name, true, "PASS: no capabilities").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val caps =
|
||||
cm.getNetworkCapabilities(net)
|
||||
?: return CheckResult(name, true, "PASS: no capabilities").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val hasVpn = caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)
|
||||
val hasWifi = caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
|
||||
val hasCellular = caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
|
||||
val detail = if (!hasVpn) {
|
||||
"PASS: hasTransport(VPN)=false, WIFI=$hasWifi, CELLULAR=$hasCellular"
|
||||
} else {
|
||||
"FAIL: hasTransport(VPN)=true, WIFI=$hasWifi, CELLULAR=$hasCellular"
|
||||
}
|
||||
val detail =
|
||||
if (!hasVpn) {
|
||||
"PASS: hasTransport(VPN)=false, WIFI=$hasWifi, CELLULAR=$hasCellular"
|
||||
} else {
|
||||
"FAIL: hasTransport(VPN)=true, WIFI=$hasWifi, CELLULAR=$hasCellular"
|
||||
}
|
||||
Log.i(TAG, "[$name] $detail")
|
||||
Log.i(TAG, "[$name] caps.toString(): $caps")
|
||||
return CheckResult(name, !hasVpn, detail)
|
||||
|
|
@ -266,10 +284,12 @@ private fun checkHasTransportVpn(cm: ConnectivityManager): CheckResult {
|
|||
private fun checkHasCapabilityNotVpn(cm: ConnectivityManager): CheckResult {
|
||||
val name = "8. hasCapability(NOT_VPN)"
|
||||
Log.i(TAG, "=== CHECK: $name ===")
|
||||
val net = cm.activeNetwork
|
||||
?: return CheckResult(name, true, "PASS: no active network").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val caps = cm.getNetworkCapabilities(net)
|
||||
?: return CheckResult(name, true, "PASS: no capabilities").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val net =
|
||||
cm.activeNetwork
|
||||
?: return CheckResult(name, true, "PASS: no active network").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val caps =
|
||||
cm.getNetworkCapabilities(net)
|
||||
?: return CheckResult(name, true, "PASS: no capabilities").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val notVpn = caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
|
||||
val detail = if (notVpn) "PASS: NOT_VPN capability present" else "FAIL: NOT_VPN capability MISSING"
|
||||
Log.i(TAG, "[$name] $detail")
|
||||
|
|
@ -279,10 +299,12 @@ private fun checkHasCapabilityNotVpn(cm: ConnectivityManager): CheckResult {
|
|||
private fun checkTransportInfo(cm: ConnectivityManager): CheckResult {
|
||||
val name = "9. getTransportInfo()"
|
||||
Log.i(TAG, "=== CHECK: $name ===")
|
||||
val net = cm.activeNetwork
|
||||
?: return CheckResult(name, true, "PASS: no active network").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val caps = cm.getNetworkCapabilities(net)
|
||||
?: return CheckResult(name, true, "PASS: no capabilities").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val net =
|
||||
cm.activeNetwork
|
||||
?: return CheckResult(name, true, "PASS: no active network").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val caps =
|
||||
cm.getNetworkCapabilities(net)
|
||||
?: return CheckResult(name, true, "PASS: no capabilities").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val info = caps.transportInfo
|
||||
val className = info?.javaClass?.name ?: "null"
|
||||
Log.i(TAG, "[$name] transportInfo class=$className, value=$info")
|
||||
|
|
@ -296,8 +318,9 @@ private fun checkNetworkInterfaceEnum(): CheckResult {
|
|||
val name = "10. NetworkInterface enum"
|
||||
Log.i(TAG, "=== CHECK: $name ===")
|
||||
return try {
|
||||
val ifaces = NetworkInterface.getNetworkInterfaces()
|
||||
?: return CheckResult(name, true, "PASS: returned null").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val ifaces =
|
||||
NetworkInterface.getNetworkInterfaces()
|
||||
?: return CheckResult(name, true, "PASS: returned null").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val allNames = mutableListOf<String>()
|
||||
val vpnNames = mutableListOf<String>()
|
||||
for (iface in ifaces) {
|
||||
|
|
@ -305,11 +328,12 @@ private fun checkNetworkInterfaceEnum(): CheckResult {
|
|||
Log.i(TAG, "[$name] ${iface.name} up=${iface.isUp} loopback=${iface.isLoopback} p2p=${iface.isPointToPoint}")
|
||||
if (VPN_PREFIXES.any { iface.name.startsWith(it) }) vpnNames.add(iface.name)
|
||||
}
|
||||
val detail = if (vpnNames.isEmpty()) {
|
||||
"PASS: ${allNames.size} ifaces [${allNames.joinToString()}], no VPN"
|
||||
} else {
|
||||
"FAIL: VPN [${vpnNames.joinToString()}] in [${allNames.joinToString()}]"
|
||||
}
|
||||
val detail =
|
||||
if (vpnNames.isEmpty()) {
|
||||
"PASS: ${allNames.size} ifaces [${allNames.joinToString()}], no VPN"
|
||||
} else {
|
||||
"FAIL: VPN [${vpnNames.joinToString()}] in [${allNames.joinToString()}]"
|
||||
}
|
||||
Log.i(TAG, "[$name] $detail")
|
||||
CheckResult(name, vpnNames.isEmpty(), detail)
|
||||
} catch (e: Exception) {
|
||||
|
|
@ -341,11 +365,12 @@ private fun checkAllNetworksVpn(cm: ConnectivityManager): CheckResult {
|
|||
Log.i(TAG, "[$name] Network $net: [${transports.joinToString()}] VPN=$hasVpn")
|
||||
if (hasVpn) vpnNetworks.add(net.toString())
|
||||
}
|
||||
val detail = if (vpnNetworks.isEmpty()) {
|
||||
"PASS: ${networks.size} networks, none have TRANSPORT_VPN"
|
||||
} else {
|
||||
"FAIL: ${vpnNetworks.size} network(s) with TRANSPORT_VPN: [${vpnNetworks.joinToString()}]"
|
||||
}
|
||||
val detail =
|
||||
if (vpnNetworks.isEmpty()) {
|
||||
"PASS: ${networks.size} networks, none have TRANSPORT_VPN"
|
||||
} else {
|
||||
"FAIL: ${vpnNetworks.size} network(s) with TRANSPORT_VPN: [${vpnNetworks.joinToString()}]"
|
||||
}
|
||||
Log.i(TAG, "[$name] $detail")
|
||||
return CheckResult(name, vpnNetworks.isEmpty(), detail)
|
||||
}
|
||||
|
|
@ -353,10 +378,12 @@ private fun checkAllNetworksVpn(cm: ConnectivityManager): CheckResult {
|
|||
private fun checkActiveNetworkVpn(cm: ConnectivityManager): CheckResult {
|
||||
val name = "11. ActiveNetwork transports"
|
||||
Log.i(TAG, "=== CHECK: $name ===")
|
||||
val net = cm.activeNetwork
|
||||
?: return CheckResult(name, true, "PASS: no active network").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val caps = cm.getNetworkCapabilities(net)
|
||||
?: return CheckResult(name, true, "PASS: no capabilities").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val net =
|
||||
cm.activeNetwork
|
||||
?: return CheckResult(name, true, "PASS: no active network").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val caps =
|
||||
cm.getNetworkCapabilities(net)
|
||||
?: return CheckResult(name, true, "PASS: no capabilities").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val transports = mutableListOf<String>()
|
||||
mapOf(
|
||||
NetworkCapabilities.TRANSPORT_CELLULAR to "CELLULAR",
|
||||
|
|
@ -367,11 +394,12 @@ private fun checkActiveNetworkVpn(cm: ConnectivityManager): CheckResult {
|
|||
NetworkCapabilities.TRANSPORT_WIFI_AWARE to "WIFI_AWARE",
|
||||
).forEach { (id, label) -> if (caps.hasTransport(id)) transports.add(label) }
|
||||
val hasVpn = caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)
|
||||
val detail = if (!hasVpn) {
|
||||
"PASS: transports=[${transports.joinToString()}], no VPN"
|
||||
} else {
|
||||
"FAIL: transports include VPN: [${transports.joinToString()}]"
|
||||
}
|
||||
val detail =
|
||||
if (!hasVpn) {
|
||||
"PASS: transports=[${transports.joinToString()}], no VPN"
|
||||
} else {
|
||||
"FAIL: transports include VPN: [${transports.joinToString()}]"
|
||||
}
|
||||
Log.i(TAG, "[$name] $detail")
|
||||
return CheckResult(name, !hasVpn, detail)
|
||||
}
|
||||
|
|
@ -379,10 +407,12 @@ private fun checkActiveNetworkVpn(cm: ConnectivityManager): CheckResult {
|
|||
private fun checkLinkPropertiesIfname(cm: ConnectivityManager): CheckResult {
|
||||
val name = "12. LinkProperties ifname"
|
||||
Log.i(TAG, "=== CHECK: $name ===")
|
||||
val net = cm.activeNetwork
|
||||
?: return CheckResult(name, true, "PASS: no active network").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val lp = cm.getLinkProperties(net)
|
||||
?: return CheckResult(name, true, "PASS: no link properties").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val net =
|
||||
cm.activeNetwork
|
||||
?: return CheckResult(name, true, "PASS: no active network").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val lp =
|
||||
cm.getLinkProperties(net)
|
||||
?: return CheckResult(name, true, "PASS: no link properties").also { Log.i(TAG, "[$name] ${it.detail}") }
|
||||
val ifname = lp.interfaceName ?: "(null)"
|
||||
val routes = lp.routes.map { "${it.destination} via ${it.gateway} dev ${it.`interface`}" }
|
||||
val dns = lp.dnsServers.map { it.hostAddress ?: "?" }
|
||||
|
|
@ -391,11 +421,12 @@ private fun checkLinkPropertiesIfname(cm: ConnectivityManager): CheckResult {
|
|||
Log.i(TAG, "[$name] dns=${dns.joinToString(", ")}")
|
||||
Log.i(TAG, "[$name] httpProxy=${lp.httpProxy}")
|
||||
val isVpn = VPN_PREFIXES.any { ifname.startsWith(it) }
|
||||
val detail = if (!isVpn) {
|
||||
"PASS: ifname=$ifname, ${routes.size} routes, dns=[${dns.joinToString()}]"
|
||||
} else {
|
||||
"FAIL: ifname=$ifname is a VPN interface"
|
||||
}
|
||||
val detail =
|
||||
if (!isVpn) {
|
||||
"PASS: ifname=$ifname, ${routes.size} routes, dns=[${dns.joinToString()}]"
|
||||
} else {
|
||||
"FAIL: ifname=$ifname is a VPN interface"
|
||||
}
|
||||
Log.i(TAG, "[$name] $detail")
|
||||
return CheckResult(name, !isVpn, detail)
|
||||
}
|
||||
|
|
@ -409,11 +440,12 @@ private fun checkProxyHost(): CheckResult {
|
|||
val socksPort = System.getProperty("socksProxyPort")
|
||||
Log.i(TAG, "[$name] http=$httpHost:$httpPort, socks=$socksHost:$socksPort")
|
||||
val hasProxy = !httpHost.isNullOrEmpty() || !socksHost.isNullOrEmpty()
|
||||
val detail = if (!hasProxy) {
|
||||
"PASS: no proxy (http=$httpHost, socks=$socksHost)"
|
||||
} else {
|
||||
"FAIL: proxy found — http=$httpHost:$httpPort, socks=$socksHost:$socksPort"
|
||||
}
|
||||
val detail =
|
||||
if (!hasProxy) {
|
||||
"PASS: no proxy (http=$httpHost, socks=$socksHost)"
|
||||
} else {
|
||||
"FAIL: proxy found — http=$httpHost:$httpPort, socks=$socksHost:$socksPort"
|
||||
}
|
||||
Log.i(TAG, "[$name] $detail")
|
||||
return CheckResult(name, !hasProxy, detail)
|
||||
}
|
||||
|
|
@ -432,11 +464,12 @@ private fun checkProcNetRouteJava(): CheckResult {
|
|||
if (VPN_PREFIXES.any { line!!.startsWith(it) }) vpnLines.add(line!!.take(60))
|
||||
}
|
||||
}
|
||||
val detail = if (vpnLines.isEmpty()) {
|
||||
"PASS: ${allLines.size} lines, no VPN entries"
|
||||
} else {
|
||||
"FAIL: ${vpnLines.size} VPN lines:\n${vpnLines.joinToString("\n") { " $it" }}"
|
||||
}
|
||||
val detail =
|
||||
if (vpnLines.isEmpty()) {
|
||||
"PASS: ${allLines.size} lines, no VPN entries"
|
||||
} else {
|
||||
"FAIL: ${vpnLines.size} VPN lines:\n${vpnLines.joinToString("\n") { " $it" }}"
|
||||
}
|
||||
Log.i(TAG, "[$name] $detail")
|
||||
CheckResult(name, vpnLines.isEmpty(), detail)
|
||||
} catch (e: Exception) {
|
||||
|
|
|
|||
|
|
@ -6,18 +6,32 @@ object NativeChecks {
|
|||
}
|
||||
|
||||
external fun checkIoctlSiocgifflags(): String
|
||||
|
||||
external fun checkIoctlSiocgifconf(): String
|
||||
|
||||
external fun checkGetifaddrs(): String
|
||||
|
||||
external fun checkProcNetRoute(): String
|
||||
|
||||
external fun checkProcNetIfInet6(): String
|
||||
|
||||
external fun checkNetlinkGetlink(): String
|
||||
|
||||
external fun checkNetlinkGetroute(): String
|
||||
|
||||
external fun checkProcNetIpv6Route(): String
|
||||
|
||||
external fun checkProcNetTcp(): String
|
||||
|
||||
external fun checkProcNetTcp6(): String
|
||||
|
||||
external fun checkProcNetUdp(): String
|
||||
|
||||
external fun checkProcNetUdp6(): String
|
||||
|
||||
external fun checkProcNetDev(): String
|
||||
|
||||
external fun checkProcNetFibTrie(): String
|
||||
|
||||
external fun checkSysClassNet(): String
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue