~ubuntu-branches/ubuntu/trusty/libnl3/trusty

« back to all changes in this revision

Viewing changes to lib/genl/genl.c

  • Committer: Bazaar Package Importer
  • Author(s): Heiko Stuebner
  • Date: 2011-05-21 19:25:13 UTC
  • Revision ID: james.westby@ubuntu.com-20110521192513-1ieyu9w9kym4bt16
Tags: upstream-3.0
ImportĀ upstreamĀ versionĀ 3.0

Show diffs side-by-side

added added

removed removed

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