144d362409d5469aed47d19e7908d19bd194493aThomas Graf/* 244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/genl/genl.c Generic Netlink 344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 444d362409d5469aed47d19e7908d19bd194493aThomas Graf * This library is free software; you can redistribute it and/or 544d362409d5469aed47d19e7908d19bd194493aThomas Graf * modify it under the terms of the GNU Lesser General Public 644d362409d5469aed47d19e7908d19bd194493aThomas Graf * License as published by the Free Software Foundation version 2.1 744d362409d5469aed47d19e7908d19bd194493aThomas Graf * of the License. 844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 9054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch> 1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1144d362409d5469aed47d19e7908d19bd194493aThomas Graf 1244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 13054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @defgroup genl Generic Netlink Library (libnl-genl) 1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 1513c85b663390547d8787aa8f45fbd009f4f8a332Thomas Graf * @{ 1644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1744d362409d5469aed47d19e7908d19bd194493aThomas Graf 18054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#include <netlink-private/genl.h> 1944d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h> 2044d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/genl/genl.h> 2144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h> 2244d362409d5469aed47d19e7908d19bd194493aThomas Graf 2344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 24054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @name Generic Netlink Socket 2544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 2644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 2744d362409d5469aed47d19e7908d19bd194493aThomas Graf 28054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/** 29054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Connect a Generic Netlink socket 30054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg sk Unconnected Netlink socket 31054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 32054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * This function expects a struct nl_socket object previously allocated via 33054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * nl_socket_alloc(). It calls nl_connect() to create the local socket file 34054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * descriptor and binds the socket to the \c NETLINK_GENERIC Netlink protocol. 35054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 36054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Using this function is equivalent to: 37054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @code 38054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * nl_connect(sk, NETLINK_GENERIC); 39054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @endcode 40054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 41054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @see nl_connect() 42054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 43054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return 0 on success or a negative error code. 44054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */ 451155370f520cb64657e25153255cf7dc1424317fThomas Grafint genl_connect(struct nl_sock *sk) 4644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 471155370f520cb64657e25153255cf7dc1424317fThomas Graf return nl_connect(sk, NETLINK_GENERIC); 4844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 4944d362409d5469aed47d19e7908d19bd194493aThomas Graf 5044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 5144d362409d5469aed47d19e7908d19bd194493aThomas Graf 5244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 53054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @name Sending Data 5444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 5544d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 5644d362409d5469aed47d19e7908d19bd194493aThomas Graf 5744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 58054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Send a Generic Netlink message consisting only of a header 59054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg sk Generic Netlink socket 60054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg family Numeric family identifier 61054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg cmd Numeric command identifier 62054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg version Interface version 63054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg flags Additional Netlink message flags (optional) 64054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 65054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * This function is a shortcut for sending a Generic Netlink message without 66054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * any message payload. The message will only consist of the Netlink and 67054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Generic Netlink headers. The header is constructed based on the specified 68054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * parameters and passed on to nl_send_simple() to send it on the specified 69054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * socket. 70054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 71054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @par Example: 72054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @code 73054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * #include <netlink/genl/genl.h> 74054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * #include <linux/genetlink.h> 75054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 76054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * err = genl_send_simple(sk, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, CTRL_VERSION, 77054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * NLM_F_DUMP); 78054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @endcode 7944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 80054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @see nl_send_simple() 8144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 8244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code. 8344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 841155370f520cb64657e25153255cf7dc1424317fThomas Grafint genl_send_simple(struct nl_sock *sk, int family, int cmd, 8544d362409d5469aed47d19e7908d19bd194493aThomas Graf int version, int flags) 8644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 8744d362409d5469aed47d19e7908d19bd194493aThomas Graf struct genlmsghdr hdr = { 8844d362409d5469aed47d19e7908d19bd194493aThomas Graf .cmd = cmd, 8944d362409d5469aed47d19e7908d19bd194493aThomas Graf .version = version, 9044d362409d5469aed47d19e7908d19bd194493aThomas Graf }; 9144d362409d5469aed47d19e7908d19bd194493aThomas Graf 921155370f520cb64657e25153255cf7dc1424317fThomas Graf return nl_send_simple(sk, family, flags, &hdr, sizeof(hdr)); 9344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 9444d362409d5469aed47d19e7908d19bd194493aThomas Graf 9544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 9644d362409d5469aed47d19e7908d19bd194493aThomas Graf 9744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 9844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Message Parsing 9944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 10044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 10144d362409d5469aed47d19e7908d19bd194493aThomas Graf 102054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/** 103054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Validate Generic Netlink message headers 104054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg nlh Pointer to Netlink message header 105054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg hdrlen Length of user header 106054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 107054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Verifies the integrity of the Netlink and Generic Netlink headers by 108054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * enforcing the following requirements: 109054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * - Valid Netlink message header (nlmsg_valid_hdr()) 110054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * - Presence of a complete Generic Netlink header 111054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * - At least \c hdrlen bytes of payload included after the generic 112054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * netlink header. 113054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 114054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return A positive integer (true) if the headers are valid or 115054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 0 (false) if not. 116054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */ 117c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Grafint genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen) 118c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf{ 119c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf struct genlmsghdr *ghdr; 120c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 121c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf if (!nlmsg_valid_hdr(nlh, GENL_HDRLEN)) 122c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf return 0; 123c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 124c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf ghdr = nlmsg_data(nlh); 125c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf if (genlmsg_len(ghdr) < NLMSG_ALIGN(hdrlen)) 126c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf return 0; 127c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 128c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf return 1; 129c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf} 130c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 131054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/** 132054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Validate Generic Netlink message including attributes 133054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg nlh Pointer to Netlink message header 134054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg hdrlen Length of user header 135054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg maxtype Maximum attribtue id expected 136054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg policy Attribute validation policy 137054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 138054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Verifies the validity of the Netlink and Generic Netlink headers using 139054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * genlmsg_valid_hdr() and calls nla_validate() on the message payload to 140054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * verify the integrity of eventual attributes. 141054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 142054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @note You may call genlmsg_parse() directly to perform validation and 143054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * parsing in a single step. 144054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 145054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @see genlmsg_valid_hdr() 146054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @see nla_validate() 147054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @see genlmsg_parse() 148054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 149054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return 0 on success or a negative error code. 150054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */ 151c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Grafint genlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype, 152054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart struct nla_policy *policy) 153c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf{ 154c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf struct genlmsghdr *ghdr; 155c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 156c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf if (!genlmsg_valid_hdr(nlh, hdrlen)) 1578a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_MSG_TOOSHORT; 158c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 159c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf ghdr = nlmsg_data(nlh); 160c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf return nla_validate(genlmsg_attrdata(ghdr, hdrlen), 161c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf genlmsg_attrlen(ghdr, hdrlen), maxtype, policy); 162c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf} 163c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 164054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/** 165054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Parse Generic Netlink message including attributes 166054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg nlh Pointer to Netlink message header 167054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg hdrlen Length of user header 168054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg tb Array to store parsed attributes 169054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg maxtype Maximum attribute id expected 170054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg policy Attribute validation policy 171054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 172054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Verifies the validity of the Netlink and Generic Netlink headers using 173054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * genlmsg_valid_hdr() and calls nla_parse() on the message payload to 174054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * parse eventual attributes. 175054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 176054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @par Example: 177054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @code 178054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * struct nlattr *attrs[MY_TYPE_MAX+1]; 179054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 180054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * if ((err = genlsmg_parse(nlmsg_nlh(msg), sizeof(struct my_hdr), attrs, 181054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * MY_TYPE_MAX, attr_policy)) < 0) 182054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * // ERROR 183054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @endcode 184054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 185054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @see genlmsg_valid_hdr() 186054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @see genlmsg_validate() 187054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @see nla_parse() 188054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 189054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return 0 on success or a negative error code. 190054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */ 191c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Grafint genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], 192c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf int maxtype, struct nla_policy *policy) 193c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf{ 194c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf struct genlmsghdr *ghdr; 195c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 196c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf if (!genlmsg_valid_hdr(nlh, hdrlen)) 1978a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_MSG_TOOSHORT; 198c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 199c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf ghdr = nlmsg_data(nlh); 200c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf return nla_parse(tb, maxtype, genlmsg_attrdata(ghdr, hdrlen), 201c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf genlmsg_attrlen(ghdr, hdrlen), policy); 202c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf} 203c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 20444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 205054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Return pointer to Generic Netlink header 206054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg nlh Netlink message header 207054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 208054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return Pointer to Generic Netlink message header 20944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 210054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartstruct genlmsghdr *genlmsg_hdr(struct nlmsghdr *nlh) 21144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 212054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return nlmsg_data(nlh); 21344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 21444d362409d5469aed47d19e7908d19bd194493aThomas Graf 21544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 216054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Return length of message payload including user header 217054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg gnlh Generic Netlink message header 218054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 219054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @see genlmsg_data() 220054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 221054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return Length of user payload including an eventual user header in 222054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * number of bytes. 22344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 22444d362409d5469aed47d19e7908d19bd194493aThomas Grafint genlmsg_len(const struct genlmsghdr *gnlh) 22544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 226054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart const struct nlmsghdr *nlh; 227054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 228054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart nlh = (const struct nlmsghdr *)((const unsigned char *) gnlh - NLMSG_HDRLEN); 22944d362409d5469aed47d19e7908d19bd194493aThomas Graf return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN); 23044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 23144d362409d5469aed47d19e7908d19bd194493aThomas Graf 232054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 233054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/** 234054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Return pointer to user header 235054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg gnlh Generic Netlink message header 236054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 237054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Calculates the pointer to the user header based on the pointer to 238054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * the Generic Netlink message header. 239054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 240054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return Pointer to the user header 241054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */ 242054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartvoid *genlmsg_user_hdr(const struct genlmsghdr *gnlh) 243054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{ 244054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return genlmsg_data(gnlh); 245054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart} 246054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 247054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/** 248054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Return pointer to user data 249054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg gnlh Generic netlink message header 250054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg hdrlen Length of user header 251054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 252054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Calculates the pointer to the user data based on the pointer to 253054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * the Generic Netlink message header. 254054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 255054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @see genlmsg_user_datalen() 256054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 257054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return Pointer to the user data 258054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */ 259054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartvoid *genlmsg_user_data(const struct genlmsghdr *gnlh, const int hdrlen) 260054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{ 261054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return genlmsg_user_hdr(gnlh) + NLMSG_ALIGN(hdrlen); 262054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart} 263054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 264054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/** 265054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Return length of user data 266054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg gnlh Generic Netlink message header 267054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg hdrlen Length of user header 268054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 269054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @see genlmsg_user_data() 270054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 271054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return Length of user data in bytes 272054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */ 273054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartint genlmsg_user_datalen(const struct genlmsghdr *gnlh, const int hdrlen) 274054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{ 275054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return genlmsg_len(gnlh) - NLMSG_ALIGN(hdrlen); 276054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart} 277054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 27844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 279054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Return pointer to message attributes 280054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg gnlh Generic Netlink message header 281054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg hdrlen Length of user header 282054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 283054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @see genlmsg_attrlen() 284054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 285054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return Pointer to the start of the message's attributes section. 28644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 28744d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen) 28844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 289054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return genlmsg_user_data(gnlh, hdrlen); 29044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 29144d362409d5469aed47d19e7908d19bd194493aThomas Graf 29244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 293054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Return length of message attributes 294054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg gnlh Generic Netlink message header 295054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg hdrlen Length of user header 296054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 297054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @see genlmsg_attrdata() 298054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 299054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return Length of the message section containing attributes in number 300054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * of bytes. 30144d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 30244d362409d5469aed47d19e7908d19bd194493aThomas Grafint genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen) 30344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 30444d362409d5469aed47d19e7908d19bd194493aThomas Graf return genlmsg_len(gnlh) - NLMSG_ALIGN(hdrlen); 30544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 30644d362409d5469aed47d19e7908d19bd194493aThomas Graf 30744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 30844d362409d5469aed47d19e7908d19bd194493aThomas Graf 30944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 310054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @name Message Construction 31144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 31244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 31344d362409d5469aed47d19e7908d19bd194493aThomas Graf 31444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 315054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Add Generic Netlink headers to Netlink message 316054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg msg Netlink message object 317054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg port Netlink port or NL_AUTO_PORT 318054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg seq Sequence number of message or NL_AUTO_SEQ 319054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg family Numeric family identifier 320054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg hdrlen Length of user header 321054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg flags Additional Netlink message flags (optional) 322054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg cmd Numeric command identifier 323054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg version Interface version 324054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 325054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Calls nlmsg_put() on the specified message object to reserve space for 326054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * the Netlink header, the Generic Netlink header, and a user header of 327054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * specified length. Fills out the header fields with the specified 328054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * parameters. 329054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 330054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @par Example: 331054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @code 332054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * struct nl_msg *msg; 333054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * struct my_hdr *user_hdr; 334054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 335054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * if (!(msg = nlmsg_alloc())) 336054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * // ERROR 337054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 338054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * user_hdr = genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, family_id, 339054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * sizeof(struct my_hdr), 0, MY_CMD_FOO, 0); 340054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * if (!user_hdr) 341054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * // ERROR 342054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @endcode 343054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 344054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @see nlmsg_put() 345054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 346054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Returns Pointer to user header or NULL if an error occurred. 34744d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 348054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartvoid *genlmsg_put(struct nl_msg *msg, uint32_t port, uint32_t seq, int family, 34944d362409d5469aed47d19e7908d19bd194493aThomas Graf int hdrlen, int flags, uint8_t cmd, uint8_t version) 35044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 35144d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlmsghdr *nlh; 35244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct genlmsghdr hdr = { 35344d362409d5469aed47d19e7908d19bd194493aThomas Graf .cmd = cmd, 35444d362409d5469aed47d19e7908d19bd194493aThomas Graf .version = version, 35544d362409d5469aed47d19e7908d19bd194493aThomas Graf }; 35644d362409d5469aed47d19e7908d19bd194493aThomas Graf 357054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart nlh = nlmsg_put(msg, port, seq, family, GENL_HDRLEN + hdrlen, flags); 35844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (nlh == NULL) 35944d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 36044d362409d5469aed47d19e7908d19bd194493aThomas Graf 36144d362409d5469aed47d19e7908d19bd194493aThomas Graf memcpy(nlmsg_data(nlh), &hdr, sizeof(hdr)); 36244d362409d5469aed47d19e7908d19bd194493aThomas Graf NL_DBG(2, "msg %p: Added generic netlink header cmd=%d version=%d\n", 36344d362409d5469aed47d19e7908d19bd194493aThomas Graf msg, cmd, version); 36444d362409d5469aed47d19e7908d19bd194493aThomas Graf 36544d362409d5469aed47d19e7908d19bd194493aThomas Graf return nlmsg_data(nlh) + GENL_HDRLEN; 36644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 36744d362409d5469aed47d19e7908d19bd194493aThomas Graf 36844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 36944d362409d5469aed47d19e7908d19bd194493aThomas Graf 370054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/** 371054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @name Deprecated 372054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @{ 373054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */ 374054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 375054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/** 376054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Return pointer to message payload 377054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg gnlh Generic Netlink message header 378054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 379054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @deprecated This function has been deprecated due to inability to specify 380054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * the length of the user header. Use genlmsg_user_hdr() 381054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * respectively genlmsg_user_data(). 382054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * 383054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return Pointer to payload section 384054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */ 385054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartvoid *genlmsg_data(const struct genlmsghdr *gnlh) 386054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{ 387054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return ((unsigned char *) gnlh + GENL_HDRLEN); 388054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart} 389054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 390054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/** @} */ 39144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 392