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