/* * Form all types of queries. * Returns the size of the result or -1. */ int res_mkquery ( int op, /* opcode of query */ const char *dname, /* domain name */ int Class, /* class of query */ int type, /* type of query */ const u_char *data, /* resource record data */ int datalen, /* length of data */ const u_char *newrr_in, /* new rr for modify or append */ u_char *buf, /* buffer to put query */ int buflen) /* size of buffer */ { struct rrec *newrr = (struct rrec *) newrr_in; HEADER *hp; u_char *cp; u_char *dnptrs[20]; u_char **dpp, **lastdnptr; int n; if ((_res.options & RES_INIT) == 0 && res_init() == -1) { h_errno = NETDB_INTERNAL; return (-1); } if (_res.options & RES_DEBUG) (*_printf) (";; res_mkquery(%d, %s, %d, %d)\n", op, dname, Class, type); /* Initialize header fields. */ if (!buf || buflen < HFIXEDSZ) return (-1); memset (buf, 0, HFIXEDSZ); hp = (HEADER*) buf; hp->id = htons (++_res.id); hp->opcode = op; hp->rd = (_res.options & RES_RECURSE) != 0; hp->rcode = NOERROR; cp = buf + HFIXEDSZ; buflen -= HFIXEDSZ; dpp = dnptrs; *dpp++ = buf; *dpp++ = NULL; lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; /* perform opcode specific processing */ switch (op) { case STATUS: /** \todo Handle STATUS case */ return (-1); case QUERY: /* fallthrough */ case NS_NOTIFY_OP: /* Notify secondary server of SOA change */ buflen -= QFIXEDSZ; if (buflen < 0) return (-1); if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) return (-1); cp += n; buflen -= n; __putshort (type, cp); cp += INT16SZ; __putshort (Class, cp); cp += INT16SZ; hp->qdcount = htons (1); if (op == QUERY || !data) break; /* * Make an additional record for completion domain. */ buflen -= RRFIXEDSZ; n = dn_comp ((char*)data, cp, buflen, dnptrs, lastdnptr); if (n < 0) return (-1); cp += n; buflen -= n; __putshort (T_NULL, cp); cp += INT16SZ; __putshort (Class, cp); cp += INT16SZ; __putlong (0, cp); cp += INT32SZ; __putshort (0, cp); cp += INT16SZ; hp->arcount = htons (1); break; case IQUERY: /* * Initialize answer section */ if (buflen < 1 + RRFIXEDSZ + datalen) return (-1); *cp++ = '\0'; /* no domain name */ __putshort (type, cp); cp += INT16SZ; __putshort (Class, cp); cp += INT16SZ; __putlong (0, cp); cp += INT32SZ; __putshort (datalen, cp); cp += INT16SZ; if (datalen) { memcpy (cp,data,datalen); cp += datalen; } hp->ancount = htons (1); break; #if ALLOW_UPDATES /* * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA * (Record to be modified is followed by its replacement in msg.) */ case UPDATEM: case UPDATEMA: case UPDATED: /* * The res code for UPDATED and UPDATEDA is the same; user * calls them differently: specifies data for UPDATED; server * ignores data if specified for UPDATEDA. */ case UPDATEDA: buflen -= RRFIXEDSZ + datalen; if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) return (-1); cp += n; __putshort (type, cp); cp += INT16SZ; __putshort (Class, cp); cp += INT16SZ; __putlong (0, cp); cp += INT32SZ; __putshort (datalen, cp); cp += INT16SZ; if (datalen) { memcpy (cp,data,datalen); cp += datalen; } if (op == UPDATED || op == UPDATEDA) { hp->ancount = 0; break; } /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */ case UPDATEA: /* Add new resource record */ buflen -= RRFIXEDSZ + datalen; if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) return (-1); cp += n; __putshort (newrr->r_type, cp); cp += INT16SZ; __putshort (newrr->r_class, cp); cp += INT16SZ; __putlong (0, cp); cp += INT32SZ; __putshort (newrr->r_size, cp); cp += INT16SZ; if (newrr->r_size) { memcpy (cp,newrr->r_data,newrr->r_size); cp += newrr->r_size; } hp->ancount = 0; break; #endif default: return (-1); } #if ALLOW_UPDATES == 0 ARGSUSED (newrr); ARGSUSED (newrr_in); #endif return (cp - buf); }
int build_rr(char* p, PDNS_RECORD ptr, int qclass) { int i = 0; int n = 0; char* cp = p; char* temp = NULL; unsigned int index = 0; i = put_qname(cp, ptr->pName); cp = p + i; __putshort(ptr->wType, (u_char *)cp); i += sizeof(u_short); cp = p + i; __putshort(qclass, (u_char *)cp); i += sizeof(u_short); cp = p + i; __putlong(ptr->dwTtl, (u_char*)cp); i += sizeof(u_long); cp = p + i; switch (ptr->wType) { case DNS_TYPE_A: __putshort(sizeof(ptr->Data.A), (u_char*)cp); //RDLENGTH i += sizeof(u_short); cp = p + i; memcpy(cp, &(ptr->Data.A), sizeof(ptr->Data.A)); i += sizeof(ptr->Data.A); break; case DNS_TYPE_NS: case DNS_TYPE_MD: case DNS_TYPE_MF: case DNS_TYPE_CNAME: case DNS_TYPE_MB: case DNS_TYPE_MG: case DNS_TYPE_MR: case DNS_TYPE_PTR: temp = cp; // hold the spot for RD length i += sizeof(u_short); cp = p+i; n = put_qname(cp, ptr->Data.Ptr.pNameHost); i += n; __putshort(n, (u_char*)temp); //set RDLENGTH break; case DNS_TYPE_TEXT: case DNS_TYPE_HINFO: case DNS_TYPE_ISDN: case DNS_TYPE_X25: temp = cp; // hold the spot for RDLENGTH i += sizeof(u_short); cp = p + i; n = 0; for (index = 0; index < ptr->Data.Txt.dwStringCount; index++) { *cp = (int)(strlen(ptr->Data.Txt.pStringArray[index])); n += *cp; n++; strcpy(++cp, ptr->Data.Txt.pStringArray[index]); } i += n; __putshort(n,(u_char*)temp); // set RDLENGTH break; case DNS_TYPE_SRV: temp = cp; // hold the spot for RDLENGTH i += sizeof(u_short); cp = p + i; // priority __putshort(ptr->Data.Srv.wPriority, (u_char*)cp); i += sizeof(u_short); cp = p + i; //weight __putshort(ptr->Data.Srv.wWeight, (u_char*)cp); i += sizeof(u_short); cp = p + i; //port __putshort(ptr->Data.Srv.wPort, (u_char*)cp); i += sizeof(u_short); cp = p + i; n = put_qname(cp, ptr->Data.Srv.pNameTarget); i+=n; __putshort((u_short)(n + sizeof(u_short)*3),(u_char*)temp); break; case DNS_TYPE_MX: case DNS_TYPE_AFSDB: case DNS_TYPE_RT: temp = cp; // hold the spot for RDLENGTH i += sizeof(u_short); cp = p + i; __putshort(ptr->Data.Mx.wPreference, (u_char*)cp); // put wPreference i += sizeof(u_short); cp = p + i; n = put_qname(cp, ptr->Data.Mx.pNameExchange); i+=n; __putshort((u_short)(n+sizeof(u_short)),(u_char*)temp); break; case DNS_TYPE_SOA: temp = cp; // hold the spot for RDLENGTH i += sizeof(u_short); cp = p + i; // primary server name n = put_qname(cp, ptr->Data.Soa.pNamePrimaryServer); i+= n; cp = p + i; //the person responsible for this zone. n += put_qname(cp, ptr->Data.Soa.pNameAdministrator); i += n; cp = p + i; //SERIAL __putlong(ptr->Data.Soa.dwSerialNo, cp); n += sizeof(u_long); i += sizeof(u_long); cp = p + i; //refresh __putlong(ptr->Data.Soa.dwRefresh, cp); n += sizeof(u_long); i += sizeof(u_long); cp = p + i; //retry __putlong(ptr->Data.Soa.dwRetry, cp); n += sizeof(u_long); i += sizeof(u_long); cp = p + i; // expire __putlong(ptr->Data.Soa.dwExpire, cp); n += sizeof(u_long); i += sizeof(u_long); cp = p + i; // minimum TTL __putlong(ptr->Data.Soa.dwDefaultTtl, cp); n += sizeof(u_long); i += sizeof(u_long); // set RDLength __putshort(n,(u_char*)temp); break; case DNS_TYPE_NULL: __putshort((short)ptr->Data.Null.dwByteCount, (u_char*)cp); //RDLENGTH i += sizeof(u_short); cp = p + i; memcpy(cp, ptr->Data.Null.Data, ptr->Data.Null.dwByteCount); i += ptr->Data.Null.dwByteCount; break; case DNS_TYPE_WKS: // needs more work temp = cp; // hold the spot for RDLENGTH i += sizeof(u_short); cp = p + i; // address memcpy(cp, &(ptr->Data.Wks.IpAddress), sizeof(ptr->Data.Wks.IpAddress)); n = sizeof(ptr->Data.Wks.IpAddress); i += sizeof(ptr->Data.Wks.IpAddress); cp = p + i; // protocol *cp = ptr->Data.Wks.chProtocol; i++; n++; cp = p + i; //bit mask memcpy(cp, &(ptr->Data.Wks.BitMask), sizeof(ptr->Data.Wks.BitMask)); n+=sizeof(ptr->Data.Wks.BitMask); i += n; // set RDLength __putshort(n,(u_char*)temp); break; case DNS_TYPE_MINFO: case DNS_TYPE_RP: temp = cp; // hold the spot for RDLENGTH i += sizeof(u_short); cp = p + i; // pNameMailbox n = put_qname(cp, ptr->Data.Minfo.pNameMailbox); i+= n; cp = p + i; // pNameErrorsMailbox; n += put_qname(cp, ptr->Data.Minfo.pNameMailbox); i += n; // set RDLength __putshort(n,(u_char*)temp); break; case DNS_TYPE_AAAA: __putshort(sizeof(ptr->Data.AAAA), (u_char*)cp); //RDLENGTH i += sizeof(u_short); cp = p + i; memcpy(cp, &(ptr->Data.AAAA), sizeof(ptr->Data.AAAA)); i += sizeof(ptr->Data.AAAA); break; } return i; }