118548Sralph /* 221387Sdist * Copyright (c) 1985 Regents of the University of California. 321387Sdist * All rights reserved. The Berkeley software License Agreement 421387Sdist * specifies the terms and conditions for redistribution. 518548Sralph */ 618548Sralph 726634Sdonn #if defined(LIBC_SCCS) && !defined(lint) 8*32496Sbostic static char sccsid[] = "@(#)res_mkquery.c 6.6 (Berkeley) 10/22/87"; 926634Sdonn #endif LIBC_SCCS and not lint 1021387Sdist 1118143Sralph #include <stdio.h> 1218143Sralph #include <sys/types.h> 1318143Sralph #include <netinet/in.h> 1424082Skjd #include <arpa/nameser.h> 1526895Skjd #include <resolv.h> 1618143Sralph 1718143Sralph /* 1818143Sralph * Form all types of queries. 1918143Sralph * Returns the size of the result or -1. 2018143Sralph */ 2118531Sralph res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen) 2218143Sralph int op; /* opcode of query */ 2318143Sralph char *dname; /* domain name */ 2418143Sralph int class, type; /* class and type of query */ 2518143Sralph char *data; /* resource record data */ 2618143Sralph int datalen; /* length of data */ 2718143Sralph struct rrec *newrr; /* new rr for modify or append */ 2818143Sralph char *buf; /* buffer to put query */ 2918143Sralph int buflen; /* size of buffer */ 3018143Sralph { 3118143Sralph register HEADER *hp; 3218143Sralph register char *cp; 3318143Sralph register int n; 3418143Sralph char dnbuf[MAXDNAME]; 3518143Sralph char *dnptrs[10], **dpp, **lastdnptr; 3618528Sralph extern char *index(); 3718143Sralph 3824734Sbloom #ifdef DEBUG 3918143Sralph if (_res.options & RES_DEBUG) 4018531Sralph printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type); 4125156Skjd #endif DEBUG 4218143Sralph /* 4318143Sralph * Initialize header fields. 4418143Sralph */ 4518143Sralph hp = (HEADER *) buf; 4618143Sralph hp->id = htons(++_res.id); 4718143Sralph hp->opcode = op; 4818143Sralph hp->qr = hp->aa = hp->tc = hp->ra = 0; 4918143Sralph hp->pr = (_res.options & RES_PRIMARY) != 0; 5018143Sralph hp->rd = (_res.options & RES_RECURSE) != 0; 5118143Sralph hp->rcode = NOERROR; 5218143Sralph hp->qdcount = 0; 5318143Sralph hp->ancount = 0; 5418143Sralph hp->nscount = 0; 5518143Sralph hp->arcount = 0; 5618143Sralph cp = buf + sizeof(HEADER); 5718143Sralph buflen -= sizeof(HEADER); 5818143Sralph dpp = dnptrs; 5918143Sralph *dpp++ = buf; 6018143Sralph *dpp++ = NULL; 6118341Sralph lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); 6218143Sralph /* 6318528Sralph * If the domain name contains no dots (single label), then 6418143Sralph * append the default domain name to the one given. 6518143Sralph */ 6625156Skjd if ((_res.options & RES_DEFNAMES) && dname != 0 && dname[0] != '\0' && 6718528Sralph index(dname, '.') == NULL) { 6818143Sralph if (!(_res.options & RES_INIT)) 6924734Sbloom if (res_init() == -1) 7024734Sbloom return(-1); 71*32496Sbostic if (_res.defdname[0] != '\0') { 72*32496Sbostic (void)sprintf(dnbuf, "%s.%s", dname, _res.defdname); 73*32496Sbostic dname = dnbuf; 74*32496Sbostic } 7518143Sralph } 7618143Sralph /* 7718143Sralph * perform opcode specific processing 7818143Sralph */ 7918143Sralph switch (op) { 8018143Sralph case QUERY: 8118143Sralph buflen -= QFIXEDSZ; 8218143Sralph if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 8318143Sralph return (-1); 8418143Sralph cp += n; 8518143Sralph buflen -= n; 8618528Sralph putshort(type, cp); 8718143Sralph cp += sizeof(u_short); 8818528Sralph putshort(class, cp); 8918143Sralph cp += sizeof(u_short); 9023872Skjd hp->qdcount = htons(1); 9118143Sralph if (op == QUERY || data == NULL) 9218143Sralph break; 9318143Sralph /* 9418143Sralph * Make an additional record for completion domain. 9518143Sralph */ 9618528Sralph buflen -= RRFIXEDSZ; 9718143Sralph if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0) 9818143Sralph return (-1); 9918143Sralph cp += n; 10018143Sralph buflen -= n; 10118528Sralph putshort(T_NULL, cp); 10218143Sralph cp += sizeof(u_short); 10318528Sralph putshort(class, cp); 10418143Sralph cp += sizeof(u_short); 10518528Sralph putlong(0, cp); 10618143Sralph cp += sizeof(u_long); 10718528Sralph putshort(0, cp); 10818143Sralph cp += sizeof(u_short); 10923872Skjd hp->arcount = htons(1); 11018143Sralph break; 11118143Sralph 11218143Sralph case IQUERY: 11318143Sralph /* 11418143Sralph * Initialize answer section 11518143Sralph */ 11618143Sralph if (buflen < 1 + RRFIXEDSZ + datalen) 11718143Sralph return (-1); 11818143Sralph *cp++ = '\0'; /* no domain name */ 11918528Sralph putshort(type, cp); 12018143Sralph cp += sizeof(u_short); 12118528Sralph putshort(class, cp); 12218143Sralph cp += sizeof(u_short); 12318528Sralph putlong(0, cp); 12418143Sralph cp += sizeof(u_long); 12518528Sralph putshort(datalen, cp); 12618143Sralph cp += sizeof(u_short); 12718143Sralph if (datalen) { 12818143Sralph bcopy(data, cp, datalen); 12918143Sralph cp += datalen; 13018143Sralph } 13123872Skjd hp->ancount = htons(1); 13218143Sralph break; 13318143Sralph 13429989Skjd #ifdef ALLOW_UPDATES 13529989Skjd /* 13629989Skjd * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA 13729989Skjd * (Record to be modified is followed by its replacement in msg.) 13829989Skjd */ 13929989Skjd case UPDATEM: 14029989Skjd case UPDATEMA: 14129989Skjd 14218143Sralph case UPDATED: 14318143Sralph /* 14429989Skjd * The res code for UPDATED and UPDATEDA is the same; user 14529989Skjd * calls them differently: specifies data for UPDATED; server 14629989Skjd * ignores data if specified for UPDATEDA. 14718143Sralph */ 14829989Skjd case UPDATEDA: 14918143Sralph buflen -= RRFIXEDSZ + datalen; 15029989Skjd if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 15118143Sralph return (-1); 15218143Sralph cp += n; 15329989Skjd putshort(type, cp); 15429989Skjd cp += sizeof(u_short); 15529989Skjd putshort(class, cp); 15629989Skjd cp += sizeof(u_short); 15729989Skjd putlong(0, cp); 15818143Sralph cp += sizeof(u_long); 15929989Skjd putshort(datalen, cp); 16029989Skjd cp += sizeof(u_short); 16118143Sralph if (datalen) { 16218143Sralph bcopy(data, cp, datalen); 16318143Sralph cp += datalen; 16418143Sralph } 16529989Skjd if ( (op == UPDATED) || (op == UPDATEDA) ) { 16629989Skjd hp->ancount = htons(0); 16729989Skjd break; 16829989Skjd } 16929989Skjd /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */ 17018143Sralph 17129989Skjd case UPDATEA: /* Add new resource record */ 17218143Sralph buflen -= RRFIXEDSZ + datalen; 17318143Sralph if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 17418143Sralph return (-1); 17518143Sralph cp += n; 17629989Skjd putshort(newrr->r_type, cp); 17729989Skjd cp += sizeof(u_short); 17829989Skjd putshort(newrr->r_class, cp); 17929989Skjd cp += sizeof(u_short); 18029989Skjd putlong(0, cp); 18118143Sralph cp += sizeof(u_long); 18229989Skjd putshort(newrr->r_size, cp); 18329989Skjd cp += sizeof(u_short); 18418143Sralph if (newrr->r_size) { 18518143Sralph bcopy(newrr->r_data, cp, newrr->r_size); 18618143Sralph cp += newrr->r_size; 18718143Sralph } 18829989Skjd hp->ancount = htons(0); 18918143Sralph break; 19029989Skjd 19129989Skjd #endif ALLOW_UPDATES 19218143Sralph } 19318143Sralph return (cp - buf); 19418143Sralph } 195