xref: /aosp_15_r20/external/libnl/lib/route/act/nat.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3  * Copyright (c) 2016 Magnus Öberg <[email protected]>
4  */
5 
6 /**
7  * @ingroup act
8  * @defgroup act_nat NAT
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/nat.h>
19 #include <netlink/route/tc.h>
20 
21 #include "tc-api.h"
22 
23 static struct nla_policy nat_policy[TCA_NAT_MAX + 1] = {
24 	[TCA_NAT_PARMS] = { .minlen = sizeof(struct tc_nat) },
25 };
26 
27 /**
28  * nat operations
29  */
30 
nat_msg_parser(struct rtnl_tc * tc,void * data)31 static int nat_msg_parser(struct rtnl_tc *tc, void *data)
32 {
33 	struct tc_nat *nat = data;
34 	struct nlattr *tb[TCA_NAT_MAX + 1];
35 	int err;
36 
37 	err = tca_parse(tb, TCA_NAT_MAX, tc, nat_policy);
38 	if (err < 0)
39 		return err;
40 
41 	if (!tb[TCA_NAT_PARMS])
42 		return -NLE_MISSING_ATTR;
43 
44 	nla_memcpy(nat, tb[TCA_NAT_PARMS], sizeof(*nat));
45 
46 	return NLE_SUCCESS;
47 }
48 
nat_free_data(struct rtnl_tc * tc,void * data)49 static void nat_free_data(struct rtnl_tc *tc, void *data)
50 {
51 }
52 
nat_msg_fill(struct rtnl_tc * tc,void * data,struct nl_msg * msg)53 static int nat_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
54 {
55 	struct tc_nat *nat = data;
56 
57 	if (!nat)
58 		return -NLE_OBJ_NOTFOUND;
59 
60 	NLA_PUT(msg, TCA_NAT_PARMS, sizeof(*nat), nat);
61 
62 	return NLE_SUCCESS;
63 
64 nla_put_failure:
65 	return -NLE_NOMEM;
66 }
67 
nat_dump_line(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)68 static void nat_dump_line(struct rtnl_tc *tc, void *data,
69 			  struct nl_dump_params *p)
70 {
71 	struct tc_nat *nat = data;
72 	char buf[32];
73 	uint32_t mask;
74 	int pfx = 0;
75 
76 	if (!nat)
77 		return;
78 
79 	if (nat->flags & TCA_NAT_FLAG_EGRESS)
80 		nl_dump(p, " egress");
81 	else
82 		nl_dump(p, " ingress");
83 
84 	mask = nat->mask;
85 	while (mask > 0) {
86 		mask = mask >> 1;
87 		pfx++;
88 	}
89 
90 	inet_ntop(AF_INET, &nat->old_addr, buf, sizeof(buf));
91 	nl_dump(p, " %s", buf);
92 	if (pfx < 32)
93 		nl_dump(p, "/%d", pfx);
94 
95 	inet_ntop(AF_INET, &nat->new_addr, buf, sizeof(buf));
96 	nl_dump(p, " %s", buf);
97 	if (pfx < 32)
98 		nl_dump(p, "/%d", pfx);
99 }
100 
101 /**
102  * @name Attribute Modifications
103  * @{
104  */
105 
106 /**
107  * Set old IPv4 address on a netlink NAT action object
108  * @arg act        Action object
109  * @arg addr       Binary IPv4 address in host byte order
110  *
111  * @return 0 on success or negative error code in case of an error.
112  */
rtnl_nat_set_old_addr(struct rtnl_act * act,in_addr_t addr)113 int rtnl_nat_set_old_addr(struct rtnl_act *act, in_addr_t addr)
114 {
115 	struct tc_nat *nat;
116 
117 	if (!(nat = (struct tc_nat *)rtnl_tc_data(TC_CAST(act))))
118 		return -NLE_NOMEM;
119 
120 	nat->old_addr = addr;
121 
122 	return NLE_SUCCESS;
123 }
124 
rtnl_nat_get_old_addr(struct rtnl_act * act,in_addr_t * addr)125 int rtnl_nat_get_old_addr(struct rtnl_act *act, in_addr_t *addr)
126 {
127 	struct tc_nat *nat;
128 
129 	if (!(nat = (struct tc_nat *)rtnl_tc_data_peek(TC_CAST(act))))
130 		return -NLE_NOATTR;
131 
132 	*addr = nat->old_addr;
133 
134 	return NLE_SUCCESS;
135 }
136 
137 /**
138  * Set new IPv4 address on a netlink NAT action object
139  * @arg act        Action object
140  * @arg addr       Binary IPv4 address in host byte order
141  *
142  * @return 0 on success or negative error code in case of an error.
143  */
rtnl_nat_set_new_addr(struct rtnl_act * act,in_addr_t addr)144 int rtnl_nat_set_new_addr(struct rtnl_act *act, in_addr_t addr)
145 {
146 	struct tc_nat *nat;
147 
148 	if (!(nat = (struct tc_nat *)rtnl_tc_data(TC_CAST(act))))
149 		return -NLE_NOMEM;
150 
151 	nat->new_addr = addr;
152 
153 	return NLE_SUCCESS;
154 }
155 
rtnl_nat_get_new_addr(struct rtnl_act * act,in_addr_t * addr)156 int rtnl_nat_get_new_addr(struct rtnl_act *act, in_addr_t *addr)
157 {
158 	struct tc_nat *nat;
159 
160 	if (!(nat = (struct tc_nat *)rtnl_tc_data_peek(TC_CAST(act))))
161 		return -NLE_NOATTR;
162 
163 	*addr = nat->new_addr;
164 
165 	return NLE_SUCCESS;
166 }
167 
168 /**
169  * Set IPv4 address mask on a netlink NAT action object
170  * @arg act        Action object
171  * @arg mask       IPv4 address mask
172  *
173  * @return 0 on success or negative error code in case of an error.
174  */
rtnl_nat_set_mask(struct rtnl_act * act,in_addr_t bitmask)175 int rtnl_nat_set_mask(struct rtnl_act *act, in_addr_t bitmask)
176 {
177 	struct tc_nat *nat;
178 
179 	if (!(nat = (struct tc_nat *)rtnl_tc_data(TC_CAST(act))))
180 		return -NLE_NOMEM;
181 
182 	nat->mask = bitmask;
183 
184 	return NLE_SUCCESS;
185 }
186 
rtnl_nat_get_mask(struct rtnl_act * act,in_addr_t * bitmask)187 int rtnl_nat_get_mask(struct rtnl_act *act, in_addr_t *bitmask)
188 {
189 	struct tc_nat *nat;
190 
191 	if (!(nat = (struct tc_nat *)rtnl_tc_data_peek(TC_CAST(act))))
192 		return -NLE_NOATTR;
193 
194 	*bitmask = nat->mask;
195 
196 	return NLE_SUCCESS;
197 }
198 
199 /**
200  * Set flags for a netlink NAT action object
201  * @arg act        Action object
202  * @arg flags      TCA_NAT_FLAG_* flags.
203  *
204  * Currently only TCA_NAT_FLAG_EGRESS is defined. Selects NAT on
205  * egress/IP src if set, ingress/IP dst otherwise.
206  *
207  * @return 0 on success or negative error code in case of an error.
208  */
rtnl_nat_set_flags(struct rtnl_act * act,uint32_t flags)209 int rtnl_nat_set_flags(struct rtnl_act *act, uint32_t flags)
210 {
211 	struct tc_nat *nat;
212 
213 	if (!(nat = (struct tc_nat *)rtnl_tc_data(TC_CAST(act))))
214 		return -NLE_NOMEM;
215 
216 	nat->flags = flags;
217 
218 	return NLE_SUCCESS;
219 }
220 
rtnl_nat_get_flags(struct rtnl_act * act,uint32_t * flags)221 int rtnl_nat_get_flags(struct rtnl_act *act, uint32_t *flags)
222 {
223 	struct tc_nat *nat;
224 
225 	if (!(nat = (struct tc_nat *)rtnl_tc_data_peek(TC_CAST(act))))
226 		return -NLE_NOATTR;
227 
228 	*flags = nat->flags;
229 
230 	return NLE_SUCCESS;
231 }
232 
rtnl_nat_set_action(struct rtnl_act * act,int action)233 int rtnl_nat_set_action(struct rtnl_act *act, int action)
234 {
235 	struct tc_nat *nat;
236 
237 	if (!(nat = (struct tc_nat *)rtnl_tc_data(TC_CAST(act))))
238 		return -NLE_NOMEM;
239 
240 	if (action < TC_ACT_UNSPEC)
241 		return -NLE_INVAL;
242 
243 	nat->action = action;
244 
245 	return NLE_SUCCESS;
246 }
247 
rtnl_nat_get_action(struct rtnl_act * act,int * action)248 int rtnl_nat_get_action(struct rtnl_act *act, int *action)
249 {
250 	struct tc_nat *nat;
251 
252 	if (!(nat = (struct tc_nat *)rtnl_tc_data_peek(TC_CAST(act))))
253 		return -NLE_NOATTR;
254 
255 	*action = nat->action;
256 
257 	return NLE_SUCCESS;
258 }
259 
260 /**
261  * @}
262  */
263 
264 static struct rtnl_tc_ops nat_ops = {
265 	.to_kind                = "nat",
266 	.to_type                = RTNL_TC_TYPE_ACT,
267 	.to_size                = sizeof(struct tc_nat),
268 	.to_msg_parser          = nat_msg_parser,
269 	.to_free_data           = nat_free_data,
270 	.to_clone               = NULL,
271 	.to_msg_fill            = nat_msg_fill,
272 	.to_dump = {
273 		[NL_DUMP_LINE]  = nat_dump_line,
274 	},
275 };
276 
nat_init(void)277 static void _nl_init nat_init(void)
278 {
279 	rtnl_tc_register(&nat_ops);
280 }
281 
nat_exit(void)282 static void _nl_exit nat_exit(void)
283 {
284 	rtnl_tc_unregister(&nat_ops);
285 }
286 
287 /**
288  * @}
289  */
290