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*36322Skarels static char sccsid[] = "@(#)res_mkquery.c 6.9 (Berkeley) 12/08/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 */ 56*36322Skarels bzero(buf, sizeof(HEADER)); 5718143Sralph hp = (HEADER *) buf; 5818143Sralph hp->id = htons(++_res.id); 5918143Sralph hp->opcode = op; 6018143Sralph hp->pr = (_res.options & RES_PRIMARY) != 0; 6118143Sralph hp->rd = (_res.options & RES_RECURSE) != 0; 6218143Sralph hp->rcode = NOERROR; 6318143Sralph cp = buf + sizeof(HEADER); 6418143Sralph buflen -= sizeof(HEADER); 6518143Sralph dpp = dnptrs; 6618143Sralph *dpp++ = buf; 6718143Sralph *dpp++ = NULL; 6818341Sralph lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); 6918143Sralph /* 7018143Sralph * perform opcode specific processing 7118143Sralph */ 7218143Sralph switch (op) { 7318143Sralph case QUERY: 7418143Sralph buflen -= QFIXEDSZ; 7518143Sralph if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 7618143Sralph return (-1); 7718143Sralph cp += n; 7818143Sralph buflen -= n; 7918528Sralph putshort(type, cp); 8018143Sralph cp += sizeof(u_short); 8118528Sralph putshort(class, cp); 8218143Sralph cp += sizeof(u_short); 8323872Skjd hp->qdcount = htons(1); 8418143Sralph if (op == QUERY || data == NULL) 8518143Sralph break; 8618143Sralph /* 8718143Sralph * Make an additional record for completion domain. 8818143Sralph */ 8918528Sralph buflen -= RRFIXEDSZ; 9018143Sralph if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0) 9118143Sralph return (-1); 9218143Sralph cp += n; 9318143Sralph buflen -= n; 9418528Sralph putshort(T_NULL, cp); 9518143Sralph cp += sizeof(u_short); 9618528Sralph putshort(class, cp); 9718143Sralph cp += sizeof(u_short); 9818528Sralph putlong(0, cp); 9918143Sralph cp += sizeof(u_long); 10018528Sralph putshort(0, cp); 10118143Sralph cp += sizeof(u_short); 10223872Skjd hp->arcount = htons(1); 10318143Sralph break; 10418143Sralph 10518143Sralph case IQUERY: 10618143Sralph /* 10718143Sralph * Initialize answer section 10818143Sralph */ 10918143Sralph if (buflen < 1 + RRFIXEDSZ + datalen) 11018143Sralph return (-1); 11118143Sralph *cp++ = '\0'; /* no domain name */ 11218528Sralph putshort(type, cp); 11318143Sralph cp += sizeof(u_short); 11418528Sralph putshort(class, cp); 11518143Sralph cp += sizeof(u_short); 11618528Sralph putlong(0, cp); 11718143Sralph cp += sizeof(u_long); 11818528Sralph putshort(datalen, cp); 11918143Sralph cp += sizeof(u_short); 12018143Sralph if (datalen) { 12118143Sralph bcopy(data, cp, datalen); 12218143Sralph cp += datalen; 12318143Sralph } 12423872Skjd hp->ancount = htons(1); 12518143Sralph break; 12618143Sralph 12729989Skjd #ifdef ALLOW_UPDATES 12829989Skjd /* 12929989Skjd * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA 13029989Skjd * (Record to be modified is followed by its replacement in msg.) 13129989Skjd */ 13229989Skjd case UPDATEM: 13329989Skjd case UPDATEMA: 13429989Skjd 13518143Sralph case UPDATED: 13618143Sralph /* 13729989Skjd * The res code for UPDATED and UPDATEDA is the same; user 13829989Skjd * calls them differently: specifies data for UPDATED; server 13929989Skjd * ignores data if specified for UPDATEDA. 14018143Sralph */ 14129989Skjd case UPDATEDA: 14218143Sralph buflen -= RRFIXEDSZ + datalen; 14329989Skjd if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 14418143Sralph return (-1); 14518143Sralph cp += n; 14629989Skjd putshort(type, cp); 14729989Skjd cp += sizeof(u_short); 14829989Skjd putshort(class, cp); 14929989Skjd cp += sizeof(u_short); 15029989Skjd putlong(0, cp); 15118143Sralph cp += sizeof(u_long); 15229989Skjd putshort(datalen, cp); 15329989Skjd cp += sizeof(u_short); 15418143Sralph if (datalen) { 15518143Sralph bcopy(data, cp, datalen); 15618143Sralph cp += datalen; 15718143Sralph } 15829989Skjd if ( (op == UPDATED) || (op == UPDATEDA) ) { 15929989Skjd hp->ancount = htons(0); 16029989Skjd break; 16129989Skjd } 16229989Skjd /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */ 16318143Sralph 16429989Skjd case UPDATEA: /* Add new resource record */ 16518143Sralph buflen -= RRFIXEDSZ + datalen; 16618143Sralph if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 16718143Sralph return (-1); 16818143Sralph cp += n; 16929989Skjd putshort(newrr->r_type, cp); 17029989Skjd cp += sizeof(u_short); 17129989Skjd putshort(newrr->r_class, cp); 17229989Skjd cp += sizeof(u_short); 17329989Skjd putlong(0, cp); 17418143Sralph cp += sizeof(u_long); 17529989Skjd putshort(newrr->r_size, cp); 17629989Skjd cp += sizeof(u_short); 17718143Sralph if (newrr->r_size) { 17818143Sralph bcopy(newrr->r_data, cp, newrr->r_size); 17918143Sralph cp += newrr->r_size; 18018143Sralph } 18129989Skjd hp->ancount = htons(0); 18218143Sralph break; 18329989Skjd 18429989Skjd #endif ALLOW_UPDATES 18518143Sralph } 18618143Sralph return (cp - buf); 18718143Sralph } 188