LCOV - code coverage report
Current view: top level - plugins/dns - request_node.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 69 88 78.4 %
Date: 2023-07-05 22:20:52 Functions: 7 8 87.5 %

          Line data    Source code
       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 <dns/dns.h>
      17             : 
      18             : #include <vlib/vlib.h>
      19             : #include <vnet/vnet.h>
      20             : 
      21             : vlib_node_registration_t dns46_request_node;
      22             : 
      23             : typedef struct
      24             : {
      25             :   u32 pool_index;
      26             :   u32 disposition;
      27             : } dns46_request_trace_t;
      28             : 
      29             : /* packet trace format function */
      30             : static u8 *
      31           1 : format_dns46_request_trace (u8 * s, va_list * args)
      32             : {
      33           1 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
      34           1 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
      35           1 :   dns46_request_trace_t *t = va_arg (*args, dns46_request_trace_t *);
      36             : 
      37           1 :   s = format (s, "DNS46_REPLY: pool index %d, disposition  %d",
      38             :               t->pool_index, t->disposition);
      39           1 :   return s;
      40             : }
      41             : 
      42             : vlib_node_registration_t dns46_request_node;
      43             : 
      44             : static char *dns46_request_error_strings[] = {
      45             : #define _(sym,string) string,
      46             :   foreach_dns46_request_error
      47             : #undef _
      48             : };
      49             : 
      50             : typedef enum
      51             : {
      52             :   DNS46_REQUEST_NEXT_DROP,
      53             :   DNS46_REQUEST_NEXT_IP_LOOKUP,
      54             :   DNS46_REQUEST_NEXT_PUNT,
      55             :   DNS46_REQUEST_N_NEXT,
      56             : } dns46_request_next_t;
      57             : 
      58             : static uword
      59           1 : dns46_request_inline (vlib_main_t * vm,
      60             :                       vlib_node_runtime_t * node, vlib_frame_t * frame,
      61             :                       int is_ip6)
      62             : {
      63             :   u32 n_left_from, *from, *to_next;
      64             :   dns46_request_next_t next_index;
      65           1 :   dns_main_t *dm = &dns_main;
      66             : 
      67           1 :   from = vlib_frame_vector_args (frame);
      68           1 :   n_left_from = frame->n_vectors;
      69           1 :   next_index = node->cached_next_index;
      70             : 
      71           2 :   while (n_left_from > 0)
      72             :     {
      73             :       u32 n_left_to_next;
      74             : 
      75           1 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
      76             : 
      77             : #if 0
      78             :       while (n_left_from >= 4 && n_left_to_next >= 2)
      79             :         {
      80             :           u32 next0 = DNS46_REQUEST_NEXT_INTERFACE_OUTPUT;
      81             :           u32 next1 = DNS46_REQUEST_NEXT_INTERFACE_OUTPUT;
      82             :           u32 sw_if_index0, sw_if_index1;
      83             :           u8 tmp0[6], tmp1[6];
      84             :           ethernet_header_t *en0, *en1;
      85             :           u32 bi0, bi1;
      86             :           vlib_buffer_t *b0, *b1;
      87             : 
      88             :           /* Prefetch next iteration. */
      89             :           {
      90             :             vlib_buffer_t *p2, *p3;
      91             : 
      92             :             p2 = vlib_get_buffer (vm, from[2]);
      93             :             p3 = vlib_get_buffer (vm, from[3]);
      94             : 
      95             :             vlib_prefetch_buffer_header (p2, LOAD);
      96             :             vlib_prefetch_buffer_header (p3, LOAD);
      97             : 
      98             :             clib_prefetch_store (p2->data);
      99             :             clib_prefetch_store (p3->data);
     100             :           }
     101             : 
     102             :           /* speculatively enqueue b0 and b1 to the current next frame */
     103             :           to_next[0] = bi0 = from[0];
     104             :           to_next[1] = bi1 = from[1];
     105             :           from += 2;
     106             :           to_next += 2;
     107             :           n_left_from -= 2;
     108             :           n_left_to_next -= 2;
     109             : 
     110             :           b0 = vlib_get_buffer (vm, bi0);
     111             :           b1 = vlib_get_buffer (vm, bi1);
     112             : 
     113             :           /* $$$$$ End of processing 2 x packets $$$$$ */
     114             : 
     115             :           if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
     116             :             {
     117             :               if (b0->flags & VLIB_BUFFER_IS_TRACED)
     118             :                 {
     119             :                   dns46_request_trace_t *t =
     120             :                     vlib_add_trace (vm, node, b0, sizeof (*t));
     121             :                   t->sw_if_index = sw_if_index0;
     122             :                   t->next_index = next0;
     123             :                 }
     124             :               if (b1->flags & VLIB_BUFFER_IS_TRACED)
     125             :                 {
     126             :                   dns46_request_trace_t *t =
     127             :                     vlib_add_trace (vm, node, b1, sizeof (*t));
     128             :                   t->sw_if_index = sw_if_index1;
     129             :                   t->next_index = next1;
     130             :                 }
     131             :             }
     132             : 
     133             :           /* verify speculative enqueues, maybe switch current next frame */
     134             :           vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
     135             :                                            to_next, n_left_to_next,
     136             :                                            bi0, bi1, next0, next1);
     137             :         }
     138             : #endif
     139             : 
     140           3 :       while (n_left_from > 0 && n_left_to_next > 0)
     141             :         {
     142             :           u32 bi0;
     143             :           vlib_buffer_t *b0;
     144           2 :           u32 next0 = DNS46_REQUEST_NEXT_DROP;
     145           2 :           u32 error0 = DNS46_REQUEST_ERROR_NONE;
     146             :           udp_header_t *u0;
     147             :           dns_header_t *d0;
     148             :           dns_query_t *q0;
     149           2 :           ip4_header_t *ip40 = 0;
     150           2 :           ip6_header_t *ip60 = 0;
     151             :           dns_cache_entry_t *ep0;
     152           2 :           dns_pending_request_t _t0, *t0 = &_t0;
     153             :           u16 flags0;
     154           2 :           u32 pool_index0 = ~0;
     155             :           u8 *name0;
     156             :           u8 *label0;
     157             : 
     158             :           /* speculatively enqueue b0 to the current next frame */
     159           2 :           bi0 = from[0];
     160           2 :           to_next[0] = bi0;
     161           2 :           from += 1;
     162           2 :           to_next += 1;
     163           2 :           n_left_from -= 1;
     164           2 :           n_left_to_next -= 1;
     165             : 
     166           2 :           b0 = vlib_get_buffer (vm, bi0);
     167           2 :           d0 = vlib_buffer_get_current (b0);
     168           2 :           u0 = (udp_header_t *) ((u8 *) d0 - sizeof (*u0));
     169             : 
     170           2 :           if (PREDICT_FALSE (dm->is_enabled == 0))
     171             :             {
     172           0 :               next0 = DNS46_REQUEST_NEXT_PUNT;
     173           0 :               goto done0;
     174             :             }
     175             : 
     176           2 :           if (is_ip6)
     177             :             {
     178           0 :               ip60 = (ip6_header_t *) (((u8 *) u0) - sizeof (ip6_header_t));
     179           0 :               next0 = DNS46_REQUEST_NEXT_DROP;
     180           0 :               error0 = DNS46_REQUEST_ERROR_UNIMPLEMENTED;
     181           0 :               goto done0;
     182             :             }
     183             :           else
     184             :             {
     185           2 :               ip40 = (ip4_header_t *) (((u8 *) u0) - sizeof (ip4_header_t));
     186           2 :               if (ip40->ip_version_and_header_length != 0x45)
     187             :                 {
     188           0 :                   error0 = DNS46_REQUEST_ERROR_IP_OPTIONS;
     189           0 :                   goto done0;
     190             :                 }
     191             :             }
     192             :           /* Parse through the DNS request */
     193           2 :           flags0 = clib_net_to_host_u16 (d0->flags);
     194             : 
     195             :           /* Requests only */
     196           2 :           if (flags0 & DNS_QR)
     197             :             {
     198           0 :               next0 = DNS46_REQUEST_NEXT_DROP;
     199           0 :               error0 = DNS46_REQUEST_ERROR_BAD_REQUEST;
     200           0 :               goto done0;
     201             :             }
     202           2 :           if (clib_net_to_host_u16 (d0->qdcount) != 1)
     203             :             {
     204           0 :               next0 = DNS46_REQUEST_NEXT_DROP;
     205           0 :               error0 = DNS46_REQUEST_ERROR_TOO_MANY_REQUESTS;
     206           0 :               goto done0;
     207             :             }
     208             : 
     209           2 :           label0 = (u8 *) (d0 + 1);
     210             : 
     211           2 :           name0 = vnet_dns_labels_to_name (label0, (u8 *) d0, (u8 **) & q0);
     212             : 
     213           2 :           t0->request_type = DNS_PEER_PENDING_NAME_TO_IP;
     214             : 
     215             :           /*
     216             :            * See if this is a reverse lookup. Both ip4 and ip6 reverse
     217             :            * requests end with ".arpa"
     218             :            */
     219           2 :           if (PREDICT_TRUE (vec_len (name0) > 5))
     220             :             {
     221           2 :               u8 *aptr0 = name0 + vec_len (name0) - 5;
     222             : 
     223           2 :               if (!memcmp (aptr0, ".arpa", 5))
     224           0 :                 t0->request_type = DNS_PEER_PENDING_IP_TO_NAME;
     225             :             }
     226             : 
     227           2 :           t0->client_index = ~0;
     228           2 :           t0->is_ip6 = is_ip6;
     229           2 :           t0->dst_port = u0->src_port;
     230           2 :           t0->id = d0->id;
     231           2 :           t0->name = name0;
     232           2 :           if (is_ip6)
     233           0 :             clib_memcpy_fast (t0->dst_address, ip60->src_address.as_u8,
     234             :                               sizeof (ip6_address_t));
     235             :           else
     236           2 :             clib_memcpy_fast (t0->dst_address, ip40->src_address.as_u8,
     237             :                               sizeof (ip4_address_t));
     238             : 
     239             :           /*
     240             :            * vnet_dns_labels_to_name produces a non NULL terminated vector
     241             :            * vnet_dns_resolve_name expects a C-string.
     242             :            */
     243           2 :           vec_add1 (name0, 0);
     244           2 :           vnet_dns_resolve_name (vm, dm, name0, t0, &ep0);
     245             : 
     246           2 :           if (ep0)
     247             :             {
     248           1 :               if (is_ip6)
     249           0 :                 vnet_send_dns6_reply (vm, dm, t0, ep0, b0);
     250             :               else
     251           1 :                 vnet_send_dns4_reply (vm, dm, t0, ep0, b0);
     252           1 :               next0 = DNS46_REQUEST_NEXT_IP_LOOKUP;
     253             :             }
     254             :           else
     255             :             {
     256           1 :               error0 = DNS46_REQUEST_ERROR_RESOLUTION_REQUIRED;
     257             :             }
     258             : 
     259           2 :         done0:
     260           2 :           b0->error = node->errors[error0];
     261             : 
     262           2 :           if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
     263             :                              && (b0->flags & VLIB_BUFFER_IS_TRACED)))
     264             :             {
     265             :               dns46_request_trace_t *t =
     266           1 :                 vlib_add_trace (vm, node, b0, sizeof (*t));
     267           1 :               t->disposition = error0;
     268           1 :               t->pool_index = pool_index0;
     269             :             }
     270             : 
     271             :           /* verify speculative enqueue, maybe switch current next frame */
     272           2 :           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
     273             :                                            to_next, n_left_to_next,
     274             :                                            bi0, next0);
     275             :         }
     276             : 
     277           1 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     278             :     }
     279             : 
     280           1 :   return frame->n_vectors;
     281             : }
     282             : 
     283             : static uword
     284           1 : dns4_request_node_fn (vlib_main_t * vm,
     285             :                       vlib_node_runtime_t * node, vlib_frame_t * frame)
     286             : {
     287             : 
     288           1 :   return dns46_request_inline (vm, node, frame, 0 /* is_ip6 */ );
     289             : }
     290             : 
     291             : /* *INDENT-OFF* */
     292      146760 : VLIB_REGISTER_NODE (dns4_request_node) =
     293             : {
     294             :   .function = dns4_request_node_fn,
     295             :   .name = "dns4-request",
     296             :   .vector_size = sizeof (u32),
     297             :   .format_trace = format_dns46_request_trace,
     298             :   .type = VLIB_NODE_TYPE_INTERNAL,
     299             :   .n_errors = ARRAY_LEN (dns46_request_error_strings),
     300             :   .error_strings = dns46_request_error_strings,
     301             :   .n_next_nodes = DNS46_REQUEST_N_NEXT,
     302             :   .next_nodes = {
     303             :     [DNS46_REQUEST_NEXT_DROP] = "error-drop",
     304             :     [DNS46_REQUEST_NEXT_PUNT] = "error-punt",
     305             :     [DNS46_REQUEST_NEXT_IP_LOOKUP] = "ip4-lookup",
     306             :   },
     307             : };
     308             : /* *INDENT-ON* */
     309             : 
     310             : static uword
     311           0 : dns6_request_node_fn (vlib_main_t * vm,
     312             :                       vlib_node_runtime_t * node, vlib_frame_t * frame)
     313             : {
     314             : 
     315           0 :   return dns46_request_inline (vm, node, frame, 1 /* is_ip6 */ );
     316             : }
     317             : 
     318             : /* *INDENT-OFF* */
     319      146760 : VLIB_REGISTER_NODE (dns6_request_node) =
     320             : {
     321             :   .function = dns6_request_node_fn,
     322             :   .name = "dns6-request",
     323             :   .vector_size = sizeof (u32),
     324             :   .format_trace = format_dns46_request_trace,
     325             :   .type = VLIB_NODE_TYPE_INTERNAL,
     326             :   .n_errors = ARRAY_LEN (dns46_request_error_strings),
     327             :   .error_strings = dns46_request_error_strings,
     328             :   .n_next_nodes = DNS46_REQUEST_N_NEXT,
     329             :   .next_nodes = {
     330             :     [DNS46_REQUEST_NEXT_DROP] = "error-drop",
     331             :     [DNS46_REQUEST_NEXT_PUNT] = "error-punt",
     332             :     [DNS46_REQUEST_NEXT_IP_LOOKUP] = "ip6-lookup",
     333             :   },
     334             : };
     335             : /* *INDENT-ON* */
     336             : 
     337             : /*
     338             :  * fd.io coding-style-patch-verification: ON
     339             :  *
     340             :  * Local Variables:
     341             :  * eval: (c-set-style "gnu")
     342             :  * End:
     343             :  */

Generated by: LCOV version 1.14