SNAT: move API code to separate file
[vpp.git] / src / plugins / snat / snat_api.c
1 /*
2  * Copyright (c) 2017 Cisco and/or its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 /**
17  * @file
18  * @brief SNAT plugin API implementation
19  */
20
21 #include <snat/snat.h>
22 #include <snat/snat_det.h>
23 #include <vlibapi/api.h>
24 #include <vlibmemory/api.h>
25 #include <vlibsocket/api.h>
26 #include <snat/snat_msg_enum.h>
27 #include <vnet/fib/ip4_fib.h>
28
29 /* define message structures */
30 #define vl_typedefs
31 #include <snat/snat_all_api_h.h>
32 #undef vl_typedefs
33
34 /* define generated endian-swappers */
35 #define vl_endianfun
36 #include <snat/snat_all_api_h.h>
37 #undef vl_endianfun
38
39 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
40
41 #define REPLY_MSG_ID_BASE sm->msg_id_base
42 #include <vlibapi/api_helper_macros.h>
43
44 /* Get the API version number */
45 #define vl_api_version(n,v) static u32 api_version=(v);
46 #include <snat/snat_all_api_h.h>
47 #undef vl_api_version
48
49 /* Macro to finish up custom dump fns */
50 #define FINISH                                  \
51     vec_add1 (s, 0);                            \
52     vl_print (handle, (char *)s);               \
53     vec_free (s);                               \
54     return handle;
55
56 static void
57   vl_api_snat_add_address_range_t_handler
58   (vl_api_snat_add_address_range_t * mp)
59 {
60   snat_main_t *sm = &snat_main;
61   vl_api_snat_add_address_range_reply_t *rmp;
62   ip4_address_t this_addr;
63   u32 start_host_order, end_host_order;
64   u32 vrf_id;
65   int i, count;
66   int rv = 0;
67   u32 *tmp;
68
69   if (mp->is_ip4 != 1)
70     {
71       rv = VNET_API_ERROR_UNIMPLEMENTED;
72       goto send_reply;
73     }
74
75   if (sm->static_mapping_only)
76     {
77       rv = VNET_API_ERROR_FEATURE_DISABLED;
78       goto send_reply;
79     }
80
81   tmp = (u32 *) mp->first_ip_address;
82   start_host_order = clib_host_to_net_u32 (tmp[0]);
83   tmp = (u32 *) mp->last_ip_address;
84   end_host_order = clib_host_to_net_u32 (tmp[0]);
85
86   count = (end_host_order - start_host_order) + 1;
87
88   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
89
90   if (count > 1024)
91     clib_warning ("%U - %U, %d addresses...",
92                   format_ip4_address, mp->first_ip_address,
93                   format_ip4_address, mp->last_ip_address, count);
94
95   memcpy (&this_addr.as_u8, mp->first_ip_address, 4);
96
97   for (i = 0; i < count; i++)
98     {
99       if (mp->is_add)
100         snat_add_address (sm, &this_addr, vrf_id);
101       else
102         rv = snat_del_address (sm, this_addr, 0);
103
104       if (rv)
105         goto send_reply;
106
107       increment_v4_address (&this_addr);
108     }
109
110 send_reply:
111   REPLY_MACRO (VL_API_SNAT_ADD_ADDRESS_RANGE_REPLY);
112 }
113
114 static void *vl_api_snat_add_address_range_t_print
115   (vl_api_snat_add_address_range_t * mp, void *handle)
116 {
117   u8 *s;
118
119   s = format (0, "SCRIPT: snat_add_address_range ");
120   s = format (s, "%U ", format_ip4_address, mp->first_ip_address);
121   if (memcmp (mp->first_ip_address, mp->last_ip_address, 4))
122     {
123       s = format (s, " - %U ", format_ip4_address, mp->last_ip_address);
124     }
125   FINISH;
126 }
127
128 static void
129   send_snat_address_details
130   (snat_address_t * a, unix_shared_memory_queue_t * q, u32 context)
131 {
132   vl_api_snat_address_details_t *rmp;
133   snat_main_t *sm = &snat_main;
134
135   rmp = vl_msg_api_alloc (sizeof (*rmp));
136   memset (rmp, 0, sizeof (*rmp));
137   rmp->_vl_msg_id = ntohs (VL_API_SNAT_ADDRESS_DETAILS + sm->msg_id_base);
138   rmp->is_ip4 = 1;
139   clib_memcpy (rmp->ip_address, &(a->addr), 4);
140   if (a->fib_index != ~0)
141     rmp->vrf_id = ntohl (ip4_fib_get (a->fib_index)->table_id);
142   else
143     rmp->vrf_id = ~0;
144   rmp->context = context;
145
146   vl_msg_api_send_shmem (q, (u8 *) & rmp);
147 }
148
149 static void
150 vl_api_snat_address_dump_t_handler (vl_api_snat_address_dump_t * mp)
151 {
152   unix_shared_memory_queue_t *q;
153   snat_main_t *sm = &snat_main;
154   snat_address_t *a;
155
156   q = vl_api_client_index_to_input_queue (mp->client_index);
157   if (q == 0)
158     return;
159
160   /* *INDENT-OFF* */
161   vec_foreach (a, sm->addresses)
162     send_snat_address_details (a, q, mp->context);
163   /* *INDENT-ON* */
164 }
165
166 static void *vl_api_snat_address_dump_t_print
167   (vl_api_snat_address_dump_t * mp, void *handle)
168 {
169   u8 *s;
170
171   s = format (0, "SCRIPT: snat_address_dump ");
172
173   FINISH;
174 }
175
176 static void
177   vl_api_snat_interface_add_del_feature_t_handler
178   (vl_api_snat_interface_add_del_feature_t * mp)
179 {
180   snat_main_t *sm = &snat_main;
181   vl_api_snat_interface_add_del_feature_reply_t *rmp;
182   u8 is_del = mp->is_add == 0;
183   u32 sw_if_index = ntohl (mp->sw_if_index);
184   int rv = 0;
185
186   VALIDATE_SW_IF_INDEX (mp);
187
188   rv = snat_interface_add_del (sw_if_index, mp->is_inside, is_del);
189
190   BAD_SW_IF_INDEX_LABEL;
191
192   REPLY_MACRO (VL_API_SNAT_INTERFACE_ADD_DEL_FEATURE_REPLY);
193 }
194
195 static void *vl_api_snat_interface_add_del_feature_t_print
196   (vl_api_snat_interface_add_del_feature_t * mp, void *handle)
197 {
198   u8 *s;
199
200   s = format (0, "SCRIPT: snat_interface_add_del_feature ");
201   s = format (s, "sw_if_index %d %s %s",
202               clib_host_to_net_u32 (mp->sw_if_index),
203               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
204
205   FINISH;
206 }
207
208 static void
209   send_snat_interface_details
210   (snat_interface_t * i, unix_shared_memory_queue_t * q, u32 context)
211 {
212   vl_api_snat_interface_details_t *rmp;
213   snat_main_t *sm = &snat_main;
214
215   rmp = vl_msg_api_alloc (sizeof (*rmp));
216   memset (rmp, 0, sizeof (*rmp));
217   rmp->_vl_msg_id = ntohs (VL_API_SNAT_INTERFACE_DETAILS + sm->msg_id_base);
218   rmp->sw_if_index = ntohl (i->sw_if_index);
219   rmp->is_inside = i->is_inside;
220   rmp->context = context;
221
222   vl_msg_api_send_shmem (q, (u8 *) & rmp);
223 }
224
225 static void
226 vl_api_snat_interface_dump_t_handler (vl_api_snat_interface_dump_t * mp)
227 {
228   unix_shared_memory_queue_t *q;
229   snat_main_t *sm = &snat_main;
230   snat_interface_t *i;
231
232   q = vl_api_client_index_to_input_queue (mp->client_index);
233   if (q == 0)
234     return;
235
236   /* *INDENT-OFF* */
237   pool_foreach (i, sm->interfaces,
238   ({
239     send_snat_interface_details(i, q, mp->context);
240   }));
241   /* *INDENT-ON* */
242 }
243
244 static void *vl_api_snat_interface_dump_t_print
245   (vl_api_snat_interface_dump_t * mp, void *handle)
246 {
247   u8 *s;
248
249   s = format (0, "SCRIPT: snat_interface_dump ");
250
251   FINISH;
252 } static void
253   vl_api_snat_add_static_mapping_t_handler
254   (vl_api_snat_add_static_mapping_t * mp)
255 {
256   snat_main_t *sm = &snat_main;
257   vl_api_snat_add_static_mapping_reply_t *rmp;
258   ip4_address_t local_addr, external_addr;
259   u16 local_port = 0, external_port = 0;
260   u32 vrf_id, external_sw_if_index;
261   int rv = 0;
262   snat_protocol_t proto;
263
264   if (mp->is_ip4 != 1)
265     {
266       rv = VNET_API_ERROR_UNIMPLEMENTED;
267       goto send_reply;
268     }
269
270   memcpy (&local_addr.as_u8, mp->local_ip_address, 4);
271   memcpy (&external_addr.as_u8, mp->external_ip_address, 4);
272   if (mp->addr_only == 0)
273     {
274       local_port = clib_net_to_host_u16 (mp->local_port);
275       external_port = clib_net_to_host_u16 (mp->external_port);
276     }
277   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
278   external_sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
279   proto = ip_proto_to_snat_proto (mp->protocol);
280
281   rv = snat_add_static_mapping (local_addr, external_addr, local_port,
282                                 external_port, vrf_id, mp->addr_only,
283                                 external_sw_if_index, proto, mp->is_add);
284
285 send_reply:
286   REPLY_MACRO (VL_API_SNAT_ADD_ADDRESS_RANGE_REPLY);
287 }
288
289 static void *vl_api_snat_add_static_mapping_t_print
290   (vl_api_snat_add_static_mapping_t * mp, void *handle)
291 {
292   u8 *s;
293
294   s = format (0, "SCRIPT: snat_add_static_mapping ");
295   s = format (s, "protocol %d local_addr %U external_addr %U ",
296               mp->protocol,
297               format_ip4_address, mp->local_ip_address,
298               format_ip4_address, mp->external_ip_address);
299
300   if (mp->addr_only == 0)
301     s = format (s, "local_port %d external_port %d ",
302                 clib_net_to_host_u16 (mp->local_port),
303                 clib_net_to_host_u16 (mp->external_port));
304
305   if (mp->vrf_id != ~0)
306     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
307
308   if (mp->external_sw_if_index != ~0)
309     s = format (s, "external_sw_if_index %d",
310                 clib_net_to_host_u32 (mp->external_sw_if_index));
311   FINISH;
312 }
313
314 static void
315   send_snat_static_mapping_details
316   (snat_static_mapping_t * m, unix_shared_memory_queue_t * q, u32 context)
317 {
318   vl_api_snat_static_mapping_details_t *rmp;
319   snat_main_t *sm = &snat_main;
320
321   rmp = vl_msg_api_alloc (sizeof (*rmp));
322   memset (rmp, 0, sizeof (*rmp));
323   rmp->_vl_msg_id =
324     ntohs (VL_API_SNAT_STATIC_MAPPING_DETAILS + sm->msg_id_base);
325   rmp->is_ip4 = 1;
326   rmp->addr_only = m->addr_only;
327   clib_memcpy (rmp->local_ip_address, &(m->local_addr), 4);
328   clib_memcpy (rmp->external_ip_address, &(m->external_addr), 4);
329   rmp->local_port = htons (m->local_port);
330   rmp->external_port = htons (m->external_port);
331   rmp->external_sw_if_index = ~0;
332   rmp->vrf_id = htonl (m->vrf_id);
333   rmp->protocol = snat_proto_to_ip_proto (m->proto);
334   rmp->context = context;
335
336   vl_msg_api_send_shmem (q, (u8 *) & rmp);
337 }
338
339 static void
340   send_snat_static_map_resolve_details
341   (snat_static_map_resolve_t * m, unix_shared_memory_queue_t * q, u32 context)
342 {
343   vl_api_snat_static_mapping_details_t *rmp;
344   snat_main_t *sm = &snat_main;
345
346   rmp = vl_msg_api_alloc (sizeof (*rmp));
347   memset (rmp, 0, sizeof (*rmp));
348   rmp->_vl_msg_id =
349     ntohs (VL_API_SNAT_STATIC_MAPPING_DETAILS + sm->msg_id_base);
350   rmp->is_ip4 = 1;
351   rmp->addr_only = m->addr_only;
352   clib_memcpy (rmp->local_ip_address, &(m->l_addr), 4);
353   rmp->local_port = htons (m->l_port);
354   rmp->external_port = htons (m->e_port);
355   rmp->external_sw_if_index = htonl (m->sw_if_index);
356   rmp->vrf_id = htonl (m->vrf_id);
357   rmp->protocol = snat_proto_to_ip_proto (m->proto);
358   rmp->context = context;
359
360   vl_msg_api_send_shmem (q, (u8 *) & rmp);
361 }
362
363 static void
364   vl_api_snat_static_mapping_dump_t_handler
365   (vl_api_snat_static_mapping_dump_t * mp)
366 {
367   unix_shared_memory_queue_t *q;
368   snat_main_t *sm = &snat_main;
369   snat_static_mapping_t *m;
370   snat_static_map_resolve_t *rp;
371   int j;
372
373   q = vl_api_client_index_to_input_queue (mp->client_index);
374   if (q == 0)
375     return;
376
377   /* *INDENT-OFF* */
378   pool_foreach (m, sm->static_mappings,
379   ({
380       send_snat_static_mapping_details (m, q, mp->context);
381   }));
382   /* *INDENT-ON* */
383
384   for (j = 0; j < vec_len (sm->to_resolve); j++)
385     {
386       rp = sm->to_resolve + j;
387       send_snat_static_map_resolve_details (rp, q, mp->context);
388     }
389 }
390
391 static void *vl_api_snat_static_mapping_dump_t_print
392   (vl_api_snat_static_mapping_dump_t * mp, void *handle)
393 {
394   u8 *s;
395
396   s = format (0, "SCRIPT: snat_static_mapping_dump ");
397
398   FINISH;
399 }
400
401 static void
402 vl_api_snat_control_ping_t_handler (vl_api_snat_control_ping_t * mp)
403 {
404   vl_api_snat_control_ping_reply_t *rmp;
405   snat_main_t *sm = &snat_main;
406   int rv = 0;
407
408   /* *INDENT-OFF* */
409   REPLY_MACRO2 (VL_API_SNAT_CONTROL_PING_REPLY,
410   ({
411     rmp->vpe_pid = ntohl (getpid ());
412   }));
413   /* *INDENT-ON* */
414 }
415
416 static void *vl_api_snat_control_ping_t_print
417   (vl_api_snat_control_ping_t * mp, void *handle)
418 {
419   u8 *s;
420
421   s = format (0, "SCRIPT: snat_control_ping ");
422
423   FINISH;
424 }
425
426 static void
427 vl_api_snat_show_config_t_handler (vl_api_snat_show_config_t * mp)
428 {
429   vl_api_snat_show_config_reply_t *rmp;
430   snat_main_t *sm = &snat_main;
431   int rv = 0;
432
433   /* *INDENT-OFF* */
434   REPLY_MACRO2 (VL_API_SNAT_SHOW_CONFIG_REPLY,
435   ({
436     rmp->translation_buckets = htonl (sm->translation_buckets);
437     rmp->translation_memory_size = htonl (sm->translation_memory_size);
438     rmp->user_buckets = htonl (sm->user_buckets);
439     rmp->user_memory_size = htonl (sm->user_memory_size);
440     rmp->max_translations_per_user = htonl (sm->max_translations_per_user);
441     rmp->outside_vrf_id = htonl (sm->outside_vrf_id);
442     rmp->inside_vrf_id = htonl (sm->inside_vrf_id);
443     rmp->static_mapping_only = sm->static_mapping_only;
444     rmp->static_mapping_connection_tracking =
445       sm->static_mapping_connection_tracking;
446     rmp->deterministic = sm->deterministic;
447   }));
448   /* *INDENT-ON* */
449 }
450
451 static void *vl_api_snat_show_config_t_print
452   (vl_api_snat_show_config_t * mp, void *handle)
453 {
454   u8 *s;
455
456   s = format (0, "SCRIPT: snat_show_config ");
457
458   FINISH;
459 }
460
461 static void
462 vl_api_snat_set_workers_t_handler (vl_api_snat_set_workers_t * mp)
463 {
464   snat_main_t *sm = &snat_main;
465   vl_api_snat_set_workers_reply_t *rmp;
466   int rv = 0;
467   uword *bitmap = 0;
468   u64 mask = clib_net_to_host_u64 (mp->worker_mask);
469
470   if (sm->num_workers < 2)
471     {
472       rv = VNET_API_ERROR_FEATURE_DISABLED;
473       goto send_reply;
474     }
475
476   bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
477   rv = snat_set_workers (bitmap);
478   clib_bitmap_free (bitmap);
479
480 send_reply:
481   REPLY_MACRO (VL_API_SNAT_SET_WORKERS_REPLY);
482 }
483
484 static void *vl_api_snat_set_workers_t_print
485   (vl_api_snat_set_workers_t * mp, void *handle)
486 {
487   u8 *s;
488   uword *bitmap = 0;
489   u8 first = 1;
490   int i;
491   u64 mask = clib_net_to_host_u64 (mp->worker_mask);
492
493   s = format (0, "SCRIPT: snat_set_workers ");
494   bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
495   /* *INDENT-OFF* */
496   clib_bitmap_foreach (i, bitmap,
497     ({
498       if (first)
499         s = format (s, "%d", i);
500       else
501         s = format (s, ",%d", i);
502       first = 0;
503     }));
504   /* *INDENT-ON* */
505   clib_bitmap_free (bitmap);
506   FINISH;
507 }
508
509 static void
510   send_snat_worker_details
511   (u32 worker_index, unix_shared_memory_queue_t * q, u32 context)
512 {
513   vl_api_snat_worker_details_t *rmp;
514   snat_main_t *sm = &snat_main;
515   vlib_worker_thread_t *w =
516     vlib_worker_threads + worker_index + sm->first_worker_index;
517
518   rmp = vl_msg_api_alloc (sizeof (*rmp));
519   memset (rmp, 0, sizeof (*rmp));
520   rmp->_vl_msg_id = ntohs (VL_API_SNAT_WORKER_DETAILS + sm->msg_id_base);
521   rmp->context = context;
522   rmp->worker_index = htonl (worker_index);
523   rmp->lcore_id = htonl (w->lcore_id);
524   strncpy ((char *) rmp->name, (char *) w->name, ARRAY_LEN (rmp->name) - 1);
525
526   vl_msg_api_send_shmem (q, (u8 *) & rmp);
527 }
528
529 static void
530 vl_api_snat_worker_dump_t_handler (vl_api_snat_worker_dump_t * mp)
531 {
532   unix_shared_memory_queue_t *q;
533   snat_main_t *sm = &snat_main;
534   u32 *worker_index;
535
536   q = vl_api_client_index_to_input_queue (mp->client_index);
537   if (q == 0)
538     return;
539
540   /* *INDENT-OFF* */
541   vec_foreach (worker_index, sm->workers)
542     send_snat_worker_details(*worker_index, q, mp->context);
543   /* *INDENT-ON* */
544 }
545
546 static void *vl_api_snat_worker_dump_t_print
547   (vl_api_snat_worker_dump_t * mp, void *handle)
548 {
549   u8 *s;
550
551   s = format (0, "SCRIPT: snat_worker_dump ");
552
553   FINISH;
554 }
555
556 static void
557   vl_api_snat_add_del_interface_addr_t_handler
558   (vl_api_snat_add_del_interface_addr_t * mp)
559 {
560   snat_main_t *sm = &snat_main;
561   vl_api_snat_add_del_interface_addr_reply_t *rmp;
562   u8 is_del = mp->is_add == 0;
563   u32 sw_if_index = ntohl (mp->sw_if_index);
564   int rv = 0;
565
566   VALIDATE_SW_IF_INDEX (mp);
567
568   rv = snat_add_interface_address (sm, sw_if_index, is_del);
569
570   BAD_SW_IF_INDEX_LABEL;
571
572   REPLY_MACRO (VL_API_SNAT_ADD_DEL_INTERFACE_ADDR_REPLY);
573 }
574
575 static void *vl_api_snat_add_del_interface_addr_t_print
576   (vl_api_snat_add_del_interface_addr_t * mp, void *handle)
577 {
578   u8 *s;
579
580   s = format (0, "SCRIPT: snat_add_del_interface_addr ");
581   s = format (s, "sw_if_index %d %s",
582               clib_host_to_net_u32 (mp->sw_if_index),
583               mp->is_add ? "" : "del");
584
585   FINISH;
586 }
587
588 static void
589   send_snat_interface_addr_details
590   (u32 sw_if_index, unix_shared_memory_queue_t * q, u32 context)
591 {
592   vl_api_snat_interface_addr_details_t *rmp;
593   snat_main_t *sm = &snat_main;
594
595   rmp = vl_msg_api_alloc (sizeof (*rmp));
596   memset (rmp, 0, sizeof (*rmp));
597   rmp->_vl_msg_id =
598     ntohs (VL_API_SNAT_INTERFACE_ADDR_DETAILS + sm->msg_id_base);
599   rmp->sw_if_index = ntohl (sw_if_index);
600   rmp->context = context;
601
602   vl_msg_api_send_shmem (q, (u8 *) & rmp);
603 }
604
605 static void
606   vl_api_snat_interface_addr_dump_t_handler
607   (vl_api_snat_interface_addr_dump_t * mp)
608 {
609   unix_shared_memory_queue_t *q;
610   snat_main_t *sm = &snat_main;
611   u32 *i;
612
613   q = vl_api_client_index_to_input_queue (mp->client_index);
614   if (q == 0)
615     return;
616
617   /* *INDENT-OFF* */
618   vec_foreach (i, sm->auto_add_sw_if_indices)
619     send_snat_interface_addr_details(*i, q, mp->context);
620   /* *INDENT-ON* */
621 }
622
623 static void *vl_api_snat_interface_addr_dump_t_print
624   (vl_api_snat_interface_addr_dump_t * mp, void *handle)
625 {
626   u8 *s;
627
628   s = format (0, "SCRIPT: snat_interface_addr_dump ");
629
630   FINISH;
631 }
632
633 static void
634   vl_api_snat_ipfix_enable_disable_t_handler
635   (vl_api_snat_ipfix_enable_disable_t * mp)
636 {
637   snat_main_t *sm = &snat_main;
638   vl_api_snat_ipfix_enable_disable_reply_t *rmp;
639   int rv = 0;
640
641   rv = snat_ipfix_logging_enable_disable (mp->enable,
642                                           clib_host_to_net_u32
643                                           (mp->domain_id),
644                                           clib_host_to_net_u16
645                                           (mp->src_port));
646
647   REPLY_MACRO (VL_API_SNAT_IPFIX_ENABLE_DISABLE_REPLY);
648 }
649
650 static void *vl_api_snat_ipfix_enable_disable_t_print
651   (vl_api_snat_ipfix_enable_disable_t * mp, void *handle)
652 {
653   u8 *s;
654
655   s = format (0, "SCRIPT: snat_ipfix_enable_disable ");
656   if (mp->domain_id)
657     s = format (s, "domain %d ", clib_net_to_host_u32 (mp->domain_id));
658   if (mp->src_port)
659     s = format (s, "src_port %d ", clib_net_to_host_u16 (mp->src_port));
660   if (!mp->enable)
661     s = format (s, "disable ");
662
663   FINISH;
664 }
665
666 static void
667   send_snat_user_details
668   (snat_user_t * u, unix_shared_memory_queue_t * q, u32 context)
669 {
670   vl_api_snat_user_details_t *rmp;
671   snat_main_t *sm = &snat_main;
672   ip4_fib_t *fib_table;
673
674   rmp = vl_msg_api_alloc (sizeof (*rmp));
675   memset (rmp, 0, sizeof (*rmp));
676   rmp->_vl_msg_id = ntohs (VL_API_SNAT_USER_DETAILS + sm->msg_id_base);
677
678   fib_table = ip4_fib_get (u->fib_index);
679   rmp->vrf_id = ntohl (fib_table->table_id);
680
681   rmp->is_ip4 = 1;
682   clib_memcpy (rmp->ip_address, &(u->addr), 4);
683   rmp->nsessions = ntohl (u->nsessions);
684   rmp->nstaticsessions = ntohl (u->nstaticsessions);
685   rmp->context = context;
686
687   vl_msg_api_send_shmem (q, (u8 *) & rmp);
688 }
689
690 static void
691 vl_api_snat_user_dump_t_handler (vl_api_snat_user_dump_t * mp)
692 {
693   unix_shared_memory_queue_t *q;
694   snat_main_t *sm = &snat_main;
695   snat_main_per_thread_data_t *tsm;
696   snat_user_t *u;
697
698   q = vl_api_client_index_to_input_queue (mp->client_index);
699   if (q == 0)
700     return;
701
702   /* *INDENT-OFF* */
703   vec_foreach (tsm, sm->per_thread_data)
704     vec_foreach (u, tsm->users)
705       send_snat_user_details (u, q, mp->context);
706   /* *INDENT-ON* */
707 }
708
709 static void *vl_api_snat_user_dump_t_print
710   (vl_api_snat_user_dump_t * mp, void *handle)
711 {
712   u8 *s;
713
714   s = format (0, "SCRIPT: snat_user_dump ");
715
716   FINISH;
717 }
718
719 static void
720   send_snat_user_session_details
721   (snat_session_t * s, unix_shared_memory_queue_t * q, u32 context)
722 {
723   vl_api_snat_user_session_details_t *rmp;
724   snat_main_t *sm = &snat_main;
725
726   rmp = vl_msg_api_alloc (sizeof (*rmp));
727   memset (rmp, 0, sizeof (*rmp));
728   rmp->_vl_msg_id =
729     ntohs (VL_API_SNAT_USER_SESSION_DETAILS + sm->msg_id_base);
730   rmp->is_ip4 = 1;
731   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
732   rmp->outside_port = s->out2in.port;
733   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
734   rmp->inside_port = s->in2out.port;
735   rmp->protocol = ntohs (snat_proto_to_ip_proto (s->in2out.protocol));
736   rmp->is_static = s->flags & SNAT_SESSION_FLAG_STATIC_MAPPING ? 1 : 0;
737   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
738   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
739   rmp->total_pkts = ntohl (s->total_pkts);
740   rmp->context = context;
741
742   vl_msg_api_send_shmem (q, (u8 *) & rmp);
743 }
744
745 static void
746   vl_api_snat_user_session_dump_t_handler
747   (vl_api_snat_user_session_dump_t * mp)
748 {
749   unix_shared_memory_queue_t *q;
750   snat_main_t *sm = &snat_main;
751   snat_main_per_thread_data_t *tsm;
752   snat_session_t *s;
753   clib_bihash_kv_8_8_t key, value;
754   snat_user_key_t ukey;
755   snat_user_t *u;
756   u32 session_index, head_index, elt_index;
757   dlist_elt_t *head, *elt;
758
759   q = vl_api_client_index_to_input_queue (mp->client_index);
760   if (q == 0)
761     return;
762   if (!mp->is_ip4)
763     return;
764
765   clib_memcpy (&ukey.addr, mp->ip_address, 4);
766   ukey.fib_index = ip4_fib_index_from_table_id (ntohl (mp->vrf_id));
767   key.key = ukey.as_u64;
768   if (!clib_bihash_search_8_8 (&sm->worker_by_in, &key, &value))
769     tsm = vec_elt_at_index (sm->per_thread_data, value.value);
770   else
771     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
772   if (clib_bihash_search_8_8 (&sm->user_hash, &key, &value))
773     return;
774   u = pool_elt_at_index (tsm->users, value.value);
775   if (!u->nsessions && !u->nstaticsessions)
776     return;
777
778   head_index = u->sessions_per_user_list_head_index;
779   head = pool_elt_at_index (tsm->list_pool, head_index);
780   elt_index = head->next;
781   elt = pool_elt_at_index (tsm->list_pool, elt_index);
782   session_index = elt->value;
783   while (session_index != ~0)
784     {
785       s = pool_elt_at_index (tsm->sessions, session_index);
786
787       send_snat_user_session_details (s, q, mp->context);
788
789       elt_index = elt->next;
790       elt = pool_elt_at_index (tsm->list_pool, elt_index);
791       session_index = elt->value;
792     }
793 }
794
795 static void *vl_api_snat_user_session_dump_t_print
796   (vl_api_snat_user_session_dump_t * mp, void *handle)
797 {
798   u8 *s;
799
800   s = format (0, "SCRIPT: snat_user_session_dump ");
801   s = format (s, "ip_address %U vrf_id %d\n",
802               format_ip4_address, mp->ip_address,
803               clib_net_to_host_u32 (mp->vrf_id));
804
805   FINISH;
806 }
807
808 static void
809 vl_api_snat_add_det_map_t_handler (vl_api_snat_add_det_map_t * mp)
810 {
811   snat_main_t *sm = &snat_main;
812   vl_api_snat_add_det_map_reply_t *rmp;
813   int rv = 0;
814   ip4_address_t in_addr, out_addr;
815
816   clib_memcpy (&in_addr, mp->in_addr, 4);
817   clib_memcpy (&out_addr, mp->out_addr, 4);
818   rv = snat_det_add_map (sm, &in_addr, mp->in_plen, &out_addr,
819                          mp->out_plen, mp->is_add);
820
821   REPLY_MACRO (VL_API_SNAT_ADD_DET_MAP_REPLY);
822 }
823
824 static void *vl_api_snat_add_det_map_t_print
825   (vl_api_snat_add_det_map_t * mp, void *handle)
826 {
827   u8 *s;
828
829   s = format (0, "SCRIPT: snat_add_det_map ");
830   s = format (s, "inside address %U/%d outside address %U/%d\n",
831               format_ip4_address, mp->in_addr, mp->in_plen,
832               format_ip4_address, mp->out_addr, mp->out_plen);
833
834   FINISH;
835 }
836
837 static void
838 vl_api_snat_det_forward_t_handler (vl_api_snat_det_forward_t * mp)
839 {
840   snat_main_t *sm = &snat_main;
841   vl_api_snat_det_forward_reply_t *rmp;
842   int rv = 0;
843   u16 lo_port = 0, hi_port = 0;
844   snat_det_map_t *dm;
845   ip4_address_t in_addr, out_addr;
846
847   out_addr.as_u32 = 0;
848   clib_memcpy (&in_addr, mp->in_addr, 4);
849   dm = snat_det_map_by_user (sm, &in_addr);
850   if (!dm)
851     {
852       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
853       goto send_reply;
854     }
855
856   snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
857   hi_port = lo_port + dm->ports_per_host - 1;
858
859 send_reply:
860   /* *INDENT-OFF* */
861   REPLY_MACRO2 (VL_API_SNAT_DET_FORWARD_REPLY,
862   ({
863     rmp->out_port_lo = ntohs (lo_port);
864     rmp->out_port_hi = ntohs (hi_port);
865     rmp->is_ip4 = 1;
866     memset (rmp->out_addr, 0, 16);
867     clib_memcpy (rmp->out_addr, &out_addr, 4);
868   }))
869   /* *INDENT-ON* */
870 }
871
872 static void *vl_api_snat_det_forward_t_print
873   (vl_api_snat_det_forward_t * mp, void *handle)
874 {
875   u8 *s;
876
877   s = format (0, "SCRIPT: smat_det_forward_t");
878   s = format (s, "inside ip address %U\n", format_ip4_address, mp->in_addr);
879
880   FINISH;
881 }
882
883 static void
884 vl_api_snat_det_reverse_t_handler (vl_api_snat_det_reverse_t * mp)
885 {
886   snat_main_t *sm = &snat_main;
887   vl_api_snat_det_reverse_reply_t *rmp;
888   int rv = 0;
889   ip4_address_t out_addr, in_addr;
890   snat_det_map_t *dm;
891
892   in_addr.as_u32 = 0;
893   clib_memcpy (&out_addr, mp->out_addr, 4);
894   dm = snat_det_map_by_out (sm, &out_addr);
895   if (!dm)
896     {
897       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
898       goto send_reply;
899     }
900
901   snat_det_reverse (dm, &out_addr, htons (mp->out_port), &in_addr);
902
903 send_reply:
904   /* *INDENT-OFF* */
905   REPLY_MACRO2 (VL_API_SNAT_DET_REVERSE_REPLY,
906   ({
907     rmp->is_ip4 = 1;
908     memset (rmp->in_addr, 0, 16);
909     clib_memcpy (rmp->in_addr, &in_addr, 4);
910   }))
911   /* *INDENT-ON* */
912 }
913
914 static void *vl_api_snat_det_reverse_t_print
915   (vl_api_snat_det_reverse_t * mp, void *handle)
916 {
917   u8 *s;
918
919   s = format (0, "SCRIPT: smat_det_reverse_t");
920   s = format (s, "outside ip address %U outside port %d",
921               format_ip4_address, mp->out_addr, ntohs (mp->out_port));
922
923   FINISH;
924 }
925
926 static void
927   sent_snat_det_map_details
928   (snat_det_map_t * m, unix_shared_memory_queue_t * q, u32 context)
929 {
930   vl_api_snat_det_map_details_t *rmp;
931   snat_main_t *sm = &snat_main;
932
933   rmp = vl_msg_api_alloc (sizeof (*rmp));
934   memset (rmp, 0, sizeof (*rmp));
935   rmp->_vl_msg_id = ntohs (VL_API_SNAT_DET_MAP_DETAILS + sm->msg_id_base);
936   rmp->is_ip4 = 1;
937   clib_memcpy (rmp->in_addr, &m->in_addr, 4);
938   rmp->in_plen = m->in_plen;
939   clib_memcpy (rmp->out_addr, &m->out_addr, 4);
940   rmp->out_plen = m->out_plen;
941   rmp->sharing_ratio = htonl (m->sharing_ratio);
942   rmp->ports_per_host = htons (m->ports_per_host);
943   rmp->ses_num = htonl (m->ses_num);
944   rmp->context = context;
945
946   vl_msg_api_send_shmem (q, (u8 *) & rmp);
947 }
948
949 static void
950 vl_api_snat_det_map_dump_t_handler (vl_api_snat_det_map_dump_t * mp)
951 {
952   unix_shared_memory_queue_t *q;
953   snat_main_t *sm = &snat_main;
954   snat_det_map_t *m;
955
956   q = vl_api_client_index_to_input_queue (mp->client_index);
957   if (q == 0)
958     return;
959
960   /* *INDENT-OFF* */
961   vec_foreach(m, sm->det_maps)
962     sent_snat_det_map_details(m, q, mp->context);
963   /* *INDENT-ON* */
964 }
965
966 static void *vl_api_snat_det_map_dump_t_print
967   (vl_api_snat_det_map_dump_t * mp, void *handle)
968 {
969   u8 *s;
970
971   s = format (0, "SCRIPT: snat_det_map_dump ");
972
973   FINISH;
974 }
975
976 static void
977 vl_api_snat_det_set_timeouts_t_handler (vl_api_snat_det_set_timeouts_t * mp)
978 {
979   snat_main_t *sm = &snat_main;
980   vl_api_snat_det_set_timeouts_reply_t *rmp;
981   int rv = 0;
982
983   sm->udp_timeout = ntohl (mp->udp);
984   sm->tcp_established_timeout = ntohl (mp->tcp_established);
985   sm->tcp_transitory_timeout = ntohl (mp->tcp_transitory);
986   sm->icmp_timeout = ntohl (mp->icmp);
987
988   REPLY_MACRO (VL_API_SNAT_DET_SET_TIMEOUTS_REPLY);
989 }
990
991 static void *vl_api_snat_det_set_timeouts_t_print
992   (vl_api_snat_det_set_timeouts_t * mp, void *handle)
993 {
994   u8 *s;
995
996   s = format (0, "SCRIPT: snat_det_set_timeouts ");
997   s = format (s, "udp %d tcp_established %d tcp_transitory %d icmp %d\n",
998               ntohl (mp->udp),
999               ntohl (mp->tcp_established),
1000               ntohl (mp->tcp_transitory), ntohl (mp->icmp));
1001
1002   FINISH;
1003 }
1004
1005 static void
1006 vl_api_snat_det_get_timeouts_t_handler (vl_api_snat_det_get_timeouts_t * mp)
1007 {
1008   snat_main_t *sm = &snat_main;
1009   vl_api_snat_det_get_timeouts_reply_t *rmp;
1010   int rv = 0;
1011
1012   /* *INDENT-OFF* */
1013   REPLY_MACRO2 (VL_API_SNAT_DET_GET_TIMEOUTS_REPLY,
1014   ({
1015     rmp->udp = htonl (sm->udp_timeout);
1016     rmp->tcp_established = htonl (sm->tcp_established_timeout);
1017     rmp->tcp_transitory = htonl (sm->tcp_transitory_timeout);
1018     rmp->icmp = htonl (sm->icmp_timeout);
1019   }))
1020   /* *INDENT-ON* */
1021 }
1022
1023 static void *vl_api_snat_det_get_timeouts_t_print
1024   (vl_api_snat_det_get_timeouts_t * mp, void *handle)
1025 {
1026   u8 *s;
1027
1028   s = format (0, "SCRIPT: snat_det_get_timeouts");
1029
1030   FINISH;
1031 }
1032
1033 static void
1034   vl_api_snat_det_close_session_out_t_handler
1035   (vl_api_snat_det_close_session_out_t * mp)
1036 {
1037   snat_main_t *sm = &snat_main;
1038   vl_api_snat_det_close_session_out_reply_t *rmp;
1039   ip4_address_t out_addr, ext_addr, in_addr;
1040   snat_det_out_key_t key;
1041   snat_det_map_t *dm;
1042   snat_det_session_t *ses;
1043   int rv = 0;
1044
1045   clib_memcpy (&out_addr, mp->out_addr, 4);
1046   clib_memcpy (&ext_addr, mp->ext_addr, 4);
1047
1048   dm = snat_det_map_by_out (sm, &out_addr);
1049   if (!dm)
1050     {
1051       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1052       goto send_reply;
1053     }
1054   snat_det_reverse (dm, &ext_addr, ntohs (mp->out_port), &in_addr);
1055   key.ext_host_addr = ext_addr;
1056   key.ext_host_port = mp->ext_port;
1057   key.out_port = mp->out_port;
1058   ses = snat_det_get_ses_by_out (dm, &in_addr, key.as_u64);
1059   if (!ses)
1060     {
1061       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1062       goto send_reply;
1063     }
1064   snat_det_ses_close (dm, ses);
1065
1066 send_reply:
1067   REPLY_MACRO (VL_API_SNAT_DET_CLOSE_SESSION_OUT_REPLY);
1068 }
1069
1070 static void *vl_api_snat_det_close_session_out_t_print
1071   (vl_api_snat_det_close_session_out_t * mp, void *handle)
1072 {
1073   u8 *s;
1074
1075   s = format (0, "SCRIPT: snat_det_close_session_out ");
1076   s = format (s, "out_addr %U out_port %d "
1077               "ext_addr %U ext_port %d\n",
1078               format_ip4_address, mp->out_addr, ntohs (mp->out_port),
1079               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
1080
1081   FINISH;
1082 }
1083
1084 static void
1085   vl_api_snat_det_close_session_in_t_handler
1086   (vl_api_snat_det_close_session_in_t * mp)
1087 {
1088   snat_main_t *sm = &snat_main;
1089   vl_api_snat_det_close_session_in_reply_t *rmp;
1090   ip4_address_t in_addr, ext_addr;
1091   snat_det_out_key_t key;
1092   snat_det_map_t *dm;
1093   snat_det_session_t *ses;
1094   int rv = 0;
1095
1096   clib_memcpy (&in_addr, mp->in_addr, 4);
1097   clib_memcpy (&ext_addr, mp->ext_addr, 4);
1098
1099   dm = snat_det_map_by_user (sm, &in_addr);
1100   if (!dm)
1101     {
1102       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1103       goto send_reply;
1104     }
1105   key.ext_host_addr = ext_addr;
1106   key.ext_host_port = mp->ext_port;
1107   ses = snat_det_find_ses_by_in (dm, &in_addr, mp->in_port, key);
1108   if (!ses)
1109     {
1110       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1111       goto send_reply;
1112     }
1113   snat_det_ses_close (dm, ses);
1114
1115 send_reply:
1116   REPLY_MACRO (VL_API_SNAT_DET_CLOSE_SESSION_OUT_REPLY);
1117 }
1118
1119 static void *vl_api_snat_det_close_session_in_t_print
1120   (vl_api_snat_det_close_session_in_t * mp, void *handle)
1121 {
1122   u8 *s;
1123   s = format (0, "SCRIPT: snat_det_close_session_in ");
1124   s = format (s, "in_addr %U in_port %d "
1125               "ext_addr %U ext_port %d\n",
1126               format_ip4_address, mp->in_addr, ntohs (mp->in_port),
1127               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
1128
1129   FINISH;
1130 }
1131
1132 static void
1133   send_snat_det_session_details
1134   (snat_det_session_t * s, unix_shared_memory_queue_t * q, u32 context)
1135 {
1136   vl_api_snat_det_session_details_t *rmp;
1137   snat_main_t *sm = &snat_main;
1138
1139   rmp = vl_msg_api_alloc (sizeof (*rmp));
1140   memset (rmp, 0, sizeof (*rmp));
1141   rmp->_vl_msg_id = ntohs (VL_API_SNAT_DET_SESSION_DETAILS + sm->msg_id_base);
1142   rmp->is_ip4 = 1;
1143   rmp->in_port = s->in_port;
1144   clib_memcpy (rmp->ext_addr, &s->out.ext_host_addr, 4);
1145   rmp->ext_port = s->out.ext_host_port;
1146   rmp->out_port = s->out.out_port;
1147   rmp->state = s->state;
1148   rmp->expire = ntohl (s->expire);
1149   rmp->context = context;
1150
1151   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1152 }
1153
1154 static void
1155 vl_api_snat_det_session_dump_t_handler (vl_api_snat_det_session_dump_t * mp)
1156 {
1157   unix_shared_memory_queue_t *q;
1158   snat_main_t *sm = &snat_main;
1159   ip4_address_t user_addr;
1160   snat_det_map_t *dm;
1161   snat_det_session_t *s, empty_ses;
1162   u16 i;
1163
1164   q = vl_api_client_index_to_input_queue (mp->client_index);
1165   if (q == 0)
1166     return;
1167   if (!mp->is_ip4)
1168     return;
1169
1170   memset (&empty_ses, 0, sizeof (empty_ses));
1171   clib_memcpy (&user_addr, mp->user_addr, 4);
1172   dm = snat_det_map_by_user (sm, &user_addr);
1173   if (!dm)
1174     return;
1175
1176   s = dm->sessions + snat_det_user_ses_offset (&user_addr, dm->in_plen);
1177   for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
1178     {
1179       if (s->out.as_u64)
1180         send_snat_det_session_details (s, q, mp->context);
1181       s++;
1182     }
1183 }
1184
1185 static void *vl_api_snat_det_session_dump_t_print
1186   (vl_api_snat_det_session_dump_t * mp, void *handle)
1187 {
1188   u8 *s;
1189
1190   s = format (0, "SCRIPT: snat_det_session_dump ");
1191   s = format (s, "user_addr %U\n", format_ip4_address, mp->user_addr);
1192
1193   FINISH;
1194 }
1195
1196 /* List of message types that this plugin understands */
1197 #define foreach_snat_plugin_api_msg                                     \
1198 _(SNAT_ADD_ADDRESS_RANGE, snat_add_address_range)                       \
1199 _(SNAT_INTERFACE_ADD_DEL_FEATURE, snat_interface_add_del_feature)       \
1200 _(SNAT_ADD_STATIC_MAPPING, snat_add_static_mapping)                     \
1201 _(SNAT_CONTROL_PING, snat_control_ping)                                 \
1202 _(SNAT_STATIC_MAPPING_DUMP, snat_static_mapping_dump)                   \
1203 _(SNAT_SHOW_CONFIG, snat_show_config)                                   \
1204 _(SNAT_ADDRESS_DUMP, snat_address_dump)                                 \
1205 _(SNAT_INTERFACE_DUMP, snat_interface_dump)                             \
1206 _(SNAT_SET_WORKERS, snat_set_workers)                                   \
1207 _(SNAT_WORKER_DUMP, snat_worker_dump)                                   \
1208 _(SNAT_ADD_DEL_INTERFACE_ADDR, snat_add_del_interface_addr)             \
1209 _(SNAT_INTERFACE_ADDR_DUMP, snat_interface_addr_dump)                   \
1210 _(SNAT_IPFIX_ENABLE_DISABLE, snat_ipfix_enable_disable)                 \
1211 _(SNAT_USER_DUMP, snat_user_dump)                                       \
1212 _(SNAT_USER_SESSION_DUMP, snat_user_session_dump)                       \
1213 _(SNAT_ADD_DET_MAP, snat_add_det_map)                                   \
1214 _(SNAT_DET_FORWARD, snat_det_forward)                                   \
1215 _(SNAT_DET_REVERSE, snat_det_reverse)                                   \
1216 _(SNAT_DET_MAP_DUMP, snat_det_map_dump)                                 \
1217 _(SNAT_DET_SET_TIMEOUTS, snat_det_set_timeouts)                         \
1218 _(SNAT_DET_GET_TIMEOUTS, snat_det_get_timeouts)                         \
1219 _(SNAT_DET_CLOSE_SESSION_OUT, snat_det_close_session_out)               \
1220 _(SNAT_DET_CLOSE_SESSION_IN, snat_det_close_session_in)                 \
1221 _(SNAT_DET_SESSION_DUMP, snat_det_session_dump)
1222
1223
1224 /* Set up the API message handling tables */
1225 static clib_error_t *
1226 snat_plugin_api_hookup (vlib_main_t * vm)
1227 {
1228   snat_main_t *sm __attribute__ ((unused)) = &snat_main;
1229 #define _(N,n)                                                  \
1230     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
1231                            #n,                                  \
1232                            vl_api_##n##_t_handler,              \
1233                            vl_noop_handler,                     \
1234                            vl_api_##n##_t_endian,               \
1235                            vl_api_##n##_t_print,                \
1236                            sizeof(vl_api_##n##_t), 1);
1237   foreach_snat_plugin_api_msg;
1238 #undef _
1239
1240   return 0;
1241 }
1242
1243 #define vl_msg_name_crc_list
1244 #include <snat/snat_all_api_h.h>
1245 #undef vl_msg_name_crc_list
1246
1247 static void
1248 setup_message_id_table (snat_main_t * sm, api_main_t * am)
1249 {
1250 #define _(id,n,crc) \
1251   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base);
1252   foreach_vl_msg_name_crc_snat;
1253 #undef _
1254 }
1255
1256 static void
1257 plugin_custom_dump_configure (snat_main_t * sm)
1258 {
1259 #define _(n,f) sm->api_main->msg_print_handlers \
1260   [VL_API_##n + sm->msg_id_base]                \
1261     = (void *) vl_api_##f##_t_print;
1262   foreach_snat_plugin_api_msg;
1263 #undef _
1264 }
1265
1266 clib_error_t *
1267 snat_api_init (vlib_main_t * vm, snat_main_t * sm)
1268 {
1269   u8 *name;
1270   clib_error_t *error = 0;
1271
1272   name = format (0, "snat_%08x%c", api_version, 0);
1273
1274   /* Ask for a correctly-sized block of API message decode slots */
1275   sm->msg_id_base =
1276     vl_msg_api_get_msg_ids ((char *) name, VL_MSG_FIRST_AVAILABLE);
1277
1278   error = snat_plugin_api_hookup (vm);
1279
1280   /* Add our API messages to the global name_crc hash table */
1281   setup_message_id_table (sm, sm->api_main);
1282
1283   plugin_custom_dump_configure (sm);
1284
1285   vec_free (name);
1286
1287   return error;
1288 }
1289
1290 /*
1291  * fd.io coding-style-patch-verification: ON
1292  *
1293  * Local Variables:
1294  * eval: (c-set-style "gnu")
1295  * End:
1296  */