summaryrefslogtreecommitdiffstats
path: root/src/vnet/dns/dns.h
blob: b2e3e9b90cb6810f4b5cc39647d83f2b0cc2931e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

@media only all and (prefers-color-scheme: dark) {
.highlight .hll { background-color: #49483e }
.highlight .c { color: #75715e } /* Comment */
.highlight .err { color: #960050; background-color: #1e0010 } /* Error */
.highlight .k { color: #66d9ef } /* Keyword */
.highlight .l { color: #ae81ff } /* Literal */
.highlight .n { color: #f8f8f2 } /* Name */
.highlight .o { color: #f92672 } /* Operator */
.highlight .p { color: #f8f8f2 } /* Punctuation */
.highlight .ch { color: #75715e } /* Comment.Hashbang */
.highlight .cm { color: #75715e } /* Comment.Multiline */
.highlight .cp { color: #75715e } /* Comment.Preproc */
.highlight .cpf { color: #75715e } /* Comment.PreprocFile */
.highlight .c1 { color: #75715e } /* Comment.Single */
.highlight .cs { color: #75715e } /* Comment.Special */
.highlight .gd { color: #f92672 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gi { color: #a6e22e } /* Generic.Inserted */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #75715e } /* Generic.Subheading */
.highlight .kc { color: #66d9ef } /* Keyword.Constant */
.highlight .kd { color: #66d9ef } /* Keyword.Declaration */
.highlight .kn { color: #f92672 } /* Keyword.Namespace */
.highlight .kp { color: #66d9ef } /* Keyword.Pseudo */
.highlight .kr { color: #66d9ef } /* Keyword.Reserved */
.highlight .kt { color: #66d9ef } /* Keyword.Type */
.highlight .ld { color: #e6db74 } /* Literal.Date */
.highlight .m { color: #ae81ff } /* Literal.Number */
.highlight .s { color: #e6db74 } /* Literal.String */
.highlight .na { color: #a6e22e } /* Name.Attribute */
.highlight .nb { color: #f8f8f2 } /* Name.Builtin */
.highlight .nc { color: #a6e22e } /* Name.Class */
.highlight .no { color: #66d9ef } /* Name.Constant */
.highlight .nd { color: #a6e22e } /* Name.Decorator */
.highlight .ni { color: #f8f8f2 } /* Name.Entity */
.highlight .ne { color: #a6e22e } /* Name.Exception */
.highlight .nf { color: #a6e22e } /* Name.Function */
.highlight .nl { color: #f8f8f2 } /* Name.Label */
.highlight .nn { color: #f8f8f2 } /* Name.Namespace */
.highlight .nx { color: #a6e22e } /* Name.Other */
.highlight .py { color: #f8f8f2 } /* Name.Property */
.highlight .nt { color: #f92672 } /* Name.Tag */
.highlight .nv { color: #f8f8f2 } /* Name.Variable */
.highlight .ow { color: #f92672 } /* Operator.Word */
.highlight .w { color: #f8f8f2 } /* Text.Whitespace */
.highlight .mb { color: #ae81ff } /* Literal.Number.Bin */
.highlight .mf { color: #ae81ff } /* Literal.Number.Float */
.highlight .mh { color: #ae81ff } /* Literal.Number.Hex */
.highlight .mi { color: #ae81ff } /* Literal.Number.Integer */
.highlight .mo { color: #ae81ff } /* Literal.Number.Oct */
.highlight .sa { color: #e6db74 } /* Literal.String.Affix */
.highlight .sb { color: #e6db74 } /* Literal.String.Backtick */
.highlight .sc { color: #e6db74 } /* Literal.String.Char */
.highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */
.highlight .sd { color: #e6db74 } /* Literal.String.Doc */
.highlight .s2 { color: #e6db74 } /* Literal.String.Double */
.highlight .se { color: #ae81ff } /* Literal.String.Escape */
.highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */
.highlight .si { color: #e6db74 } /* Literal.String.Interpol */
.highlight .sx { color: #e6db74 } /* Literal.String.Other */
.highlight .sr { color: #e6db74 } /* Literal.String.Regex */
.highlight .s1 { color: #e6db74 } /* Literal.String.Single */
.highlight .ss { color: #e6db74 } /* Literal.String.Symbol */
.highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #a6e22e } /* Name.Function.Magic */
.highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */
.highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */
.highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */
.highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */
.highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */
}
@media (prefers-color-scheme: light) {
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { colo
/*
 * Copyright (c) 2017 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef included_dns_h
#define included_dns_h

#include <vppinfra/time.h>
#include <vppinfra/cache.h>
#include <vppinfra/error.h>

#include <vppinfra/hash.h>
#include <vnet/dns/dns_packet.h>
#include <vnet/ip/ip.h>

typedef struct
{
  u32 request_type;
  u32 client_index;
  u32 client_context;
  u8 is_ip6;
  u16 dst_port;
  u16 id;
  u16 pad;
  u8 dst_address[16];
  u8 *name;
} dns_pending_request_t;

typedef enum
{
  DNS_API_PENDING_NAME_TO_IP = 1,
  DNS_API_PENDING_IP_TO_NAME,
  DNS_PEER_PENDING_NAME_TO_IP,
  DNS_PEER_PENDING_IP_TO_NAME,
} dns_pending_request_type_t;

typedef struct
{
  /** flags */
  volatile u8 flags;

  /** The name in "normal human being" notation, e.g. www.foobar.com */
  u8 *name;

  /** For CNAME records, the "next name" to resolve */
  u8 *cname;

  /** Expiration time */
  f64 expiration_time;

  /** Cached dns request, for sending retries */
  u8 *dns_request;

  /** Retry parameters */
  int retry_count;
  int server_rotor;
  int server_af;
  int server_fails;
  f64 retry_timer;

  /** Cached dns response */
  u8 *dns_response;

  /** Clients / peers awaiting responses */
  dns_pending_request_t *pending_requests;
} dns_cache_entry_t;

#define DNS_CACHE_ENTRY_FLAG_VALID	(1<<0) /**< we have Actual Data */
#define DNS_CACHE_ENTRY_FLAG_STATIC	(1<<1) /**< static entry */
#define DNS_CACHE_ENTRY_FLAG_CNAME	(1<<2) /**< CNAME (indirect) entry */

#define DNS_RETRIES_PER_SERVER 3

#define DNS_RESOLVER_EVENT_RESOLVED	1
#define DNS_RESOLVER_EVENT_PENDING	2


typedef struct
{
  /** Pool of cache entries */
  dns_cache_entry_t *entries;

  /** Pool indices of unresolved entries */
  u32 *unresolved_entries;

  /** Find cached record by name */
  uword *cache_entry_by_name;
  uword *cache_lock;

  /** enable / disable flag */
  int is_enabled;

  /** udp port registration complete */
  int udp_ports_registered;

  /** upstream name servers, e.g. 8.8.8.8 */
  ip4_address_t *ip4_name_servers;
  ip6_address_t *ip6_name_servers;

  /** resolver process node index */
  u32 resolver_process_node_index;

  /** config parameters */
  u32 name_cache_size;
  u32 max_ttl_in_seconds;
  u32 random_seed;

  /* convenience */
  vlib_main_t *vlib_main;
  vnet_main_t *vnet_main;
} dns_main_t;

extern dns_main_t dns_main;

extern vlib_node_registration_t dns46_reply_node;
extern vlib_node_registration_t dns4_request_node;
extern vlib_node_registration_t dns6_request_node;
extern vlib_node_registration_t dns_resolver_node;

#define foreach_dns46_request_error                                     \
_(NONE, "No error")							\
_(UNIMPLEMENTED, "Unimplemented")                                       \
_(PROCESSED, "DNS request pkts processed")                              \
_(IP_OPTIONS, "DNS pkts with ip options (dropped)")                     \
_(BAD_REQUEST, "DNS pkts with serious discrepanices (dropped)")         \
_(TOO_MANY_REQUESTS, "DNS pkts asking too many questions")              \
_(RESOLUTION_REQUIRED, "DNS pkts pending upstream name resolution")

typedef enum
{
#define _(sym,str) DNS46_REQUEST_ERROR_##sym,
  foreach_dns46_request_error
#undef _
    DNS46_REQUEST_N_ERROR,
} dns46_request_error_t;

#define foreach_dns46_reply_error                       \
_(DISABLED, "DNS pkts punted (feature disabled)")       \
_(PROCESSED, "DNS reply pkts processed")                \
_(NO_ELT, "No DNS pool element")                        \
_(FORMAT_ERROR, "DNS format errors")                    \
_(TEST_DROP, "DNS reply pkt dropped for test purposes")

typedef enum
{
#define _(sym,str) DNS46_REPLY_ERROR_##sym,
  foreach_dns46_reply_error
#undef _
    DNS46_REPLY_N_ERROR,
} dns46_reply_error_t;

void vnet_send_dns_request (dns_main_t * dm, dns_cache_entry_t * ep);
int
vnet_dns_cname_indirection_nolock (dns_main_t * dm, u32 ep_index, u8 * reply);

int vnet_dns_delete_entry_by_index_nolock (dns_main_t * dm, u32 index);

int
vnet_dns_resolve_name (dns_main_t * dm, u8 * name, dns_pending_request_t * t,
		       dns_cache_entry_t ** retp);

void
vnet_dns_send_dns6_request (dns_main_t * dm,
			    dns_cache_entry_t * ep, ip6_address_t * server);
void
vnet_dns_send_dns4_request (dns_main_t * dm,
			    dns_cache_entry_t * ep, ip4_address_t * server);

void vnet_send_dns4_reply (dns_main_t * dm, dns_pending_request_t * t,
			   dns_cache_entry_t * ep, vlib_buffer_t * b0);

void vnet_send_dns6_reply (dns_main_t * dm, dns_pending_request_t * t,
			   dns_cache_entry_t * ep, vlib_buffer_t * b0);

u8 *vnet_dns_labels_to_name (u8 * label, u8 * full_text,
			     u8 ** parse_from_here);

void vnet_dns_create_resolver_process (dns_main_t * dm);

format_function_t format_dns_reply;

static inline void
dns_cache_lock (dns_main_t * dm)
{
  if (dm->cache_lock)
    {
      while (clib_atomic_test_and_set (dm->cache_lock))
	;
    }
}

static inline void
dns_cache_unlock (dns_main_t * dm)
{
  if (dm->cache_lock)
    {
      CLIB_MEMORY_BARRIER ();
      *dm->cache_lock = 0;
    }
}

#endif /* included_dns_h */

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */