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