STRUCT GENL_FAMILY(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

okay so this is the Kernel API Manual page for struct genl_family, and bestie it's literally the blueprint for your generic netlink family. think of it as the main-character struct β€” it holds all the metadata, callbacks, and policy info the core needs to know about your family. no cap, it's iconic.


✨ SYNOPSIS ✨

here's the whole struct, exactly as it lives in the header β€” don't touch the formatting, she's perfect:

struct genl_family {
    unsigned int            hdrsize;
    char name[GENL_NAMSIZ];
    unsigned int            version;
    unsigned int            maxattr;
    u8 netnsok:1;
    u8 parallel_ops:1;
    u8 n_ops;
    u8 n_small_ops;
    u8 n_split_ops;
    u8 n_mcgrps;
    u8 resv_start_op;
    const struct nla_policy *policy;
    int (*pre_doit)(const struct genl_split_ops *ops, struct sk_buff
*skb, struct genl_info *info);
    void (*post_doit)(const struct genl_split_ops *ops, struct sk_buff
*skb, struct genl_info *info);
    int (*bind)(int mcgrp);
    void (*unbind)(int mcgrp);
    const struct genl_ops * ops;
    const struct genl_small_ops *small_ops;
    const struct genl_split_ops *split_ops;
    const struct genl_multicast_group *mcgrps;
    struct module           *module;
    size_t sock_priv_size;
    void (*sock_priv_init)(void *priv);
    void (*sock_priv_destroy)(void *priv);
 };

🌸 MEMBERS 🌸

every field gets its moment, so let's go through them one by one:

  • hdrsize β€” how many bytes of user-specific header you're rocking at the front of every message. just the length, no drama.
  • name β€” the name of your family, stored in a char[GENL_NAMSIZ]. pick something cute but permanent.
  • version β€” the protocol version. yes, you have to version your family. yes, it matters.
  • maxattr β€” the maximum number of attributes you support. literally the ceiling.
  • netnsok β€” set this to true if your family can handle network namespaces and should show up in all of them. one bit, big responsibility.
  • parallel_ops β€” set to true if your operations can be called in parallel and aren't synchronized by the core genetlink code. highkey a flex if you can handle it.
  • n_ops β€” the number of operations your family supports.
  • n_small_ops β€” the number of small-struct operations your family supports.
  • n_split_ops β€” the number of entries in split_ops. heads up: with split do/dump ops, this is not the same as the number of commands. don't get it twisted.
  • n_mcgrps β€” the number of multicast groups. count them carefully, bestie.
  • resv_start_op β€” the first operation for which reserved fields of the header can be validated and policies are required (see the description below for the full tea). new families should leave this field at zero. periodt.
  • policy β€” the netlink policy. the vibe check for your attributes.
  • pre_doit β€” this callback gets called before an operation's doit callback. it can do additional, common filtering and return an error if something's off. think of it as the bouncer at the club.
  • post_doit β€” called after an operation's doit callback. it may undo whatever pre_doit did β€” for example, release locks. the cleanup crew. 🧹
  • bind β€” called when a family multicast group is added to a netlink socket. it takes an int mcgrp.
  • unbind β€” called when a family multicast group is removed from a netlink socket. also takes an int mcgrp. the sad goodbye.
  • ops β€” the operations supported by this family. the classic full-struct form.
  • small_ops β€” the small-struct operations supported by this family. lean and mean.
  • split_ops β€” the split do/dump form of operation definition. very fancy, very modern.
  • mcgrps β€” the multicast groups used by this family. where the group chat actually happens.
  • module β€” pointer to the owning module β€” set it to THIS_MODULE. don't forget or the kernel will be confused.
  • sock_priv_size β€” the size of per-socket private memory. how much room your family gets to keep its own little secrets per socket.
  • sock_priv_init β€” the per-socket private memory initializer. runs when that memory gets set up.
  • sock_priv_destroy β€” the per-socket private memory destructor. runs when it's time to let go. 😭

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so here's the part where it gets real. attribute policies β€” that's the combination of the policy and maxattr fields β€” can be attached at the family level or at the operation level. if both are present, the per-operation policy takes precedence. like, operation-level always wins the argument.

for operations before resv_start_op, lack of policy means the core will perform no attribute parsing or validation. literally zero. the wild west.

for newer operations, if policy is not provided, the core will reject all TLV attributes. so like… provide a policy, bestie. unless you want your attributes to get ghosted. πŸ‘»

⚠️ also: new families should leave resv_start_op at zero. that's not a suggestion, that's the instruction. don't come for me, I'm just the messenger.

πŸ”₯ SEE ALSO πŸ”₯

the whole extended fam β€” check out the kernel file ./include/net and these iconic structs/functions:


source: ./include/net β€’ October 2026 β€’ struct genl_family(9)

and that's the page, bestie. now go build your family, set module to THIS_MODULE, and don't forget your policy. mwah. πŸ’…βœ¨

πŸ“¦ where this page comes from