libnl  3.2.24-rc1
basic.c
1 /*
2  * lib/route/cls/basic.c Basic 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) 2008-2013 Thomas Graf <tgraf@suug.ch>
10  */
11 
12 /**
13  * @ingroup cls
14  * @defgroup cls_basic Basic Classifier
15  *
16  * @par Introduction
17  * The basic classifier is the simplest form of a classifier. It does
18  * not have any special classification capabilities, instead it can be
19  * used to classify exclusively based on extended matches or to
20  * create a "catch-all" filter.
21  *
22  * @{
23  */
24 
25 #include <netlink-private/netlink.h>
26 #include <netlink-private/tc.h>
27 #include <netlink/netlink.h>
28 #include <netlink-private/route/tc-api.h>
29 #include <netlink/route/classifier.h>
30 #include <netlink/route/action.h>
31 #include <netlink/route/cls/basic.h>
32 #include <netlink/route/cls/ematch.h>
33 
34 struct rtnl_basic
35 {
36  uint32_t b_target;
37  struct rtnl_ematch_tree * b_ematch;
38  int b_mask;
39  struct rtnl_act * b_act;
40 };
41 
42 /** @cond SKIP */
43 #define BASIC_ATTR_TARGET 0x001
44 #define BASIC_ATTR_EMATCH 0x002
45 #define BASIC_ATTR_ACTION 0x004
46 /** @endcond */
47 
48 static struct nla_policy basic_policy[TCA_BASIC_MAX+1] = {
49  [TCA_BASIC_CLASSID] = { .type = NLA_U32 },
50  [TCA_BASIC_EMATCHES] = { .type = NLA_NESTED },
51 };
52 
53 static int basic_clone(void *_dst, void *_src)
54 {
55  return -NLE_OPNOTSUPP;
56 }
57 
58 static void basic_free_data(struct rtnl_tc *tc, void *data)
59 {
60  struct rtnl_basic *b = data;
61 
62  if (!b)
63  return;
64 
65  if (b->b_act)
66  rtnl_act_put_all(&b->b_act);
67  rtnl_ematch_tree_free(b->b_ematch);
68 }
69 
70 static int basic_msg_parser(struct rtnl_tc *tc, void *data)
71 {
72  struct nlattr *tb[TCA_BASIC_MAX + 1];
73  struct rtnl_basic *b = data;
74  int err;
75 
76  err = tca_parse(tb, TCA_BASIC_MAX, tc, basic_policy);
77  if (err < 0)
78  return err;
79 
80  if (tb[TCA_BASIC_CLASSID]) {
81  b->b_target = nla_get_u32(tb[TCA_BASIC_CLASSID]);
82  b->b_mask |= BASIC_ATTR_TARGET;
83  }
84 
85  if (tb[TCA_BASIC_EMATCHES]) {
86  if ((err = rtnl_ematch_parse_attr(tb[TCA_BASIC_EMATCHES],
87  &b->b_ematch)) < 0)
88  return err;
89 
90  if (b->b_ematch)
91  b->b_mask |= BASIC_ATTR_EMATCH;
92  }
93  if (tb[TCA_BASIC_ACT]) {
94  b->b_mask |= BASIC_ATTR_ACTION;
95  err = rtnl_act_parse(&b->b_act, tb[TCA_BASIC_ACT]);
96  if (err)
97  return err;
98  }
99 
100  return 0;
101 }
102 
103 static void basic_dump_line(struct rtnl_tc *tc, void *data,
104  struct nl_dump_params *p)
105 {
106  struct rtnl_basic *b = data;
107  char buf[32];
108 
109  if (!b)
110  return;
111 
112  if (b->b_mask & BASIC_ATTR_EMATCH)
113  nl_dump(p, " ematch");
114  else
115  nl_dump(p, " match-all");
116 
117  if (b->b_mask & BASIC_ATTR_TARGET)
118  nl_dump(p, " target %s",
119  rtnl_tc_handle2str(b->b_target, buf, sizeof(buf)));
120 }
121 
122 static void basic_dump_details(struct rtnl_tc *tc, void *data,
123  struct nl_dump_params *p)
124 {
125  struct rtnl_basic *b = data;
126 
127  if (!b)
128  return;
129 
130  if (b->b_mask & BASIC_ATTR_EMATCH) {
131  nl_dump_line(p, " ematch ");
132  rtnl_ematch_tree_dump(b->b_ematch, p);
133  } else
134  nl_dump(p, "no options.\n");
135 }
136 
137 static int basic_msg_fill(struct rtnl_tc *tc, void *data,
138  struct nl_msg *msg)
139 {
140  struct rtnl_basic *b = data;
141 
142  if (!b)
143  return 0;
144 
145  if (!(b->b_mask & BASIC_ATTR_TARGET))
146  return -NLE_MISSING_ATTR;
147 
148  NLA_PUT_U32(msg, TCA_BASIC_CLASSID, b->b_target);
149 
150  if (b->b_mask & BASIC_ATTR_EMATCH &&
151  rtnl_ematch_fill_attr(msg, TCA_BASIC_EMATCHES, b->b_ematch) < 0)
152  goto nla_put_failure;
153 
154  if (b->b_mask & BASIC_ATTR_ACTION) {
155  int err;
156 
157  err = rtnl_act_fill(msg, TCA_BASIC_ACT, b->b_act);
158  if (err)
159  return err;
160  }
161 
162  return 0;
163 
164 nla_put_failure:
165  return -NLE_NOMEM;
166 }
167 
168 /**
169  * @name Attribute Modifications
170  * @{
171  */
172 
173 void rtnl_basic_set_target(struct rtnl_cls *cls, uint32_t target)
174 {
175  struct rtnl_basic *b;
176 
177  if (!(b = rtnl_tc_data(TC_CAST(cls))))
178  return;
179 
180  b->b_target = target;
181  b->b_mask |= BASIC_ATTR_TARGET;
182 }
183 
184 uint32_t rtnl_basic_get_target(struct rtnl_cls *cls)
185 {
186  struct rtnl_basic *b;
187 
188  if (!(b = rtnl_tc_data(TC_CAST(cls))))
189  return 0;
190 
191  return b->b_target;
192 }
193 
194 void rtnl_basic_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree)
195 {
196  struct rtnl_basic *b;
197 
198  if (!(b = rtnl_tc_data(TC_CAST(cls))))
199  return;
200 
201  if (b->b_ematch) {
202  rtnl_ematch_tree_free(b->b_ematch);
203  b->b_mask &= ~BASIC_ATTR_EMATCH;
204  }
205 
206  b->b_ematch = tree;
207 
208  if (tree)
209  b->b_mask |= BASIC_ATTR_EMATCH;
210 }
211 
212 struct rtnl_ematch_tree *rtnl_basic_get_ematch(struct rtnl_cls *cls)
213 {
214  struct rtnl_basic *b;
215 
216  if (!(b = rtnl_tc_data(TC_CAST(cls))))
217  return NULL;
218 
219  return b->b_ematch;
220 }
221 
222 int rtnl_basic_add_action(struct rtnl_cls *cls, struct rtnl_act *act)
223 {
224  struct rtnl_basic *b;
225 
226  if (!act)
227  return 0;
228 
229  if (!(b = rtnl_tc_data(TC_CAST(cls))))
230  return -NLE_NOMEM;
231 
232  b->b_mask |= BASIC_ATTR_ACTION;
233  return rtnl_act_append(&b->b_act, act);
234 }
235 
236 int rtnl_basic_del_action(struct rtnl_cls *cls, struct rtnl_act *act)
237 {
238  struct rtnl_basic *b;
239  int ret;
240 
241  if (!act)
242  return 0;
243 
244  if (!(b = rtnl_tc_data(TC_CAST(cls))))
245  return -NLE_NOMEM;
246 
247  if (!(b->b_mask & BASIC_ATTR_ACTION))
248  return -NLE_INVAL;
249  ret = rtnl_act_remove(&b->b_act, act);
250  if (!b->b_act)
251  b->b_mask &= ~BASIC_ATTR_ACTION;
252  return ret;
253 }
254 /** @} */
255 
256 static struct rtnl_tc_ops basic_ops = {
257  .to_kind = "basic",
258  .to_type = RTNL_TC_TYPE_CLS,
259  .to_size = sizeof(struct rtnl_basic),
260  .to_msg_parser = basic_msg_parser,
261  .to_clone = basic_clone,
262  .to_free_data = basic_free_data,
263  .to_msg_fill = basic_msg_fill,
264  .to_dump = {
265  [NL_DUMP_LINE] = basic_dump_line,
266  [NL_DUMP_DETAILS] = basic_dump_details,
267  },
268 };
269 
270 static void __init basic_init(void)
271 {
272  rtnl_tc_register(&basic_ops);
273 }
274 
275 static void __exit basic_exit(void)
276 {
277  rtnl_tc_unregister(&basic_ops);
278 }
279 
280 /** @} */