linux-cp: populate mapping vif-sw_if_index only for default-ns
[vpp.git] / src / plugins / nat / det44 / det44_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 /**
17  * @file
18  * @brief Deterministic NAT (CGN) plugin API implementation
19  */
20
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>
27
28 #include <vlibmemory/api.h>
29
30 #define REPLY_MSG_ID_BASE dm->msg_id_base
31 #include <vlibapi/api_helper_macros.h>
32
33 static void
34 vl_api_det44_add_del_map_t_handler (vl_api_det44_add_del_map_t * mp)
35 {
36   det44_main_t *dm = &det44_main;
37   vl_api_det44_add_del_map_reply_t *rmp;
38   int rv = 0;
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);
45 }
46
47 static void
48 vl_api_det44_forward_t_handler (vl_api_det44_forward_t * mp)
49 {
50   det44_main_t *dm = &det44_main;
51   vl_api_det44_forward_reply_t *rmp;
52   int rv = 0;
53   u16 lo_port = 0, hi_port = 0;
54   snat_det_map_t *m;
55   ip4_address_t in_addr, out_addr;
56
57   out_addr.as_u32 = 0;
58   clib_memcpy (&in_addr, mp->in_addr, 4);
59   m = snat_det_map_by_user (&in_addr);
60   if (!m)
61     {
62       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
63       goto send_reply;
64     }
65
66   snat_det_forward (m, &in_addr, &out_addr, &lo_port);
67   hi_port = lo_port + m->ports_per_host - 1;
68
69 send_reply:
70   REPLY_MACRO2 (VL_API_DET44_FORWARD_REPLY,
71   ({
72     rmp->out_port_lo = ntohs (lo_port);
73     rmp->out_port_hi = ntohs (hi_port);
74     clib_memcpy (rmp->out_addr, &out_addr, 4);
75   }))
76 }
77
78 static void
79 vl_api_det44_reverse_t_handler (vl_api_det44_reverse_t * mp)
80 {
81   det44_main_t *dm = &det44_main;
82   vl_api_det44_reverse_reply_t *rmp;
83   int rv = 0;
84   ip4_address_t out_addr, in_addr;
85   snat_det_map_t *m;
86
87   in_addr.as_u32 = 0;
88   clib_memcpy (&out_addr, mp->out_addr, 4);
89   m = snat_det_map_by_out (&out_addr);
90   if (!m)
91     {
92       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
93       goto send_reply;
94     }
95
96   snat_det_reverse (m, &out_addr, htons (mp->out_port), &in_addr);
97
98 send_reply:
99   REPLY_MACRO2 (VL_API_DET44_REVERSE_REPLY,
100   ({
101     clib_memcpy (rmp->in_addr, &in_addr, 4);
102   }))
103 }
104
105 static void
106 sent_det44_map_details (snat_det_map_t * m, vl_api_registration_t * reg,
107                         u32 context)
108 {
109   det44_main_t *dm = &det44_main;
110   vl_api_det44_map_details_t *rmp;
111
112   rmp = vl_msg_api_alloc (sizeof (*rmp));
113   clib_memset (rmp, 0, sizeof (*rmp));
114   rmp->_vl_msg_id = ntohs (VL_API_DET44_MAP_DETAILS + dm->msg_id_base);
115   clib_memcpy (rmp->in_addr, &m->in_addr, 4);
116   rmp->in_plen = m->in_plen;
117   clib_memcpy (rmp->out_addr, &m->out_addr, 4);
118   rmp->out_plen = m->out_plen;
119   rmp->sharing_ratio = htonl (m->sharing_ratio);
120   rmp->ports_per_host = htons (m->ports_per_host);
121   rmp->ses_num = htonl (m->ses_num);
122   rmp->context = context;
123
124   vl_api_send_msg (reg, (u8 *) rmp);
125 }
126
127 static void
128 vl_api_det44_map_dump_t_handler (vl_api_det44_map_dump_t * mp)
129 {
130   det44_main_t *dm = &det44_main;
131   vl_api_registration_t *reg;
132   snat_det_map_t *m;
133
134   reg = vl_api_client_index_to_registration (mp->client_index);
135   if (!reg)
136     return;
137
138   vec_foreach(m, dm->det_maps)
139     sent_det44_map_details(m, reg, mp->context);
140 }
141
142 static void
143 vl_api_det44_close_session_out_t_handler (vl_api_det44_close_session_out_t
144                                           * mp)
145 {
146   det44_main_t *dm = &det44_main;
147   vl_api_det44_close_session_out_reply_t *rmp;
148   ip4_address_t out_addr, ext_addr, in_addr;
149   snat_det_out_key_t key;
150   snat_det_map_t *m;
151   snat_det_session_t *ses;
152   int rv = 0;
153
154   clib_memcpy (&out_addr, mp->out_addr, 4);
155   clib_memcpy (&ext_addr, mp->ext_addr, 4);
156
157   m = snat_det_map_by_out (&out_addr);
158   if (!m)
159     {
160       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
161       goto send_reply;
162     }
163   snat_det_reverse (m, &ext_addr, ntohs (mp->out_port), &in_addr);
164   key.ext_host_addr = ext_addr;
165   key.ext_host_port = mp->ext_port;
166   key.out_port = mp->out_port;
167   ses = snat_det_get_ses_by_out (m, &in_addr, key.as_u64);
168   if (!ses)
169     {
170       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
171       goto send_reply;
172     }
173   snat_det_ses_close (m, ses);
174
175 send_reply:
176   REPLY_MACRO (VL_API_DET44_CLOSE_SESSION_OUT_REPLY);
177 }
178
179 static void
180 vl_api_det44_close_session_in_t_handler (vl_api_det44_close_session_in_t * mp)
181 {
182   det44_main_t *dm = &det44_main;
183   vl_api_det44_close_session_in_reply_t *rmp;
184   ip4_address_t in_addr, ext_addr;
185   snat_det_out_key_t key;
186   snat_det_map_t *m;
187   snat_det_session_t *ses;
188   int rv = 0;
189
190   clib_memcpy (&in_addr, mp->in_addr, 4);
191   clib_memcpy (&ext_addr, mp->ext_addr, 4);
192
193   m = snat_det_map_by_user (&in_addr);
194   if (!m)
195     {
196       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
197       goto send_reply;
198     }
199   key.ext_host_addr = ext_addr;
200   key.ext_host_port = mp->ext_port;
201   ses = snat_det_find_ses_by_in (m, &in_addr, mp->in_port, key);
202   if (!ses)
203     {
204       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
205       goto send_reply;
206     }
207   snat_det_ses_close (m, ses);
208
209 send_reply:
210   REPLY_MACRO (VL_API_DET44_CLOSE_SESSION_OUT_REPLY);
211 }
212
213 static void
214 send_det44_session_details (snat_det_session_t * s,
215                             vl_api_registration_t * reg, u32 context)
216 {
217   det44_main_t *dm = &det44_main;
218   vl_api_det44_session_details_t *rmp;
219
220   rmp = vl_msg_api_alloc (sizeof (*rmp));
221   clib_memset (rmp, 0, sizeof (*rmp));
222   rmp->_vl_msg_id = ntohs (VL_API_DET44_SESSION_DETAILS + dm->msg_id_base);
223   rmp->in_port = s->in_port;
224   clib_memcpy (rmp->ext_addr, &s->out.ext_host_addr, 4);
225   rmp->ext_port = s->out.ext_host_port;
226   rmp->out_port = s->out.out_port;
227   rmp->state = s->state;
228   rmp->expire = ntohl (s->expire);
229   rmp->context = context;
230
231   vl_api_send_msg (reg, (u8 *) rmp);
232 }
233
234 static void
235 vl_api_det44_session_dump_t_handler (vl_api_det44_session_dump_t * mp)
236 {
237   vl_api_registration_t *reg;
238   ip4_address_t user_addr;
239   snat_det_map_t *m;
240   snat_det_session_t *s, empty_ses;
241   u16 i;
242
243   reg = vl_api_client_index_to_registration (mp->client_index);
244   if (!reg)
245     return;
246
247   clib_memset (&empty_ses, 0, sizeof (empty_ses));
248   clib_memcpy (&user_addr, mp->user_addr, 4);
249   m = snat_det_map_by_user (&user_addr);
250   if (!m)
251     return;
252
253   s = m->sessions + snat_det_user_ses_offset (&user_addr, m->in_plen);
254   for (i = 0; i < DET44_SES_PER_USER; i++)
255     {
256       if (s->out.as_u64)
257         send_det44_session_details (s, reg, mp->context);
258       s++;
259     }
260 }
261
262 static void
263   vl_api_det44_plugin_enable_disable_t_handler
264   (vl_api_det44_plugin_enable_disable_t * mp)
265 {
266   det44_main_t *dm = &det44_main;
267   vl_api_det44_plugin_enable_disable_reply_t *rmp;
268   det44_config_t c = { 0 };
269   int rv = 0;
270   if (mp->enable)
271     {
272       c.outside_vrf_id = ntohl (mp->outside_vrf);
273       c.inside_vrf_id = ntohl (mp->inside_vrf);
274       rv = det44_plugin_enable (c);
275     }
276   else
277     {
278       rv = det44_plugin_disable ();
279     }
280   REPLY_MACRO (VL_API_DET44_PLUGIN_ENABLE_DISABLE_REPLY);
281 }
282
283 static void
284   vl_api_det44_interface_add_del_feature_t_handler
285   (vl_api_det44_interface_add_del_feature_t * mp)
286 {
287   det44_main_t *dm = &det44_main;
288   vl_api_det44_interface_add_del_feature_reply_t *rmp;
289   u32 sw_if_index = ntohl (mp->sw_if_index);
290   int rv = 0;
291   VALIDATE_SW_IF_INDEX (mp);
292   rv = det44_interface_add_del (sw_if_index, mp->is_inside, !mp->is_add);
293   BAD_SW_IF_INDEX_LABEL;
294   REPLY_MACRO (VL_API_DET44_INTERFACE_ADD_DEL_FEATURE_REPLY);
295 }
296
297 static void
298 det44_send_interface_details (det44_interface_t * i,
299                               vl_api_registration_t * reg, u32 context)
300 {
301   det44_main_t *dm = &det44_main;
302   vl_api_det44_interface_details_t *rmp;
303
304   rmp = vl_msg_api_alloc (sizeof (*rmp));
305   clib_memset (rmp, 0, sizeof (*rmp));
306   rmp->_vl_msg_id = ntohs (VL_API_DET44_INTERFACE_DETAILS + dm->msg_id_base);
307   rmp->sw_if_index = ntohl (i->sw_if_index);
308   rmp->is_outside = det44_interface_is_outside (i);
309   rmp->is_inside = det44_interface_is_inside (i);
310   rmp->context = context;
311   vl_api_send_msg (reg, (u8 *) rmp);
312 }
313
314 static void
315 vl_api_det44_interface_dump_t_handler (vl_api_det44_interface_dump_t * mp)
316 {
317   det44_main_t *dm = &det44_main;
318   vl_api_registration_t *reg;
319   det44_interface_t *i;
320
321   reg = vl_api_client_index_to_registration (mp->client_index);
322   if (!reg)
323     return;
324
325   pool_foreach (i, dm->interfaces)
326    {
327     det44_send_interface_details(i, reg, mp->context);
328   }
329 }
330
331 static void
332 vl_api_det44_set_timeouts_t_handler (vl_api_det44_set_timeouts_t * mp)
333 {
334   det44_main_t *dm = &det44_main;
335   vl_api_det44_set_timeouts_reply_t *rmp;
336   nat_timeouts_t timeouts;
337   int rv = 0;
338   timeouts.udp = ntohl (mp->udp);
339   timeouts.tcp.established = ntohl (mp->tcp_established);
340   timeouts.tcp.transitory = ntohl (mp->tcp_transitory);
341   timeouts.icmp = ntohl (mp->icmp);
342   rv = det44_set_timeouts (&timeouts);
343   REPLY_MACRO (VL_API_DET44_SET_TIMEOUTS_REPLY);
344 }
345
346 static void
347 vl_api_det44_get_timeouts_t_handler (vl_api_det44_get_timeouts_t * mp)
348 {
349   det44_main_t *dm = &det44_main;
350   vl_api_det44_get_timeouts_reply_t *rmp;
351   nat_timeouts_t timeouts;
352   int rv = 0;
353   timeouts = det44_get_timeouts ();
354   REPLY_MACRO2 (VL_API_DET44_GET_TIMEOUTS_REPLY,
355   ({
356     rmp->udp = htonl (timeouts.udp);
357     rmp->tcp_established = htonl (timeouts.tcp.established);
358     rmp->tcp_transitory = htonl (timeouts.tcp.transitory);
359     rmp->icmp = htonl (timeouts.icmp);
360   }))
361 }
362
363 /*
364  * Obsolete deterministic API to be removed
365  */
366
367 static void
368 vl_api_nat_det_add_del_map_t_handler (vl_api_nat_det_add_del_map_t * mp)
369 {
370   det44_main_t *dm = &det44_main;
371   vl_api_nat_det_add_del_map_reply_t *rmp;
372   int rv = 0;
373   ip4_address_t in_addr, out_addr;
374
375   clib_memcpy (&in_addr, mp->in_addr, 4);
376   clib_memcpy (&out_addr, mp->out_addr, 4);
377   rv = snat_det_add_map (&in_addr, mp->in_plen, &out_addr,
378                          mp->out_plen, mp->is_add);
379   REPLY_MACRO (VL_API_NAT_DET_ADD_DEL_MAP_REPLY);
380 }
381
382 static void
383 vl_api_nat_det_forward_t_handler (vl_api_nat_det_forward_t * mp)
384 {
385   det44_main_t *dm = &det44_main;
386   vl_api_nat_det_forward_reply_t *rmp;
387   int rv = 0;
388   u16 lo_port = 0, hi_port = 0;
389   snat_det_map_t *m;
390   ip4_address_t in_addr, out_addr;
391
392   out_addr.as_u32 = 0;
393   clib_memcpy (&in_addr, mp->in_addr, 4);
394   m = snat_det_map_by_user (&in_addr);
395   if (!m)
396     {
397       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
398       goto send_reply;
399     }
400
401   snat_det_forward (m, &in_addr, &out_addr, &lo_port);
402   hi_port = lo_port + m->ports_per_host - 1;
403
404 send_reply:
405   REPLY_MACRO2 (VL_API_NAT_DET_FORWARD_REPLY,
406   ({
407     rmp->out_port_lo = ntohs (lo_port);
408     rmp->out_port_hi = ntohs (hi_port);
409     clib_memcpy (rmp->out_addr, &out_addr, 4);
410   }))
411 }
412
413 static void
414 vl_api_nat_det_reverse_t_handler (vl_api_nat_det_reverse_t * mp)
415 {
416   det44_main_t *dm = &det44_main;
417   vl_api_nat_det_reverse_reply_t *rmp;
418   int rv = 0;
419   ip4_address_t out_addr, in_addr;
420   snat_det_map_t *m;
421
422   in_addr.as_u32 = 0;
423   clib_memcpy (&out_addr, mp->out_addr, 4);
424   m = snat_det_map_by_out (&out_addr);
425   if (!m)
426     {
427       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
428       goto send_reply;
429     }
430
431   snat_det_reverse (m, &out_addr, htons (mp->out_port), &in_addr);
432
433 send_reply:
434   REPLY_MACRO2 (VL_API_NAT_DET_REVERSE_REPLY,
435   ({
436     clib_memcpy (rmp->in_addr, &in_addr, 4);
437   }))
438 }
439
440 static void
441 sent_nat_det_map_details (snat_det_map_t * m, vl_api_registration_t * reg,
442                           u32 context)
443 {
444   det44_main_t *dm = &det44_main;
445   vl_api_nat_det_map_details_t *rmp;
446
447   rmp = vl_msg_api_alloc (sizeof (*rmp));
448   clib_memset (rmp, 0, sizeof (*rmp));
449   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_MAP_DETAILS + dm->msg_id_base);
450   clib_memcpy (rmp->in_addr, &m->in_addr, 4);
451   rmp->in_plen = m->in_plen;
452   clib_memcpy (rmp->out_addr, &m->out_addr, 4);
453   rmp->out_plen = m->out_plen;
454   rmp->sharing_ratio = htonl (m->sharing_ratio);
455   rmp->ports_per_host = htons (m->ports_per_host);
456   rmp->ses_num = htonl (m->ses_num);
457   rmp->context = context;
458
459   vl_api_send_msg (reg, (u8 *) rmp);
460 }
461
462 static void
463 vl_api_nat_det_map_dump_t_handler (vl_api_nat_det_map_dump_t * mp)
464 {
465   det44_main_t *dm = &det44_main;
466   vl_api_registration_t *reg;
467   snat_det_map_t *m;
468
469   reg = vl_api_client_index_to_registration (mp->client_index);
470   if (!reg)
471     return;
472
473   vec_foreach(m, dm->det_maps)
474     sent_nat_det_map_details(m, reg, mp->context);
475 }
476
477 static void
478 vl_api_nat_det_close_session_out_t_handler (vl_api_nat_det_close_session_out_t
479                                             * mp)
480 {
481   det44_main_t *dm = &det44_main;
482   vl_api_nat_det_close_session_out_reply_t *rmp;
483   ip4_address_t out_addr, ext_addr, in_addr;
484   snat_det_out_key_t key;
485   snat_det_map_t *m;
486   snat_det_session_t *ses;
487   int rv = 0;
488
489   clib_memcpy (&out_addr, mp->out_addr, 4);
490   clib_memcpy (&ext_addr, mp->ext_addr, 4);
491
492   m = snat_det_map_by_out (&out_addr);
493   if (!m)
494     {
495       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
496       goto send_reply;
497     }
498   snat_det_reverse (m, &ext_addr, ntohs (mp->out_port), &in_addr);
499   key.ext_host_addr = ext_addr;
500   key.ext_host_port = mp->ext_port;
501   key.out_port = mp->out_port;
502   ses = snat_det_get_ses_by_out (m, &in_addr, key.as_u64);
503   if (!ses)
504     {
505       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
506       goto send_reply;
507     }
508   snat_det_ses_close (m, ses);
509
510 send_reply:
511   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
512 }
513
514 static void
515 vl_api_nat_det_close_session_in_t_handler (vl_api_nat_det_close_session_in_t *
516                                            mp)
517 {
518   det44_main_t *dm = &det44_main;
519   vl_api_nat_det_close_session_in_reply_t *rmp;
520   ip4_address_t in_addr, ext_addr;
521   snat_det_out_key_t key;
522   snat_det_map_t *m;
523   snat_det_session_t *ses;
524   int rv = 0;
525
526   clib_memcpy (&in_addr, mp->in_addr, 4);
527   clib_memcpy (&ext_addr, mp->ext_addr, 4);
528
529   m = snat_det_map_by_user (&in_addr);
530   if (!m)
531     {
532       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
533       goto send_reply;
534     }
535   key.ext_host_addr = ext_addr;
536   key.ext_host_port = mp->ext_port;
537   ses = snat_det_find_ses_by_in (m, &in_addr, mp->in_port, key);
538   if (!ses)
539     {
540       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
541       goto send_reply;
542     }
543   snat_det_ses_close (m, ses);
544
545 send_reply:
546   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
547 }
548
549 static void
550 send_nat_det_session_details (snat_det_session_t * s,
551                               vl_api_registration_t * reg, u32 context)
552 {
553   det44_main_t *dm = &det44_main;
554   vl_api_nat_det_session_details_t *rmp;
555
556   rmp = vl_msg_api_alloc (sizeof (*rmp));
557   clib_memset (rmp, 0, sizeof (*rmp));
558   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_SESSION_DETAILS + dm->msg_id_base);
559   rmp->in_port = s->in_port;
560   clib_memcpy (rmp->ext_addr, &s->out.ext_host_addr, 4);
561   rmp->ext_port = s->out.ext_host_port;
562   rmp->out_port = s->out.out_port;
563   rmp->state = s->state;
564   rmp->expire = ntohl (s->expire);
565   rmp->context = context;
566
567   vl_api_send_msg (reg, (u8 *) rmp);
568 }
569
570 static void
571 vl_api_nat_det_session_dump_t_handler (vl_api_nat_det_session_dump_t * mp)
572 {
573   vl_api_registration_t *reg;
574   ip4_address_t user_addr;
575   snat_det_map_t *m;
576   snat_det_session_t *s, empty_ses;
577   u16 i;
578
579   reg = vl_api_client_index_to_registration (mp->client_index);
580   if (!reg)
581     return;
582
583   clib_memset (&empty_ses, 0, sizeof (empty_ses));
584   clib_memcpy (&user_addr, mp->user_addr, 4);
585   m = snat_det_map_by_user (&user_addr);
586   if (!m)
587     return;
588
589   s = m->sessions + snat_det_user_ses_offset (&user_addr, m->in_plen);
590   for (i = 0; i < DET44_SES_PER_USER; i++)
591     {
592       if (s->out.as_u64)
593         send_nat_det_session_details (s, reg, mp->context);
594       s++;
595     }
596 }
597
598 /* API definitions */
599 #include <vnet/format_fns.h>
600 #include <nat/det44/det44.api.c>
601
602 /* Set up the API message handling tables */
603 clib_error_t *
604 det44_api_hookup (vlib_main_t * vm)
605 {
606   det44_main_t *dm = &det44_main;
607   dm->msg_id_base = setup_message_id_table ();
608   return 0;
609 }
610
611 /*
612  * fd.io coding-style-patch-verification: ON
613  *
614  * Local Variables:
615  * eval: (c-set-style "gnu")
616  * End:
617  */