libnl 1.1.4
genl.c
1/*
2 * lib/genl/genl.c Generic Netlink
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation version 2.1
7 * of the License.
8 *
9 * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
10 */
11
12/**
13 * @ingroup nlfam
14 * @defgroup genl Generic Netlink
15 *
16 * @par Message Format
17 * @code
18 * <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) --->
19 * +----------------------------+- - -+- - - - - - - - - - -+- - -+
20 * | Header | Pad | Payload | Pad |
21 * | struct nlmsghdr | | | |
22 * +----------------------------+- - -+- - - - - - - - - - -+- - -+
23 * @endcode
24 * @code
25 * <-------- GENL_HDRLEN -------> <--- hdrlen -->
26 * <------- genlmsg_len(ghdr) ------>
27 * +------------------------+- - -+---------------+- - -+------------+
28 * | Generic Netlink Header | Pad | Family Header | Pad | Attributes |
29 * | struct genlmsghdr | | | | |
30 * +------------------------+- - -+---------------+- - -+------------+
31 * genlmsg_data(ghdr)--------------^ ^
32 * genlmsg_attrdata(ghdr, hdrlen)-------------------------
33 * @endcode
34 *
35 * @par Example
36 * @code
37 * #include <netlink/netlink.h>
38 * #include <netlink/genl/genl.h>
39 * #include <netlink/genl/ctrl.h>
40 *
41 * struct nl_handle *sock;
42 * struct nl_msg *msg;
43 * int family;
44 *
45 * // Allocate a new netlink socket
46 * sock = nl_handle_alloc();
47 *
48 * // Connect to generic netlink socket on kernel side
49 * genl_connect(sock);
50 *
51 * // Ask kernel to resolve family name to family id
52 * family = genl_ctrl_resolve(sock, "generic_netlink_family_name");
53 *
54 * // Construct a generic netlink by allocating a new message, fill in
55 * // the header and append a simple integer attribute.
56 * msg = nlmsg_alloc();
57 * genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_ECHO,
58 * CMD_FOO_GET, FOO_VERSION);
59 * nla_put_u32(msg, ATTR_FOO, 123);
60 *
61 * // Send message over netlink socket
62 * nl_send_auto_complete(sock, msg);
63 *
64 * // Free message
65 * nlmsg_free(msg);
66 *
67 * // Prepare socket to receive the answer by specifying the callback
68 * // function to be called for valid messages.
69 * nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, parse_cb, NULL);
70 *
71 * // Wait for the answer and receive it
72 * nl_recvmsgs_default(sock);
73 *
74 * static int parse_cb(struct nl_msg *msg, void *arg)
75 * {
76 * struct nlmsghdr *nlh = nlmsg_hdr(msg);
77 * struct nlattr *attrs[ATTR_MAX+1];
78 *
79 * // Validate message and parse attributes
80 * genlmsg_parse(nlh, 0, attrs, ATTR_MAX, policy);
81 *
82 * if (attrs[ATTR_FOO]) {
83 * uint32_t value = nla_get_u32(attrs[ATTR_FOO]);
84 * ...
85 * }
86 *
87 * return 0;
88 * }
89 * @endcode
90 * @{
91 */
92
93#include <netlink-generic.h>
94#include <netlink/netlink.h>
95#include <netlink/genl/genl.h>
96#include <netlink/utils.h>
97
98/**
99 * @name Socket Creating
100 * @{
101 */
102
103int genl_connect(struct nl_handle *handle)
104{
105 return nl_connect(handle, NETLINK_GENERIC);
106}
107
108/** @} */
109
110/**
111 * @name Sending
112 * @{
113 */
114
115/**
116 * Send trivial generic netlink message
117 * @arg handle Netlink handle.
118 * @arg family Generic netlink family
119 * @arg cmd Command
120 * @arg version Version
121 * @arg flags Additional netlink message flags.
122 *
123 * Fills out a routing netlink request message and sends it out
124 * using nl_send_simple().
125 *
126 * @return 0 on success or a negative error code.
127 */
128int genl_send_simple(struct nl_handle *handle, int family, int cmd,
129 int version, int flags)
130{
131 struct genlmsghdr hdr = {
132 .cmd = cmd,
133 .version = version,
134 };
135
136 return nl_send_simple(handle, family, flags, &hdr, sizeof(hdr));
137}
138
139/** @} */
140
141
142/**
143 * @name Message Parsing
144 * @{
145 */
146
147int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen)
148{
149 struct genlmsghdr *ghdr;
150
151 if (!nlmsg_valid_hdr(nlh, GENL_HDRLEN))
152 return 0;
153
154 ghdr = nlmsg_data(nlh);
155 if (genlmsg_len(ghdr) < NLMSG_ALIGN(hdrlen))
156 return 0;
157
158 return 1;
159}
160
161int genlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype,
162 struct nla_policy *policy)
163{
164 struct genlmsghdr *ghdr;
165
166 if (!genlmsg_valid_hdr(nlh, hdrlen))
167 return nl_errno(EINVAL);
168
169 ghdr = nlmsg_data(nlh);
170 return nla_validate(genlmsg_attrdata(ghdr, hdrlen),
171 genlmsg_attrlen(ghdr, hdrlen), maxtype, policy);
172}
173
174int genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
175 int maxtype, struct nla_policy *policy)
176{
177 struct genlmsghdr *ghdr;
178
179 if (!genlmsg_valid_hdr(nlh, hdrlen))
180 return nl_errno(EINVAL);
181
182 ghdr = nlmsg_data(nlh);
183 return nla_parse(tb, maxtype, genlmsg_attrdata(ghdr, hdrlen),
184 genlmsg_attrlen(ghdr, hdrlen), policy);
185}
186
187/**
188 * Get head of message payload
189 * @arg gnlh genetlink messsage header
190 */
191void *genlmsg_data(const struct genlmsghdr *gnlh)
192{
193 return ((unsigned char *) gnlh + GENL_HDRLEN);
194}
195
196/**
197 * Get lenght of message payload
198 * @arg gnlh genetlink message header
199 */
200int genlmsg_len(const struct genlmsghdr *gnlh)
201{
202 struct nlmsghdr *nlh = (struct nlmsghdr *)((unsigned char *)gnlh -
203 NLMSG_HDRLEN);
204 return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN);
205}
206
207/**
208 * Get head of attribute data
209 * @arg gnlh generic netlink message header
210 * @arg hdrlen length of family specific header
211 */
212struct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen)
213{
214 return genlmsg_data(gnlh) + NLMSG_ALIGN(hdrlen);
215}
216
217/**
218 * Get length of attribute data
219 * @arg gnlh generic netlink message header
220 * @arg hdrlen length of family specific header
221 */
222int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen)
223{
224 return genlmsg_len(gnlh) - NLMSG_ALIGN(hdrlen);
225}
226
227/** @} */
228
229/**
230 * @name Message Building
231 * @{
232 */
233
234/**
235 * Add generic netlink header to netlink message
236 * @arg msg netlink message
237 * @arg pid netlink process id or NL_AUTO_PID
238 * @arg seq sequence number of message or NL_AUTO_SEQ
239 * @arg family generic netlink family
240 * @arg hdrlen length of user specific header
241 * @arg flags message flags
242 * @arg cmd generic netlink command
243 * @arg version protocol version
244 *
245 * Returns pointer to user specific header.
246 */
247void *genlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, int family,
248 int hdrlen, int flags, uint8_t cmd, uint8_t version)
249{
250 struct nlmsghdr *nlh;
251 struct genlmsghdr hdr = {
252 .cmd = cmd,
253 .version = version,
254 };
255
256 nlh = nlmsg_put(msg, pid, seq, family, GENL_HDRLEN + hdrlen, flags);
257 if (nlh == NULL)
258 return NULL;
259
260 memcpy(nlmsg_data(nlh), &hdr, sizeof(hdr));
261 NL_DBG(2, "msg %p: Added generic netlink header cmd=%d version=%d\n",
262 msg, cmd, version);
263
264 return nlmsg_data(nlh) + GENL_HDRLEN;
265}
266
267/** @} */
268
269/** @} */
int nla_validate(struct nlattr *head, int len, int maxtype, struct nla_policy *policy)
Validate a stream of attributes.
Definition: attr.c:327
int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, struct nla_policy *policy)
Parse a stream of attributes into a tb buffer.
Definition: attr.c:262
void * genlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, int family, int hdrlen, int flags, uint8_t cmd, uint8_t version)
Add generic netlink header to netlink message.
Definition: genl.c:247
struct nlattr * genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen)
Get head of attribute data.
Definition: genl.c:212
int genlmsg_len(const struct genlmsghdr *gnlh)
Get lenght of message payload.
Definition: genl.c:200
int genl_send_simple(struct nl_handle *handle, int family, int cmd, int version, int flags)
Send trivial generic netlink message.
Definition: genl.c:128
void * genlmsg_data(const struct genlmsghdr *gnlh)
Get head of message payload.
Definition: genl.c:191
int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen)
Get length of attribute data.
Definition: genl.c:222
void * nlmsg_data(const struct nlmsghdr *nlh)
head of message payload
Definition: msg.c:218
struct nlmsghdr * nlmsg_put(struct nl_msg *n, uint32_t pid, uint32_t seq, int type, int payload, int flags)
Add a netlink message header to a netlink message.
Definition: msg.c:610
int nl_connect(struct nl_handle *handle, int protocol)
Create and connect netlink socket.
Definition: nl.c:191
int nl_send_simple(struct nl_handle *handle, int type, int flags, void *buf, size_t size)
Send simple netlink message using nl_send_auto_complete()
Definition: nl.c:410
attribute validation policy
Definition: attr.h:73
Netlink message header.
uint32_t nlmsg_len
Length of message including header.