FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
dns.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 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 <vnet/vnet.h>
17 #include <vnet/udp/udp_local.h>
18 #include <vnet/plugin/plugin.h>
19 #include <dns/dns.h>
20 #include <vnet/ip/ip_sas.h>
21 #include <vlibapi/api.h>
22 #include <vlibmemory/api.h>
23 #include <vpp/app/version.h>
24 #include <stdbool.h>
25 
26 /* define message IDs */
27 #include <dns/dns.api_enum.h>
28 #include <dns/dns.api_types.h>
29 
30 #define REPLY_MSG_ID_BASE dm->msg_id_base
32 
33 /* Macro to finish up custom dump fns */
34 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
35 #define FINISH \
36  vec_add1 (s, 0); \
37  vl_print (handle, (char *)s); \
38  vec_free (s); \
39  return handle;
40 
42 
43 static int
45 {
47 
48  if (dm->is_enabled == 0)
49  return VNET_API_ERROR_NAME_RESOLUTION_NOT_ENABLED;
50 
51  dns_cache_lock (dm, 1);
52 
53  /* *INDENT-OFF* */
54  pool_foreach (ep, dm->entries)
55  {
56  vec_free (ep->name);
58  }
59  /* *INDENT-ON* */
60 
61  pool_free (dm->entries);
63  dm->cache_entry_by_name = hash_create_string (0, sizeof (uword));
65  dns_cache_unlock (dm);
66  return 0;
67 }
68 
69 static int
70 dns_enable_disable (vlib_main_t * vm, dns_main_t * dm, int is_enable)
71 {
73  u32 n_vlib_mains = tm->n_vlib_mains;
74 
75  /* Create the resolver process if not done already */
77 
78  if (is_enable)
79  {
80  if (vec_len (dm->ip4_name_servers) == 0
81  && (vec_len (dm->ip6_name_servers) == 0))
82  return VNET_API_ERROR_NO_NAME_SERVERS;
83 
84  if (dm->udp_ports_registered == 0)
85  {
86  udp_register_dst_port (vm, UDP_DST_PORT_dns_reply,
87  dns46_reply_node.index, 1 /* is_ip4 */ );
88 
89  udp_register_dst_port (vm, UDP_DST_PORT_dns_reply6,
90  dns46_reply_node.index, 0 /* is_ip4 */ );
91 
92  udp_register_dst_port (vm, UDP_DST_PORT_dns,
93  dns4_request_node.index, 1 /* is_ip4 */ );
94 
95  udp_register_dst_port (vm, UDP_DST_PORT_dns6,
96  dns6_request_node.index, 0 /* is_ip4 */ );
97 
98  dm->udp_ports_registered = 1;
99  }
100 
101  if (dm->cache_entry_by_name == 0)
102  {
103  if (n_vlib_mains > 1)
105 
106  dm->cache_entry_by_name = hash_create_string (0, sizeof (uword));
107  }
108 
109  dm->is_enabled = 1;
110  }
111  else
112  {
113  dns_cache_clear (dm);
114  dm->is_enabled = 0;
115  }
116  return 0;
117 }
118 
121 {
122  vl_api_dns_enable_disable_reply_t *rmp;
124  dns_main_t *dm = &dns_main;
125  int rv;
126 
127  rv = dns_enable_disable (vm, dm, mp->enable);
128 
129  REPLY_MACRO (VL_API_DNS_ENABLE_DISABLE_REPLY);
130 }
131 
132 static int
134  u8 * server_address_as_u8, int is_add)
135 {
136  int i;
137  ip6_address_t *ap;
138 
139  if (is_add)
140  {
141  /* Already there? done... */
142  for (i = 0; i < vec_len (dm->ip6_name_servers); i++)
143  {
144  if (!memcmp (dm->ip6_name_servers + i, server_address_as_u8,
145  sizeof (ip6_address_t)))
146  return 0;
147  }
148 
149  vec_add2 (dm->ip6_name_servers, ap, 1);
150  clib_memcpy (ap, server_address_as_u8, sizeof (*ap));
151  }
152  else
153  {
154  for (i = 0; i < vec_len (dm->ip6_name_servers); i++)
155  {
156  if (!memcmp (dm->ip6_name_servers + i, server_address_as_u8,
157  sizeof (ip6_address_t)))
158  {
159  vec_delete (dm->ip6_name_servers, 1, i);
160  return 0;
161  }
162  }
163  return VNET_API_ERROR_NAME_SERVER_NOT_FOUND;
164  }
165  return 0;
166 }
167 
168 static int
170  u8 * server_address_as_u8, int is_add)
171 {
172  int i;
173  ip4_address_t *ap;
174 
175  if (is_add)
176  {
177  /* Already there? done... */
178  for (i = 0; i < vec_len (dm->ip4_name_servers); i++)
179  {
180  if (!memcmp (dm->ip4_name_servers + i, server_address_as_u8,
181  sizeof (ip4_address_t)))
182  return 0;
183  }
184 
185  vec_add2 (dm->ip4_name_servers, ap, 1);
186  clib_memcpy (ap, server_address_as_u8, sizeof (*ap));
187  }
188  else
189  {
190  for (i = 0; i < vec_len (dm->ip4_name_servers); i++)
191  {
192  if (!memcmp (dm->ip4_name_servers + i, server_address_as_u8,
193  sizeof (ip4_address_t)))
194  {
195  vec_delete (dm->ip4_name_servers, 1, i);
196  return 0;
197  }
198  }
199  return VNET_API_ERROR_NAME_SERVER_NOT_FOUND;
200  }
201  return 0;
202 }
203 
206 {
207  dns_main_t *dm = &dns_main;
208  vl_api_dns_name_server_add_del_reply_t *rmp;
209  int rv;
210 
211  if (mp->is_ip6)
213  else
215 
216  REPLY_MACRO (VL_API_DNS_NAME_SERVER_ADD_DEL_REPLY);
217 }
218 
219 void
221  dns_cache_entry_t * ep, ip4_address_t * server)
222 {
223  f64 now = vlib_time_now (vm);
224  u32 bi;
225  vlib_buffer_t *b;
226  ip4_header_t *ip;
227  udp_header_t *udp;
229  u8 *dns_request;
230  vlib_frame_t *f;
231  u32 *to_next;
232 
233  ASSERT (ep->dns_request);
234 
235  if (!ip4_sas (0 /* default VRF for now */, ~0, server, &src_address))
236  return;
237 
238  /* Go get a buffer */
239  if (vlib_buffer_alloc (vm, &bi, 1) != 1)
240  return;
241 
242  b = vlib_get_buffer (vm, bi);
243  b->current_length = sizeof (ip4_header_t) + sizeof (udp_header_t) +
244  vec_len (ep->dns_request);
246  b->flags =
247  VLIB_BUFFER_TOTAL_LENGTH_VALID | VNET_BUFFER_F_LOCALLY_ORIGINATED;
248  vnet_buffer (b)->sw_if_index[VLIB_RX] = 0; /* "local0" */
249  vnet_buffer (b)->sw_if_index[VLIB_TX] = 0; /* default VRF for now */
250 
252  clib_memset (ip, 0, sizeof (*ip));
253  udp = (udp_header_t *) (ip + 1);
254  clib_memset (udp, 0, sizeof (*udp));
255 
256  dns_request = (u8 *) (udp + 1);
257 
258  /* IP header */
259  ip->ip_version_and_header_length = 0x45;
260  ip->length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b));
261  ip->ttl = 255;
262  ip->protocol = IP_PROTOCOL_UDP;
263  ip->src_address.as_u32 = src_address.as_u32;
264  ip->dst_address.as_u32 = server->as_u32;
265  ip->checksum = ip4_header_checksum (ip);
266 
267  /* UDP header */
268  udp->src_port = clib_host_to_net_u16 (UDP_DST_PORT_dns_reply);
269  udp->dst_port = clib_host_to_net_u16 (UDP_DST_PORT_dns);
270  udp->length = clib_host_to_net_u16 (sizeof (udp_header_t) +
271  vec_len (ep->dns_request));
272  udp->checksum = 0;
273 
274  /* The actual DNS request */
275  clib_memcpy (dns_request, ep->dns_request, vec_len (ep->dns_request));
276 
277  /* Ship it to ip4_lookup */
279  to_next = vlib_frame_vector_args (f);
280  to_next[0] = bi;
281  f->n_vectors = 1;
283 
284  ep->retry_timer = now + 2.0;
285 }
286 
287 void
289  dns_cache_entry_t * ep, ip6_address_t * server)
290 {
291  f64 now = vlib_time_now (vm);
292  u32 bi;
293  vlib_buffer_t *b;
294  ip6_header_t *ip;
295  udp_header_t *udp;
296  ip6_address_t src_address;
297  u8 *dns_request;
298  vlib_frame_t *f;
299  u32 *to_next;
300  int junk __attribute__ ((unused));
301 
302  ASSERT (ep->dns_request);
303 
304  if (!ip6_sas (0 /* default VRF for now */, ~0, server, &src_address))
305  return;
306 
307  /* Go get a buffer */
308  if (vlib_buffer_alloc (vm, &bi, 1) != 1)
309  return;
310 
311  b = vlib_get_buffer (vm, bi);
312  b->current_length = sizeof (ip6_header_t) + sizeof (udp_header_t) +
313  vec_len (ep->dns_request);
315  b->flags =
316  VLIB_BUFFER_TOTAL_LENGTH_VALID | VNET_BUFFER_F_LOCALLY_ORIGINATED;
317 
319  clib_memset (ip, 0, sizeof (*ip));
320  udp = (udp_header_t *) (ip + 1);
321  clib_memset (udp, 0, sizeof (*udp));
322 
323  dns_request = (u8 *) (udp + 1);
324 
325  /* IP header */
326  ip->ip_version_traffic_class_and_flow_label =
327  clib_host_to_net_u32 (0x6 << 28);
328 
329  ip->payload_length =
330  clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b)
331  - sizeof (ip6_header_t));
332  ip->hop_limit = 255;
333  ip->protocol = IP_PROTOCOL_UDP;
334  ip6_address_copy (&ip->src_address, &src_address);
335  clib_memcpy (&ip->dst_address, server, sizeof (ip6_address_t));
336 
337  /* UDP header */
338  udp->src_port = clib_host_to_net_u16 (UDP_DST_PORT_dns_reply);
339  udp->dst_port = clib_host_to_net_u16 (UDP_DST_PORT_dns);
340  udp->length = clib_host_to_net_u16 (sizeof (udp_header_t) +
341  vec_len (ep->dns_request));
342  udp->checksum = 0;
344 
345  /* The actual DNS request */
346  clib_memcpy (dns_request, ep->dns_request, vec_len (ep->dns_request));
347 
348  /* Ship it to ip6_lookup */
350  to_next = vlib_frame_vector_args (f);
351  to_next[0] = bi;
352  f->n_vectors = 1;
353 
354  ep->retry_timer = now + 2.0;
355 }
356 
357 /**
358  * Translate "foo.com" into "0x3 f o o 0x3 c o m 0x0"
359  * A historical / hysterical micro-TLV scheme. DGMS.
360  */
361 u8 *
363 {
364  int i;
365  int last_label_index;
366  u8 *rv;
367 
368  rv = vec_dup (name);
369 
370  /* punch in space for the first length */
371  vec_insert (rv, 1, 0);
372  last_label_index = 0;
373  i = 1;
374 
375  while (i < vec_len (rv))
376  {
377  if (rv[i] == '.')
378  {
379  rv[last_label_index] = (i - last_label_index) - 1;
380  if ((i - last_label_index) > 63)
381  clib_warning ("stupid name, label length %d",
382  i - last_label_index);
383  last_label_index = i;
384  rv[i] = 0;
385  }
386  i++;
387  }
388  /* Set the last real label length */
389  rv[last_label_index] = (i - last_label_index) - 1;
390 
391  /*
392  * Add a [sic] NULL root label. Otherwise, the name parser can't figure out
393  * where to stop.
394  */
395  vec_add1 (rv, 0);
396  return rv;
397 }
398 
399 /**
400  * arc-function for the above.
401  * Translate "0x3 f o o 0x3 c o m 0x0" into "foo.com"
402  * Produces a non-NULL-terminated u8 *vector. %v format is your friend.
403  */
404 u8 *
405 vnet_dns_labels_to_name (u8 * label, u8 * full_text, u8 ** parse_from_here)
406 {
407  u8 *reply = 0;
408  u16 offset;
409  u8 len;
410  int i;
411 
412  *parse_from_here = 0;
413 
414  /* chase initial pointer? */
415  if ((label[0] & 0xC0) == 0xC0)
416  {
417  *parse_from_here = label + 2;
418  offset = ((label[0] & 0x3f) << 8) + label[1];
419  label = full_text + offset;
420  }
421 
422  len = *label++;
423 
424  while (len)
425  {
426  for (i = 0; i < len; i++)
427  vec_add1 (reply, *label++);
428 
429  /* chase pointer? */
430  if ((label[0] & 0xC0) == 0xC0)
431  {
432  *parse_from_here = label + 2;
433  offset = ((label[0] & 0x3f) << 8) + label[1];
434  label = full_text + offset;
435  }
436 
437  len = *label++;
438  if (len)
439  vec_add1 (reply, '.');
440  }
441  if (*parse_from_here == 0)
442  *parse_from_here = label;
443  return reply;
444 }
445 
446 void
448  dns_cache_entry_t * ep)
449 {
450  dns_header_t *h;
451  dns_query_t *qp;
452  u16 tmp;
453  u8 *request, *name_copy;
454  u32 qp_offset;
455 
456  /* This can easily happen if sitting in GDB, etc. */
457  if (ep->flags & DNS_CACHE_ENTRY_FLAG_VALID || ep->server_fails > 1)
458  return;
459 
460  /* Construct the dns request, if we haven't been here already */
461  if (vec_len (ep->dns_request) == 0)
462  {
463  /*
464  * Start with the variadic portion of the exercise.
465  * Turn the name into a set of DNS "labels". Max length
466  * per label is 63, enforce that.
467  */
468  request = name_to_labels (ep->name);
469  name_copy = vec_dup (request);
470  qp_offset = vec_len (request);
471 
472  /*
473  * At least when testing against "known good" DNS servers:
474  * it turns out that sending 2x requests - one for an A-record
475  * and another for a AAAA-record - seems to work better than
476  * sending a DNS_TYPE_ALL request.
477  */
478 
479  /* Add space for the query header */
480  vec_validate (request, 2 * qp_offset + 2 * sizeof (dns_query_t) - 1);
481 
482  qp = (dns_query_t *) (request + qp_offset);
483 
484  qp->type = clib_host_to_net_u16 (DNS_TYPE_A);
485  qp->class = clib_host_to_net_u16 (DNS_CLASS_IN);
486  qp++;
487  clib_memcpy (qp, name_copy, vec_len (name_copy));
488  qp = (dns_query_t *) (((u8 *) qp) + vec_len (name_copy));
489  vec_free (name_copy);
490 
491  qp->type = clib_host_to_net_u16 (DNS_TYPE_AAAA);
492  qp->class = clib_host_to_net_u16 (DNS_CLASS_IN);
493 
494  /* Punch in space for the dns_header_t */
495  vec_insert (request, sizeof (dns_header_t), 0);
496 
497  h = (dns_header_t *) request;
498 
499  /* Transaction ID = pool index */
500  h->id = clib_host_to_net_u16 (ep - dm->entries);
501 
502  /* Ask for a recursive lookup */
504  h->flags = clib_host_to_net_u16 (tmp);
505  h->qdcount = clib_host_to_net_u16 (2);
506  h->nscount = 0;
507  h->arcount = 0;
508 
509  ep->dns_request = request;
510  }
511 
512  /* Work out which server / address family we're going to use */
513 
514  /* Retry using current server */
516  {
517  if (ep->server_af == 1 /* ip6 */ )
518  {
519  if (vec_len (dm->ip6_name_servers))
520  {
522  (vm, dm, ep, dm->ip6_name_servers + ep->server_rotor);
523  goto out;
524  }
525  else
526  ep->server_af = 0;
527  }
528  if (vec_len (dm->ip4_name_servers))
529  {
531  (vm, dm, ep, dm->ip4_name_servers + ep->server_rotor);
532  goto out;
533  }
534  }
535  else /* switch to a new server */
536  {
537  ep->retry_count = 1;
538  ep->server_rotor++;
539  if (ep->server_af == 1 /* ip6 */ )
540  {
541  if (ep->server_rotor >= vec_len (dm->ip6_name_servers))
542  {
543  ep->server_rotor = 0;
544  ep->server_af = vec_len (dm->ip4_name_servers) > 0 ? 0 : 1;
545  }
546  }
547  else
548  {
549  if (ep->server_rotor >= vec_len (dm->ip4_name_servers))
550  {
551  ep->server_rotor = 0;
552  ep->server_af = vec_len (dm->ip6_name_servers) > 0 ? 1 : 0;
553  }
554  }
555  }
556 
557  if (ep->server_af == 1 /* ip6 */ )
559  (vm, dm, ep, dm->ip6_name_servers + ep->server_rotor);
560  else
562  (vm, dm, ep, dm->ip4_name_servers + ep->server_rotor);
563 
564 out:
565 
569 }
570 
571 int
573 {
574  dns_cache_entry_t *ep;
575  int i;
576 
577  if (dm->is_enabled == 0)
578  return VNET_API_ERROR_NAME_RESOLUTION_NOT_ENABLED;
579 
580  if (pool_is_free_index (dm->entries, index))
581  return VNET_API_ERROR_NO_SUCH_ENTRY;
582 
583  ep = pool_elt_at_index (dm->entries, index);
584  if (!(ep->flags & DNS_CACHE_ENTRY_FLAG_VALID))
585  {
586  for (i = 0; i < vec_len (dm->unresolved_entries); i++)
587  if (index == dm->unresolved_entries[i])
588  {
589  vec_delete (dm->unresolved_entries, 1, i);
590  goto found;
591  }
592  clib_warning ("pool elt %d supposedly pending, but not found...",
593  index);
594  }
595 
596 found:
598  vec_free (ep->name);
600  pool_put (dm->entries, ep);
601 
602  return 0;
603 }
604 
605 static int
607 {
608  int rv;
609  uword *p;
610 
611  if (dm->is_enabled == 0)
612  return VNET_API_ERROR_NAME_RESOLUTION_NOT_ENABLED;
613 
614  dns_cache_lock (dm, 2);
616  if (!p)
617  {
618  dns_cache_unlock (dm);
619  return VNET_API_ERROR_NO_SUCH_ENTRY;
620  }
622 
623  dns_cache_unlock (dm);
624 
625  return rv;
626 }
627 
628 static int
630 {
631  int rv;
632  u32 victim_index, start_index, i;
633  u32 limit;
634  dns_cache_entry_t *ep;
635 
636  if (dm->is_enabled == 0)
637  return VNET_API_ERROR_NAME_RESOLUTION_NOT_ENABLED;
638 
639  /*
640  * Silence spurious coverity warning. We know pool_elts >> 0, or
641  * we wouldn't be here...
642  */
643 #ifdef __COVERITY__
644  if (pool_elts (dm->entries) == 0)
645  return VNET_API_ERROR_UNSPECIFIED;
646 #endif
647 
648  dns_cache_lock (dm, 3);
649  limit = pool_elts (dm->entries);
650  start_index = random_u32 (&dm->random_seed) % limit;
651 
652  for (i = 0; i < limit; i++)
653  {
654  victim_index = (start_index + i) % limit;
655 
656  if (!pool_is_free_index (dm->entries, victim_index))
657  {
658  ep = pool_elt_at_index (dm->entries, victim_index);
659  /* Delete only valid, non-static entries */
661  && ((ep->flags & DNS_CACHE_ENTRY_FLAG_STATIC) == 0))
662  {
663  rv = vnet_dns_delete_entry_by_index_nolock (dm, victim_index);
664  dns_cache_unlock (dm);
665  return rv;
666  }
667  }
668  }
669  dns_cache_unlock (dm);
670 
671  clib_warning ("Couldn't find an entry to delete?");
672  return VNET_API_ERROR_UNSPECIFIED;
673 }
674 
675 static int
676 dns_add_static_entry (dns_main_t * dm, u8 * name, u8 * dns_reply_data)
677 {
678  dns_cache_entry_t *ep;
679  uword *p;
680  int rv;
681 
682  if (dm->is_enabled == 0)
683  return VNET_API_ERROR_NAME_RESOLUTION_NOT_ENABLED;
684 
685  dns_cache_lock (dm, 4);
687  if (p)
688  {
689  dns_cache_unlock (dm);
690  return VNET_API_ERROR_ENTRY_ALREADY_EXISTS;
691  }
692 
693  if (pool_elts (dm->entries) == dm->name_cache_size)
694  {
695  /* Will only fail if the cache is totally filled w/ static entries... */
696  rv = delete_random_entry (dm);
697  if (rv)
698  {
699  dns_cache_unlock (dm);
700  return rv;
701  }
702  }
703 
704  pool_get (dm->entries, ep);
705  clib_memset (ep, 0, sizeof (*ep));
706 
707  /* Note: consumes the name vector */
708  ep->name = name;
709  /* make sure it NULL-terminated as hash_set_mem will use strlen() */
711  hash_set_mem (dm->cache_entry_by_name, ep->name, ep - dm->entries);
713  ep->dns_response = dns_reply_data;
714 
715  dns_cache_unlock (dm);
716  return 0;
717 }
718 
719 int
722 {
723  dns_cache_entry_t *ep;
724  int rv;
725  f64 now;
726  uword *p;
728  int count;
729 
730  now = vlib_time_now (vm);
731 
732  /* In case we can't actually answer the question right now... */
733  *retp = 0;
734 
735  /* binary API caller might forget to set the name. Guess how we know. */
736  if (name[0] == 0)
737  return VNET_API_ERROR_INVALID_VALUE;
738 
739  dns_cache_lock (dm, 5);
740 search_again:
742  if (p)
743  {
744  ep = pool_elt_at_index (dm->entries, p[0]);
746  {
747  /* Has the entry expired? */
748  if (((ep->flags & DNS_CACHE_ENTRY_FLAG_STATIC) == 0)
749  && (now > ep->expiration_time))
750  {
751  int i;
752  u32 *indices_to_delete = 0;
753 
754  /*
755  * Take out the rest of the resolution chain
756  * This isn't optimal, but it won't happen very often.
757  */
758  while (ep)
759  {
760  if ((ep->flags & DNS_CACHE_ENTRY_FLAG_CNAME))
761  {
762  vec_add1 (indices_to_delete, ep - dm->entries);
763 
764  p = hash_get_mem (dm->cache_entry_by_name, ep->cname);
765  if (!p)
766  break;
767  ep = pool_elt_at_index (dm->entries, p[0]);
768  }
769  else
770  {
771  vec_add1 (indices_to_delete, ep - dm->entries);
772  break;
773  }
774  }
775  for (i = 0; i < vec_len (indices_to_delete); i++)
776  {
777  /* Reenable to watch re-resolutions */
778  if (0)
779  {
780  ep = pool_elt_at_index (dm->entries,
781  indices_to_delete[i]);
782  clib_warning ("Re-resolve %s", ep->name);
783  }
784 
786  (dm, indices_to_delete[i]);
787  }
788  vec_free (indices_to_delete);
789  /* Yes, kill it... */
790  goto re_resolve;
791  }
792 
794  {
795  name = ep->cname;
796  goto search_again;
797  }
798  *retp = ep;
799  dns_cache_unlock (dm);
800  return (0);
801  }
802  else
803  {
804  /*
805  * Resolution pending. Add request to the pending vector
806  * by copying the template request
807  */
808  vec_add2 (ep->pending_requests, pr, 1);
809  memcpy (pr, t, sizeof (*pr));
810  dns_cache_unlock (dm);
811  return (0);
812  }
813  }
814 
815 re_resolve:
816  if (pool_elts (dm->entries) == dm->name_cache_size)
817  {
818  /* Will only fail if the cache is totally filled w/ static entries... */
819  rv = delete_random_entry (dm);
820  if (rv)
821  {
822  dns_cache_unlock (dm);
823  return rv;
824  }
825  }
826 
827  /* add new hash table entry */
828  pool_get (dm->entries, ep);
829  clib_memset (ep, 0, sizeof (*ep));
830 
831  ep->name = format (0, "%s%c", name, 0);
832  _vec_len (ep->name) = vec_len (ep->name) - 1;
833 
834  hash_set_mem (dm->cache_entry_by_name, ep->name, ep - dm->entries);
835 
836  vec_add1 (dm->unresolved_entries, ep - dm->entries);
837  vec_add2 (ep->pending_requests, pr, 1);
838 
839  pr->request_type = t->request_type;
840 
841  /* Remember details so we can reply later... */
844  {
845  pr->client_index = t->client_index;
847  }
848  else
849  {
850  pr->client_index = ~0;
851  pr->is_ip6 = t->is_ip6;
852  pr->dst_port = t->dst_port;
853  pr->id = t->id;
854  pr->name = t->name;
855  if (t->is_ip6)
856  count = 16;
857  else
858  count = 4;
860  }
861 
862  vnet_send_dns_request (vm, dm, ep);
863  dns_cache_unlock (dm);
864  return 0;
865 }
866 
867 #define foreach_notification_to_move \
868 _(pending_requests)
869 
870 /**
871  * Handle cname indirection. JFC. Called with the cache locked.
872  * returns 0 if the reply is not a CNAME.
873  */
874 
875 int
877  u32 ep_index, u8 * reply)
878 {
879  dns_header_t *h;
880  dns_query_t *qp;
881  dns_rr_t *rr;
882  u8 *curpos;
883  u8 *pos, *pos2;
884  u8 *cname_pos = 0;
885  int len, i;
886  u8 *cname = 0;
887  u8 *request = 0;
888  u8 *name_copy;
889  u32 qp_offset;
890  u16 flags;
891  u16 rcode;
892  dns_cache_entry_t *ep, *next_ep;
893  f64 now;
894 
895  h = (dns_header_t *) reply;
896  flags = clib_net_to_host_u16 (h->flags);
897  rcode = flags & DNS_RCODE_MASK;
898 
899  /* See if the response is OK */
900  switch (rcode)
901  {
902  case DNS_RCODE_NO_ERROR:
903  break;
904 
909  case DNS_RCODE_REFUSED:
910  return -1;
911  }
912 
913  curpos = (u8 *) (h + 1);
914  pos = curpos;
915  len = *pos++;
916 
917  /* Skip the questions */
918  for (i = 0; i < clib_net_to_host_u16 (h->qdcount); i++)
919  {
920  while (len)
921  {
922  pos += len;
923  len = *pos++;
924  }
925  pos += sizeof (dns_query_t);
926  }
927  pos2 = pos;
928  /* expect a pointer chase here for a CNAME record */
929  if ((pos2[0] & 0xC0) == 0xC0)
930  pos += 2;
931  else
932  return 0;
933 
934  /* Walk the answer(s) to see what to do next */
935  for (i = 0; i < clib_net_to_host_u16 (h->anscount); i++)
936  {
937  rr = (dns_rr_t *) pos;
938  switch (clib_net_to_host_u16 (rr->type))
939  {
940  /* Real address record? Done.. */
941  case DNS_TYPE_A:
942  case DNS_TYPE_AAAA:
943  return 0;
944  /*
945  * Maybe chase a CNAME pointer?
946  * It's not unheard-of for name-servers to return
947  * both CNAME and A/AAAA records...
948  */
949  case DNS_TYPE_CNAME:
950  cname_pos = pos;
951  break;
952 
953  /* Some other junk, e.g. a nameserver... */
954  default:
955  break;
956  }
957  pos += sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength);
958  /* Skip name... */
959  if ((pos2[0] & 0xc0) == 0xc0)
960  pos += 2;
961  }
962 
963  /* Neither a CNAME nor a real address. Try another server */
964  if (cname_pos == 0)
965  {
966  flags &= ~DNS_RCODE_MASK;
968  h->flags = clib_host_to_net_u16 (flags);
969  return -1;
970  }
971 
972  /* This is a CNAME record, chase the name chain. */
973  pos = cname_pos;
974 
975  /* The last request is no longer pending.. */
976  for (i = 0; i < vec_len (dm->unresolved_entries); i++)
977  if (ep_index == dm->unresolved_entries[i])
978  {
979  vec_delete (dm->unresolved_entries, 1, i);
980  goto found_last_request;
981  }
982  clib_warning ("pool elt %d supposedly pending, but not found...", ep_index);
983  return -1;
984 
985 found_last_request:
986 
987  now = vlib_time_now (vm);
988  cname = vnet_dns_labels_to_name (rr->rdata, reply, &pos2);
989  /* Save the cname */
990  vec_add1 (cname, 0);
991  _vec_len (cname) -= 1;
992  ep = pool_elt_at_index (dm->entries, ep_index);
993  ep->cname = cname;
995  /* Save the response */
996  if (ep->dns_response)
997  vec_free (ep->dns_response);
998  ep->dns_response = reply;
999  /* Set up expiration time */
1000  ep->expiration_time = now + clib_net_to_host_u32 (rr->ttl);
1001 
1002  pool_get (dm->entries, next_ep);
1003 
1004  /* Need to recompute ep post pool-get */
1005  ep = pool_elt_at_index (dm->entries, ep_index);
1006 
1007  clib_memset (next_ep, 0, sizeof (*next_ep));
1008  next_ep->name = vec_dup (cname);
1009  vec_add1 (next_ep->name, 0);
1010  _vec_len (next_ep->name) -= 1;
1011 
1012  hash_set_mem (dm->cache_entry_by_name, next_ep->name,
1013  next_ep - dm->entries);
1014 
1015  /* Use the same server */
1016  next_ep->server_rotor = ep->server_rotor;
1017  next_ep->server_af = ep->server_af;
1018 
1019  /* Move notification data to the next name in the chain */
1020 #define _(a) next_ep->a = ep->a; ep->a = 0;
1022 #undef _
1023 
1024  request = name_to_labels (cname);
1025  name_copy = vec_dup (request);
1026 
1027  qp_offset = vec_len (request);
1028 
1029  /* Add space for the query header */
1030  vec_validate (request, 2 * qp_offset + 2 * sizeof (dns_query_t) - 1);
1031 
1032  qp = (dns_query_t *) (request + qp_offset);
1033 
1034  qp->type = clib_host_to_net_u16 (DNS_TYPE_A);
1035  qp->class = clib_host_to_net_u16 (DNS_CLASS_IN);
1036  clib_memcpy (qp, name_copy, vec_len (name_copy));
1037  qp = (dns_query_t *) (((u8 *) qp) + vec_len (name_copy));
1038  vec_free (name_copy);
1039 
1040  qp->type = clib_host_to_net_u16 (DNS_TYPE_AAAA);
1041  qp->class = clib_host_to_net_u16 (DNS_CLASS_IN);
1042 
1043  /* Punch in space for the dns_header_t */
1044  vec_insert (request, sizeof (dns_header_t), 0);
1045 
1046  h = (dns_header_t *) request;
1047 
1048  /* Transaction ID = pool index */
1049  h->id = clib_host_to_net_u16 (next_ep - dm->entries);
1050 
1051  /* Ask for a recursive lookup */
1052  h->flags = clib_host_to_net_u16 (DNS_RD | DNS_OPCODE_QUERY);
1053  h->qdcount = clib_host_to_net_u16 (2);
1054  h->nscount = 0;
1055  h->arcount = 0;
1056 
1057  next_ep->dns_request = request;
1058  next_ep->retry_timer = now + 2.0;
1059  next_ep->retry_count = 0;
1060 
1061  /*
1062  * Enable this to watch recursive resolution happen...
1063  * fformat (stdout, "%U", format_dns_reply, request, 2);
1064  */
1065 
1066  vec_add1 (dm->unresolved_entries, next_ep - dm->entries);
1067  vnet_send_dns_request (vm, dm, next_ep);
1068  return (1);
1069 }
1070 
1071 int
1073  u32 *min_ttlp)
1074 {
1075  dns_header_t *h;
1076  dns_query_t *qp;
1077  dns_rr_t *rr;
1078  int i, limit;
1079  u8 len;
1080  u8 *curpos, *pos, *pos2;
1081  u16 flags;
1082  u16 rcode;
1083  u32 ttl;
1084  int pointer_chase, addr_set = 0;
1085 
1086  h = (dns_header_t *) response;
1087  flags = clib_net_to_host_u16 (h->flags);
1088  rcode = flags & DNS_RCODE_MASK;
1089 
1090  /* See if the response is OK, etc. */
1091  switch (rcode)
1092  {
1093  default:
1094  case DNS_RCODE_NO_ERROR:
1095  break;
1096 
1097  case DNS_RCODE_NAME_ERROR:
1099  return VNET_API_ERROR_NAME_SERVER_NO_SUCH_NAME;
1100 
1103  case DNS_RCODE_REFUSED:
1104  return VNET_API_ERROR_NAME_SERVER_NEXT_SERVER;
1105  }
1106 
1107  /* No answers? Loser... */
1108  if (clib_net_to_host_u16 (h->anscount) < 1)
1109  return VNET_API_ERROR_NAME_SERVER_NO_ADDRESSES;
1110 
1111  curpos = (u8 *) (h + 1);
1112 
1113  /* Skip the name we asked about */
1114  pos = curpos;
1115  len = *pos++;
1116  /* Should never happen, but stil... */
1117  if ((len & 0xC0) == 0xC0)
1118  curpos += 2;
1119  else
1120  {
1121  /* skip the name / label-set */
1122  while (len)
1123  {
1124  pos += len;
1125  len = *pos++;
1126  }
1127  curpos = pos;
1128  }
1129  /* Skip queries */
1130  limit = clib_net_to_host_u16 (h->qdcount);
1131  qp = (dns_query_t *) curpos;
1132  qp += limit;
1133  curpos = (u8 *) qp;
1134 
1135  /* Parse answers */
1136  limit = clib_net_to_host_u16 (h->anscount);
1137 
1138  for (i = 0; i < limit; i++)
1139  {
1140  pos = pos2 = curpos;
1141  pointer_chase = 0;
1142 
1143  /* Expect pointer chases in the answer section... */
1144  if ((pos2[0] & 0xC0) == 0xC0)
1145  {
1146  pos = pos2 + 2;
1147  pos2 = response + ((pos2[0] & 0x3f) << 8) + pos2[1];
1148  pointer_chase = 1;
1149  }
1150 
1151  len = *pos2++;
1152 
1153  while (len)
1154  {
1155  pos2 += len;
1156  if ((pos2[0] & 0xc0) == 0xc0)
1157  {
1158  /*
1159  * If we've already done one pointer chase,
1160  * do not move the pos pointer.
1161  */
1162  if (pointer_chase == 0)
1163  pos = pos2 + 2;
1164  pos2 = response + ((pos2[0] & 0x3f) << 8) + pos2[1];
1165  len = *pos2++;
1166  pointer_chase = 1;
1167  }
1168  else
1169  len = *pos2++;
1170  }
1171 
1172  if (pointer_chase == 0)
1173  pos = pos2;
1174 
1175  rr = (dns_rr_t *) pos;
1176 
1177  switch (clib_net_to_host_u16 (rr->type))
1178  {
1179  case DNS_TYPE_A:
1180  /* Collect an ip4 address. Do not pass go. Do not collect $200 */
1181  ip_address_set (&rn->address, rr->rdata, AF_IP4);
1182  ttl = clib_net_to_host_u32 (rr->ttl);
1183  addr_set += 1;
1184  if (min_ttlp && *min_ttlp > ttl)
1185  *min_ttlp = ttl;
1186  break;
1187  case DNS_TYPE_AAAA:
1188  /* Collect an ip6 address. Do not pass go. Do not collect $200 */
1189  ip_address_set (&rn->address, rr->rdata, AF_IP6);
1190  ttl = clib_net_to_host_u32 (rr->ttl);
1191  if (min_ttlp && *min_ttlp > ttl)
1192  *min_ttlp = ttl;
1193  addr_set += 1;
1194  break;
1195 
1196  default:
1197  break;
1198  }
1199  /* Might as well stop ASAP */
1200  if (addr_set > 1)
1201  break;
1202  pos += sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength);
1203  curpos = pos;
1204  }
1205 
1206  if (addr_set == 0)
1207  return VNET_API_ERROR_NAME_SERVER_NO_ADDRESSES;
1208  return 0;
1209 }
1210 
1211 int
1214  u32 * min_ttlp)
1215 {
1216  dns_header_t *h;
1217  dns_query_t *qp;
1218  dns_rr_t *rr;
1219  int i, limit;
1220  u8 len;
1221  u8 *curpos, *pos, *pos2;
1222  u16 flags;
1223  u16 rcode;
1224  u8 *name;
1225  u32 ttl;
1226  u8 *junk __attribute__ ((unused));
1227  int name_set = 0;
1228  int pointer_chase;
1229 
1230  h = (dns_header_t *) response;
1231  flags = clib_net_to_host_u16 (h->flags);
1232  rcode = flags & DNS_RCODE_MASK;
1233 
1234  /* See if the response is OK, etc. */
1235  switch (rcode)
1236  {
1237  default:
1238  case DNS_RCODE_NO_ERROR:
1239  break;
1240 
1241  case DNS_RCODE_NAME_ERROR:
1243  return VNET_API_ERROR_NAME_SERVER_NO_SUCH_NAME;
1244 
1247  case DNS_RCODE_REFUSED:
1248  return VNET_API_ERROR_NAME_SERVER_NEXT_SERVER;
1249  }
1250 
1251  /* No answers? Loser... */
1252  if (clib_net_to_host_u16 (h->anscount) < 1)
1253  return VNET_API_ERROR_NAME_SERVER_NO_ADDRESSES;
1254 
1255  curpos = (u8 *) (h + 1);
1256 
1257  /* Skip the name we asked about */
1258  pos = curpos;
1259  len = *pos++;
1260  /* Should never happen, but stil... */
1261  if ((len & 0xC0) == 0xC0)
1262  curpos += 2;
1263  else
1264  {
1265  /* skip the name / label-set */
1266  while (len)
1267  {
1268  pos += len;
1269  len = *pos++;
1270  }
1271  curpos = pos;
1272  }
1273  /* Skip queries */
1274  limit = clib_net_to_host_u16 (h->qdcount);
1275  qp = (dns_query_t *) curpos;
1276  qp += limit;
1277  curpos = (u8 *) qp;
1278 
1279  /* Parse answers */
1280  limit = clib_net_to_host_u16 (h->anscount);
1281 
1282  for (i = 0; i < limit; i++)
1283  {
1284  pos = pos2 = curpos;
1285  pointer_chase = 0;
1286 
1287  /* Expect pointer chases in the answer section... */
1288  if ((pos2[0] & 0xC0) == 0xC0)
1289  {
1290  pos = pos2 + 2;
1291  pos2 = response + ((pos2[0] & 0x3f) << 8) + pos2[1];
1292  pointer_chase = 1;
1293  }
1294 
1295  len = *pos2++;
1296 
1297  while (len)
1298  {
1299  pos2 += len;
1300  if ((pos2[0] & 0xc0) == 0xc0)
1301  {
1302  /*
1303  * If we've already done one pointer chase,
1304  * do not move the pos pointer.
1305  */
1306  if (pointer_chase == 0)
1307  pos = pos2 + 2;
1308  pos2 = response + ((pos2[0] & 0x3f) << 8) + pos2[1];
1309  len = *pos2++;
1310  pointer_chase = 1;
1311  }
1312  else
1313  len = *pos2++;
1314  }
1315 
1316  if (pointer_chase == 0)
1317  pos = pos2;
1318 
1319  rr = (dns_rr_t *) pos;
1320 
1321  switch (clib_net_to_host_u16 (rr->type))
1322  {
1323  case DNS_TYPE_PTR:
1324  name = vnet_dns_labels_to_name (rr->rdata, response, &junk);
1325  memcpy (rmp->name, name, vec_len (name));
1326  ttl = clib_net_to_host_u32 (rr->ttl);
1327  if (min_ttlp)
1328  *min_ttlp = ttl;
1329  rmp->name[vec_len (name)] = 0;
1330  name_set = 1;
1331  break;
1332  default:
1333  break;
1334  }
1335  /* Might as well stop ASAP */
1336  if (name_set == 1)
1337  break;
1338  pos += sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength);
1339  curpos = pos;
1340  }
1341 
1342  if (name_set == 0)
1343  return VNET_API_ERROR_NAME_SERVER_NO_SUCH_NAME;
1344  return 0;
1345 }
1346 
1347 __clib_export int
1349  dns_resolve_name_t *rn)
1350 {
1351  dns_main_t *dm = &dns_main;
1353 
1354  int rv = vnet_dns_resolve_name (vm, dm, name, t0, ep);
1355 
1356  /* Error, e.g. not enabled? Tell the user */
1357  if (rv < 0)
1358  return rv;
1359 
1360  /* Resolution pending? Don't reply... */
1361  if (ep[0] == 0)
1362  return 0;
1363 
1364  return vnet_dns_response_to_reply (ep[0]->dns_response, rn, 0 /* ttl-ptr */);
1365 }
1366 
1367 static void
1369 {
1370  dns_main_t *dm = &dns_main;
1372  dns_cache_entry_t *ep = 0;
1373  dns_pending_request_t _t0, *t0 = &_t0;
1374  int rv;
1375  dns_resolve_name_t rn;
1376 
1377  /* Sanitize the name slightly */
1378  mp->name[ARRAY_LEN (mp->name) - 1] = 0;
1379 
1381  t0->client_index = mp->client_index;
1382  t0->client_context = mp->context;
1383 
1384  rv = dns_resolve_name (mp->name, &ep, t0, &rn);
1385 
1386  /* Error, e.g. not enabled? Tell the user */
1387  if (rv < 0)
1388  {
1389  REPLY_MACRO (VL_API_DNS_RESOLVE_NAME_REPLY);
1390  return;
1391  }
1392 
1393  /* Resolution pending? Don't reply... */
1394  if (ep == 0)
1395  return;
1396 
1397  /* *INDENT-OFF* */
1398  REPLY_MACRO2 (VL_API_DNS_RESOLVE_NAME_REPLY, ({
1400  if (ip_addr_version (&rn.address) == AF_IP4)
1401  rmp->ip4_set = 1;
1402  else
1403  rmp->ip6_set = 1;
1404  }));
1405  /* *INDENT-ON* */
1406 }
1407 
1408 static void
1410 {
1412  dns_main_t *dm = &dns_main;
1414  dns_cache_entry_t *ep;
1415  int rv;
1416  int i, len;
1417  u8 *lookup_name = 0;
1418  u8 digit, nybble;
1419  dns_pending_request_t _t0, *t0 = &_t0;
1420 
1421  if (mp->is_ip6)
1422  {
1423  for (i = 15; i >= 0; i--)
1424  {
1425  digit = mp->address[i];
1426  nybble = (digit & 0x0F);
1427  if (nybble > 9)
1428  vec_add1 (lookup_name, (nybble - 10) + 'a');
1429  else
1430  vec_add1 (lookup_name, nybble + '0');
1431  vec_add1 (lookup_name, '.');
1432  nybble = (digit & 0xF0) >> 4;
1433  if (nybble > 9)
1434  vec_add1 (lookup_name, (nybble - 10) + 'a');
1435  else
1436  vec_add1 (lookup_name, nybble + '0');
1437  vec_add1 (lookup_name, '.');
1438  }
1439  len = vec_len (lookup_name);
1440  vec_validate (lookup_name, len + 8);
1441  memcpy (lookup_name + len, "ip6.arpa", 8);
1442  }
1443  else
1444  {
1445  for (i = 3; i >= 0; i--)
1446  {
1447  digit = mp->address[i];
1448  lookup_name = format (lookup_name, "%d.", digit);
1449  }
1450  lookup_name = format (lookup_name, "in-addr.arpa");
1451  }
1452 
1453  vec_add1 (lookup_name, 0);
1454 
1456  t0->client_index = mp->client_index;
1457  t0->client_context = mp->context;
1458 
1459  rv = vnet_dns_resolve_name (vm, dm, lookup_name, t0, &ep);
1460 
1461  vec_free (lookup_name);
1462 
1463  /* Error, e.g. not enabled? Tell the user */
1464  if (rv < 0)
1465  {
1466  REPLY_MACRO (VL_API_DNS_RESOLVE_IP_REPLY);
1467  return;
1468  }
1469 
1470  /* Resolution pending? Don't reply... */
1471  if (ep == 0)
1472  return;
1473 
1474  /* *INDENT-OFF* */
1475  REPLY_MACRO2(VL_API_DNS_RESOLVE_IP_REPLY,
1476  ({
1477  rv = vnet_dns_response_to_name (ep->dns_response, rmp, 0 /* ttl-ptr */);
1478  rmp->retval = clib_host_to_net_u32 (rv);
1479  }));
1480  /* *INDENT-ON* */
1481 }
1482 
1483 static clib_error_t *
1485 {
1486  dns_main_t *dm = &dns_main;
1487 
1488  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1489  {
1490  if (unformat (input, "max-cache-size %u", &dm->name_cache_size))
1491  ;
1492  else if (unformat (input, "max-ttl %u", &dm->max_ttl_in_seconds))
1493  ;
1494  else
1495  return clib_error_return (0, "unknown input `%U'",
1496  format_unformat_error, input);
1497  }
1498  return 0;
1499 }
1500 
1502 
1503 uword
1504 unformat_dns_reply (unformat_input_t * input, va_list * args)
1505 {
1506  u8 **result = va_arg (*args, u8 **);
1507  u8 **namep = va_arg (*args, u8 **);
1508  ip4_address_t a4;
1509  ip6_address_t a6;
1510  int a4_set = 0;
1511  int a6_set = 0;
1512  u8 *name;
1513  int name_set = 0;
1514  u8 *ce;
1515  u32 qp_offset;
1516  dns_header_t *h;
1517  dns_query_t *qp;
1518  dns_rr_t *rr;
1519  u8 *rru8;
1520 
1521  if (unformat (input, "%v", &name))
1522  name_set = 1;
1523 
1524  if (unformat (input, "%U", unformat_ip4_address, &a4))
1525  {
1526  a4_set = 1;
1527  if (unformat (input, "%U", unformat_ip6_address, &a6))
1528  a6_set = 1;
1529  }
1530 
1531  if (unformat (input, "%U", unformat_ip6_address, &a6))
1532  {
1533  a6_set = 1;
1534  if (unformat (input, "%U", unformat_ip4_address, &a6))
1535  a4_set = 1;
1536  }
1537 
1538  /* Must have a name */
1539  if (!name_set)
1540  return 0;
1541 
1542  /* Must have at least one address */
1543  if (!(a4_set + a6_set))
1544  return 0;
1545 
1546  /* Build a fake DNS cache entry string, one hemorrhoid at a time */
1547  ce = name_to_labels (name);
1548  qp_offset = vec_len (ce);
1549 
1550  /* Add space for the query header */
1551  vec_validate (ce, qp_offset + sizeof (dns_query_t) - 1);
1552  qp = (dns_query_t *) (ce + qp_offset);
1553 
1554  qp->type = clib_host_to_net_u16 (DNS_TYPE_ALL);
1555  qp->class = clib_host_to_net_u16 (DNS_CLASS_IN);
1556 
1557  /* Punch in space for the dns_header_t */
1558  vec_insert (ce, sizeof (dns_header_t), 0);
1559 
1560  h = (dns_header_t *) ce;
1561 
1562  /* Fake Transaction ID */
1563  h->id = 0xFFFF;
1564 
1565  h->flags = clib_host_to_net_u16 (DNS_RD | DNS_RA);
1566  h->qdcount = clib_host_to_net_u16 (1);
1567  h->anscount = clib_host_to_net_u16 (a4_set + a6_set);
1568  h->nscount = 0;
1569  h->arcount = 0;
1570 
1571  /* Now append one or two A/AAAA RR's... */
1572  if (a4_set)
1573  {
1574  /* Pointer to the name (DGMS) */
1575  vec_add1 (ce, 0xC0);
1576  vec_add1 (ce, 0x0C);
1577  vec_add2 (ce, rru8, sizeof (*rr) + 4);
1578  rr = (void *) rru8;
1579  rr->type = clib_host_to_net_u16 (DNS_TYPE_A);
1580  rr->class = clib_host_to_net_u16 (DNS_CLASS_IN);
1581  rr->ttl = clib_host_to_net_u32 (86400);
1582  rr->rdlength = clib_host_to_net_u16 (4);
1583  memcpy (rr->rdata, &a4, sizeof (a4));
1584  }
1585  if (a6_set)
1586  {
1587  /* Pointer to the name (DGMS) */
1588  vec_add1 (ce, 0xC0);
1589  vec_add1 (ce, 0x0C);
1590  vec_add2 (ce, rru8, sizeof (*rr) + 16);
1591  rr = (void *) rru8;
1592  rr->type = clib_host_to_net_u16 (DNS_TYPE_AAAA);
1593  rr->class = clib_host_to_net_u16 (DNS_CLASS_IN);
1594  rr->ttl = clib_host_to_net_u32 (86400);
1595  rr->rdlength = clib_host_to_net_u16 (16);
1596  memcpy (rr->rdata, &a6, sizeof (a6));
1597  }
1598  *result = ce;
1599  if (namep)
1600  *namep = name;
1601  else
1602  vec_free (name);
1603 
1604  return 1;
1605 }
1606 
1607 u8 *
1608 format_dns_query (u8 * s, va_list * args)
1609 {
1610  u8 **curpos = va_arg (*args, u8 **);
1611  int verbose = va_arg (*args, int);
1612  u8 *pos;
1613  dns_query_t *qp;
1614  int len, i;
1615  if (verbose > 1)
1616  s = format (s, " Name: ");
1617 
1618  /* Unwind execrated counted-label sheit */
1619  pos = *curpos;
1620  len = *pos++;
1621 
1622  while (len)
1623  {
1624  for (i = 0; i < len; i++)
1625  vec_add1 (s, *pos++);
1626 
1627  len = *pos++;
1628  if (len)
1629  vec_add1 (s, '.');
1630  else
1631  {
1632  vec_add1 (s, ':');
1633  vec_add1 (s, ' ');
1634  }
1635  }
1636 
1637  qp = (dns_query_t *) pos;
1638  if (verbose > 1)
1639  {
1640  switch (clib_net_to_host_u16 (qp->type))
1641  {
1642  case DNS_TYPE_A:
1643  s = format (s, "type A\n");
1644  break;
1645  case DNS_TYPE_AAAA:
1646  s = format (s, "type AAAA\n");
1647  break;
1648  case DNS_TYPE_ALL:
1649  s = format (s, "type ALL\n");
1650  break;
1651 
1652  default:
1653  s = format (s, "type %d\n", clib_net_to_host_u16 (qp->type));
1654  break;
1655  }
1656  }
1657 
1658  pos += sizeof (*qp);
1659 
1660  *curpos = pos;
1661  return s;
1662 }
1663 
1664 /**
1665  * format dns reply data
1666  * verbose > 1, dump everything
1667  * verbose == 1, dump all A and AAAA records
1668  * verbose == 0, dump one A record, and one AAAA record
1669  */
1670 
1671 u8 *
1672 format_dns_reply_data (u8 * s, va_list * args)
1673 {
1674  u8 *reply = va_arg (*args, u8 *);
1675  u8 **curpos = va_arg (*args, u8 **);
1676  int verbose = va_arg (*args, int);
1677  int *print_ip4 = va_arg (*args, int *);
1678  int *print_ip6 = va_arg (*args, int *);
1679  int len;
1680  u8 *pos, *pos2;
1681  dns_rr_t *rr;
1682  int i;
1683  int pointer_chase = 0;
1684  u16 *tp;
1685  u16 rrtype_host_byte_order;
1686 
1687  pos = pos2 = *curpos;
1688 
1689  if (verbose > 1)
1690  s = format (s, " ");
1691 
1692  /* chase pointer? almost always yes here... */
1693  if ((pos2[0] & 0xc0) == 0xc0)
1694  {
1695  pos = pos2 + 2;
1696  pos2 = reply + ((pos2[0] & 0x3f) << 8) + pos2[1];
1697  pointer_chase = 1;
1698  }
1699 
1700  len = *pos2++;
1701 
1702  while (len)
1703  {
1704  for (i = 0; i < len; i++)
1705  {
1706  if (verbose > 1)
1707  vec_add1 (s, *pos2);
1708  pos2++;
1709  }
1710  if ((pos2[0] & 0xc0) == 0xc0)
1711  {
1712  /*
1713  * If we've already done one pointer chase,
1714  * do not move the pos pointer.
1715  */
1716  if (pointer_chase == 0)
1717  pos = pos2 + 2;
1718  pos2 = reply + ((pos2[0] & 0x3f) << 8) + pos2[1];
1719  len = *pos2++;
1720  pointer_chase = 1;
1721  }
1722  else
1723  len = *pos2++;
1724  if (len)
1725  {
1726  if (verbose > 1)
1727  vec_add1 (s, '.');
1728  }
1729  else
1730  {
1731  if (verbose > 1)
1732  vec_add1 (s, ' ');
1733  }
1734  }
1735 
1736  if (pointer_chase == 0)
1737  pos = pos2;
1738 
1739  rr = (dns_rr_t *) pos;
1740  rrtype_host_byte_order = clib_net_to_host_u16 (rr->type);
1741 
1742  switch (rrtype_host_byte_order)
1743  {
1744  case DNS_TYPE_A:
1745  if (verbose > 1)
1746  {
1747  s = format (s, "A: ttl %d %U\n", clib_net_to_host_u32 (rr->ttl),
1748  format_ip4_address, rr->rdata);
1749  }
1750  else
1751  {
1752  if (*print_ip4)
1753  s = format (s, "%U [%u] ", format_ip4_address, rr->rdata,
1754  clib_net_to_host_u32 (rr->ttl));
1755  if (verbose == 0)
1756  *print_ip4 = 0;
1757 
1758  }
1759  pos += sizeof (*rr) + 4;
1760  break;
1761 
1762  case DNS_TYPE_AAAA:
1763  if (verbose > 1)
1764  {
1765  s = format (s, "AAAA: ttl %d %U\n", clib_net_to_host_u32 (rr->ttl),
1766  format_ip6_address, rr->rdata);
1767  }
1768  else
1769  {
1770  if (*print_ip6)
1771  s = format (s, "%U [%u] ", format_ip6_address, rr->rdata,
1772  clib_net_to_host_u32 (rr->ttl));
1773  if (verbose == 0)
1774  *print_ip6 = 0;
1775  }
1776  pos += sizeof (*rr) + 16;
1777  break;
1778 
1779  case DNS_TYPE_TEXT:
1780  if (verbose > 1)
1781  {
1782  s = format (s, "TEXT: ");
1783  for (i = 0; i < clib_net_to_host_u16 (rr->rdlength); i++)
1784  vec_add1 (s, rr->rdata[i]);
1785  vec_add1 (s, '\n');
1786  }
1787  pos += sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength);
1788  break;
1789 
1790  case DNS_TYPE_HINFO:
1791  {
1792  /* Two counted strings. DGMS */
1793  u8 *len;
1794  u8 *curpos;
1795  int i;
1796  if (verbose > 1)
1797  {
1798  s = format (s, "HINFO: ");
1799  len = rr->rdata;
1800  curpos = len + 1;
1801  for (i = 0; i < *len; i++)
1802  vec_add1 (s, *curpos++);
1803 
1804  vec_add1 (s, ' ');
1805  len = curpos++;
1806  for (i = 0; i < *len; i++)
1807  vec_add1 (s, *curpos++);
1808 
1809  vec_add1 (s, '\n');
1810  }
1811  }
1812  pos += sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength);
1813  break;
1814 
1815  case DNS_TYPE_NAMESERVER:
1816  if (verbose > 1)
1817  {
1818  s = format (s, "Nameserver: ");
1819  pos2 = rr->rdata;
1820 
1821  /* chase pointer? */
1822  if ((pos2[0] & 0xc0) == 0xc0)
1823  {
1824  pos = pos2 + 2;
1825  pos2 = reply + ((pos2[0] & 0x3f) << 8) + pos2[1];
1826  }
1827 
1828  len = *pos2++;
1829 
1830  while (len)
1831  {
1832  for (i = 0; i < len; i++)
1833  vec_add1 (s, *pos2++);
1834 
1835  /* chase pointer, typically to offset 12... */
1836  if (pos2[0] == 0xC0)
1837  pos2 = reply + pos2[1];
1838 
1839  len = *pos2++;
1840  if (len)
1841  vec_add1 (s, '.');
1842  else
1843  vec_add1 (s, '\n');
1844  }
1845  }
1846  pos += sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength);
1847  break;
1848 
1849  case DNS_TYPE_MAIL_EXCHANGE:
1850  if (verbose > 1)
1851  {
1852  tp = (u16 *) rr->rdata;
1853 
1854  s = format (s, "Mail Exchange: Preference %d ", (u32)
1855  clib_net_to_host_u16 (*tp));
1856 
1857  pos2 = rr->rdata + 2;
1858 
1859  /* chase pointer? */
1860  if (pos2[0] == 0xc0)
1861  pos2 = reply + pos2[1];
1862 
1863  len = *pos2++;
1864 
1865  while (len)
1866  {
1867  for (i = 0; i < len; i++)
1868  vec_add1 (s, *pos2++);
1869 
1870  /* chase pointer */
1871  if (pos2[0] == 0xC0)
1872  pos2 = reply + pos2[1];
1873 
1874  len = *pos2++;
1875  if (len)
1876  vec_add1 (s, '.');
1877  else
1878  vec_add1 (s, '\n');
1879  }
1880  }
1881 
1882  pos += sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength);
1883  break;
1884 
1885  case DNS_TYPE_PTR:
1886  case DNS_TYPE_CNAME:
1887  if (verbose > 1)
1888  {
1889  tp = (u16 *) rr->rdata;
1890 
1891  if (rrtype_host_byte_order == DNS_TYPE_CNAME)
1892  s = format (s, "CNAME: ");
1893  else
1894  s = format (s, "PTR: ");
1895 
1896  pos2 = rr->rdata;
1897 
1898  /* chase pointer? */
1899  if (pos2[0] == 0xc0)
1900  pos2 = reply + pos2[1];
1901 
1902  len = *pos2++;
1903 
1904  while (len)
1905  {
1906  for (i = 0; i < len; i++)
1907  vec_add1 (s, *pos2++);
1908 
1909  /* chase pointer */
1910  if (pos2[0] == 0xC0)
1911  pos2 = reply + pos2[1];
1912 
1913  len = *pos2++;
1914  if (len)
1915  vec_add1 (s, '.');
1916  else
1917  vec_add1 (s, '\n');
1918  }
1919  }
1920  pos += sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength);
1921  break;
1922 
1923  default:
1924  if (verbose > 1)
1925  s = format (s, "type %d: len %d\n",
1926  (int) clib_net_to_host_u16 (rr->type),
1927  sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength));
1928  pos += sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength);
1929  break;
1930  }
1931 
1932  *curpos = pos;
1933 
1934  return s;
1935 }
1936 
1937 u8 *
1938 format_dns_reply (u8 * s, va_list * args)
1939 {
1940  u8 *reply_as_u8 = va_arg (*args, u8 *);
1941  int verbose = va_arg (*args, int);
1942  dns_header_t *h;
1943  u16 id, flags;
1944  u8 *curpos;
1945  int i;
1946  int print_ip4 = 1;
1947  int print_ip6 = 1;
1948 
1949  h = (dns_header_t *) reply_as_u8;
1950  id = clib_net_to_host_u16 (h->id);
1951  flags = clib_net_to_host_u16 (h->flags);
1952 
1953  if (verbose > 1)
1954  {
1955  s = format (s, "DNS %s: id %d\n", (flags & DNS_QR) ? "reply" : "query",
1956  id);
1957  s = format (s, " %s %s %s %s\n",
1958  (flags & DNS_RA) ? "recur" : "no-recur",
1959  (flags & DNS_RD) ? "recur-des" : "no-recur-des",
1960  (flags & DNS_TC) ? "trunc" : "no-trunc",
1961  (flags & DNS_AA) ? "auth" : "non-auth");
1962  s = format (s, " %d queries, %d answers, %d name-servers,"
1963  " %d add'l recs\n",
1964  clib_net_to_host_u16 (h->qdcount),
1965  clib_net_to_host_u16 (h->anscount),
1966  clib_net_to_host_u16 (h->nscount),
1967  clib_net_to_host_u16 (h->arcount));
1968  }
1969 
1970  curpos = (u8 *) (h + 1);
1971 
1972  if (h->qdcount)
1973  {
1974  if (verbose > 1)
1975  s = format (s, " Queries:\n");
1976  for (i = 0; i < clib_net_to_host_u16 (h->qdcount); i++)
1977  {
1978  /* The query is variable-length, so curpos is a value-result parm */
1979  s = format (s, "%U", format_dns_query, &curpos, verbose);
1980  }
1981  }
1982  if (h->anscount)
1983  {
1984  if (verbose > 1)
1985  s = format (s, " Replies:\n");
1986 
1987  for (i = 0; i < clib_net_to_host_u16 (h->anscount); i++)
1988  {
1989  /* curpos is a value-result parm */
1990  s = format (s, "%U", format_dns_reply_data, reply_as_u8, &curpos,
1991  verbose, &print_ip4, &print_ip6);
1992  }
1993  }
1994  return s;
1995 }
1996 
1997 u8 *
1998 format_dns_cache (u8 * s, va_list * args)
1999 {
2000  dns_main_t *dm = va_arg (*args, dns_main_t *);
2001  f64 now = va_arg (*args, f64);
2002  int verbose = va_arg (*args, int);
2003  u8 *name = va_arg (*args, u8 *);
2004  dns_cache_entry_t *ep;
2005  char *ss;
2006  uword *p;
2007 
2008  if (dm->is_enabled == 0)
2009  {
2010  s = format (s, "The DNS cache is disabled...");
2011  return s;
2012  }
2013 
2014  if (pool_elts (dm->entries) == 0)
2015  {
2016  s = format (s, "The DNS cache is empty...");
2017  return s;
2018  }
2019 
2020  dns_cache_lock (dm, 6);
2021 
2022  if (name)
2023  {
2025  if (!p)
2026  {
2027  s = format (s, "%s is not in the cache...", name);
2028  dns_cache_unlock (dm);
2029  return (s);
2030  }
2031 
2032  ep = pool_elt_at_index (dm->entries, p[0]);
2033  /* Magic to spit out a C-initializer to research hemorrhoids... */
2034  if (verbose == 3)
2035  {
2036  int i, j;
2037  s = format (s, "static u8 dns_reply_data_initializer[] =\n");
2038  s = format (s, "{\n");
2039  j = 0;
2040  for (i = 0; i < vec_len (ep->dns_response); i++)
2041  {
2042  if (j++ == 8)
2043  {
2044  j = 0;
2045  vec_add1 (s, '\n');
2046  }
2047  s = format (s, "0x%02x, ", ep->dns_response[i]);
2048  }
2049  s = format (s, "};\n");
2050  }
2051  else
2052  {
2054  {
2055  ASSERT (ep->dns_response);
2057  ss = "[S] ";
2058  else
2059  ss = " ";
2060 
2061  if (verbose < 2 && ep->flags & DNS_CACHE_ENTRY_FLAG_CNAME)
2062  s = format (s, "%s%s -> %s", ss, ep->name, ep->cname);
2063  else
2064  s = format (s, "%s%s -> %U", ss, ep->name,
2065  format_dns_reply, ep->dns_response, verbose);
2066  if (!(ep->flags & DNS_CACHE_ENTRY_FLAG_STATIC))
2067  {
2068  f64 time_left = ep->expiration_time - now;
2069  if (time_left > 0.0)
2070  s = format (s, " TTL left %.1f", time_left);
2071  else
2072  s = format (s, " EXPIRED");
2073  }
2074  }
2075  else
2076  {
2077  ASSERT (ep->dns_request);
2078  s = format (s, "[P] %U", format_dns_reply, ep->dns_request,
2079  verbose);
2080  }
2081  vec_add1 (s, '\n');
2082  }
2083  return s;
2084  }
2085 
2086  s = format (s, "DNS cache contains %d entries\n", pool_elts (dm->entries));
2087 
2088  if (verbose > 0)
2089  {
2090  /* *INDENT-OFF* */
2091  pool_foreach (ep, dm->entries)
2092  {
2094  {
2095  ASSERT (ep->dns_response);
2097  ss = "[S] ";
2098  else
2099  ss = " ";
2100 
2101  if (verbose < 2 && ep->flags & DNS_CACHE_ENTRY_FLAG_CNAME)
2102  s = format (s, "%s%s -> %s", ss, ep->name, ep->cname);
2103  else
2104  s = format (s, "%s%s -> %U", ss, ep->name,
2106  ep->dns_response,
2107  verbose);
2108  if (!(ep->flags & DNS_CACHE_ENTRY_FLAG_STATIC))
2109  {
2110  f64 time_left = ep->expiration_time - now;
2111  if (time_left > 0.0)
2112  s = format (s, " TTL left %.1f", time_left);
2113  else
2114  s = format (s, " EXPIRED");
2115 
2116  if (verbose > 2)
2117  s = format (s, " %d client notifications pending\n",
2118  vec_len(ep->pending_requests));
2119  }
2120  }
2121  else
2122  {
2123  ASSERT (ep->dns_request);
2124  s = format (s, "[P] %U", format_dns_reply, ep->dns_request,
2125  verbose);
2126  }
2127  vec_add1 (s, '\n');
2128  }
2129  /* *INDENT-ON* */
2130  }
2131 
2132  dns_cache_unlock (dm);
2133 
2134  return s;
2135 }
2136 
2137 static clib_error_t *
2139  unformat_input_t * input, vlib_cli_command_t * cmd)
2140 {
2141  dns_main_t *dm = &dns_main;
2142  int verbose = 0;
2143  u8 *name = 0;
2144  f64 now = vlib_time_now (vm);
2145 
2146  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2147  {
2148  if (unformat (input, "verbose %d", &verbose))
2149  ;
2150  else if (unformat (input, "verbose"))
2151  verbose = 1;
2152  else if (unformat (input, "name %s", &name))
2153  ;
2154  else
2155  return clib_error_return (0, "unknown input `%U'",
2156  format_unformat_error, input);
2157  }
2158 
2159  vlib_cli_output (vm, "%U", format_dns_cache, dm, now, verbose, name);
2160 
2161  return 0;
2162 }
2163 
2164 /* *INDENT-OFF* */
2166 {
2167  .path = "show dns cache",
2168  .short_help = "show dns cache [verbose [nn]]",
2169  .function = show_dns_cache_command_fn,
2170 };
2171 /* *INDENT-ON* */
2172 
2173 static clib_error_t *
2175  unformat_input_t * input,
2176  vlib_cli_command_t * cmd)
2177 {
2178  dns_main_t *dm = &dns_main;
2179  int i;
2180 
2181  if ((vec_len (dm->ip4_name_servers) + vec_len (dm->ip6_name_servers)) == 0)
2182  return clib_error_return (0, "No name servers configured...");
2183 
2184  if (vec_len (dm->ip4_name_servers))
2185  {
2186  vlib_cli_output (vm, "ip4 name servers:");
2187  for (i = 0; i < vec_len (dm->ip4_name_servers); i++)
2189  dm->ip4_name_servers + i);
2190  }
2191  if (vec_len (dm->ip6_name_servers))
2192  {
2193  vlib_cli_output (vm, "ip6 name servers:");
2194  for (i = 0; i < vec_len (dm->ip6_name_servers); i++)
2196  dm->ip4_name_servers + i);
2197  }
2198  return 0;
2199 }
2200 
2201 /* *INDENT-OFF* */
2203 {
2204  .path = "show dns servers",
2205  .short_help = "show dns servers",
2206  .function = show_dns_servers_command_fn,
2207 };
2208 /* *INDENT-ON* */
2209 
2210 
2211 static clib_error_t *
2213  unformat_input_t * input,
2214  vlib_cli_command_t * cmd)
2215 {
2216  dns_main_t *dm = &dns_main;
2217  u8 *dns_reply_data;
2218  u8 *name;
2219  int is_add = -1;
2220  int is_clear = -1;
2221  int rv;
2223 
2224  if (unformat (input, "add"))
2225  is_add = 1;
2226  if (unformat (input, "del"))
2227  is_add = 0;
2228  if (unformat (input, "clear"))
2229  is_clear = 1;
2230 
2231  if (is_add == -1 && is_clear == -1)
2232  return clib_error_return (0, "add / del / clear required...");
2233 
2234  if (is_clear == 1)
2235  {
2236  rv = dns_cache_clear (dm);
2237  switch (rv)
2238  {
2239  case 0:
2240  return 0;
2241 
2242  case VNET_API_ERROR_NAME_RESOLUTION_NOT_ENABLED:
2243  error = clib_error_return (0, "Name resolution not enabled");
2244  return error;
2245  }
2246  }
2247 
2248  /* Delete (by name)? */
2249  if (is_add == 0)
2250  {
2251  if (unformat (input, "%v", &name))
2252  {
2253  rv = dns_delete_by_name (dm, name);
2254  switch (rv)
2255  {
2256  case VNET_API_ERROR_NO_SUCH_ENTRY:
2257  error = clib_error_return (0, "%v not in the cache...", name);
2258  vec_free (name);
2259  return error;
2260 
2261  case VNET_API_ERROR_NAME_RESOLUTION_NOT_ENABLED:
2262  error = clib_error_return (0, "Name resolution not enabled");
2263  vec_free (name);
2264  return error;
2265 
2266  case 0:
2267  vec_free (name);
2268  return 0;
2269 
2270  default:
2271  error = clib_error_return (0, "dns_delete_by_name returned %d",
2272  rv);
2273  vec_free (name);
2274  return error;
2275  }
2276  }
2277  return clib_error_return (0, "unknown input `%U'",
2278  format_unformat_error, input);
2279  }
2280 
2281  /* Note: dns_add_static_entry consumes the name vector if OK... */
2282  if (unformat (input, "%U", unformat_dns_reply, &dns_reply_data, &name))
2283  {
2284  rv = dns_add_static_entry (dm, name, dns_reply_data);
2285  switch (rv)
2286  {
2287  case VNET_API_ERROR_ENTRY_ALREADY_EXISTS:
2288  vec_free (name);
2289  vec_free (dns_reply_data);
2290  return clib_error_return (0, "%v already in the cache...", name);
2291  case 0:
2292  return 0;
2293 
2294  default:
2295  return clib_error_return (0, "dns_add_static_entry returned %d",
2296  rv);
2297  }
2298  }
2299 
2300  return 0;
2301 }
2302 
2303 /* *INDENT-OFF* */
2305 {
2306  .path = "dns cache",
2307  .short_help = "dns cache [add|del|clear] <name> [ip4][ip6]",
2308  .function = dns_cache_add_del_command_fn,
2309 };
2310 /* *INDENT-ON* */
2311 
2312 #define DNS_FORMAT_TEST 1
2313 
2314 #if DNS_FORMAT_TEST > 0
2315 #if 0
2316 /* yahoo.com */
2317 static u8 dns_reply_data_initializer[] =
2318  { 0x0, 0x0, 0x81, 0x80, 0x0, 0x1, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x5,
2319  0x79, 0x61, 0x68, 0x6f, 0x6f, 0x3, 0x63, 0x6f, 0x6d,
2320  0x0, /* null lbl */
2321  0x0, 0xff, /* type ALL */
2322  0x0, 0x1, /* class IN */
2323  0xc0, 0xc, /* pointer to yahoo.com name */
2324  0x0, 0x10, 0x0, 0x1, 0x0, 0x0, 0x6, 0x5c, 0x0, 0x24, 0x23,
2325  0x76, 0x3d, 0x73, 0x70, 0x66, 0x31, 0x20, 0x72, 0x65, 0x64, 0x69, 0x72,
2326  0x65, 0x63, 0x74, 0x3d, 0x5f, 0x73, 0x70, 0x66, 0x2e, 0x6d, 0x61, 0x69,
2327  0x6c, 0x2e, 0x79, 0x61, 0x68, 0x6f, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0xc0,
2328  0xc, 0x0, 0x2, 0x0, 0x1, 0x0, 0x1, 0x50, 0xd4, 0x0, 0x6, 0x3, 0x6e, 0x73,
2329  0x35, 0xc0, 0xc, 0xc0, 0xc, 0x0, 0x2, 0x0, 0x1, 0x0, 0x1, 0x50, 0xd4, 0x0,
2330  0x6, 0x3, 0x6e, 0x73, 0x34, 0xc0, 0xc, 0xc0, 0xc, 0x0, 0x2, 0x0, 0x1, 0x0,
2331  0x1, 0x50, 0xd4, 0x0, 0x6, 0x3, 0x6e, 0x73, 0x31, 0xc0, 0xc, 0xc0, 0xc,
2332  0x0, 0x2, 0x0, 0x1, 0x0, 0x1, 0x50, 0xd4, 0x0, 0x6, 0x3, 0x6e, 0x73, 0x32,
2333  0xc0, 0xc, 0xc0, 0xc, 0x0, 0x2, 0x0, 0x1, 0x0, 0x1, 0x50, 0xd4, 0x0, 0x6,
2334  0x3, 0x6e, 0x73, 0x33, 0xc0, 0xc, 0xc0, 0xc, 0x0, 0xf, 0x0, 0x1, 0x0, 0x0,
2335  0x6, 0x5c, 0x0, 0x19, 0x0, 0x1, 0x4, 0x6d, 0x74, 0x61, 0x36, 0x3, 0x61,
2336  0x6d, 0x30, 0x8, 0x79, 0x61, 0x68, 0x6f, 0x6f, 0x64, 0x6e, 0x73, 0x3,
2337  0x6e,
2338  0x65, 0x74, 0x0, 0xc0, 0xc, 0x0, 0xf, 0x0, 0x1, 0x0, 0x0, 0x6, 0x5c, 0x0,
2339  0x9, 0x0, 0x1, 0x4, 0x6d, 0x74, 0x61, 0x37, 0xc0, 0xb8, 0xc0, 0xc, 0x0,
2340  0xf, 0x0, 0x1, 0x0, 0x0, 0x6, 0x5c, 0x0, 0x9, 0x0, 0x1, 0x4, 0x6d, 0x74,
2341  0x61, 0x35, 0xc0, 0xb8, 0xc0, 0xc, 0x0, 0x1c, 0x0, 0x1, 0x0, 0x0, 0x6,
2342  0x5c, 0x0, 0x10, 0x20, 0x1, 0x49, 0x98, 0x0, 0x44, 0x2, 0x4, 0x0, 0x0,
2343  0x0,
2344  0x0, 0x0, 0x0, 0x0, 0xa7, 0xc0, 0xc, 0x0, 0x1c, 0x0, 0x1, 0x0, 0x0, 0x6,
2345  0x5c, 0x0, 0x10, 0x20, 0x1, 0x49, 0x98, 0x0, 0xc, 0xa, 0x6, 0x0, 0x0, 0x0,
2346  0x0, 0x0, 0x2, 0x40, 0x8, 0xc0, 0xc, 0x0, 0x1c, 0x0, 0x1, 0x0, 0x0, 0x6,
2347  0x5c, 0x0, 0x10, 0x20, 0x1, 0x49, 0x98, 0x0, 0x58, 0xc, 0x2, 0x0, 0x0,
2348  0x0,
2349  0x0, 0x0, 0x0, 0x0, 0xa9, 0xc0, 0xc, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x6,
2350  0x5c, 0x0, 0x4, 0x62, 0x8a, 0xfd, 0x6d, 0xc0, 0xc, 0x0, 0x1, 0x0, 0x1,
2351  0x0,
2352  0x0, 0x6, 0x5c, 0x0, 0x4, 0xce, 0xbe, 0x24, 0x2d, 0xc0, 0xc, 0x0, 0x1,
2353  0x0,
2354  0x1, 0x0, 0x0, 0x6, 0x5c, 0x0, 0x4, 0x62, 0x8b, 0xb4, 0x95, 0xc0, 0xc,
2355  0x0,
2356  0x6, 0x0, 0x1, 0x0, 0x0, 0x6, 0x5c, 0x0, 0x2d, 0xc0, 0x7b, 0xa, 0x68,
2357  0x6f,
2358  0x73, 0x74, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x9, 0x79, 0x61, 0x68,
2359  0x6f, 0x6f, 0x2d, 0x69, 0x6e, 0x63, 0xc0, 0x12, 0x78, 0x3a, 0x85, 0x44,
2360  0x0, 0x0, 0xe, 0x10, 0x0, 0x0, 0x1, 0x2c, 0x0, 0x1b, 0xaf, 0x80, 0x0, 0x0,
2361  0x2, 0x58
2362 };
2363 
2364 /* www.cisco.com, has no addresses in reply */
2365 static u8 dns_reply_data_initializer[] = {
2366  0x00, 0x01, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
2367  0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77, 0x05,
2368  0x63, 0x69, 0x73, 0x63, 0x6f, 0x03, 0x63, 0x6f, 0x6d,
2369 
2370  0x00, 0x00, 0xff, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x05,
2371  0x00, 0x01, 0x00, 0x00, 0x0b, 0xd3, 0x00, 0x1a, 0x03,
2372  0x77, 0x77, 0x77, 0x05, 0x63, 0x69, 0x73, 0x63, 0x6f,
2373  0x03, 0x63, 0x6f, 0x6d, 0x06, 0x61, 0x6b, 0x61, 0x64,
2374  0x6e, 0x73, 0x03, 0x6e, 0x65, 0x74, 0x00,
2375 };
2376 
2377 /* bind8 (linux widget, w/ nasty double pointer chasees */
2378 static u8 dns_reply_data_initializer[] = {
2379  /* 0 */
2380  0x00, 0x01, 0x81, 0x80, 0x00, 0x01, 0x00, 0x08,
2381  /* 8 */
2382  0x00, 0x06, 0x00, 0x06, 0x0a, 0x6f, 0x72, 0x69,
2383  /* 16 */
2384  0x67, 0x69, 0x6e, 0x2d, 0x77, 0x77, 0x77, 0x05,
2385  /* 24 */
2386  0x63, 0x69, 0x73, 0x63, 0x6f, 0x03, 0x63, 0x6f,
2387  /* 32 */
2388  0x6d, 0x00, 0x00, 0xff, 0x00, 0x01, 0x0a, 0x6f,
2389  /* 40 */
2390  0x72, 0x69, 0x67, 0x69, 0x6e, 0x2d, 0x77, 0x77,
2391  /* 48 */
2392  0x77, 0x05, 0x43, 0x49, 0x53, 0x43, 0x4f, 0xc0,
2393 
2394  /* 56 */
2395  0x1d, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x05,
2396 
2397  /* 64 */
2398  0x9a, 0x00, 0x18, 0x15, 0x72, 0x63, 0x64,
2399  0x6e, 0x39, 0x2d, 0x31, 0x34, 0x70, 0x2d, 0x64, 0x63,
2400  0x7a, 0x30, 0x35, 0x6e, 0x2d, 0x67, 0x73, 0x73, 0x31,
2401  0xc0, 0x17, 0xc0, 0x26, 0x00, 0x02, 0x00, 0x01, 0x00,
2402  0x00, 0x05, 0x9a, 0x00, 0x1a, 0x17, 0x61, 0x6c, 0x6c,
2403  0x6e, 0x30, 0x31, 0x2d, 0x61, 0x67, 0x30, 0x39, 0x2d,
2404  0x64, 0x63, 0x7a, 0x30, 0x33, 0x6e, 0x2d, 0x67, 0x73,
2405  0x73, 0x31, 0xc0, 0x17, 0xc0, 0x26, 0x00, 0x02, 0x00,
2406  0x01, 0x00, 0x00, 0x05, 0x9a, 0x00, 0x10, 0x0d, 0x72,
2407  0x74, 0x70, 0x35, 0x2d, 0x64, 0x6d, 0x7a, 0x2d, 0x67,
2408  0x73, 0x73, 0x31, 0xc0, 0x17, 0xc0, 0x26, 0x00, 0x02,
2409  0x00, 0x01, 0x00, 0x00, 0x05, 0x9a, 0x00, 0x18, 0x15,
2410  0x6d, 0x74, 0x76, 0x35, 0x2d, 0x61, 0x70, 0x31, 0x30,
2411  0x2d, 0x64, 0x63, 0x7a, 0x30, 0x36, 0x6e, 0x2d, 0x67,
2412  0x73, 0x73, 0x31, 0xc0, 0x17, 0xc0, 0x26, 0x00, 0x02,
2413  0x00, 0x01, 0x00, 0x00, 0x05, 0x9a, 0x00, 0x1b, 0x18,
2414  0x73, 0x6e, 0x67, 0x64, 0x63, 0x30, 0x31, 0x2d, 0x61,
2415  0x62, 0x30, 0x37, 0x2d, 0x64, 0x63, 0x7a, 0x30, 0x31,
2416  0x6e, 0x2d, 0x67, 0x73, 0x73, 0x31, 0xc0, 0x17, 0xc0,
2417  0x26, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x05, 0x9a,
2418  0x00, 0x1a, 0x17, 0x61, 0x65, 0x72, 0x30, 0x31, 0x2d,
2419  0x72, 0x34, 0x63, 0x32, 0x35, 0x2d, 0x64, 0x63, 0x7a,
2420  0x30, 0x31, 0x6e, 0x2d, 0x67, 0x73, 0x73, 0x31, 0xc0,
2421  0x17, 0xc0, 0x26, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
2422  0x00, 0x81, 0x00, 0x04, 0x48, 0xa3, 0x04, 0xa1, 0xc0,
2423  0x26, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x82,
2424  0x00, 0x10, 0x20, 0x01, 0x04, 0x20, 0x12, 0x01, 0x00,
2425  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
2426  0xc0, 0x0c, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x05,
2427  0x9a, 0x00, 0x02, 0xc0, 0xf4, 0xc0, 0x0c, 0x00, 0x02,
2428  0x00, 0x01, 0x00, 0x00, 0x05, 0x9a, 0x00, 0x02, 0xc0,
2429  0xcd, 0xc0, 0x0c, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00,
2430  0x05, 0x9a, 0x00, 0x02, 0xc0, 0x8d, 0xc0, 0x0c, 0x00,
2431  0x02, 0x00, 0x01, 0x00, 0x00, 0x05, 0x9a, 0x00, 0x02,
2432  0xc0, 0x43, 0xc0, 0x0c, 0x00, 0x02, 0x00, 0x01, 0x00,
2433  0x00, 0x05, 0x9a, 0x00, 0x02, 0xc0, 0xa9, 0xc0, 0x0c,
2434  0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x05, 0x9a, 0x00,
2435  0x02, 0xc0, 0x67, 0xc0, 0x8d, 0x00, 0x01, 0x00, 0x01,
2436  0x00, 0x00, 0x07, 0x08, 0x00, 0x04, 0x40, 0x66, 0xf6,
2437  0x05, 0xc0, 0xa9, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
2438  0x07, 0x08, 0x00, 0x04, 0xad, 0x24, 0xe0, 0x64, 0xc0,
2439  0x43, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x07, 0x08,
2440  0x00, 0x04, 0x48, 0xa3, 0x04, 0x1c, 0xc0, 0xf4, 0x00,
2441  0x01, 0x00, 0x01, 0x00, 0x00, 0x07, 0x08, 0x00, 0x04,
2442  0xad, 0x26, 0xd4, 0x6c, 0xc0, 0x67, 0x00, 0x01, 0x00,
2443  0x01, 0x00, 0x00, 0x07, 0x08, 0x00, 0x04, 0xad, 0x25,
2444  0x90, 0x64, 0xc0, 0xcd, 0x00, 0x01, 0x00, 0x01, 0x00,
2445  0x00, 0x07, 0x08, 0x00, 0x04, 0xad, 0x27, 0x70, 0x44,
2446 };
2447 
2448 /* google.com */
2449 static u8 dns_reply_data_initializer[] =
2450  { 0x0, 0x0, 0x81, 0x80, 0x0, 0x1, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x6,
2451  0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x3, 0x63, 0x6f, 0x6d, 0x0, 0x0, 0xff,
2452  0x0, 0x1, 0xc0, 0xc, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x1, 0x2b, 0x0, 0x4,
2453  0xac, 0xd9, 0x3, 0x2e, 0xc0, 0xc, 0x0, 0x1c, 0x0, 0x1, 0x0, 0x0, 0x1,
2454  0x2b,
2455  0x0, 0x10, 0x26, 0x7, 0xf8, 0xb0, 0x40, 0x4, 0x8, 0xf, 0x0, 0x0, 0x0, 0x0,
2456  0x0, 0x0, 0x20, 0xe, 0xc0, 0xc, 0x0, 0x2, 0x0, 0x1, 0x0, 0x1, 0x51, 0x7f,
2457  0x0, 0x6, 0x3, 0x6e, 0x73, 0x31, 0xc0, 0xc, 0xc0, 0xc, 0x0, 0x6, 0x0, 0x1,
2458  0x0, 0x0, 0x0, 0x3b, 0x0, 0x22, 0xc0, 0x54, 0x9, 0x64, 0x6e, 0x73, 0x2d,
2459  0x61, 0x64, 0x6d, 0x69, 0x6e, 0xc0, 0xc, 0xa, 0x3d, 0xc7, 0x30, 0x0, 0x0,
2460  0x3, 0x84, 0x0, 0x0, 0x3, 0x84, 0x0, 0x0, 0x7, 0x8, 0x0, 0x0, 0x0, 0x3c,
2461  0xc0, 0xc, 0x0, 0xf, 0x0, 0x1, 0x0, 0x0, 0x2, 0x57, 0x0, 0x11, 0x0, 0x1e,
2462  0x4, 0x61, 0x6c, 0x74, 0x32, 0x5, 0x61, 0x73, 0x70, 0x6d, 0x78, 0x1, 0x6c,
2463  0xc0, 0xc, 0xc0, 0xc, 0x0, 0xf, 0x0, 0x1, 0x0, 0x0, 0x2, 0x57, 0x0, 0x4,
2464  0x0, 0xa, 0xc0, 0x9b, 0xc0, 0xc, 0x0, 0x10, 0x0, 0x1, 0x0, 0x0, 0xe, 0xf,
2465  0x0, 0x24, 0x23, 0x76, 0x3d, 0x73, 0x70, 0x66, 0x31, 0x20, 0x69, 0x6e,
2466  0x63, 0x6c, 0x75, 0x64, 0x65, 0x3a, 0x5f, 0x73, 0x70, 0x66, 0x2e, 0x67,
2467  0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x7e, 0x61,
2468  0x6c, 0x6c, 0xc0, 0xc, 0x0, 0x2, 0x0, 0x1, 0x0, 0x1, 0x51, 0x7f, 0x0, 0x6,
2469  0x3, 0x6e, 0x73, 0x32, 0xc0, 0xc, 0xc0, 0xc, 0x1, 0x1, 0x0, 0x1, 0x0, 0x1,
2470  0x51, 0x7f, 0x0, 0xf, 0x0, 0x5, 0x69, 0x73, 0x73, 0x75, 0x65, 0x70, 0x6b,
2471  0x69, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0xc0, 0xc, 0x0, 0x2, 0x0, 0x1, 0x0,
2472  0x1, 0x51, 0x7f, 0x0, 0x6, 0x3, 0x6e, 0x73, 0x34, 0xc0, 0xc, 0xc0, 0xc,
2473  0x0, 0xf, 0x0, 0x1, 0x0, 0x0, 0x2, 0x57, 0x0, 0x9, 0x0, 0x28, 0x4, 0x61,
2474  0x6c, 0x74, 0x33, 0xc0, 0x9b, 0xc0, 0xc, 0x0, 0x2, 0x0, 0x1, 0x0, 0x1,
2475  0x51, 0x7f, 0x0, 0x6, 0x3, 0x6e, 0x73, 0x33, 0xc0, 0xc, 0xc0, 0xc, 0x0,
2476  0xf, 0x0, 0x1, 0x0, 0x0, 0x2, 0x57, 0x0, 0x9, 0x0, 0x32, 0x4, 0x61, 0x6c,
2477  0x74, 0x34, 0xc0, 0x9b, 0xc0, 0xc, 0x0, 0xf, 0x0, 0x1, 0x0, 0x0, 0x2,
2478  0x57,
2479  0x0, 0x9, 0x0, 0x14, 0x4, 0x61, 0x6c, 0x74, 0x31, 0xc0, 0x9b
2480 };
2481 
2482 #else
2483 /* www.weatherlink.com */
2485  0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
2486  0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77, 0x0b,
2487  0x77, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x6c, 0x69,
2488  0x6e, 0x6b, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0xff,
2489  0x00, 0x01, 0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00,
2490  0x00, 0x0c, 0x9e, 0x00, 0x1f, 0x0e, 0x64, 0x33, 0x6b,
2491  0x72, 0x30, 0x67, 0x75, 0x62, 0x61, 0x31, 0x64, 0x76,
2492  0x77, 0x66, 0x0a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x66,
2493  0x72, 0x6f, 0x6e, 0x74, 0x03, 0x6e, 0x65, 0x74, 0x00,
2494 };
2495 
2496 #endif
2497 
2498 static clib_error_t *
2500  unformat_input_t * input, vlib_cli_command_t * cmd)
2501 {
2502  dns_resolve_name_t _rn, *rn = &_rn;
2503  u8 *dns_reply_data = 0;
2504  int verbose = 0;
2505  int rv;
2506  vl_api_dns_resolve_name_reply_t _rm, *rmp = &_rm;
2507 
2508  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2509  {
2510  if (unformat (input, "verbose %d", &verbose))
2511  ;
2512  else if (unformat (input, "verbose"))
2513  verbose = 1;
2514  else
2515  return clib_error_return (0, "unknown input `%U'",
2516  format_unformat_error, input);
2517  }
2518 
2519  vec_validate (dns_reply_data, ARRAY_LEN (dns_reply_data_initializer) - 1);
2520 
2521  memcpy (dns_reply_data, dns_reply_data_initializer,
2523 
2524  vlib_cli_output (vm, "%U", format_dns_reply, dns_reply_data, verbose);
2525 
2526  clib_memset (rmp, 0, sizeof (*rmp));
2527 
2528  rv = vnet_dns_response_to_reply (dns_reply_data, rn, 0 /* ttl-ptr */);
2529 
2530  switch (rv)
2531  {
2532  case VNET_API_ERROR_NAME_SERVER_NO_ADDRESSES:
2533  vlib_cli_output (vm, "no addresses found...");
2534  break;
2535 
2536  default:
2537  vlib_cli_output (vm, "response to reply returned %d", rv);
2538  break;
2539 
2540  case 0:
2541  vlib_cli_output (vm, "ip address: %U", format_ip_address, &rn->address);
2542  break;
2543  }
2544 
2545  vec_free (dns_reply_data);
2546 
2547  return 0;
2548 }
2549 
2550 
2551 /* *INDENT-OFF* */
2553 {
2554  .path = "test dns format",
2555  .short_help = "test dns format",
2556  .function = test_dns_fmt_command_fn,
2557 };
2558 /* *INDENT-ON* */
2559 
2560 static clib_error_t *
2562  unformat_input_t * input, vlib_cli_command_t * cmd)
2563 {
2564  u8 *dns_reply_data = 0;
2565  int verbose = 0;
2566  int reply_set = 0;
2567 
2568  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2569  {
2570  if (unformat (input, "verbose %d", &verbose))
2571  ;
2572  else if (unformat (input, "verbose"))
2573  verbose = 1;
2574  else if (unformat (input, "%U", unformat_dns_reply, &dns_reply_data))
2575  reply_set = 1;
2576  else
2577  return clib_error_return (0, "unknown input `%U'",
2578  format_unformat_error, input);
2579  }
2580 
2581  if (reply_set == 0)
2582  return clib_error_return (0, "dns data not set...");
2583 
2584  vlib_cli_output (vm, "%U", format_dns_reply, dns_reply_data, verbose);
2585 
2586  vec_free (dns_reply_data);
2587 
2588  return 0;
2589 }
2590 
2591 /* *INDENT-OFF* */
2593 {
2594  .path = "test dns unformat",
2595  .short_help = "test dns unformat <name> [ip4][ip6]",
2596  .function = test_dns_unfmt_command_fn,
2597 };
2598 /* *INDENT-ON* */
2599 
2600 static clib_error_t *
2602  unformat_input_t * input,
2603  vlib_cli_command_t * cmd)
2604 {
2605  dns_main_t *dm = &dns_main;
2606  u8 *name = 0;
2607  uword *p;
2608  clib_error_t *e;
2609  dns_cache_entry_t *ep;
2610 
2611  if (unformat (input, "%v", &name))
2612  {
2613  vec_add1 (name, 0);
2614  _vec_len (name) -= 1;
2615  }
2616  else
2617  return clib_error_return (0, "no name provided");
2618 
2619  dns_cache_lock (dm, 7);
2620 
2622  if (!p)
2623  {
2624  dns_cache_unlock (dm);
2625  e = clib_error_return (0, "%s is not in the cache...", name);
2626  vec_free (name);
2627  return e;
2628  }
2629 
2630  ep = pool_elt_at_index (dm->entries, p[0]);
2631 
2632  ep->expiration_time = 0;
2633 
2634  return 0;
2635 }
2636 
2637 /* *INDENT-OFF* */
2639 {
2640  .path = "test dns expire",
2641  .short_help = "test dns expire <name>",
2642  .function = test_dns_expire_command_fn,
2643 };
2644 /* *INDENT-ON* */
2645 #endif
2646 
2647 void
2650  vlib_buffer_t * b0)
2651 {
2652  clib_warning ("Unimplemented...");
2653 }
2654 
2655 
2656 void
2659  vlib_buffer_t * b0)
2660 {
2661  u32 bi = 0;
2663  ip4_header_t *ip;
2664  udp_header_t *udp;
2665  dns_header_t *dh;
2666  vlib_frame_t *f;
2667  u32 *to_next;
2668  u8 *dns_response;
2669  u8 *reply;
2670  /* vl_api_dns_resolve_name_reply_t _rnr, *rnr = &_rnr; */
2671  dns_resolve_name_t _rn, *rn = &_rn;
2672  vl_api_dns_resolve_ip_reply_t _rir, *rir = &_rir;
2673  u32 ttl = 64, tmp;
2674  u32 qp_offset;
2675  dns_query_t *qp;
2676  dns_rr_t *rr;
2677  u8 *rrptr;
2678  int is_fail = 0;
2679  int is_recycle = (b0 != 0);
2680 
2681  ASSERT (ep && ep->dns_response);
2682 
2684  {
2685  /* Quick and dirty way to dig up the A-record address. $$ FIXME */
2686  clib_memset (rn, 0, sizeof (*rn));
2688  {
2689  /* clib_warning ("response_to_reply failed..."); */
2690  is_fail = 1;
2691  }
2692  else if (ip_addr_version (&rn->address) != AF_IP4)
2693  {
2694  /* clib_warning ("No A-record..."); */
2695  is_fail = 1;
2696  }
2697  }
2698  else if (pr->request_type == DNS_PEER_PENDING_IP_TO_NAME)
2699  {
2700  clib_memset (rir, 0, sizeof (*rir));
2701  if (vnet_dns_response_to_name (ep->dns_response, rir, &ttl))
2702  {
2703  /* clib_warning ("response_to_name failed..."); */
2704  is_fail = 1;
2705  }
2706  }
2707  else
2708  {
2709  clib_warning ("Unknown request type %d", pr->request_type);
2710  return;
2711  }
2712 
2713  /* Initialize a buffer */
2714  if (b0 == 0)
2715  {
2716  if (vlib_buffer_alloc (vm, &bi, 1) != 1)
2717  return;
2718  b0 = vlib_get_buffer (vm, bi);
2719  }
2720  else
2721  {
2722  /* Use the buffer we were handed. Reinitialize it... */
2723  vlib_buffer_t bt = { };
2724  /* push/pop the reference count */
2725  u8 save_ref_count = b0->ref_count;
2726  vlib_buffer_copy_template (b0, &bt);
2727  b0->ref_count = save_ref_count;
2728  bi = vlib_get_buffer_index (vm, b0);
2729  }
2730 
2731  if (b0->flags & VLIB_BUFFER_NEXT_PRESENT)
2733 
2734  /*
2735  * Reset the buffer. We recycle the DNS request packet in the cache
2736  * hit case, and reply immediately from the request node.
2737  *
2738  * In the resolution-required / deferred case, resetting a freshly-allocated
2739  * buffer won't hurt. We hope.
2740  */
2741  b0->flags |= (VNET_BUFFER_F_LOCALLY_ORIGINATED
2742  | VLIB_BUFFER_TOTAL_LENGTH_VALID);
2743  vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0; /* "local0" */
2744  vnet_buffer (b0)->sw_if_index[VLIB_TX] = 0; /* default VRF for now */
2745 
2746  if (!ip4_sas (0 /* default VRF for now */, ~0,
2747  (const ip4_address_t *) &pr->dst_address, &src_address))
2748  return;
2749 
2750  ip = vlib_buffer_get_current (b0);
2751  udp = (udp_header_t *) (ip + 1);
2752  dns_response = (u8 *) (udp + 1);
2753  clib_memset (ip, 0, sizeof (*ip) + sizeof (*udp));
2754 
2755  /*
2756  * Start with the variadic portion of the exercise.
2757  * Turn the name into a set of DNS "labels". Max length
2758  * per label is 63, enforce that.
2759  */
2760  reply = name_to_labels (pr->name);
2761  vec_free (pr->name);
2762 
2763  qp_offset = vec_len (reply);
2764 
2765  /* Add space for the query header */
2766  vec_validate (reply, qp_offset + sizeof (dns_query_t) - 1);
2767 
2768  qp = (dns_query_t *) (reply + qp_offset);
2769 
2771  qp->type = clib_host_to_net_u16 (DNS_TYPE_A);
2772  else
2773  qp->type = clib_host_to_net_u16 (DNS_TYPE_PTR);
2774 
2775  qp->class = clib_host_to_net_u16 (DNS_CLASS_IN);
2776 
2777  /* Punch in space for the dns_header_t */
2778  vec_insert (reply, sizeof (dns_header_t), 0);
2779 
2780  dh = (dns_header_t *) reply;
2781 
2782  /* Transaction ID = pool index */
2783  dh->id = pr->id;
2784 
2785  /* Announce that we did a recursive lookup */
2787  if (is_fail)
2789  dh->flags = clib_host_to_net_u16 (tmp);
2790  dh->qdcount = clib_host_to_net_u16 (1);
2791  dh->anscount = (is_fail == 0) ? clib_host_to_net_u16 (1) : 0;
2792  dh->nscount = 0;
2793  dh->arcount = 0;
2794 
2795  /* If the name resolution worked, cough up an appropriate RR */
2796  if (is_fail == 0)
2797  {
2798  /* Add the answer. First, a name pointer (0xC00C) */
2799  vec_add1 (reply, 0xC0);
2800  vec_add1 (reply, 0x0C);
2801 
2802  /* Now, add single A-rec RR */
2804  {
2805  vec_add2 (reply, rrptr, sizeof (dns_rr_t) + sizeof (ip4_address_t));
2806  rr = (dns_rr_t *) rrptr;
2807 
2808  rr->type = clib_host_to_net_u16 (DNS_TYPE_A);
2809  rr->class = clib_host_to_net_u16 (1 /* internet */ );
2810  rr->ttl = clib_host_to_net_u32 (ttl);
2811  rr->rdlength = clib_host_to_net_u16 (sizeof (ip4_address_t));
2812  ip_address_copy_addr (rr->rdata, &rn->address);
2813  }
2814  else
2815  {
2816  /* Or a single PTR RR */
2817  u8 *vecname = format (0, "%s", rir->name);
2818  u8 *label_vec = name_to_labels (vecname);
2819  vec_free (vecname);
2820 
2821  vec_add2 (reply, rrptr, sizeof (dns_rr_t) + vec_len (label_vec));
2822  rr = (dns_rr_t *) rrptr;
2823  rr->type = clib_host_to_net_u16 (DNS_TYPE_PTR);
2824  rr->class = clib_host_to_net_u16 (1 /* internet */ );
2825  rr->ttl = clib_host_to_net_u32 (ttl);
2826  rr->rdlength = clib_host_to_net_u16 (vec_len (label_vec));
2827  clib_memcpy (rr->rdata, label_vec, vec_len (label_vec));
2828  vec_free (label_vec);
2829  }
2830  }
2831  clib_memcpy (dns_response, reply, vec_len (reply));
2832 
2833  /* Set the packet length */
2834  b0->current_length = sizeof (*ip) + sizeof (*udp) + vec_len (reply);
2835 
2836  /* IP header */
2837  ip->ip_version_and_header_length = 0x45;
2838  ip->length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0));
2839  ip->ttl = 255;
2840  ip->protocol = IP_PROTOCOL_UDP;
2841  ip->src_address.as_u32 = src_address.as_u32;
2842  clib_memcpy (ip->dst_address.as_u8, pr->dst_address,
2843  sizeof (ip4_address_t));
2844  ip->checksum = ip4_header_checksum (ip);
2845 
2846  /* UDP header */
2847  udp->src_port = clib_host_to_net_u16 (UDP_DST_PORT_dns);
2848  udp->dst_port = pr->dst_port;
2849  udp->length = clib_host_to_net_u16 (sizeof (udp_header_t) +
2850  vec_len (reply));
2851  udp->checksum = 0;
2852  vec_free (reply);
2853 
2854  /*
2855  * Ship pkts made out of whole cloth to ip4_lookup
2856  * Caller will ship recycled dns reply packets to ip4_lookup
2857  */
2858  if (is_recycle == 0)
2859  {
2861  to_next = vlib_frame_vector_args (f);
2862  to_next[0] = bi;
2863  f->n_vectors = 1;
2865  }
2866 }
2867 
2868 #include <dns/dns.api.c>
2869 static clib_error_t *
2871 {
2872  dns_main_t *dm = &dns_main;
2873 
2874  dm->vnet_main = vnet_get_main ();
2875  dm->name_cache_size = 1000;
2876  dm->max_ttl_in_seconds = 86400;
2877  dm->random_seed = 0xDEADDABE;
2878  dm->api_main = vlibapi_get_main ();
2879 
2880  /* Ask for a correctly-sized block of API message decode slots */
2882 
2883  return 0;
2884 }
2885 
2886 /* *INDENT-OFF* */
2888  .init_order = VLIB_INITS ("flow_classify_init", "dns_init"),
2889 };
2890 
2892 {
2893  .version = VPP_BUILD_VER,
2894  .description = "Simple DNS name resolver",
2895 };
2896 /* *INDENT-ON* */
2897 
2898 
2899 /*
2900  * fd.io coding-style-patch-verification: ON
2901  *
2902  * Local Variables:
2903  * eval: (c-set-style "gnu")
2904  * End:
2905  */
vlib_process_signal_event_mt
static void vlib_process_signal_event_mt(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Signal event to process from any thread.
Definition: node_funcs.h:1043
vnet_dns_response_to_reply
int vnet_dns_response_to_reply(u8 *response, dns_resolve_name_t *rn, u32 *min_ttlp)
Definition: dns.c:1072
clib_spinlock_init
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:65
tmp
u32 * tmp
Definition: interface_output.c:1096
vlib_buffer_t::next_buffer
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:149
ip4_lookup_node
vlib_node_registration_t ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (ip4_lookup_node)
Definition: ip4_forward.c:105
vlib_frame_t::n_vectors
u16 n_vectors
Definition: node.h:387
udp_header_t::src_port
u16 src_port
Definition: udp_packet.h:48
udp_header_t::length
u16 length
Definition: udp_packet.h:51
api.h
format_dns_query
u8 * format_dns_query(u8 *s, va_list *args)
Definition: dns.c:1608
DNS_RA
#define DNS_RA
recursion available
Definition: dns_packet.h:42
label
u32 label
Definition: fib_types.api:25
DNS_RCODE_REFUSED
#define DNS_RCODE_REFUSED
Definition: dns_packet.h:40
show_dns_server_command
vlib_cli_command_t show_dns_server_command
(constructor) VLIB_CLI_COMMAND (show_dns_server_command)
Definition: dns.c:2202
hash_free
#define hash_free(h)
Definition: hash.h:310
dns_main_t::entries
dns_cache_entry_t * entries
Pool of cache entries.
Definition: dns.h:99
REPLY_MACRO2
#define REPLY_MACRO2(t, body)
Definition: api_helper_macros.h:65
dns_cache_entry_t
Definition: dns.h:55
dns_pending_request_t::id
u16 id
Definition: dns.h:36
ip6_tcp_udp_icmp_compute_checksum
u16 ip6_tcp_udp_icmp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip6_header_t *ip0, int *bogus_lengthp)
Definition: ip6_forward.c:1096
format_ip4_address
format_function_t format_ip4_address
Definition: format.h:73
dns_main_t::is_enabled
int is_enabled
enable / disable flag
Definition: dns.h:110
clib_memcpy
#define clib_memcpy(d, s, n)
Definition: string.h:197
dns_main_t::msg_id_base
u16 msg_id_base
message-ID base
Definition: dns.h:128
DNS_API_PENDING_IP_TO_NAME
@ DNS_API_PENDING_IP_TO_NAME
Definition: dns.h:50
dns_cache_lock
static void dns_cache_lock(dns_main_t *dm, int tag)
Definition: dns.h:209
DNS_RCODE_NOT_IMPLEMENTED
#define DNS_RCODE_NOT_IMPLEMENTED
Definition: dns_packet.h:39
DNS_RCODE_NAME_ERROR
#define DNS_RCODE_NAME_ERROR
Definition: dns_packet.h:38
dns_cache_entry_t::retry_timer
f64 retry_timer
Definition: dns.h:77
DNS_CACHE_ENTRY_FLAG_STATIC
#define DNS_CACHE_ENTRY_FLAG_STATIC
static entry
Definition: dns.h:87
vlib_get_buffer
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
vl_api_dns_resolve_name_reply_t
DNS name resolution reply.
Definition: dns.api:71
f
vlib_frame_t * f
Definition: interface_output.c:1098
name_to_labels
u8 * name_to_labels(u8 *name)
Translate "foo.com" into "0x3 f o o 0x3 c o m 0x0" A historical / hysterical micro-TLV scheme.
Definition: dns.c:362
pool_elt_at_index
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:549
name
string name[64]
Definition: fib.api:25
DNS_QR
#define DNS_QR
query=0, response=1
Definition: dns_packet.h:50
ttl
u8 ttl
Definition: fib_types.api:26
vnet_dns_response_to_name
int vnet_dns_response_to_name(u8 *response, vl_api_dns_resolve_ip_reply_t *rmp, u32 *min_ttlp)
Definition: dns.c:1212
DNS_CLASS_IN
#define DNS_CLASS_IN
The Internet.
Definition: dns_packet.h:145
vl_api_dns_resolve_name_t::context
u32 context
Definition: dns.api:56
vl_api_dns_resolve_ip_t::is_ip6
u8 is_ip6
Definition: dns.api:90
dns_cache_add_del_command_fn
static clib_error_t * dns_cache_add_del_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: dns.c:2212
vnet_dns_send_dns6_request
void vnet_dns_send_dns6_request(vlib_main_t *vm, dns_main_t *dm, dns_cache_entry_t *ep, ip6_address_t *server)
Definition: dns.c:288
DNS_RD
#define DNS_RD
recursion desired
Definition: dns_packet.h:43
hash_create_string
#define hash_create_string(elts, value_bytes)
Definition: hash.h:689
clib_error_return
#define clib_error_return(e, args...)
Definition: error.h:99
vlib_cli_command_t::path
char * path
Definition: cli.h:96
ip4_address_t::as_u32
u32 as_u32
Definition: ip4_packet.h:57
ip_sas.h
DNS_API_PENDING_NAME_TO_IP
@ DNS_API_PENDING_NAME_TO_IP
Definition: dns.h:49
dns4_name_server_add_del
static int dns4_name_server_add_del(dns_main_t *dm, u8 *server_address_as_u8, int is_add)
Definition: dns.c:169
u16
unsigned short u16
Definition: types.h:57
hash_set_mem
#define hash_set_mem(h, key, value)
Definition: hash.h:275
dns_cache_entry_t::flags
volatile u8 flags
flags
Definition: dns.h:58
format_dns_reply
u8 * format_dns_reply(u8 *s, va_list *args)
Definition: dns.c:1938
dns_main
dns_main_t dns_main
Definition: dns.c:41
pool_put
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:305
dns4_request_node
vlib_node_registration_t dns4_request_node
(constructor) VLIB_REGISTER_NODE (dns4_request_node)
Definition: request_node.c:293
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
api.h
DNS_RCODE_NO_ERROR
#define DNS_RCODE_NO_ERROR
Definition: dns_packet.h:35
AF_IP4
@ AF_IP4
Definition: ip_types.h:23
vec_delete
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:875
dns_main_t::udp_ports_registered
int udp_ports_registered
udp port registration complete
Definition: dns.h:113
test_dns_fmt_command
vlib_cli_command_t test_dns_fmt_command
(constructor) VLIB_CLI_COMMAND (test_dns_fmt_command)
Definition: dns.c:2552
VLIB_RX
@ VLIB_RX
Definition: defs.h:46
dns_config_fn
static clib_error_t * dns_config_fn(vlib_main_t *vm, unformat_input_t *input)
Definition: dns.c:1484
dns_pending_request_t::dst_address
u8 dst_address[16]
Definition: dns.h:38
vl_api_dns_resolve_ip_t
DNS IP -> name resolution request.
Definition: dns.api:87
unformat_input_t
struct _unformat_input_t unformat_input_t
vl_api_dns_resolve_ip_reply_t::retval
i32 retval
Definition: dns.api:104
dns_cache_unlock
static void dns_cache_unlock(dns_main_t *dm)
Definition: dns.h:221
ip4_sas
bool ip4_sas(u32 table_id, u32 sw_if_index, const ip4_address_t *dst, ip4_address_t *src)
Definition: ip_sas.c:187
show_dns_cache_command_fn
static clib_error_t * show_dns_cache_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: dns.c:2138
vlib_frame_t
Definition: node.h:372
show_dns_cache_command
vlib_cli_command_t show_dns_cache_command
(constructor) VLIB_CLI_COMMAND (show_dns_cache_command)
Definition: dns.c:2165
vlib_get_frame_to_node
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:184
vl_api_dns_resolve_ip_t::context
u32 context
Definition: dns.api:89
vlib_buffer_length_in_chain
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:433
vl_api_dns_resolve_name_reply_t::ip4_address
u8 ip4_address[4]
Definition: dns.api:76
ip6_lookup_node
vlib_node_registration_t ip6_lookup_node
(constructor) VLIB_REGISTER_NODE (ip6_lookup_node)
Definition: ip6_forward.c:739
test_dns_fmt_command_fn
static clib_error_t * test_dns_fmt_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: dns.c:2499
udp_header_t
Definition: udp_packet.h:45
ip4_header_t
Definition: ip4_packet.h:87
dns_main_t::ip4_name_servers
ip4_address_t * ip4_name_servers
upstream name servers, e.g.
Definition: dns.h:116
dns_cache_entry_t::server_rotor
int server_rotor
Definition: dns.h:74
h
h
Definition: flowhash_template.h:372
vl_api_dns_resolve_name_t
DNS name resolution request.
Definition: dns.api:54
error
Definition: cJSON.c:88
dns_resolve_name_t
Definition: dns.h:42
vl_api_dns_name_server_add_del_t::server_address
u8 server_address[16]
Definition: dns.api:44
vnet_dns_resolve_name
int vnet_dns_resolve_name(vlib_main_t *vm, dns_main_t *dm, u8 *name, dns_pending_request_t *t, dns_cache_entry_t **retp)
Definition: dns.c:720
dns_resolve_name
__clib_export int dns_resolve_name(u8 *name, dns_cache_entry_t **ep, dns_pending_request_t *t0, dns_resolve_name_t *rn)
Definition: dns.c:1348
dns_pending_request_t::name
u8 * name
Definition: dns.h:39
test_dns_expire_command
vlib_cli_command_t test_dns_expire_command
(constructor) VLIB_CLI_COMMAND (test_dns_expire_command)
Definition: dns.c:2638
ip6_sas
bool ip6_sas(u32 table_id, u32 sw_if_index, const ip6_address_t *dst, ip6_address_t *src)
Definition: ip_sas.c:149
random_u32
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
vl_api_dns_name_server_add_del_t::is_add
u8 is_add
Definition: dns.api:43
vnet_dns_cname_indirection_nolock
int vnet_dns_cname_indirection_nolock(vlib_main_t *vm, dns_main_t *dm, u32 ep_index, u8 *reply)
Handle cname indirection.
Definition: dns.c:876
VLIB_CONFIG_FUNCTION
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:181
unformat
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
pool_is_free_index
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:302
dns_cache_entry_t::pending_requests
dns_pending_request_t * pending_requests
Clients / peers awaiting responses.
Definition: dns.h:83
vl_api_dns_resolve_name_t_handler
static void vl_api_dns_resolve_name_t_handler(vl_api_dns_resolve_name_t *mp)
Definition: dns.c:1368
dns_main_t::ip6_name_servers
ip6_address_t * ip6_name_servers
Definition: dns.h:117
dns_add_static_entry
static int dns_add_static_entry(dns_main_t *dm, u8 *name, u8 *dns_reply_data)
Definition: dns.c:676
vlib_put_frame_to_node
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:218
vlib_thread_main_t::n_vlib_mains
u32 n_vlib_mains
Definition: threads.h:262
ip_addr_version
#define ip_addr_version(_a)
Definition: ip_types.h:93
pool_foreach
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:534
ip_address_copy_addr
void ip_address_copy_addr(void *dst, const ip_address_t *src)
Definition: ip_types.c:164
vnet_send_dns_request
void vnet_send_dns_request(vlib_main_t *vm, dns_main_t *dm, dns_cache_entry_t *ep)
Definition: dns.c:447
count
u8 count
Definition: dhcp.api:208
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
dns_cache_entry_t::name
u8 * name
The name in "normal human being" notation, e.g.
Definition: dns.h:61
len
u8 len
Definition: ip_types.api:103
dns_main_t::cache_lock
clib_spinlock_t cache_lock
Definition: dns.h:106
dns_pending_request_t::client_index
u32 client_index
Definition: dns.h:32
vec_add2
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:644
vec_add1
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:606
dns_resolve_name_t::address
ip_address_t address
Definition: dns.h:44
dns6_request_node
vlib_node_registration_t dns6_request_node
(constructor) VLIB_REGISTER_NODE (dns6_request_node)
Definition: request_node.c:320
vnet_send_dns6_reply
void vnet_send_dns6_reply(vlib_main_t *vm, dns_main_t *dm, dns_pending_request_t *pr, dns_cache_entry_t *ep, vlib_buffer_t *b0)
Definition: dns.c:2648
vlib_buffer_alloc
static __clib_warn_unused_result u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:702
hash_unset_mem
#define hash_unset_mem(h, key)
Definition: hash.h:291
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:441
vec_dup
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:444
vnet_get_main
vnet_main_t * vnet_get_main(void)
Definition: pnat_test_stubs.h:56
vnet_dns_send_dns4_request
void vnet_dns_send_dns4_request(vlib_main_t *vm, dns_main_t *dm, dns_cache_entry_t *ep, ip4_address_t *server)
Definition: dns.c:220
dns_main_t::cache_entry_by_name
uword * cache_entry_by_name
Find cached record by name.
Definition: dns.h:105
vl_api_dns_resolve_name_reply_t::ip6_set
u8 ip6_set
Definition: dns.api:75
offset
struct clib_bihash_value offset
template key/value backing page structure
vl_api_dns_name_server_add_del_t
add or delete an upstream name server
Definition: dns.api:39
vl_api_dns_resolve_name_reply_t::ip4_set
u8 ip4_set
Definition: dns.api:74
REPLY_MACRO
#define REPLY_MACRO(t)
Definition: api_helper_macros.h:30
setup_message_id_table
static void setup_message_id_table(api_main_t *am)
Definition: sr_mpls_api.c:174
ARRAY_LEN
#define ARRAY_LEN(x)
Definition: clib.h:70
vlib_get_buffer_index
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
Definition: buffer_funcs.h:324
vlib_frame_vector_args
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
unformat_check_input
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:163
vlib_config_function_runtime_t
Definition: init.h:68
dns_pending_request_t::dst_port
u16 dst_port
Definition: dns.h:35
vnet_send_dns4_reply
void vnet_send_dns4_reply(vlib_main_t *vm, dns_main_t *dm, dns_pending_request_t *pr, dns_cache_entry_t *ep, vlib_buffer_t *b0)
Definition: dns.c:2657
vl_api_dns_resolve_name_t::name
u8 name[256]
Definition: dns.api:57
udp_local.h
dns_pending_request_t::client_context
u32 client_context
Definition: dns.h:33
format_ip_address
u8 * format_ip_address(u8 *s, va_list *args)
Definition: ip_types.c:21
uword
u64 uword
Definition: types.h:112
test_dns_unfmt_command
vlib_cli_command_t test_dns_unfmt_command
(constructor) VLIB_CLI_COMMAND (test_dns_unfmt_command)
Definition: dns.c:2592
if
if(node->flags &VLIB_NODE_FLAG_TRACE) vnet_interface_output_trace(vm
vlib_thread_main
vlib_thread_main_t vlib_thread_main
Definition: threads.c:36
dns_enable_disable
static int dns_enable_disable(vlib_main_t *vm, dns_main_t *dm, int is_enable)
Definition: dns.c:70
dns_main_t::api_main
api_main_t * api_main
Definition: dns.h:132
vlibapi_get_main
static api_main_t * vlibapi_get_main(void)
Definition: api_common.h:390
udp_register_dst_port
void udp_register_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
Definition: udp_local.c:431
dns_reply_data_initializer
static u8 dns_reply_data_initializer[]
Definition: dns.c:2484
vlib_buffer_copy_template
static_always_inline void vlib_buffer_copy_template(vlib_buffer_t *b, vlib_buffer_t *bt)
Definition: buffer_funcs.h:171
vl_api_dns_resolve_ip_t_handler
static void vl_api_dns_resolve_ip_t_handler(vl_api_dns_resolve_ip_t *mp)
Definition: dns.c:1409
f64
double f64
Definition: types.h:142
dns_main_t::max_ttl_in_seconds
u32 max_ttl_in_seconds
Definition: dns.h:124
vl_api_dns_enable_disable_t::enable
u8 enable
Definition: dns.api:27
format_unformat_error
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
pool_get
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:255
vec_validate
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment)
Definition: vec.h:523
dns_cache_clear
static int dns_cache_clear(dns_main_t *dm)
Definition: dns.c:44
VLIB_CLI_COMMAND
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:163
dns_cache_entry_t::expiration_time
f64 expiration_time
Expiration time.
Definition: dns.h:67
vlib_buffer_t::ref_count
volatile u8 ref_count
Reference count for this buffer.
Definition: buffer.h:139
dns6_name_server_add_del
static int dns6_name_server_add_del(dns_main_t *dm, u8 *server_address_as_u8, int is_add)
Definition: dns.c:133
ip_address_set
void ip_address_set(ip_address_t *dst, const void *src, ip_address_family_t af)
Definition: ip_types.c:207
ip4_address_t
Definition: ip4_packet.h:50
dns_pending_request_t::request_type
u32 request_type
Definition: dns.h:31
ip6_address_copy
static void ip6_address_copy(ip6_address_t *dst, const ip6_address_t *src)
Definition: ip6_packet.h:127
DNS_PEER_PENDING_IP_TO_NAME
@ DNS_PEER_PENDING_IP_TO_NAME
Definition: dns.h:52
vlib_cli_output
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:716
vlib_buffer_t::current_length
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:122
dns46_reply_node
vlib_node_registration_t dns46_reply_node
(constructor) VLIB_REGISTER_NODE (dns46_reply_node)
Definition: reply_node.c:42
vl_api_dns_resolve_ip_reply_t::name
u8 name[256]
Definition: dns.api:105
dns_main_t::random_seed
u32 random_seed
Definition: dns.h:125
plugin.h
udp_header_t::checksum
u16 checksum
Definition: udp_packet.h:55
vl_api_dns_enable_disable_t
enable/disable name resolution
Definition: dns.api:24
vl_api_dns_resolve_name_t::client_index
u32 client_index
Definition: dns.api:55
id
u8 id[64]
Definition: dhcp.api:160
request
vhost_user_req_t request
Definition: vhost_user.h:123
dns_cache_entry_t::dns_request
u8 * dns_request
Cached dns request, for sending retries.
Definition: dns.h:70
hash_get_mem
#define hash_get_mem(h, key)
Definition: hash.h:269
vl_api_dns_enable_disable_t_handler
static void vl_api_dns_enable_disable_t_handler(vl_api_dns_enable_disable_t *mp)
Definition: dns.c:120
dns_cache_entry_t::dns_response
u8 * dns_response
Cached dns response.
Definition: dns.h:80
vec_free
#define vec_free(V)
Free vector's memory (no header).
Definition: vec.h:395
dns_cache_entry_t::cname
u8 * cname
For CNAME records, the "next name" to resolve.
Definition: dns.h:64
index
u32 index
Definition: flow_types.api:221
clib_bihash_value
template key/value backing page structure
Definition: bihash_doc.h:44
vl_api_dns_resolve_ip_t::client_index
u32 client_index
Definition: dns.api:88
format
description fragment has unexpected format
Definition: map.api:433
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
u32
unsigned int u32
Definition: types.h:88
VLIB_INIT_FUNCTION
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
test_dns_unfmt_command_fn
static clib_error_t * test_dns_unfmt_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: dns.c:2561
udp_header_t::dst_port
u16 dst_port
Definition: udp_packet.h:48
vlib_thread_main_t
Definition: threads.h:243
vl_api_dns_name_server_add_del_t_handler
static void vl_api_dns_name_server_add_del_t_handler(vl_api_dns_name_server_add_del_t *mp)
Definition: dns.c:205
format_dns_reply_data
u8 * format_dns_reply_data(u8 *s, va_list *args)
format dns reply data verbose > 1, dump everything verbose == 1, dump all A and AAAA records verbose ...
Definition: dns.c:1672
dh
vl_api_ikev2_sa_transform_t dh
Definition: ikev2_types.api:160
VLIB_PLUGIN_REGISTER
VLIB_PLUGIN_REGISTER()
api_helper_macros.h
dns_main_t::name_cache_size
u32 name_cache_size
config parameters
Definition: dns.h:123
pool_elts
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127
AF_IP6
@ AF_IP6
Definition: ip_types.h:24
ip6_header_t
Definition: ip6_packet.h:294
now
f64 now
Definition: nat44_ei_out2in.c:710
dns_pending_request_t::is_ip6
u8 is_ip6
Definition: dns.h:34
clib_memset
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
vlib_main_t
Definition: main.h:102
dns_cache_add_del_command
vlib_cli_command_t dns_cache_add_del_command
(constructor) VLIB_CLI_COMMAND (dns_cache_add_del_command)
Definition: dns.c:2304
VLIB_INITS
#define VLIB_INITS(...)
Definition: init.h:352
vlib_get_main
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:38
delete_random_entry
static int delete_random_entry(dns_main_t *dm)
Definition: dns.c:629
b
vlib_buffer_t ** b
Definition: nat44_ei_out2in.c:717
DNS_PEER_PENDING_NAME_TO_IP
@ DNS_PEER_PENDING_NAME_TO_IP
Definition: dns.h:51
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
vlib_buffer_get_current
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
ip
vl_api_address_t ip
Definition: l2.api:558
vnet_dns_labels_to_name
u8 * vnet_dns_labels_to_name(u8 *label, u8 *full_text, u8 **parse_from_here)
arc-function for the above.
Definition: dns.c:405
ip4_header_checksum
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:314
dns_main_t::vnet_main
vnet_main_t * vnet_main
Definition: dns.h:131
vlib_init_function_t
clib_error_t *() vlib_init_function_t(struct vlib_main_t *vm)
Definition: init.h:51
format_ip6_address
format_function_t format_ip6_address
Definition: format.h:91
vec_terminate_c_string
#define vec_terminate_c_string(V)
(If necessary) NULL terminate a vector containing a c-string.
Definition: vec.h:1132
i
int i
Definition: flowhash_template.h:376
pool_free
#define pool_free(p)
Free a pool.
Definition: pool.h:447
DNS_RESOLVER_EVENT_PENDING
#define DNS_RESOLVER_EVENT_PENDING
Definition: dns.h:93
vl_api_dns_resolve_ip_reply_t
DNS ip->name resolution reply.
Definition: dns.api:102
clib_warning
#define clib_warning(format, args...)
Definition: error.h:59
unformat_ip6_address
unformat_function_t unformat_ip6_address
Definition: format.h:89
DNS_RCODE_MASK
#define DNS_RCODE_MASK
Definition: dns_packet.h:34
DNS_RCODE_FORMAT_ERROR
#define DNS_RCODE_FORMAT_ERROR
Definition: dns_packet.h:36
rv
int __clib_unused rv
Definition: application.c:491
show_dns_servers_command_fn
static clib_error_t * show_dns_servers_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: dns.c:2174
unformat_ip4_address
unformat_function_t unformat_ip4_address
Definition: format.h:68
vlib_buffer_free_one
static void vlib_buffer_free_one(vlib_main_t *vm, u32 buffer_index)
Free one buffer Shorthand to free a single buffer chain.
Definition: buffer_funcs.h:1012
dns_main_t::resolver_process_node_index
u32 resolver_process_node_index
resolver process node index
Definition: dns.h:120
dns_delete_by_name
static int dns_delete_by_name(dns_main_t *dm, u8 *name)
Definition: dns.c:606
dns_main_t::unresolved_entries
u32 * unresolved_entries
Pool indices of unresolved entries.
Definition: dns.h:102
dns_pending_request_t
Definition: dns.h:29
vlib_time_now
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:327
vl_api_dns_name_server_add_del_t::is_ip6
u8 is_ip6
Definition: dns.api:42
DNS_RETRIES_PER_SERVER
#define DNS_RETRIES_PER_SERVER
Definition: dns.h:90
vnet_dns_delete_entry_by_index_nolock
int vnet_dns_delete_entry_by_index_nolock(dns_main_t *dm, u32 index)
Definition: dns.c:572
vnet.h
dns.h
src_address
vl_api_address_union_t src_address
Definition: ip_types.api:122
vlib_cli_command_t
Definition: cli.h:92
test_dns_expire_command_fn
static clib_error_t * test_dns_expire_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: dns.c:2601
dns_main_t
Definition: dns.h:96
vlib_buffer_t::total_length_not_including_first_buffer
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
Definition: buffer.h:176
format_dns_cache
u8 * format_dns_cache(u8 *s, va_list *args)
Definition: dns.c:1998
DNS_TC
#define DNS_TC
truncation
Definition: dns_packet.h:44
vnet_dns_create_resolver_process
void vnet_dns_create_resolver_process(vlib_main_t *vm, dns_main_t *dm)
Definition: resolver_process.c:349
VLIB_TX
@ VLIB_TX
Definition: defs.h:47
DNS_RCODE_SERVER_FAILURE
#define DNS_RCODE_SERVER_FAILURE
Definition: dns_packet.h:37
vec_insert
#define vec_insert(V, N, M)
Insert N vector elements starting at element M, initialize new elements to zero (no header,...
Definition: vec.h:775
DNS_AA
#define DNS_AA
authoritative answer
Definition: dns_packet.h:45
dns_cache_entry_t::server_af
int server_af
Definition: dns.h:75
dns_cache_entry_t::retry_count
int retry_count
Retry parameters.
Definition: dns.h:73
dns_init
static clib_error_t * dns_init(vlib_main_t *vm)
Definition: dns.c:2870
dns_cache_entry_t::server_fails
int server_fails
Definition: dns.h:76
vl_api_dns_resolve_ip_t::address
u8 address[16]
Definition: dns.api:91
UNFORMAT_END_OF_INPUT
#define UNFORMAT_END_OF_INPUT
Definition: format.h:137
DNS_CACHE_ENTRY_FLAG_VALID
#define DNS_CACHE_ENTRY_FLAG_VALID
we have Actual Data
Definition: dns.h:86
foreach_notification_to_move
#define foreach_notification_to_move
Definition: dns.c:867
vlib_buffer_t::flags
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index,...
Definition: buffer.h:133
unformat_dns_reply
uword unformat_dns_reply(unformat_input_t *input, va_list *args)
Definition: dns.c:1504
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
DNS_OPCODE_QUERY
#define DNS_OPCODE_QUERY
standard query
Definition: dns_packet.h:47
DNS_CACHE_ENTRY_FLAG_CNAME
#define DNS_CACHE_ENTRY_FLAG_CNAME
CNAME (indirect) entry.
Definition: dns.h:88
flags
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105