/*-1* SPDX-License-Identifier: (ISC AND BSD-3-Clause)2*3* Portions Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")4* Portions Copyright (C) 1996, 1997, 1988, 1999, 2001, 2003 Internet Software Consortium.5*6* Permission to use, copy, modify, and/or distribute this software for any7* purpose with or without fee is hereby granted, provided that the above8* copyright notice and this permission notice appear in all copies.9*10* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH11* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY12* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,13* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM14* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE15* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR16* PERFORMANCE OF THIS SOFTWARE.17*/1819/*-20* Copyright (c) 1985, 199321* The Regents of the University of California. All rights reserved.22*23* Redistribution and use in source and binary forms, with or without24* modification, are permitted provided that the following conditions25* are met:26* 1. Redistributions of source code must retain the above copyright27* notice, this list of conditions and the following disclaimer.28* 2. Redistributions in binary form must reproduce the above copyright29* notice, this list of conditions and the following disclaimer in the30* documentation and/or other materials provided with the distribution.31* 3. Neither the name of the University nor the names of its contributors32* may be used to endorse or promote products derived from this software33* without specific prior written permission.34*35* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND36* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE37* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE38* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE39* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL40* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS41* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)42* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT43* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY44* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF45* SUCH DAMAGE.46*/4748/*49* Portions Copyright (c) 1993 by Digital Equipment Corporation.50*51* Permission to use, copy, modify, and distribute this software for any52* purpose with or without fee is hereby granted, provided that the above53* copyright notice and this permission notice appear in all copies, and that54* the name of Digital Equipment Corporation not be used in advertising or55* publicity pertaining to distribution of the document or software without56* specific, written prior permission.57*58* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL59* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES60* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT61* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL62* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR63* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS64* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS65* SOFTWARE.66*/6768#include "port_before.h"69#include <sys/param.h>70#include <netinet/in.h>71#include <arpa/nameser.h>72#include <netdb.h>73#include <resolv.h>74#include <stdio.h>75#include <string.h>76#include "port_after.h"7778extern const char *_res_opcodes[];7980/*%81* Form all types of queries.82* Returns the size of the result or -1.83*/84int85res_nmkquery(res_state statp,86int op, /*!< opcode of query */87const char *dname, /*!< domain name */88int class, int type, /*!< class and type of query */89const u_char *data, /*!< resource record data */90int datalen, /*!< length of data */91const u_char *newrr_in, /*!< new rr for modify or append */92u_char *buf, /*!< buffer to put query */93int buflen) /*!< size of buffer */94{95HEADER *hp;96u_char *cp, *ep;97int n;98u_char *dnptrs[20], **dpp, **lastdnptr;99100UNUSED(newrr_in);101102#ifdef DEBUG103if (statp->options & RES_DEBUG)104printf(";; res_nmkquery(%s, %s, %s, %s)\n",105_res_opcodes[op], dname, p_class(class), p_type(type));106#endif107/*108* Initialize header fields.109*/110if ((buf == NULL) || (buflen < HFIXEDSZ))111return (-1);112memset(buf, 0, HFIXEDSZ);113hp = (HEADER *) buf;114statp->id = res_nrandomid(statp);115hp->id = htons(statp->id);116hp->opcode = op;117hp->rd = (statp->options & RES_RECURSE) != 0U;118hp->rcode = NOERROR;119cp = buf + HFIXEDSZ;120ep = buf + buflen;121dpp = dnptrs;122*dpp++ = buf;123*dpp++ = NULL;124lastdnptr = dnptrs + nitems(dnptrs);125/*126* perform opcode specific processing127*/128switch (op) {129case QUERY: /*FALLTHROUGH*/130case NS_NOTIFY_OP:131if (ep - cp < QFIXEDSZ)132return (-1);133if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs,134lastdnptr)) < 0)135return (-1);136cp += n;137ns_put16(type, cp);138cp += INT16SZ;139ns_put16(class, cp);140cp += INT16SZ;141hp->qdcount = htons(1);142if (op == QUERY || data == NULL)143break;144/*145* Make an additional record for completion domain.146*/147if ((ep - cp) < RRFIXEDSZ)148return (-1);149n = dn_comp((const char *)data, cp, ep - cp - RRFIXEDSZ,150dnptrs, lastdnptr);151if (n < 0)152return (-1);153cp += n;154ns_put16(T_NULL, cp);155cp += INT16SZ;156ns_put16(class, cp);157cp += INT16SZ;158ns_put32(0, cp);159cp += INT32SZ;160ns_put16(0, cp);161cp += INT16SZ;162hp->arcount = htons(1);163break;164165case IQUERY:166/*167* Initialize answer section168*/169if (ep - cp < 1 + RRFIXEDSZ + datalen)170return (-1);171*cp++ = '\0'; /*%< no domain name */172ns_put16(type, cp);173cp += INT16SZ;174ns_put16(class, cp);175cp += INT16SZ;176ns_put32(0, cp);177cp += INT32SZ;178ns_put16(datalen, cp);179cp += INT16SZ;180if (datalen) {181memcpy(cp, data, datalen);182cp += datalen;183}184hp->ancount = htons(1);185break;186187default:188return (-1);189}190return (cp - buf);191}192193#ifdef RES_USE_EDNS0194/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */195196int197res_nopt(res_state statp,198int n0, /*%< current offset in buffer */199u_char *buf, /*%< buffer to put query */200int buflen, /*%< size of buffer */201int anslen) /*%< UDP answer buffer size */202{203HEADER *hp;204u_char *cp, *ep;205u_int16_t flags = 0;206207#ifdef DEBUG208if ((statp->options & RES_DEBUG) != 0U)209printf(";; res_nopt()\n");210#endif211212hp = (HEADER *) buf;213cp = buf + n0;214ep = buf + buflen;215216if ((ep - cp) < 1 + RRFIXEDSZ)217return (-1);218219*cp++ = 0; /*%< "." */220ns_put16(ns_t_opt, cp); /*%< TYPE */221cp += INT16SZ;222if (anslen > 0xffff)223anslen = 0xffff; /* limit to 16bit value */224ns_put16(anslen & 0xffff, cp); /*%< CLASS = UDP payload size */225cp += INT16SZ;226*cp++ = NOERROR; /*%< extended RCODE */227*cp++ = 0; /*%< EDNS version */228229if (statp->options & RES_USE_DNSSEC) {230#ifdef DEBUG231if (statp->options & RES_DEBUG)232printf(";; res_opt()... ENDS0 DNSSEC\n");233#endif234flags |= NS_OPT_DNSSEC_OK;235}236ns_put16(flags, cp);237cp += INT16SZ;238239ns_put16(0U, cp); /*%< RDLEN */240cp += INT16SZ;241242hp->arcount = htons(ntohs(hp->arcount) + 1);243244return (cp - buf);245}246247/*248* Construct variable data (RDATA) block for OPT pseudo-RR, append it249* to the buffer, then update the RDLEN field (previously set to zero by250* res_nopt()) with the new RDATA length.251*/252int253res_nopt_rdata(res_state statp,254int n0, /*%< current offset in buffer */255u_char *buf, /*%< buffer to put query */256int buflen, /*%< size of buffer */257u_char *rdata, /*%< ptr to start of opt rdata */258u_short code, /*%< OPTION-CODE */259u_short len, /*%< OPTION-LENGTH */260u_char *data) /*%< OPTION_DATA */261{262register u_char *cp, *ep;263264#ifdef DEBUG265if ((statp->options & RES_DEBUG) != 0U)266printf(";; res_nopt_rdata()\n");267#endif268269cp = buf + n0;270ep = buf + buflen;271272if ((ep - cp) < (4 + len))273return (-1);274275if (rdata < (buf + 2) || rdata >= ep)276return (-1);277278ns_put16(code, cp);279cp += INT16SZ;280281ns_put16(len, cp);282cp += INT16SZ;283284memcpy(cp, data, len);285cp += len;286287len = cp - rdata;288ns_put16(len, rdata - 2); /* Update RDLEN field */289290return (cp - buf);291}292#endif293294/*! \file */295296297