118548Sralph /* 221387Sdist * Copyright (c) 1985 Regents of the University of California. 333679Sbostic * All rights reserved. 433679Sbostic * 5*42627Sbostic * %sccs.include.redist.c% 618548Sralph */ 718548Sralph 826634Sdonn #if defined(LIBC_SCCS) && !defined(lint) 9*42627Sbostic static char sccsid[] = "@(#)res_mkquery.c 6.12 (Berkeley) 06/01/90"; 1033679Sbostic #endif /* LIBC_SCCS and not lint */ 1121387Sdist 1218143Sralph #include <stdio.h> 1318143Sralph #include <sys/types.h> 1418143Sralph #include <netinet/in.h> 1524082Skjd #include <arpa/nameser.h> 1626895Skjd #include <resolv.h> 1718143Sralph 1818143Sralph /* 1918143Sralph * Form all types of queries. 2018143Sralph * Returns the size of the result or -1. 2118143Sralph */ 2218531Sralph res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen) 2318143Sralph int op; /* opcode of query */ 2418143Sralph char *dname; /* domain name */ 2518143Sralph int class, type; /* class and type of query */ 2618143Sralph char *data; /* resource record data */ 2718143Sralph int datalen; /* length of data */ 2818143Sralph struct rrec *newrr; /* new rr for modify or append */ 2918143Sralph char *buf; /* buffer to put query */ 3018143Sralph int buflen; /* size of buffer */ 3118143Sralph { 3218143Sralph register HEADER *hp; 3318143Sralph register char *cp; 3418143Sralph register int n; 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 */ 4539789Sbloom if ((buf == NULL) || (buflen < sizeof(HEADER))) 4639789Sbloom return(-1); 4736322Skarels bzero(buf, sizeof(HEADER)); 4818143Sralph hp = (HEADER *) buf; 4918143Sralph hp->id = htons(++_res.id); 5018143Sralph hp->opcode = op; 5118143Sralph hp->pr = (_res.options & RES_PRIMARY) != 0; 5218143Sralph hp->rd = (_res.options & RES_RECURSE) != 0; 5318143Sralph hp->rcode = NOERROR; 5418143Sralph cp = buf + sizeof(HEADER); 5518143Sralph buflen -= sizeof(HEADER); 5618143Sralph dpp = dnptrs; 5718143Sralph *dpp++ = buf; 5818143Sralph *dpp++ = NULL; 5918341Sralph lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); 6018143Sralph /* 6118143Sralph * perform opcode specific processing 6218143Sralph */ 6318143Sralph switch (op) { 6418143Sralph case QUERY: 6539789Sbloom if ((buflen -= QFIXEDSZ) < 0) 6639789Sbloom return(-1); 6718143Sralph if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 6818143Sralph return (-1); 6918143Sralph cp += n; 7018143Sralph buflen -= n; 7118528Sralph putshort(type, cp); 7218143Sralph cp += sizeof(u_short); 7318528Sralph putshort(class, cp); 7418143Sralph cp += sizeof(u_short); 7523872Skjd hp->qdcount = htons(1); 7618143Sralph if (op == QUERY || data == NULL) 7718143Sralph break; 7818143Sralph /* 7918143Sralph * Make an additional record for completion domain. 8018143Sralph */ 8118528Sralph buflen -= RRFIXEDSZ; 8218143Sralph if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0) 8318143Sralph return (-1); 8418143Sralph cp += n; 8518143Sralph buflen -= n; 8618528Sralph putshort(T_NULL, cp); 8718143Sralph cp += sizeof(u_short); 8818528Sralph putshort(class, cp); 8918143Sralph cp += sizeof(u_short); 9018528Sralph putlong(0, cp); 9118143Sralph cp += sizeof(u_long); 9218528Sralph putshort(0, cp); 9318143Sralph cp += sizeof(u_short); 9423872Skjd hp->arcount = htons(1); 9518143Sralph break; 9618143Sralph 9718143Sralph case IQUERY: 9818143Sralph /* 9918143Sralph * Initialize answer section 10018143Sralph */ 10118143Sralph if (buflen < 1 + RRFIXEDSZ + datalen) 10218143Sralph return (-1); 10318143Sralph *cp++ = '\0'; /* no domain name */ 10418528Sralph putshort(type, cp); 10518143Sralph cp += sizeof(u_short); 10618528Sralph putshort(class, cp); 10718143Sralph cp += sizeof(u_short); 10818528Sralph putlong(0, cp); 10918143Sralph cp += sizeof(u_long); 11018528Sralph putshort(datalen, cp); 11118143Sralph cp += sizeof(u_short); 11218143Sralph if (datalen) { 11318143Sralph bcopy(data, cp, datalen); 11418143Sralph cp += datalen; 11518143Sralph } 11623872Skjd hp->ancount = htons(1); 11718143Sralph break; 11818143Sralph 11929989Skjd #ifdef ALLOW_UPDATES 12029989Skjd /* 12129989Skjd * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA 12229989Skjd * (Record to be modified is followed by its replacement in msg.) 12329989Skjd */ 12429989Skjd case UPDATEM: 12529989Skjd case UPDATEMA: 12629989Skjd 12718143Sralph case UPDATED: 12818143Sralph /* 12929989Skjd * The res code for UPDATED and UPDATEDA is the same; user 13029989Skjd * calls them differently: specifies data for UPDATED; server 13129989Skjd * ignores data if specified for UPDATEDA. 13218143Sralph */ 13329989Skjd case UPDATEDA: 13418143Sralph buflen -= RRFIXEDSZ + datalen; 13529989Skjd if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 13618143Sralph return (-1); 13718143Sralph cp += n; 13829989Skjd putshort(type, cp); 13929989Skjd cp += sizeof(u_short); 14029989Skjd putshort(class, cp); 14129989Skjd cp += sizeof(u_short); 14229989Skjd putlong(0, cp); 14318143Sralph cp += sizeof(u_long); 14429989Skjd putshort(datalen, cp); 14529989Skjd cp += sizeof(u_short); 14618143Sralph if (datalen) { 14718143Sralph bcopy(data, cp, datalen); 14818143Sralph cp += datalen; 14918143Sralph } 15029989Skjd if ( (op == UPDATED) || (op == UPDATEDA) ) { 15129989Skjd hp->ancount = htons(0); 15229989Skjd break; 15329989Skjd } 15429989Skjd /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */ 15518143Sralph 15629989Skjd case UPDATEA: /* Add new resource record */ 15718143Sralph buflen -= RRFIXEDSZ + datalen; 15818143Sralph if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 15918143Sralph return (-1); 16018143Sralph cp += n; 16129989Skjd putshort(newrr->r_type, cp); 16229989Skjd cp += sizeof(u_short); 16329989Skjd putshort(newrr->r_class, cp); 16429989Skjd cp += sizeof(u_short); 16529989Skjd putlong(0, cp); 16618143Sralph cp += sizeof(u_long); 16729989Skjd putshort(newrr->r_size, cp); 16829989Skjd cp += sizeof(u_short); 16918143Sralph if (newrr->r_size) { 17018143Sralph bcopy(newrr->r_data, cp, newrr->r_size); 17118143Sralph cp += newrr->r_size; 17218143Sralph } 17329989Skjd hp->ancount = htons(0); 17418143Sralph break; 17529989Skjd 17629989Skjd #endif ALLOW_UPDATES 17718143Sralph } 17818143Sralph return (cp - buf); 17918143Sralph } 180