dns: make the dns name resolver a plugin
[vpp.git] / src / plugins / dns / dns_test.c
1 /*
2  * dns.c - skeleton vpp-api-test plug-in
3  *
4  * Copyright (c) <current-year> <your-organization>
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 #include <vat/vat.h>
18 #include <vlibapi/api.h>
19 #include <vlibmemory/api.h>
20 #include <vppinfra/error.h>
21 #include <stdbool.h>
22 #include <vnet/ip/ip.h>
23
24 uword unformat_sw_if_index (unformat_input_t * input, va_list * args);
25
26 /* Declare message IDs */
27 #include <dns/dns_msg_enum.h>
28
29 /* define message structures */
30 #define vl_typedefs
31 #include <dns/dns_all_api_h.h>
32 #undef vl_typedefs
33
34 /* declare message handlers for each api */
35
36 #define vl_endianfun            /* define message structures */
37 #include <dns/dns_all_api_h.h>
38 #undef vl_endianfun
39
40 /* instantiate all the print functions we know about */
41 #define vl_print(handle, ...)
42 #define vl_printfun
43 #include <dns/dns_all_api_h.h>
44 #undef vl_printfun
45
46 /* Get the API version number. */
47 #define vl_api_version(n,v) static u32 api_version=(v);
48 #include <dns/dns_all_api_h.h>
49 #undef vl_api_version
50
51 typedef struct
52 {
53   /* API message ID base */
54   u16 msg_id_base;
55   vat_main_t *vat_main;
56 } dns_test_main_t;
57
58 dns_test_main_t dns_test_main;
59
60 #define __plugin_msg_base dns_test_main.msg_id_base
61 #include <vlibapi/vat_helper_macros.h>
62
63 #define foreach_standard_reply_retval_handler   \
64 _(dns_enable_disable_reply)                     \
65 _(dns_name_server_add_del_reply)
66
67 #define _(n)                                                    \
68     static void vl_api_##n##_t_handler                          \
69     (vl_api_##n##_t * mp)                                       \
70     {                                                           \
71         vat_main_t * vam = dns_test_main.vat_main;              \
72         i32 retval = (i32) clib_net_to_host_u32(mp->retval);    \
73         if (vam->async_mode) {                                  \
74             vam->async_errors += (retval < 0);                  \
75         } else {                                                \
76             vam->retval = retval;                               \
77             vam->result_ready = 1;                              \
78         }                                                       \
79     }
80 foreach_standard_reply_retval_handler;
81 #undef _
82
83 static void vl_api_dns_resolve_name_reply_t_handler
84   (vl_api_dns_resolve_name_reply_t * mp)
85 {
86   vat_main_t *vam = dns_test_main.vat_main;
87   i32 retval = (i32) clib_net_to_host_u32 (mp->retval);
88   if (retval == 0)
89     {
90       if (mp->ip4_set)
91         clib_warning ("resolved: %U", format_ip4_address, mp->ip4_address);
92       if (mp->ip6_set)
93         clib_warning ("resolved: %U", format_ip6_address, mp->ip6_address);
94     }
95   if (vam->async_mode)
96     vam->async_errors += (retval < 0);
97   else
98     {
99       vam->retval = retval;
100       vam->result_ready = 1;
101     }
102 }
103
104 static void vl_api_dns_resolve_ip_reply_t_handler
105   (vl_api_dns_resolve_ip_reply_t * mp)
106 {
107   vat_main_t *vam = dns_test_main.vat_main;
108   i32 retval = (i32) clib_net_to_host_u32 (mp->retval);
109   if (retval == 0)
110     clib_warning ("resolved: %s", mp->name);
111   if (vam->async_mode)
112     vam->async_errors += (retval < 0);
113   else
114     {
115       vam->retval = retval;
116       vam->result_ready = 1;
117     }
118 }
119
120 /*
121  * Table of message reply handlers, must include boilerplate handlers
122  * we just generated
123  */
124 #define foreach_vpe_api_reply_msg                               \
125 _(DNS_ENABLE_DISABLE_REPLY, dns_enable_disable_reply)           \
126 _(DNS_NAME_SERVER_ADD_DEL_REPLY, dns_name_server_add_del_reply) \
127 _(DNS_RESOLVE_NAME_REPLY, dns_resolve_name_reply)               \
128 _(DNS_RESOLVE_IP_REPLY, dns_resolve_ip_reply)
129
130 static int
131 api_dns_enable_disable (vat_main_t * vam)
132 {
133   vl_api_dns_enable_disable_t *mp;
134   unformat_input_t *i = vam->input;
135   int enable = 1;
136   int ret;
137
138   /* Parse args required to build the message */
139   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
140     {
141       if (unformat (i, "disable"))
142         enable = 0;
143       else if (unformat (i, "enable"))
144         enable = 1;
145       else
146         break;
147     }
148
149   /* Construct the API message */
150   M (DNS_ENABLE_DISABLE, mp);
151   mp->enable = enable;
152
153   /* send it... */
154   S (mp);
155
156   /* Wait for a reply... */
157   W (ret);
158   return ret;
159 }
160
161 /*
162  * List of messages that the api test plugin sends,
163  * and that the data plane plugin processes
164  */
165 #define foreach_vpe_api_msg \
166 _(dns_enable_disable, "[enable][disable]")                              \
167 _(dns_name_server_add_del, "<ip-address> [del]")                        \
168 _(dns_resolve_name, "<hostname>")                                       \
169 _(dns_resolve_ip, "<ip4|ip6>")                                          \
170 _(dns_name_server_add_del, "<ip-address> [del]")                        \
171 _(dns_resolve_name, "<hostname>")
172
173 static int
174 api_dns_resolve_name (vat_main_t * vam)
175 {
176   unformat_input_t *line_input = vam->input;
177   vl_api_dns_resolve_name_t *mp;
178   u8 *name = 0;
179   int ret;
180
181   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
182     {
183       if (unformat (line_input, "%s", &name))
184         ;
185       else
186         break;
187     }
188
189   if (vec_len (name) > 127)
190     {
191       errmsg ("name too long");
192       return -99;
193     }
194
195   /* Construct the API message */
196   M (DNS_RESOLVE_NAME, mp);
197   memcpy (mp->name, name, vec_len (name));
198   vec_free (name);
199
200   /* send it... */
201   S (mp);
202   /* Wait for the reply */
203   W (ret);
204   return ret;
205 }
206
207 static int
208 api_dns_resolve_ip (vat_main_t * vam)
209 {
210   unformat_input_t *line_input = vam->input;
211   vl_api_dns_resolve_ip_t *mp;
212   int is_ip6 = -1;
213   ip4_address_t addr4;
214   ip6_address_t addr6;
215   int ret;
216
217   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
218     {
219       if (unformat (line_input, "%U", unformat_ip6_address, &addr6))
220         is_ip6 = 1;
221       else if (unformat (line_input, "%U", unformat_ip4_address, &addr4))
222         is_ip6 = 0;
223       else
224         break;
225     }
226
227   if (is_ip6 == -1)
228     {
229       errmsg ("missing address");
230       return -99;
231     }
232
233   /* Construct the API message */
234   M (DNS_RESOLVE_IP, mp);
235   mp->is_ip6 = is_ip6;
236   if (is_ip6)
237     memcpy (mp->address, &addr6, sizeof (addr6));
238   else
239     memcpy (mp->address, &addr4, sizeof (addr4));
240
241   /* send it... */
242   S (mp);
243   /* Wait for the reply */
244   W (ret);
245   return ret;
246 }
247
248 static int
249 api_dns_name_server_add_del (vat_main_t * vam)
250 {
251   unformat_input_t *i = vam->input;
252   vl_api_dns_name_server_add_del_t *mp;
253   u8 is_add = 1;
254   ip6_address_t ip6_server;
255   ip4_address_t ip4_server;
256   int ip6_set = 0;
257   int ip4_set = 0;
258   int ret = 0;
259
260   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
261     {
262       if (unformat (i, "%U", unformat_ip6_address, &ip6_server))
263         ip6_set = 1;
264       else if (unformat (i, "%U", unformat_ip4_address, &ip4_server))
265         ip4_set = 1;
266       else if (unformat (i, "del"))
267         is_add = 0;
268       else
269         {
270           clib_warning ("parse error '%U'", format_unformat_error, i);
271           return -99;
272         }
273     }
274
275   if (ip4_set && ip6_set)
276     {
277       errmsg ("Only one server address allowed per message");
278       return -99;
279     }
280   if ((ip4_set + ip6_set) == 0)
281     {
282       errmsg ("Server address required");
283       return -99;
284     }
285
286   /* Construct the API message */
287   M (DNS_NAME_SERVER_ADD_DEL, mp);
288
289   if (ip6_set)
290     {
291       memcpy (mp->server_address, &ip6_server, sizeof (ip6_address_t));
292       mp->is_ip6 = 1;
293     }
294   else
295     {
296       memcpy (mp->server_address, &ip4_server, sizeof (ip4_address_t));
297       mp->is_ip6 = 0;
298     }
299
300   mp->is_add = is_add;
301
302   /* send it... */
303   S (mp);
304
305   /* Wait for a reply, return good/bad news  */
306   W (ret);
307   return ret;
308 }
309
310 static void
311 dns_api_hookup (vat_main_t * vam)
312 {
313   dns_test_main_t *dtmp = &dns_test_main;
314   /* Hook up handlers for replies from the data plane plug-in */
315 #define _(N,n)                                                  \
316     vl_msg_api_set_handlers((VL_API_##N + dtmp->msg_id_base),   \
317                            #n,                                  \
318                            vl_api_##n##_t_handler,              \
319                            vl_noop_handler,                     \
320                            vl_api_##n##_t_endian,               \
321                            vl_api_##n##_t_print,                \
322                            sizeof(vl_api_##n##_t), 1);
323   foreach_vpe_api_reply_msg;
324 #undef _
325
326   /* API messages we can send */
327 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
328   foreach_vpe_api_msg;
329 #undef _
330
331   /* Help strings */
332 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
333   foreach_vpe_api_msg;
334 #undef _
335 }
336
337 VAT_PLUGIN_REGISTER (dns);
338
339
340 /*
341  * fd.io coding-style-patch-verification: ON
342  *
343  * Local Variables:
344  * eval: (c-set-style "gnu")
345  * End:
346  */