net/netlink/af_netlink.c
Source file repositories/reference/linux-study-clean/net/netlink/af_netlink.c
File Facts
- System
- Linux kernel
- Corpus path
net/netlink/af_netlink.c- Extension
.c- Size
- 71577 bytes
- Lines
- 2960
- Domain
- Networking Core
- Bucket
- Sockets, Protocols, Packet Path, And Network Policy
- Inferred role
- Networking Core: operation-table or driver-model contract
- Status
- pattern implementation candidate
Why This File Exists
Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.
- Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/module.hlinux/bpf.hlinux/capability.hlinux/kernel.hlinux/filter.hlinux/init.hlinux/signal.hlinux/sched.hlinux/errno.hlinux/string.hlinux/stat.hlinux/socket.hlinux/un.hlinux/fcntl.hlinux/termios.hlinux/sockios.hlinux/net.hlinux/fs.hlinux/slab.hlinux/uaccess.hlinux/uio.hlinux/skbuff.hlinux/netdevice.hlinux/rtnetlink.hlinux/proc_fs.hlinux/seq_file.hlinux/notifier.hlinux/security.hlinux/jhash.hlinux/jiffies.hlinux/random.hlinux/bitops.h
Detected Declarations
struct listenersstruct netlink_tap_netstruct netlink_compare_argstruct netlink_broadcast_datastruct netlink_set_err_datastruct nl_seq_iterstruct bpf_iter__netlinkfunction netlink_is_kernelfunction do_trace_netlink_extackfunction netlink_group_maskfunction netlink_add_tapfunction __netlink_remove_tapfunction list_for_each_entryfunction netlink_remove_tapfunction netlink_tap_init_netfunction netlink_filter_tapfunction __netlink_deliver_tap_skbfunction __netlink_deliver_tapfunction list_for_each_entry_rcufunction netlink_deliver_tapfunction netlink_deliver_tap_kernelfunction netlink_overrunfunction netlink_rcv_wakefunction netlink_skb_destructorfunction netlink_skb_set_owner_rfunction netlink_sock_destructfunction netlink_table_grabfunction netlink_table_ungrabfunction netlink_lock_tablefunction netlink_unlock_tablefunction netlink_comparefunction netlink_compare_arg_initfunction __netlink_insertfunction netlink_update_listenersfunction sk_for_each_boundfunction netlink_insertfunction netlink_removefunction __netlink_createfunction netlink_createfunction deferred_put_nlk_skfunction netlink_releasefunction netlink_autobindfunction __netlink_ns_capablefunction netlink_ns_capablefunction netlink_capablefunction netlink_net_capablefunction netlink_allowedfunction netlink_update_subscriptions
Annotated Snippet
static const struct proto_ops netlink_ops;
static void
netlink_update_listeners(struct sock *sk)
{
struct netlink_table *tbl = &nl_table[sk->sk_protocol];
unsigned long mask;
unsigned int i;
struct listeners *listeners;
listeners = nl_deref_protected(tbl->listeners);
if (!listeners)
return;
for (i = 0; i < NLGRPLONGS(tbl->groups); i++) {
mask = 0;
sk_for_each_bound(sk, &tbl->mc_list) {
if (i < NLGRPLONGS(nlk_sk(sk)->ngroups))
mask |= nlk_sk(sk)->groups[i];
}
listeners->masks[i] = mask;
}
/* this function is only called with the netlink table "grabbed", which
* makes sure updates are visible before bind or setsockopt return. */
}
static int netlink_insert(struct sock *sk, u32 portid)
{
struct netlink_table *table = &nl_table[sk->sk_protocol];
int err;
lock_sock(sk);
err = nlk_sk(sk)->portid == portid ? 0 : -EBUSY;
if (nlk_sk(sk)->bound)
goto err;
/* portid can be read locklessly from netlink_getname(). */
WRITE_ONCE(nlk_sk(sk)->portid, portid);
sock_hold(sk);
err = __netlink_insert(table, sk);
if (err) {
/* In case the hashtable backend returns with -EBUSY
* from here, it must not escape to the caller.
*/
if (unlikely(err == -EBUSY))
err = -EOVERFLOW;
if (err == -EEXIST)
err = -EADDRINUSE;
sock_put(sk);
goto err;
}
/* We need to ensure that the socket is hashed and visible. */
smp_wmb();
/* Paired with lockless reads from netlink_bind(),
* netlink_connect() and netlink_sendmsg().
*/
WRITE_ONCE(nlk_sk(sk)->bound, portid);
err:
release_sock(sk);
return err;
}
static void netlink_remove(struct sock *sk)
{
struct netlink_table *table;
table = &nl_table[sk->sk_protocol];
if (!rhashtable_remove_fast(&table->hash, &nlk_sk(sk)->node,
netlink_rhashtable_params))
__sock_put(sk);
netlink_table_grab();
if (nlk_sk(sk)->subscriptions) {
__sk_del_bind_node(sk);
netlink_update_listeners(sk);
}
if (sk->sk_protocol == NETLINK_GENERIC)
atomic_inc(&genl_sk_destructing_cnt);
netlink_table_ungrab();
}
static struct proto netlink_proto = {
.name = "NETLINK",
.owner = THIS_MODULE,
.obj_size = sizeof(struct netlink_sock),
Annotation
- Immediate include surface: `linux/module.h`, `linux/bpf.h`, `linux/capability.h`, `linux/kernel.h`, `linux/filter.h`, `linux/init.h`, `linux/signal.h`, `linux/sched.h`.
- Detected declarations: `struct listeners`, `struct netlink_tap_net`, `struct netlink_compare_arg`, `struct netlink_broadcast_data`, `struct netlink_set_err_data`, `struct nl_seq_iter`, `struct bpf_iter__netlink`, `function netlink_is_kernel`, `function do_trace_netlink_extack`, `function netlink_group_mask`.
- Atlas domain: Networking Core / Sockets, Protocols, Packet Path, And Network Policy.
- Implementation status: pattern implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.