nat: cleanup & reorganization
[vpp.git] / src / plugins / nat / nat64 / nat64_api.c
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   vl_api_nat64_plugin_enable_disable_t_handler
29   (vl_api_nat64_plugin_enable_disable_t * mp)
30 {
31   nat64_main_t *nm = &nat64_main;
32   vl_api_nat64_plugin_enable_disable_reply_t *rmp;
33   nat64_config_t c = { 0 };
34   int rv = 0;
35   if (mp->enable)
36     {
37       c.bib_buckets = ntohl (mp->bib_buckets);
38       c.bib_memory_size = ntohl (mp->bib_memory_size);
39       c.st_buckets = ntohl (mp->st_buckets);
40       c.st_memory_size = ntohl (mp->st_memory_size);
41       rv = nat64_plugin_enable (c);
42     }
43   else
44     {
45       rv = nat64_plugin_disable ();
46     }
47   REPLY_MACRO (VL_API_NAT64_PLUGIN_ENABLE_DISABLE_REPLY);
48 }
49
50 static void
51 vl_api_nat64_set_timeouts_t_handler (vl_api_nat64_set_timeouts_t * mp)
52 {
53   nat64_main_t *nm = &nat64_main;
54   vl_api_nat64_set_timeouts_reply_t *rmp;
55   int rv = 0;
56
57   nm->udp_timeout = ntohl (mp->udp);
58   nm->tcp_est_timeout = ntohl (mp->tcp_established);
59   nm->tcp_trans_timeout = ntohl (mp->tcp_transitory);
60   nm->icmp_timeout = ntohl (mp->icmp);
61
62   REPLY_MACRO (VL_API_NAT64_SET_TIMEOUTS_REPLY);
63 }
64
65 static void
66 vl_api_nat64_get_timeouts_t_handler (vl_api_nat64_get_timeouts_t * mp)
67 {
68   nat64_main_t *nm = &nat64_main;
69   vl_api_nat64_get_timeouts_reply_t *rmp;
70   int rv = 0;
71
72   /* *INDENT-OFF* */
73   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   vl_api_nat64_add_del_pool_addr_range_t_handler
85   (vl_api_nat64_add_del_pool_addr_range_t * mp)
86 {
87   nat64_main_t *nm = &nat64_main;
88   vl_api_nat64_add_del_pool_addr_range_reply_t *rmp;
89   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   tmp = (u32 *) mp->start_addr;
97   start_host_order = clib_host_to_net_u32 (tmp[0]);
98   tmp = (u32 *) mp->end_addr;
99   end_host_order = clib_host_to_net_u32 (tmp[0]);
100
101   count = (end_host_order - start_host_order) + 1;
102
103   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
104
105   memcpy (&this_addr.as_u8, mp->start_addr, 4);
106
107   for (i = 0; i < count; i++)
108     {
109       if ((rv = nat64_add_del_pool_addr (0, &this_addr, vrf_id, mp->is_add)))
110         goto send_reply;
111
112       increment_v4_address (&this_addr);
113     }
114
115 send_reply:
116   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 nat64_api_pool_walk (nat64_address_t * a, void *arg)
128 {
129   nat64_main_t *nm = &nat64_main;
130   vl_api_nat64_pool_addr_details_t *rmp;
131   nat64_api_walk_ctx_t *ctx = arg;
132
133   rmp = vl_msg_api_alloc (sizeof (*rmp));
134   clib_memset (rmp, 0, sizeof (*rmp));
135   rmp->_vl_msg_id = ntohs (VL_API_NAT64_POOL_ADDR_DETAILS + nm->msg_id_base);
136   clib_memcpy (rmp->address, &(a->addr), 4);
137   if (a->fib_index != ~0)
138     {
139       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP6);
140       if (!fib)
141         return -1;
142       rmp->vrf_id = ntohl (fib->ft_table_id);
143     }
144   else
145     rmp->vrf_id = ~0;
146   rmp->context = ctx->context;
147
148   vl_api_send_msg (ctx->reg, (u8 *) rmp);
149
150   return 0;
151 }
152
153 static void
154 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   reg = vl_api_client_index_to_registration (mp->client_index);
159   if (!reg)
160     return;
161
162   nat64_api_walk_ctx_t ctx = {
163     .reg = reg,
164     .context = mp->context,
165   };
166
167   nat64_pool_addr_walk (nat64_api_pool_walk, &ctx);
168 }
169
170 static void
171 vl_api_nat64_add_del_interface_t_handler (vl_api_nat64_add_del_interface_t *
172                                           mp)
173 {
174   nat64_main_t *nm = &nat64_main;
175   vl_api_nat64_add_del_interface_reply_t *rmp;
176   int rv = 0;
177
178   VALIDATE_SW_IF_INDEX (mp);
179
180   rv =
181     nat64_interface_add_del (ntohl (mp->sw_if_index),
182                              mp->flags & NAT_API_IS_INSIDE, mp->is_add);
183
184   BAD_SW_IF_INDEX_LABEL;
185
186   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_REPLY);
187 }
188
189 static int
190 nat64_api_interface_walk (nat64_interface_t * i, void *arg)
191 {
192   nat64_main_t *nm = &nat64_main;
193   vl_api_nat64_interface_details_t *rmp;
194   nat64_api_walk_ctx_t *ctx = arg;
195
196   rmp = vl_msg_api_alloc (sizeof (*rmp));
197   clib_memset (rmp, 0, sizeof (*rmp));
198   rmp->_vl_msg_id = ntohs (VL_API_NAT64_INTERFACE_DETAILS + nm->msg_id_base);
199   rmp->sw_if_index = ntohl (i->sw_if_index);
200
201   if (nat64_interface_is_inside (i))
202     rmp->flags |= NAT_API_IS_INSIDE;
203   if (nat64_interface_is_outside (i))
204     rmp->flags |= NAT_API_IS_OUTSIDE;
205
206   rmp->context = ctx->context;
207
208   vl_api_send_msg (ctx->reg, (u8 *) rmp);
209
210   return 0;
211 }
212
213 static void
214 vl_api_nat64_interface_dump_t_handler (vl_api_nat64_interface_dump_t * mp)
215 {
216   vl_api_registration_t *reg;
217
218   reg = vl_api_client_index_to_registration (mp->client_index);
219   if (!reg)
220     return;
221
222   nat64_api_walk_ctx_t ctx = {
223     .reg = reg,
224     .context = mp->context,
225   };
226
227   nat64_interfaces_walk (nat64_api_interface_walk, &ctx);
228 }
229
230 static void
231   vl_api_nat64_add_del_static_bib_t_handler
232   (vl_api_nat64_add_del_static_bib_t * mp)
233 {
234   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   int rv = 0;
239
240   memcpy (&in_addr.as_u8, mp->i_addr, 16);
241   memcpy (&out_addr.as_u8, mp->o_addr, 4);
242
243   rv =
244     nat64_add_del_static_bib_entry (&in_addr, &out_addr,
245                                     clib_net_to_host_u16 (mp->i_port),
246                                     clib_net_to_host_u16 (mp->o_port),
247                                     mp->proto,
248                                     clib_net_to_host_u32 (mp->vrf_id),
249                                     mp->is_add);
250
251   REPLY_MACRO (VL_API_NAT64_ADD_DEL_STATIC_BIB_REPLY);
252 }
253
254 static int
255 nat64_api_bib_walk (nat64_db_bib_entry_t * bibe, void *arg)
256 {
257   nat64_main_t *nm = &nat64_main;
258   vl_api_nat64_bib_details_t *rmp;
259   nat64_api_walk_ctx_t *ctx = arg;
260   fib_table_t *fib;
261
262   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
263   if (!fib)
264     return -1;
265
266   rmp = vl_msg_api_alloc (sizeof (*rmp));
267   clib_memset (rmp, 0, sizeof (*rmp));
268   rmp->_vl_msg_id = ntohs (VL_API_NAT64_BIB_DETAILS + nm->msg_id_base);
269   rmp->context = ctx->context;
270   clib_memcpy (rmp->i_addr, &(bibe->in_addr), 16);
271   clib_memcpy (rmp->o_addr, &(bibe->out_addr), 4);
272   rmp->i_port = bibe->in_port;
273   rmp->o_port = bibe->out_port;
274   rmp->vrf_id = ntohl (fib->ft_table_id);
275   rmp->proto = bibe->proto;
276   if (bibe->is_static)
277     rmp->flags |= NAT_API_IS_STATIC;
278   rmp->ses_num = ntohl (bibe->ses_num);
279
280   vl_api_send_msg (ctx->reg, (u8 *) rmp);
281
282   return 0;
283 }
284
285 static void
286 vl_api_nat64_bib_dump_t_handler (vl_api_nat64_bib_dump_t * mp)
287 {
288   nat64_main_t *nm = &nat64_main;
289   vl_api_registration_t *reg;
290   nat64_db_t *db;
291
292   reg = vl_api_client_index_to_registration (mp->client_index);
293   if (!reg)
294     return;
295
296   nat64_api_walk_ctx_t ctx = {
297     .reg = reg,
298     .context = mp->context,
299   };
300
301   /* *INDENT-OFF* */
302   vec_foreach (db, nm->db)
303     nat64_db_bib_walk (db, mp->proto, nat64_api_bib_walk, &ctx);
304   /* *INDENT-ON* */
305 }
306
307 static int
308 nat64_api_st_walk (nat64_db_st_entry_t * ste, void *arg)
309 {
310   nat64_main_t *nm = &nat64_main;
311   vl_api_nat64_st_details_t *rmp;
312   nat64_api_walk_ctx_t *ctx = arg;
313   nat64_db_bib_entry_t *bibe;
314   fib_table_t *fib;
315
316   bibe = nat64_db_bib_entry_by_index (ctx->db, ste->proto, ste->bibe_index);
317   if (!bibe)
318     return -1;
319
320   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
321   if (!fib)
322     return -1;
323
324   rmp = vl_msg_api_alloc (sizeof (*rmp));
325   clib_memset (rmp, 0, sizeof (*rmp));
326   rmp->_vl_msg_id = ntohs (VL_API_NAT64_ST_DETAILS + nm->msg_id_base);
327   rmp->context = ctx->context;
328   clib_memcpy (rmp->il_addr, &(bibe->in_addr), 16);
329   clib_memcpy (rmp->ol_addr, &(bibe->out_addr), 4);
330   rmp->il_port = bibe->in_port;
331   rmp->ol_port = bibe->out_port;
332   clib_memcpy (rmp->ir_addr, &(ste->in_r_addr), 16);
333   clib_memcpy (rmp->or_addr, &(ste->out_r_addr), 4);
334   rmp->il_port = ste->r_port;
335   rmp->vrf_id = ntohl (fib->ft_table_id);
336   rmp->proto = ste->proto;
337
338   vl_api_send_msg (ctx->reg, (u8 *) rmp);
339
340   return 0;
341 }
342
343 static void
344 vl_api_nat64_st_dump_t_handler (vl_api_nat64_st_dump_t * mp)
345 {
346   nat64_main_t *nm = &nat64_main;
347   vl_api_registration_t *reg;
348   nat64_db_t *db;
349
350   reg = vl_api_client_index_to_registration (mp->client_index);
351   if (!reg)
352     return;
353
354   nat64_api_walk_ctx_t ctx = {
355     .reg = reg,
356     .context = mp->context,
357   };
358
359   /* *INDENT-OFF* */
360   vec_foreach (db, nm->db)
361     {
362       ctx.db = db;
363       nat64_db_st_walk (db, mp->proto, nat64_api_st_walk, &ctx);
364     }
365   /* *INDENT-ON* */
366 }
367
368 static void
369 vl_api_nat64_add_del_prefix_t_handler (vl_api_nat64_add_del_prefix_t * mp)
370 {
371   nat64_main_t *nm = &nat64_main;
372   vl_api_nat64_add_del_prefix_reply_t *rmp;
373   ip6_address_t prefix;
374   int rv = 0;
375
376   memcpy (&prefix.as_u8, mp->prefix.address, 16);
377
378   rv =
379     nat64_add_del_prefix (&prefix, mp->prefix.len,
380                           clib_net_to_host_u32 (mp->vrf_id), mp->is_add);
381   REPLY_MACRO (VL_API_NAT64_ADD_DEL_PREFIX_REPLY);
382 }
383
384 static int
385 nat64_api_prefix_walk (nat64_prefix_t * p, void *arg)
386 {
387   nat64_main_t *nm = &nat64_main;
388   vl_api_nat64_prefix_details_t *rmp;
389   nat64_api_walk_ctx_t *ctx = arg;
390
391   rmp = vl_msg_api_alloc (sizeof (*rmp));
392   clib_memset (rmp, 0, sizeof (*rmp));
393   rmp->_vl_msg_id = ntohs (VL_API_NAT64_PREFIX_DETAILS + nm->msg_id_base);
394   clib_memcpy (rmp->prefix.address, &(p->prefix), 16);
395   rmp->prefix.len = p->plen;
396   rmp->vrf_id = ntohl (p->vrf_id);
397   rmp->context = ctx->context;
398
399   vl_api_send_msg (ctx->reg, (u8 *) rmp);
400
401   return 0;
402 }
403
404 static void
405 vl_api_nat64_prefix_dump_t_handler (vl_api_nat64_prefix_dump_t * mp)
406 {
407   vl_api_registration_t *reg;
408
409   reg = vl_api_client_index_to_registration (mp->client_index);
410   if (!reg)
411     return;
412
413   nat64_api_walk_ctx_t ctx = {
414     .reg = reg,
415     .context = mp->context,
416   };
417
418   nat64_prefix_walk (nat64_api_prefix_walk, &ctx);
419 }
420
421 static void
422   vl_api_nat64_add_del_interface_addr_t_handler
423   (vl_api_nat64_add_del_interface_addr_t * mp)
424 {
425   nat64_main_t *nm = &nat64_main;
426   vl_api_nat64_add_del_interface_addr_reply_t *rmp;
427   u32 sw_if_index = ntohl (mp->sw_if_index);
428   int rv = 0;
429
430   VALIDATE_SW_IF_INDEX (mp);
431
432   rv = nat64_add_interface_address (sw_if_index, mp->is_add);
433
434   BAD_SW_IF_INDEX_LABEL;
435
436   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 nat64_api_hookup (vlib_main_t * vm)
446 {
447   nat64_main_t *nm = &nat64_main;
448   nm->msg_id_base = setup_message_id_table ();
449   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  */