libnl  1.1
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 
103 int 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  */
128 int 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 
147 int 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 
161 int 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 
174 int 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  */
191 void *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  */
200 int 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  */
212 struct 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  */
222 int 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  */
247 void *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:328
void * nlmsg_data(const struct nlmsghdr *nlh)
head of message payload
Definition: msg.c:218
attribute validation policy
Definition: attr.h:73
Netlink message header.
uint32_t nlmsg_len
Length of message including header.
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:613
struct nlattr * genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen)
Get head of attribute data.
Definition: genl.c:212
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
int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen)
Get length of attribute data.
Definition: genl.c:222
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_data(const struct genlmsghdr *gnlh)
Get head of message payload.
Definition: genl.c:191
int nl_connect(struct nl_handle *handle, int protocol)
Create and connect netlink socket.
Definition: nl.c:191
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_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