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