xref: /aosp_15_r20/external/libnl/lib/route/act/mirred.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3  * Copyright (c) 2013 Cong Wang <[email protected]>
4  */
5 
6 /**
7  * @ingroup act
8  * @defgroup act_mirred Mirror and Redirect
9  *
10  * @{
11  */
12 
13 #include "nl-default.h"
14 
15 #include <netlink/netlink.h>
16 #include <netlink/attr.h>
17 #include <netlink/utils.h>
18 #include <netlink/route/act/mirred.h>
19 
20 #include "tc-api.h"
21 
22 struct rtnl_mirred {
23 	struct tc_mirred m_parm;
24 };
25 
26 static struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
27 	[TCA_MIRRED_PARMS]      = { .minlen = sizeof(struct tc_mirred) },
28 };
29 
mirred_msg_parser(struct rtnl_tc * tc,void * data)30 static int mirred_msg_parser(struct rtnl_tc *tc, void *data)
31 {
32 	struct rtnl_mirred *u = data;
33 	struct nlattr *tb[TCA_MIRRED_MAX + 1];
34 	int err;
35 
36 	err = tca_parse(tb, TCA_MIRRED_MAX, tc, mirred_policy);
37 	if (err < 0)
38 		return err;
39 
40 	if (!tb[TCA_MIRRED_PARMS])
41 		return -NLE_MISSING_ATTR;
42 
43 	nla_memcpy(&u->m_parm, tb[TCA_MIRRED_PARMS], sizeof(u->m_parm));
44 	return 0;
45 }
46 
mirred_free_data(struct rtnl_tc * tc,void * data)47 static void mirred_free_data(struct rtnl_tc *tc, void *data)
48 {
49 }
50 
mirred_dump_line(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)51 static void mirred_dump_line(struct rtnl_tc *tc, void *data,
52 			  struct nl_dump_params *p)
53 {
54 	struct rtnl_mirred *u = data;
55 	if (!u)
56 		return;
57 
58 	nl_dump(p, " index %u", u->m_parm.ifindex);
59 
60 	if (u->m_parm.eaction == TCA_EGRESS_MIRROR)
61 		nl_dump(p, " egress mirror");
62 	else if (u->m_parm.eaction == TCA_EGRESS_REDIR)
63 		nl_dump(p, " egress redirect");
64 
65 	switch(u->m_parm.action) {
66 	case TC_ACT_UNSPEC:
67 		nl_dump(p, " unspecified");
68 		break;
69 	case TC_ACT_PIPE:
70 		nl_dump(p, " pipe");
71 		break;
72 	case TC_ACT_STOLEN:
73 		nl_dump(p, " stolen");
74 		break;
75 	case TC_ACT_SHOT:
76 		nl_dump(p, " shot");
77 		break;
78 	case TC_ACT_QUEUED:
79 		nl_dump(p, " queued");
80 		break;
81 	case TC_ACT_REPEAT:
82 		nl_dump(p, " repeat");
83 		break;
84 	}
85 }
86 
mirred_dump_details(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)87 static void mirred_dump_details(struct rtnl_tc *tc, void *data,
88 			     struct nl_dump_params *p)
89 {
90 }
91 
mirred_dump_stats(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)92 static void mirred_dump_stats(struct rtnl_tc *tc, void *data,
93 			   struct nl_dump_params *p)
94 {
95 	struct rtnl_mirred *u = data;
96 
97 	if (!u)
98 		return;
99 	/* TODO */
100 }
101 
102 
mirred_msg_fill(struct rtnl_tc * tc,void * data,struct nl_msg * msg)103 static int mirred_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
104 {
105 	struct rtnl_mirred *u = data;
106 
107 	if (!u)
108 		return 0;
109 
110 	NLA_PUT(msg, TCA_MIRRED_PARMS, sizeof(u->m_parm), &u->m_parm);
111 	return 0;
112 
113 nla_put_failure:
114 	return -NLE_NOMEM;
115 }
116 
117 /**
118  * @name Attribute Modifications
119  * @{
120  */
121 
rtnl_mirred_set_action(struct rtnl_act * act,int action)122 int rtnl_mirred_set_action(struct rtnl_act *act, int action)
123 {
124 	struct rtnl_mirred *u;
125 
126 	if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
127 		return -NLE_NOMEM;
128 
129 	if (action > TCA_INGRESS_MIRROR || action < TCA_EGRESS_REDIR)
130 		return -NLE_INVAL;
131 
132 	switch (action) {
133 	case TCA_EGRESS_MIRROR:
134 	case TCA_EGRESS_REDIR:
135 		u->m_parm.eaction = action;
136 		break;
137 	case TCA_INGRESS_REDIR:
138 	case TCA_INGRESS_MIRROR:
139 	default:
140 		return NLE_OPNOTSUPP;
141 	}
142 	return 0;
143 }
144 
rtnl_mirred_get_action(struct rtnl_act * act)145 int rtnl_mirred_get_action(struct rtnl_act *act)
146 {
147 	struct rtnl_mirred *u;
148 
149 	if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
150 		return -NLE_NOMEM;
151 	return u->m_parm.eaction;
152 }
153 
rtnl_mirred_set_ifindex(struct rtnl_act * act,uint32_t ifindex)154 int rtnl_mirred_set_ifindex(struct rtnl_act *act, uint32_t ifindex)
155 {
156 	struct rtnl_mirred *u;
157 
158 	if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
159 		return -NLE_NOMEM;
160 
161 	u->m_parm.ifindex = ifindex;
162 	return 0;
163 }
164 
rtnl_mirred_get_ifindex(struct rtnl_act * act)165 uint32_t rtnl_mirred_get_ifindex(struct rtnl_act *act)
166 {
167 	struct rtnl_mirred *u;
168 
169 	if ((u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
170 		return u->m_parm.ifindex;
171 	return 0;
172 }
173 
rtnl_mirred_set_policy(struct rtnl_act * act,int policy)174 int rtnl_mirred_set_policy(struct rtnl_act *act, int policy)
175 {
176 	struct rtnl_mirred *u;
177 
178 	if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
179 		return -NLE_NOMEM;
180 
181 	u->m_parm.action = policy;
182 
183 	return 0;
184 }
185 
rtnl_mirred_get_policy(struct rtnl_act * act)186 int rtnl_mirred_get_policy(struct rtnl_act *act)
187 {
188 	struct rtnl_mirred *u;
189 
190 	if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
191 		return -NLE_NOMEM;
192 	return u->m_parm.action;
193 }
194 
195 /** @} */
196 
197 static struct rtnl_tc_ops mirred_ops = {
198 	.to_kind		= "mirred",
199 	.to_type		= RTNL_TC_TYPE_ACT,
200 	.to_size		= sizeof(struct rtnl_mirred),
201 	.to_msg_parser		= mirred_msg_parser,
202 	.to_free_data		= mirred_free_data,
203 	.to_clone		= NULL,
204 	.to_msg_fill		= mirred_msg_fill,
205 	.to_dump = {
206 	    [NL_DUMP_LINE]	= mirred_dump_line,
207 	    [NL_DUMP_DETAILS]	= mirred_dump_details,
208 	    [NL_DUMP_STATS]	= mirred_dump_stats,
209 	},
210 };
211 
mirred_init(void)212 static void _nl_init mirred_init(void)
213 {
214 	rtnl_tc_register(&mirred_ops);
215 }
216 
mirred_exit(void)217 static void _nl_exit mirred_exit(void)
218 {
219 	rtnl_tc_unregister(&mirred_ops);
220 }
221 
222 /** @} */
223