cnat: coverity fix
[vpp.git] / src / plugins / cnat / cnat_api.c
1 /*
2  * Copyright (c) 2016 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 <stddef.h>
17
18 #include <vnet/vnet.h>
19 #include <vnet/plugin/plugin.h>
20 #include <cnat/cnat_translation.h>
21 #include <cnat/cnat_session.h>
22 #include <cnat/cnat_client.h>
23 #include <cnat/cnat_snat.h>
24
25 #include <vnet/ip/ip_types_api.h>
26
27 #include <vpp/app/version.h>
28
29 #include <vlibapi/api.h>
30 #include <vlibmemory/api.h>
31
32 /* define message IDs */
33 #include <vnet/format_fns.h>
34 #include <cnat/cnat.api_enum.h>
35 #include <cnat/cnat.api_types.h>
36
37 /**
38  * Base message ID fot the plugin
39  */
40 static u32 cnat_base_msg_id;
41
42 #define REPLY_MSG_ID_BASE cnat_base_msg_id
43
44 #include <vlibapi/api_helper_macros.h>
45
46 static int
47 cnat_endpoint_decode (const vl_api_cnat_endpoint_t * in,
48                       cnat_endpoint_t * out)
49 {
50   int rv = 0;
51   out->ce_port = clib_net_to_host_u16 (in->port);
52   out->ce_sw_if_index = clib_net_to_host_u32 (in->sw_if_index);
53   out->ce_flags = 0;
54   if (out->ce_sw_if_index == INDEX_INVALID)
55     ip_address_decode2 (&in->addr, &out->ce_ip);
56   else
57     rv = ip_address_family_decode (in->if_af, &out->ce_ip.version);
58   return rv;
59 }
60
61 static int
62 cnat_endpoint_tuple_decode (const vl_api_cnat_endpoint_tuple_t * in,
63                             cnat_endpoint_tuple_t * out)
64 {
65   int rv = 0;
66   rv = cnat_endpoint_decode (&in->src_ep, &out->src_ep);
67   if (rv)
68     return rv;
69   rv = cnat_endpoint_decode (&in->dst_ep, &out->dst_ep);
70   return rv;
71 }
72
73 static void
74 cnat_endpoint_encode (const cnat_endpoint_t * in,
75                       vl_api_cnat_endpoint_t * out)
76 {
77   out->port = clib_net_to_host_u16 (in->ce_port);
78   out->sw_if_index = clib_net_to_host_u32 (in->ce_sw_if_index);
79   out->if_af = ip_address_family_encode (in->ce_ip.version);
80   if (in->ce_flags & CNAT_EP_FLAG_RESOLVED)
81     ip_address_encode2 (&in->ce_ip, &out->addr);
82   else
83     clib_memset ((void *) &in->ce_ip, 0, sizeof (in->ce_ip));
84 }
85
86 static void
87 vl_api_cnat_translation_update_t_handler (vl_api_cnat_translation_update_t
88                                           * mp)
89 {
90   vl_api_cnat_translation_update_reply_t *rmp;
91   cnat_endpoint_t vip;
92   cnat_endpoint_tuple_t *paths = NULL, *path;
93   ip_protocol_t ip_proto;
94   u32 id = ~0;
95   u8 flags;
96   int rv = 0;
97   u32 pi, n_paths;
98
99   rv = ip_proto_decode (mp->translation.ip_proto, &ip_proto);
100
101   if (rv)
102     goto done;
103
104   n_paths = clib_net_to_host_u32 (mp->translation.n_paths);
105   vec_validate (paths, n_paths - 1);
106
107   for (pi = 0; pi < n_paths; pi++)
108     {
109       path = &paths[pi];
110       rv = cnat_endpoint_tuple_decode (&mp->translation.paths[pi], path);
111       if (rv)
112         goto done;
113     }
114
115   rv = cnat_endpoint_decode (&mp->translation.vip, &vip);
116   if (rv)
117     goto done;
118
119   flags = mp->translation.flags;
120   if (!mp->translation.is_real_ip)
121     flags |= CNAT_FLAG_EXCLUSIVE;
122   id = cnat_translation_update (&vip, ip_proto, paths, flags);
123
124   vec_free (paths);
125
126 done:
127   /* *INDENT-OFF* */
128   REPLY_MACRO2 (VL_API_CNAT_TRANSLATION_UPDATE_REPLY,
129   ({
130     rmp->id = htonl (id);
131   }));
132   /* *INDENT-ON* */
133 }
134
135 static void
136 vl_api_cnat_translation_del_t_handler (vl_api_cnat_translation_del_t * mp)
137 {
138   vl_api_cnat_translation_del_reply_t *rmp;
139   int rv;
140
141   rv = cnat_translation_delete (ntohl (mp->id));
142
143   REPLY_MACRO (VL_API_CNAT_TRANSLATION_DEL_REPLY);
144 }
145
146 typedef struct cnat_dump_walk_ctx_t_
147 {
148   vl_api_registration_t *rp;
149   u32 context;
150 } cnat_dump_walk_ctx_t;
151
152 static walk_rc_t
153 cnat_translation_send_details (u32 cti, void *args)
154 {
155   vl_api_cnat_translation_details_t *mp;
156   cnat_dump_walk_ctx_t *ctx;
157   cnat_ep_trk_t *trk;
158   vl_api_cnat_endpoint_tuple_t *path;
159   size_t msg_size;
160   cnat_translation_t *ct;
161   u32 n_paths;
162
163   ctx = args;
164   ct = cnat_translation_get (cti);
165   n_paths = vec_len (ct->ct_paths);
166   msg_size = sizeof (*mp) + sizeof (mp->translation.paths[0]) * n_paths;
167
168   mp = vl_msg_api_alloc_zero (msg_size);
169   mp->_vl_msg_id = ntohs (VL_API_CNAT_TRANSLATION_DETAILS + cnat_base_msg_id);
170
171   /* fill in the message */
172   mp->context = ctx->context;
173   mp->translation.n_paths = clib_host_to_net_u32 (n_paths);
174   mp->translation.id = clib_host_to_net_u32 (cti);
175   cnat_endpoint_encode (&ct->ct_vip, &mp->translation.vip);
176   mp->translation.ip_proto = ip_proto_encode (ct->ct_proto);
177
178   path = mp->translation.paths;
179   vec_foreach (trk, ct->ct_paths)
180   {
181     cnat_endpoint_encode (&trk->ct_ep[VLIB_TX], &path->dst_ep);
182     cnat_endpoint_encode (&trk->ct_ep[VLIB_RX], &path->src_ep);
183     path++;
184   }
185
186   vl_api_send_msg (ctx->rp, (u8 *) mp);
187
188   return (WALK_CONTINUE);
189 }
190
191 static void
192 vl_api_cnat_translation_dump_t_handler (vl_api_cnat_translation_dump_t * mp)
193 {
194   vl_api_registration_t *rp;
195
196   rp = vl_api_client_index_to_registration (mp->client_index);
197   if (rp == 0)
198     return;
199
200   cnat_dump_walk_ctx_t ctx = {
201     .rp = rp,
202     .context = mp->context,
203   };
204
205   cnat_translation_walk (cnat_translation_send_details, &ctx);
206 }
207
208 static void
209 ip_address2_from_46 (const ip46_address_t * nh,
210                      ip_address_family_t af, ip_address_t * ip)
211 {
212   ip_addr_46 (ip) = *nh;
213   ip_addr_version (ip) = af;
214 }
215
216 static walk_rc_t
217 cnat_session_send_details (const cnat_session_t * session, void *args)
218 {
219   vl_api_cnat_session_details_t *mp;
220   cnat_dump_walk_ctx_t *ctx;
221   cnat_endpoint_t ep;
222
223   ctx = args;
224
225   mp = vl_msg_api_alloc_zero (sizeof (*mp));
226   mp->_vl_msg_id = ntohs (VL_API_CNAT_SESSION_DETAILS + cnat_base_msg_id);
227
228   /* fill in the message */
229   mp->context = ctx->context;
230
231   ep.ce_sw_if_index = INDEX_INVALID;
232   ep.ce_flags = CNAT_EP_FLAG_RESOLVED;
233   ip_address2_from_46 (&session->value.cs_ip[VLIB_TX], session->key.cs_af,
234                        &ep.ce_ip);
235   ep.ce_port = clib_host_to_net_u16 (session->value.cs_port[VLIB_TX]);
236   cnat_endpoint_encode (&ep, &mp->session.new);
237
238   ip_address2_from_46 (&session->key.cs_ip[VLIB_RX], session->key.cs_af,
239                        &ep.ce_ip);
240   ep.ce_port = clib_host_to_net_u16 (session->key.cs_port[VLIB_RX]);
241   cnat_endpoint_encode (&ep, &mp->session.src);
242
243   ip_address2_from_46 (&session->key.cs_ip[VLIB_TX], session->key.cs_af,
244                        &ep.ce_ip);
245   ep.ce_port = clib_host_to_net_u16 (session->key.cs_port[VLIB_TX]);
246   cnat_endpoint_encode (&ep, &mp->session.dst);
247
248   mp->session.ip_proto = ip_proto_encode (session->key.cs_proto);
249
250   vl_api_send_msg (ctx->rp, (u8 *) mp);
251
252   return (WALK_CONTINUE);
253 }
254
255 static void
256 vl_api_cnat_session_dump_t_handler (vl_api_cnat_session_dump_t * mp)
257 {
258   vl_api_registration_t *rp;
259
260   rp = vl_api_client_index_to_registration (mp->client_index);
261   if (rp == 0)
262     return;
263
264   cnat_dump_walk_ctx_t ctx = {
265     .rp = rp,
266     .context = mp->context,
267   };
268
269   cnat_session_walk (cnat_session_send_details, &ctx);
270 }
271
272 static void
273 vl_api_cnat_session_purge_t_handler (vl_api_cnat_session_purge_t * mp)
274 {
275   vl_api_cnat_session_purge_reply_t *rmp;
276   int rv;
277
278   cnat_client_throttle_pool_process ();
279   rv = cnat_session_purge ();
280   rv |= cnat_translation_purge ();
281
282   REPLY_MACRO (VL_API_CNAT_SESSION_PURGE_REPLY);
283 }
284
285 static void
286 vl_api_cnat_get_snat_addresses_t_handler (vl_api_cnat_get_snat_addresses_t
287                                           * mp)
288 {
289   vl_api_cnat_get_snat_addresses_reply_t *rmp;
290   int rv = 0;
291
292   /* *INDENT-OFF* */
293   REPLY_MACRO2 (VL_API_CNAT_GET_SNAT_ADDRESSES_REPLY,
294   ({
295     ip6_address_encode (&ip_addr_v6(&cnat_main.snat_ip6.ce_ip), rmp->snat_ip6);
296     ip4_address_encode (&ip_addr_v4(&cnat_main.snat_ip4.ce_ip), rmp->snat_ip4);
297     rmp->sw_if_index = clib_host_to_net_u32 (cnat_main.snat_ip6.ce_sw_if_index);
298   }));
299   /* *INDENT-ON* */
300 }
301
302 static void
303 vl_api_cnat_set_snat_addresses_t_handler (vl_api_cnat_set_snat_addresses_t
304                                           * mp)
305 {
306   vl_api_cnat_set_snat_addresses_reply_t *rmp;
307   u32 sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
308   ip4_address_t ip4;
309   ip6_address_t ip6;
310   int rv = 0;
311
312   ip4_address_decode (mp->snat_ip4, &ip4);
313   ip6_address_decode (mp->snat_ip6, &ip6);
314
315   cnat_set_snat (&ip4, &ip6, sw_if_index);
316
317   REPLY_MACRO (VL_API_CNAT_SET_SNAT_ADDRESSES_REPLY);
318 }
319
320 static void
321   vl_api_cnat_add_del_snat_prefix_t_handler
322   (vl_api_cnat_add_del_snat_prefix_t * mp)
323 {
324   vl_api_cnat_add_del_snat_prefix_reply_t *rmp;
325   ip_prefix_t pfx;
326   int rv;
327
328   ip_prefix_decode2 (&mp->prefix, &pfx);
329   if (mp->is_add)
330     rv = cnat_add_snat_prefix (&pfx);
331   else
332     rv = cnat_del_snat_prefix (&pfx);
333
334   REPLY_MACRO (VL_API_CNAT_ADD_DEL_SNAT_PREFIX_REPLY);
335 }
336
337 #include <cnat/cnat.api.c>
338
339 static clib_error_t *
340 cnat_api_init (vlib_main_t * vm)
341 {
342   /* Ask for a correctly-sized block of API message decode slots */
343   cnat_base_msg_id = setup_message_id_table ();
344
345   return 0;
346 }
347
348 VLIB_INIT_FUNCTION (cnat_api_init);
349
350 /* *INDENT-OFF* */
351 VLIB_PLUGIN_REGISTER () = {
352     .version = VPP_BUILD_VER,
353     .description = "CNat Translate",
354 };
355 /* *INDENT-ON* */
356
357 /*
358  * fd.io coding-style-patch-verification: ON
359  *
360  * Local Variables:
361  * eval: (c-set-style "gnu")
362  * End:
363  */