118548Sralph /* 221387Sdist * Copyright (c) 1985 Regents of the University of California. 333679Sbostic * All rights reserved. 433679Sbostic * 533679Sbostic * Redistribution and use in source and binary forms are permitted 635597Skarels * provided that the above copyright notice and this paragraph are 735597Skarels * duplicated in all such forms and that any documentation, 835597Skarels * advertising materials, and other materials related to such 935597Skarels * distribution and use acknowledge that the software was developed 1035597Skarels * by the University of California, Berkeley. The name of the 1135597Skarels * University may not be used to endorse or promote products derived 1235597Skarels * from this software without specific prior written permission. 1335597Skarels * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1435597Skarels * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1535597Skarels * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1618548Sralph */ 1718548Sralph 1826634Sdonn #if defined(LIBC_SCCS) && !defined(lint) 19*39789Sbloom static char sccsid[] = "@(#)res_mkquery.c 6.10 (Berkeley) 12/27/89"; 2033679Sbostic #endif /* LIBC_SCCS and not lint */ 2121387Sdist 2218143Sralph #include <stdio.h> 2318143Sralph #include <sys/types.h> 2418143Sralph #include <netinet/in.h> 2524082Skjd #include <arpa/nameser.h> 2626895Skjd #include <resolv.h> 2718143Sralph 2818143Sralph /* 2918143Sralph * Form all types of queries. 3018143Sralph * Returns the size of the result or -1. 3118143Sralph */ 3218531Sralph res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen) 3318143Sralph int op; /* opcode of query */ 3418143Sralph char *dname; /* domain name */ 3518143Sralph int class, type; /* class and type of query */ 3618143Sralph char *data; /* resource record data */ 3718143Sralph int datalen; /* length of data */ 3818143Sralph struct rrec *newrr; /* new rr for modify or append */ 3918143Sralph char *buf; /* buffer to put query */ 4018143Sralph int buflen; /* size of buffer */ 4118143Sralph { 4218143Sralph register HEADER *hp; 4318143Sralph register char *cp; 4418143Sralph register int n; 4518143Sralph char dnbuf[MAXDNAME]; 4618143Sralph char *dnptrs[10], **dpp, **lastdnptr; 4718528Sralph extern char *index(); 4818143Sralph 4924734Sbloom #ifdef DEBUG 5018143Sralph if (_res.options & RES_DEBUG) 5118531Sralph printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type); 5225156Skjd #endif DEBUG 5318143Sralph /* 5418143Sralph * Initialize header fields. 5518143Sralph */ 56*39789Sbloom if ((buf == NULL) || (buflen < sizeof(HEADER))) 57*39789Sbloom return(-1); 5836322Skarels bzero(buf, sizeof(HEADER)); 5918143Sralph hp = (HEADER *) buf; 6018143Sralph hp->id = htons(++_res.id); 6118143Sralph hp->opcode = op; 6218143Sralph hp->pr = (_res.options & RES_PRIMARY) != 0; 6318143Sralph hp->rd = (_res.options & RES_RECURSE) != 0; 6418143Sralph hp->rcode = NOERROR; 6518143Sralph cp = buf + sizeof(HEADER); 6618143Sralph buflen -= sizeof(HEADER); 6718143Sralph dpp = dnptrs; 6818143Sralph *dpp++ = buf; 6918143Sralph *dpp++ = NULL; 7018341Sralph lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); 7118143Sralph /* 7218143Sralph * perform opcode specific processing 7318143Sralph */ 7418143Sralph switch (op) { 7518143Sralph case QUERY: 76*39789Sbloom if ((buflen -= QFIXEDSZ) < 0) 77*39789Sbloom return(-1); 7818143Sralph if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 7918143Sralph return (-1); 8018143Sralph cp += n; 8118143Sralph buflen -= n; 8218528Sralph putshort(type, cp); 8318143Sralph cp += sizeof(u_short); 8418528Sralph putshort(class, cp); 8518143Sralph cp += sizeof(u_short); 8623872Skjd hp->qdcount = htons(1); 8718143Sralph if (op == QUERY || data == NULL) 8818143Sralph break; 8918143Sralph /* 9018143Sralph * Make an additional record for completion domain. 9118143Sralph */ 9218528Sralph buflen -= RRFIXEDSZ; 9318143Sralph if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0) 9418143Sralph return (-1); 9518143Sralph cp += n; 9618143Sralph buflen -= n; 9718528Sralph putshort(T_NULL, cp); 9818143Sralph cp += sizeof(u_short); 9918528Sralph putshort(class, cp); 10018143Sralph cp += sizeof(u_short); 10118528Sralph putlong(0, cp); 10218143Sralph cp += sizeof(u_long); 10318528Sralph putshort(0, cp); 10418143Sralph cp += sizeof(u_short); 10523872Skjd hp->arcount = htons(1); 10618143Sralph break; 10718143Sralph 10818143Sralph case IQUERY: 10918143Sralph /* 11018143Sralph * Initialize answer section 11118143Sralph */ 11218143Sralph if (buflen < 1 + RRFIXEDSZ + datalen) 11318143Sralph return (-1); 11418143Sralph *cp++ = '\0'; /* no domain name */ 11518528Sralph putshort(type, cp); 11618143Sralph cp += sizeof(u_short); 11718528Sralph putshort(class, cp); 11818143Sralph cp += sizeof(u_short); 11918528Sralph putlong(0, cp); 12018143Sralph cp += sizeof(u_long); 12118528Sralph putshort(datalen, cp); 12218143Sralph cp += sizeof(u_short); 12318143Sralph if (datalen) { 12418143Sralph bcopy(data, cp, datalen); 12518143Sralph cp += datalen; 12618143Sralph } 12723872Skjd hp->ancount = htons(1); 12818143Sralph break; 12918143Sralph 13029989Skjd #ifdef ALLOW_UPDATES 13129989Skjd /* 13229989Skjd * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA 13329989Skjd * (Record to be modified is followed by its replacement in msg.) 13429989Skjd */ 13529989Skjd case UPDATEM: 13629989Skjd case UPDATEMA: 13729989Skjd 13818143Sralph case UPDATED: 13918143Sralph /* 14029989Skjd * The res code for UPDATED and UPDATEDA is the same; user 14129989Skjd * calls them differently: specifies data for UPDATED; server 14229989Skjd * ignores data if specified for UPDATEDA. 14318143Sralph */ 14429989Skjd case UPDATEDA: 14518143Sralph buflen -= RRFIXEDSZ + datalen; 14629989Skjd if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 14718143Sralph return (-1); 14818143Sralph cp += n; 14929989Skjd putshort(type, cp); 15029989Skjd cp += sizeof(u_short); 15129989Skjd putshort(class, cp); 15229989Skjd cp += sizeof(u_short); 15329989Skjd putlong(0, cp); 15418143Sralph cp += sizeof(u_long); 15529989Skjd putshort(datalen, cp); 15629989Skjd cp += sizeof(u_short); 15718143Sralph if (datalen) { 15818143Sralph bcopy(data, cp, datalen); 15918143Sralph cp += datalen; 16018143Sralph } 16129989Skjd if ( (op == UPDATED) || (op == UPDATEDA) ) { 16229989Skjd hp->ancount = htons(0); 16329989Skjd break; 16429989Skjd } 16529989Skjd /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */ 16618143Sralph 16729989Skjd case UPDATEA: /* Add new resource record */ 16818143Sralph buflen -= RRFIXEDSZ + datalen; 16918143Sralph if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 17018143Sralph return (-1); 17118143Sralph cp += n; 17229989Skjd putshort(newrr->r_type, cp); 17329989Skjd cp += sizeof(u_short); 17429989Skjd putshort(newrr->r_class, cp); 17529989Skjd cp += sizeof(u_short); 17629989Skjd putlong(0, cp); 17718143Sralph cp += sizeof(u_long); 17829989Skjd putshort(newrr->r_size, cp); 17929989Skjd cp += sizeof(u_short); 18018143Sralph if (newrr->r_size) { 18118143Sralph bcopy(newrr->r_data, cp, newrr->r_size); 18218143Sralph cp += newrr->r_size; 18318143Sralph } 18429989Skjd hp->ancount = htons(0); 18518143Sralph break; 18629989Skjd 18729989Skjd #endif ALLOW_UPDATES 18818143Sralph } 18918143Sralph return (cp - buf); 19018143Sralph } 191