]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - resolv/res_mkquery.c
hurd: Fix build
[thirdparty/glibc.git] / resolv / res_mkquery.c
index 505c3914a9cdc720ca8199d8fb42407cabca9133..dd43d347af1e0f0c3835c36f333b62d2ad91eec8 100644 (file)
@@ -1,6 +1,22 @@
+/* Creation of DNS query packets.
+   Copyright (C) 1995-2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
 /*
- * ++Copyright++ 1985, 1993
- * -
  * Copyright (c) 1985, 1993
  *    The Regents of the University of California.  All rights reserved.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -31,7 +43,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- * -
+ */
+
+/*
  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  * SOFTWARE.
- * -
- * --Copyright--
  */
 
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_mkquery.c      8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id$";
-#endif /* LIBC_SCCS and not lint */
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
 
+#include <stdint.h>
 #include <sys/types.h>
 #include <sys/param.h>
 #include <netinet/in.h>
 #include <arpa/nameser.h>
-
-#include <stdio.h>
 #include <netdb.h>
-#include <resolv.h>
-#if defined(BSD) && (BSD >= 199103)
-# include <string.h>
-#else
-# include "../conf/portability.h"
-#endif
+#include <resolv/resolv-internal.h>
+#include <resolv/resolv_context.h>
+#include <string.h>
+#include <sys/time.h>
+#include <shlib-compat.h>
+#include <random-bits.h>
 
-#if defined(USE_OPTIONS_H)
-# include <../conf/options.h>
-#endif
+int
+__res_context_mkquery (struct resolv_context *ctx, int op, const char *dname,
+                       int class, int type, const unsigned char *data,
+                       unsigned char *buf, int buflen)
+{
+  HEADER *hp;
+  unsigned char *cp;
+  int n;
+  unsigned char *dnptrs[20], **dpp, **lastdnptr;
 
-/*
- * Form all types of queries.
- * Returns the size of the result or -1.
- */
+  if (class < 0 || class > 65535 || type < 0 || type > 65535)
+    return -1;
+
+  /* Initialize header fields.  */
+  if ((buf == NULL) || (buflen < HFIXEDSZ))
+    return -1;
+  memset (buf, 0, HFIXEDSZ);
+  hp = (HEADER *) buf;
+  /* We randomize the IDs every time.  The old code just incremented
+     by one after the initial randomization which still predictable if
+     the application does multiple requests.  */
+  hp->id = random_bits ();
+  hp->opcode = op;
+  hp->rd = (ctx->resp->options & RES_RECURSE) != 0;
+  hp->rcode = NOERROR;
+  cp = buf + HFIXEDSZ;
+  buflen -= HFIXEDSZ;
+  dpp = dnptrs;
+  *dpp++ = buf;
+  *dpp++ = NULL;
+  lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
+
+  /* Perform opcode specific processing.  */
+  switch (op)
+    {
+    case NS_NOTIFY_OP:
+      if ((buflen -= QFIXEDSZ + (data == NULL ? 0 : RRFIXEDSZ)) < 0)
+        return -1;
+      goto compose;
+
+    case QUERY:
+      if ((buflen -= QFIXEDSZ) < 0)
+        return -1;
+    compose:
+      n = ns_name_compress (dname, cp, buflen,
+                            (const unsigned char **) dnptrs,
+                            (const unsigned char **) lastdnptr);
+      if (n < 0)
+        return -1;
+      cp += n;
+      buflen -= n;
+      NS_PUT16 (type, cp);
+      NS_PUT16 (class, cp);
+      hp->qdcount = htons (1);
+      if (op == QUERY || data == NULL)
+        break;
+
+      /* Make an additional record for completion domain.  */
+      n = ns_name_compress ((char *)data, cp, buflen,
+                            (const unsigned char **) dnptrs,
+                            (const unsigned char **) lastdnptr);
+      if (__glibc_unlikely (n < 0))
+        return -1;
+      cp += n;
+      buflen -= n;
+      NS_PUT16 (T_NULL, cp);
+      NS_PUT16 (class, cp);
+      NS_PUT32 (0, cp);
+      NS_PUT16 (0, cp);
+      hp->arcount = htons (1);
+      break;
+
+    default:
+      return -1;
+    }
+  return cp - buf;
+}
+
+/* Common part of res_nmkquery and res_mkquery.  */
+static int
+context_mkquery_common (struct resolv_context *ctx,
+                        int op, const char *dname, int class, int type,
+                        const unsigned char *data,
+                        unsigned char *buf, int buflen)
+{
+  if (ctx == NULL)
+    return -1;
+  int result = __res_context_mkquery
+    (ctx, op, dname, class, type, data, buf, buflen);
+  if (result >= 2)
+    memcpy (&ctx->resp->id, buf, 2);
+  __resolv_context_put (ctx);
+  return result;
+}
+
+/* Form all types of queries.  Returns the size of the result or -1 on
+   error.
+
+   STATP points to an initialized resolver state.  OP is the opcode of
+   the query.  DNAME is the domain.  CLASS and TYPE are the DNS query
+   class and type.  DATA can be NULL; otherwise, it is a pointer to a
+   domain name which is included in the generated packet (if op ==
+   NS_NOTIFY_OP).  BUF must point to the out buffer of BUFLEN bytes.
+
+   DATALEN and NEWRR_IN are currently ignored.  */
 int
-res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
-       int op;                 /* opcode of query */
-       const char *dname;      /* domain name */
-       int class, type;        /* class and type of query */
-       const u_char *data;     /* resource record data */
-       int datalen;            /* length of data */
-       const u_char *newrr_in; /* new rr for modify or append */
-       u_char *buf;            /* buffer to put query */
-       int buflen;             /* size of buffer */
+res_nmkquery (res_state statp, int op, const char *dname,
+              int class, int type,
+              const unsigned char *data, int datalen,
+              const unsigned char *newrr_in,
+              unsigned char *buf, int buflen)
 {
-       register HEADER *hp;
-       register u_char *cp;
-       register int n;
-       u_char *dnptrs[20], **dpp, **lastdnptr;
-
-       if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
-               h_errno = NETDB_INTERNAL;
-               return (-1);
-       }
-#ifdef DEBUG
-       if (_res.options & RES_DEBUG)
-               printf(";; res_mkquery(%d, %s, %d, %d)\n",
-                      op, dname, class, type);
-#endif
-       /*
-        * Initialize header fields.
-        */
-       if ((buf == NULL) || (buflen < HFIXEDSZ))
-               return (-1);
-       bzero(buf, HFIXEDSZ);
-       hp = (HEADER *) buf;
-       hp->id = htons(++_res.id);
-       hp->opcode = op;
-       hp->rd = (_res.options & RES_RECURSE) != 0;
-       hp->rcode = NOERROR;
-       cp = buf + HFIXEDSZ;
-       buflen -= HFIXEDSZ;
-       dpp = dnptrs;
-       *dpp++ = buf;
-       *dpp++ = NULL;
-       lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
-       /*
-        * perform opcode specific processing
-        */
-       switch (op) {
-       case QUERY:     /*FALLTHROUGH*/
-       case NS_NOTIFY_OP:
-               if ((buflen -= QFIXEDSZ) < 0)
-                       return (-1);
-               if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
-                       return (-1);
-               cp += n;
-               buflen -= n;
-               __putshort(type, cp);
-               cp += INT16SZ;
-               __putshort(class, cp);
-               cp += INT16SZ;
-               hp->qdcount = htons(1);
-               if (op == QUERY || data == NULL)
-                       break;
-               /*
-                * Make an additional record for completion domain.
-                */
-               buflen -= RRFIXEDSZ;
-               n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr);
-               if (n < 0)
-                       return (-1);
-               cp += n;
-               buflen -= n;
-               __putshort(T_NULL, cp);
-               cp += INT16SZ;
-               __putshort(class, cp);
-               cp += INT16SZ;
-               __putlong(0, cp);
-               cp += INT32SZ;
-               __putshort(0, cp);
-               cp += INT16SZ;
-               hp->arcount = htons(1);
-               break;
-
-       case IQUERY:
-               /*
-                * Initialize answer section
-                */
-               if (buflen < 1 + RRFIXEDSZ + datalen)
-                       return (-1);
-               *cp++ = '\0';   /* no domain name */
-               __putshort(type, cp);
-               cp += INT16SZ;
-               __putshort(class, cp);
-               cp += INT16SZ;
-               __putlong(0, cp);
-               cp += INT32SZ;
-               __putshort(datalen, cp);
-               cp += INT16SZ;
-               if (datalen) {
-                       bcopy(data, cp, datalen);
-                       cp += datalen;
-               }
-               hp->ancount = htons(1);
-               break;
-
-       default:
-               return (-1);
-       }
-       return (cp - buf);
+  return context_mkquery_common
+    (__resolv_context_get_override (statp),
+     op, dname, class, type, data, buf, buflen);
+}
+
+int
+res_mkquery (int op, const char *dname, int class, int type,
+             const unsigned char *data, int datalen,
+             const unsigned char *newrr_in,
+             unsigned char *buf, int buflen)
+{
+  return context_mkquery_common
+    (__resolv_context_get_preinit (),
+     op, dname, class, type, data, buf, buflen);
+}
+
+/* Create an OPT resource record.  Return the length of the final
+   packet, or -1 on error.
+
+   STATP must be an initialized resolver state.  N0 is the current
+   number of bytes of the packet (already written to BUF by the
+   aller).  BUF is the packet being constructed.  The array it
+   pointers to must be BUFLEN bytes long.  ANSLEN is the advertised
+   EDNS buffer size (to be included in the OPT resource record).  */
+int
+__res_nopt (struct resolv_context *ctx,
+            int n0, unsigned char *buf, int buflen, int anslen)
+{
+  uint16_t flags = 0;
+  HEADER *hp = (HEADER *) buf;
+  unsigned char *cp = buf + n0;
+  unsigned char *ep = buf + buflen;
+
+  if ((ep - cp) < 1 + RRFIXEDSZ)
+    return -1;
+
+  /* Add the root label.  */
+  *cp++ = 0;
+
+  NS_PUT16 (T_OPT, cp);         /* Record type.  */
+
+  /* Lowering the advertised buffer size based on the actual
+     answer buffer size is desirable because the server will
+     minimize the reply to fit into the UDP packet (and A
+     non-minimal response might not fit the buffer).
+
+     The RESOLV_EDNS_BUFFER_SIZE limit could still result in TCP
+     fallback and a non-minimal response which has to be
+     hard-truncated in the stub resolver, but this is price to
+     pay for avoiding fragmentation.  (This issue does not
+     affect the nss_dns functions because they use the stub
+     resolver in such a way that it allocates a properly sized
+     response buffer.)  */
+  {
+    uint16_t buffer_size;
+    if (anslen < 512)
+      buffer_size = 512;
+    else if (anslen > RESOLV_EDNS_BUFFER_SIZE)
+      buffer_size = RESOLV_EDNS_BUFFER_SIZE;
+    else
+      buffer_size = anslen;
+    NS_PUT16 (buffer_size, cp);
+  }
+
+  *cp++ = NOERROR;              /* Extended RCODE.  */
+  *cp++ = 0;                    /* EDNS version.  */
+
+  if (ctx->resp->options & RES_USE_DNSSEC)
+    flags |= NS_OPT_DNSSEC_OK;
+
+  NS_PUT16 (flags, cp);
+  NS_PUT16 (0, cp);       /* RDATA length (no options are preent).  */
+  hp->arcount = htons (ntohs (hp->arcount) + 1);
+
+  return cp - buf;
 }
+
+#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_2)
+# undef res_mkquery
+weak_alias (__res_mkquery, res_mkquery);
+#endif