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 * 91155370f520cb64657e25153255cf7dc1424317fThomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1144d362409d5469aed47d19e7908d19bd194493aThomas Graf 1244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup genl Generic Netlink 1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par Message Format 1644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 1744d362409d5469aed47d19e7908d19bd194493aThomas Graf * <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) ---> 1844d362409d5469aed47d19e7908d19bd194493aThomas Graf * +----------------------------+- - -+- - - - - - - - - - -+- - -+ 1944d362409d5469aed47d19e7908d19bd194493aThomas Graf * | Header | Pad | Payload | Pad | 2044d362409d5469aed47d19e7908d19bd194493aThomas Graf * | struct nlmsghdr | | | | 2144d362409d5469aed47d19e7908d19bd194493aThomas Graf * +----------------------------+- - -+- - - - - - - - - - -+- - -+ 2244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 2344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 2444d362409d5469aed47d19e7908d19bd194493aThomas Graf * <-------- GENL_HDRLEN -------> <--- hdrlen --> 2544d362409d5469aed47d19e7908d19bd194493aThomas Graf * <------- genlmsg_len(ghdr) ------> 2644d362409d5469aed47d19e7908d19bd194493aThomas Graf * +------------------------+- - -+---------------+- - -+------------+ 2744d362409d5469aed47d19e7908d19bd194493aThomas Graf * | Generic Netlink Header | Pad | Family Header | Pad | Attributes | 2844d362409d5469aed47d19e7908d19bd194493aThomas Graf * | struct genlmsghdr | | | | | 2944d362409d5469aed47d19e7908d19bd194493aThomas Graf * +------------------------+- - -+---------------+- - -+------------+ 3044d362409d5469aed47d19e7908d19bd194493aThomas Graf * genlmsg_data(ghdr)--------------^ ^ 3144d362409d5469aed47d19e7908d19bd194493aThomas Graf * genlmsg_attrdata(ghdr, hdrlen)------------------------- 3244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 3344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 34c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * @par Example 3544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 36c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * #include <netlink/netlink.h> 37c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * #include <netlink/genl/genl.h> 38c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * #include <netlink/genl/ctrl.h> 39c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * 401155370f520cb64657e25153255cf7dc1424317fThomas Graf * struct nl_sock *sock; 4144d362409d5469aed47d19e7908d19bd194493aThomas Graf * struct nl_msg *msg; 42c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * int family; 4344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 44c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * // Allocate a new netlink socket 451155370f520cb64657e25153255cf7dc1424317fThomas Graf * sock = nl_socket_alloc(); 4644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 47c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * // Connect to generic netlink socket on kernel side 48c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * genl_connect(sock); 4944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 50c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * // Ask kernel to resolve family name to family id 51c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * family = genl_ctrl_resolve(sock, "generic_netlink_family_name"); 5244d362409d5469aed47d19e7908d19bd194493aThomas Graf * 53c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * // Construct a generic netlink by allocating a new message, fill in 54c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * // the header and append a simple integer attribute. 55c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * msg = nlmsg_alloc(); 56c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_ECHO, 57c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * CMD_FOO_GET, FOO_VERSION); 58c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * nla_put_u32(msg, ATTR_FOO, 123); 5944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 60c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * // Send message over netlink socket 61c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * nl_send_auto_complete(sock, msg); 6244d362409d5469aed47d19e7908d19bd194493aThomas Graf * 63c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * // Free message 6444d362409d5469aed47d19e7908d19bd194493aThomas Graf * nlmsg_free(msg); 6544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 66c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * // Prepare socket to receive the answer by specifying the callback 67c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * // function to be called for valid messages. 68c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, parse_cb, NULL); 69c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * 70c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * // Wait for the answer and receive it 71c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * nl_recvmsgs_default(sock); 72c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * 73c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * static int parse_cb(struct nl_msg *msg, void *arg) 74c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * { 75c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * struct nlmsghdr *nlh = nlmsg_hdr(msg); 76c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * struct nlattr *attrs[ATTR_MAX+1]; 77c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * 78c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * // Validate message and parse attributes 79c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * genlmsg_parse(nlh, 0, attrs, ATTR_MAX, policy); 80c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * 81c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * if (attrs[ATTR_FOO]) { 82c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * uint32_t value = nla_get_u32(attrs[ATTR_FOO]); 83c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * ... 84c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * } 85c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * 86c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * return 0; 87c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf * } 8844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 8913c85b663390547d8787aa8f45fbd009f4f8a332Thomas Graf * @{ 9044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 9144d362409d5469aed47d19e7908d19bd194493aThomas Graf 9244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-generic.h> 9344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h> 9444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/genl/genl.h> 9544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h> 9644d362409d5469aed47d19e7908d19bd194493aThomas Graf 9744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 9844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Socket Creating 9944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 10044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 10144d362409d5469aed47d19e7908d19bd194493aThomas Graf 1021155370f520cb64657e25153255cf7dc1424317fThomas Grafint genl_connect(struct nl_sock *sk) 10344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 1041155370f520cb64657e25153255cf7dc1424317fThomas Graf return nl_connect(sk, NETLINK_GENERIC); 10544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 10644d362409d5469aed47d19e7908d19bd194493aThomas Graf 10744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 10844d362409d5469aed47d19e7908d19bd194493aThomas Graf 10944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 11044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Sending 11144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 11244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 11344d362409d5469aed47d19e7908d19bd194493aThomas Graf 11444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 11544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Send trivial generic netlink message 1161155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk Netlink socket. 11744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg family Generic netlink family 11844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cmd Command 11944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg version Version 12044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags Additional netlink message flags. 12144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 12244d362409d5469aed47d19e7908d19bd194493aThomas Graf * Fills out a routing netlink request message and sends it out 12344d362409d5469aed47d19e7908d19bd194493aThomas Graf * using nl_send_simple(). 12444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 12544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code. 12644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1271155370f520cb64657e25153255cf7dc1424317fThomas Grafint genl_send_simple(struct nl_sock *sk, int family, int cmd, 12844d362409d5469aed47d19e7908d19bd194493aThomas Graf int version, int flags) 12944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 13044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct genlmsghdr hdr = { 13144d362409d5469aed47d19e7908d19bd194493aThomas Graf .cmd = cmd, 13244d362409d5469aed47d19e7908d19bd194493aThomas Graf .version = version, 13344d362409d5469aed47d19e7908d19bd194493aThomas Graf }; 13444d362409d5469aed47d19e7908d19bd194493aThomas Graf 1351155370f520cb64657e25153255cf7dc1424317fThomas Graf return nl_send_simple(sk, family, flags, &hdr, sizeof(hdr)); 13644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 13744d362409d5469aed47d19e7908d19bd194493aThomas Graf 13844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 13944d362409d5469aed47d19e7908d19bd194493aThomas Graf 14044d362409d5469aed47d19e7908d19bd194493aThomas Graf 14144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 14244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Message Parsing 14344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 14444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 14544d362409d5469aed47d19e7908d19bd194493aThomas Graf 146c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Grafint genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen) 147c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf{ 148c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf struct genlmsghdr *ghdr; 149c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 150c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf if (!nlmsg_valid_hdr(nlh, GENL_HDRLEN)) 151c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf return 0; 152c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 153c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf ghdr = nlmsg_data(nlh); 154c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf if (genlmsg_len(ghdr) < NLMSG_ALIGN(hdrlen)) 155c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf return 0; 156c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 157c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf return 1; 158c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf} 159c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 160c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Grafint genlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype, 161c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf struct nla_policy *policy) 162c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf{ 163c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf struct genlmsghdr *ghdr; 164c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 165c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf if (!genlmsg_valid_hdr(nlh, hdrlen)) 1668a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_MSG_TOOSHORT; 167c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 168c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf ghdr = nlmsg_data(nlh); 169c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf return nla_validate(genlmsg_attrdata(ghdr, hdrlen), 170c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf genlmsg_attrlen(ghdr, hdrlen), maxtype, policy); 171c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf} 172c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 173c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Grafint genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], 174c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf int maxtype, struct nla_policy *policy) 175c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf{ 176c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf struct genlmsghdr *ghdr; 177c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 178c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf if (!genlmsg_valid_hdr(nlh, hdrlen)) 1798a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_MSG_TOOSHORT; 180c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 181c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf ghdr = nlmsg_data(nlh); 182c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf return nla_parse(tb, maxtype, genlmsg_attrdata(ghdr, hdrlen), 183c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf genlmsg_attrlen(ghdr, hdrlen), policy); 184c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf} 185c8a0a5cdfba51f7de5d203aa13a97377b215515aThomas Graf 18644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 18744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get head of message payload 18844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg gnlh genetlink messsage header 18944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 19044d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid *genlmsg_data(const struct genlmsghdr *gnlh) 19144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 19244d362409d5469aed47d19e7908d19bd194493aThomas Graf return ((unsigned char *) gnlh + GENL_HDRLEN); 19344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 19444d362409d5469aed47d19e7908d19bd194493aThomas Graf 19544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 19644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get lenght of message payload 19744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg gnlh genetlink message header 19844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 19944d362409d5469aed47d19e7908d19bd194493aThomas Grafint genlmsg_len(const struct genlmsghdr *gnlh) 20044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 20144d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlmsghdr *nlh = (struct nlmsghdr *)((unsigned char *)gnlh - 20244d362409d5469aed47d19e7908d19bd194493aThomas Graf NLMSG_HDRLEN); 20344d362409d5469aed47d19e7908d19bd194493aThomas Graf return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN); 20444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 20544d362409d5469aed47d19e7908d19bd194493aThomas Graf 20644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 20744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get head of attribute data 20844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg gnlh generic netlink message header 20944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg hdrlen length of family specific header 21044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 21144d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen) 21244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 21344d362409d5469aed47d19e7908d19bd194493aThomas Graf return genlmsg_data(gnlh) + NLMSG_ALIGN(hdrlen); 21444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 21544d362409d5469aed47d19e7908d19bd194493aThomas Graf 21644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 21744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get length of attribute data 21844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg gnlh generic netlink message header 21944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg hdrlen length of family specific header 22044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 22144d362409d5469aed47d19e7908d19bd194493aThomas Grafint genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen) 22244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 22344d362409d5469aed47d19e7908d19bd194493aThomas Graf return genlmsg_len(gnlh) - NLMSG_ALIGN(hdrlen); 22444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 22544d362409d5469aed47d19e7908d19bd194493aThomas Graf 22644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 22744d362409d5469aed47d19e7908d19bd194493aThomas Graf 22844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 22944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Message Building 23044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 23144d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 23244d362409d5469aed47d19e7908d19bd194493aThomas Graf 23344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 23444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Add generic netlink header to netlink message 23544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg msg netlink message 23644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg pid netlink process id or NL_AUTO_PID 23744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg seq sequence number of message or NL_AUTO_SEQ 23844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg family generic netlink family 23944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg hdrlen length of user specific header 24044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags message flags 24144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cmd generic netlink command 24244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg version protocol version 24344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 24444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Returns pointer to user specific header. 24544d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 24644d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid *genlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, int family, 24744d362409d5469aed47d19e7908d19bd194493aThomas Graf int hdrlen, int flags, uint8_t cmd, uint8_t version) 24844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 24944d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlmsghdr *nlh; 25044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct genlmsghdr hdr = { 25144d362409d5469aed47d19e7908d19bd194493aThomas Graf .cmd = cmd, 25244d362409d5469aed47d19e7908d19bd194493aThomas Graf .version = version, 25344d362409d5469aed47d19e7908d19bd194493aThomas Graf }; 25444d362409d5469aed47d19e7908d19bd194493aThomas Graf 25544d362409d5469aed47d19e7908d19bd194493aThomas Graf nlh = nlmsg_put(msg, pid, seq, family, GENL_HDRLEN + hdrlen, flags); 25644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (nlh == NULL) 25744d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 25844d362409d5469aed47d19e7908d19bd194493aThomas Graf 25944d362409d5469aed47d19e7908d19bd194493aThomas Graf memcpy(nlmsg_data(nlh), &hdr, sizeof(hdr)); 26044d362409d5469aed47d19e7908d19bd194493aThomas Graf NL_DBG(2, "msg %p: Added generic netlink header cmd=%d version=%d\n", 26144d362409d5469aed47d19e7908d19bd194493aThomas Graf msg, cmd, version); 26244d362409d5469aed47d19e7908d19bd194493aThomas Graf 26344d362409d5469aed47d19e7908d19bd194493aThomas Graf return nlmsg_data(nlh) + GENL_HDRLEN; 26444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 26544d362409d5469aed47d19e7908d19bd194493aThomas Graf 26644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 26744d362409d5469aed47d19e7908d19bd194493aThomas Graf 26844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 269