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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @brief Deterministic NAT (CGN) plugin API implementation
21 #include <vnet/ip/ip_types_api.h>
22 #include <nat/det44/det44.h>
23 #include <nat/det44/det44.api_enum.h>
24 #include <nat/det44/det44.api_types.h>
25 #include <vnet/fib/fib_table.h>
26 #include <vnet/ip/ip.h>
28 #include <vlibmemory/api.h>
30 #define REPLY_MSG_ID_BASE dm->msg_id_base
31 #include <vlibapi/api_helper_macros.h>
34 vl_api_det44_add_del_map_t_handler (vl_api_det44_add_del_map_t * mp)
36 det44_main_t *dm = &det44_main;
37 vl_api_det44_add_del_map_reply_t *rmp;
39 ip4_address_t in_addr, out_addr;
40 clib_memcpy (&in_addr, mp->in_addr, 4);
41 clib_memcpy (&out_addr, mp->out_addr, 4);
42 rv = snat_det_add_map (&in_addr, mp->in_plen, &out_addr,
43 mp->out_plen, mp->is_add);
44 REPLY_MACRO (VL_API_DET44_ADD_DEL_MAP_REPLY);
48 vl_api_det44_forward_t_handler (vl_api_det44_forward_t * mp)
50 det44_main_t *dm = &det44_main;
51 vl_api_det44_forward_reply_t *rmp;
53 u16 lo_port = 0, hi_port = 0;
55 ip4_address_t in_addr, out_addr;
58 clib_memcpy (&in_addr, mp->in_addr, 4);
59 m = snat_det_map_by_user (&in_addr);
62 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
66 snat_det_forward (m, &in_addr, &out_addr, &lo_port);
67 hi_port = lo_port + m->ports_per_host - 1;
71 REPLY_MACRO2 (VL_API_DET44_FORWARD_REPLY,
73 rmp->out_port_lo = ntohs (lo_port);
74 rmp->out_port_hi = ntohs (hi_port);
75 clib_memcpy (rmp->out_addr, &out_addr, 4);
81 vl_api_det44_reverse_t_handler (vl_api_det44_reverse_t * mp)
83 det44_main_t *dm = &det44_main;
84 vl_api_det44_reverse_reply_t *rmp;
86 ip4_address_t out_addr, in_addr;
90 clib_memcpy (&out_addr, mp->out_addr, 4);
91 m = snat_det_map_by_out (&out_addr);
94 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
98 snat_det_reverse (m, &out_addr, htons (mp->out_port), &in_addr);
102 REPLY_MACRO2 (VL_API_DET44_REVERSE_REPLY,
104 clib_memcpy (rmp->in_addr, &in_addr, 4);
110 sent_det44_map_details (snat_det_map_t * m, vl_api_registration_t * reg,
113 det44_main_t *dm = &det44_main;
114 vl_api_det44_map_details_t *rmp;
116 rmp = vl_msg_api_alloc (sizeof (*rmp));
117 clib_memset (rmp, 0, sizeof (*rmp));
118 rmp->_vl_msg_id = ntohs (VL_API_DET44_MAP_DETAILS + dm->msg_id_base);
119 clib_memcpy (rmp->in_addr, &m->in_addr, 4);
120 rmp->in_plen = m->in_plen;
121 clib_memcpy (rmp->out_addr, &m->out_addr, 4);
122 rmp->out_plen = m->out_plen;
123 rmp->sharing_ratio = htonl (m->sharing_ratio);
124 rmp->ports_per_host = htons (m->ports_per_host);
125 rmp->ses_num = htonl (m->ses_num);
126 rmp->context = context;
128 vl_api_send_msg (reg, (u8 *) rmp);
132 vl_api_det44_map_dump_t_handler (vl_api_det44_map_dump_t * mp)
134 det44_main_t *dm = &det44_main;
135 vl_api_registration_t *reg;
138 reg = vl_api_client_index_to_registration (mp->client_index);
143 vec_foreach(m, dm->det_maps)
144 sent_det44_map_details(m, reg, mp->context);
149 vl_api_det44_close_session_out_t_handler (vl_api_det44_close_session_out_t
152 det44_main_t *dm = &det44_main;
153 vl_api_det44_close_session_out_reply_t *rmp;
154 ip4_address_t out_addr, ext_addr, in_addr;
155 snat_det_out_key_t key;
157 snat_det_session_t *ses;
160 clib_memcpy (&out_addr, mp->out_addr, 4);
161 clib_memcpy (&ext_addr, mp->ext_addr, 4);
163 m = snat_det_map_by_out (&out_addr);
166 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
169 snat_det_reverse (m, &ext_addr, ntohs (mp->out_port), &in_addr);
170 key.ext_host_addr = ext_addr;
171 key.ext_host_port = mp->ext_port;
172 key.out_port = mp->out_port;
173 ses = snat_det_get_ses_by_out (m, &in_addr, key.as_u64);
176 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
179 snat_det_ses_close (m, ses);
182 REPLY_MACRO (VL_API_DET44_CLOSE_SESSION_OUT_REPLY);
186 vl_api_det44_close_session_in_t_handler (vl_api_det44_close_session_in_t * mp)
188 det44_main_t *dm = &det44_main;
189 vl_api_det44_close_session_in_reply_t *rmp;
190 ip4_address_t in_addr, ext_addr;
191 snat_det_out_key_t key;
193 snat_det_session_t *ses;
196 clib_memcpy (&in_addr, mp->in_addr, 4);
197 clib_memcpy (&ext_addr, mp->ext_addr, 4);
199 m = snat_det_map_by_user (&in_addr);
202 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
205 key.ext_host_addr = ext_addr;
206 key.ext_host_port = mp->ext_port;
207 ses = snat_det_find_ses_by_in (m, &in_addr, mp->in_port, key);
210 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
213 snat_det_ses_close (m, ses);
216 REPLY_MACRO (VL_API_DET44_CLOSE_SESSION_OUT_REPLY);
220 send_det44_session_details (snat_det_session_t * s,
221 vl_api_registration_t * reg, u32 context)
223 det44_main_t *dm = &det44_main;
224 vl_api_det44_session_details_t *rmp;
226 rmp = vl_msg_api_alloc (sizeof (*rmp));
227 clib_memset (rmp, 0, sizeof (*rmp));
228 rmp->_vl_msg_id = ntohs (VL_API_DET44_SESSION_DETAILS + dm->msg_id_base);
229 rmp->in_port = s->in_port;
230 clib_memcpy (rmp->ext_addr, &s->out.ext_host_addr, 4);
231 rmp->ext_port = s->out.ext_host_port;
232 rmp->out_port = s->out.out_port;
233 rmp->state = s->state;
234 rmp->expire = ntohl (s->expire);
235 rmp->context = context;
237 vl_api_send_msg (reg, (u8 *) rmp);
241 vl_api_det44_session_dump_t_handler (vl_api_det44_session_dump_t * mp)
243 vl_api_registration_t *reg;
244 ip4_address_t user_addr;
246 snat_det_session_t *s, empty_ses;
249 reg = vl_api_client_index_to_registration (mp->client_index);
253 clib_memset (&empty_ses, 0, sizeof (empty_ses));
254 clib_memcpy (&user_addr, mp->user_addr, 4);
255 m = snat_det_map_by_user (&user_addr);
259 s = m->sessions + snat_det_user_ses_offset (&user_addr, m->in_plen);
260 for (i = 0; i < DET44_SES_PER_USER; i++)
263 send_det44_session_details (s, reg, mp->context);
269 vl_api_det44_plugin_enable_disable_t_handler
270 (vl_api_det44_plugin_enable_disable_t * mp)
272 det44_main_t *dm = &det44_main;
273 vl_api_det44_plugin_enable_disable_reply_t *rmp;
274 det44_config_t c = { 0 };
278 c.outside_vrf_id = ntohl (mp->outside_vrf);
279 c.inside_vrf_id = ntohl (mp->inside_vrf);
280 rv = det44_plugin_enable (c);
284 rv = det44_plugin_disable ();
286 REPLY_MACRO (VL_API_DET44_PLUGIN_ENABLE_DISABLE_REPLY);
290 vl_api_det44_interface_add_del_feature_t_handler
291 (vl_api_det44_interface_add_del_feature_t * mp)
293 det44_main_t *dm = &det44_main;
294 vl_api_det44_interface_add_del_feature_reply_t *rmp;
295 u32 sw_if_index = ntohl (mp->sw_if_index);
297 VALIDATE_SW_IF_INDEX (mp);
298 rv = det44_interface_add_del (sw_if_index, mp->is_inside, !mp->is_add);
299 BAD_SW_IF_INDEX_LABEL;
300 REPLY_MACRO (VL_API_DET44_INTERFACE_ADD_DEL_FEATURE_REPLY);
304 det44_send_interface_details (det44_interface_t * i,
305 vl_api_registration_t * reg, u32 context)
307 det44_main_t *dm = &det44_main;
308 vl_api_det44_interface_details_t *rmp;
310 rmp = vl_msg_api_alloc (sizeof (*rmp));
311 clib_memset (rmp, 0, sizeof (*rmp));
312 rmp->_vl_msg_id = ntohs (VL_API_DET44_INTERFACE_DETAILS + dm->msg_id_base);
313 rmp->sw_if_index = ntohl (i->sw_if_index);
314 rmp->is_outside = det44_interface_is_outside (i);
315 rmp->is_inside = det44_interface_is_inside (i);
316 rmp->context = context;
317 vl_api_send_msg (reg, (u8 *) rmp);
321 vl_api_det44_interface_dump_t_handler (vl_api_det44_interface_dump_t * mp)
323 det44_main_t *dm = &det44_main;
324 vl_api_registration_t *reg;
325 det44_interface_t *i;
327 reg = vl_api_client_index_to_registration (mp->client_index);
332 pool_foreach (i, dm->interfaces,
334 det44_send_interface_details(i, reg, mp->context);
340 vl_api_det44_set_timeouts_t_handler (vl_api_det44_set_timeouts_t * mp)
342 det44_main_t *dm = &det44_main;
343 vl_api_det44_set_timeouts_reply_t *rmp;
344 nat_timeouts_t timeouts;
346 timeouts.udp = ntohl (mp->udp);
347 timeouts.tcp.established = ntohl (mp->tcp_established);
348 timeouts.tcp.transitory = ntohl (mp->tcp_transitory);
349 timeouts.icmp = ntohl (mp->icmp);
350 rv = det44_set_timeouts (&timeouts);
351 REPLY_MACRO (VL_API_DET44_SET_TIMEOUTS_REPLY);
355 vl_api_det44_get_timeouts_t_handler (vl_api_det44_get_timeouts_t * mp)
357 det44_main_t *dm = &det44_main;
358 vl_api_det44_get_timeouts_reply_t *rmp;
359 nat_timeouts_t timeouts;
361 timeouts = det44_get_timeouts ();
363 REPLY_MACRO2 (VL_API_DET44_GET_TIMEOUTS_REPLY,
365 rmp->udp = htonl (timeouts.udp);
366 rmp->tcp_established = htonl (timeouts.tcp.established);
367 rmp->tcp_transitory = htonl (timeouts.tcp.transitory);
368 rmp->icmp = htonl (timeouts.icmp);
374 * Obsolete deterministic API to be removed
378 vl_api_nat_det_add_del_map_t_handler (vl_api_nat_det_add_del_map_t * mp)
380 det44_main_t *dm = &det44_main;
381 vl_api_nat_det_add_del_map_reply_t *rmp;
383 ip4_address_t in_addr, out_addr;
385 clib_memcpy (&in_addr, mp->in_addr, 4);
386 clib_memcpy (&out_addr, mp->out_addr, 4);
387 rv = snat_det_add_map (&in_addr, mp->in_plen, &out_addr,
388 mp->out_plen, mp->is_add);
389 REPLY_MACRO (VL_API_NAT_DET_ADD_DEL_MAP_REPLY);
393 vl_api_nat_det_forward_t_handler (vl_api_nat_det_forward_t * mp)
395 det44_main_t *dm = &det44_main;
396 vl_api_nat_det_forward_reply_t *rmp;
398 u16 lo_port = 0, hi_port = 0;
400 ip4_address_t in_addr, out_addr;
403 clib_memcpy (&in_addr, mp->in_addr, 4);
404 m = snat_det_map_by_user (&in_addr);
407 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
411 snat_det_forward (m, &in_addr, &out_addr, &lo_port);
412 hi_port = lo_port + m->ports_per_host - 1;
416 REPLY_MACRO2 (VL_API_NAT_DET_FORWARD_REPLY,
418 rmp->out_port_lo = ntohs (lo_port);
419 rmp->out_port_hi = ntohs (hi_port);
420 clib_memcpy (rmp->out_addr, &out_addr, 4);
426 vl_api_nat_det_reverse_t_handler (vl_api_nat_det_reverse_t * mp)
428 det44_main_t *dm = &det44_main;
429 vl_api_nat_det_reverse_reply_t *rmp;
431 ip4_address_t out_addr, in_addr;
435 clib_memcpy (&out_addr, mp->out_addr, 4);
436 m = snat_det_map_by_out (&out_addr);
439 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
443 snat_det_reverse (m, &out_addr, htons (mp->out_port), &in_addr);
447 REPLY_MACRO2 (VL_API_NAT_DET_REVERSE_REPLY,
449 clib_memcpy (rmp->in_addr, &in_addr, 4);
455 sent_nat_det_map_details (snat_det_map_t * m, vl_api_registration_t * reg,
458 det44_main_t *dm = &det44_main;
459 vl_api_nat_det_map_details_t *rmp;
461 rmp = vl_msg_api_alloc (sizeof (*rmp));
462 clib_memset (rmp, 0, sizeof (*rmp));
463 rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_MAP_DETAILS + dm->msg_id_base);
464 clib_memcpy (rmp->in_addr, &m->in_addr, 4);
465 rmp->in_plen = m->in_plen;
466 clib_memcpy (rmp->out_addr, &m->out_addr, 4);
467 rmp->out_plen = m->out_plen;
468 rmp->sharing_ratio = htonl (m->sharing_ratio);
469 rmp->ports_per_host = htons (m->ports_per_host);
470 rmp->ses_num = htonl (m->ses_num);
471 rmp->context = context;
473 vl_api_send_msg (reg, (u8 *) rmp);
477 vl_api_nat_det_map_dump_t_handler (vl_api_nat_det_map_dump_t * mp)
479 det44_main_t *dm = &det44_main;
480 vl_api_registration_t *reg;
483 reg = vl_api_client_index_to_registration (mp->client_index);
488 vec_foreach(m, dm->det_maps)
489 sent_nat_det_map_details(m, reg, mp->context);
494 vl_api_nat_det_close_session_out_t_handler (vl_api_nat_det_close_session_out_t
497 det44_main_t *dm = &det44_main;
498 vl_api_nat_det_close_session_out_reply_t *rmp;
499 ip4_address_t out_addr, ext_addr, in_addr;
500 snat_det_out_key_t key;
502 snat_det_session_t *ses;
505 clib_memcpy (&out_addr, mp->out_addr, 4);
506 clib_memcpy (&ext_addr, mp->ext_addr, 4);
508 m = snat_det_map_by_out (&out_addr);
511 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
514 snat_det_reverse (m, &ext_addr, ntohs (mp->out_port), &in_addr);
515 key.ext_host_addr = ext_addr;
516 key.ext_host_port = mp->ext_port;
517 key.out_port = mp->out_port;
518 ses = snat_det_get_ses_by_out (m, &in_addr, key.as_u64);
521 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
524 snat_det_ses_close (m, ses);
527 REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
531 vl_api_nat_det_close_session_in_t_handler (vl_api_nat_det_close_session_in_t *
534 det44_main_t *dm = &det44_main;
535 vl_api_nat_det_close_session_in_reply_t *rmp;
536 ip4_address_t in_addr, ext_addr;
537 snat_det_out_key_t key;
539 snat_det_session_t *ses;
542 clib_memcpy (&in_addr, mp->in_addr, 4);
543 clib_memcpy (&ext_addr, mp->ext_addr, 4);
545 m = snat_det_map_by_user (&in_addr);
548 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
551 key.ext_host_addr = ext_addr;
552 key.ext_host_port = mp->ext_port;
553 ses = snat_det_find_ses_by_in (m, &in_addr, mp->in_port, key);
556 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
559 snat_det_ses_close (m, ses);
562 REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
566 send_nat_det_session_details (snat_det_session_t * s,
567 vl_api_registration_t * reg, u32 context)
569 det44_main_t *dm = &det44_main;
570 vl_api_nat_det_session_details_t *rmp;
572 rmp = vl_msg_api_alloc (sizeof (*rmp));
573 clib_memset (rmp, 0, sizeof (*rmp));
574 rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_SESSION_DETAILS + dm->msg_id_base);
575 rmp->in_port = s->in_port;
576 clib_memcpy (rmp->ext_addr, &s->out.ext_host_addr, 4);
577 rmp->ext_port = s->out.ext_host_port;
578 rmp->out_port = s->out.out_port;
579 rmp->state = s->state;
580 rmp->expire = ntohl (s->expire);
581 rmp->context = context;
583 vl_api_send_msg (reg, (u8 *) rmp);
587 vl_api_nat_det_session_dump_t_handler (vl_api_nat_det_session_dump_t * mp)
589 vl_api_registration_t *reg;
590 ip4_address_t user_addr;
592 snat_det_session_t *s, empty_ses;
595 reg = vl_api_client_index_to_registration (mp->client_index);
599 clib_memset (&empty_ses, 0, sizeof (empty_ses));
600 clib_memcpy (&user_addr, mp->user_addr, 4);
601 m = snat_det_map_by_user (&user_addr);
605 s = m->sessions + snat_det_user_ses_offset (&user_addr, m->in_plen);
606 for (i = 0; i < DET44_SES_PER_USER; i++)
609 send_nat_det_session_details (s, reg, mp->context);
614 /* API definitions */
615 #include <vnet/format_fns.h>
616 #include <nat/det44/det44.api.c>
618 /* Set up the API message handling tables */
620 det44_api_hookup (vlib_main_t * vm)
622 det44_main_t *dm = &det44_main;
623 dm->msg_id_base = setup_message_id_table ();
628 * fd.io coding-style-patch-verification: ON
631 * eval: (c-set-style "gnu")