Line data Source code
1 : /*
2 : * Copyright (c) 2015 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 <vat/vat.h>
17 : #include <vlibapi/api.h>
18 : #include <vlibmemory/api.h>
19 : #include <vppinfra/error.h>
20 :
21 : #include <dhcp/client.h>
22 : #include <dhcp/dhcp_proxy.h>
23 : #include <vnet/ip/ip_format_fns.h>
24 : #include <vnet/ethernet/ethernet_format_fns.h>
25 :
26 : /* define message IDs */
27 : #include <dhcp/dhcp.api_enum.h>
28 : #include <dhcp/dhcp.api_types.h>
29 :
30 : typedef struct
31 : {
32 : /* API message ID base */
33 : u16 msg_id_base;
34 : vat_main_t *vat_main;
35 : } dhcp_test_main_t;
36 :
37 : dhcp_test_main_t dhcp_test_main;
38 :
39 : #define __plugin_msg_base dhcp_test_main.msg_id_base
40 : #include <vlibapi/vat_helper_macros.h>
41 :
42 : #define FINISH \
43 : vec_add1 (s, 0); \
44 : vlib_cli_output (handle, (char *) s); \
45 : vec_free (s); \
46 : return handle;
47 :
48 : static int
49 0 : api_dhcp_proxy_config (vat_main_t * vam)
50 : {
51 0 : unformat_input_t *i = vam->input;
52 : vl_api_dhcp_proxy_config_t *mp;
53 0 : u32 rx_vrf_id = 0;
54 0 : u32 server_vrf_id = 0;
55 0 : u8 is_add = 1;
56 0 : u8 v4_address_set = 0;
57 0 : u8 v6_address_set = 0;
58 : ip4_address_t v4address;
59 : ip6_address_t v6address;
60 0 : u8 v4_src_address_set = 0;
61 0 : u8 v6_src_address_set = 0;
62 : ip4_address_t v4srcaddress;
63 : ip6_address_t v6srcaddress;
64 : int ret;
65 :
66 : /* Parse args required to build the message */
67 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
68 : {
69 0 : if (unformat (i, "del"))
70 0 : is_add = 0;
71 0 : else if (unformat (i, "rx_vrf_id %d", &rx_vrf_id))
72 : ;
73 0 : else if (unformat (i, "server_vrf_id %d", &server_vrf_id))
74 : ;
75 0 : else if (unformat (i, "svr %U", unformat_ip4_address, &v4address))
76 0 : v4_address_set = 1;
77 0 : else if (unformat (i, "svr %U", unformat_ip6_address, &v6address))
78 0 : v6_address_set = 1;
79 0 : else if (unformat (i, "src %U", unformat_ip4_address, &v4srcaddress))
80 0 : v4_src_address_set = 1;
81 0 : else if (unformat (i, "src %U", unformat_ip6_address, &v6srcaddress))
82 0 : v6_src_address_set = 1;
83 : else
84 0 : break;
85 : }
86 :
87 0 : if (v4_address_set && v6_address_set)
88 : {
89 0 : errmsg ("both v4 and v6 server addresses set");
90 0 : return -99;
91 : }
92 0 : if (!v4_address_set && !v6_address_set)
93 : {
94 0 : errmsg ("no server addresses set");
95 0 : return -99;
96 : }
97 :
98 0 : if (v4_src_address_set && v6_src_address_set)
99 : {
100 0 : errmsg ("both v4 and v6 src addresses set");
101 0 : return -99;
102 : }
103 0 : if (!v4_src_address_set && !v6_src_address_set)
104 : {
105 0 : errmsg ("no src addresses set");
106 0 : return -99;
107 : }
108 :
109 0 : if (!(v4_src_address_set && v4_address_set) &&
110 0 : !(v6_src_address_set && v6_address_set))
111 : {
112 0 : errmsg ("no matching server and src addresses set");
113 0 : return -99;
114 : }
115 :
116 : /* Construct the API message */
117 0 : M (DHCP_PROXY_CONFIG, mp);
118 :
119 0 : mp->is_add = is_add;
120 0 : mp->rx_vrf_id = ntohl (rx_vrf_id);
121 0 : mp->server_vrf_id = ntohl (server_vrf_id);
122 0 : if (v6_address_set)
123 : {
124 0 : clib_memcpy (&mp->dhcp_server.un, &v6address, sizeof (v6address));
125 0 : clib_memcpy (&mp->dhcp_src_address.un, &v6srcaddress,
126 : sizeof (v6address));
127 : }
128 : else
129 : {
130 0 : clib_memcpy (&mp->dhcp_server.un, &v4address, sizeof (v4address));
131 0 : clib_memcpy (&mp->dhcp_src_address.un, &v4srcaddress,
132 : sizeof (v4address));
133 : }
134 :
135 : /* send it... */
136 0 : S (mp);
137 :
138 : /* Wait for a reply, return good/bad news */
139 0 : W (ret);
140 0 : return ret;
141 : }
142 :
143 : static void
144 0 : vl_api_dhcp_proxy_details_t_handler (vl_api_dhcp_proxy_details_t * mp)
145 : {
146 0 : vat_main_t *vam = &vat_main;
147 0 : u32 i, count = mp->count;
148 : vl_api_dhcp_server_t *s;
149 :
150 0 : if (mp->is_ipv6)
151 0 : print (vam->ofp,
152 : "RX Table-ID %d, Source Address %U, VSS Type %d, "
153 : "VSS ASCII VPN-ID '%s', VSS RFC2685 VPN-ID (oui:id) %d:%d",
154 : ntohl (mp->rx_vrf_id),
155 : format_ip6_address, mp->dhcp_src_address,
156 0 : mp->vss_type, mp->vss_vpn_ascii_id,
157 : ntohl (mp->vss_oui), ntohl (mp->vss_fib_id));
158 : else
159 0 : print (vam->ofp,
160 : "RX Table-ID %d, Source Address %U, VSS Type %d, "
161 : "VSS ASCII VPN-ID '%s', VSS RFC2685 VPN-ID (oui:id) %d:%d",
162 : ntohl (mp->rx_vrf_id),
163 : format_ip4_address, mp->dhcp_src_address,
164 0 : mp->vss_type, mp->vss_vpn_ascii_id,
165 : ntohl (mp->vss_oui), ntohl (mp->vss_fib_id));
166 :
167 0 : for (i = 0; i < count; i++)
168 : {
169 0 : s = &mp->servers[i];
170 :
171 0 : if (mp->is_ipv6)
172 0 : print (vam->ofp,
173 : " Server Table-ID %d, Server Address %U",
174 : ntohl (s->server_vrf_id), format_ip6_address, s->dhcp_server);
175 : else
176 0 : print (vam->ofp,
177 : " Server Table-ID %d, Server Address %U",
178 : ntohl (s->server_vrf_id), format_ip4_address, s->dhcp_server);
179 : }
180 0 : }
181 :
182 : static int
183 0 : api_dhcp_proxy_dump (vat_main_t * vam)
184 : {
185 0 : unformat_input_t *i = vam->input;
186 : vl_api_dhcp_plugin_control_ping_t *mp_ping;
187 : vl_api_dhcp_proxy_dump_t *mp;
188 0 : u8 is_ipv6 = 0;
189 : int ret;
190 :
191 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
192 : {
193 0 : if (unformat (i, "ipv6"))
194 0 : is_ipv6 = 1;
195 : else
196 : {
197 0 : clib_warning ("parse error '%U'", format_unformat_error, i);
198 0 : return -99;
199 : }
200 : }
201 :
202 0 : M (DHCP_PROXY_DUMP, mp);
203 :
204 0 : mp->is_ip6 = is_ipv6;
205 0 : S (mp);
206 :
207 : /* Use a control ping for synchronization */
208 0 : MPING (DHCP_PLUGIN_CONTROL_PING, mp_ping);
209 0 : S (mp_ping);
210 :
211 0 : W (ret);
212 0 : return ret;
213 : }
214 :
215 : static int
216 0 : api_dhcp_proxy_set_vss (vat_main_t * vam)
217 : {
218 0 : unformat_input_t *i = vam->input;
219 : vl_api_dhcp_proxy_set_vss_t *mp;
220 0 : u8 is_ipv6 = 0;
221 0 : u8 is_add = 1;
222 0 : u32 tbl_id = ~0;
223 0 : u8 vss_type = VSS_TYPE_DEFAULT;
224 0 : u8 *vpn_ascii_id = 0;
225 0 : u32 oui = 0;
226 0 : u32 fib_id = 0;
227 : int ret;
228 :
229 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
230 : {
231 0 : if (unformat (i, "tbl_id %d", &tbl_id))
232 : ;
233 0 : else if (unformat (i, "vpn_ascii_id %s", &vpn_ascii_id))
234 0 : vss_type = VSS_TYPE_ASCII;
235 0 : else if (unformat (i, "fib_id %d", &fib_id))
236 0 : vss_type = VSS_TYPE_VPN_ID;
237 0 : else if (unformat (i, "oui %d", &oui))
238 0 : vss_type = VSS_TYPE_VPN_ID;
239 0 : else if (unformat (i, "ipv6"))
240 0 : is_ipv6 = 1;
241 0 : else if (unformat (i, "del"))
242 0 : is_add = 0;
243 : else
244 0 : break;
245 : }
246 :
247 0 : if (tbl_id == ~0)
248 : {
249 0 : errmsg ("missing tbl_id ");
250 0 : vec_free (vpn_ascii_id);
251 0 : return -99;
252 : }
253 :
254 0 : if ((vpn_ascii_id) && (vec_len (vpn_ascii_id) > 128))
255 : {
256 0 : errmsg ("vpn_ascii_id cannot be longer than 128 ");
257 0 : vec_free (vpn_ascii_id);
258 0 : return -99;
259 : }
260 :
261 0 : M (DHCP_PROXY_SET_VSS, mp);
262 0 : mp->tbl_id = ntohl (tbl_id);
263 0 : mp->vss_type = vss_type;
264 0 : if (vpn_ascii_id)
265 : {
266 0 : clib_memcpy (mp->vpn_ascii_id, vpn_ascii_id, vec_len (vpn_ascii_id));
267 0 : mp->vpn_ascii_id[vec_len (vpn_ascii_id)] = 0;
268 : }
269 0 : mp->vpn_index = ntohl (fib_id);
270 0 : mp->oui = ntohl (oui);
271 0 : mp->is_ipv6 = is_ipv6;
272 0 : mp->is_add = is_add;
273 :
274 0 : S (mp);
275 0 : W (ret);
276 :
277 0 : vec_free (vpn_ascii_id);
278 0 : return ret;
279 : }
280 :
281 : static int
282 0 : api_dhcp_client_config (vat_main_t * vam)
283 : {
284 0 : unformat_input_t *i = vam->input;
285 : vl_api_dhcp_client_config_t *mp;
286 : u32 sw_if_index;
287 0 : u8 sw_if_index_set = 0;
288 0 : u8 is_add = 1;
289 0 : u8 *hostname = 0;
290 0 : u8 disable_event = 0;
291 : int ret;
292 :
293 : /* Parse args required to build the message */
294 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
295 : {
296 0 : if (unformat (i, "del"))
297 0 : is_add = 0;
298 0 : else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
299 0 : sw_if_index_set = 1;
300 0 : else if (unformat (i, "sw_if_index %d", &sw_if_index))
301 0 : sw_if_index_set = 1;
302 0 : else if (unformat (i, "hostname %s", &hostname))
303 : ;
304 0 : else if (unformat (i, "disable_event"))
305 0 : disable_event = 1;
306 : else
307 0 : break;
308 : }
309 :
310 0 : if (sw_if_index_set == 0)
311 : {
312 0 : errmsg ("missing interface name or sw_if_index");
313 0 : return -99;
314 : }
315 :
316 0 : if (vec_len (hostname) > 63)
317 : {
318 0 : errmsg ("hostname too long");
319 : }
320 0 : vec_add1 (hostname, 0);
321 :
322 : /* Construct the API message */
323 0 : M (DHCP_CLIENT_CONFIG, mp);
324 :
325 0 : mp->is_add = is_add;
326 0 : mp->client.sw_if_index = htonl (sw_if_index);
327 0 : clib_memcpy (mp->client.hostname, hostname, vec_len (hostname));
328 0 : vec_free (hostname);
329 0 : mp->client.want_dhcp_event = disable_event ? 0 : 1;
330 0 : mp->client.pid = htonl (getpid ());
331 :
332 : /* send it... */
333 0 : S (mp);
334 :
335 : /* Wait for a reply, return good/bad news */
336 0 : W (ret);
337 0 : return ret;
338 : }
339 :
340 : static int
341 0 : api_want_dhcp6_reply_events (vat_main_t * vam)
342 : {
343 0 : return -1;
344 : }
345 :
346 : static int
347 0 : api_want_dhcp6_pd_reply_events (vat_main_t * vam)
348 : {
349 0 : return -1;
350 : }
351 :
352 : static int
353 0 : api_dhcp6_send_client_message (vat_main_t * vam)
354 : {
355 0 : return -1;
356 : }
357 :
358 : static int
359 0 : api_dhcp6_pd_send_client_message (vat_main_t * vam)
360 : {
361 0 : return -1;
362 : }
363 :
364 : static void
365 0 : vl_api_dhcp_client_details_t_handler (vl_api_dhcp_client_details_t * mp)
366 : {
367 0 : vat_main_t *vam = &vat_main;
368 : vl_api_dhcp_client_t *cp;
369 : vl_api_dhcp_lease_t *lp;
370 :
371 0 : cp = &mp->client;
372 0 : lp = &mp->lease;
373 :
374 0 : print (vam->ofp, "sw_if_index %d, id '%s'", ntohl (cp->sw_if_index),
375 0 : cp->id);
376 :
377 0 : print (vam->ofp, "leased address %U, router address %U",
378 : format_ip4_address, &lp->host_address.un,
379 : format_ip4_address, &lp->router_address.un);
380 0 : }
381 :
382 : static int
383 0 : api_dhcp_client_dump (vat_main_t * vam)
384 : {
385 : vl_api_dhcp_plugin_control_ping_t *mp_ping;
386 : vl_api_dhcp_client_dump_t *mp;
387 : int ret;
388 :
389 0 : M (DHCP_CLIENT_DUMP, mp);
390 :
391 0 : S (mp);
392 :
393 : /* Use a control ping for synchronization */
394 0 : MPING (DHCP_PLUGIN_CONTROL_PING, mp_ping);
395 0 : S (mp_ping);
396 :
397 0 : W (ret);
398 0 : return ret;
399 : }
400 :
401 : static int
402 0 : api_dhcp6_duid_ll_set (vat_main_t * vam)
403 : {
404 0 : return -1;
405 : }
406 :
407 : static int
408 0 : api_dhcp6_clients_enable_disable (vat_main_t * vam)
409 : {
410 0 : return -1;
411 : }
412 :
413 : static int
414 0 : api_dhcp_plugin_control_ping (vat_main_t * vam)
415 : {
416 0 : return -1;
417 : }
418 :
419 : static int
420 0 : api_dhcp_plugin_get_version (vat_main_t * vam)
421 : {
422 0 : return -1;
423 : }
424 :
425 : static void
426 0 : vl_api_dhcp_plugin_get_version_reply_t_handler
427 : (vl_api_dhcp_plugin_get_version_reply_t * mp)
428 : {
429 0 : vat_main_t *vam = dhcp_test_main.vat_main;
430 0 : clib_warning ("DHCP plugin version: %d.%d", ntohl (mp->major),
431 : ntohl (mp->minor));
432 0 : vam->result_ready = 1;
433 0 : }
434 :
435 : static void
436 0 : vl_api_dhcp_plugin_control_ping_reply_t_handler
437 : (vl_api_dhcp_plugin_control_ping_reply_t * mp)
438 : {
439 0 : vat_main_t *vam = dhcp_test_main.vat_main;
440 0 : i32 retval = ntohl (mp->retval);
441 0 : if (vam->async_mode)
442 : {
443 0 : vam->async_errors += (retval < 0);
444 : }
445 : else
446 : {
447 0 : vam->retval = retval;
448 0 : vam->result_ready = 1;
449 : }
450 0 : }
451 :
452 : #include <dhcp/dhcp.api_test.c>
453 :
454 : /*
455 : * fd.io coding-style-patch-verification: ON
456 : *
457 : * Local Variables:
458 : * eval: (c-set-style "gnu")
459 : * End:
460 : */
|