Line data Source code
1 : /*
2 : * Copyright (c) 2020 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 :
16 : #include <vnet/ip/ip_types_api.h>
17 : #include <vlibmemory/api.h>
18 : #include <nat/nat64/nat64.h>
19 : #include <nat/nat64/nat64.api_enum.h>
20 : #include <nat/nat64/nat64.api_types.h>
21 : #include <vnet/fib/fib_table.h>
22 : #include <vnet/ip/ip.h>
23 :
24 : #define REPLY_MSG_ID_BASE nm->msg_id_base
25 : #include <vlibapi/api_helper_macros.h>
26 :
27 : static void
28 40 : vl_api_nat64_plugin_enable_disable_t_handler
29 : (vl_api_nat64_plugin_enable_disable_t * mp)
30 : {
31 40 : nat64_main_t *nm = &nat64_main;
32 : vl_api_nat64_plugin_enable_disable_reply_t *rmp;
33 40 : nat64_config_t c = { 0 };
34 40 : int rv = 0;
35 40 : if (mp->enable)
36 : {
37 20 : c.bib_buckets = ntohl (mp->bib_buckets);
38 20 : c.bib_memory_size = ntohl (mp->bib_memory_size);
39 20 : c.st_buckets = ntohl (mp->st_buckets);
40 20 : c.st_memory_size = ntohl (mp->st_memory_size);
41 20 : rv = nat64_plugin_enable (c);
42 : }
43 : else
44 : {
45 20 : rv = nat64_plugin_disable ();
46 : }
47 40 : REPLY_MACRO (VL_API_NAT64_PLUGIN_ENABLE_DISABLE_REPLY);
48 : }
49 :
50 : static void
51 2 : vl_api_nat64_set_timeouts_t_handler (vl_api_nat64_set_timeouts_t * mp)
52 : {
53 2 : nat64_main_t *nm = &nat64_main;
54 : vl_api_nat64_set_timeouts_reply_t *rmp;
55 2 : int rv = 0;
56 :
57 2 : nm->udp_timeout = ntohl (mp->udp);
58 2 : nm->tcp_est_timeout = ntohl (mp->tcp_established);
59 2 : nm->tcp_trans_timeout = ntohl (mp->tcp_transitory);
60 2 : nm->icmp_timeout = ntohl (mp->icmp);
61 :
62 2 : REPLY_MACRO (VL_API_NAT64_SET_TIMEOUTS_REPLY);
63 : }
64 :
65 : static void
66 2 : vl_api_nat64_get_timeouts_t_handler (vl_api_nat64_get_timeouts_t * mp)
67 : {
68 2 : nat64_main_t *nm = &nat64_main;
69 : vl_api_nat64_get_timeouts_reply_t *rmp;
70 2 : int rv = 0;
71 :
72 : /* *INDENT-OFF* */
73 2 : REPLY_MACRO2 (VL_API_NAT64_GET_TIMEOUTS_REPLY,
74 : ({
75 : rmp->udp = htonl (nm->udp_timeout);
76 : rmp->tcp_established = htonl (nm->tcp_est_timeout);
77 : rmp->tcp_transitory = htonl (nm->tcp_trans_timeout);
78 : rmp->icmp = htonl (nm->icmp_timeout);
79 : }))
80 : /* *INDENT-ON* */
81 : }
82 :
83 : static void
84 20 : vl_api_nat64_add_del_pool_addr_range_t_handler
85 : (vl_api_nat64_add_del_pool_addr_range_t * mp)
86 : {
87 20 : nat64_main_t *nm = &nat64_main;
88 : vl_api_nat64_add_del_pool_addr_range_reply_t *rmp;
89 20 : int rv = 0;
90 : ip4_address_t this_addr;
91 : u32 start_host_order, end_host_order;
92 : u32 vrf_id;
93 : int i, count;
94 : u32 *tmp;
95 :
96 20 : tmp = (u32 *) mp->start_addr;
97 20 : start_host_order = clib_host_to_net_u32 (tmp[0]);
98 20 : tmp = (u32 *) mp->end_addr;
99 20 : end_host_order = clib_host_to_net_u32 (tmp[0]);
100 :
101 20 : count = (end_host_order - start_host_order) + 1;
102 :
103 20 : vrf_id = clib_host_to_net_u32 (mp->vrf_id);
104 :
105 20 : memcpy (&this_addr.as_u8, mp->start_addr, 4);
106 :
107 50 : for (i = 0; i < count; i++)
108 : {
109 30 : if ((rv = nat64_add_del_pool_addr (0, &this_addr, vrf_id, mp->is_add)))
110 0 : goto send_reply;
111 :
112 30 : increment_v4_address (&this_addr);
113 : }
114 :
115 20 : send_reply:
116 20 : REPLY_MACRO (VL_API_NAT64_ADD_DEL_POOL_ADDR_RANGE_REPLY);
117 : }
118 :
119 : typedef struct nat64_api_walk_ctx_t_
120 : {
121 : vl_api_registration_t *reg;
122 : u32 context;
123 : nat64_db_t *db;
124 : } nat64_api_walk_ctx_t;
125 :
126 : static int
127 2 : nat64_api_pool_walk (nat64_address_t * a, void *arg)
128 : {
129 2 : nat64_main_t *nm = &nat64_main;
130 : vl_api_nat64_pool_addr_details_t *rmp;
131 2 : nat64_api_walk_ctx_t *ctx = arg;
132 :
133 2 : rmp = vl_msg_api_alloc (sizeof (*rmp));
134 2 : clib_memset (rmp, 0, sizeof (*rmp));
135 2 : rmp->_vl_msg_id = ntohs (VL_API_NAT64_POOL_ADDR_DETAILS + nm->msg_id_base);
136 2 : clib_memcpy (rmp->address, &(a->addr), 4);
137 2 : if (a->fib_index != ~0)
138 : {
139 0 : fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP6);
140 0 : if (!fib)
141 0 : return -1;
142 0 : rmp->vrf_id = ntohl (fib->ft_table_id);
143 : }
144 : else
145 2 : rmp->vrf_id = ~0;
146 2 : rmp->context = ctx->context;
147 :
148 2 : vl_api_send_msg (ctx->reg, (u8 *) rmp);
149 :
150 2 : return 0;
151 : }
152 :
153 : static void
154 4 : vl_api_nat64_pool_addr_dump_t_handler (vl_api_nat64_pool_addr_dump_t * mp)
155 : {
156 : vl_api_registration_t *reg;
157 :
158 4 : reg = vl_api_client_index_to_registration (mp->client_index);
159 4 : if (!reg)
160 0 : return;
161 :
162 4 : nat64_api_walk_ctx_t ctx = {
163 : .reg = reg,
164 4 : .context = mp->context,
165 : };
166 :
167 4 : nat64_pool_addr_walk (nat64_api_pool_walk, &ctx);
168 : }
169 :
170 : static void
171 35 : vl_api_nat64_add_del_interface_t_handler (vl_api_nat64_add_del_interface_t *
172 : mp)
173 : {
174 35 : nat64_main_t *nm = &nat64_main;
175 : vl_api_nat64_add_del_interface_reply_t *rmp;
176 35 : int rv = 0;
177 :
178 35 : VALIDATE_SW_IF_INDEX (mp);
179 :
180 : rv =
181 35 : nat64_interface_add_del (ntohl (mp->sw_if_index),
182 35 : mp->flags & NAT_API_IS_INSIDE, mp->is_add);
183 :
184 35 : BAD_SW_IF_INDEX_LABEL;
185 :
186 35 : REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_REPLY);
187 : }
188 :
189 : static int
190 2 : nat64_api_interface_walk (nat64_interface_t * i, void *arg)
191 : {
192 2 : nat64_main_t *nm = &nat64_main;
193 : vl_api_nat64_interface_details_t *rmp;
194 2 : nat64_api_walk_ctx_t *ctx = arg;
195 :
196 2 : rmp = vl_msg_api_alloc (sizeof (*rmp));
197 2 : clib_memset (rmp, 0, sizeof (*rmp));
198 2 : rmp->_vl_msg_id = ntohs (VL_API_NAT64_INTERFACE_DETAILS + nm->msg_id_base);
199 2 : rmp->sw_if_index = ntohl (i->sw_if_index);
200 :
201 2 : if (nat64_interface_is_inside (i))
202 1 : rmp->flags |= NAT_API_IS_INSIDE;
203 2 : if (nat64_interface_is_outside (i))
204 1 : rmp->flags |= NAT_API_IS_OUTSIDE;
205 :
206 2 : rmp->context = ctx->context;
207 :
208 2 : vl_api_send_msg (ctx->reg, (u8 *) rmp);
209 :
210 2 : return 0;
211 : }
212 :
213 : static void
214 2 : vl_api_nat64_interface_dump_t_handler (vl_api_nat64_interface_dump_t * mp)
215 : {
216 : vl_api_registration_t *reg;
217 :
218 2 : reg = vl_api_client_index_to_registration (mp->client_index);
219 2 : if (!reg)
220 0 : return;
221 :
222 2 : nat64_api_walk_ctx_t ctx = {
223 : .reg = reg,
224 2 : .context = mp->context,
225 : };
226 :
227 2 : nat64_interfaces_walk (nat64_api_interface_walk, &ctx);
228 : }
229 :
230 : static void
231 11 : vl_api_nat64_add_del_static_bib_t_handler
232 : (vl_api_nat64_add_del_static_bib_t * mp)
233 : {
234 11 : nat64_main_t *nm = &nat64_main;
235 : vl_api_nat64_add_del_static_bib_reply_t *rmp;
236 : ip6_address_t in_addr;
237 : ip4_address_t out_addr;
238 11 : int rv = 0;
239 :
240 11 : memcpy (&in_addr.as_u8, mp->i_addr, 16);
241 11 : memcpy (&out_addr.as_u8, mp->o_addr, 4);
242 :
243 : rv =
244 11 : nat64_add_del_static_bib_entry (&in_addr, &out_addr,
245 11 : clib_net_to_host_u16 (mp->i_port),
246 11 : clib_net_to_host_u16 (mp->o_port),
247 11 : mp->proto,
248 : clib_net_to_host_u32 (mp->vrf_id),
249 11 : mp->is_add);
250 :
251 11 : REPLY_MACRO (VL_API_NAT64_ADD_DEL_STATIC_BIB_REPLY);
252 : }
253 :
254 : static int
255 1 : nat64_api_bib_walk (nat64_db_bib_entry_t * bibe, void *arg)
256 : {
257 1 : nat64_main_t *nm = &nat64_main;
258 : vl_api_nat64_bib_details_t *rmp;
259 1 : nat64_api_walk_ctx_t *ctx = arg;
260 : fib_table_t *fib;
261 :
262 1 : fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
263 1 : if (!fib)
264 0 : return -1;
265 :
266 1 : rmp = vl_msg_api_alloc (sizeof (*rmp));
267 1 : clib_memset (rmp, 0, sizeof (*rmp));
268 1 : rmp->_vl_msg_id = ntohs (VL_API_NAT64_BIB_DETAILS + nm->msg_id_base);
269 1 : rmp->context = ctx->context;
270 1 : clib_memcpy (rmp->i_addr, &(bibe->in_addr), 16);
271 1 : clib_memcpy (rmp->o_addr, &(bibe->out_addr), 4);
272 1 : rmp->i_port = bibe->in_port;
273 1 : rmp->o_port = bibe->out_port;
274 1 : rmp->vrf_id = ntohl (fib->ft_table_id);
275 1 : rmp->proto = bibe->proto;
276 1 : if (bibe->is_static)
277 1 : rmp->flags |= NAT_API_IS_STATIC;
278 1 : rmp->ses_num = ntohl (bibe->ses_num);
279 :
280 1 : vl_api_send_msg (ctx->reg, (u8 *) rmp);
281 :
282 1 : return 0;
283 : }
284 :
285 : static void
286 2 : vl_api_nat64_bib_dump_t_handler (vl_api_nat64_bib_dump_t * mp)
287 : {
288 2 : nat64_main_t *nm = &nat64_main;
289 : vl_api_registration_t *reg;
290 : nat64_db_t *db;
291 :
292 2 : reg = vl_api_client_index_to_registration (mp->client_index);
293 2 : if (!reg)
294 0 : return;
295 :
296 2 : nat64_api_walk_ctx_t ctx = {
297 : .reg = reg,
298 2 : .context = mp->context,
299 : };
300 :
301 : /* *INDENT-OFF* */
302 4 : vec_foreach (db, nm->db)
303 2 : nat64_db_bib_walk (db, mp->proto, nat64_api_bib_walk, &ctx);
304 : /* *INDENT-ON* */
305 : }
306 :
307 : static int
308 10 : nat64_api_st_walk (nat64_db_st_entry_t * ste, void *arg)
309 : {
310 10 : nat64_main_t *nm = &nat64_main;
311 : vl_api_nat64_st_details_t *rmp;
312 10 : nat64_api_walk_ctx_t *ctx = arg;
313 : nat64_db_bib_entry_t *bibe;
314 : fib_table_t *fib;
315 :
316 10 : bibe = nat64_db_bib_entry_by_index (ctx->db, ste->proto, ste->bibe_index);
317 10 : if (!bibe)
318 0 : return -1;
319 :
320 10 : fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
321 10 : if (!fib)
322 0 : return -1;
323 :
324 10 : rmp = vl_msg_api_alloc (sizeof (*rmp));
325 10 : clib_memset (rmp, 0, sizeof (*rmp));
326 10 : rmp->_vl_msg_id = ntohs (VL_API_NAT64_ST_DETAILS + nm->msg_id_base);
327 10 : rmp->context = ctx->context;
328 10 : clib_memcpy (rmp->il_addr, &(bibe->in_addr), 16);
329 10 : clib_memcpy (rmp->ol_addr, &(bibe->out_addr), 4);
330 10 : rmp->il_port = bibe->in_port;
331 10 : rmp->ol_port = bibe->out_port;
332 10 : clib_memcpy (rmp->ir_addr, &(ste->in_r_addr), 16);
333 10 : clib_memcpy (rmp->or_addr, &(ste->out_r_addr), 4);
334 10 : rmp->il_port = ste->r_port;
335 10 : rmp->vrf_id = ntohl (fib->ft_table_id);
336 10 : rmp->proto = ste->proto;
337 :
338 10 : vl_api_send_msg (ctx->reg, (u8 *) rmp);
339 :
340 10 : return 0;
341 : }
342 :
343 : static void
344 6 : vl_api_nat64_st_dump_t_handler (vl_api_nat64_st_dump_t * mp)
345 : {
346 6 : nat64_main_t *nm = &nat64_main;
347 : vl_api_registration_t *reg;
348 : nat64_db_t *db;
349 :
350 6 : reg = vl_api_client_index_to_registration (mp->client_index);
351 6 : if (!reg)
352 0 : return;
353 :
354 6 : nat64_api_walk_ctx_t ctx = {
355 : .reg = reg,
356 6 : .context = mp->context,
357 : };
358 :
359 : /* *INDENT-OFF* */
360 12 : vec_foreach (db, nm->db)
361 : {
362 6 : ctx.db = db;
363 6 : nat64_db_st_walk (db, mp->proto, nat64_api_st_walk, &ctx);
364 : }
365 : /* *INDENT-ON* */
366 : }
367 :
368 : static void
369 2 : vl_api_nat64_add_del_prefix_t_handler (vl_api_nat64_add_del_prefix_t * mp)
370 : {
371 2 : nat64_main_t *nm = &nat64_main;
372 : vl_api_nat64_add_del_prefix_reply_t *rmp;
373 : ip6_address_t prefix;
374 2 : int rv = 0;
375 :
376 2 : memcpy (&prefix.as_u8, mp->prefix.address, 16);
377 :
378 : rv =
379 2 : nat64_add_del_prefix (&prefix, mp->prefix.len,
380 2 : clib_net_to_host_u32 (mp->vrf_id), mp->is_add);
381 2 : REPLY_MACRO (VL_API_NAT64_ADD_DEL_PREFIX_REPLY);
382 : }
383 :
384 : static int
385 3 : nat64_api_prefix_walk (nat64_prefix_t * p, void *arg)
386 : {
387 3 : nat64_main_t *nm = &nat64_main;
388 : vl_api_nat64_prefix_details_t *rmp;
389 3 : nat64_api_walk_ctx_t *ctx = arg;
390 :
391 3 : rmp = vl_msg_api_alloc (sizeof (*rmp));
392 3 : clib_memset (rmp, 0, sizeof (*rmp));
393 3 : rmp->_vl_msg_id = ntohs (VL_API_NAT64_PREFIX_DETAILS + nm->msg_id_base);
394 3 : clib_memcpy (rmp->prefix.address, &(p->prefix), 16);
395 3 : rmp->prefix.len = p->plen;
396 3 : rmp->vrf_id = ntohl (p->vrf_id);
397 3 : rmp->context = ctx->context;
398 :
399 3 : vl_api_send_msg (ctx->reg, (u8 *) rmp);
400 :
401 3 : return 0;
402 : }
403 :
404 : static void
405 2 : vl_api_nat64_prefix_dump_t_handler (vl_api_nat64_prefix_dump_t * mp)
406 : {
407 : vl_api_registration_t *reg;
408 :
409 2 : reg = vl_api_client_index_to_registration (mp->client_index);
410 2 : if (!reg)
411 0 : return;
412 :
413 2 : nat64_api_walk_ctx_t ctx = {
414 : .reg = reg,
415 2 : .context = mp->context,
416 : };
417 :
418 2 : nat64_prefix_walk (nat64_api_prefix_walk, &ctx);
419 : }
420 :
421 : static void
422 1 : vl_api_nat64_add_del_interface_addr_t_handler
423 : (vl_api_nat64_add_del_interface_addr_t * mp)
424 : {
425 1 : nat64_main_t *nm = &nat64_main;
426 : vl_api_nat64_add_del_interface_addr_reply_t *rmp;
427 1 : u32 sw_if_index = ntohl (mp->sw_if_index);
428 1 : int rv = 0;
429 :
430 1 : VALIDATE_SW_IF_INDEX (mp);
431 :
432 1 : rv = nat64_add_interface_address (sw_if_index, mp->is_add);
433 :
434 1 : BAD_SW_IF_INDEX_LABEL;
435 :
436 1 : REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_ADDR_REPLY);
437 : }
438 :
439 : /* API definitions */
440 : #include <vnet/format_fns.h>
441 : #include <nat/nat64/nat64.api.c>
442 :
443 : /* Set up the API message handling tables */
444 : clib_error_t *
445 559 : nat64_api_hookup (vlib_main_t * vm)
446 : {
447 559 : nat64_main_t *nm = &nat64_main;
448 559 : nm->msg_id_base = setup_message_id_table ();
449 559 : return 0;
450 : }
451 :
452 : /*
453 : * fd.io coding-style-patch-verification: ON
454 : *
455 : * Local Variables:
456 : * eval: (c-set-style "gnu")
457 : * End:
458 : */
|