18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Operations on the lowpower protocol 68c2ecf20Sopenharmony_ci * Authors: yangyanjun 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci#ifdef CONFIG_LOWPOWER_PROTOCOL 98c2ecf20Sopenharmony_ci#include <linux/types.h> 108c2ecf20Sopenharmony_ci#include <linux/kernel.h> 118c2ecf20Sopenharmony_ci#include <linux/proc_fs.h> 128c2ecf20Sopenharmony_ci#include <linux/printk.h> 138c2ecf20Sopenharmony_ci#include <linux/list.h> 148c2ecf20Sopenharmony_ci#include <linux/rwlock_types.h> 158c2ecf20Sopenharmony_ci#include <linux/net_namespace.h> 168c2ecf20Sopenharmony_ci#include <net/sock.h> 178c2ecf20Sopenharmony_ci#include <net/ip.h> 188c2ecf20Sopenharmony_ci#include <net/tcp.h> 198c2ecf20Sopenharmony_ci#include <net/lowpower_protocol.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistatic atomic_t g_foreground_uid = ATOMIC_INIT(FOREGROUND_UID_INIT); 228c2ecf20Sopenharmony_ci#define OPT_LEN 3 238c2ecf20Sopenharmony_ci#define TO_DECIMAL 10 248c2ecf20Sopenharmony_ci#define LIST_MAX 500 258c2ecf20Sopenharmony_ci#define DECIMAL_CHAR_NUM 10 // u32 decimal characters (4,294,967,295) 268c2ecf20Sopenharmony_cistatic DEFINE_RWLOCK(g_dpa_rwlock); 278c2ecf20Sopenharmony_cistatic u32 g_dpa_uid_list_cnt; 288c2ecf20Sopenharmony_cistatic struct list_head g_dpa_uid_list; 298c2ecf20Sopenharmony_cistruct dpa_node { 308c2ecf20Sopenharmony_ci struct list_head list_node; 318c2ecf20Sopenharmony_ci uid_t uid; 328c2ecf20Sopenharmony_ci}; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic void foreground_uid_atomic_set(uid_t val) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci atomic_set(&g_foreground_uid, val); 378c2ecf20Sopenharmony_ci} 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic uid_t foreground_uid_atomic_read(void) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci return (uid_t)atomic_read(&g_foreground_uid); 428c2ecf20Sopenharmony_ci} 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci// cat /proc/net/foreground_uid 458c2ecf20Sopenharmony_cistatic int foreground_uid_show(struct seq_file *seq, void *v) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci uid_t uid = foreground_uid_atomic_read(); 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci seq_printf(seq, "%u\n", uid); 508c2ecf20Sopenharmony_ci return 0; 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci// echo xx > /proc/net/foreground_uid 548c2ecf20Sopenharmony_cistatic int foreground_uid_write(struct file *file, char *buf, size_t size) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci char *p = buf; 578c2ecf20Sopenharmony_ci uid_t uid = simple_strtoul(p, &p, TO_DECIMAL); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci if (!p) 608c2ecf20Sopenharmony_ci return -EINVAL; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci foreground_uid_atomic_set(uid); 638c2ecf20Sopenharmony_ci return 0; 648c2ecf20Sopenharmony_ci} 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci// cat /proc/net/dpa_uid 678c2ecf20Sopenharmony_cistatic int dpa_uid_show(struct seq_file *seq, void *v) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci struct dpa_node *node = NULL; 708c2ecf20Sopenharmony_ci struct dpa_node *tmp_node = NULL; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci read_lock(&g_dpa_rwlock); 738c2ecf20Sopenharmony_ci seq_printf(seq, "uid list num: %u\n", g_dpa_uid_list_cnt); 748c2ecf20Sopenharmony_ci list_for_each_entry_safe(node, tmp_node, &g_dpa_uid_list, list_node) 758c2ecf20Sopenharmony_ci seq_printf(seq, "%u\n", node->uid); 768c2ecf20Sopenharmony_ci read_unlock(&g_dpa_rwlock); 778c2ecf20Sopenharmony_ci return 0; 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci// echo "add xx yy zz" > /proc/net/dpa_uid 818c2ecf20Sopenharmony_ci// echo "del xx yy zz" > /proc/net/dpa_uid 828c2ecf20Sopenharmony_cistatic int dpa_uid_add(uid_t uid); 838c2ecf20Sopenharmony_cistatic int dpa_uid_del(uid_t uid); 848c2ecf20Sopenharmony_cistatic int get_dpa_uids(char *buf, size_t size, u32 *uid_list, 858c2ecf20Sopenharmony_ci u32 index_max, u32 *index); 868c2ecf20Sopenharmony_cistatic int dpa_uid_write(struct file *file, char *buf, size_t size) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci u32 dpa_list[LIST_MAX]; 898c2ecf20Sopenharmony_ci u32 index = 0; 908c2ecf20Sopenharmony_ci int ret = -EINVAL; 918c2ecf20Sopenharmony_ci int i; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci if (get_dpa_uids(buf, size, dpa_list, LIST_MAX, &index) != 0) { 948c2ecf20Sopenharmony_ci pr_err("[dpa-uid-cfg] fail to parse dpa uids\n"); 958c2ecf20Sopenharmony_ci return ret; 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci if (strncmp(buf, "add", OPT_LEN) == 0) { 998c2ecf20Sopenharmony_ci for (i = 0; i < index; i++) { 1008c2ecf20Sopenharmony_ci ret = dpa_uid_add(dpa_list[i]); 1018c2ecf20Sopenharmony_ci if (ret != 0) { 1028c2ecf20Sopenharmony_ci pr_err("[dpa-uid-cfg] add fail, index=%u\n", i); 1038c2ecf20Sopenharmony_ci return ret; 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci } else if (strncmp(buf, "del", OPT_LEN) == 0) { 1078c2ecf20Sopenharmony_ci for (i = 0; i < index; i++) { 1088c2ecf20Sopenharmony_ci ret = dpa_uid_del(dpa_list[i]); 1098c2ecf20Sopenharmony_ci if (ret != 0) { 1108c2ecf20Sopenharmony_ci pr_err("[dpa-uid-cfg] del fail, index=%u\n", i); 1118c2ecf20Sopenharmony_ci return ret; 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci } else { 1158c2ecf20Sopenharmony_ci pr_err("[dpa-uid-cfg] cmd unknown\n"); 1168c2ecf20Sopenharmony_ci } 1178c2ecf20Sopenharmony_ci return ret; 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic int dpa_uid_add(uid_t uid) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci bool exist = false; 1238c2ecf20Sopenharmony_ci struct dpa_node *node = NULL; 1248c2ecf20Sopenharmony_ci struct dpa_node *tmp_node = NULL; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci write_lock(&g_dpa_rwlock); 1278c2ecf20Sopenharmony_ci if (g_dpa_uid_list_cnt >= LIST_MAX) { 1288c2ecf20Sopenharmony_ci write_unlock(&g_dpa_rwlock); 1298c2ecf20Sopenharmony_ci return -EFBIG; 1308c2ecf20Sopenharmony_ci } 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci list_for_each_entry_safe(node, tmp_node, &g_dpa_uid_list, list_node) { 1338c2ecf20Sopenharmony_ci if (node->uid == uid) { 1348c2ecf20Sopenharmony_ci exist = true; 1358c2ecf20Sopenharmony_ci break; 1368c2ecf20Sopenharmony_ci } 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci if (!exist) { 1408c2ecf20Sopenharmony_ci node = kzalloc(sizeof(*node), GFP_ATOMIC); 1418c2ecf20Sopenharmony_ci if (node) { 1428c2ecf20Sopenharmony_ci node->uid = uid; 1438c2ecf20Sopenharmony_ci list_add_tail(&node->list_node, &g_dpa_uid_list); 1448c2ecf20Sopenharmony_ci g_dpa_uid_list_cnt++; 1458c2ecf20Sopenharmony_ci } 1468c2ecf20Sopenharmony_ci } 1478c2ecf20Sopenharmony_ci write_unlock(&g_dpa_rwlock); 1488c2ecf20Sopenharmony_ci return 0; 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cistatic int dpa_uid_del(uid_t uid) 1528c2ecf20Sopenharmony_ci{ 1538c2ecf20Sopenharmony_ci struct dpa_node *node = NULL; 1548c2ecf20Sopenharmony_ci struct dpa_node *tmp_node = NULL; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci write_lock(&g_dpa_rwlock); 1578c2ecf20Sopenharmony_ci list_for_each_entry_safe(node, tmp_node, &g_dpa_uid_list, list_node) { 1588c2ecf20Sopenharmony_ci if (node->uid == uid) { 1598c2ecf20Sopenharmony_ci list_del(&node->list_node); 1608c2ecf20Sopenharmony_ci if (g_dpa_uid_list_cnt) 1618c2ecf20Sopenharmony_ci --g_dpa_uid_list_cnt; 1628c2ecf20Sopenharmony_ci break; 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci write_unlock(&g_dpa_rwlock); 1668c2ecf20Sopenharmony_ci return 0; 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic uid_t parse_single_uid(char *begin, char *end) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci char *cur = NULL; 1728c2ecf20Sopenharmony_ci uid_t uid = 0; 1738c2ecf20Sopenharmony_ci u32 len = end - begin; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci // u32 decimal characters (4,294,967,295) 1768c2ecf20Sopenharmony_ci if (len > DECIMAL_CHAR_NUM) { 1778c2ecf20Sopenharmony_ci pr_err("[dpa-uid-cfg] single uid len(%u) overflow\n", len); 1788c2ecf20Sopenharmony_ci return uid; 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci cur = begin; 1828c2ecf20Sopenharmony_ci while (cur < end) { 1838c2ecf20Sopenharmony_ci if (*cur < '0' || *cur > '9') { 1848c2ecf20Sopenharmony_ci pr_err("[dpa-uid-cfg] invalid character '%c'\n", *cur); 1858c2ecf20Sopenharmony_ci return uid; 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci cur++; 1888c2ecf20Sopenharmony_ci } 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci uid = simple_strtoul(begin, &begin, TO_DECIMAL); 1918c2ecf20Sopenharmony_ci if (!begin || !uid) { 1928c2ecf20Sopenharmony_ci pr_err("[dpa-uid-cfg] fail to change str to data"); 1938c2ecf20Sopenharmony_ci return uid; 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci return uid; 1978c2ecf20Sopenharmony_ci} 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_cistatic int parse_uids(char *args, u32 args_len, u32 *uid_list, 2008c2ecf20Sopenharmony_ci u32 index_max, u32 *index) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci char *begin = args; 2038c2ecf20Sopenharmony_ci char *end = strchr(args, ' '); 2048c2ecf20Sopenharmony_ci uid_t uid = 0; 2058c2ecf20Sopenharmony_ci u32 len = 0; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci while (end) { 2088c2ecf20Sopenharmony_ci // cur decimal characters cnt + ' ' or '\n' 2098c2ecf20Sopenharmony_ci len += end - begin + 1; 2108c2ecf20Sopenharmony_ci if (len > args_len || *index > index_max) { 2118c2ecf20Sopenharmony_ci pr_err("[dpa-uid-cfg] str len(%u) or index(%u) overflow\n", 2128c2ecf20Sopenharmony_ci len, *index); 2138c2ecf20Sopenharmony_ci return -EINVAL; 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci uid = parse_single_uid(begin, end); 2178c2ecf20Sopenharmony_ci if (!uid) 2188c2ecf20Sopenharmony_ci return -EINVAL; 2198c2ecf20Sopenharmony_ci uid_list[(*index)++] = uid; 2208c2ecf20Sopenharmony_ci begin = ++end; // next decimal characters (skip ' ' or '\n') 2218c2ecf20Sopenharmony_ci end = strchr(begin, ' '); 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci // find last uid characters 2258c2ecf20Sopenharmony_ci end = strchr(begin, '\n'); 2268c2ecf20Sopenharmony_ci if (!end) { 2278c2ecf20Sopenharmony_ci pr_err("[dpa-uid-cfg] last character is not '\\n'"); 2288c2ecf20Sopenharmony_ci return -EINVAL; 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci // cur decimal characters cnt + ' ' or '\n' 2328c2ecf20Sopenharmony_ci len += end - begin + 1; 2338c2ecf20Sopenharmony_ci if (len > args_len || *index > index_max) { 2348c2ecf20Sopenharmony_ci pr_err("[dpa-uid-cfg] str len(%u) or last index(%u) overflow\n", 2358c2ecf20Sopenharmony_ci len, *index); 2368c2ecf20Sopenharmony_ci return -EINVAL; 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci uid = parse_single_uid(begin, end); 2398c2ecf20Sopenharmony_ci if (!uid) 2408c2ecf20Sopenharmony_ci return -EINVAL; 2418c2ecf20Sopenharmony_ci uid_list[(*index)++] = uid; 2428c2ecf20Sopenharmony_ci return 0; 2438c2ecf20Sopenharmony_ci} 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_cistatic int get_dpa_uids(char *buf, size_t size, u32 *uid_list, 2468c2ecf20Sopenharmony_ci u32 index_max, u32 *index) 2478c2ecf20Sopenharmony_ci{ 2488c2ecf20Sopenharmony_ci char *args = NULL; 2498c2ecf20Sopenharmony_ci u32 opt_len; 2508c2ecf20Sopenharmony_ci u32 data_len; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci // split into cmd and argslist 2538c2ecf20Sopenharmony_ci args = strchr(buf, ' '); 2548c2ecf20Sopenharmony_ci if (!args) { 2558c2ecf20Sopenharmony_ci pr_err("[dpa-uid-cfg] cmd fmt invalid\n"); 2568c2ecf20Sopenharmony_ci return -EINVAL; 2578c2ecf20Sopenharmony_ci } 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci // cmd is add or del, len is 3 2608c2ecf20Sopenharmony_ci opt_len = args - buf; 2618c2ecf20Sopenharmony_ci if (opt_len != OPT_LEN) { 2628c2ecf20Sopenharmony_ci pr_err("[dpa-uid-cfg] cmd len invalid\n"); 2638c2ecf20Sopenharmony_ci return -EINVAL; 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci data_len = size - (opt_len + 1); 2678c2ecf20Sopenharmony_ci return parse_uids(args + 1, data_len, uid_list, index_max, index); 2688c2ecf20Sopenharmony_ci} 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cibool dpa_uid_match(uid_t kuid) 2718c2ecf20Sopenharmony_ci{ 2728c2ecf20Sopenharmony_ci bool match = false; 2738c2ecf20Sopenharmony_ci struct dpa_node *node = NULL; 2748c2ecf20Sopenharmony_ci struct dpa_node *tmp_node = NULL; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci if (kuid == 0) 2778c2ecf20Sopenharmony_ci return match; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci read_lock(&g_dpa_rwlock); 2808c2ecf20Sopenharmony_ci list_for_each_entry_safe(node, tmp_node, &g_dpa_uid_list, list_node) { 2818c2ecf20Sopenharmony_ci if (node->uid == kuid) { 2828c2ecf20Sopenharmony_ci match = true; 2838c2ecf20Sopenharmony_ci break; 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci } 2868c2ecf20Sopenharmony_ci read_unlock(&g_dpa_rwlock); 2878c2ecf20Sopenharmony_ci return match; 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dpa_uid_match); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci// call this fun in net/ipv4/af_inet.c inet_init_net() 2928c2ecf20Sopenharmony_civoid __net_init lowpower_protocol_net_init(struct net *net) 2938c2ecf20Sopenharmony_ci{ 2948c2ecf20Sopenharmony_ci if (!proc_create_net_single_write("foreground_uid", 0644, 2958c2ecf20Sopenharmony_ci net->proc_net, 2968c2ecf20Sopenharmony_ci foreground_uid_show, 2978c2ecf20Sopenharmony_ci foreground_uid_write, 2988c2ecf20Sopenharmony_ci NULL)) 2998c2ecf20Sopenharmony_ci pr_err("fail to create /proc/net/foreground_uid"); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&g_dpa_uid_list); 3028c2ecf20Sopenharmony_ci if (!proc_create_net_single_write("dpa_uid", 0644, 3038c2ecf20Sopenharmony_ci net->proc_net, 3048c2ecf20Sopenharmony_ci dpa_uid_show, 3058c2ecf20Sopenharmony_ci dpa_uid_write, 3068c2ecf20Sopenharmony_ci NULL)) 3078c2ecf20Sopenharmony_ci pr_err("fail to create /proc/net/dpa_uid"); 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_cistatic bool foreground_uid_match(struct net *net, struct sock *sk) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci uid_t kuid; 3138c2ecf20Sopenharmony_ci uid_t foreground_uid; 3148c2ecf20Sopenharmony_ci struct sock *fullsk; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci if (!net || !sk) 3178c2ecf20Sopenharmony_ci return false; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci fullsk = sk_to_full_sk(sk); 3208c2ecf20Sopenharmony_ci if (!fullsk || !sk_fullsock(fullsk)) 3218c2ecf20Sopenharmony_ci return false; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci kuid = sock_net_uid(net, fullsk).val; 3248c2ecf20Sopenharmony_ci foreground_uid = foreground_uid_atomic_read(); 3258c2ecf20Sopenharmony_ci if (kuid != foreground_uid) 3268c2ecf20Sopenharmony_ci return false; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci return true; 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci/* 3328c2ecf20Sopenharmony_ci * ack optimization is only enable for large data receiving tasks and 3338c2ecf20Sopenharmony_ci * there is no packet loss scenario 3348c2ecf20Sopenharmony_ci */ 3358c2ecf20Sopenharmony_ciint tcp_ack_num(struct sock *sk) 3368c2ecf20Sopenharmony_ci{ 3378c2ecf20Sopenharmony_ci if (!sk) 3388c2ecf20Sopenharmony_ci return 1; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci if (foreground_uid_match(sock_net(sk), sk) == false) 3418c2ecf20Sopenharmony_ci return 1; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci if (tcp_sk(sk)->bytes_received >= BIG_DATA_BYTES && 3448c2ecf20Sopenharmony_ci tcp_sk(sk)->dup_ack_counter < TCP_FASTRETRANS_THRESH) 3458c2ecf20Sopenharmony_ci return TCP_ACK_NUM; 3468c2ecf20Sopenharmony_ci return 1; 3478c2ecf20Sopenharmony_ci} 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_cibool netfilter_bypass_enable(struct net *net, struct sk_buff *skb, 3508c2ecf20Sopenharmony_ci int (*fun)(struct net *, struct sock *, struct sk_buff *), 3518c2ecf20Sopenharmony_ci int *ret) 3528c2ecf20Sopenharmony_ci{ 3538c2ecf20Sopenharmony_ci if (!net || !skb || !ip_hdr(skb) || ip_hdr(skb)->protocol != IPPROTO_TCP) 3548c2ecf20Sopenharmony_ci return false; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci if (foreground_uid_match(net, skb->sk)) { 3578c2ecf20Sopenharmony_ci *ret = fun(net, NULL, skb); 3588c2ecf20Sopenharmony_ci return true; 3598c2ecf20Sopenharmony_ci } 3608c2ecf20Sopenharmony_ci return false; 3618c2ecf20Sopenharmony_ci} 3628c2ecf20Sopenharmony_ci#endif /* CONFIG_LOWPOWER_PROTOCOL */ 363