c11 safe string handling support
[vpp.git] / src / plugins / pppoe / pppoe_api.c
1 /*
2  *------------------------------------------------------------------
3  * pppoe_api.c - pppoe api
4  *
5  * Copyright (c) 2017 Intel 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/interface.h>
21 #include <vnet/api_errno.h>
22 #include <vnet/feature/feature.h>
23 #include <vnet/fib/fib_table.h>
24
25 #include <vppinfra/byte_order.h>
26 #include <vlibmemory/api.h>
27
28
29 #include <pppoe/pppoe.h>
30
31
32 #define vl_msg_id(n,h) n,
33 typedef enum
34 {
35 #include <pppoe/pppoe.api.h>
36   /* We'll want to know how many messages IDs we need... */
37   VL_MSG_FIRST_AVAILABLE,
38 } vl_msg_id_t;
39 #undef vl_msg_id
40
41 /* define message structures */
42 #define vl_typedefs
43 #include <pppoe/pppoe.api.h>
44 #undef vl_typedefs
45
46 /* define generated endian-swappers */
47 #define vl_endianfun
48 #include <pppoe/pppoe.api.h>
49 #undef vl_endianfun
50
51 /* instantiate all the print functions we know about */
52 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
53 #define vl_printfun
54 #include <pppoe/pppoe.api.h>
55 #undef vl_printfun
56
57 /* Get the API version number */
58 #define vl_api_version(n,v) static u32 api_version=(v);
59 #include <pppoe/pppoe.api.h>
60 #undef vl_api_version
61
62 #define vl_msg_name_crc_list
63 #include <pppoe/pppoe.api.h>
64 #undef vl_msg_name_crc_list
65
66 #define REPLY_MSG_ID_BASE pem->msg_id_base
67 #include <vlibapi/api_helper_macros.h>
68
69 static void
70 setup_message_id_table (pppoe_main_t * pem, api_main_t * am)
71 {
72 #define _(id,n,crc) \
73   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + pem->msg_id_base);
74   foreach_vl_msg_name_crc_pppoe;
75 #undef _
76 }
77
78 #define foreach_pppoe_plugin_api_msg                             \
79 _(PPPOE_ADD_DEL_SESSION, pppoe_add_del_session)                           \
80 _(PPPOE_SESSION_DUMP, pppoe_session_dump)
81
82 static void vl_api_pppoe_add_del_session_t_handler
83   (vl_api_pppoe_add_del_session_t * mp)
84 {
85   vl_api_pppoe_add_del_session_reply_t *rmp;
86   int rv = 0;
87   u32 decap_fib_index;
88   ip4_main_t *im = &ip4_main;
89   pppoe_main_t *pem = &pppoe_main;
90
91   uword *p = hash_get (im->fib_index_by_table_id, ntohl (mp->decap_vrf_id));
92   if (!p)
93     {
94       rv = VNET_API_ERROR_NO_SUCH_INNER_FIB;
95       goto out;
96     }
97   decap_fib_index = p[0];
98
99   vnet_pppoe_add_del_session_args_t a = {
100     .is_add = mp->is_add,
101     .is_ip6 = mp->is_ipv6,
102     .decap_fib_index = decap_fib_index,
103     .session_id = ntohs (mp->session_id),
104     .client_ip = to_ip46 (mp->is_ipv6, mp->client_ip),
105   };
106   clib_memcpy (a.client_mac, mp->client_mac, 6);
107
108   u32 sw_if_index = ~0;
109   rv = vnet_pppoe_add_del_session (&a, &sw_if_index);
110
111 out:
112   /* *INDENT-OFF* */
113   REPLY_MACRO2(VL_API_PPPOE_ADD_DEL_SESSION_REPLY,
114   ({
115     rmp->sw_if_index = ntohl (sw_if_index);
116   }));
117   /* *INDENT-ON* */
118 }
119
120 static void send_pppoe_session_details
121   (pppoe_session_t * t, vl_api_registration_t * reg, u32 context)
122 {
123   vl_api_pppoe_session_details_t *rmp;
124   ip4_main_t *im4 = &ip4_main;
125   ip6_main_t *im6 = &ip6_main;
126   u8 is_ipv6 = !ip46_address_is_ip4 (&t->client_ip);
127
128   rmp = vl_msg_api_alloc (sizeof (*rmp));
129   clib_memset (rmp, 0, sizeof (*rmp));
130   rmp->_vl_msg_id = ntohs (VL_API_PPPOE_SESSION_DETAILS);
131   if (is_ipv6)
132     {
133       memcpy (rmp->client_ip, t->client_ip.ip6.as_u8, 16);
134       rmp->decap_vrf_id = htonl (im6->fibs[t->decap_fib_index].ft_table_id);
135     }
136   else
137     {
138       memcpy (rmp->client_ip, t->client_ip.ip4.as_u8, 4);
139       rmp->decap_vrf_id = htonl (im4->fibs[t->decap_fib_index].ft_table_id);
140     }
141   rmp->session_id = htons (t->session_id);
142   rmp->encap_if_index = htonl (t->encap_if_index);
143   clib_memcpy (rmp->local_mac, t->local_mac, 6);
144   clib_memcpy (rmp->client_mac, t->client_mac, 6);
145   rmp->sw_if_index = htonl (t->sw_if_index);
146   rmp->is_ipv6 = is_ipv6;
147   rmp->context = context;
148
149   vl_api_send_msg (reg, (u8 *) rmp);
150 }
151
152 static void
153 vl_api_pppoe_session_dump_t_handler (vl_api_pppoe_session_dump_t * mp)
154 {
155   vl_api_registration_t *reg;
156   pppoe_main_t *pem = &pppoe_main;
157   pppoe_session_t *t;
158   u32 sw_if_index;
159
160   reg = vl_api_client_index_to_registration (mp->client_index);
161   if (!reg)
162     return;
163
164   sw_if_index = ntohl (mp->sw_if_index);
165
166   if (~0 == sw_if_index)
167     {
168       /* *INDENT-OFF* */
169       pool_foreach (t, pem->sessions,
170       ({
171         send_pppoe_session_details(t, reg, mp->context);
172       }));
173       /* *INDENT-ON* */
174     }
175   else
176     {
177       if ((sw_if_index >= vec_len (pem->session_index_by_sw_if_index)) ||
178           (~0 == pem->session_index_by_sw_if_index[sw_if_index]))
179         {
180           return;
181         }
182       t = &pem->sessions[pem->session_index_by_sw_if_index[sw_if_index]];
183       send_pppoe_session_details (t, reg, mp->context);
184     }
185 }
186
187
188 static clib_error_t *
189 pppoe_api_hookup (vlib_main_t * vm)
190 {
191   pppoe_main_t *pem = &pppoe_main;
192
193   u8 *name = format (0, "pppoe_%08x%c", api_version, 0);
194   pem->msg_id_base = vl_msg_api_get_msg_ids
195     ((char *) name, VL_MSG_FIRST_AVAILABLE);
196
197 #define _(N,n)                                                  \
198     vl_msg_api_set_handlers((VL_API_##N + pem->msg_id_base),     \
199                            #n,                  \
200                            vl_api_##n##_t_handler,              \
201                            vl_noop_handler,                     \
202                            vl_api_##n##_t_endian,               \
203                            vl_api_##n##_t_print,                \
204                            sizeof(vl_api_##n##_t), 1);
205   foreach_pppoe_plugin_api_msg;
206 #undef _
207
208   /* Add our API messages to the global name_crc hash table */
209   setup_message_id_table (pem, &api_main);
210
211   return 0;
212 }
213
214 VLIB_API_INIT_FUNCTION (pppoe_api_hookup);
215
216 /*
217  * fd.io coding-style-patch-verification: ON
218  *
219  * Local Variables:
220  * eval: (c-set-style "gnu")
221  * End:
222  */