18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * NetLabel Network Address Lists 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This file contains network address list functions used to manage ordered 68c2ecf20Sopenharmony_ci * lists of network addresses for use by the NetLabel subsystem. The NetLabel 78c2ecf20Sopenharmony_ci * system manages static and dynamic label mappings for network protocols such 88c2ecf20Sopenharmony_ci * as CIPSO and RIPSO. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Author: Paul Moore <paul@paul-moore.com> 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* 148c2ecf20Sopenharmony_ci * (c) Copyright Hewlett-Packard Development Company, L.P., 2008 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <linux/types.h> 188c2ecf20Sopenharmony_ci#include <linux/rcupdate.h> 198c2ecf20Sopenharmony_ci#include <linux/list.h> 208c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 218c2ecf20Sopenharmony_ci#include <linux/in.h> 228c2ecf20Sopenharmony_ci#include <linux/in6.h> 238c2ecf20Sopenharmony_ci#include <linux/ip.h> 248c2ecf20Sopenharmony_ci#include <linux/ipv6.h> 258c2ecf20Sopenharmony_ci#include <net/ip.h> 268c2ecf20Sopenharmony_ci#include <net/ipv6.h> 278c2ecf20Sopenharmony_ci#include <linux/audit.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include "netlabel_addrlist.h" 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci/* 328c2ecf20Sopenharmony_ci * Address List Functions 338c2ecf20Sopenharmony_ci */ 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/** 368c2ecf20Sopenharmony_ci * netlbl_af4list_search - Search for a matching IPv4 address entry 378c2ecf20Sopenharmony_ci * @addr: IPv4 address 388c2ecf20Sopenharmony_ci * @head: the list head 398c2ecf20Sopenharmony_ci * 408c2ecf20Sopenharmony_ci * Description: 418c2ecf20Sopenharmony_ci * Searches the IPv4 address list given by @head. If a matching address entry 428c2ecf20Sopenharmony_ci * is found it is returned, otherwise NULL is returned. The caller is 438c2ecf20Sopenharmony_ci * responsible for calling the rcu_read_[un]lock() functions. 448c2ecf20Sopenharmony_ci * 458c2ecf20Sopenharmony_ci */ 468c2ecf20Sopenharmony_cistruct netlbl_af4list *netlbl_af4list_search(__be32 addr, 478c2ecf20Sopenharmony_ci struct list_head *head) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci struct netlbl_af4list *iter; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci list_for_each_entry_rcu(iter, head, list) 528c2ecf20Sopenharmony_ci if (iter->valid && (addr & iter->mask) == iter->addr) 538c2ecf20Sopenharmony_ci return iter; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci return NULL; 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/** 598c2ecf20Sopenharmony_ci * netlbl_af4list_search_exact - Search for an exact IPv4 address entry 608c2ecf20Sopenharmony_ci * @addr: IPv4 address 618c2ecf20Sopenharmony_ci * @mask: IPv4 address mask 628c2ecf20Sopenharmony_ci * @head: the list head 638c2ecf20Sopenharmony_ci * 648c2ecf20Sopenharmony_ci * Description: 658c2ecf20Sopenharmony_ci * Searches the IPv4 address list given by @head. If an exact match if found 668c2ecf20Sopenharmony_ci * it is returned, otherwise NULL is returned. The caller is responsible for 678c2ecf20Sopenharmony_ci * calling the rcu_read_[un]lock() functions. 688c2ecf20Sopenharmony_ci * 698c2ecf20Sopenharmony_ci */ 708c2ecf20Sopenharmony_cistruct netlbl_af4list *netlbl_af4list_search_exact(__be32 addr, 718c2ecf20Sopenharmony_ci __be32 mask, 728c2ecf20Sopenharmony_ci struct list_head *head) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci struct netlbl_af4list *iter; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci list_for_each_entry_rcu(iter, head, list) 778c2ecf20Sopenharmony_ci if (iter->valid && iter->addr == addr && iter->mask == mask) 788c2ecf20Sopenharmony_ci return iter; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci return NULL; 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6) 858c2ecf20Sopenharmony_ci/** 868c2ecf20Sopenharmony_ci * netlbl_af6list_search - Search for a matching IPv6 address entry 878c2ecf20Sopenharmony_ci * @addr: IPv6 address 888c2ecf20Sopenharmony_ci * @head: the list head 898c2ecf20Sopenharmony_ci * 908c2ecf20Sopenharmony_ci * Description: 918c2ecf20Sopenharmony_ci * Searches the IPv6 address list given by @head. If a matching address entry 928c2ecf20Sopenharmony_ci * is found it is returned, otherwise NULL is returned. The caller is 938c2ecf20Sopenharmony_ci * responsible for calling the rcu_read_[un]lock() functions. 948c2ecf20Sopenharmony_ci * 958c2ecf20Sopenharmony_ci */ 968c2ecf20Sopenharmony_cistruct netlbl_af6list *netlbl_af6list_search(const struct in6_addr *addr, 978c2ecf20Sopenharmony_ci struct list_head *head) 988c2ecf20Sopenharmony_ci{ 998c2ecf20Sopenharmony_ci struct netlbl_af6list *iter; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci list_for_each_entry_rcu(iter, head, list) 1028c2ecf20Sopenharmony_ci if (iter->valid && 1038c2ecf20Sopenharmony_ci ipv6_masked_addr_cmp(&iter->addr, &iter->mask, addr) == 0) 1048c2ecf20Sopenharmony_ci return iter; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci return NULL; 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci/** 1108c2ecf20Sopenharmony_ci * netlbl_af6list_search_exact - Search for an exact IPv6 address entry 1118c2ecf20Sopenharmony_ci * @addr: IPv6 address 1128c2ecf20Sopenharmony_ci * @mask: IPv6 address mask 1138c2ecf20Sopenharmony_ci * @head: the list head 1148c2ecf20Sopenharmony_ci * 1158c2ecf20Sopenharmony_ci * Description: 1168c2ecf20Sopenharmony_ci * Searches the IPv6 address list given by @head. If an exact match if found 1178c2ecf20Sopenharmony_ci * it is returned, otherwise NULL is returned. The caller is responsible for 1188c2ecf20Sopenharmony_ci * calling the rcu_read_[un]lock() functions. 1198c2ecf20Sopenharmony_ci * 1208c2ecf20Sopenharmony_ci */ 1218c2ecf20Sopenharmony_cistruct netlbl_af6list *netlbl_af6list_search_exact(const struct in6_addr *addr, 1228c2ecf20Sopenharmony_ci const struct in6_addr *mask, 1238c2ecf20Sopenharmony_ci struct list_head *head) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci struct netlbl_af6list *iter; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci list_for_each_entry_rcu(iter, head, list) 1288c2ecf20Sopenharmony_ci if (iter->valid && 1298c2ecf20Sopenharmony_ci ipv6_addr_equal(&iter->addr, addr) && 1308c2ecf20Sopenharmony_ci ipv6_addr_equal(&iter->mask, mask)) 1318c2ecf20Sopenharmony_ci return iter; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci return NULL; 1348c2ecf20Sopenharmony_ci} 1358c2ecf20Sopenharmony_ci#endif /* IPv6 */ 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci/** 1388c2ecf20Sopenharmony_ci * netlbl_af4list_add - Add a new IPv4 address entry to a list 1398c2ecf20Sopenharmony_ci * @entry: address entry 1408c2ecf20Sopenharmony_ci * @head: the list head 1418c2ecf20Sopenharmony_ci * 1428c2ecf20Sopenharmony_ci * Description: 1438c2ecf20Sopenharmony_ci * Add a new address entry to the list pointed to by @head. On success zero is 1448c2ecf20Sopenharmony_ci * returned, otherwise a negative value is returned. The caller is responsible 1458c2ecf20Sopenharmony_ci * for calling the necessary locking functions. 1468c2ecf20Sopenharmony_ci * 1478c2ecf20Sopenharmony_ci */ 1488c2ecf20Sopenharmony_ciint netlbl_af4list_add(struct netlbl_af4list *entry, struct list_head *head) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci struct netlbl_af4list *iter; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci iter = netlbl_af4list_search(entry->addr, head); 1538c2ecf20Sopenharmony_ci if (iter != NULL && 1548c2ecf20Sopenharmony_ci iter->addr == entry->addr && iter->mask == entry->mask) 1558c2ecf20Sopenharmony_ci return -EEXIST; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci /* in order to speed up address searches through the list (the common 1588c2ecf20Sopenharmony_ci * case) we need to keep the list in order based on the size of the 1598c2ecf20Sopenharmony_ci * address mask such that the entry with the widest mask (smallest 1608c2ecf20Sopenharmony_ci * numerical value) appears first in the list */ 1618c2ecf20Sopenharmony_ci list_for_each_entry_rcu(iter, head, list) 1628c2ecf20Sopenharmony_ci if (iter->valid && 1638c2ecf20Sopenharmony_ci ntohl(entry->mask) > ntohl(iter->mask)) { 1648c2ecf20Sopenharmony_ci __list_add_rcu(&entry->list, 1658c2ecf20Sopenharmony_ci iter->list.prev, 1668c2ecf20Sopenharmony_ci &iter->list); 1678c2ecf20Sopenharmony_ci return 0; 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci list_add_tail_rcu(&entry->list, head); 1708c2ecf20Sopenharmony_ci return 0; 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6) 1748c2ecf20Sopenharmony_ci/** 1758c2ecf20Sopenharmony_ci * netlbl_af6list_add - Add a new IPv6 address entry to a list 1768c2ecf20Sopenharmony_ci * @entry: address entry 1778c2ecf20Sopenharmony_ci * @head: the list head 1788c2ecf20Sopenharmony_ci * 1798c2ecf20Sopenharmony_ci * Description: 1808c2ecf20Sopenharmony_ci * Add a new address entry to the list pointed to by @head. On success zero is 1818c2ecf20Sopenharmony_ci * returned, otherwise a negative value is returned. The caller is responsible 1828c2ecf20Sopenharmony_ci * for calling the necessary locking functions. 1838c2ecf20Sopenharmony_ci * 1848c2ecf20Sopenharmony_ci */ 1858c2ecf20Sopenharmony_ciint netlbl_af6list_add(struct netlbl_af6list *entry, struct list_head *head) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci struct netlbl_af6list *iter; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci iter = netlbl_af6list_search(&entry->addr, head); 1908c2ecf20Sopenharmony_ci if (iter != NULL && 1918c2ecf20Sopenharmony_ci ipv6_addr_equal(&iter->addr, &entry->addr) && 1928c2ecf20Sopenharmony_ci ipv6_addr_equal(&iter->mask, &entry->mask)) 1938c2ecf20Sopenharmony_ci return -EEXIST; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci /* in order to speed up address searches through the list (the common 1968c2ecf20Sopenharmony_ci * case) we need to keep the list in order based on the size of the 1978c2ecf20Sopenharmony_ci * address mask such that the entry with the widest mask (smallest 1988c2ecf20Sopenharmony_ci * numerical value) appears first in the list */ 1998c2ecf20Sopenharmony_ci list_for_each_entry_rcu(iter, head, list) 2008c2ecf20Sopenharmony_ci if (iter->valid && 2018c2ecf20Sopenharmony_ci ipv6_addr_cmp(&entry->mask, &iter->mask) > 0) { 2028c2ecf20Sopenharmony_ci __list_add_rcu(&entry->list, 2038c2ecf20Sopenharmony_ci iter->list.prev, 2048c2ecf20Sopenharmony_ci &iter->list); 2058c2ecf20Sopenharmony_ci return 0; 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci list_add_tail_rcu(&entry->list, head); 2088c2ecf20Sopenharmony_ci return 0; 2098c2ecf20Sopenharmony_ci} 2108c2ecf20Sopenharmony_ci#endif /* IPv6 */ 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci/** 2138c2ecf20Sopenharmony_ci * netlbl_af4list_remove_entry - Remove an IPv4 address entry 2148c2ecf20Sopenharmony_ci * @entry: address entry 2158c2ecf20Sopenharmony_ci * 2168c2ecf20Sopenharmony_ci * Description: 2178c2ecf20Sopenharmony_ci * Remove the specified IP address entry. The caller is responsible for 2188c2ecf20Sopenharmony_ci * calling the necessary locking functions. 2198c2ecf20Sopenharmony_ci * 2208c2ecf20Sopenharmony_ci */ 2218c2ecf20Sopenharmony_civoid netlbl_af4list_remove_entry(struct netlbl_af4list *entry) 2228c2ecf20Sopenharmony_ci{ 2238c2ecf20Sopenharmony_ci entry->valid = 0; 2248c2ecf20Sopenharmony_ci list_del_rcu(&entry->list); 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci/** 2288c2ecf20Sopenharmony_ci * netlbl_af4list_remove - Remove an IPv4 address entry 2298c2ecf20Sopenharmony_ci * @addr: IP address 2308c2ecf20Sopenharmony_ci * @mask: IP address mask 2318c2ecf20Sopenharmony_ci * @head: the list head 2328c2ecf20Sopenharmony_ci * 2338c2ecf20Sopenharmony_ci * Description: 2348c2ecf20Sopenharmony_ci * Remove an IP address entry from the list pointed to by @head. Returns the 2358c2ecf20Sopenharmony_ci * entry on success, NULL on failure. The caller is responsible for calling 2368c2ecf20Sopenharmony_ci * the necessary locking functions. 2378c2ecf20Sopenharmony_ci * 2388c2ecf20Sopenharmony_ci */ 2398c2ecf20Sopenharmony_cistruct netlbl_af4list *netlbl_af4list_remove(__be32 addr, __be32 mask, 2408c2ecf20Sopenharmony_ci struct list_head *head) 2418c2ecf20Sopenharmony_ci{ 2428c2ecf20Sopenharmony_ci struct netlbl_af4list *entry; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci entry = netlbl_af4list_search_exact(addr, mask, head); 2458c2ecf20Sopenharmony_ci if (entry == NULL) 2468c2ecf20Sopenharmony_ci return NULL; 2478c2ecf20Sopenharmony_ci netlbl_af4list_remove_entry(entry); 2488c2ecf20Sopenharmony_ci return entry; 2498c2ecf20Sopenharmony_ci} 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6) 2528c2ecf20Sopenharmony_ci/** 2538c2ecf20Sopenharmony_ci * netlbl_af6list_remove_entry - Remove an IPv6 address entry 2548c2ecf20Sopenharmony_ci * @entry: address entry 2558c2ecf20Sopenharmony_ci * 2568c2ecf20Sopenharmony_ci * Description: 2578c2ecf20Sopenharmony_ci * Remove the specified IP address entry. The caller is responsible for 2588c2ecf20Sopenharmony_ci * calling the necessary locking functions. 2598c2ecf20Sopenharmony_ci * 2608c2ecf20Sopenharmony_ci */ 2618c2ecf20Sopenharmony_civoid netlbl_af6list_remove_entry(struct netlbl_af6list *entry) 2628c2ecf20Sopenharmony_ci{ 2638c2ecf20Sopenharmony_ci entry->valid = 0; 2648c2ecf20Sopenharmony_ci list_del_rcu(&entry->list); 2658c2ecf20Sopenharmony_ci} 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci/** 2688c2ecf20Sopenharmony_ci * netlbl_af6list_remove - Remove an IPv6 address entry 2698c2ecf20Sopenharmony_ci * @addr: IP address 2708c2ecf20Sopenharmony_ci * @mask: IP address mask 2718c2ecf20Sopenharmony_ci * @head: the list head 2728c2ecf20Sopenharmony_ci * 2738c2ecf20Sopenharmony_ci * Description: 2748c2ecf20Sopenharmony_ci * Remove an IP address entry from the list pointed to by @head. Returns the 2758c2ecf20Sopenharmony_ci * entry on success, NULL on failure. The caller is responsible for calling 2768c2ecf20Sopenharmony_ci * the necessary locking functions. 2778c2ecf20Sopenharmony_ci * 2788c2ecf20Sopenharmony_ci */ 2798c2ecf20Sopenharmony_cistruct netlbl_af6list *netlbl_af6list_remove(const struct in6_addr *addr, 2808c2ecf20Sopenharmony_ci const struct in6_addr *mask, 2818c2ecf20Sopenharmony_ci struct list_head *head) 2828c2ecf20Sopenharmony_ci{ 2838c2ecf20Sopenharmony_ci struct netlbl_af6list *entry; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci entry = netlbl_af6list_search_exact(addr, mask, head); 2868c2ecf20Sopenharmony_ci if (entry == NULL) 2878c2ecf20Sopenharmony_ci return NULL; 2888c2ecf20Sopenharmony_ci netlbl_af6list_remove_entry(entry); 2898c2ecf20Sopenharmony_ci return entry; 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci#endif /* IPv6 */ 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci/* 2948c2ecf20Sopenharmony_ci * Audit Helper Functions 2958c2ecf20Sopenharmony_ci */ 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci#ifdef CONFIG_AUDIT 2988c2ecf20Sopenharmony_ci/** 2998c2ecf20Sopenharmony_ci * netlbl_af4list_audit_addr - Audit an IPv4 address 3008c2ecf20Sopenharmony_ci * @audit_buf: audit buffer 3018c2ecf20Sopenharmony_ci * @src: true if source address, false if destination 3028c2ecf20Sopenharmony_ci * @dev: network interface 3038c2ecf20Sopenharmony_ci * @addr: IP address 3048c2ecf20Sopenharmony_ci * @mask: IP address mask 3058c2ecf20Sopenharmony_ci * 3068c2ecf20Sopenharmony_ci * Description: 3078c2ecf20Sopenharmony_ci * Write the IPv4 address and address mask, if necessary, to @audit_buf. 3088c2ecf20Sopenharmony_ci * 3098c2ecf20Sopenharmony_ci */ 3108c2ecf20Sopenharmony_civoid netlbl_af4list_audit_addr(struct audit_buffer *audit_buf, 3118c2ecf20Sopenharmony_ci int src, const char *dev, 3128c2ecf20Sopenharmony_ci __be32 addr, __be32 mask) 3138c2ecf20Sopenharmony_ci{ 3148c2ecf20Sopenharmony_ci u32 mask_val = ntohl(mask); 3158c2ecf20Sopenharmony_ci char *dir = (src ? "src" : "dst"); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci if (dev != NULL) 3188c2ecf20Sopenharmony_ci audit_log_format(audit_buf, " netif=%s", dev); 3198c2ecf20Sopenharmony_ci audit_log_format(audit_buf, " %s=%pI4", dir, &addr); 3208c2ecf20Sopenharmony_ci if (mask_val != 0xffffffff) { 3218c2ecf20Sopenharmony_ci u32 mask_len = 0; 3228c2ecf20Sopenharmony_ci while (mask_val > 0) { 3238c2ecf20Sopenharmony_ci mask_val <<= 1; 3248c2ecf20Sopenharmony_ci mask_len++; 3258c2ecf20Sopenharmony_ci } 3268c2ecf20Sopenharmony_ci audit_log_format(audit_buf, " %s_prefixlen=%d", dir, mask_len); 3278c2ecf20Sopenharmony_ci } 3288c2ecf20Sopenharmony_ci} 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6) 3318c2ecf20Sopenharmony_ci/** 3328c2ecf20Sopenharmony_ci * netlbl_af6list_audit_addr - Audit an IPv6 address 3338c2ecf20Sopenharmony_ci * @audit_buf: audit buffer 3348c2ecf20Sopenharmony_ci * @src: true if source address, false if destination 3358c2ecf20Sopenharmony_ci * @dev: network interface 3368c2ecf20Sopenharmony_ci * @addr: IP address 3378c2ecf20Sopenharmony_ci * @mask: IP address mask 3388c2ecf20Sopenharmony_ci * 3398c2ecf20Sopenharmony_ci * Description: 3408c2ecf20Sopenharmony_ci * Write the IPv6 address and address mask, if necessary, to @audit_buf. 3418c2ecf20Sopenharmony_ci * 3428c2ecf20Sopenharmony_ci */ 3438c2ecf20Sopenharmony_civoid netlbl_af6list_audit_addr(struct audit_buffer *audit_buf, 3448c2ecf20Sopenharmony_ci int src, 3458c2ecf20Sopenharmony_ci const char *dev, 3468c2ecf20Sopenharmony_ci const struct in6_addr *addr, 3478c2ecf20Sopenharmony_ci const struct in6_addr *mask) 3488c2ecf20Sopenharmony_ci{ 3498c2ecf20Sopenharmony_ci char *dir = (src ? "src" : "dst"); 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci if (dev != NULL) 3528c2ecf20Sopenharmony_ci audit_log_format(audit_buf, " netif=%s", dev); 3538c2ecf20Sopenharmony_ci audit_log_format(audit_buf, " %s=%pI6", dir, addr); 3548c2ecf20Sopenharmony_ci if (ntohl(mask->s6_addr32[3]) != 0xffffffff) { 3558c2ecf20Sopenharmony_ci u32 mask_len = 0; 3568c2ecf20Sopenharmony_ci u32 mask_val; 3578c2ecf20Sopenharmony_ci int iter = -1; 3588c2ecf20Sopenharmony_ci while (ntohl(mask->s6_addr32[++iter]) == 0xffffffff) 3598c2ecf20Sopenharmony_ci mask_len += 32; 3608c2ecf20Sopenharmony_ci mask_val = ntohl(mask->s6_addr32[iter]); 3618c2ecf20Sopenharmony_ci while (mask_val > 0) { 3628c2ecf20Sopenharmony_ci mask_val <<= 1; 3638c2ecf20Sopenharmony_ci mask_len++; 3648c2ecf20Sopenharmony_ci } 3658c2ecf20Sopenharmony_ci audit_log_format(audit_buf, " %s_prefixlen=%d", dir, mask_len); 3668c2ecf20Sopenharmony_ci } 3678c2ecf20Sopenharmony_ci} 3688c2ecf20Sopenharmony_ci#endif /* IPv6 */ 3698c2ecf20Sopenharmony_ci#endif /* CONFIG_AUDIT */ 370