118548Sralph /* 221387Sdist * Copyright (c) 1985 Regents of the University of California. 3*33679Sbostic * All rights reserved. 4*33679Sbostic * 5*33679Sbostic * Redistribution and use in source and binary forms are permitted 6*33679Sbostic * provided that this notice is preserved and that due credit is given 7*33679Sbostic * to the University of California at Berkeley. The name of the University 8*33679Sbostic * may not be used to endorse or promote products derived from this 9*33679Sbostic * software without specific prior written permission. This software 10*33679Sbostic * is provided ``as is'' without express or implied warranty. 1118548Sralph */ 1218548Sralph 1326634Sdonn #if defined(LIBC_SCCS) && !defined(lint) 14*33679Sbostic static char sccsid[] = "@(#)res_mkquery.c 6.7 (Berkeley) 03/07/88"; 15*33679Sbostic #endif /* LIBC_SCCS and not lint */ 1621387Sdist 1718143Sralph #include <stdio.h> 1818143Sralph #include <sys/types.h> 1918143Sralph #include <netinet/in.h> 2024082Skjd #include <arpa/nameser.h> 2126895Skjd #include <resolv.h> 2218143Sralph 2318143Sralph /* 2418143Sralph * Form all types of queries. 2518143Sralph * Returns the size of the result or -1. 2618143Sralph */ 2718531Sralph res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen) 2818143Sralph int op; /* opcode of query */ 2918143Sralph char *dname; /* domain name */ 3018143Sralph int class, type; /* class and type of query */ 3118143Sralph char *data; /* resource record data */ 3218143Sralph int datalen; /* length of data */ 3318143Sralph struct rrec *newrr; /* new rr for modify or append */ 3418143Sralph char *buf; /* buffer to put query */ 3518143Sralph int buflen; /* size of buffer */ 3618143Sralph { 3718143Sralph register HEADER *hp; 3818143Sralph register char *cp; 3918143Sralph register int n; 4018143Sralph char dnbuf[MAXDNAME]; 4118143Sralph char *dnptrs[10], **dpp, **lastdnptr; 4218528Sralph extern char *index(); 4318143Sralph 4424734Sbloom #ifdef DEBUG 4518143Sralph if (_res.options & RES_DEBUG) 4618531Sralph printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type); 4725156Skjd #endif DEBUG 4818143Sralph /* 4918143Sralph * Initialize header fields. 5018143Sralph */ 5118143Sralph hp = (HEADER *) buf; 5218143Sralph hp->id = htons(++_res.id); 5318143Sralph hp->opcode = op; 5418143Sralph hp->qr = hp->aa = hp->tc = hp->ra = 0; 5518143Sralph hp->pr = (_res.options & RES_PRIMARY) != 0; 5618143Sralph hp->rd = (_res.options & RES_RECURSE) != 0; 5718143Sralph hp->rcode = NOERROR; 5818143Sralph hp->qdcount = 0; 5918143Sralph hp->ancount = 0; 6018143Sralph hp->nscount = 0; 6118143Sralph hp->arcount = 0; 6218143Sralph cp = buf + sizeof(HEADER); 6318143Sralph buflen -= sizeof(HEADER); 6418143Sralph dpp = dnptrs; 6518143Sralph *dpp++ = buf; 6618143Sralph *dpp++ = NULL; 6718341Sralph lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); 6818143Sralph /* 6918528Sralph * If the domain name contains no dots (single label), then 7018143Sralph * append the default domain name to the one given. 7118143Sralph */ 7225156Skjd if ((_res.options & RES_DEFNAMES) && dname != 0 && dname[0] != '\0' && 7318528Sralph index(dname, '.') == NULL) { 7418143Sralph if (!(_res.options & RES_INIT)) 7524734Sbloom if (res_init() == -1) 7624734Sbloom return(-1); 7732496Sbostic if (_res.defdname[0] != '\0') { 7832496Sbostic (void)sprintf(dnbuf, "%s.%s", dname, _res.defdname); 7932496Sbostic dname = dnbuf; 8032496Sbostic } 8118143Sralph } 8218143Sralph /* 8318143Sralph * perform opcode specific processing 8418143Sralph */ 8518143Sralph switch (op) { 8618143Sralph case QUERY: 8718143Sralph buflen -= QFIXEDSZ; 8818143Sralph if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 8918143Sralph return (-1); 9018143Sralph cp += n; 9118143Sralph buflen -= n; 9218528Sralph putshort(type, cp); 9318143Sralph cp += sizeof(u_short); 9418528Sralph putshort(class, cp); 9518143Sralph cp += sizeof(u_short); 9623872Skjd hp->qdcount = htons(1); 9718143Sralph if (op == QUERY || data == NULL) 9818143Sralph break; 9918143Sralph /* 10018143Sralph * Make an additional record for completion domain. 10118143Sralph */ 10218528Sralph buflen -= RRFIXEDSZ; 10318143Sralph if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0) 10418143Sralph return (-1); 10518143Sralph cp += n; 10618143Sralph buflen -= n; 10718528Sralph putshort(T_NULL, cp); 10818143Sralph cp += sizeof(u_short); 10918528Sralph putshort(class, cp); 11018143Sralph cp += sizeof(u_short); 11118528Sralph putlong(0, cp); 11218143Sralph cp += sizeof(u_long); 11318528Sralph putshort(0, cp); 11418143Sralph cp += sizeof(u_short); 11523872Skjd hp->arcount = htons(1); 11618143Sralph break; 11718143Sralph 11818143Sralph case IQUERY: 11918143Sralph /* 12018143Sralph * Initialize answer section 12118143Sralph */ 12218143Sralph if (buflen < 1 + RRFIXEDSZ + datalen) 12318143Sralph return (-1); 12418143Sralph *cp++ = '\0'; /* no domain name */ 12518528Sralph putshort(type, cp); 12618143Sralph cp += sizeof(u_short); 12718528Sralph putshort(class, cp); 12818143Sralph cp += sizeof(u_short); 12918528Sralph putlong(0, cp); 13018143Sralph cp += sizeof(u_long); 13118528Sralph putshort(datalen, cp); 13218143Sralph cp += sizeof(u_short); 13318143Sralph if (datalen) { 13418143Sralph bcopy(data, cp, datalen); 13518143Sralph cp += datalen; 13618143Sralph } 13723872Skjd hp->ancount = htons(1); 13818143Sralph break; 13918143Sralph 14029989Skjd #ifdef ALLOW_UPDATES 14129989Skjd /* 14229989Skjd * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA 14329989Skjd * (Record to be modified is followed by its replacement in msg.) 14429989Skjd */ 14529989Skjd case UPDATEM: 14629989Skjd case UPDATEMA: 14729989Skjd 14818143Sralph case UPDATED: 14918143Sralph /* 15029989Skjd * The res code for UPDATED and UPDATEDA is the same; user 15129989Skjd * calls them differently: specifies data for UPDATED; server 15229989Skjd * ignores data if specified for UPDATEDA. 15318143Sralph */ 15429989Skjd case UPDATEDA: 15518143Sralph buflen -= RRFIXEDSZ + datalen; 15629989Skjd if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 15718143Sralph return (-1); 15818143Sralph cp += n; 15929989Skjd putshort(type, cp); 16029989Skjd cp += sizeof(u_short); 16129989Skjd putshort(class, cp); 16229989Skjd cp += sizeof(u_short); 16329989Skjd putlong(0, cp); 16418143Sralph cp += sizeof(u_long); 16529989Skjd putshort(datalen, cp); 16629989Skjd cp += sizeof(u_short); 16718143Sralph if (datalen) { 16818143Sralph bcopy(data, cp, datalen); 16918143Sralph cp += datalen; 17018143Sralph } 17129989Skjd if ( (op == UPDATED) || (op == UPDATEDA) ) { 17229989Skjd hp->ancount = htons(0); 17329989Skjd break; 17429989Skjd } 17529989Skjd /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */ 17618143Sralph 17729989Skjd case UPDATEA: /* Add new resource record */ 17818143Sralph buflen -= RRFIXEDSZ + datalen; 17918143Sralph if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 18018143Sralph return (-1); 18118143Sralph cp += n; 18229989Skjd putshort(newrr->r_type, cp); 18329989Skjd cp += sizeof(u_short); 18429989Skjd putshort(newrr->r_class, cp); 18529989Skjd cp += sizeof(u_short); 18629989Skjd putlong(0, cp); 18718143Sralph cp += sizeof(u_long); 18829989Skjd putshort(newrr->r_size, cp); 18929989Skjd cp += sizeof(u_short); 19018143Sralph if (newrr->r_size) { 19118143Sralph bcopy(newrr->r_data, cp, newrr->r_size); 19218143Sralph cp += newrr->r_size; 19318143Sralph } 19429989Skjd hp->ancount = htons(0); 19518143Sralph break; 19629989Skjd 19729989Skjd #endif ALLOW_UPDATES 19818143Sralph } 19918143Sralph return (cp - buf); 20018143Sralph } 201