net/netlabel/netlabel_domainhash.c

Source file repositories/reference/linux-study-clean/net/netlabel/netlabel_domainhash.c

File Facts

System
Linux kernel
Corpus path
net/netlabel/netlabel_domainhash.c
Extension
.c
Size
28050 bytes
Lines
971
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

struct netlbl_domhsh_tbl {
	struct list_head *tbl;
	u32 size;
};

/* Domain hash table */
/* updates should be so rare that having one spinlock for the entire hash table
 * should be okay */
static DEFINE_SPINLOCK(netlbl_domhsh_lock);
#define netlbl_domhsh_rcu_deref(p) \
	rcu_dereference_check(p, lockdep_is_held(&netlbl_domhsh_lock))
static struct netlbl_domhsh_tbl __rcu *netlbl_domhsh;
static struct netlbl_dom_map __rcu *netlbl_domhsh_def_ipv4;
static struct netlbl_dom_map __rcu *netlbl_domhsh_def_ipv6;

/*
 * Domain Hash Table Helper Functions
 */

/**
 * netlbl_domhsh_free_entry - Frees a domain hash table entry
 * @entry: the entry's RCU field
 *
 * Description:
 * This function is designed to be used as a callback to the call_rcu()
 * function so that the memory allocated to a hash table entry can be released
 * safely.
 *
 */
static void netlbl_domhsh_free_entry(struct rcu_head *entry)
{
	struct netlbl_dom_map *ptr;
	struct netlbl_af4list *iter4;
	struct netlbl_af4list *tmp4;
#if IS_ENABLED(CONFIG_IPV6)
	struct netlbl_af6list *iter6;
	struct netlbl_af6list *tmp6;
#endif /* IPv6 */

	ptr = container_of(entry, struct netlbl_dom_map, rcu);
	if (ptr->def.type == NETLBL_NLTYPE_ADDRSELECT) {
		netlbl_af4list_foreach_safe(iter4, tmp4,
					    &ptr->def.addrsel->list4) {
			netlbl_af4list_remove_entry(iter4);
			kfree(netlbl_domhsh_addr4_entry(iter4));
		}
#if IS_ENABLED(CONFIG_IPV6)
		netlbl_af6list_foreach_safe(iter6, tmp6,
					    &ptr->def.addrsel->list6) {
			netlbl_af6list_remove_entry(iter6);
			kfree(netlbl_domhsh_addr6_entry(iter6));
		}
#endif /* IPv6 */
		kfree(ptr->def.addrsel);
	}
	kfree(ptr->domain);
	kfree(ptr);
}

/**
 * netlbl_domhsh_hash - Hashing function for the domain hash table
 * @key: the domain name to hash
 *
 * Description:
 * This is the hashing function for the domain hash table, it returns the
 * correct bucket number for the domain.  The caller is responsible for
 * ensuring that the hash table is protected with either a RCU read lock or the
 * hash table lock.
 *
 */
static u32 netlbl_domhsh_hash(const char *key)
{
	u32 iter;
	u32 val;
	u32 len;

	/* This is taken (with slight modification) from
	 * security/selinux/ss/symtab.c:symhash() */

	for (iter = 0, val = 0, len = strlen(key); iter < len; iter++)
		val = (val << 4 | (val >> (8 * sizeof(u32) - 4))) ^ key[iter];
	return val & (netlbl_domhsh_rcu_deref(netlbl_domhsh)->size - 1);
}

static bool netlbl_family_match(u16 f1, u16 f2)
{
	return (f1 == f2) || (f1 == AF_UNSPEC) || (f2 == AF_UNSPEC);
}

/**

Annotation

Implementation Notes