1: /* 2: * Copyright (c) 1985 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #if defined(LIBC_SCCS) && !defined(lint) 8: static char sccsid[] = "@(#)res_mkquery.c 6.3 (Berkeley) 3/17/86"; 9: #endif LIBC_SCCS and not lint 10: 11: #include <stdio.h> 12: #include <sys/types.h> 13: #include <netinet/in.h> 14: #include <arpa/nameser.h> 15: #include <resolv.h> 16: 17: extern char *sprintf(); 18: 19: /* 20: * Form all types of queries. 21: * Returns the size of the result or -1. 22: */ 23: res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen) 24: int op; /* opcode of query */ 25: char *dname; /* domain name */ 26: int class, type; /* class and type of query */ 27: char *data; /* resource record data */ 28: int datalen; /* length of data */ 29: struct rrec *newrr; /* new rr for modify or append */ 30: char *buf; /* buffer to put query */ 31: int buflen; /* size of buffer */ 32: { 33: register HEADER *hp; 34: register char *cp; 35: register int n; 36: char dnbuf[MAXDNAME]; 37: char *dnptrs[10], **dpp, **lastdnptr; 38: extern char *index(); 39: 40: #ifdef DEBUG 41: if (_res.options & RES_DEBUG) 42: printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type); 43: #endif DEBUG 44: /* 45: * Initialize header fields. 46: */ 47: hp = (HEADER *) buf; 48: hp->id = htons(++_res.id); 49: hp->opcode = op; 50: hp->qr = hp->aa = hp->tc = hp->ra = 0; 51: hp->pr = (_res.options & RES_PRIMARY) != 0; 52: hp->rd = (_res.options & RES_RECURSE) != 0; 53: hp->rcode = NOERROR; 54: hp->qdcount = 0; 55: hp->ancount = 0; 56: hp->nscount = 0; 57: hp->arcount = 0; 58: cp = buf + sizeof(HEADER); 59: buflen -= sizeof(HEADER); 60: dpp = dnptrs; 61: *dpp++ = buf; 62: *dpp++ = NULL; 63: lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); 64: /* 65: * If the domain name contains no dots (single label), then 66: * append the default domain name to the one given. 67: */ 68: if ((_res.options & RES_DEFNAMES) && dname != 0 && dname[0] != '\0' && 69: index(dname, '.') == NULL) { 70: if (!(_res.options & RES_INIT)) 71: if (res_init() == -1) 72: return(-1); 73: if (_res.defdname[0] != '\0') 74: dname = sprintf(dnbuf, "%s.%s", dname, _res.defdname); 75: } 76: /* 77: * perform opcode specific processing 78: */ 79: switch (op) { 80: case QUERY: 81: case CQUERYM: 82: case CQUERYU: 83: buflen -= QFIXEDSZ; 84: if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 85: return (-1); 86: cp += n; 87: buflen -= n; 88: putshort(type, cp); 89: cp += sizeof(u_short); 90: putshort(class, cp); 91: cp += sizeof(u_short); 92: hp->qdcount = htons(1); 93: if (op == QUERY || data == NULL) 94: break; 95: /* 96: * Make an additional record for completion domain. 97: */ 98: buflen -= RRFIXEDSZ; 99: if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0) 100: return (-1); 101: cp += n; 102: buflen -= n; 103: putshort(T_NULL, cp); 104: cp += sizeof(u_short); 105: putshort(class, cp); 106: cp += sizeof(u_short); 107: putlong(0, cp); 108: cp += sizeof(u_long); 109: putshort(0, cp); 110: cp += sizeof(u_short); 111: hp->arcount = htons(1); 112: break; 113: 114: case IQUERY: 115: /* 116: * Initialize answer section 117: */ 118: if (buflen < 1 + RRFIXEDSZ + datalen) 119: return (-1); 120: *cp++ = '\0'; /* no domain name */ 121: putshort(type, cp); 122: cp += sizeof(u_short); 123: putshort(class, cp); 124: cp += sizeof(u_short); 125: putlong(0, cp); 126: cp += sizeof(u_long); 127: putshort(datalen, cp); 128: cp += sizeof(u_short); 129: if (datalen) { 130: bcopy(data, cp, datalen); 131: cp += datalen; 132: } 133: hp->ancount = htons(1); 134: break; 135: 136: #ifdef notdef 137: case UPDATED: 138: /* 139: * Put record to be added or deleted in additional section 140: */ 141: buflen -= RRFIXEDSZ + datalen; 142: if ((n = dn_comp(dname, cp, buflen, NULL, NULL)) < 0) 143: return (-1); 144: cp += n; 145: *((u_short *)cp) = htons(type); 146: cp += sizeof(u_short); 147: *((u_short *)cp) = htons(class); 148: cp += sizeof(u_short); 149: *((u_long *)cp) = 0; 150: cp += sizeof(u_long); 151: *((u_short *)cp) = htons(datalen); 152: cp += sizeof(u_short); 153: if (datalen) { 154: bcopy(data, cp, datalen); 155: cp += datalen; 156: } 157: break; 158: 159: case UPDATEM: 160: /* 161: * Record to be modified followed by its replacement 162: */ 163: buflen -= RRFIXEDSZ + datalen; 164: if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 165: return (-1); 166: cp += n; 167: *((u_short *)cp) = htons(type); 168: cp += sizeof(u_short); 169: *((u_short *)cp) = htons(class); 170: cp += sizeof(u_short); 171: *((u_long *)cp) = 0; 172: cp += sizeof(u_long); 173: *((u_short *)cp) = htons(datalen); 174: cp += sizeof(u_short); 175: if (datalen) { 176: bcopy(data, cp, datalen); 177: cp += datalen; 178: } 179: 180: case UPDATEA: 181: buflen -= RRFIXEDSZ + newrr->r_size; 182: if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 183: return (-1); 184: cp += n; 185: *((u_short *)cp) = htons(newrr->r_type); 186: cp += sizeof(u_short); 187: *((u_short *)cp) = htons(newrr->r_type); 188: cp += sizeof(u_short); 189: *((u_long *)cp) = htonl(newrr->r_ttl); 190: cp += sizeof(u_long); 191: *((u_short *)cp) = htons(newrr->r_size); 192: cp += sizeof(u_short); 193: if (newrr->r_size) { 194: bcopy(newrr->r_data, cp, newrr->r_size); 195: cp += newrr->r_size; 196: } 197: break; 198: #endif 199: } 200: return (cp - buf); 201: }