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 7*26634Sdonn #if defined(LIBC_SCCS) && !defined(lint) 8*26634Sdonn static char sccsid[] = "@(#)res_mkquery.c 6.2 (Berkeley) 03/09/86"; 9*26634Sdonn #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> 1524082Skjd #include <arpa/resolv.h> 1618143Sralph 1725300Skjd extern char *sprintf(); 1825300Skjd 1918143Sralph /* 2018143Sralph * Form all types of queries. 2118143Sralph * Returns the size of the result or -1. 2218143Sralph */ 2318531Sralph res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen) 2418143Sralph int op; /* opcode of query */ 2518143Sralph char *dname; /* domain name */ 2618143Sralph int class, type; /* class and type of query */ 2718143Sralph char *data; /* resource record data */ 2818143Sralph int datalen; /* length of data */ 2918143Sralph struct rrec *newrr; /* new rr for modify or append */ 3018143Sralph char *buf; /* buffer to put query */ 3118143Sralph int buflen; /* size of buffer */ 3218143Sralph { 3318143Sralph register HEADER *hp; 3418143Sralph register char *cp; 3518143Sralph register int n; 3618143Sralph char dnbuf[MAXDNAME]; 3718143Sralph char *dnptrs[10], **dpp, **lastdnptr; 3818528Sralph extern char *index(); 3918143Sralph 4024734Sbloom #ifdef DEBUG 4118143Sralph if (_res.options & RES_DEBUG) 4218531Sralph printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type); 4325156Skjd #endif DEBUG 4418143Sralph /* 4518143Sralph * Initialize header fields. 4618143Sralph */ 4718143Sralph hp = (HEADER *) buf; 4818143Sralph hp->id = htons(++_res.id); 4918143Sralph hp->opcode = op; 5018143Sralph hp->qr = hp->aa = hp->tc = hp->ra = 0; 5118143Sralph hp->pr = (_res.options & RES_PRIMARY) != 0; 5218143Sralph hp->rd = (_res.options & RES_RECURSE) != 0; 5318143Sralph hp->rcode = NOERROR; 5418143Sralph hp->qdcount = 0; 5518143Sralph hp->ancount = 0; 5618143Sralph hp->nscount = 0; 5718143Sralph hp->arcount = 0; 5818143Sralph cp = buf + sizeof(HEADER); 5918143Sralph buflen -= sizeof(HEADER); 6018143Sralph dpp = dnptrs; 6118143Sralph *dpp++ = buf; 6218143Sralph *dpp++ = NULL; 6318341Sralph lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); 6418143Sralph /* 6518528Sralph * If the domain name contains no dots (single label), then 6618143Sralph * append the default domain name to the one given. 6718143Sralph */ 6825156Skjd if ((_res.options & RES_DEFNAMES) && dname != 0 && dname[0] != '\0' && 6918528Sralph index(dname, '.') == NULL) { 7018143Sralph if (!(_res.options & RES_INIT)) 7124734Sbloom if (res_init() == -1) 7224734Sbloom return(-1); 7318143Sralph if (_res.defdname[0] != '\0') 7418143Sralph dname = sprintf(dnbuf, "%s.%s", dname, _res.defdname); 7518143Sralph } 7618143Sralph /* 7718143Sralph * perform opcode specific processing 7818143Sralph */ 7918143Sralph switch (op) { 8018143Sralph case QUERY: 8118143Sralph case CQUERYM: 8218143Sralph case CQUERYU: 8318143Sralph buflen -= QFIXEDSZ; 8418143Sralph if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 8518143Sralph return (-1); 8618143Sralph cp += n; 8718143Sralph buflen -= n; 8818528Sralph putshort(type, cp); 8918143Sralph cp += sizeof(u_short); 9018528Sralph putshort(class, cp); 9118143Sralph cp += sizeof(u_short); 9223872Skjd hp->qdcount = htons(1); 9318143Sralph if (op == QUERY || data == NULL) 9418143Sralph break; 9518143Sralph /* 9618143Sralph * Make an additional record for completion domain. 9718143Sralph */ 9818528Sralph buflen -= RRFIXEDSZ; 9918143Sralph if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0) 10018143Sralph return (-1); 10118143Sralph cp += n; 10218143Sralph buflen -= n; 10318528Sralph putshort(T_NULL, cp); 10418143Sralph cp += sizeof(u_short); 10518528Sralph putshort(class, cp); 10618143Sralph cp += sizeof(u_short); 10718528Sralph putlong(0, cp); 10818143Sralph cp += sizeof(u_long); 10918528Sralph putshort(0, cp); 11018143Sralph cp += sizeof(u_short); 11123872Skjd hp->arcount = htons(1); 11218143Sralph break; 11318143Sralph 11418143Sralph case IQUERY: 11518143Sralph /* 11618143Sralph * Initialize answer section 11718143Sralph */ 11818143Sralph if (buflen < 1 + RRFIXEDSZ + datalen) 11918143Sralph return (-1); 12018143Sralph *cp++ = '\0'; /* no domain name */ 12118528Sralph putshort(type, cp); 12218143Sralph cp += sizeof(u_short); 12318528Sralph putshort(class, cp); 12418143Sralph cp += sizeof(u_short); 12518528Sralph putlong(0, cp); 12618143Sralph cp += sizeof(u_long); 12718528Sralph putshort(datalen, cp); 12818143Sralph cp += sizeof(u_short); 12918143Sralph if (datalen) { 13018143Sralph bcopy(data, cp, datalen); 13118143Sralph cp += datalen; 13218143Sralph } 13323872Skjd hp->ancount = htons(1); 13418143Sralph break; 13518143Sralph 13618143Sralph #ifdef notdef 13718143Sralph case UPDATED: 13818143Sralph /* 13918143Sralph * Put record to be added or deleted in additional section 14018143Sralph */ 14118143Sralph buflen -= RRFIXEDSZ + datalen; 14218143Sralph if ((n = dn_comp(dname, cp, buflen, NULL, NULL)) < 0) 14318143Sralph return (-1); 14418143Sralph cp += n; 14518143Sralph *((u_short *)cp) = htons(type); 14618143Sralph cp += sizeof(u_short); 14718143Sralph *((u_short *)cp) = htons(class); 14818143Sralph cp += sizeof(u_short); 14918143Sralph *((u_long *)cp) = 0; 15018143Sralph cp += sizeof(u_long); 15118143Sralph *((u_short *)cp) = htons(datalen); 15218143Sralph cp += sizeof(u_short); 15318143Sralph if (datalen) { 15418143Sralph bcopy(data, cp, datalen); 15518143Sralph cp += datalen; 15618143Sralph } 15718143Sralph break; 15818143Sralph 15918143Sralph case UPDATEM: 16018143Sralph /* 16118143Sralph * Record to be modified followed by its replacement 16218143Sralph */ 16318143Sralph buflen -= RRFIXEDSZ + datalen; 16418143Sralph if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 16518143Sralph return (-1); 16618143Sralph cp += n; 16718143Sralph *((u_short *)cp) = htons(type); 16818143Sralph cp += sizeof(u_short); 16918143Sralph *((u_short *)cp) = htons(class); 17018143Sralph cp += sizeof(u_short); 17118143Sralph *((u_long *)cp) = 0; 17218143Sralph cp += sizeof(u_long); 17318143Sralph *((u_short *)cp) = htons(datalen); 17418143Sralph cp += sizeof(u_short); 17518143Sralph if (datalen) { 17618143Sralph bcopy(data, cp, datalen); 17718143Sralph cp += datalen; 17818143Sralph } 17918143Sralph 18018143Sralph case UPDATEA: 18118143Sralph buflen -= RRFIXEDSZ + newrr->r_size; 18218143Sralph if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 18318143Sralph return (-1); 18418143Sralph cp += n; 18518143Sralph *((u_short *)cp) = htons(newrr->r_type); 18618143Sralph cp += sizeof(u_short); 18718143Sralph *((u_short *)cp) = htons(newrr->r_type); 18818143Sralph cp += sizeof(u_short); 18918143Sralph *((u_long *)cp) = htonl(newrr->r_ttl); 19018143Sralph cp += sizeof(u_long); 19118143Sralph *((u_short *)cp) = htons(newrr->r_size); 19218143Sralph cp += sizeof(u_short); 19318143Sralph if (newrr->r_size) { 19418143Sralph bcopy(newrr->r_data, cp, newrr->r_size); 19518143Sralph cp += newrr->r_size; 19618143Sralph } 19718143Sralph break; 19818143Sralph #endif 19918143Sralph } 20018143Sralph return (cp - buf); 20118143Sralph } 202