libnl 3.9.0
nat.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2016 Magnus Öberg <magnus.oberg@westermo.se>
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
23static 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
31static 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
49static void nat_free_data(struct rtnl_tc *tc, void *data)
50{
51}
52
53static 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
64nla_put_failure:
65 return -NLE_NOMEM;
66}
67
68static 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 */
113int 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
125int 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 */
144int 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
156int 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 */
175int 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
187int 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 */
209int 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
221int 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
233int 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
248int 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
264static 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
277static void _nl_init nat_init(void)
278{
279 rtnl_tc_register(&nat_ops);
280}
281
282static void _nl_exit nat_exit(void)
283{
284 rtnl_tc_unregister(&nat_ops);
285}
286
287/**
288 * @}
289 */
int rtnl_nat_set_new_addr(struct rtnl_act *act, in_addr_t addr)
Set new IPv4 address on a netlink NAT action object.
Definition nat.c:144
int rtnl_nat_set_flags(struct rtnl_act *act, uint32_t flags)
Set flags for a netlink NAT action object.
Definition nat.c:209
int rtnl_nat_set_old_addr(struct rtnl_act *act, in_addr_t addr)
Set old IPv4 address on a netlink NAT action object.
Definition nat.c:113
int rtnl_nat_set_mask(struct rtnl_act *act, in_addr_t bitmask)
Set IPv4 address mask on a netlink NAT action object.
Definition nat.c:175
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
Definition attr.h:159
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
Definition attr.c:351
void * rtnl_tc_data_peek(struct rtnl_tc *tc)
Returns the private data of the traffic control object.
Definition tc.c:1065
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
Definition tc.h:50
void * rtnl_tc_data(struct rtnl_tc *)
Return pointer to private data of traffic control object.
Definition tc.c:1079
int rtnl_tc_register(struct rtnl_tc_ops *)
Register a traffic control module.
Definition tc.c:1018
void rtnl_tc_unregister(struct rtnl_tc_ops *)
Unregister a traffic control module.
Definition tc.c:1052
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition utils.c:1017
@ NL_DUMP_LINE
Dump object briefly on one line.
Definition types.h:20
Dumping parameters.
Definition types.h:32
Attribute validation policy.
Definition attr.h:63
uint16_t minlen
Minimal length of payload required.
Definition attr.h:68