161023Skarels /*-
2*61151Sbostic * Copyright (c) 1985, 1993
3*61151Sbostic * The Regents of the University of California. All rights reserved.
433679Sbostic *
542627Sbostic * %sccs.include.redist.c%
661023Skarels * -
761023Skarels * Portions Copyright (c) 1993 by Digital Equipment Corporation.
861023Skarels *
961023Skarels * Permission to use, copy, modify, and distribute this software for any
1061023Skarels * purpose with or without fee is hereby granted, provided that the above
1161023Skarels * copyright notice and this permission notice appear in all copies, and that
1261023Skarels * the name of Digital Equipment Corporation not be used in advertising or
1361023Skarels * publicity pertaining to distribution of the document or software without
1461023Skarels * specific, written prior permission.
1561023Skarels *
1661023Skarels * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
1761023Skarels * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
1861023Skarels * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
1961023Skarels * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
2061023Skarels * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
2161023Skarels * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
2261023Skarels * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2361023Skarels * SOFTWARE.
2461023Skarels * -
2561023Skarels * --Copyright--
2618548Sralph */
2718548Sralph
2826634Sdonn #if defined(LIBC_SCCS) && !defined(lint)
29*61151Sbostic static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 06/04/93";
3061023Skarels static char rcsid[] = "$Id: res_mkquery.c,v 4.9.1.2 1993/05/17 10:00:01 vixie Exp $";
3133679Sbostic #endif /* LIBC_SCCS and not lint */
3221387Sdist
3345845Swilliam #include <sys/param.h>
3418143Sralph #include <netinet/in.h>
3524082Skjd #include <arpa/nameser.h>
3626895Skjd #include <resolv.h>
3746604Sbostic #include <stdio.h>
3846604Sbostic #include <string.h>
3918143Sralph
4018143Sralph /*
4118143Sralph * Form all types of queries.
4218143Sralph * Returns the size of the result or -1.
4318143Sralph */
res_mkquery(op,dname,class,type,data,datalen,newrr_in,buf,buflen)4461023Skarels res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
4518143Sralph int op; /* opcode of query */
4646604Sbostic const char *dname; /* domain name */
4718143Sralph int class, type; /* class and type of query */
4846604Sbostic const char *data; /* resource record data */
4918143Sralph int datalen; /* length of data */
5061023Skarels const char *newrr_in; /* new rr for modify or append */
5118143Sralph char *buf; /* buffer to put query */
5218143Sralph int buflen; /* size of buffer */
5318143Sralph {
5418143Sralph register HEADER *hp;
5518143Sralph register char *cp;
5618143Sralph register int n;
5761023Skarels struct rrec *newrr = (struct rrec *) newrr_in;
5818143Sralph char *dnptrs[10], **dpp, **lastdnptr;
5918143Sralph
6024734Sbloom #ifdef DEBUG
6118143Sralph if (_res.options & RES_DEBUG)
6261023Skarels printf(";; res_mkquery(%d, %s, %d, %d)\n",
6361023Skarels op, dname, class, type);
6461023Skarels #endif
6518143Sralph /*
6618143Sralph * Initialize header fields.
6718143Sralph */
6839789Sbloom if ((buf == NULL) || (buflen < sizeof(HEADER)))
6939789Sbloom return(-1);
7036322Skarels bzero(buf, sizeof(HEADER));
7118143Sralph hp = (HEADER *) buf;
7218143Sralph hp->id = htons(++_res.id);
7318143Sralph hp->opcode = op;
7418143Sralph hp->pr = (_res.options & RES_PRIMARY) != 0;
7518143Sralph hp->rd = (_res.options & RES_RECURSE) != 0;
7618143Sralph hp->rcode = NOERROR;
7718143Sralph cp = buf + sizeof(HEADER);
7818143Sralph buflen -= sizeof(HEADER);
7918143Sralph dpp = dnptrs;
8018143Sralph *dpp++ = buf;
8118143Sralph *dpp++ = NULL;
8218341Sralph lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
8318143Sralph /*
8418143Sralph * perform opcode specific processing
8518143Sralph */
8618143Sralph switch (op) {
8718143Sralph case QUERY:
8839789Sbloom if ((buflen -= QFIXEDSZ) < 0)
8939789Sbloom return(-1);
9046604Sbostic if ((n = dn_comp((u_char *)dname, (u_char *)cp, buflen,
9146604Sbostic (u_char **)dnptrs, (u_char **)lastdnptr)) < 0)
9218143Sralph return (-1);
9318143Sralph cp += n;
9418143Sralph buflen -= n;
9547045Sbostic __putshort(type, (u_char *)cp);
9661023Skarels cp += sizeof(u_int16_t);
9747045Sbostic __putshort(class, (u_char *)cp);
9861023Skarels cp += sizeof(u_int16_t);
9923872Skjd hp->qdcount = htons(1);
10018143Sralph if (op == QUERY || data == NULL)
10118143Sralph break;
10218143Sralph /*
10318143Sralph * Make an additional record for completion domain.
10418143Sralph */
10518528Sralph buflen -= RRFIXEDSZ;
10646604Sbostic if ((n = dn_comp((u_char *)data, (u_char *)cp, buflen,
10746604Sbostic (u_char **)dnptrs, (u_char **)lastdnptr)) < 0)
10818143Sralph return (-1);
10918143Sralph cp += n;
11018143Sralph buflen -= n;
11147045Sbostic __putshort(T_NULL, (u_char *)cp);
11261023Skarels cp += sizeof(u_int16_t);
11347045Sbostic __putshort(class, (u_char *)cp);
11461023Skarels cp += sizeof(u_int16_t);
11547045Sbostic __putlong(0, (u_char *)cp);
11661023Skarels cp += sizeof(u_int32_t);
11747045Sbostic __putshort(0, (u_char *)cp);
11861023Skarels cp += sizeof(u_int16_t);
11923872Skjd hp->arcount = htons(1);
12018143Sralph break;
12118143Sralph
12218143Sralph case IQUERY:
12318143Sralph /*
12418143Sralph * Initialize answer section
12518143Sralph */
12618143Sralph if (buflen < 1 + RRFIXEDSZ + datalen)
12718143Sralph return (-1);
12818143Sralph *cp++ = '\0'; /* no domain name */
12947045Sbostic __putshort(type, (u_char *)cp);
13061023Skarels cp += sizeof(u_int16_t);
13147045Sbostic __putshort(class, (u_char *)cp);
13261023Skarels cp += sizeof(u_int16_t);
13347045Sbostic __putlong(0, (u_char *)cp);
13461023Skarels cp += sizeof(u_int32_t);
13547045Sbostic __putshort(datalen, (u_char *)cp);
13661023Skarels cp += sizeof(u_int16_t);
13718143Sralph if (datalen) {
13818143Sralph bcopy(data, cp, datalen);
13918143Sralph cp += datalen;
14018143Sralph }
14123872Skjd hp->ancount = htons(1);
14218143Sralph break;
14318143Sralph
14429989Skjd #ifdef ALLOW_UPDATES
14529989Skjd /*
14629989Skjd * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
14729989Skjd * (Record to be modified is followed by its replacement in msg.)
14829989Skjd */
14929989Skjd case UPDATEM:
15029989Skjd case UPDATEMA:
15129989Skjd
15218143Sralph case UPDATED:
15318143Sralph /*
15429989Skjd * The res code for UPDATED and UPDATEDA is the same; user
15529989Skjd * calls them differently: specifies data for UPDATED; server
15629989Skjd * ignores data if specified for UPDATEDA.
15718143Sralph */
15829989Skjd case UPDATEDA:
15918143Sralph buflen -= RRFIXEDSZ + datalen;
16029989Skjd if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
16118143Sralph return (-1);
16218143Sralph cp += n;
16346496Sbostic __putshort(type, cp);
16461023Skarels cp += sizeof(u_int16_t);
16546496Sbostic __putshort(class, cp);
16661023Skarels cp += sizeof(u_int16_t);
16746496Sbostic __putlong(0, cp);
16861023Skarels cp += sizeof(u_int32_t);
16946496Sbostic __putshort(datalen, cp);
17061023Skarels cp += sizeof(u_int16_t);
17118143Sralph if (datalen) {
17218143Sralph bcopy(data, cp, datalen);
17318143Sralph cp += datalen;
17418143Sralph }
17529989Skjd if ( (op == UPDATED) || (op == UPDATEDA) ) {
17629989Skjd hp->ancount = htons(0);
17729989Skjd break;
17829989Skjd }
17929989Skjd /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
18018143Sralph
18129989Skjd case UPDATEA: /* Add new resource record */
18218143Sralph buflen -= RRFIXEDSZ + datalen;
18318143Sralph if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
18418143Sralph return (-1);
18518143Sralph cp += n;
18646496Sbostic __putshort(newrr->r_type, cp);
18761023Skarels cp += sizeof(u_int16_t);
18846496Sbostic __putshort(newrr->r_class, cp);
18961023Skarels cp += sizeof(u_int16_t);
19046496Sbostic __putlong(0, cp);
19161023Skarels cp += sizeof(u_int32_t);
19246496Sbostic __putshort(newrr->r_size, cp);
19361023Skarels cp += sizeof(u_int16_t);
19418143Sralph if (newrr->r_size) {
19518143Sralph bcopy(newrr->r_data, cp, newrr->r_size);
19618143Sralph cp += newrr->r_size;
19718143Sralph }
19829989Skjd hp->ancount = htons(0);
19918143Sralph break;
20029989Skjd
20161023Skarels #endif /* ALLOW_UPDATES */
20218143Sralph }
20318143Sralph return (cp - buf);
20418143Sralph }
205