From bf555703f27295798de30fa8c04d727410788f66 Mon Sep 17 00:00:00 2001 From: Bob Halley Date: Wed, 1 Sep 1999 20:50:34 +0000 Subject: [PATCH] OPT support --- bin/tests/printmsg.c | 23 +++-- bin/tests/sdig.c | 73 ++++++++++++- lib/dns/include/dns/message.h | 2 +- lib/dns/message.c | 42 ++++---- lib/dns/rdata/generic/opt_41.c | 181 +++++++++++++++++++++++++++++++++ lib/dns/rdata/generic/opt_41.h | 24 +++++ 6 files changed, 318 insertions(+), 27 deletions(-) create mode 100644 lib/dns/rdata/generic/opt_41.c create mode 100644 lib/dns/rdata/generic/opt_41.h diff --git a/bin/tests/printmsg.c b/bin/tests/printmsg.c index 6ad2894f4f..20135b3b55 100644 --- a/bin/tests/printmsg.c +++ b/bin/tests/printmsg.c @@ -90,7 +90,7 @@ printsection(dns_message_t *msg, dns_section_t sectionid, char *section_name) char t[1000]; isc_boolean_t first; isc_boolean_t no_rdata; - + if (sectionid == DNS_SECTION_QUESTION) no_rdata = ISC_TRUE; else @@ -117,11 +117,22 @@ printsection(dns_message_t *msg, dns_section_t sectionid, char *section_name) for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { - result = dns_rdataset_totext(rdataset, print_name, - ISC_FALSE, no_rdata, - &target); - if (result != DNS_R_SUCCESS) - return (result); + if (rdataset->type == dns_rdatatype_opt) { + /* + * XXX + */ + printf("OPT: udp=%u, ttl=%u\n", + (unsigned int)rdataset->rdclass, + (unsigned int)rdataset->ttl); + } else { + result = dns_rdataset_totext(rdataset, + print_name, + ISC_FALSE, + no_rdata, + &target); + if (result != DNS_R_SUCCESS) + return (result); + } #ifdef USEINITALWS if (first) { print_name = &empty_name; diff --git a/bin/tests/sdig.c b/bin/tests/sdig.c index 5fb29df540..10cf902f0a 100644 --- a/bin/tests/sdig.c +++ b/bin/tests/sdig.c @@ -40,6 +40,8 @@ extern int h_errno; #include #include #include +#include +#include #include #include #include @@ -47,6 +49,8 @@ extern int h_errno; #include "printmsg.h" +#define SDIG_BUFFER_SIZE 2048 + static dns_message_t *message = NULL; static isc_boolean_t have_ipv6 = ISC_FALSE; @@ -89,6 +93,49 @@ add_type(dns_message_t *message, dns_name_t *name, dns_rdataclass_t rdclass, ISC_LIST_APPEND(name->list, rdataset, link); } +static void +add_opt(dns_message_t *message, dns_name_t *name, isc_uint16_t udpsize) { + dns_rdataset_t *rdataset; + dns_rdatalist_t *rdatalist; + dns_rdata_t *rdata; + isc_result_t result; + + rdataset = NULL; + result = dns_message_gettemprdataset(message, &rdataset); + check_result(result, "dns_message_gettemprdataset()"); + dns_rdataset_init(rdataset); + rdatalist = NULL; + result = dns_message_gettemprdatalist(message, &rdatalist); + check_result(result, "dns_message_gettemprdatalist()"); + rdata = NULL; + result = dns_message_gettemprdata(message, &rdata); + check_result(result, "dns_message_gettemprdata()"); + + rdatalist->type = dns_rdatatype_opt; + rdatalist->covers = 0; + + /* + * Set Maximum UDP buffer size. + */ + rdatalist->rdclass = udpsize; + + /* + * Set EXTENDED-RCODE, VERSION, and Z to 0. + */ + rdatalist->ttl = 0; + + /* + * No ENDS options. + */ + rdata->data = NULL; + rdata->length = 0; + + ISC_LIST_INIT(rdatalist->rdata); + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + dns_rdatalist_tordataset(rdatalist, rdataset); + ISC_LIST_APPEND(name->list, rdataset, link); +} + static void hex_dump(isc_buffer_t *b) { @@ -167,9 +214,10 @@ int main(int argc, char *argv[]) { char *server; unsigned int port; - isc_boolean_t vc, have_name, have_type; + isc_boolean_t vc, have_name, have_type, edns0; dns_fixedname_t fname; dns_name_t *name; + dns_name_t optname; dns_rdatatype_t rdtype; dns_rdataclass_t rdclass, nclass; size_t len; @@ -182,8 +230,8 @@ main(int argc, char *argv[]) { isc_task_t *task; isc_socketmgr_t *socketmgr; isc_socket_t *sock; - unsigned char *data[512]; - unsigned char *data2[512]; + unsigned char *data[SDIG_BUFFER_SIZE]; + unsigned char *data2[SDIG_BUFFER_SIZE]; isc_sockaddr_t sockaddr; int i; @@ -220,9 +268,12 @@ main(int argc, char *argv[]) { have_name = ISC_FALSE; have_type = ISC_FALSE; rdclass = dns_rdataclass_in; + edns0 = ISC_FALSE; dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); + dns_name_init(&optname, NULL); + dns_name_clone(dns_rootname, &optname); message = NULL; result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message); check_result(result, "dns_message_create()"); @@ -243,6 +294,12 @@ main(int argc, char *argv[]) { argc--; } else if (strcmp(argv[0], "+vc") == 0) { fatal("TCP transport not yet implemented"); + } else if (strcmp(argv[0], "+edns0") == 0) { + if (!edns0) { + add_opt(message, &optname, + (isc_uint16_t)SDIG_BUFFER_SIZE); + edns0 = ISC_TRUE; + } } else { len = strlen(argv[0]); tr.base = argv[0]; @@ -283,6 +340,8 @@ main(int argc, char *argv[]) { message->opcode = dns_opcode_query; message->flags |= DNS_MESSAGEFLAG_RD; dns_message_addname(message, name, DNS_SECTION_QUESTION); + if (edns0) + dns_message_addname(message, &optname, DNS_SECTION_ADDITIONAL); isc_buffer_init(&b, data, sizeof data, ISC_BUFFERTYPE_BINARY); result = dns_message_renderbegin(message, &b); @@ -290,9 +349,17 @@ main(int argc, char *argv[]) { result = dns_message_rendersection(message, DNS_SECTION_QUESTION, 0, 0); check_result(result, "dns_message_rendersection()"); + if (edns0) { + result = dns_message_rendersection(message, + DNS_SECTION_ADDITIONAL, + 0, 0); + check_result(result, "dns_message_rendersection()"); + } result = dns_message_renderend(message); check_result(result, "dns_message_renderend()"); + (void)printmessage(message); + get_address(server, port, &sockaddr); result = isc_socket_create(socketmgr, isc_sockaddr_pf(&sockaddr), diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index 482dd1997a..41bcf08046 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -116,7 +116,7 @@ struct dns_message { /* private from here down */ dns_namelist_t sections[DNS_SECTION_MAX]; dns_name_t *cursors[DNS_SECTION_MAX]; - dns_rdata_t *opt; + dns_rdataset_t *opt; int state; unsigned int from_to_wire : 2; diff --git a/lib/dns/message.c b/lib/dns/message.c index 9631755f7f..163d9de2ec 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -936,8 +936,10 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, for (count = 0 ; count < msg->counts[sectionid] ; count++) { int recstart = source->current; + isc_boolean_t skip_search; section = &msg->sections[sectionid]; + skip_search = ISC_FALSE; name = newname(msg); if (name == NULL) return (DNS_R_NOMEMORY); @@ -983,16 +985,32 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, return (DNS_R_FORMERR); /* - * If it is a tsig, verify that it is in the additional data - * section, and switch sections for the rest of this rdata. + * Special type handling for TSIG and OPT. */ if (rdtype == dns_rdatatype_tsig) { + /* + * If it is a tsig, verify that it is in the + * additional data section, and switch sections for + * the rest of this rdata. + */ if (sectionid != DNS_SECTION_ADDITIONAL) return (DNS_R_FORMERR); if (rdclass != dns_rdataclass_any) return (DNS_R_FORMERR); section = &msg->sections[DNS_SECTION_TSIG]; msg->tsigstart = recstart; + skip_search = ISC_TRUE; + } else if (rdtype == dns_rdatatype_opt) { + /* + * The name of an OPT record must be ".", it + * must be in the additional data section, and + * it must be the first OPT we've seen. + */ + if (!dns_name_equal(dns_rootname, name) || + sectionid != DNS_SECTION_ADDITIONAL || + msg->opt != NULL) + return (DNS_R_FORMERR); + skip_search = ISC_TRUE; } /* @@ -1008,8 +1026,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, * If we are doing a dynamic update don't bother searching * for a name, just append this one to the end of the message. */ - if (preserve_order || msg->opcode == dns_opcode_update - || rdtype == dns_rdatatype_tsig) { + if (preserve_order || msg->opcode == dns_opcode_update || + skip_search) { ISC_LIST_APPEND(*section, name, link); } else { /* @@ -1031,14 +1049,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, } } - /* - * If this is an OPT record, There Can Be Only One. - */ -#if 0 /* until there is a dns_rdatatype_opt XXXMLG */ - if (rdtype == dns_rdatatype_opt && msg->opt != NULL) - return (DNS_R_FORMERR); -#endif - /* * Read the rdata from the wire format. Interpret the * rdata according to its actual class, even if it had a @@ -1067,8 +1077,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, * Search name for the particular type and class. * Skip this stage if in update mode, or this is a TSIG. */ - if (preserve_order || msg->opcode == dns_opcode_update - || rdtype == dns_rdatatype_tsig) + if (preserve_order || msg->opcode == dns_opcode_update || + skip_search) result = DNS_R_NOTFOUND; else result = findtype(&rdataset, name, rdtype, covers); @@ -1117,10 +1127,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, /* * If this is an OPT record, remember it. */ -#if 0 /* until there is a dns_rdatatype_opt XXXMLG */ if (rdtype == dns_rdatatype_opt) - msg->opt = rdata; -#endif + msg->opt = rdataset; } return (DNS_R_SUCCESS); diff --git a/lib/dns/rdata/generic/opt_41.c b/lib/dns/rdata/generic/opt_41.c new file mode 100644 index 0000000000..8b54d4a90e --- /dev/null +++ b/lib/dns/rdata/generic/opt_41.c @@ -0,0 +1,181 @@ +/* + * Copyright (C) 1998, 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + + /* $Id: opt_41.c,v 1.1 1999/09/01 20:50:04 halley Exp $ */ + +#ifndef RDATA_GENERIC_OPT_41_C +#define RDATA_GENERIC_OPT_41_C + +static inline dns_result_t +fromtext_opt(dns_rdataclass_t rdclass, dns_rdatatype_t type, + isc_lex_t *lexer, dns_name_t *origin, + isc_boolean_t downcase, isc_buffer_t *target) +{ + /* + * OPT records do not have a text format. + */ + + REQUIRE(type == 41); + + (void)rdclass; + (void)lexer; + (void)origin; + (void)downcase; + (void)target; + + return (DNS_R_NOTIMPLEMENTED); +} + +static inline dns_result_t +totext_opt(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ + /* + * OPT records do not have a text format. + */ + + REQUIRE(rdata->type == 41); + + (void)tctx; + (void)target; + + return (DNS_R_NOTIMPLEMENTED); +} + +static inline dns_result_t +fromwire_opt(dns_rdataclass_t rdclass, dns_rdatatype_t type, + isc_buffer_t *source, dns_decompress_t *dctx, + isc_boolean_t downcase, isc_buffer_t *target) +{ + isc_region_t sregion; + isc_region_t tregion; + isc_uint16_t option, length; + unsigned int total; + + REQUIRE(type == 41); + + (void)rdclass; + (void)dctx; + (void)downcase; + + isc_buffer_active(source, &sregion); + total = 0; + while (sregion.length != 0) { + if (sregion.length < 4) + return (DNS_R_UNEXPECTEDEND); + option = uint16_fromregion(&sregion); + length = uint16_fromregion(&sregion); + isc_region_consume(&sregion, 4); + total += 4; + if (sregion.length < length) + return (DNS_R_UNEXPECTEDEND); + isc_region_consume(&sregion, length); + total += length; + } + + isc_buffer_active(source, &sregion); + isc_buffer_available(target, &tregion); + if (tregion.length < total) + return (DNS_R_NOSPACE); + memcpy(tregion.base, sregion.base, total); + isc_buffer_forward(source, total); + isc_buffer_add(target, total); + + return (DNS_R_SUCCESS); +} + +static inline dns_result_t +towire_opt(dns_rdata_t *rdata, dns_compress_t *cctx, isc_buffer_t *target) { + + REQUIRE(rdata->type == 41); + + (void)cctx; + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_opt(dns_rdata_t *rdata1, dns_rdata_t *rdata2) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == 41); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (compare_region(&r1, &r2)); +} + +static inline dns_result_t +fromstruct_opt(dns_rdataclass_t rdclass, dns_rdatatype_t type, void *source, + isc_buffer_t *target) +{ + REQUIRE(type == 41); + + (void)rdclass; + (void)source; + (void)target; + + return (DNS_R_NOTIMPLEMENTED); +} + +static inline dns_result_t +tostruct_opt(dns_rdata_t *rdata, void *target, isc_mem_t *mctx) { + + REQUIRE(rdata->type == 41); + + (void)target; + (void)mctx; + + return (DNS_R_NOTIMPLEMENTED); +} + +static inline void +freestruct_opt(void *source) { + (void)source; +} + +static inline dns_result_t +additionaldata_opt(dns_rdata_t *rdata, dns_additionaldatafunc_t add, + void *arg) +{ + REQUIRE(rdata->type == 41); + + (void)add; + (void)arg; + + return (DNS_R_SUCCESS); +} + +static inline dns_result_t +digest_opt(dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg) { + + /* + * OPT records are not digested. + */ + + REQUIRE(rdata->type == 41); + + (void)digest; + (void)arg; + + return (DNS_R_NOTIMPLEMENTED); +} + +#endif /* RDATA_GENERIC_OPT_41_C */ diff --git a/lib/dns/rdata/generic/opt_41.h b/lib/dns/rdata/generic/opt_41.h new file mode 100644 index 0000000000..8d114d15d8 --- /dev/null +++ b/lib/dns/rdata/generic/opt_41.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 1998, 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + + /* $Id: opt_41.h,v 1.1 1999/09/01 20:50:04 halley Exp $ */ + +typedef struct dns_rdata_opt { + dns_rdatacommon_t common; + isc_mem_t *mctx; /* if required */ + /* XXXRTH Not implemented. */ +} dns_rdata_opt_t; -- GitLab