linux-cp: fix seg fault in get_v2 methods
[vpp.git] / src / plugins / linux-cp / lcp_api.c
1 /*
2  * Copyright 2020 Rubicon Communications, LLC.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6
7 #include <sys/socket.h>
8 #include <linux/if.h>
9
10 #include <vnet/vnet.h>
11 #include <vnet/plugin/plugin.h>
12
13 #include <vlibapi/api.h>
14 #include <vlibmemory/api.h>
15 #include <vpp/app/version.h>
16 #include <vnet/format_fns.h>
17
18 #include <linux-cp/lcp_interface.h>
19 #include <linux-cp/lcp.api_enum.h>
20 #include <linux-cp/lcp.api_types.h>
21
22 static u16 lcp_msg_id_base;
23 #define REPLY_MSG_ID_BASE lcp_msg_id_base
24 #include <vlibapi/api_helper_macros.h>
25
26 static lip_host_type_t
27 api_decode_host_type (vl_api_lcp_itf_host_type_t type)
28 {
29   if (type == LCP_API_ITF_HOST_TUN)
30     return LCP_ITF_HOST_TUN;
31
32   return LCP_ITF_HOST_TAP;
33 }
34
35 static vl_api_lcp_itf_host_type_t
36 api_encode_host_type (lip_host_type_t type)
37 {
38   if (type == LCP_ITF_HOST_TUN)
39     return LCP_API_ITF_HOST_TUN;
40
41   return LCP_API_ITF_HOST_TAP;
42 }
43
44 static int
45 vl_api_lcp_itf_pair_add (u32 phy_sw_if_index, lip_host_type_t lip_host_type,
46                          u8 *mp_host_if_name, size_t sizeof_host_if_name,
47                          u8 *mp_namespace, size_t sizeof_mp_namespace,
48                          u32 *host_sw_if_index_p, u32 *vif_index_p)
49 {
50   u8 *host_if_name, *netns;
51   int host_len, netns_len, rv;
52
53   host_if_name = netns = 0;
54
55   /* lcp_itf_pair_create expects vec of u8 */
56   host_len = clib_strnlen ((char *) mp_host_if_name, sizeof_host_if_name - 1);
57   vec_add (host_if_name, mp_host_if_name, host_len);
58   vec_add1 (host_if_name, 0);
59
60   netns_len = clib_strnlen ((char *) mp_namespace, sizeof_mp_namespace - 1);
61   vec_add (netns, mp_namespace, netns_len);
62   vec_add1 (netns, 0);
63
64   rv = lcp_itf_pair_create (phy_sw_if_index, host_if_name, lip_host_type,
65                             netns, host_sw_if_index_p);
66
67   if (!rv && (vif_index_p != NULL))
68     {
69       lcp_itf_pair_t *pair =
70         lcp_itf_pair_get (lcp_itf_pair_find_by_phy (phy_sw_if_index));
71       *vif_index_p = pair->lip_vif_index;
72     }
73
74   vec_free (host_if_name);
75   vec_free (netns);
76
77   return rv;
78 }
79
80 static void
81 vl_api_lcp_itf_pair_add_del_t_handler (vl_api_lcp_itf_pair_add_del_t *mp)
82 {
83   u32 phy_sw_if_index;
84   vl_api_lcp_itf_pair_add_del_reply_t *rmp;
85   lip_host_type_t lip_host_type;
86   int rv;
87
88   VALIDATE_SW_IF_INDEX_END (mp);
89
90   phy_sw_if_index = mp->sw_if_index;
91   lip_host_type = api_decode_host_type (mp->host_if_type);
92   if (mp->is_add)
93     {
94       rv = vl_api_lcp_itf_pair_add (
95         phy_sw_if_index, lip_host_type, mp->host_if_name,
96         sizeof (mp->host_if_name), mp->netns, sizeof (mp->netns), NULL, NULL);
97     }
98   else
99     {
100       rv = lcp_itf_pair_delete (phy_sw_if_index);
101     }
102
103   BAD_SW_IF_INDEX_LABEL;
104   REPLY_MACRO_END (VL_API_LCP_ITF_PAIR_ADD_DEL_REPLY);
105 }
106
107 static void
108 vl_api_lcp_itf_pair_add_del_v2_t_handler (vl_api_lcp_itf_pair_add_del_v2_t *mp)
109 {
110   u32 phy_sw_if_index, host_sw_if_index = ~0;
111   vl_api_lcp_itf_pair_add_del_v2_reply_t *rmp;
112   lip_host_type_t lip_host_type;
113   int rv;
114
115   VALIDATE_SW_IF_INDEX_END (mp);
116
117   phy_sw_if_index = mp->sw_if_index;
118   lip_host_type = api_decode_host_type (mp->host_if_type);
119   if (mp->is_add)
120     {
121       rv = vl_api_lcp_itf_pair_add (
122         phy_sw_if_index, lip_host_type, mp->host_if_name,
123         sizeof (mp->host_if_name), mp->netns, sizeof (mp->netns),
124         &host_sw_if_index, NULL);
125     }
126   else
127     {
128       rv = lcp_itf_pair_delete (phy_sw_if_index);
129     }
130
131   BAD_SW_IF_INDEX_LABEL;
132   REPLY_MACRO2_END (VL_API_LCP_ITF_PAIR_ADD_DEL_V2_REPLY,
133                     { rmp->host_sw_if_index = host_sw_if_index; });
134 }
135
136 static void
137 vl_api_lcp_itf_pair_add_del_v3_t_handler (vl_api_lcp_itf_pair_add_del_v3_t *mp)
138 {
139   u32 phy_sw_if_index, host_sw_if_index = ~0, vif_index = ~0;
140   vl_api_lcp_itf_pair_add_del_v3_reply_t *rmp;
141   lip_host_type_t lip_host_type;
142   int rv;
143
144   VALIDATE_SW_IF_INDEX_END (mp);
145
146   phy_sw_if_index = mp->sw_if_index;
147   lip_host_type = api_decode_host_type (mp->host_if_type);
148   if (mp->is_add)
149     {
150       rv = vl_api_lcp_itf_pair_add (
151         phy_sw_if_index, lip_host_type, mp->host_if_name,
152         sizeof (mp->host_if_name), mp->netns, sizeof (mp->netns),
153         &host_sw_if_index, &vif_index);
154     }
155   else
156     {
157       rv = lcp_itf_pair_delete (phy_sw_if_index);
158     }
159
160   BAD_SW_IF_INDEX_LABEL;
161   REPLY_MACRO2_END (VL_API_LCP_ITF_PAIR_ADD_DEL_V3_REPLY, ({
162                       rmp->host_sw_if_index = host_sw_if_index;
163                       rmp->vif_index = vif_index;
164                     }));
165 }
166
167 static void
168 send_lcp_itf_pair_details (index_t lipi, vl_api_registration_t *rp,
169                            u32 context)
170 {
171   vl_api_lcp_itf_pair_details_t *rmp;
172   lcp_itf_pair_t *lcp_pair = lcp_itf_pair_get (lipi);
173
174   REPLY_MACRO_DETAILS4_END (
175     VL_API_LCP_ITF_PAIR_DETAILS, rp, context, ({
176       rmp->phy_sw_if_index = lcp_pair->lip_phy_sw_if_index;
177       rmp->host_sw_if_index = lcp_pair->lip_host_sw_if_index;
178       rmp->vif_index = lcp_pair->lip_vif_index;
179       rmp->host_if_type = api_encode_host_type (lcp_pair->lip_host_type);
180
181       memcpy_s (rmp->host_if_name, sizeof (rmp->host_if_name),
182                 lcp_pair->lip_host_name, vec_len (lcp_pair->lip_host_name));
183       rmp->host_if_name[vec_len (lcp_pair->lip_host_name)] = 0;
184
185       memcpy_s (rmp->netns, sizeof (rmp->netns), lcp_pair->lip_namespace,
186                 vec_len (lcp_pair->lip_namespace));
187       rmp->netns[vec_len (lcp_pair->lip_namespace)] = 0;
188     }));
189 }
190
191 static void
192 vl_api_lcp_itf_pair_get_t_handler (vl_api_lcp_itf_pair_get_t *mp)
193 {
194   vl_api_lcp_itf_pair_get_reply_t *rmp;
195   i32 rv = 0;
196
197   REPLY_AND_DETAILS_MACRO_END (
198     VL_API_LCP_ITF_PAIR_GET_REPLY, lcp_itf_pair_pool,
199     ({ send_lcp_itf_pair_details (cursor, rp, mp->context); }));
200 }
201
202 static void
203 vl_api_lcp_itf_pair_get_v2_t_handler (vl_api_lcp_itf_pair_get_v2_t *mp)
204 {
205   vl_api_lcp_itf_pair_get_v2_reply_t *rmp;
206   i32 rv = 0;
207
208   if (mp->sw_if_index == ~0)
209     {
210       REPLY_AND_DETAILS_MACRO_END (
211         VL_API_LCP_ITF_PAIR_GET_REPLY, lcp_itf_pair_pool,
212         ({ send_lcp_itf_pair_details (cursor, rp, mp->context); }));
213     }
214   else
215     {
216       VALIDATE_SW_IF_INDEX_END (mp);
217
218       u32 pair_index = lcp_itf_pair_find_by_phy (mp->sw_if_index);
219       if (pair_index == INDEX_INVALID)
220         {
221           rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
222           goto bad_sw_if_index;
223         }
224       send_lcp_itf_pair_details (
225         pair_index, vl_api_client_index_to_registration (mp->client_index),
226         mp->context);
227
228       BAD_SW_IF_INDEX_LABEL;
229       REPLY_MACRO2_END (VL_API_LCP_ITF_PAIR_GET_V2_REPLY,
230                         ({ rmp->cursor = ~0; }));
231     }
232 }
233
234 static void
235 vl_api_lcp_default_ns_set_t_handler (vl_api_lcp_default_ns_set_t *mp)
236 {
237   vl_api_lcp_default_ns_set_reply_t *rmp;
238   int rv;
239
240   mp->netns[LCP_NS_LEN - 1] = 0;
241   rv = lcp_set_default_ns (mp->netns);
242
243   REPLY_MACRO (VL_API_LCP_DEFAULT_NS_SET_REPLY);
244 }
245
246 static void
247 vl_api_lcp_default_ns_get_t_handler (vl_api_lcp_default_ns_get_t *mp)
248 {
249   vl_api_lcp_default_ns_get_reply_t *rmp;
250
251   REPLY_MACRO_DETAILS2 (VL_API_LCP_DEFAULT_NS_GET_REPLY, ({
252                           char *ns = (char *) lcp_get_default_ns ();
253                           if (ns)
254                             clib_strncpy ((char *) rmp->netns, ns,
255                                           LCP_NS_LEN - 1);
256                         }));
257 }
258
259 static void
260 vl_api_lcp_itf_pair_replace_begin_t_handler (
261   vl_api_lcp_itf_pair_replace_begin_t *mp)
262 {
263   vl_api_lcp_itf_pair_replace_begin_reply_t *rmp;
264   int rv;
265
266   rv = lcp_itf_pair_replace_begin ();
267
268   REPLY_MACRO (VL_API_LCP_ITF_PAIR_REPLACE_BEGIN_REPLY);
269 }
270
271 static void
272 vl_api_lcp_itf_pair_replace_end_t_handler (
273   vl_api_lcp_itf_pair_replace_end_t *mp)
274 {
275   vl_api_lcp_itf_pair_replace_end_reply_t *rmp;
276   int rv = 0;
277
278   rv = lcp_itf_pair_replace_end ();
279
280   REPLY_MACRO (VL_API_LCP_ITF_PAIR_REPLACE_END_REPLY);
281 }
282
283 /*
284  * Set up the API message handling tables
285  */
286 #include <linux-cp/lcp.api.c>
287
288 static clib_error_t *
289 lcp_api_init (vlib_main_t *vm)
290 {
291   /* Ask for a correctly-sized block of API message decode slots */
292   lcp_msg_id_base = setup_message_id_table ();
293
294   return (NULL);
295 }
296
297 VLIB_INIT_FUNCTION (lcp_api_init);
298
299 #include <vpp/app/version.h>
300 VLIB_PLUGIN_REGISTER () = {
301   .version = VPP_BUILD_VER,
302   .description = "Linux Control Plane - Interface Mirror",
303   .default_disabled = 1,
304 };
305
306 /*
307  * fd.io coding-style-patch-verification: ON
308  *
309  * Local Variables:
310  * eval: (c-set-style "gnu")
311  * End:
312  */