Blame resolv/res_mkquery.c

Packit Service 82fcde
/* Creation of DNS query packets.
Packit Service 82fcde
   Copyright (C) 1995-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * Copyright (c) 1985, 1993
Packit Service 82fcde
 *    The Regents of the University of California.  All rights reserved.
Packit Service 82fcde
 *
Packit Service 82fcde
 * Redistribution and use in source and binary forms, with or without
Packit Service 82fcde
 * modification, are permitted provided that the following conditions
Packit Service 82fcde
 * are met:
Packit Service 82fcde
 * 1. Redistributions of source code must retain the above copyright
Packit Service 82fcde
 *    notice, this list of conditions and the following disclaimer.
Packit Service 82fcde
 * 2. Redistributions in binary form must reproduce the above copyright
Packit Service 82fcde
 *    notice, this list of conditions and the following disclaimer in the
Packit Service 82fcde
 *    documentation and/or other materials provided with the distribution.
Packit Service 82fcde
 * 4. Neither the name of the University nor the names of its contributors
Packit Service 82fcde
 *    may be used to endorse or promote products derived from this software
Packit Service 82fcde
 *    without specific prior written permission.
Packit Service 82fcde
 *
Packit Service 82fcde
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
Packit Service 82fcde
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit Service 82fcde
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit Service 82fcde
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
Packit Service 82fcde
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit Service 82fcde
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
Packit Service 82fcde
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Packit Service 82fcde
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
Packit Service 82fcde
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
Packit Service 82fcde
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
Packit Service 82fcde
 * SUCH DAMAGE.
Packit Service 82fcde
 */
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
Packit Service 82fcde
 *
Packit Service 82fcde
 * Permission to use, copy, modify, and distribute this software for any
Packit Service 82fcde
 * purpose with or without fee is hereby granted, provided that the above
Packit Service 82fcde
 * copyright notice and this permission notice appear in all copies, and that
Packit Service 82fcde
 * the name of Digital Equipment Corporation not be used in advertising or
Packit Service 82fcde
 * publicity pertaining to distribution of the document or software without
Packit Service 82fcde
 * specific, written prior permission.
Packit Service 82fcde
 *
Packit Service 82fcde
 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
Packit Service 82fcde
 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
Packit Service 82fcde
 * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
Packit Service 82fcde
 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
Packit Service 82fcde
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
Packit Service 82fcde
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
Packit Service 82fcde
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
Packit Service 82fcde
 * SOFTWARE.
Packit Service 82fcde
 */
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
Packit Service 82fcde
 *
Packit Service 82fcde
 * Permission to use, copy, modify, and distribute this software for any
Packit Service 82fcde
 * purpose with or without fee is hereby granted, provided that the above
Packit Service 82fcde
 * copyright notice and this permission notice appear in all copies.
Packit Service 82fcde
 *
Packit Service 82fcde
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
Packit Service 82fcde
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
Packit Service 82fcde
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
Packit Service 82fcde
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
Packit Service 82fcde
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
Packit Service 82fcde
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
Packit Service 82fcde
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
Packit Service 82fcde
 * SOFTWARE.
Packit Service 82fcde
 */
Packit Service 82fcde
Packit Service 82fcde
#include <sys/types.h>
Packit Service 82fcde
#include <sys/param.h>
Packit Service 82fcde
#include <netinet/in.h>
Packit Service 82fcde
#include <arpa/nameser.h>
Packit Service 82fcde
#include <netdb.h>
Packit Service 82fcde
#include <resolv/resolv-internal.h>
Packit Service 82fcde
#include <resolv/resolv_context.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
#include <sys/time.h>
Packit Service 82fcde
#include <shlib-compat.h>
Packit Service 82fcde
Packit Service 82fcde
#include <hp-timing.h>
Packit Service 82fcde
#include <stdint.h>
Packit Service 82fcde
#if HP_TIMING_AVAIL
Packit Service 82fcde
# define RANDOM_BITS(Var) { uint64_t v64; HP_TIMING_NOW (v64); Var = v64; }
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
int
Packit Service 82fcde
__res_context_mkquery (struct resolv_context *ctx, int op, const char *dname,
Packit Service 82fcde
                       int class, int type, const unsigned char *data,
Packit Service 82fcde
                       unsigned char *buf, int buflen)
Packit Service 82fcde
{
Packit Service 82fcde
  HEADER *hp;
Packit Service 82fcde
  unsigned char *cp;
Packit Service 82fcde
  int n;
Packit Service 82fcde
  unsigned char *dnptrs[20], **dpp, **lastdnptr;
Packit Service 82fcde
Packit Service 82fcde
  if (class < 0 || class > 65535 || type < 0 || type > 65535)
Packit Service 82fcde
    return -1;
Packit Service 82fcde
Packit Service 82fcde
  /* Initialize header fields.  */
Packit Service 82fcde
  if ((buf == NULL) || (buflen < HFIXEDSZ))
Packit Service 82fcde
    return -1;
Packit Service 82fcde
  memset (buf, 0, HFIXEDSZ);
Packit Service 82fcde
  hp = (HEADER *) buf;
Packit Service 82fcde
  /* We randomize the IDs every time.  The old code just incremented
Packit Service 82fcde
     by one after the initial randomization which still predictable if
Packit Service 82fcde
     the application does multiple requests.  */
Packit Service 82fcde
  int randombits;
Packit Service 82fcde
#ifdef RANDOM_BITS
Packit Service 82fcde
  RANDOM_BITS (randombits);
Packit Service 82fcde
#else
Packit Service 82fcde
  struct timeval tv;
Packit Service 82fcde
  __gettimeofday (&tv, NULL);
Packit Service 82fcde
  randombits = (tv.tv_sec << 8) ^ tv.tv_usec;
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
  hp->id = randombits;
Packit Service 82fcde
  hp->opcode = op;
Packit Service 82fcde
  hp->rd = (ctx->resp->options & RES_RECURSE) != 0;
Packit Service 82fcde
  hp->rcode = NOERROR;
Packit Service 82fcde
  cp = buf + HFIXEDSZ;
Packit Service 82fcde
  buflen -= HFIXEDSZ;
Packit Service 82fcde
  dpp = dnptrs;
Packit Service 82fcde
  *dpp++ = buf;
Packit Service 82fcde
  *dpp++ = NULL;
Packit Service 82fcde
  lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
Packit Service 82fcde
Packit Service 82fcde
  /* Perform opcode specific processing.  */
Packit Service 82fcde
  switch (op)
Packit Service 82fcde
    {
Packit Service 82fcde
    case NS_NOTIFY_OP:
Packit Service 82fcde
      if ((buflen -= QFIXEDSZ + (data == NULL ? 0 : RRFIXEDSZ)) < 0)
Packit Service 82fcde
        return -1;
Packit Service 82fcde
      goto compose;
Packit Service 82fcde
Packit Service 82fcde
    case QUERY:
Packit Service 82fcde
      if ((buflen -= QFIXEDSZ) < 0)
Packit Service 82fcde
        return -1;
Packit Service 82fcde
    compose:
Packit Service 82fcde
      n = ns_name_compress (dname, cp, buflen,
Packit Service 82fcde
                            (const unsigned char **) dnptrs,
Packit Service 82fcde
                            (const unsigned char **) lastdnptr);
Packit Service 82fcde
      if (n < 0)
Packit Service 82fcde
        return -1;
Packit Service 82fcde
      cp += n;
Packit Service 82fcde
      buflen -= n;
Packit Service 82fcde
      NS_PUT16 (type, cp);
Packit Service 82fcde
      NS_PUT16 (class, cp);
Packit Service 82fcde
      hp->qdcount = htons (1);
Packit Service 82fcde
      if (op == QUERY || data == NULL)
Packit Service 82fcde
        break;
Packit Service 82fcde
Packit Service 82fcde
      /* Make an additional record for completion domain.  */
Packit Service 82fcde
      n = ns_name_compress ((char *)data, cp, buflen,
Packit Service 82fcde
                            (const unsigned char **) dnptrs,
Packit Service 82fcde
                            (const unsigned char **) lastdnptr);
Packit Service 82fcde
      if (__glibc_unlikely (n < 0))
Packit Service 82fcde
        return -1;
Packit Service 82fcde
      cp += n;
Packit Service 82fcde
      buflen -= n;
Packit Service 82fcde
      NS_PUT16 (T_NULL, cp);
Packit Service 82fcde
      NS_PUT16 (class, cp);
Packit Service 82fcde
      NS_PUT32 (0, cp);
Packit Service 82fcde
      NS_PUT16 (0, cp);
Packit Service 82fcde
      hp->arcount = htons (1);
Packit Service 82fcde
      break;
Packit Service 82fcde
Packit Service 82fcde
    default:
Packit Service 82fcde
      return -1;
Packit Service 82fcde
    }
Packit Service 82fcde
  return cp - buf;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Common part of res_nmkquery and res_mkquery.  */
Packit Service 82fcde
static int
Packit Service 82fcde
context_mkquery_common (struct resolv_context *ctx,
Packit Service 82fcde
                        int op, const char *dname, int class, int type,
Packit Service 82fcde
                        const unsigned char *data,
Packit Service 82fcde
                        unsigned char *buf, int buflen)
Packit Service 82fcde
{
Packit Service 82fcde
  if (ctx == NULL)
Packit Service 82fcde
    return -1;
Packit Service 82fcde
  int result = __res_context_mkquery
Packit Service 82fcde
    (ctx, op, dname, class, type, data, buf, buflen);
Packit Service 82fcde
  if (result >= 2)
Packit Service 82fcde
    memcpy (&ctx->resp->id, buf, 2);
Packit Service 82fcde
  __resolv_context_put (ctx);
Packit Service 82fcde
  return result;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Form all types of queries.  Returns the size of the result or -1 on
Packit Service 82fcde
   error.
Packit Service 82fcde
Packit Service 82fcde
   STATP points to an initialized resolver state.  OP is the opcode of
Packit Service 82fcde
   the query.  DNAME is the domain.  CLASS and TYPE are the DNS query
Packit Service 82fcde
   class and type.  DATA can be NULL; otherwise, it is a pointer to a
Packit Service 82fcde
   domain name which is included in the generated packet (if op ==
Packit Service 82fcde
   NS_NOTIFY_OP).  BUF must point to the out buffer of BUFLEN bytes.
Packit Service 82fcde
Packit Service 82fcde
   DATALEN and NEWRR_IN are currently ignored.  */
Packit Service 82fcde
int
Packit Service 82fcde
res_nmkquery (res_state statp, int op, const char *dname,
Packit Service 82fcde
              int class, int type,
Packit Service 82fcde
              const unsigned char *data, int datalen,
Packit Service 82fcde
              const unsigned char *newrr_in,
Packit Service 82fcde
              unsigned char *buf, int buflen)
Packit Service 82fcde
{
Packit Service 82fcde
  return context_mkquery_common
Packit Service 82fcde
    (__resolv_context_get_override (statp),
Packit Service 82fcde
     op, dname, class, type, data, buf, buflen);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
int
Packit Service 82fcde
res_mkquery (int op, const char *dname, int class, int type,
Packit Service 82fcde
             const unsigned char *data, int datalen,
Packit Service 82fcde
             const unsigned char *newrr_in,
Packit Service 82fcde
             unsigned char *buf, int buflen)
Packit Service 82fcde
{
Packit Service 82fcde
  return context_mkquery_common
Packit Service 82fcde
    (__resolv_context_get_preinit (),
Packit Service 82fcde
     op, dname, class, type, data, buf, buflen);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Create an OPT resource record.  Return the length of the final
Packit Service 82fcde
   packet, or -1 on error.
Packit Service 82fcde
Packit Service 82fcde
   STATP must be an initialized resolver state.  N0 is the current
Packit Service 82fcde
   number of bytes of the packet (already written to BUF by the
Packit Service 82fcde
   aller).  BUF is the packet being constructed.  The array it
Packit Service 82fcde
   pointers to must be BUFLEN bytes long.  ANSLEN is the advertised
Packit Service 82fcde
   EDNS buffer size (to be included in the OPT resource record).  */
Packit Service 82fcde
int
Packit Service 82fcde
__res_nopt (struct resolv_context *ctx,
Packit Service 82fcde
            int n0, unsigned char *buf, int buflen, int anslen)
Packit Service 82fcde
{
Packit Service 82fcde
  uint16_t flags = 0;
Packit Service 82fcde
  HEADER *hp = (HEADER *) buf;
Packit Service 82fcde
  unsigned char *cp = buf + n0;
Packit Service 82fcde
  unsigned char *ep = buf + buflen;
Packit Service 82fcde
Packit Service 82fcde
  if ((ep - cp) < 1 + RRFIXEDSZ)
Packit Service 82fcde
    return -1;
Packit Service 82fcde
Packit Service 82fcde
  /* Add the root label.  */
Packit Service 82fcde
  *cp++ = 0;
Packit Service 82fcde
Packit Service 82fcde
  NS_PUT16 (T_OPT, cp);         /* Record type.  */
Packit Service 82fcde
Packit Service 82fcde
  /* Lowering the advertised buffer size based on the actual
Packit Service 82fcde
     answer buffer size is desirable because the server will
Packit Service 82fcde
     minimize the reply to fit into the UDP packet (and A
Packit Service 82fcde
     non-minimal response might not fit the buffer).
Packit Service 82fcde
Packit Service 82fcde
     The RESOLV_EDNS_BUFFER_SIZE limit could still result in TCP
Packit Service 82fcde
     fallback and a non-minimal response which has to be
Packit Service 82fcde
     hard-truncated in the stub resolver, but this is price to
Packit Service 82fcde
     pay for avoiding fragmentation.  (This issue does not
Packit Service 82fcde
     affect the nss_dns functions because they use the stub
Packit Service 82fcde
     resolver in such a way that it allocates a properly sized
Packit Service 82fcde
     response buffer.)  */
Packit Service 82fcde
  {
Packit Service 82fcde
    uint16_t buffer_size;
Packit Service 82fcde
    if (anslen < 512)
Packit Service 82fcde
      buffer_size = 512;
Packit Service 82fcde
    else if (anslen > RESOLV_EDNS_BUFFER_SIZE)
Packit Service 82fcde
      buffer_size = RESOLV_EDNS_BUFFER_SIZE;
Packit Service 82fcde
    else
Packit Service 82fcde
      buffer_size = anslen;
Packit Service 82fcde
    NS_PUT16 (buffer_size, cp);
Packit Service 82fcde
  }
Packit Service 82fcde
Packit Service 82fcde
  *cp++ = NOERROR;              /* Extended RCODE.  */
Packit Service 82fcde
  *cp++ = 0;                    /* EDNS version.  */
Packit Service 82fcde
Packit Service 82fcde
  if (ctx->resp->options & RES_USE_DNSSEC)
Packit Service 82fcde
    flags |= NS_OPT_DNSSEC_OK;
Packit Service 82fcde
Packit Service 82fcde
  NS_PUT16 (flags, cp);
Packit Service 82fcde
  NS_PUT16 (0, cp);       /* RDATA length (no options are preent).  */
Packit Service 82fcde
  hp->arcount = htons (ntohs (hp->arcount) + 1);
Packit Service 82fcde
Packit Service 82fcde
  return cp - buf;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_2)
Packit Service 82fcde
# undef res_mkquery
Packit Service 82fcde
weak_alias (__res_mkquery, res_mkquery);
Packit Service 82fcde
#endif