libnl 1.1.4
classifier.c
1/*
2 * lib/route/classifier.c Classifier
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 tc
14 * @defgroup cls Classifiers
15 *
16 * @par Classifier Identification
17 * - protocol
18 * - priority
19 * - parent
20 * - interface
21 * - kind
22 * - handle
23 *
24 * @{
25 */
26
27#include <netlink-local.h>
28#include <netlink-tc.h>
29#include <netlink/netlink.h>
30#include <netlink/utils.h>
31#include <netlink/route/tc.h>
32#include <netlink/route/classifier.h>
33#include <netlink/route/classifier-modules.h>
34#include <netlink/route/link.h>
35
36static struct nl_cache_ops rtnl_cls_ops;
37
38static int cls_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
39 struct nlmsghdr *nlh, struct nl_parser_param *pp)
40{
41 int err;
42 struct rtnl_cls *cls;
43 struct rtnl_cls_ops *cops;
44
45 cls = rtnl_cls_alloc();
46 if (!cls) {
47 err = nl_errno(ENOMEM);
48 goto errout;
49 }
50 cls->ce_msgtype = nlh->nlmsg_type;
51
52 err = tca_msg_parser(nlh, (struct rtnl_tca *) cls);
53 if (err < 0)
54 goto errout_free;
55
56 cls->c_prio = TC_H_MAJ(cls->c_info) >> 16;
57 cls->c_protocol = ntohs(TC_H_MIN(cls->c_info));
58
59 cops = rtnl_cls_lookup_ops(cls);
60 if (cops && cops->co_msg_parser) {
61 err = cops->co_msg_parser(cls);
62 if (err < 0)
63 goto errout_free;
64 }
65
66 err = pp->pp_cb((struct nl_object *) cls, pp);
67 if (err < 0)
68 goto errout_free;
69
70 err = P_ACCEPT;
71
72errout_free:
73 rtnl_cls_put(cls);
74errout:
75 return err;
76}
77
78static int cls_request_update(struct nl_cache *cache, struct nl_handle *handle)
79{
80 struct tcmsg tchdr = {
81 .tcm_family = AF_UNSPEC,
82 .tcm_ifindex = cache->c_iarg1,
83 .tcm_parent = cache->c_iarg2,
84 };
85
86 return nl_send_simple(handle, RTM_GETTFILTER, NLM_F_DUMP, &tchdr,
87 sizeof(tchdr));
88}
89
90
91static struct nl_msg *cls_build(struct rtnl_cls *cls, int type, int flags)
92{
93 struct nl_msg *msg;
94 struct rtnl_cls_ops *cops;
95 int err, prio, proto;
96 struct tcmsg *tchdr;
97
98 msg = tca_build_msg((struct rtnl_tca *) cls, type, flags);
99 if (!msg)
100 goto errout;
101
102 tchdr = nlmsg_data(nlmsg_hdr(msg));
103 prio = rtnl_cls_get_prio(cls);
104 proto = rtnl_cls_get_protocol(cls);
105 tchdr->tcm_info = TC_H_MAKE(prio << 16, htons(proto)),
106
107 cops = rtnl_cls_lookup_ops(cls);
108 if (cops && cops->co_get_opts) {
109 struct nl_msg *opts;
110
111 opts = cops->co_get_opts(cls);
112 if (opts) {
113 err = nla_put_nested(msg, TCA_OPTIONS, opts);
114 nlmsg_free(opts);
115 if (err < 0)
116 goto errout;
117 }
118 }
119
120 return msg;
121errout:
122 nlmsg_free(msg);
123 return NULL;
124}
125
126/**
127 * @name Classifier Addition/Modification/Deletion
128 * @{
129 */
130
131/**
132 * Build a netlink message to add a new classifier
133 * @arg cls classifier to add
134 * @arg flags additional netlink message flags
135 *
136 * Builds a new netlink message requesting an addition of a classifier
137 * The netlink message header isn't fully equipped with all relevant
138 * fields and must be sent out via nl_send_auto_complete() or
139 * supplemented as needed. \a classifier must contain the attributes of
140 * the new classifier set via \c rtnl_cls_set_* functions. \a opts
141 * may point to the clsasifier specific options.
142 *
143 * @return New netlink message
144 */
145struct nl_msg * rtnl_cls_build_add_request(struct rtnl_cls *cls, int flags)
146{
147 return cls_build(cls, RTM_NEWTFILTER, NLM_F_CREATE | flags);
148}
149
150/**
151 * Add a new classifier
152 * @arg handle netlink handle
153 * @arg cls classifier to add
154 * @arg flags additional netlink message flags
155 *
156 * Builds a netlink message by calling rtnl_cls_build_add_request(),
157 * sends the request to the kernel and waits for the next ACK to be
158 * received and thus blocks until the request has been processed.
159 *
160 * @return 0 on sucess or a negative error if an error occured.
161 */
162int rtnl_cls_add(struct nl_handle *handle, struct rtnl_cls *cls, int flags)
163{
164 int err;
165 struct nl_msg *msg;
166
167 msg = rtnl_cls_build_add_request(cls, flags);
168 if (!msg)
169 return nl_errno(ENOMEM);
170
171 err = nl_send_auto_complete(handle, msg);
172 nlmsg_free(msg);
173 if (err < 0)
174 return err;
175
176 return nl_wait_for_ack(handle);
177}
178
179/**
180 * Build a netlink message to change classifier attributes
181 * @arg cls classifier to change
182 * @arg flags additional netlink message flags
183 *
184 * Builds a new netlink message requesting a change of a neigh
185 * attributes. The netlink message header isn't fully equipped with
186 * all relevant fields and must thus be sent out via nl_send_auto_complete()
187 * or supplemented as needed.
188 *
189 * @return The netlink message
190 */
191struct nl_msg *rtnl_cls_build_change_request(struct rtnl_cls *cls, int flags)
192{
193 return cls_build(cls, RTM_NEWTFILTER, NLM_F_REPLACE | flags);
194}
195
196/**
197 * Change a classifier
198 * @arg handle netlink handle
199 * @arg cls classifier to change
200 * @arg flags additional netlink message flags
201 *
202 * Builds a netlink message by calling rtnl_cls_build_change_request(),
203 * sends the request to the kernel and waits for the next ACK to be
204 * received and thus blocks until the request has been processed.
205 *
206 * @return 0 on sucess or a negative error if an error occured.
207 */
208int rtnl_cls_change(struct nl_handle *handle, struct rtnl_cls *cls,
209 int flags)
210{
211 int err;
212 struct nl_msg *msg;
213
214 msg = rtnl_cls_build_change_request(cls, flags);
215 if (!msg)
216 return nl_errno(ENOMEM);
217
218 err = nl_send_auto_complete(handle, msg);
219 nlmsg_free(msg);
220 if (err < 0)
221 return err;
222
223 return nl_wait_for_ack(handle);
224}
225
226/**
227 * Build a netlink request message to delete a classifier
228 * @arg cls classifier to delete
229 * @arg flags additional netlink message flags
230 *
231 * Builds a new netlink message requesting a deletion of a classifier.
232 * The netlink message header isn't fully equipped with all relevant
233 * fields and must thus be sent out via nl_send_auto_complete()
234 * or supplemented as needed.
235 *
236 * @return New netlink message
237 */
238struct nl_msg *rtnl_cls_build_delete_request(struct rtnl_cls *cls, int flags)
239{
240 return cls_build(cls, RTM_DELTFILTER, flags);
241}
242
243
244/**
245 * Delete a classifier
246 * @arg handle netlink handle
247 * @arg cls classifier to delete
248 * @arg flags additional netlink message flags
249 *
250 * Builds a netlink message by calling rtnl_cls_build_delete_request(),
251 * sends the request to the kernel and waits for the next ACK to be
252 * received and thus blocks until the request has been processed.
253 *
254 * @return 0 on sucess or a negative error if an error occured.
255 */
256int rtnl_cls_delete(struct nl_handle *handle, struct rtnl_cls *cls, int flags)
257{
258 int err;
259 struct nl_msg *msg;
260
261 msg = rtnl_cls_build_delete_request(cls, flags);
262 if (!msg)
263 return nl_errno(ENOMEM);
264
265 err = nl_send_auto_complete(handle, msg);
266 nlmsg_free(msg);
267 if (err < 0)
268 return err;
269
270 return nl_wait_for_ack(handle);
271}
272
273/** @} */
274
275/**
276 * @name Cache Management
277 * @{
278 */
279
280/**
281 * Build a classifier cache including all classifiers attached to the
282 * specified class/qdisc on eht specified interface.
283 * @arg handle netlink handle
284 * @arg ifindex interface index of the link the classes are
285 * attached to.
286 * @arg parent parent qdisc/class
287 *
288 * Allocates a new cache, initializes it properly and updates it to
289 * include all classes attached to the specified interface.
290 *
291 * @note The caller is responsible for destroying and freeing the
292 * cache after using it.
293 * @return The cache or NULL if an error has occured.
294 */
295struct nl_cache *rtnl_cls_alloc_cache(struct nl_handle *handle,
296 int ifindex, uint32_t parent)
297{
298 struct nl_cache * cache;
299
301 if (cache == NULL)
302 return NULL;
303
304 cache->c_iarg1 = ifindex;
305 cache->c_iarg2 = parent;
306
307 if (handle && nl_cache_refill(handle, cache) < 0) {
308 nl_cache_free(cache);
309 return NULL;
310 }
311
312 return cache;
313}
314
315/** @} */
316
317static struct nl_cache_ops rtnl_cls_ops = {
318 .co_name = "route/cls",
319 .co_hdrsize = sizeof(struct tcmsg),
320 .co_msgtypes = {
321 { RTM_NEWTFILTER, NL_ACT_NEW, "new" },
322 { RTM_DELTFILTER, NL_ACT_DEL, "del" },
323 { RTM_GETTFILTER, NL_ACT_GET, "get" },
324 END_OF_MSGTYPES_LIST,
325 },
326 .co_protocol = NETLINK_ROUTE,
327 .co_request_update = cls_request_update,
328 .co_msg_parser = cls_msg_parser,
329 .co_obj_ops = &cls_obj_ops,
330};
331
332static void __init cls_init(void)
333{
335}
336
337static void __exit cls_exit(void)
338{
340}
341
342/** @} */
int nla_put_nested(struct nl_msg *n, int attrtype, struct nl_msg *nested)
Add a nested netlink attribute to a netlink message.
Definition: attr.c:535
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
Definition: cache_mngt.c:261
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
Definition: cache_mngt.c:226
void nl_cache_free(struct nl_cache *cache)
Free a cache.
Definition: cache.c:277
struct nl_cache * nl_cache_alloc(struct nl_cache_ops *ops)
Allocate an empty cache.
Definition: cache.c:170
int nl_cache_refill(struct nl_handle *handle, struct nl_cache *cache)
(Re)fill a cache with the contents in the kernel.
Definition: cache.c:680
struct rtnl_cls_ops * rtnl_cls_lookup_ops(struct rtnl_cls *cls)
Lookup classifier operations for a classifier object.
Definition: cls_api.c:92
struct nl_msg * rtnl_cls_build_change_request(struct rtnl_cls *cls, int flags)
Build a netlink message to change classifier attributes.
Definition: classifier.c:191
struct nl_msg * rtnl_cls_build_add_request(struct rtnl_cls *cls, int flags)
Build a netlink message to add a new classifier.
Definition: classifier.c:145
struct nl_msg * rtnl_cls_build_delete_request(struct rtnl_cls *cls, int flags)
Build a netlink request message to delete a classifier.
Definition: classifier.c:238
int rtnl_cls_change(struct nl_handle *handle, struct rtnl_cls *cls, int flags)
Change a classifier.
Definition: classifier.c:208
int rtnl_cls_add(struct nl_handle *handle, struct rtnl_cls *cls, int flags)
Add a new classifier.
Definition: classifier.c:162
int rtnl_cls_delete(struct nl_handle *handle, struct rtnl_cls *cls, int flags)
Delete a classifier.
Definition: classifier.c:256
struct nl_cache * rtnl_cls_alloc_cache(struct nl_handle *handle, int ifindex, uint32_t parent)
Build a classifier cache including all classifiers attached to the specified class/qdisc on eht speci...
Definition: classifier.c:295
struct nlmsghdr * nlmsg_hdr(struct nl_msg *n)
Return actual netlink message.
Definition: msg.c:643
void nlmsg_free(struct nl_msg *n)
Free a netlink message.
Definition: msg.c:656
#define NLM_F_CREATE
Create config object if it doesn't already exist.
void * nlmsg_data(const struct nlmsghdr *nlh)
head of message payload
Definition: msg.c:218
#define NLM_F_REPLACE
Replace existing matching config object with this request.
#define NLM_F_DUMP
Dump all entries.
int nl_send_auto_complete(struct nl_handle *handle, struct nl_msg *msg)
Send netlink message and check & extend header values as needed.
Definition: nl.c:373
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 nl_wait_for_ack(struct nl_handle *handle)
Wait for ACK.
Definition: nl.c:801
Cache Operations.
Definition: cache-api.h:164
Netlink message header.
uint16_t nlmsg_type
Message type (content type)
Classifier operations.
int(* co_msg_parser)(struct rtnl_cls *)
TCA_OPTIONS message parser.
struct nl_msg *(* co_get_opts)(struct rtnl_cls *)
Must return the contents supposed to be in TCA_OPTIONS.
Netlink socket address.
Definition: netlink-kernel.h:9