118548Sralph /* 221387Sdist * Copyright (c) 1985 Regents of the University of California. 333679Sbostic * All rights reserved. 433679Sbostic * 542627Sbostic * %sccs.include.redist.c% 618548Sralph */ 718548Sralph 826634Sdonn #if defined(LIBC_SCCS) && !defined(lint) 9*47045Sbostic static char sccsid[] = "@(#)res_mkquery.c 6.16 (Berkeley) 03/06/91"; 1033679Sbostic #endif /* LIBC_SCCS and not lint */ 1121387Sdist 1245845Swilliam #include <sys/param.h> 1318143Sralph #include <netinet/in.h> 1424082Skjd #include <arpa/nameser.h> 1526895Skjd #include <resolv.h> 1646604Sbostic #include <stdio.h> 1746604Sbostic #include <string.h> 1818143Sralph 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 */ 2546604Sbostic const char *dname; /* domain name */ 2618143Sralph int class, type; /* class and type of query */ 2746604Sbostic const char *data; /* resource record data */ 2818143Sralph int datalen; /* length of data */ 2946604Sbostic const 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 *dnptrs[10], **dpp, **lastdnptr; 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); 6746604Sbostic if ((n = dn_comp((u_char *)dname, (u_char *)cp, buflen, 6846604Sbostic (u_char **)dnptrs, (u_char **)lastdnptr)) < 0) 6918143Sralph return (-1); 7018143Sralph cp += n; 7118143Sralph buflen -= n; 72*47045Sbostic __putshort(type, (u_char *)cp); 7318143Sralph cp += sizeof(u_short); 74*47045Sbostic __putshort(class, (u_char *)cp); 7518143Sralph cp += sizeof(u_short); 7623872Skjd hp->qdcount = htons(1); 7718143Sralph if (op == QUERY || data == NULL) 7818143Sralph break; 7918143Sralph /* 8018143Sralph * Make an additional record for completion domain. 8118143Sralph */ 8218528Sralph buflen -= RRFIXEDSZ; 8346604Sbostic if ((n = dn_comp((u_char *)data, (u_char *)cp, buflen, 8446604Sbostic (u_char **)dnptrs, (u_char **)lastdnptr)) < 0) 8518143Sralph return (-1); 8618143Sralph cp += n; 8718143Sralph buflen -= n; 88*47045Sbostic __putshort(T_NULL, (u_char *)cp); 8918143Sralph cp += sizeof(u_short); 90*47045Sbostic __putshort(class, (u_char *)cp); 9118143Sralph cp += sizeof(u_short); 92*47045Sbostic __putlong(0, (u_char *)cp); 9318143Sralph cp += sizeof(u_long); 94*47045Sbostic __putshort(0, (u_char *)cp); 9518143Sralph cp += sizeof(u_short); 9623872Skjd hp->arcount = htons(1); 9718143Sralph break; 9818143Sralph 9918143Sralph case IQUERY: 10018143Sralph /* 10118143Sralph * Initialize answer section 10218143Sralph */ 10318143Sralph if (buflen < 1 + RRFIXEDSZ + datalen) 10418143Sralph return (-1); 10518143Sralph *cp++ = '\0'; /* no domain name */ 106*47045Sbostic __putshort(type, (u_char *)cp); 10718143Sralph cp += sizeof(u_short); 108*47045Sbostic __putshort(class, (u_char *)cp); 10918143Sralph cp += sizeof(u_short); 110*47045Sbostic __putlong(0, (u_char *)cp); 11118143Sralph cp += sizeof(u_long); 112*47045Sbostic __putshort(datalen, (u_char *)cp); 11318143Sralph cp += sizeof(u_short); 11418143Sralph if (datalen) { 11518143Sralph bcopy(data, cp, datalen); 11618143Sralph cp += datalen; 11718143Sralph } 11823872Skjd hp->ancount = htons(1); 11918143Sralph break; 12018143Sralph 12129989Skjd #ifdef ALLOW_UPDATES 12229989Skjd /* 12329989Skjd * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA 12429989Skjd * (Record to be modified is followed by its replacement in msg.) 12529989Skjd */ 12629989Skjd case UPDATEM: 12729989Skjd case UPDATEMA: 12829989Skjd 12918143Sralph case UPDATED: 13018143Sralph /* 13129989Skjd * The res code for UPDATED and UPDATEDA is the same; user 13229989Skjd * calls them differently: specifies data for UPDATED; server 13329989Skjd * ignores data if specified for UPDATEDA. 13418143Sralph */ 13529989Skjd case UPDATEDA: 13618143Sralph buflen -= RRFIXEDSZ + datalen; 13729989Skjd if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 13818143Sralph return (-1); 13918143Sralph cp += n; 14046496Sbostic __putshort(type, cp); 14129989Skjd cp += sizeof(u_short); 14246496Sbostic __putshort(class, cp); 14329989Skjd cp += sizeof(u_short); 14446496Sbostic __putlong(0, cp); 14518143Sralph cp += sizeof(u_long); 14646496Sbostic __putshort(datalen, cp); 14729989Skjd cp += sizeof(u_short); 14818143Sralph if (datalen) { 14918143Sralph bcopy(data, cp, datalen); 15018143Sralph cp += datalen; 15118143Sralph } 15229989Skjd if ( (op == UPDATED) || (op == UPDATEDA) ) { 15329989Skjd hp->ancount = htons(0); 15429989Skjd break; 15529989Skjd } 15629989Skjd /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */ 15718143Sralph 15829989Skjd case UPDATEA: /* Add new resource record */ 15918143Sralph buflen -= RRFIXEDSZ + datalen; 16018143Sralph if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 16118143Sralph return (-1); 16218143Sralph cp += n; 16346496Sbostic __putshort(newrr->r_type, cp); 16429989Skjd cp += sizeof(u_short); 16546496Sbostic __putshort(newrr->r_class, cp); 16629989Skjd cp += sizeof(u_short); 16746496Sbostic __putlong(0, cp); 16818143Sralph cp += sizeof(u_long); 16946496Sbostic __putshort(newrr->r_size, cp); 17029989Skjd cp += sizeof(u_short); 17118143Sralph if (newrr->r_size) { 17218143Sralph bcopy(newrr->r_data, cp, newrr->r_size); 17318143Sralph cp += newrr->r_size; 17418143Sralph } 17529989Skjd hp->ancount = htons(0); 17618143Sralph break; 17729989Skjd 17829989Skjd #endif ALLOW_UPDATES 17918143Sralph } 18018143Sralph return (cp - buf); 18118143Sralph } 182