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