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 6*35597Skarels * provided that the above copyright notice and this paragraph are 7*35597Skarels * duplicated in all such forms and that any documentation, 8*35597Skarels * advertising materials, and other materials related to such 9*35597Skarels * distribution and use acknowledge that the software was developed 10*35597Skarels * by the University of California, Berkeley. The name of the 11*35597Skarels * University may not be used to endorse or promote products derived 12*35597Skarels * from this software without specific prior written permission. 13*35597Skarels * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*35597Skarels * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*35597Skarels * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1618548Sralph */ 1718548Sralph 1826634Sdonn #if defined(LIBC_SCCS) && !defined(lint) 19*35597Skarels static char sccsid[] = "@(#)res_mkquery.c 6.8 (Berkeley) 09/20/88"; 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 */ 5618143Sralph hp = (HEADER *) buf; 5718143Sralph hp->id = htons(++_res.id); 5818143Sralph hp->opcode = op; 5918143Sralph hp->qr = hp->aa = hp->tc = hp->ra = 0; 6018143Sralph hp->pr = (_res.options & RES_PRIMARY) != 0; 6118143Sralph hp->rd = (_res.options & RES_RECURSE) != 0; 6218143Sralph hp->rcode = NOERROR; 6318143Sralph hp->qdcount = 0; 6418143Sralph hp->ancount = 0; 6518143Sralph hp->nscount = 0; 6618143Sralph hp->arcount = 0; 6718143Sralph cp = buf + sizeof(HEADER); 6818143Sralph buflen -= sizeof(HEADER); 6918143Sralph dpp = dnptrs; 7018143Sralph *dpp++ = buf; 7118143Sralph *dpp++ = NULL; 7218341Sralph lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); 7318143Sralph /* 7418143Sralph * perform opcode specific processing 7518143Sralph */ 7618143Sralph switch (op) { 7718143Sralph case QUERY: 7818143Sralph buflen -= QFIXEDSZ; 7918143Sralph if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 8018143Sralph return (-1); 8118143Sralph cp += n; 8218143Sralph buflen -= n; 8318528Sralph putshort(type, cp); 8418143Sralph cp += sizeof(u_short); 8518528Sralph putshort(class, cp); 8618143Sralph cp += sizeof(u_short); 8723872Skjd hp->qdcount = htons(1); 8818143Sralph if (op == QUERY || data == NULL) 8918143Sralph break; 9018143Sralph /* 9118143Sralph * Make an additional record for completion domain. 9218143Sralph */ 9318528Sralph buflen -= RRFIXEDSZ; 9418143Sralph if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0) 9518143Sralph return (-1); 9618143Sralph cp += n; 9718143Sralph buflen -= n; 9818528Sralph putshort(T_NULL, cp); 9918143Sralph cp += sizeof(u_short); 10018528Sralph putshort(class, cp); 10118143Sralph cp += sizeof(u_short); 10218528Sralph putlong(0, cp); 10318143Sralph cp += sizeof(u_long); 10418528Sralph putshort(0, cp); 10518143Sralph cp += sizeof(u_short); 10623872Skjd hp->arcount = htons(1); 10718143Sralph break; 10818143Sralph 10918143Sralph case IQUERY: 11018143Sralph /* 11118143Sralph * Initialize answer section 11218143Sralph */ 11318143Sralph if (buflen < 1 + RRFIXEDSZ + datalen) 11418143Sralph return (-1); 11518143Sralph *cp++ = '\0'; /* no domain name */ 11618528Sralph putshort(type, cp); 11718143Sralph cp += sizeof(u_short); 11818528Sralph putshort(class, cp); 11918143Sralph cp += sizeof(u_short); 12018528Sralph putlong(0, cp); 12118143Sralph cp += sizeof(u_long); 12218528Sralph putshort(datalen, cp); 12318143Sralph cp += sizeof(u_short); 12418143Sralph if (datalen) { 12518143Sralph bcopy(data, cp, datalen); 12618143Sralph cp += datalen; 12718143Sralph } 12823872Skjd hp->ancount = htons(1); 12918143Sralph break; 13018143Sralph 13129989Skjd #ifdef ALLOW_UPDATES 13229989Skjd /* 13329989Skjd * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA 13429989Skjd * (Record to be modified is followed by its replacement in msg.) 13529989Skjd */ 13629989Skjd case UPDATEM: 13729989Skjd case UPDATEMA: 13829989Skjd 13918143Sralph case UPDATED: 14018143Sralph /* 14129989Skjd * The res code for UPDATED and UPDATEDA is the same; user 14229989Skjd * calls them differently: specifies data for UPDATED; server 14329989Skjd * ignores data if specified for UPDATEDA. 14418143Sralph */ 14529989Skjd case UPDATEDA: 14618143Sralph buflen -= RRFIXEDSZ + datalen; 14729989Skjd if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 14818143Sralph return (-1); 14918143Sralph cp += n; 15029989Skjd putshort(type, cp); 15129989Skjd cp += sizeof(u_short); 15229989Skjd putshort(class, cp); 15329989Skjd cp += sizeof(u_short); 15429989Skjd putlong(0, cp); 15518143Sralph cp += sizeof(u_long); 15629989Skjd putshort(datalen, cp); 15729989Skjd cp += sizeof(u_short); 15818143Sralph if (datalen) { 15918143Sralph bcopy(data, cp, datalen); 16018143Sralph cp += datalen; 16118143Sralph } 16229989Skjd if ( (op == UPDATED) || (op == UPDATEDA) ) { 16329989Skjd hp->ancount = htons(0); 16429989Skjd break; 16529989Skjd } 16629989Skjd /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */ 16718143Sralph 16829989Skjd case UPDATEA: /* Add new resource record */ 16918143Sralph buflen -= RRFIXEDSZ + datalen; 17018143Sralph if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 17118143Sralph return (-1); 17218143Sralph cp += n; 17329989Skjd putshort(newrr->r_type, cp); 17429989Skjd cp += sizeof(u_short); 17529989Skjd putshort(newrr->r_class, cp); 17629989Skjd cp += sizeof(u_short); 17729989Skjd putlong(0, cp); 17818143Sralph cp += sizeof(u_long); 17929989Skjd putshort(newrr->r_size, cp); 18029989Skjd cp += sizeof(u_short); 18118143Sralph if (newrr->r_size) { 18218143Sralph bcopy(newrr->r_data, cp, newrr->r_size); 18318143Sralph cp += newrr->r_size; 18418143Sralph } 18529989Skjd hp->ancount = htons(0); 18618143Sralph break; 18729989Skjd 18829989Skjd #endif ALLOW_UPDATES 18918143Sralph } 19018143Sralph return (cp - buf); 19118143Sralph } 192