18 #include <netlink-private/netlink.h>
19 #include <netlink-private/tc.h>
20 #include <netlink/netlink.h>
21 #include <netlink/utils.h>
22 #include <netlink-private/route/tc-api.h>
23 #include <netlink/route/link.h>
26 static struct nl_object_ops act_obj_ops;
27 static struct nl_cache_ops rtnl_act_ops;
29 int rtnl_act_append(
struct rtnl_act **head,
struct rtnl_act *
new)
31 struct rtnl_act *p_act;
40 while (p_act->a_next) {
42 p_act = p_act->a_next;
45 if (count > TCA_ACT_MAX_PRIO)
52 int rtnl_act_remove(
struct rtnl_act **head,
struct rtnl_act *act)
54 struct rtnl_act *a, **ap;
56 for (ap = head; (a = *ap) != NULL; ap = &a->a_next)
65 return -NLE_OBJ_NOTFOUND;
68 static int rtnl_act_fill_one(
struct nl_msg *msg,
struct rtnl_act *act,
int order)
70 struct rtnl_tc *tc =
TC_CAST(act);
71 struct rtnl_tc_ops *ops;
79 if (tc->ce_mask & TCA_ATTR_KIND)
82 ops = rtnl_tc_get_ops(tc);
83 if (ops && (ops->to_msg_fill || ops->to_msg_fill_raw)) {
87 if (ops->to_msg_fill) {
91 if ((err = ops->to_msg_fill(tc, data, msg)) < 0)
95 }
else if ((err = ops->to_msg_fill_raw(tc, data, msg)) < 0)
105 int rtnl_act_fill(
struct nl_msg *msg,
int attrtype,
struct rtnl_act *act)
107 struct rtnl_act *p_act = act;
116 err = rtnl_act_fill_one(msg, p_act, ++order);
119 p_act = p_act->a_next;
126 static int rtnl_act_msg_build(
struct rtnl_act *act,
int type,
int flags,
127 struct nl_msg **result)
130 struct tcamsg tcahdr = {
131 .tca_family = AF_UNSPEC,
133 int err = -NLE_MSGSIZE;
139 if (
nlmsg_append(msg, &tcahdr,
sizeof(tcahdr), NLMSG_ALIGNTO) < 0)
140 goto nla_put_failure;
142 err = rtnl_act_fill(msg, TCA_ACT_TAB, act);
144 goto nla_put_failure;
154 static int act_build(
struct rtnl_act *act,
int type,
int flags,
155 struct nl_msg **result)
159 err = rtnl_act_msg_build(act, type, flags, result);
170 struct rtnl_act *rtnl_act_alloc(
void)
176 tc->tc_type = RTNL_TC_TYPE_ACT;
178 return (
struct rtnl_act *) tc;
181 void rtnl_act_put(
struct rtnl_act *act)
208 struct nl_msg **result)
210 return act_build(act, RTM_NEWACTION, flags, result);
274 struct nl_msg **result)
276 return act_build(act, RTM_NEWACTION, NLM_F_REPLACE | flags, result);
317 struct nl_msg **result)
319 return act_build(act, RTM_DELACTION, flags, result);
366 static void act_dump_line(
struct rtnl_tc *tc,
struct nl_dump_params *p)
370 void rtnl_act_put_all(
struct rtnl_act **head)
372 struct rtnl_act *curr, *next;
383 int rtnl_act_parse(
struct rtnl_act **head,
struct nlattr *tb)
385 struct rtnl_tc_ops *ops;
386 struct nlattr *tb2[TCA_ACT_MAX + 1];
387 struct nlattr *nla[TCA_ACT_MAX_PRIO + 1];
388 char kind[TCKINDSIZ];
392 NLMSG_ALIGN(
nla_len(tb)), NULL);
396 for (i = 1; i <= TCA_ACT_MAX_PRIO && nla[i]; i++) {
397 struct rtnl_act *act;
400 act = rtnl_act_alloc();
411 if (tb2[TCA_ACT_KIND] == NULL) {
412 err = -NLE_MISSING_ATTR;
416 nla_strlcpy(kind, tb2[TCA_ACT_KIND],
sizeof(kind));
419 if (tb2[TCA_ACT_OPTIONS]) {
425 tc->ce_mask |= TCA_ATTR_OPTS;
428 ops = rtnl_tc_get_ops(tc);
429 if (ops && ops->to_msg_parser) {
437 err = ops->to_msg_parser(tc, data);
441 err = rtnl_act_append(head, act);
448 rtnl_act_put_all(head);
453 static int rtnl_act_msg_parse(
struct nlmsghdr *n,
struct rtnl_act **act)
455 struct rtnl_tc *tc =
TC_CAST(act);
456 struct nl_cache *link_cache;
457 struct nlattr *tb[TCAA_MAX + 1];
461 tc->ce_msgtype = n->nlmsg_type;
463 err =
nlmsg_parse(n,
sizeof(*tm), tb, TCAA_MAX, NULL);
468 tc->tc_family = tm->tca_family;
470 if (tb[TCA_ACT_TAB] == NULL)
471 return -NLE_MISSING_ATTR;
473 err = rtnl_act_parse(act, tb[TCA_ACT_TAB]);
477 if ((link_cache = __nl_cache_mngt_require(
"route/link"))) {
490 static int act_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
491 struct nlmsghdr *nlh,
struct nl_parser_param *pp)
493 struct rtnl_act *act, *p_act;
496 if (!(act = rtnl_act_alloc()))
499 if ((err = rtnl_act_msg_parse(nlh, &act)) < 0)
504 err = pp->pp_cb(OBJ_CAST(act), pp);
507 p_act = p_act->a_next;
515 static int act_request_update(
struct nl_cache *cache,
struct nl_sock *sk)
517 struct tcamsg tcahdr = {
518 .tca_family = AF_UNSPEC,
525 static struct rtnl_tc_type_ops act_ops = {
526 .tt_type = RTNL_TC_TYPE_ACT,
527 .tt_dump_prefix =
"act",
533 static struct nl_cache_ops rtnl_act_ops = {
534 .co_name =
"route/act",
535 .co_hdrsize =
sizeof(
struct tcmsg),
537 { RTM_NEWACTION, NL_ACT_NEW,
"new" },
538 { RTM_DELACTION, NL_ACT_DEL,
"del" },
539 { RTM_GETACTION, NL_ACT_GET,
"get" },
540 END_OF_MSGTYPES_LIST,
542 .co_protocol = NETLINK_ROUTE,
543 .co_request_update = act_request_update,
544 .co_msg_parser = act_msg_parser,
545 .co_obj_ops = &act_obj_ops,
548 static struct nl_object_ops act_obj_ops = {
549 .oo_name =
"route/act",
550 .oo_size =
sizeof(
struct rtnl_act),
551 .oo_free_data = rtnl_tc_free_data,
552 .oo_clone = rtnl_tc_clone,
558 .oo_compare = rtnl_tc_compare,
559 .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
562 static void __init act_init(
void)
564 rtnl_tc_type_register(&act_ops);
568 static void __exit act_exit(
void)
571 rtnl_tc_type_unregister(&act_ops);