pnat: coverity errors
[vpp.git] / src / plugins / nat / pnat / pnat_api.c
1 /*
2  * Copyright (c) 2021 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 #include "pnat.h"
16 #include <pnat/pnat.api_enum.h>
17 #include <pnat/pnat.api_types.h>
18 #include <vlibmemory/api.h>
19 #include <vnet/fib/fib_table.h>
20 #include <vnet/ip/ip.h>
21 #include <vnet/ip/ip_types_api.h>
22 #include <vnet/ip/reass/ip4_sv_reass.h>
23 #include <vnet/ip/reass/ip6_full_reass.h>
24 #include <vnet/ip/reass/ip6_sv_reass.h>
25
26 /*
27  * This file contains the API handlers for the pnat.api
28  */
29
30 #define REPLY_MSG_ID_BASE pm->msg_id_base
31 #include <vlibapi/api_helper_macros.h>
32
33 static void vl_api_pnat_binding_add_t_handler(vl_api_pnat_binding_add_t *mp) {
34     pnat_main_t *pm = &pnat_main;
35     vl_api_pnat_binding_add_reply_t *rmp;
36     u32 binding_index;
37     int rv = pnat_binding_add(&mp->match, &mp->rewrite, &binding_index);
38     REPLY_MACRO2_END(VL_API_PNAT_BINDING_ADD_REPLY,
39                      ({ rmp->binding_index = binding_index; }));
40 }
41
42 static void
43 vl_api_pnat_binding_attach_t_handler(vl_api_pnat_binding_attach_t *mp) {
44     pnat_main_t *pm = &pnat_main;
45     vl_api_pnat_binding_attach_reply_t *rmp;
46     int rv;
47
48     /* Ensure that the interface exists */
49     if (!vnet_sw_if_index_is_api_valid(mp->sw_if_index)) {
50         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
51         goto bad_sw_if_index;
52     }
53
54     rv =
55         pnat_binding_attach(mp->sw_if_index, mp->attachment, mp->binding_index);
56
57 bad_sw_if_index:
58     REPLY_MACRO_END(VL_API_PNAT_BINDING_ATTACH_REPLY);
59 }
60
61 static void
62 vl_api_pnat_binding_detach_t_handler(vl_api_pnat_binding_detach_t *mp) {
63     pnat_main_t *pm = &pnat_main;
64     vl_api_pnat_binding_detach_reply_t *rmp;
65     int rv;
66
67     /* Ensure that the interface exists */
68     if (!vnet_sw_if_index_is_api_valid(mp->sw_if_index)) {
69         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
70         goto bad_sw_if_index;
71     }
72
73     rv =
74         pnat_binding_detach(mp->sw_if_index, mp->attachment, mp->binding_index);
75
76 bad_sw_if_index:
77     REPLY_MACRO_END(VL_API_PNAT_BINDING_DETACH_REPLY);
78 }
79
80 static void vl_api_pnat_binding_del_t_handler(vl_api_pnat_binding_del_t *mp) {
81     pnat_main_t *pm = &pnat_main;
82     vl_api_pnat_binding_del_reply_t *rmp;
83     int rv = pnat_binding_del(mp->binding_index);
84     REPLY_MACRO_END(VL_API_PNAT_BINDING_DEL_REPLY);
85 }
86
87 /*
88  * Workaround for a bug in vppapigen that doesn't register the endian handler
89  * for _details messages. When that's fixed it should be possible to use
90  * REPLY_MACRO_DETAILS4_END and not have to care about endian-ness in the
91  * handler itself.
92  */
93 #define vl_endianfun
94 #include <pnat/pnat.api.h>
95 #undef vl_endianfun
96 static void send_bindings_details(u32 index, vl_api_registration_t *rp,
97                                   u32 context) {
98     pnat_main_t *pm = &pnat_main;
99     vl_api_pnat_bindings_details_t *rmp;
100     pnat_translation_t *t = pool_elt_at_index(pm->translations, index);
101
102     /* Make sure every field is initiated (or don't skip the clib_memset()) */
103
104     REPLY_MACRO_DETAILS4(VL_API_PNAT_BINDINGS_DETAILS, rp, context, ({
105                              rmp->match = t->match;
106                              rmp->rewrite = t->rewrite;
107
108                              /* Endian hack until apigen registers _details
109                               * endian functions */
110                              vl_api_pnat_bindings_details_t_endian(rmp);
111                              rmp->_vl_msg_id = htons(rmp->_vl_msg_id);
112                              rmp->context = htonl(rmp->context);
113                          }));
114 }
115
116 static void vl_api_pnat_bindings_get_t_handler(vl_api_pnat_bindings_get_t *mp) {
117     pnat_main_t *pm = &pnat_main;
118     vl_api_pnat_bindings_get_reply_t *rmp;
119
120     i32 rv = 0;
121
122     if (pool_elts(pm->translations) == 0) {
123         REPLY_MACRO(VL_API_PNAT_BINDINGS_GET_REPLY);
124         return;
125     }
126
127     /*
128      * "cursor" comes from the get call, and allows client to continue a dump
129      */
130     REPLY_AND_DETAILS_MACRO(VL_API_PNAT_BINDINGS_GET_REPLY, pm->translations, ({
131                                 send_bindings_details(cursor, rp, mp->context);
132                             }));
133 }
134
135 static void send_interfaces_details(u32 index, vl_api_registration_t *rp,
136                                     u32 context) {
137     pnat_main_t *pm = &pnat_main;
138     vl_api_pnat_interfaces_details_t *rmp;
139     pnat_interface_t *i = pool_elt_at_index(pm->interfaces, index);
140
141     /* Make sure every field is initiated (or don't skip the clib_memset()) */
142
143     REPLY_MACRO_DETAILS4(
144         VL_API_PNAT_INTERFACES_DETAILS, rp, context, ({
145             rmp->sw_if_index = i->sw_if_index;
146             clib_memcpy(rmp->enabled, i->enabled, sizeof(rmp->enabled));
147             clib_memcpy(rmp->lookup_mask, i->lookup_mask,
148                         sizeof(rmp->lookup_mask));
149
150             /* Endian hack until apigen registers _details
151              * endian functions */
152             vl_api_pnat_interfaces_details_t_endian(rmp);
153             rmp->_vl_msg_id = htons(rmp->_vl_msg_id);
154             rmp->context = htonl(rmp->context);
155         }));
156 }
157
158 static void
159 vl_api_pnat_interfaces_get_t_handler(vl_api_pnat_interfaces_get_t *mp) {
160     pnat_main_t *pm = &pnat_main;
161     vl_api_pnat_interfaces_get_reply_t *rmp;
162
163     i32 rv = 0;
164
165     if (pool_elts(pm->interfaces) == 0) {
166         REPLY_MACRO(VL_API_PNAT_INTERFACES_GET_REPLY);
167         return;
168     }
169
170     /*
171      * "cursor" comes from the get call, and allows client to continue a dump
172      */
173     REPLY_AND_DETAILS_MACRO(
174         VL_API_PNAT_INTERFACES_GET_REPLY, pm->interfaces,
175         ({ send_interfaces_details(cursor, rp, mp->context); }));
176 }
177
178 /* API definitions */
179 #include <vnet/format_fns.h>
180 #include <pnat/pnat.api.c>
181
182 /* Set up the API message handling tables */
183 clib_error_t *pnat_plugin_api_hookup(vlib_main_t *vm) {
184     pnat_main_t *pm = &pnat_main;
185
186     pm->msg_id_base = setup_message_id_table();
187
188     return 0;
189 }
190
191 /*
192  * Register the plugin and hook up the API
193  */
194 #include <vnet/plugin/plugin.h>
195 VLIB_PLUGIN_REGISTER() = {
196     .version = "0.0.1",
197     .description = "Policy 1:1 NAT",
198 };
199
200 clib_error_t *pnat_init(vlib_main_t *vm) {
201     pnat_main_t *pm = &pnat_main;
202     memset(pm, 0, sizeof(*pm));
203
204     return pnat_plugin_api_hookup(vm);
205 }
206
207 VLIB_INIT_FUNCTION(pnat_init);