http: fix client parse error handling
[vpp.git] / src / vnet / ip / punt_api.c
1 /*
2  *------------------------------------------------------------------
3  * punt_api.c - Punt api
4  *
5  * Copyright (c) 2016 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19
20 #include <vnet/vnet.h>
21 #include <vlibmemory/api.h>
22 #include <vnet/ip/punt.h>
23 #include <vnet/ip/ip_types_api.h>
24
25 #include <vnet/format_fns.h>
26 #include <vnet/ip/punt.api_enum.h>
27 #include <vnet/ip/punt.api_types.h>
28
29 #define REPLY_MSG_ID_BASE punt_main.msg_id_base
30 #include <vlibapi/api_helper_macros.h>
31
32 static int
33 vl_api_punt_type_decode (vl_api_punt_type_t in, punt_type_t * out)
34 {
35   in = clib_net_to_host_u32 (in);
36
37   switch (in)
38     {
39 #define _(v, s)                                 \
40       case PUNT_API_TYPE_##v:                   \
41         *out = PUNT_TYPE_##v;                   \
42         return (0);
43       foreach_punt_type
44 #undef _
45     }
46
47   return (-1);
48 }
49
50 static vl_api_punt_type_t
51 vl_api_punt_type_encode (punt_type_t in)
52 {
53   vl_api_punt_type_t pt = PUNT_API_TYPE_L4;
54
55   switch (in)
56     {
57 #define _(v, s)                                   \
58       case PUNT_TYPE_##v:                         \
59         pt = PUNT_API_TYPE_##v;                   \
60         break;
61       foreach_punt_type
62 #undef _
63     }
64
65   return (clib_host_to_net_u32 (pt));
66 }
67
68 static int
69 vl_api_punt_l4_decode (const vl_api_punt_l4_t * in, punt_l4_t * out)
70 {
71   int rv;
72
73   rv = ip_address_family_decode (in->af, &out->af);
74   if (rv < 0)
75     return (rv);
76   rv = ip_proto_decode (in->protocol, &out->protocol);
77   if (rv < 0)
78     return (rv);
79   out->port = clib_net_to_host_u16 (in->port);
80
81   return (rv);
82 }
83
84 static int
85 vl_api_punt_ip_proto_decode (const vl_api_punt_ip_proto_t * in,
86                              punt_ip_proto_t * out)
87 {
88   int rv;
89
90   rv = ip_address_family_decode (in->af, &out->af);
91   if (rv < 0)
92     return (rv);
93   rv = ip_proto_decode (in->protocol, &out->protocol);
94
95   return (rv);
96 }
97
98 static int
99 vl_api_punt_exception_decode (const vl_api_punt_exception_t * in,
100                               punt_exception_t * out)
101 {
102   int rv;
103
104   out->reason = clib_net_to_host_u32 (in->id);
105   rv = vlib_punt_reason_validate (out->reason);
106
107   return (rv);
108 }
109
110 static int
111 vl_api_punt_decode (const vl_api_punt_t * in, punt_reg_t * out)
112 {
113   int rv;
114
115   rv = vl_api_punt_type_decode (in->type, &out->type);
116
117   if (rv)
118     return (rv);
119
120   switch (out->type)
121     {
122     case PUNT_TYPE_L4:
123       return (vl_api_punt_l4_decode (&in->punt.l4, &out->punt.l4));
124     case PUNT_TYPE_EXCEPTION:
125       return (vl_api_punt_exception_decode (&in->punt.exception,
126                                             &out->punt.exception));
127     case PUNT_TYPE_IP_PROTO:
128       return (vl_api_punt_ip_proto_decode (&in->punt.ip_proto,
129                                            &out->punt.ip_proto));
130     }
131
132   return (-1);
133 }
134
135 static void
136 vl_api_punt_l4_encode (const punt_l4_t * in, vl_api_punt_l4_t * out)
137 {
138   out->af = ip_address_family_encode (in->af);
139   out->protocol = ip_proto_encode (in->protocol);
140   out->port = clib_net_to_host_u16 (in->port);
141 }
142
143 static void
144 vl_api_punt_ip_proto_encode (const punt_ip_proto_t * in,
145                              vl_api_punt_ip_proto_t * out)
146 {
147   out->af = ip_address_family_encode (in->af);
148   out->protocol = ip_proto_encode (in->protocol);
149 }
150
151 static void
152 vl_api_punt_exception_encode (const punt_exception_t * in,
153                               vl_api_punt_exception_t * out)
154 {
155   out->id = clib_host_to_net_u32 (in->reason);
156 }
157
158 static void
159 vl_api_punt_encode (const punt_reg_t * in, vl_api_punt_t * out)
160 {
161   out->type = vl_api_punt_type_encode (in->type);
162
163   switch (in->type)
164     {
165     case PUNT_TYPE_L4:
166       vl_api_punt_l4_encode (&in->punt.l4, &out->punt.l4);
167       break;
168     case PUNT_TYPE_IP_PROTO:
169       vl_api_punt_ip_proto_encode (&in->punt.ip_proto, &out->punt.ip_proto);
170       break;
171     case PUNT_TYPE_EXCEPTION:
172       vl_api_punt_exception_encode (&in->punt.exception,
173                                     &out->punt.exception);
174       break;
175     }
176 }
177
178 static void
179 vl_api_set_punt_t_handler (vl_api_set_punt_t * mp)
180 {
181   vl_api_set_punt_reply_t *rmp;
182   vlib_main_t *vm = vlib_get_main ();
183   clib_error_t *error;
184   punt_reg_t pr;
185   int rv;
186
187   rv = vl_api_punt_decode (&mp->punt, &pr);
188
189   if (rv)
190     goto out;
191
192   error = vnet_punt_add_del (vm, &pr, mp->is_add);
193   if (error)
194     {
195       rv = -1;
196       clib_error_report (error);
197     }
198
199 out:
200   REPLY_MACRO (VL_API_SET_PUNT_REPLY);
201 }
202
203 static void
204 vl_api_punt_socket_register_t_handler (vl_api_punt_socket_register_t * mp)
205 {
206   vl_api_punt_socket_register_reply_t *rmp;
207   vlib_main_t *vm = vlib_get_main ();
208   clib_error_t *error;
209   punt_reg_t pr;
210   int rv;
211
212   rv = vl_api_punt_decode (&mp->punt, &pr);
213
214   if (rv)
215     return;
216
217   error = vnet_punt_socket_add (vm, ntohl (mp->header_version),
218                                 &pr, (char *) mp->pathname);
219   if (error)
220     {
221       rv = -1;
222       clib_error_report (error);
223     }
224
225   char *p = vnet_punt_get_server_pathname ();
226
227   REPLY_MACRO2 (VL_API_PUNT_SOCKET_REGISTER_REPLY,
228   ({
229     memcpy ((char *) rmp->pathname, p, sizeof (rmp->pathname));
230   }));
231 }
232
233 typedef struct punt_socket_send_ctx_t_
234 {
235   vl_api_registration_t *reg;
236   u32 context;
237 } punt_socket_send_ctx_t;
238
239 static walk_rc_t
240 vl_api_punt_socket_send_details (const punt_client_t * pc, void *args)
241 {
242   punt_socket_send_ctx_t *ctx = args;
243   vl_api_punt_socket_details_t *mp;
244
245   mp = vl_msg_api_alloc (sizeof (*mp));
246   if (!mp)
247     return (WALK_STOP);
248
249   clib_memset (mp, 0, sizeof (*mp));
250   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_PUNT_SOCKET_DETAILS);
251   mp->context = ctx->context;
252   vl_api_punt_encode (&pc->reg, &mp->punt);
253   memcpy (mp->pathname, pc->caddr.sun_path, sizeof (pc->caddr.sun_path));
254
255   vl_api_send_msg (ctx->reg, (u8 *) mp);
256
257   return (WALK_CONTINUE);
258 }
259
260 static void
261 vl_api_punt_socket_dump_t_handler (vl_api_punt_socket_dump_t * mp)
262 {
263   vl_api_registration_t *reg;
264   punt_type_t pt;
265
266   if (0 != vl_api_punt_type_decode (mp->type, &pt))
267     return;
268
269   reg = vl_api_client_index_to_registration (mp->client_index);
270   if (!reg)
271     return;
272
273   punt_socket_send_ctx_t ctx = {
274     .reg = reg,
275     .context = mp->context,
276   };
277
278   punt_client_walk (pt, vl_api_punt_socket_send_details, &ctx);
279 }
280
281 static void
282 vl_api_punt_socket_deregister_t_handler (vl_api_punt_socket_deregister_t * mp)
283 {
284   vl_api_punt_socket_deregister_reply_t *rmp;
285   vlib_main_t *vm = vlib_get_main ();
286   clib_error_t *error;
287   punt_reg_t pr;
288   int rv;
289
290   rv = vl_api_punt_decode (&mp->punt, &pr);
291
292   if (rv)
293     goto out;
294
295   error = vnet_punt_socket_del (vm, &pr);
296   if (error)
297     {
298       rv = -1;
299       clib_error_report (error);
300     }
301
302 out:
303   REPLY_MACRO (VL_API_PUNT_SOCKET_DEREGISTER_REPLY);
304 }
305
306 typedef struct punt_reason_dump_walk_ctx_t_
307 {
308   vl_api_registration_t *reg;
309   u32 context;
310   u8 *name;
311 } punt_reason_dump_walk_ctx_t;
312
313 static int
314 punt_reason_dump_walk_cb (vlib_punt_reason_t id, const u8 * name, void *args)
315 {
316   punt_reason_dump_walk_ctx_t *ctx = args;
317   vl_api_punt_reason_details_t *mp;
318
319   if (ctx->name)
320     {
321       /* user requested a specific punt-reason */
322       if (vec_cmp (name, ctx->name))
323         /* not the reasonn we're lookgin for */
324         return 1;
325     }
326
327   mp = vl_msg_api_alloc (sizeof (*mp) + vec_len (name));
328   if (!mp)
329     return (0);
330
331   clib_memset (mp, 0, sizeof (*mp));
332   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_PUNT_REASON_DETAILS);
333
334   mp->context = ctx->context;
335   mp->reason.id = clib_host_to_net_u32 (id);
336   vl_api_vec_to_api_string (name, &mp->reason.name);
337
338   vl_api_send_msg (ctx->reg, (u8 *) mp);
339
340   return (1);
341 }
342
343 static void
344 vl_api_punt_reason_dump_t_handler (vl_api_punt_reason_dump_t * mp)
345 {
346   vl_api_registration_t *reg;
347
348   reg = vl_api_client_index_to_registration (mp->client_index);
349   if (!reg)
350     return;
351
352   punt_reason_dump_walk_ctx_t ctx = {
353     .reg = reg,
354     .context = mp->context,
355     .name = vl_api_from_api_to_new_vec (mp, &mp->reason.name),
356   };
357
358   punt_reason_walk (punt_reason_dump_walk_cb, &ctx);
359
360   vec_free (ctx.name);
361 }
362
363 #include <vnet/ip/punt.api.c>
364
365 static clib_error_t *
366 punt_api_hookup (vlib_main_t * vm)
367 {
368   /*
369    * Set up the (msg_name, crc, message-id) table
370    */
371   REPLY_MSG_ID_BASE = setup_message_id_table ();
372
373   return 0;
374 }
375
376 VLIB_API_INIT_FUNCTION (punt_api_hookup);
377
378
379 /*
380  * fd.io coding-style-patch-verification: ON
381  *
382  * Local Variables:
383  * eval: (c-set-style "gnu")
384  * End:
385  */