diff --git a/bin/named/client.c b/bin/named/client.c new file mode 100644 index 0000000000..628f31634f --- /dev/null +++ b/bin/named/client.c @@ -0,0 +1,568 @@ +/* + * Copyright (C) 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. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "../../isc/util.h" /* XXX */ + +#define NS_CLIENT_TRACE +#ifdef NS_CLIENT_TRACE +#include +#define CTRACE(m) printf("client %p: %s\n", client, (m)) +#define MTRACE(m) printf("clientmgr %p: %s\n", manager, (m)) +#else +#define CTRACE(m) +#define MTRACE(m) +#endif + +#define SEND_BUFFER_SIZE 512 + +struct ns_clientmgr { + /* Unlocked. */ + unsigned int magic; + isc_mem_t * mctx; + isc_taskmgr_t * taskmgr; + isc_timermgr_t * timermgr; + isc_mutex_t lock; + /* Locked by lock. */ + isc_boolean_t exiting; + unsigned int nclients; + ISC_LIST(ns_client_t) clients; +}; + +#define MANAGER_MAGIC 0x4E53436DU /* NSCm */ +#define VALID_MANAGER(m) ((m) != NULL && \ + (m)->magic == MANAGER_MAGIC) + + +static void clientmgr_destroy(ns_clientmgr_t *manager); + + +/*** + *** Client + ***/ + +/* + * Important note! + * + * All client state changes, other than that from idle to listening, occur + * as a result of events. This guarantees serialization and avoids the + * need for locking. + * + * If a routine is ever created that allows someone other than the client's + * task to change the client, then the client will have to be locked. + */ + +static inline void +client_free(ns_client_t *client) { + dns_dispatchevent_t **deventp; + + CTRACE("free"); + + isc_mempool_destroy(&client->sendbufs); + dns_message_destroy(&client->message); + isc_timer_detach(&client->timer); + if (client->dispentry != NULL) { + if (client->dispevent != NULL) + deventp = &client->dispevent; + else + deventp = NULL; + dns_dispatch_removerequest(client->dispatch, + &client->dispentry, + deventp); + } + if (client->dispatch != NULL) + dns_dispatch_detach(&client->dispatch); + isc_task_detach(&client->task); + client->magic = 0; + + isc_mem_put(client->manager->mctx, client, sizeof *client); +} + +void +ns_client_destroy(ns_client_t *client) { + ns_clientmgr_t *manager; + isc_boolean_t need_clientmgr_destroy = ISC_FALSE; + + REQUIRE(NS_CLIENT_VALID(client)); + + CTRACE("destroy"); + + manager = client->manager; + + LOCK(&manager->lock); + + INSIST(manager->nclients > 0); + manager->nclients--; + if (manager->nclients == 0 && manager->exiting) + need_clientmgr_destroy = ISC_TRUE; + ISC_LIST_UNLINK(manager->clients, client, link); + + UNLOCK(&manager->lock); + + client_free(client); + + if (need_clientmgr_destroy) + clientmgr_destroy(manager); +} + +static void +client_shutdown(isc_task_t *task, isc_event_t *event) { + ns_client_t *client; + + REQUIRE(event != NULL); + REQUIRE(event->type == ISC_TASKEVENT_SHUTDOWN); + client = event->arg; + REQUIRE(NS_CLIENT_VALID(client)); + REQUIRE(task == client->task); + + CTRACE("shutdown"); + + ns_client_destroy(client); + + isc_event_free(&event); +} + +void +ns_client_next(ns_client_t *client, isc_result_t result) { + + REQUIRE(NS_CLIENT_VALID(client)); + REQUIRE(client->state == ns_clientstate_listening || + client->state == ns_clientstate_working); + + CTRACE("next"); + + /* + * XXXRTH If result != ISC_R_SUCCESS: + * Log result if there is interest in doing so. + * If this is a TCP client, close the connection. + */ + (void)result; + + dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE); + if (client->dispevent != NULL) { + dns_dispatch_freeevent(client->dispatch, client->dispentry, + &client->dispevent); + client->state = ns_clientstate_listening; + } +} + +static void client_send(ns_client_t *client); + +static void +client_senddone(isc_task_t *task, isc_event_t *event) { + ns_client_t *client; + isc_socketevent_t *sevent = (isc_socketevent_t *)event; + + REQUIRE(sevent != NULL); + REQUIRE(sevent->common.type == ISC_SOCKEVENT_SENDDONE); + client = sevent->common.arg; + REQUIRE(NS_CLIENT_VALID(client)); + REQUIRE(task == client->task); + + CTRACE("senddone"); + + client->nsends--; + isc_mempool_put(client->sendbufs, sevent->region.base); + + isc_event_free(&event); + + /* + * If all of its sendbufs buffers were busy, the client might be + * waiting for one to become available. + */ + if (client->state == ns_clientstate_waiting) { + client->state = ns_clientstate_working; + client_send(client); + return; + } + /* XXXRTH need to add exit draining mode. */ +} + +static void +client_send(ns_client_t *client) { + isc_result_t result; + unsigned char *data; + isc_buffer_t buffer; + isc_region_t r; + + REQUIRE(NS_CLIENT_VALID(client)); + + CTRACE("send"); + + data = isc_mempool_get(client->sendbufs); + if (data == NULL) { + CTRACE("no buffers available"); + if (client->nsends > 0) { + /* + * We couldn't get memory, but there is at least one + * send outstanding. We arrange to be restarted when a + * send completes. + */ + CTRACE("waiting"); + INSIST(client->state == ns_clientstate_working); + client->state = ns_clientstate_waiting; + } else + ns_client_next(client, ISC_R_NOMEMORY); + return; + } + + isc_buffer_init(&buffer, data, SEND_BUFFER_SIZE, + ISC_BUFFERTYPE_BINARY); + result = dns_message_renderbegin(client->message, &buffer); + if (result != ISC_R_SUCCESS) + goto done; + result = dns_message_rendersection(client->message, + DNS_SECTION_QUESTION, 0, 0); + if (result != ISC_R_SUCCESS) + goto done; + result = dns_message_renderend(client->message); + if (result != ISC_R_SUCCESS) + goto done; + isc_buffer_used(&buffer, &r); + /* XXXRTH this only works for UDP clients. */ + CTRACE("sendto"); + result = isc_socket_sendto(dns_dispatch_getsocket(client->dispatch), + &r, client->task, client_senddone, client, + &client->dispevent->addr); + if (result == ISC_R_SUCCESS) + client->nsends++; + + done: + if (result != ISC_R_SUCCESS) + isc_mempool_put(client->sendbufs, data); + + ns_client_next(client, result); +} + +void +ns_client_error(ns_client_t *client, isc_result_t result) { + dns_rcode_t rcode; + + REQUIRE(NS_CLIENT_VALID(client)); + + CTRACE("error"); + + rcode = dns_result_torcode(result); + + result = dns_message_reply(client->message, ISC_TRUE); + if (result != ISC_R_SUCCESS) { + ns_client_next(client, result); + return; + } + client->message->rcode = rcode; + client_send(client); +} + +static void +client_recv(isc_task_t *task, isc_event_t *event) { + ns_client_t *client; + dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event; + isc_result_t result; + + REQUIRE(devent != NULL); + REQUIRE(devent->type == DNS_EVENT_DISPATCH); + client = devent->arg; + REQUIRE(NS_CLIENT_VALID(client)); + REQUIRE(task == client->task); + REQUIRE(client->dispentry != NULL); + + CTRACE("recv"); + + client->dispevent = devent; + if (devent->result != ISC_R_SUCCESS) { + ns_client_destroy(client); + return; + } + + client->state = ns_clientstate_working; + result = dns_message_parse(client->message, &devent->buffer); + if (result != ISC_R_SUCCESS) { + ns_client_error(client, result); + return; + } + INSIST((client->message->flags & DNS_MESSAGEFLAG_QR) == 0); + + /* + * Dispatch the request. + */ + switch (client->message->opcode) { +#if 0 + case dns_opcode_query: + CTRACE("query"); + ns_query_start(client); + break; +#endif + case dns_opcode_iquery: + CTRACE("iquery"); + ns_client_error(client, DNS_R_REFUSED); + default: + CTRACE("unknown opcode"); + ns_client_error(client, DNS_R_NOTIMP); + } +} + +static void +client_timeout(isc_task_t *task, isc_event_t *event) { + ns_client_t *client; + + REQUIRE(event != NULL); + REQUIRE(event->type == ISC_TIMEREVENT_LIFE || + event->type == ISC_TIMEREVENT_IDLE); + client = event->arg; + REQUIRE(NS_CLIENT_VALID(client)); + REQUIRE(task == client->task); + REQUIRE(client->timer != NULL); + + CTRACE("timeout"); + + isc_event_free(&event); + + ns_client_next(client, ISC_R_TIMEDOUT); +} + +static isc_result_t +client_create(ns_clientmgr_t *manager, ns_clienttype_t type, + ns_client_t **clientp) +{ + ns_client_t *client; + isc_result_t result; + + /* + * Caller must be holding the manager lock. + * + * Note: creating a client does not add the client to the manager's + * client list. The caller is responsible for that. + */ + + REQUIRE(clientp != NULL && *clientp == NULL); + + client = isc_mem_get(manager->mctx, sizeof *client); + if (client == NULL) + return (ISC_R_NOMEMORY); + + client->task = NULL; + result = isc_task_create(manager->taskmgr, manager->mctx, 0, + &client->task); + if (result != ISC_R_SUCCESS) + goto cleanup_client; + result = isc_task_onshutdown(client->task, client_shutdown, client); + if (result != ISC_R_SUCCESS) + goto cleanup_task; + + client->timer = NULL; + result = isc_timer_create(manager->timermgr, isc_timertype_inactive, + NULL, NULL, client->task, client_timeout, + client, &client->timer); + if (result != ISC_R_SUCCESS) + goto cleanup_task; + + client->message = NULL; + result = dns_message_create(manager->mctx, DNS_MESSAGE_INTENTPARSE, + &client->message); + if (result != ISC_R_SUCCESS) + goto cleanup_timer; + + /* XXXRTH Hardwired constants */ + client->sendbufs = NULL; + result = isc_mempool_create(manager->mctx, SEND_BUFFER_SIZE, + &client->sendbufs); + if (result != ISC_R_SUCCESS) + goto cleanup_message; + isc_mempool_setfreemax(client->sendbufs, 3); + isc_mempool_setmaxalloc(client->sendbufs, 3); + + client->manager = manager; + client->type = type; + client->state = ns_clientstate_idle; + client->attributes = 0; + client->dispatch = NULL; + client->dispentry = NULL; + client->dispevent = NULL; + client->nsends = 0; + ISC_LINK_INIT(client, link); + client->magic = NS_CLIENT_MAGIC; + + CTRACE("create"); + + *clientp = client; + + return (ISC_R_SUCCESS); + + cleanup_message: + dns_message_destroy(&client->message); + + cleanup_timer: + isc_timer_detach(&client->timer); + + cleanup_task: + isc_task_detach(&client->task); + + cleanup_client: + isc_mem_put(manager->mctx, client, sizeof *client); + + return (result); +} + + +/*** + *** Client Manager + ***/ + +static void +clientmgr_destroy(ns_clientmgr_t *manager) { + REQUIRE(manager->nclients == 0); + REQUIRE(ISC_LIST_EMPTY(manager->clients)); + + MTRACE("clientmgr_destroy"); + + manager->magic = 0; + isc_mem_put(manager->mctx, manager, sizeof *manager); +} + +isc_result_t +ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, + isc_timermgr_t *timermgr, ns_clientmgr_t **managerp) +{ + ns_clientmgr_t *manager; + isc_result_t result; + + manager = isc_mem_get(mctx, sizeof *manager); + if (manager == NULL) + return (ISC_R_NOMEMORY); + + result = isc_mutex_init(&manager->lock); + if (result != ISC_R_SUCCESS) + goto cleanup_manager; + + manager->mctx = mctx; + manager->taskmgr = taskmgr; + manager->timermgr = timermgr; + manager->exiting = ISC_FALSE; + manager->nclients = 0; + ISC_LIST_INIT(manager->clients); + manager->magic = MANAGER_MAGIC; + + MTRACE("create"); + + *managerp = manager; + + return (ISC_R_SUCCESS); + + cleanup_manager: + isc_mem_put(manager->mctx, manager, sizeof *manager); + + return (result); +} + +void +ns_clientmgr_destroy(ns_clientmgr_t **managerp) { + ns_clientmgr_t *manager; + ns_client_t *client; + isc_boolean_t need_destroy = ISC_FALSE; + + REQUIRE(managerp != NULL); + manager = *managerp; + REQUIRE(VALID_MANAGER(manager)); + + MTRACE("destroy"); + + LOCK(&manager->lock); + + manager->exiting = ISC_TRUE; + + for (client = ISC_LIST_HEAD(manager->clients); + client != NULL; + client = ISC_LIST_NEXT(client, link)) + isc_task_shutdown(client->task); + + if (ISC_LIST_EMPTY(manager->clients)) + need_destroy = ISC_TRUE; + + UNLOCK(&manager->lock); + + if (need_destroy) + clientmgr_destroy(manager); + + *managerp = NULL; +} + +isc_result_t +ns_clientmgr_addtodispatch(ns_clientmgr_t *manager, ns_clienttype_t type, + unsigned int n, + dns_dispatch_t *dispatch) +{ + isc_result_t result = ISC_R_SUCCESS; + unsigned int i; + ns_client_t *client; + + REQUIRE(VALID_MANAGER(manager)); + REQUIRE(n > 0); + + MTRACE("addtodispatch"); + + /* + * We MUST lock the manager lock for the entire client creation + * process. If we didn't do this, then a client could get a + * shutdown event and disappear out from under us. + */ + + LOCK(&manager->lock); + + for (i = 0; i < n; i++) { + client = NULL; + result = client_create(manager, type, &client); + if (result != ISC_R_SUCCESS) + break; + dns_dispatch_attach(dispatch, &client->dispatch); + result = dns_dispatch_addrequest(dispatch, client->task, + client_recv, + client, &client->dispentry); + if (result != ISC_R_SUCCESS) { + client_free(client); + break; + } + client->state = ns_clientstate_listening; + manager->nclients++; + ISC_LIST_APPEND(manager->clients, client, link); + } + if (i != 0) { + /* + * We managed to create at least one client, so we + * declare victory. + */ + result = ISC_R_SUCCESS; + } + + UNLOCK(&manager->lock); + + return (result); +} diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h new file mode 100644 index 0000000000..b4bb35b07c --- /dev/null +++ b/bin/named/include/named/client.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 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. + */ + +#ifndef NS_CLIENT_H +#define NS_CLIENT_H 1 + +#include +#include + +#include + +#include + +typedef enum ns_clienttype { + ns_clienttype_basic = 0, + ns_clienttype_recursive, + ns_clienttype_axfr, + ns_clienttype_ixfr +} ns_clienttype_t; + +typedef enum { + ns_clientstate_idle = 0, + ns_clientstate_listening, + ns_clientstate_working, + ns_clientstate_waiting +} ns_clientstate_t; + +struct ns_client { + unsigned int magic; + ns_clientmgr_t * manager; + ns_clienttype_t type; + ns_clientstate_t state; + unsigned int attributes; + isc_task_t * task; + dns_dispatch_t * dispatch; + dns_dispentry_t * dispentry; + dns_dispatchevent_t * dispevent; + isc_timer_t * timer; + dns_message_t * message; + unsigned int nsends; + isc_mempool_t * sendbufs; + ISC_LINK(struct ns_client) link; +}; + +#define NS_CLIENT_MAGIC 0x4E534363U /* NSCc */ +#define NS_CLIENT_VALID(c) ((c) != NULL && \ + (c)->magic == NS_CLIENT_MAGIC) + +/* + * Note! These ns_client_ routines MUST be called ONLY from the client's + * task in order to ensure synchronization. + */ +void +ns_client_error(ns_client_t *client, isc_result_t result); + +void +ns_client_next(ns_client_t *client, isc_result_t result); + +void +ns_client_destroy(ns_client_t *client); + +isc_result_t +ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, + isc_timermgr_t *timermgr, ns_clientmgr_t **managerp); + +void +ns_clientmgr_destroy(ns_clientmgr_t **managerp); + +isc_result_t +ns_clientmgr_addtodispatch(ns_clientmgr_t *manager, ns_clienttype_t type, + unsigned int n, + dns_dispatch_t *dispatch); + +#endif /* NS_CLIENT_H */ diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h new file mode 100644 index 0000000000..d30fb5e731 --- /dev/null +++ b/bin/named/include/named/globals.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 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. + */ + +#ifndef NS_GLOBALS_H +#define NS_GLOBALS_H 1 + +#include +#include + +#include + +#include +#include + +#undef EXTERN +#undef INIT +#ifdef NS_MAIN +#define EXTERN +#define INIT(v) = (v) +#else +#define EXTERN extern +#define INIT(v) +#endif + +EXTERN isc_mem_t * ns_g_mctx INIT(NULL); +EXTERN unsigned int ns_g_cpus INIT(1); +EXTERN isc_taskmgr_t * ns_g_taskmgr INIT(NULL); +/* + * XXXRTH We're going to want multiple timer managers eventually. One + * for really short timers, another for client timers, and one + * for zone timers. + */ +EXTERN isc_timermgr_t * ns_g_timermgr INIT(NULL); +EXTERN isc_socketmgr_t * ns_g_socketmgr INIT(NULL); +EXTERN ns_interfacemgr_t * ns_g_interfacemgr INIT(NULL); +EXTERN ns_clientmgr_t * ns_g_clientmgr INIT(NULL); +EXTERN char * ns_g_version INIT(VERSION); + +EXTERN isc_rwlock_t ns_g_viewlock; +EXTERN dns_viewlist_t ns_g_views; + +/* XXXRTH This next one is temporary. */ +EXTERN ns_dbinfolist_t ns_g_dbs; + +#undef EXTERN +#undef INIT + +#endif /* NS_GLOBALS_H */ diff --git a/bin/named/include/named/query.h b/bin/named/include/named/query.h new file mode 100644 index 0000000000..7acc7b171d --- /dev/null +++ b/bin/named/include/named/query.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 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. + */ + +#ifndef NS_QUERY_H +#define NS_QUERY_H 1 + +#include + +void ns_query_start(ns_client_t *client); + +#endif /* NS_QUERY_H */ diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h new file mode 100644 index 0000000000..355ec5bf01 --- /dev/null +++ b/bin/named/include/named/server.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 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. + */ + +#ifndef NS_SERVER_H +#define NS_SERVER_H 1 + +#include + +isc_result_t ns_server_init(void); + +#endif /* NS_SERVER_H */ diff --git a/bin/named/include/named/types.h b/bin/named/include/named/types.h new file mode 100644 index 0000000000..3da6e6e9df --- /dev/null +++ b/bin/named/include/named/types.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 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. + */ + +#ifndef NS_TYPES_H +#define NS_TYPES_H 1 + +#include + +#include + +typedef struct ns_client ns_client_t; +typedef struct ns_clientmgr ns_clientmgr_t; + +/* + * XXXRTH This stuff is temporary. As soon as we have zone and config + * support, it will go away. + */ + +typedef struct ns_dbinfo { + char * path; + char * origin; + isc_boolean_t iscache; + dns_db_t * db; + ISC_LINK(struct ns_dbinfo) link; +} ns_dbinfo_t; + +typedef ISC_LIST(ns_dbinfo_t) ns_dbinfolist_t; + +/* + * XXXRTH End of temporary stuff. + */ + +#endif /* NS_TYPES_H */ diff --git a/bin/named/main.c b/bin/named/main.c new file mode 100644 index 0000000000..e81f6b48e2 --- /dev/null +++ b/bin/named/main.c @@ -0,0 +1,263 @@ +/* + * Copyright (C) 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. + */ + +#include + +#include +#include +#include +#include +#include /* XXXRTH Naughty. Needed for getopt(). */ + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define NS_MAIN 1 + +#include +#include +#include +#include + +static isc_boolean_t want_stats = ISC_FALSE; + +static void +early_fatal(char *format, ...) { + va_list args; + + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + + exit(1); +} + +static void +usage(void) { + fprintf(stderr, + "usage: named [[-c cachefile] ...] [[-z zonefile] ...]\n"); + fprintf(stderr, + " [-s] [-N number of cpus]\n"); +} + +static void +parse_command_line(int argc, char *argv[]) { + char *origintext; + int ch; + ns_dbinfo_t *dbi; + + /*+ XXXRTH we need a veneered getopt() */ + while ((ch = getopt(argc, argv, "c:N:sz:")) != -1) { + switch (ch) { + case 'c': + /* XXXRTH temporary syntax */ + dbi = isc_mem_get(ns_g_mctx, sizeof *dbi); + if (dbi == NULL) + early_fatal("creating cache info failed"); + dbi->path = optarg; + dbi->origin = "."; + dbi->iscache = ISC_TRUE; + dbi->db = NULL; + ISC_LINK_INIT(dbi, link); + ISC_LIST_APPEND(ns_g_dbs, dbi, link); + break; + case 'N': + ns_g_cpus = atoi(optarg); + if (ns_g_cpus == 0) + ns_g_cpus = 1; + break; + case 's': + /* XXXRTH temporary syntax */ + want_stats = ISC_TRUE; + break; + case 'z': + /* XXXRTH temporary syntax */ + origintext = strrchr(optarg, '/'); + if (origintext == NULL) + origintext = optarg; + else + origintext++; /* Skip '/'. */ + dbi = isc_mem_get(ns_g_mctx, sizeof *dbi); + if (dbi == NULL) + early_fatal("creating zone info failed"); + dbi->path = optarg; + dbi->origin = origintext; + dbi->iscache = ISC_FALSE; + dbi->db = NULL; + ISC_LINK_INIT(dbi, link); + ISC_LIST_APPEND(ns_g_dbs, dbi, link); + break; + case '?': + usage(); + early_fatal("unknown command line argument"); + break; + default: + early_fatal("getopt() returned %d", ch); + } + } + + argc -= optind; + argv += optind; + + if (argc > 1) { + usage(); + early_fatal("extra command line arguments"); + } +} + +static isc_result_t +create_managers() { + isc_result_t result; + + result = isc_taskmgr_create(ns_g_mctx, ns_g_cpus, 0, &ns_g_taskmgr); + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "ns_taskmgr_create() failed: %s\n", + isc_result_totext(result)); + return (ISC_R_UNEXPECTED); + } + + result = isc_timermgr_create(ns_g_mctx, &ns_g_timermgr); + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "ns_timermgr_create() failed: %s\n", + isc_result_totext(result)); + return (ISC_R_UNEXPECTED); + } + + result = isc_socketmgr_create(ns_g_mctx, &ns_g_socketmgr); + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_socketmgr_create() failed: %s\n", + isc_result_totext(result)); + return (ISC_R_UNEXPECTED); + } + + result = ns_clientmgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr, + &ns_g_clientmgr); + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "ns_clientmgr_create() failed: %s\n", + isc_result_totext(result)); + return (ISC_R_UNEXPECTED); + } + + result = ns_interfacemgr_create(ns_g_mctx, ns_g_taskmgr, + ns_g_socketmgr, ns_g_clientmgr, + &ns_g_interfacemgr); + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "ns_interfacemgr_create() failed: %s\n", + isc_result_totext(result)); + return (ISC_R_UNEXPECTED); + } + + return (ISC_R_SUCCESS); +} + +static void +destroy_managers(void) { + /* + * The interface manager owns tasks, so we have to destroy it before + * we destroy the task manager. + */ + ns_interfacemgr_destroy(&ns_g_interfacemgr); + /* + * isc_taskmgr_destroy() will block until all tasks have exited, + */ + isc_taskmgr_destroy(&ns_g_taskmgr); + isc_timermgr_destroy(&ns_g_timermgr); + isc_socketmgr_destroy(&ns_g_socketmgr); + ns_clientmgr_destroy(&ns_g_clientmgr); +} + +static void +setup() { + isc_result_t result; + + ISC_LIST_INIT(ns_g_views); + + result = isc_rwlock_init(&ns_g_viewlock, 0, 0); + if (result != ISC_R_SUCCESS) + early_fatal("isc_rwlock_init() failed: %s", + isc_result_totext(result)); + + result = create_managers(); + if (result != ISC_R_SUCCESS) + early_fatal("create_managers() failed: %s", + isc_result_totext(result)); + + result = ns_server_init(); + if (result != ISC_R_SUCCESS) + early_fatal("ns_server_init() failed: %s", + isc_result_totext(result)); +} + +static void +cleanup() { + destroy_managers(); + isc_rwlock_destroy(&ns_g_viewlock); +} + +int +main(int argc, char *argv[]) { + isc_result_t result; + + result = isc_app_start(); + if (result != ISC_R_SUCCESS) + early_fatal("isc_app_start() failed: %s", + isc_result_totext(result)); + + result = isc_mem_create(0, 0, &ns_g_mctx); + if (result != ISC_R_SUCCESS) + early_fatal("isc_mem_create() failed: %s", + isc_result_totext(result)); + + dns_result_register(); + dst_result_register(); + + parse_command_line(argc, argv); + + setup(); + + /* + * Start things running and then wait for a shutdown request. + */ + result = isc_app_run(); + if (result != ISC_R_SUCCESS) + UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_run(): %s", + isc_result_totext(result)); + + cleanup(); + + if (want_stats) + isc_mem_stats(ns_g_mctx, stdout); + isc_mem_destroy(&ns_g_mctx); + + isc_app_finish(); + + return (0); +} diff --git a/bin/named/query.c b/bin/named/query.c new file mode 100644 index 0000000000..fcfb662a10 --- /dev/null +++ b/bin/named/query.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 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. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "../../isc/util.h" /* XXX */ + +static dns_result_t +resolve_packet(isc_mem_t *mctx, dns_message_t *query, isc_buffer_t *target) { + dns_message_t *message; + dns_result_t result, dbresult; + dns_name_t *qname, *fname, *rqname; + dns_fixedname_t foundname, frqname; + dns_rdataset_t *rds, *rdataset, rqrds, rdatasets[MAX_RDATASETS]; + unsigned int nrdatasets = 0; + dns_dbnode_t *node; + dns_db_t *db; + dns_rdatasetiter_t *rdsiter; + dns_rdatatype_t type; + isc_boolean_t possibly_auth = ISC_FALSE; + + message = NULL; + result = dns_message_create(mctx, &message, DNS_MESSAGE_INTENTRENDER); + CHECKRESULT(result, "dns_message_create failed"); + + message->id = query->id; + message->rcode = dns_rcode_noerror; + message->flags = query->flags; + message->flags |= DNS_MESSAGEFLAG_QR; + + result = dns_message_firstname(query, DNS_SECTION_QUESTION); + if (result != DNS_R_SUCCESS) + return (result); + qname = NULL; + dns_fixedname_init(&frqname); + rqname = dns_fixedname_name(&frqname); + dns_message_currentname(query, DNS_SECTION_QUESTION, &qname); + result = dns_name_concatenate(qname, NULL, rqname, NULL); + if (result != DNS_R_SUCCESS) + return (DNS_R_UNEXPECTED); + rds = ISC_LIST_HEAD(qname->list); + if (rds == NULL) + return (DNS_R_UNEXPECTED); + type = rds->type; + dns_rdataset_init(&rqrds); + dns_rdataset_makequestion(&rqrds, rds->rdclass, rds->type); + ISC_LIST_APPEND(rqname->list, &rqrds, link); + + dns_message_addname(message, rqname, DNS_SECTION_QUESTION); + + result = printmessage(message); + INSIST(result == DNS_R_SUCCESS); /* XXX not in a real server */ + + /* + * Find a database to answer the query from. + */ + db = NULL; + result = dns_dbtable_find(dbtable, qname, &db); + if (result != DNS_R_SUCCESS && result != DNS_R_PARTIALMATCH) { + printf("could not find a dbtable: %s\n", + dns_result_totext(result)); + message->rcode = dns_rcode_servfail; + goto render; + } + + /* + * Now look for an answer in the database. + */ + dns_fixedname_init(&foundname); + fname = dns_fixedname_name(&foundname); + rdataset = &rdatasets[nrdatasets++]; + dns_rdataset_init(rdataset); + node = NULL; + dbresult = dns_db_find(db, qname, NULL, type, 0, 0, &node, fname, + rdataset); + switch (dbresult) { + case DNS_R_SUCCESS: + case DNS_R_DNAME: + case DNS_R_CNAME: + possibly_auth = ISC_TRUE; + break; + case DNS_R_GLUE: + case DNS_R_ZONECUT: + case DNS_R_DELEGATION: + break; + case DNS_R_NXRDATASET: + if (dns_db_iszone(db)) + message->flags |= DNS_MESSAGEFLAG_AA; + dns_db_detachnode(db, &node); + dns_db_detach(&db); + goto render; + case DNS_R_NXDOMAIN: + if (dns_db_iszone(db)) + message->flags |= DNS_MESSAGEFLAG_AA; + dns_db_detach(&db); + message->rcode = dns_rcode_nxdomain; + goto render; + default: + printf("%s\n", dns_result_totext(result)); + dns_db_detach(&db); + message->rcode = dns_rcode_servfail; + goto render; + } + + if (dbresult == DNS_R_DELEGATION) { + ISC_LIST_APPEND(fname->list, rdataset, link); + dns_message_addname(message, fname, DNS_SECTION_AUTHORITY); + } else if (type == dns_rdatatype_any) { + rdsiter = NULL; + result = dns_db_allrdatasets(db, node, NULL, 0, &rdsiter); + if (result == DNS_R_SUCCESS) + result = dns_rdatasetiter_first(rdsiter); + while (result == DNS_R_SUCCESS) { + dns_rdatasetiter_current(rdsiter, rdataset); + ISC_LIST_APPEND(fname->list, rdataset, link); + if (nrdatasets == MAX_RDATASETS) { + result = DNS_R_NOSPACE; + } else { + rdataset = &rdatasets[nrdatasets++]; + dns_rdataset_init(rdataset); + result = dns_rdatasetiter_next(rdsiter); + } + } + if (result != DNS_R_NOMORE) { + dns_db_detachnode(db, &node); + dns_db_detach(&db); + message->rcode = dns_rcode_servfail; + goto render; + } + dns_message_addname(message, fname, DNS_SECTION_ANSWER); + } else { + ISC_LIST_APPEND(fname->list, rdataset, link); + dns_message_addname(message, fname, DNS_SECTION_ANSWER); + } + + if (dns_db_iszone(db) && possibly_auth) + message->flags |= DNS_MESSAGEFLAG_AA; + + dns_db_detachnode(db, &node); + dns_db_detach(&db); + + render: + + result = dns_message_renderbegin(message, target); + if (result != DNS_R_SUCCESS) + return (result); + + result = dns_message_rendersection(message, DNS_SECTION_QUESTION, + 0, 0); + if (result != DNS_R_SUCCESS) + return (result); + + result = dns_message_rendersection(message, DNS_SECTION_ANSWER, + 0, 0); + if (result != DNS_R_SUCCESS) + return (result); + + result = dns_message_rendersection(message, DNS_SECTION_AUTHORITY, + 0, 0); + if (result != DNS_R_SUCCESS) + return (result); + + result = dns_message_rendersection(message, DNS_SECTION_ADDITIONAL, + 0, 0); + if (result != DNS_R_SUCCESS) + return (result); + + result = dns_message_rendersection(message, DNS_SECTION_TSIG, + 0, 0); + if (result != DNS_R_SUCCESS) + return (result); + + result = dns_message_renderend(message); + + dns_message_destroy(&message); + + return (DNS_R_SUCCESS); +} + +void +ns_query_start(ns_client_t *client) { + +} diff --git a/doc/rfc/rfc1876.txt b/doc/rfc/rfc1876.txt new file mode 100644 index 0000000000..a289cffece --- /dev/null +++ b/doc/rfc/rfc1876.txt @@ -0,0 +1,1011 @@ + + + + + + +Network Working Group C. Davis +Request for Comments: 1876 Kapor Enterprises +Updates: 1034, 1035 P. Vixie +Category: Experimental Vixie Enterprises + T. Goodwin + FORE Systems + I. Dickinson + University of Warwick + January 1996 + + + A Means for Expressing Location Information in the Domain Name System + +Status of this Memo + + This memo defines an Experimental Protocol for the Internet + community. This memo does not specify an Internet standard of any + kind. Discussion and suggestions for improvement are requested. + Distribution of this memo is unlimited. + +1. Abstract + + This memo defines a new DNS RR type for experimental purposes. This + RFC describes a mechanism to allow the DNS to carry location + information about hosts, networks, and subnets. Such information for + a small subset of hosts is currently contained in the flat-file UUCP + maps. However, just as the DNS replaced the use of HOSTS.TXT to + carry host and network address information, it is possible to replace + the UUCP maps as carriers of location information. + + This RFC defines the format of a new Resource Record (RR) for the + Domain Name System (DNS), and reserves a corresponding DNS type + mnemonic (LOC) and numerical code (29). + + This RFC assumes that the reader is familiar with the DNS [RFC 1034, + RFC 1035]. The data shown in our examples is for pedagogical use and + does not necessarily reflect the real Internet. + + + + + + + + + + + + + + +Davis, et al Experimental [Page 1] + +RFC 1876 Location Information in the DNS January 1996 + + +2. RDATA Format + + MSB LSB + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 0| VERSION | SIZE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 2| HORIZ PRE | VERT PRE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 4| LATITUDE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 6| LATITUDE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 8| LONGITUDE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 10| LONGITUDE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 12| ALTITUDE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 14| ALTITUDE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + (octet) + +where: + +VERSION Version number of the representation. This must be zero. + Implementations are required to check this field and make + no assumptions about the format of unrecognized versions. + +SIZE The diameter of a sphere enclosing the described entity, in + centimeters, expressed as a pair of four-bit unsigned + integers, each ranging from zero to nine, with the most + significant four bits representing the base and the second + number representing the power of ten by which to multiply + the base. This allows sizes from 0e0 (<1cm) to 9e9 + (90,000km) to be expressed. This representation was chosen + such that the hexadecimal representation can be read by + eye; 0x15 = 1e5. Four-bit values greater than 9 are + undefined, as are values with a base of zero and a non-zero + exponent. + + Since 20000000m (represented by the value 0x29) is greater + than the equatorial diameter of the WGS 84 ellipsoid + (12756274m), it is therefore suitable for use as a + "worldwide" size. + +HORIZ PRE The horizontal precision of the data, in centimeters, + expressed using the same representation as SIZE. This is + the diameter of the horizontal "circle of error", rather + + + +Davis, et al Experimental [Page 2] + +RFC 1876 Location Information in the DNS January 1996 + + + than a "plus or minus" value. (This was chosen to match + the interpretation of SIZE; to get a "plus or minus" value, + divide by 2.) + +VERT PRE The vertical precision of the data, in centimeters, + expressed using the sane representation as for SIZE. This + is the total potential vertical error, rather than a "plus + or minus" value. (This was chosen to match the + interpretation of SIZE; to get a "plus or minus" value, + divide by 2.) Note that if altitude above or below sea + level is used as an approximation for altitude relative to + the [WGS 84] ellipsoid, the precision value should be + adjusted. + +LATITUDE The latitude of the center of the sphere described by the + SIZE field, expressed as a 32-bit integer, most significant + octet first (network standard byte order), in thousandths + of a second of arc. 2^31 represents the equator; numbers + above that are north latitude. + +LONGITUDE The longitude of the center of the sphere described by the + SIZE field, expressed as a 32-bit integer, most significant + octet first (network standard byte order), in thousandths + of a second of arc, rounded away from the prime meridian. + 2^31 represents the prime meridian; numbers above that are + east longitude. + +ALTITUDE The altitude of the center of the sphere described by the + SIZE field, expressed as a 32-bit integer, most significant + octet first (network standard byte order), in centimeters, + from a base of 100,000m below the [WGS 84] reference + spheroid used by GPS (semimajor axis a=6378137.0, + reciprocal flattening rf=298.257223563). Altitude above + (or below) sea level may be used as an approximation of + altitude relative to the the [WGS 84] spheroid, though due + to the Earth's surface not being a perfect spheroid, there + will be differences. (For example, the geoid (which sea + level approximates) for the continental US ranges from 10 + meters to 50 meters below the [WGS 84] spheroid. + Adjustments to ALTITUDE and/or VERT PRE will be necessary + in most cases. The Defense Mapping Agency publishes geoid + height values relative to the [WGS 84] ellipsoid. + + + + + + + + + +Davis, et al Experimental [Page 3] + +RFC 1876 Location Information in the DNS January 1996 + + +3. Master File Format + + The LOC record is expressed in a master file in the following format: + + LOC ( d1 [m1 [s1]] {"N"|"S"} d2 [m2 [s2]] + {"E"|"W"} alt["m"] [siz["m"] [hp["m"] + [vp["m"]]]] ) + + (The parentheses are used for multi-line data as specified in [RFC + 1035] section 5.1.) + + where: + + d1: [0 .. 90] (degrees latitude) + d2: [0 .. 180] (degrees longitude) + m1, m2: [0 .. 59] (minutes latitude/longitude) + s1, s2: [0 .. 59.999] (seconds latitude/longitude) + alt: [-100000.00 .. 42849672.95] BY .01 (altitude in meters) + siz, hp, vp: [0 .. 90000000.00] (size/precision in meters) + + If omitted, minutes and seconds default to zero, size defaults to 1m, + horizontal precision defaults to 10000m, and vertical precision + defaults to 10m. These defaults are chosen to represent typical + ZIP/postal code area sizes, since it is often easy to find + approximate geographical location by ZIP/postal code. + +4. Example Data + +;;; +;;; note that these data would not all appear in one zone file +;;; + +;; network LOC RR derived from ZIP data. note use of precision defaults +cambridge-net.kei.com. LOC 42 21 54 N 71 06 18 W -24m 30m + +;; higher-precision host LOC RR. note use of vertical precision default +loiosh.kei.com. LOC 42 21 43.952 N 71 5 6.344 W + -24m 1m 200m + +pipex.net. LOC 52 14 05 N 00 08 50 E 10m + +curtin.edu.au. LOC 32 7 19 S 116 2 25 E 10m + +rwy04L.logan-airport.boston. LOC 42 21 28.764 N 71 00 51.617 W + -44m 2000m + + + + + + +Davis, et al Experimental [Page 4] + +RFC 1876 Location Information in the DNS January 1996 + + +5. Application use of the LOC RR + +5.1 Suggested Uses + + Some uses for the LOC RR have already been suggested, including the + USENET backbone flow maps, a "visual traceroute" application showing + the geographical path of an IP packet, and network management + applications that could use LOC RRs to generate a map of hosts and + routers being managed. + +5.2 Search Algorithms + + This section specifies how to use the DNS to translate domain names + and/or IP addresses into location information. + + If an application wishes to have a "fallback" behavior, displaying a + less precise or larger area when a host does not have an associated + LOC RR, it MAY support use of the algorithm in section 5.2.3, as + noted in sections 5.2.1 and 5.2.2. If fallback is desired, this + behaviour is the RECOMMENDED default, but in some cases it may need + to be modified based on the specific requirements of the application + involved. + + This search algorithm is designed to allow network administrators to + specify the location of a network or subnet without requiring LOC RR + data for each individual host. For example, a computer lab with 24 + workstations, all of which are on the same subnet and in basically + the same location, would only need a LOC RR for the subnet. + (However, if the file server's location has been more precisely + measured, a separate LOC RR for it can be placed in the DNS.) + +5.2.1 Searching by Name + + If the application is beginning with a name, rather than an IP + address (as the USENET backbone flow maps do), it MUST check for a + LOC RR associated with that name. (CNAME records should be followed + as for any other RR type.) + + If there is no LOC RR for that name, all A records (if any) + associated with the name MAY be checked for network (or subnet) LOC + RRs using the "Searching by Network or Subnet" algorithm (5.2.3). If + multiple A records exist and have associated network or subnet LOC + RRs, the application may choose to use any, some, or all of the LOC + RRs found, possibly in combination. It is suggested that multi-homed + hosts have LOC RRs for their name in the DNS to avoid any ambiguity + in these cases. + + + + + +Davis, et al Experimental [Page 5] + +RFC 1876 Location Information in the DNS January 1996 + + + Note that domain names that do not have associated A records must + have a LOC RR associated with their name in order for location + information to be accessible. + +5.2.2 Searching by Address + + If the application is beginning with an IP address (as a "visual + traceroute" application might be) it MUST first map the address to a + name using the IN-ADDR.ARPA namespace (see [RFC 1034], section + 5.2.1), then check for a LOC RR associated with that name. + + If there is no LOC RR for the name, the address MAY be checked for + network (or subnet) LOC RRs using the "Searching by Network or + Subnet" algorithm (5.2.3). + +5.2.3 Searching by Network or Subnet + + Even if a host's name does not have any associated LOC RRs, the + network(s) or subnet(s) it is on may. If the application wishes to + search for such less specific data, the following algorithm SHOULD be + followed to find a network or subnet LOC RR associated with the IP + address. This algorithm is adapted slightly from that specified in + [RFC 1101], sections 4.3 and 4.4. + + Since subnet LOC RRs are (if present) more specific than network LOC + RRs, it is best to use them if available. In order to do so, we + build a stack of network and subnet names found while performing the + [RFC 1101] search, then work our way down the stack until a LOC RR is + found. + + 1. create a host-zero address using the network portion of the IP + address (one, two, or three bytes for class A, B, or C networks, + respectively). For example, for the host 128.9.2.17, on the class + B network 128.9, this would result in the address "128.9.0.0". + + 2. Reverse the octets, suffix IN-ADDR.ARPA, and query for PTR and A + records. Retrieve: + + 0.0.9.128.IN-ADDR.ARPA. PTR isi-net.isi.edu. + A 255.255.255.0 + + Push the name "isi-net.isi.edu" onto the stack of names to be + searched for LOC RRs later. + + + + + + + + +Davis, et al Experimental [Page 6] + +RFC 1876 Location Information in the DNS January 1996 + + + 3. Since an A RR was found, repeat using mask from RR + (255.255.255.0), constructing a query for 0.2.9.128.IN-ADDR.ARPA. + Retrieve: + + 0.2.9.128.IN-ADDR.ARPA. PTR div2-subnet.isi.edu. + A 255.255.255.240 + + Push the name "div2-subnet.isi.edu" onto the stack of names to be + searched for LOC RRs later. + + 4. Since another A RR was found, repeat using mask 255.255.255.240 + (x'FFFFFFF0'), constructing a query for 16.2.9.128.IN-ADDR.ARPA. + Retrieve: + + 16.2.9.128.IN-ADDR.ARPA. PTR inc-subsubnet.isi.edu. + + Push the name "inc-subsubnet.isi.edu" onto the stack of names to + be searched for LOC RRs later. + + 5. Since no A RR is present at 16.2.9.128.IN-ADDR.ARPA., there are no + more subnet levels to search. We now pop the top name from the + stack and check for an associated LOC RR. Repeat until a LOC RR + is found. + + In this case, assume that inc-subsubnet.isi.edu does not have an + associated LOC RR, but that div2-subnet.isi.edu does. We will + then use div2-subnet.isi.edu's LOC RR as an approximation of this + host's location. (Note that even if isi-net.isi.edu has a LOC RR, + it will not be used if a subnet also has a LOC RR.) + +5.3 Applicability to non-IN Classes and non-IP Addresses + + The LOC record is defined for all RR classes, and may be used with + non-IN classes such as HS and CH. The semantics of such use are not + defined by this memo. + + The search algorithm in section 5.2.3 may be adapted to other + addressing schemes by extending [RFC 1101]'s encoding of network + names to cover those schemes. Such extensions are not defined by + this memo. + + + + + + + + + + + +Davis, et al Experimental [Page 7] + +RFC 1876 Location Information in the DNS January 1996 + + +6. References + + [RFC 1034] Mockapetris, P., "Domain Names - Concepts and Facilities", + STD 13, RFC 1034, USC/Information Sciences Institute, + November 1987. + + [RFC 1035] Mockapetris, P., "Domain Names - Implementation and + Specification", STD 13, RFC 1035, USC/Information Sciences + Institute, November 1987. + + [RFC 1101] Mockapetris, P., "DNS Encoding of Network Names and Other + Types", RFC 1101, USC/Information Sciences Institute, + April 1989. + + [WGS 84] United States Department of Defense; DoD WGS-1984 - Its + Definition and Relationships with Local Geodetic Systems; + Washington, D.C.; 1985; Report AD-A188 815 DMA; 6127; 7-R- + 138-R; CV, KV; + +7. Security Considerations + + High-precision LOC RR information could be used to plan a penetration + of physical security, leading to potential denial-of-machine attacks. + To avoid any appearance of suggesting this method to potential + attackers, we declined the opportunity to name this RR "ICBM". + +8. Authors' Addresses + + The authors as a group can be reached as . + + Christopher Davis + Kapor Enterprises, Inc. + 238 Main Street, Suite 400 + Cambridge, MA 02142 + + Phone: +1 617 576 4532 + EMail: ckd@kei.com + + + Paul Vixie + Vixie Enterprises + Star Route Box 159A + Woodside, CA 94062 + + Phone: +1 415 747 0204 + EMail: paul@vix.com + + + + + +Davis, et al Experimental [Page 8] + +RFC 1876 Location Information in the DNS January 1996 + + + Tim Goodwin + Public IP Exchange Ltd (PIPEX) + 216 The Science Park + Cambridge CB4 4WA + UK + + Phone: +44 1223 250250 + EMail: tim@pipex.net + + + Ian Dickinson + FORE Systems + 2475 The Crescent + Solihull Parkway + Birmingham Business Park + B37 7YE + UK + + Phone: +44 121 717 4444 + EMail: idickins@fore.co.uk + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Davis, et al Experimental [Page 9] + +RFC 1876 Location Information in the DNS January 1996 + + +Appendix A: Sample Conversion Routines + +/* + * routines to convert between on-the-wire RR format and zone file + * format. Does not contain conversion to/from decimal degrees; + * divide or multiply by 60*60*1000 for that. + */ + +static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000, + 1000000,10000000,100000000,1000000000}; + +/* takes an XeY precision/size value, returns a string representation.*/ +static const char * +precsize_ntoa(prec) + u_int8_t prec; +{ + static char retbuf[sizeof("90000000.00")]; + unsigned long val; + int mantissa, exponent; + + mantissa = (int)((prec >> 4) & 0x0f) % 10; + exponent = (int)((prec >> 0) & 0x0f) % 10; + + val = mantissa * poweroften[exponent]; + + (void) sprintf(retbuf,"%d.%.2d", val/100, val%100); + return (retbuf); +} + +/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer.*/ +static u_int8_t +precsize_aton(strptr) + char **strptr; +{ + unsigned int mval = 0, cmval = 0; + u_int8_t retval = 0; + register char *cp; + register int exponent; + register int mantissa; + + cp = *strptr; + + while (isdigit(*cp)) + mval = mval * 10 + (*cp++ - '0'); + + if (*cp == '.') { /* centimeters */ + cp++; + if (isdigit(*cp)) { + + + +Davis, et al Experimental [Page 10] + +RFC 1876 Location Information in the DNS January 1996 + + + cmval = (*cp++ - '0') * 10; + if (isdigit(*cp)) { + cmval += (*cp++ - '0'); + } + } + } + cmval = (mval * 100) + cmval; + + for (exponent = 0; exponent < 9; exponent++) + if (cmval < poweroften[exponent+1]) + break; + + mantissa = cmval / poweroften[exponent]; + if (mantissa > 9) + mantissa = 9; + + retval = (mantissa << 4) | exponent; + + *strptr = cp; + + return (retval); +} + +/* converts ascii lat/lon to unsigned encoded 32-bit number. + * moves pointer. */ +static u_int32_t +latlon2ul(latlonstrptr,which) + char **latlonstrptr; + int *which; +{ + register char *cp; + u_int32_t retval; + int deg = 0, min = 0, secs = 0, secsfrac = 0; + + cp = *latlonstrptr; + + while (isdigit(*cp)) + deg = deg * 10 + (*cp++ - '0'); + + while (isspace(*cp)) + cp++; + + if (!(isdigit(*cp))) + goto fndhemi; + + while (isdigit(*cp)) + min = min * 10 + (*cp++ - '0'); + + + + +Davis, et al Experimental [Page 11] + +RFC 1876 Location Information in the DNS January 1996 + + + while (isspace(*cp)) + cp++; + + if (!(isdigit(*cp))) + goto fndhemi; + + while (isdigit(*cp)) + secs = secs * 10 + (*cp++ - '0'); + + if (*cp == '.') { /* decimal seconds */ + cp++; + if (isdigit(*cp)) { + secsfrac = (*cp++ - '0') * 100; + if (isdigit(*cp)) { + secsfrac += (*cp++ - '0') * 10; + if (isdigit(*cp)) { + secsfrac += (*cp++ - '0'); + } + } + } + } + + while (!isspace(*cp)) /* if any trailing garbage */ + cp++; + + while (isspace(*cp)) + cp++; + + fndhemi: + switch (*cp) { + case 'N': case 'n': + case 'E': case 'e': + retval = ((unsigned)1<<31) + + (((((deg * 60) + min) * 60) + secs) * 1000) + + secsfrac; + break; + case 'S': case 's': + case 'W': case 'w': + retval = ((unsigned)1<<31) + - (((((deg * 60) + min) * 60) + secs) * 1000) + - secsfrac; + break; + default: + retval = 0; /* invalid value -- indicates error */ + break; + } + + switch (*cp) { + + + +Davis, et al Experimental [Page 12] + +RFC 1876 Location Information in the DNS January 1996 + + + case 'N': case 'n': + case 'S': case 's': + *which = 1; /* latitude */ + break; + case 'E': case 'e': + case 'W': case 'w': + *which = 2; /* longitude */ + break; + default: + *which = 0; /* error */ + break; + } + + cp++; /* skip the hemisphere */ + + while (!isspace(*cp)) /* if any trailing garbage */ + cp++; + + while (isspace(*cp)) /* move to next field */ + cp++; + + *latlonstrptr = cp; + + return (retval); +} + +/* converts a zone file representation in a string to an RDATA + * on-the-wire representation. */ +u_int32_t +loc_aton(ascii, binary) + const char *ascii; + u_char *binary; +{ + const char *cp, *maxcp; + u_char *bcp; + + u_int32_t latit = 0, longit = 0, alt = 0; + u_int32_t lltemp1 = 0, lltemp2 = 0; + int altmeters = 0, altfrac = 0, altsign = 1; + u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */ + u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */ + u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */ + int which1 = 0, which2 = 0; + + cp = ascii; + maxcp = cp + strlen(ascii); + + lltemp1 = latlon2ul(&cp, &which1); + + + +Davis, et al Experimental [Page 13] + +RFC 1876 Location Information in the DNS January 1996 + + + lltemp2 = latlon2ul(&cp, &which2); + + switch (which1 + which2) { + case 3: /* 1 + 2, the only valid combination */ + if ((which1 == 1) && (which2 == 2)) { /* normal case */ + latit = lltemp1; + longit = lltemp2; + } else if ((which1 == 2) && (which2 == 1)) {/*reversed*/ + longit = lltemp1; + latit = lltemp2; + } else { /* some kind of brokenness */ + return 0; + } + break; + default: /* we didn't get one of each */ + return 0; + } + + /* altitude */ + if (*cp == '-') { + altsign = -1; + cp++; + } + + if (*cp == '+') + cp++; + + while (isdigit(*cp)) + altmeters = altmeters * 10 + (*cp++ - '0'); + + if (*cp == '.') { /* decimal meters */ + cp++; + if (isdigit(*cp)) { + altfrac = (*cp++ - '0') * 10; + if (isdigit(*cp)) { + altfrac += (*cp++ - '0'); + } + } + } + + alt = (10000000 + (altsign * (altmeters * 100 + altfrac))); + + while (!isspace(*cp) && (cp < maxcp)) + /* if trailing garbage or m */ + cp++; + + while (isspace(*cp) && (cp < maxcp)) + cp++; + + + +Davis, et al Experimental [Page 14] + +RFC 1876 Location Information in the DNS January 1996 + + + if (cp >= maxcp) + goto defaults; + + siz = precsize_aton(&cp); + + while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/ + cp++; + + while (isspace(*cp) && (cp < maxcp)) + cp++; + + if (cp >= maxcp) + goto defaults; + + hp = precsize_aton(&cp); + + while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/ + cp++; + + while (isspace(*cp) && (cp < maxcp)) + cp++; + + if (cp >= maxcp) + goto defaults; + + vp = precsize_aton(&cp); + + defaults: + + bcp = binary; + *bcp++ = (u_int8_t) 0; /* version byte */ + *bcp++ = siz; + *bcp++ = hp; + *bcp++ = vp; + PUTLONG(latit,bcp); + PUTLONG(longit,bcp); + PUTLONG(alt,bcp); + + return (16); /* size of RR in octets */ +} + +/* takes an on-the-wire LOC RR and prints it in zone file + * (human readable) format. */ +char * +loc_ntoa(binary,ascii) + const u_char *binary; + char *ascii; +{ + + + +Davis, et al Experimental [Page 15] + +RFC 1876 Location Information in the DNS January 1996 + + + static char tmpbuf[255*3]; + + register char *cp; + register const u_char *rcp; + + int latdeg, latmin, latsec, latsecfrac; + int longdeg, longmin, longsec, longsecfrac; + char northsouth, eastwest; + int altmeters, altfrac, altsign; + + const int referencealt = 100000 * 100; + + int32_t latval, longval, altval; + u_int32_t templ; + u_int8_t sizeval, hpval, vpval, versionval; + + char *sizestr, *hpstr, *vpstr; + + rcp = binary; + if (ascii) + cp = ascii; + else { + cp = tmpbuf; + } + + versionval = *rcp++; + + if (versionval) { + sprintf(cp,"; error: unknown LOC RR version"); + return (cp); + } + + sizeval = *rcp++; + + hpval = *rcp++; + vpval = *rcp++; + + GETLONG(templ,rcp); + latval = (templ - ((unsigned)1<<31)); + + GETLONG(templ,rcp); + longval = (templ - ((unsigned)1<<31)); + + GETLONG(templ,rcp); + if (templ < referencealt) { /* below WGS 84 spheroid */ + altval = referencealt - templ; + altsign = -1; + } else { + + + +Davis, et al Experimental [Page 16] + +RFC 1876 Location Information in the DNS January 1996 + + + altval = templ - referencealt; + altsign = 1; + } + + if (latval < 0) { + northsouth = 'S'; + latval = -latval; + } + else + northsouth = 'N'; + + latsecfrac = latval % 1000; + latval = latval / 1000; + latsec = latval % 60; + latval = latval / 60; + latmin = latval % 60; + latval = latval / 60; + latdeg = latval; + + if (longval < 0) { + eastwest = 'W'; + longval = -longval; + } + else + eastwest = 'E'; + + longsecfrac = longval % 1000; + longval = longval / 1000; + longsec = longval % 60; + longval = longval / 60; + longmin = longval % 60; + longval = longval / 60; + longdeg = longval; + + altfrac = altval % 100; + altmeters = (altval / 100) * altsign; + + sizestr = savestr(precsize_ntoa(sizeval)); + hpstr = savestr(precsize_ntoa(hpval)); + vpstr = savestr(precsize_ntoa(vpval)); + + sprintf(cp, + "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm + %sm %sm %sm", + latdeg, latmin, latsec, latsecfrac, northsouth, + longdeg, longmin, longsec, longsecfrac, eastwest, + altmeters, altfrac, sizestr, hpstr, vpstr); + + + + +Davis, et al Experimental [Page 17] + +RFC 1876 Location Information in the DNS January 1996 + + + free(sizestr); + free(hpstr); + free(vpstr); + + return (cp); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Davis, et al Experimental [Page 18] + diff --git a/doc/rfc/rfc2168.txt b/doc/rfc/rfc2168.txt new file mode 100644 index 0000000000..3eed1bdb4d --- /dev/null +++ b/doc/rfc/rfc2168.txt @@ -0,0 +1,1123 @@ + + + + + + +Network Working Group R. Daniel +Request for Comments: 2168 Los Alamos National Laboratory +Category: Experimental M. Mealling + Network Solutions, Inc. + June 1997 + + + Resolution of Uniform Resource Identifiers + using the Domain Name System + +Status of this Memo +=================== + + This memo defines an Experimental Protocol for the Internet + community. This memo does not specify an Internet standard of any + kind. Discussion and suggestions for improvement are requested. + Distribution of this memo is unlimited. + +Abstract: +========= + + Uniform Resource Locators (URLs) are the foundation of the World Wide + Web, and are a vital Internet technology. However, they have proven + to be brittle in practice. The basic problem is that URLs typically + identify a particular path to a file on a particular host. There is + no graceful way of changing the path or host once the URL has been + assigned. Neither is there a graceful way of replicating the resource + located by the URL to achieve better network utilization and/or fault + tolerance. Uniform Resource Names (URNs) have been hypothesized as a + adjunct to URLs that would overcome such problems. URNs and URLs are + both instances of a broader class of identifiers known as Uniform + Resource Identifiers (URIs). + + The requirements document for URN resolution systems[15] defines the + concept of a "resolver discovery service". This document describes + the first, experimental, RDS. It is implemented by a new DNS Resource + Record, NAPTR (Naming Authority PoinTeR), that provides rules for + mapping parts of URIs to domain names. By changing the mapping + rules, we can change the host that is contacted to resolve a URI. + This will allow a more graceful handling of URLs over long time + periods, and forms the foundation for a new proposal for Uniform + Resource Names. + + + + + + + + + +Daniel & Mealling Experimental [Page 1] + +RFC 2168 Resolution of URIs Using the DNS June 1997 + + + In addition to locating resolvers, the NAPTR provides for other + naming systems to be grandfathered into the URN world, provides + independence between the name assignment system and the resolution + protocol system, and allows multiple services (Name to Location, Name + to Description, Name to Resource, ...) to be offered. In conjunction + with the SRV RR, the NAPTR record allows those services to be + replicated for the purposes of fault tolerance and load balancing. + +Introduction: +============= + + Uniform Resource Locators have been a significant advance in + retrieving Internet-accessible resources. However, their brittle + nature over time has been recognized for several years. The Uniform + Resource Identifier working group proposed the development of Uniform + Resource Names to serve as persistent, location-independent + identifiers for Internet resources in order to overcome most of the + problems with URLs. RFC-1737 [1] sets forth requirements on URNs. + + During the lifetime of the URI-WG, a number of URN proposals were + generated. The developers of several of those proposals met in a + series of meetings, resulting in a compromise known as the Knoxville + framework. The major principle behind the Knoxville framework is + that the resolution system must be separate from the way names are + assigned. This is in marked contrast to most URLs, which identify the + host to contact and the protocol to use. Readers are referred to [2] + for background on the Knoxville framework and for additional + information on the context and purpose of this proposal. + + Separating the way names are resolved from the way they are + constructed provides several benefits. It allows multiple naming + approaches and resolution approaches to compete, as it allows + different protocols and resolvers to be used. There is just one + problem with such a separation - how do we resolve a name when it + can't give us directions to its resolver? + + For the short term, DNS is the obvious candidate for the resolution + framework, since it is widely deployed and understood. However, it is + not appropriate to use DNS to maintain information on a per-resource + basis. First of all, DNS was never intended to handle that many + records. Second, the limited record size is inappropriate for catalog + information. Third, domain names are not appropriate as URNs. + + Therefore our approach is to use DNS to locate "resolvers" that can + provide information on individual resources, potentially including + the resource itself. To accomplish this, we "rewrite" the URI into a + domain name following the rules provided in NAPTR records. Rewrite + rules provide considerable power, which is important when trying to + + + +Daniel & Mealling Experimental [Page 2] + +RFC 2168 Resolution of URIs Using the DNS June 1997 + + + meet the goals listed above. However, collections of rules can become + difficult to understand. To lessen this problem, the NAPTR rules are + *always* applied to the original URI, *never* to the output of + previous rules. + + Locating a resolver through the rewrite procedure may take multiple + steps, but the beginning is always the same. The start of the URI is + scanned to extract its colon-delimited prefix. (For URNs, the prefix + is always "urn:" and we extract the following colon-delimited + namespace identifier [3]). NAPTR resolution begins by taking the + extracted string, appending the well-known suffix ".urn.net", and + querying the DNS for NAPTR records at that domain name. Based on the + results of this query, zero or more additional DNS queries may be + needed to locate resolvers for the URI. The details of the + conversation between the client and the resolver thus located are + outside the bounds of this draft. Three brief examples of this + procedure are given in the next section. + + The NAPTR RR provides the level of indirection needed to keep the + naming system independent of the resolution system, its protocols, + and services. Coupled with the new SRV resource record proposal[4] + there is also the potential for replicating the resolver on multiple + hosts, overcoming some of the most significant problems of URLs. This + is an important and subtle point. Not only do the NAPTR and SRV + records allow us to replicate the resource, we can replicate the + resolvers that know about the replicated resource. Preventing a + single point of failure at the resolver level is a significant + benefit. Separating the resolution procedure from the way names are + constructed has additional benefits. Different resolution procedures + can be used over time, and resolution procedures that are determined + to be useful can be extended to deal with additional namespaces. + +Caveats +======= + + The NAPTR proposal is the first resolution procedure to be considered + by the URN-WG. There are several concerns about the proposal which + have motivated the group to recommend it for publication as an + Experimental rather than a standards-track RFC. + + First, URN resolution is new to the IETF and we wish to gain + operational experience before recommending any procedure for the + standards track. Second, the NAPTR proposal is based on DNS and + consequently inherits concerns about security and administration. The + recent advancement of the DNSSEC and secure update drafts to Proposed + Standard reduce these concerns, but we wish to experiment with those + new capabilities in the context of URN administration. A third area + of concern is the potential for a noticeable impact on the DNS. We + + + +Daniel & Mealling Experimental [Page 3] + +RFC 2168 Resolution of URIs Using the DNS June 1997 + + + believe that the proposal makes appropriate use of caching and + additional information, but it is best to go slow where the potential + for impact on a core system like the DNS is concerned. Fourth, the + rewrite rules in the NAPTR proposal are based on regular expressions. + Since regular expressions are difficult for humans to construct + correctly, concerns exist about the usability and maintainability of + the rules. This is especially true where international character sets + are concerned. Finally, the URN-WG is developing a requirements + document for URN Resolution Services[15], but that document is not + complete. That document needs to precede any resolution service + proposals on the standards track. + +Terminology +=========== + + "Must" or "Shall" - Software that does not behave in the manner that + this document says it must is not conformant to this + document. + "Should" - Software that does not follow the behavior that this + document says it should may still be conformant, but is + probably broken in some fundamental way. + "May" - Implementations may or may not provide the described + behavior, while still remaining conformant to this + document. + +Brief overview and examples of the NAPTR RR: +============================================ + + A detailed description of the NAPTR RR will be given later, but to + give a flavor for the proposal we first give a simple description of + the record and three examples of its use. + + The key fields in the NAPTR RR are order, preference, service, flags, + regexp, and replacement: + + * The order field specifies the order in which records MUST be + processed when multiple NAPTR records are returned in response to a + single query. A naming authority may have delegated a portion of + its namespace to another agency. Evaluating the NAPTR records in + the correct order is necessary for delegation to work properly. + + * The preference field specifies the order in which records SHOULD be + processed when multiple NAPTR records have the same value of + "order". This field lets a service provider specify the order in + which resolvers are contacted, so that more capable machines are + contacted in preference to less capable ones. + + + + + +Daniel & Mealling Experimental [Page 4] + +RFC 2168 Resolution of URIs Using the DNS June 1997 + + + * The service field specifies the resolution protocol and resolution + service(s) that will be available if the rewrite specified by the + regexp or replacement fields is applied. Resolution protocols are + the protocols used to talk with a resolver. They will be specified + in other documents, such as [5]. Resolution services are operations + such as N2R (URN to Resource), N2L (URN to URL), N2C (URN to URC), + etc. These will be discussed in the URN Resolution Services + document[6], and their behavior in a particular resolution protocol + will be given in the specification for that protocol (see [5] for a + concrete example). + + * The flags field contains modifiers that affect what happens in the + next DNS lookup, typically for optimizing the process. Flags may + also affect the interpretation of the other fields in the record, + therefore, clients MUST skip NAPTR records which contain an unknown + flag value. + + * The regexp field is one of two fields used for the rewrite rules, + and is the core concept of the NAPTR record. The regexp field is a + String containing a sed-like substitution expression. (The actual + grammar for the substitution expressions is given later in this + draft). The substitution expression is applied to the original URN + to determine the next domain name to be queried. The regexp field + should be used when the domain name to be generated is conditional + on information in the URI. If the next domain name is always known, + which is anticipated to be a common occurrence, the replacement + field should be used instead. + + * The replacement field is the other field that may be used for the + rewrite rule. It is an optimization of the rewrite process for the + case where the next domain name is fixed instead of being + conditional on the content of the URI. The replacement field is a + domain name (subject to compression if a DNS sender knows that a + given recipient is able to decompress names in this RR type's RDATA + field). If the rewrite is more complex than a simple substitution + of a domain name, the replacement field should be set to . and the + regexp field used. + + + + + + + + + + + + + + +Daniel & Mealling Experimental [Page 5] + +RFC 2168 Resolution of URIs Using the DNS June 1997 + + + Note that the client applies all the substitutions and performs all + lookups, they are not performed in the DNS servers. Note also that it + is the belief of the developers of this document that regexps should + rarely be used. The replacement field seems adequate for the vast + majority of situations. Regexps are only necessary when portions of a + namespace are to be delegated to different resolvers. Finally, note + that the regexp and replacement fields are, at present, mutually + exclusive. However, developers of client software should be aware + that a new flag might be defined which requires values in both + fields. + +Example 1 +--------- + + Consider a URN that uses the hypothetical DUNS namespace. DUNS + numbers are identifiers for approximately 30 million registered + businesses around the world, assigned and maintained by Dunn and + Bradstreet. The URN might look like: + + urn:duns:002372413:annual-report-1997 + + The first step in the resolution process is to find out about the + DUNS namespace. The namespace identifier, "duns", is extracted from + the URN, prepended to urn.net, and the NAPTRs for duns.urn.net looked + up. It might return records of the form: + +duns.urn.net +;; order pref flags service regexp replacement + IN NAPTR 100 10 "s" "dunslink+N2L+N2C" "" dunslink.udp.isi.dandb.com + IN NAPTR 100 20 "s" "rcds+N2C" "" rcds.udp.isi.dandb.com + IN NAPTR 100 30 "s" "http+N2L+N2C+N2R" "" http.tcp.isi.dandb.com + + The order field contains equal values, indicating that no name + delegation order has to be followed. The preference field indicates + that the provider would like clients to use the special dunslink + protocol, followed by the RCDS protocol, and that HTTP is offered as + a last resort. All the records specify the "s" flag, which will be + explained momentarily. The service fields say that if we speak + dunslink, we will be able to issue either the N2L or N2C requests to + obtain a URL or a URC (description) of the resource. The Resource + Cataloging and Distribution Service (RCDS)[7] could be used to get a + URC for the resource, while HTTP could be used to get a URL, URC, or + the resource itself. All the records supply the next domain name to + query, none of them need to be rewritten with the aid of regular + expressions. + + + + + + +Daniel & Mealling Experimental [Page 6] + +RFC 2168 Resolution of URIs Using the DNS June 1997 + + + The general case might require multiple NAPTR rewrites to locate a + resolver, but eventually we will come to the "terminal NAPTR". Once + we have the terminal NAPTR, our next probe into the DNS will be for a + SRV or A record instead of another NAPTR. Rather than probing for a + non-existent NAPTR record to terminate the loop, the flags field is + used to indicate a terminal lookup. If it has a value of "s", the + next lookup should be for SRV RRs, "a" denotes that A records should + sought. A "p" flag is also provided to indicate that the next action + is Protocol-specific, but that looking up another NAPTR will not be + part of it. + + Since our example RR specified the "s" flag, it was terminal. + Assuming our client does not know the dunslink protocol, our next + action is to lookup SRV RRs for rcds.udp.isi.dandb.com, which will + tell us hosts that can provide the necessary resolution service. That + lookup might return: + + ;; Pref Weight Port Target + rcds.udp.isi.dandb.com IN SRV 0 0 1000 defduns.isi.dandb.com + IN SRV 0 0 1000 dbmirror.com.au + IN SRV 0 0 1000 ukmirror.com.uk + + telling us three hosts that could actually do the resolution, and + giving us the port we should use to talk to their RCDS server. (The + reader is referred to the SRV proposal [4] for the interpretation of + the fields above). + + There is opportunity for significant optimization here. We can return + the SRV records as additional information for terminal NAPTRs (and + the A records as additional information for those SRVs). While this + recursive provision of additional information is not explicitly + blessed in the DNS specifications, it is not forbidden, and BIND does + take advantage of it [8]. This is a significant optimization. In + conjunction with a long TTL for *.urn.net records, the average number + of probes to DNS for resolving DUNS URNs would approach one. + Therefore, DNS server implementors SHOULD provide additional + information with NAPTR responses. The additional information will be + either SRV or A records. If SRV records are available, their A + records should be provided as recursive additional information. + + Note that the example NAPTR records above are intended to represent + the reply the client will see. They are not quite identical to what + the domain administrator would put into the zone files. For one + thing, the administrator should supply the trailing '.' character on + any FQDNs. + + + + + + +Daniel & Mealling Experimental [Page 7] + +RFC 2168 Resolution of URIs Using the DNS June 1997 + + +Example 2 +--------- + + Consider a URN namespace based on MIME Content-Ids. The URN might + look like this: + + urn:cid:199606121851.1@mordred.gatech.edu + + (Note that this example is chosen for pedagogical purposes, and does + not conform to the recently-approved CID URL scheme.) + + The first step in the resolution process is to find out about the CID + namespace. The namespace identifier, cid, is extracted from the URN, + prepended to urn.net, and the NAPTR for cid.urn.net looked up. It + might return records of the form: + + cid.urn.net + ;; order pref flags service regexp replacement + IN NAPTR 100 10 "" "" "/urn:cid:.+@([^\.]+\.)(.*)$/\2/i" . + + We have only one NAPTR response, so ordering the responses is not a + problem. The replacement field is empty, so we check the regexp + field and use the pattern provided there. We apply that regexp to the + entire URN to see if it matches, which it does. The \2 part of the + substitution expression returns the string "gatech.edu". Since the + flags field does not contain "s" or "a", the lookup is not terminal + and our next probe to DNS is for more NAPTR records: + lookup(query=NAPTR, "gatech.edu"). + + Note that the rule does not extract the full domain name from the + CID, instead it assumes the CID comes from a host and extracts its + domain. While all hosts, such as mordred, could have their very own + NAPTR, maintaining those records for all the machines at a site as + large as Georgia Tech would be an intolerable burden. Wildcards are + not appropriate here since they only return results when there is no + exactly matching names already in the system. + + The record returned from the query on "gatech.edu" might look like: + +gatech.edu IN NAPTR +;; order pref flags service regexp replacement + IN NAPTR 100 50 "s" "z3950+N2L+N2C" "" z3950.tcp.gatech.edu + IN NAPTR 100 50 "s" "rcds+N2C" "" rcds.udp.gatech.edu + IN NAPTR 100 50 "s" "http+N2L+N2C+N2R" "" http.tcp.gatech.edu + + + + + + + +Daniel & Mealling Experimental [Page 8] + +RFC 2168 Resolution of URIs Using the DNS June 1997 + + + Continuing with our example, we note that the values of the order and + preference fields are equal in all records, so the client is free to + pick any record. The flags field tells us that these are the last + NAPTR patterns we should see, and after the rewrite (a simple + replacement in this case) we should look up SRV records to get + information on the hosts that can provide the necessary service. + + Assuming we prefer the Z39.50 protocol, our lookup might return: + + ;; Pref Weight Port Target + z3950.tcp.gatech.edu IN SRV 0 0 1000 z3950.gatech.edu + IN SRV 0 0 1000 z3950.cc.gatech.edu + IN SRV 0 0 1000 z3950.uga.edu + + telling us three hosts that could actually do the resolution, and + giving us the port we should use to talk to their Z39.50 server. + + Recall that the regular expression used \2 to extract a domain name + from the CID, and \. for matching the literal '.' characters + seperating the domain name components. Since '\' is the escape + character, literal occurances of a backslash must be escaped by + another backslash. For the case of the cid.urn.net record above, the + regular expression entered into the zone file should be + "/urn:cid:.+@([^\\.]+\\.)(.*)$/\\2/i". When the client code actually + receives the record, the pattern will have been converted to + "/urn:cid:.+@([^.]+\.)(.*)$/\2/i". + +Example 3 +--------- + + Even if URN systems were in place now, there would still be a + tremendous number of URLs. It should be possible to develop a URN + resolution system that can also provide location independence for + those URLs. This is related to the requirement in [1] to be able to + grandfather in names from other naming systems, such as ISO Formal + Public Identifiers, Library of Congress Call Numbers, ISBNs, ISSNs, + etc. + + The NAPTR RR could also be used for URLs that have already been + assigned. Assume we have the URL for a very popular piece of + software that the publisher wishes to mirror at multiple sites around + the world: + + http://www.foo.com/software/latest-beta.exe + + + + + + + +Daniel & Mealling Experimental [Page 9] + +RFC 2168 Resolution of URIs Using the DNS June 1997 + + + We extract the prefix, "http", and lookup NAPTR records for + http.urn.net. This might return a record of the form + + http.urn.net IN NAPTR + ;; order pref flags service regexp replacement + 100 90 "" "" "!http://([^/:]+)!\1!i" . + + This expression returns everything after the first double slash and + before the next slash or colon. (We use the '!' character to delimit + the parts of the substitution expression. Otherwise we would have to + use backslashes to escape the forward slashes, and would have a + regexp in the zone file that looked like + "/http:\\/\\/([^\\/:]+)/\\1/i".). + + Applying this pattern to the URL extracts "www.foo.com". Looking up + NAPTR records for that might return: + + www.foo.com + ;; order pref flags service regexp replacement + IN NAPTR 100 100 "s" "http+L2R" "" http.tcp.foo.com + IN NAPTR 100 100 "s" "ftp+L2R" "" ftp.tcp.foo.com + + Looking up SRV records for http.tcp.foo.com would return information + on the hosts that foo.com has designated to be its mirror sites. The + client can then pick one for the user. + +NAPTR RR Format +=============== + + The format of the NAPTR RR is given below. The DNS type code for + NAPTR is 35. + + Domain TTL Class Order Preference Flags Service Regexp + Replacement + + where: + + Domain + The domain name this resource record refers to. + TTL + Standard DNS Time To Live field + Class + Standard DNS meaning + + + + + + + + +Daniel & Mealling Experimental [Page 10] + +RFC 2168 Resolution of URIs Using the DNS June 1997 + + + Order + A 16-bit integer specifying the order in which the NAPTR + records MUST be processed to ensure correct delegation of + portions of the namespace over time. Low numbers are processed + before high numbers, and once a NAPTR is found that "matches" + a URN, the client MUST NOT consider any NAPTRs with a higher + value for order. + + Preference + A 16-bit integer which specifies the order in which NAPTR + records with equal "order" values SHOULD be processed, low + numbers being processed before high numbers. This is similar + to the preference field in an MX record, and is used so domain + administrators can direct clients towards more capable hosts + or lighter weight protocols. + + Flags + A String giving flags to control aspects of the rewriting and + interpretation of the fields in the record. Flags are single + characters from the set [A-Z0-9]. The case of the alphabetic + characters is not significant. + + At this time only three flags, "S", "A", and "P", are defined. + "S" means that the next lookup should be for SRV records + instead of NAPTR records. "A" means that the next lookup + should be for A records. The "P" flag says that the remainder + of the resolution shall be carried out in a Protocol-specific + fashion, and we should not do any more DNS queries. + + The remaining alphabetic flags are reserved. The numeric flags + may be used for local experimentation. The S, A, and P flags + are all mutually exclusive, and resolution libraries MAY + signal an error if more than one is given. (Experimental code + and code for assisting in the creation of NAPTRs would be more + likely to signal such an error than a client such as a + browser). We anticipate that multiple flags will be allowed in + the future, so implementers MUST NOT assume that the flags + field can only contain 0 or 1 characters. Finally, if a client + encounters a record with an unknown flag, it MUST ignore it + and move to the next record. This test takes precedence even + over the "order" field. Since flags can control the + interpretation placed on fields, a novel flag might change the + interpretation of the regexp and/or replacement fields such + that it is impossible to determine if a record matched a URN. + + + + + + + +Daniel & Mealling Experimental [Page 11] + +RFC 2168 Resolution of URIs Using the DNS June 1997 + + + Service + Specifies the resolution service(s) available down this + rewrite path. It may also specify the particular protocol that + is used to talk with a resolver. A protocol MUST be specified + if the flags field states that the NAPTR is terminal. If a + protocol is specified, but the flags field does not state that + the NAPTR is terminal, the next lookup MUST be for a NAPTR. + The client MAY choose not to perform the next lookup if the + protocol is unknown, but that behavior MUST NOT be relied + upon. + + The service field may take any of the values below (using the + Augmented BNF of RFC 822[9]): + + service_field = [ [protocol] *("+" rs)] + protocol = ALPHA *31ALPHANUM + rs = ALPHA *31ALPHANUM + // The protocol and rs fields are limited to 32 + // characters and must start with an alphabetic. + // The current set of "known" strings are: + // protocol = "rcds" / "thttp" / "hdl" / "rwhois" / "z3950" + // rs = "N2L" / "N2Ls" / "N2R" / "N2Rs" / "N2C" + // / "N2Ns" / "L2R" / "L2Ns" / "L2Ls" / "L2C" + + i.e. an optional protocol specification followed by 0 or more + resolution services. Each resolution service is indicated by + an initial '+' character. + + Note that the empty string is also a valid service field. This + will typically be seen at the top levels of a namespace, when + it is impossible to know what services and protocols will be + offered by a particular publisher within that name space. + + At this time the known protocols are rcds[7], hdl[10] (binary, + UDP-based protocols), thttp[5] (a textual, TCP-based + protocol), rwhois[11] (textual, UDP or TCP based), and + Z39.50[12] (binary, TCP-based). More will be allowed later. + The names of the protocols must be formed from the characters + [a-Z0-9]. Case of the characters is not significant. + + The service requests currently allowed will be described in + more detail in [6], but in brief they are: + N2L - Given a URN, return a URL + N2Ls - Given a URN, return a set of URLs + N2R - Given a URN, return an instance of the resource. + N2Rs - Given a URN, return multiple instances of the + resource, typically encoded using + multipart/alternative. + + + +Daniel & Mealling Experimental [Page 12] + +RFC 2168 Resolution of URIs Using the DNS June 1997 + + + N2C - Given a URN, return a collection of meta- + information on the named resource. The format of + this response is the subject of another document. + N2Ns - Given a URN, return all URNs that are also + identifers for the resource. + L2R - Given a URL, return the resource. + L2Ns - Given a URL, return all the URNs that are + identifiers for the resource. + L2Ls - Given a URL, return all the URLs for instances of + of the same resource. + L2C - Given a URL, return a description of the + resource. + + The actual format of the service request and response will be + determined by the resolution protocol, and is the subject for + other documents (e.g. [5]). Protocols need not offer all + services. The labels for service requests shall be formed from + the set of characters [A-Z0-9]. The case of the alphabetic + characters is not significant. + + Regexp + A STRING containing a substitution expression that is applied + to the original URI in order to construct the next domain name + to lookup. The grammar of the substitution expression is given + in the next section. + + Replacement + The next NAME to query for NAPTR, SRV, or A records depending + on the value of the flags field. As mentioned above, this may + be compressed. + +Substitution Expression Grammar: +================================ + + The content of the regexp field is a substitution expression. True + sed(1) substitution expressions are not appropriate for use in this + application for a variety of reasons, therefore the contents of the + regexp field MUST follow the grammar below: + +subst_expr = delim-char ere delim-char repl delim-char *flags +delim-char = "/" / "!" / ... (Any non-digit or non-flag character other + than backslash '\'. All occurances of a delim_char in a + subst_expr must be the same character.) +ere = POSIX Extended Regular Expression (see [13], section + 2.8.4) +repl = dns_str / backref / repl dns_str / repl backref +dns_str = 1*DNS_CHAR +backref = "\" 1POS_DIGIT + + + +Daniel & Mealling Experimental [Page 13] + +RFC 2168 Resolution of URIs Using the DNS June 1997 + + +flags = "i" +DNS_CHAR = "-" / "0" / ... / "9" / "a" / ... / "z" / "A" / ... / "Z" +POS_DIGIT = "1" / "2" / ... / "9" ; 0 is not an allowed backref +value domain name (see RFC-1123 [14]). + + The result of applying the substitution expression to the original + URI MUST result in a string that obeys the syntax for DNS host names + [14]. Since it is possible for the regexp field to be improperly + specified, such that a non-conforming host name can be constructed, + client software SHOULD verify that the result is a legal host name + before making queries on it. + + Backref expressions in the repl portion of the substitution + expression are replaced by the (possibly empty) string of characters + enclosed by '(' and ')' in the ERE portion of the substitution + expression. N is a single digit from 1 through 9, inclusive. It + specifies the N'th backref expression, the one that begins with the + N'th '(' and continues to the matching ')'. For example, the ERE + (A(B(C)DE)(F)G) + has backref expressions: + \1 = ABCDEFG + \2 = BCDE + \3 = C + \4 = F + \5..\9 = error - no matching subexpression + + The "i" flag indicates that the ERE matching SHALL be performed in a + case-insensitive fashion. Furthermore, any backref replacements MAY + be normalized to lower case when the "i" flag is given. + + The first character in the substitution expression shall be used as + the character that delimits the components of the substitution + expression. There must be exactly three non-escaped occurrences of + the delimiter character in a substitution expression. Since escaped + occurrences of the delimiter character will be interpreted as + occurrences of that character, digits MUST NOT be used as delimiters. + Backrefs would be confused with literal digits were this allowed. + Similarly, if flags are specified in the substitution expression, the + delimiter character must not also be a flag character. + + + + + + + + + + + + +Daniel & Mealling Experimental [Page 14] + +RFC 2168 Resolution of URIs Using the DNS June 1997 + + +Advice to domain administrators: +================================ + + Beware of regular expressions. Not only are they a pain to get + correct on their own, but there is the previously mentioned + interaction with DNS. Any backslashes in a regexp must be entered + twice in a zone file in order to appear once in a query response. + More seriously, the need for double backslashes has probably not been + tested by all implementors of DNS servers. We anticipate that urn.net + will be the heaviest user of regexps. Only when delegating portions + of namespaces should the typical domain administrator need to use + regexps. + + On a related note, beware of interactions with the shell when + manipulating regexps from the command line. Since '\' is a common + escape character in shells, there is a good chance that when you + think you are saying "\\" you are actually saying "\". Similar + caveats apply to characters such as + + The "a" flag allows the next lookup to be for A records rather than + SRV records. Since there is no place for a port specification in the + NAPTR record, when the "A" flag is used the specified protocol must + be running on its default port. + + The URN Sytnax draft defines a canonical form for each URN, which + requires %encoding characters outside a limited repertoire. The + regular expressions MUST be written to operate on that canonical + form. Since international character sets will end up with extensive + use of %encoded characters, regular expressions operating on them + will be essentially impossible to read or write by hand. + +Usage +===== + + For the edification of implementers, pseudocode for a client routine + using NAPTRs is given below. This code is provided merely as a + convience, it does not have any weight as a standard way to process + NAPTR records. Also, as is the case with pseudocode, it has never + been executed and may contain logical errors. You have been warned. + + // + // findResolver(URN) + // Given a URN, find a host that can resolve it. + // + findResolver(string URN) { + // prepend prefix to urn.net + sprintf(key, "%s.urn.net", extractNS(URN)); + do { + + + +Daniel & Mealling Experimental [Page 15] + +RFC 2168 Resolution of URIs Using the DNS June 1997 + + + rewrite_flag = false; + terminal = false; + if (key has been seen) { + quit with a loop detected error + } + add key to list of "seens" + records = lookup(type=NAPTR, key); // get all NAPTR RRs for 'key' + + discard any records with an unknown value in the "flags" field. + sort NAPTR records by "order" field and "preference" field + (with "order" being more significant than "preference"). + n_naptrs = number of NAPTR records in response. + curr_order = records[0].order; + max_order = records[n_naptrs-1].order; + + // Process current batch of NAPTRs according to "order" field. + for (j=0; j < n_naptrs && records[j].order <= max_order; j++) { + if (unknown_flag) // skip this record and go to next one + continue; + newkey = rewrite(URN, naptr[j].replacement, naptr[j].regexp); + if (!newkey) // Skip to next record if the rewrite didn't + match continue; + // We did do a rewrite, shrink max_order to current value + // so that delegation works properly + max_order = naptr[j].order; + // Will we know what to do with the protocol and services + // specified in the NAPTR? If not, try next record. + if(!isKnownProto(naptr[j].services)) { + continue; + } + if(!isKnownService(naptr[j].services)) { + continue; + } + + // At this point we have a successful rewrite and we will + // know how to speak the protocol and request a known + // resolution service. Before we do the next lookup, check + // some optimization possibilities. + + if (strcasecmp(flags, "S") + || strcasecmp(flags, "P")) + || strcasecmp(flags, "A")) { + terminal = true; + services = naptr[j].services; + addnl = any SRV and/or A records returned as additional + info for naptr[j]. + } + key = newkey; + + + +Daniel & Mealling Experimental [Page 16] + +RFC 2168 Resolution of URIs Using the DNS June 1997 + + + rewriteflag = true; + break; + } + } while (rewriteflag && !terminal); + + // Did we not find our way to a resolver? + if (!rewrite_flag) { + report an error + return NULL; + } + + + // Leave rest to another protocol? + if (strcasecmp(flags, "P")) { + return key as host to talk to; + } + + // If not, keep plugging + if (!addnl) { // No SRVs came in as additional info, look them up + srvs = lookup(type=SRV, key); + } + + sort SRV records by preference, weight, ... + foreach (SRV record) { // in order of preference + try contacting srv[j].target using the protocol and one of the + resolution service requests from the "services" field of the + last NAPTR record. + if (successful) + return (target, protocol, service); + // Actually we would probably return a result, but this + // code was supposed to just tell us a good host to talk to. + } + die with an "unable to find a host" error; + } + +Notes: +====== + + - A client MUST process multiple NAPTR records in the order + specified by the "order" field, it MUST NOT simply use the first + record that provides a known protocol and service combination. + + + + + + + + + + +Daniel & Mealling Experimental [Page 17] + +RFC 2168 Resolution of URIs Using the DNS June 1997 + + + - If a record at a particular order matches the URI, but the + client doesn't know the specified protocol and service, the + client SHOULD continue to examine records that have the same + order. The client MUST NOT consider records with a higher value + of order. This is necessary to make delegation of portions of + the namespace work. The order field is what lets site + administrators say "all requests for URIs matching pattern x go + to server 1, all others go to server 2". + (A match is defined as: + 1) The NAPTR provides a replacement domain name + or + 2) The regular expression matches the URN + ) + + - When multiple RRs have the same "order", the client should use + the value of the preference field to select the next NAPTR to + consider. However, because of preferred protocols or services, + estimates of network distance and bandwidth, etc. clients may + use different criteria to sort the records. + - If the lookup after a rewrite fails, clients are strongly + encouraged to report a failure, rather than backing up to pursue + other rewrite paths. + - When a namespace is to be delegated among a set of resolvers, + regexps must be used. Each regexp appears in a separate NAPTR + RR. Administrators should do as little delegation as possible, + because of limitations on the size of DNS responses. + - Note that SRV RRs impose additional requirements on clients. + +Acknowledgments: +================= + + The editors would like to thank Keith Moore for all his consultations + during the development of this draft. We would also like to thank + Paul Vixie for his assistance in debugging our implementation, and + his answers on our questions. Finally, we would like to acknowledge + our enormous intellectual debt to the participants in the Knoxville + series of meetings, as well as to the participants in the URI and URN + working groups. + +References: +=========== + + [1] Sollins, Karen and Larry Masinter, "Functional Requirements + for Uniform Resource Names", RFC-1737, Dec. 1994. + + [2] The URN Implementors, Uniform Resource Names: A Progress Report, + http://www.dlib.org/dlib/february96/02arms.html, D-Lib Magazine, + February 1996. + + + +Daniel & Mealling Experimental [Page 18] + +RFC 2168 Resolution of URIs Using the DNS June 1997 + + + [3] Moats, Ryan, "URN Syntax", RFC-2141, May 1997. + + [4] Gulbrandsen, A. and P. Vixie, "A DNS RR for specifying + the location of services (DNS SRV)", RFC-2052, October 1996. + + [5] Daniel, Jr., Ron, "A Trivial Convention for using HTTP in URN + Resolution", RFC-2169, June 1997. + + [6] URN-WG, "URN Resolution Services", Work in Progress. + + [7] Moore, Keith, Shirley Browne, Jason Cox, and Jonathan Gettler, + Resource Cataloging and Distribution System, Technical Report + CS-97-346, University of Tennessee, Knoxville, December 1996 + + [8] Paul Vixie, personal communication. + + [9] Crocker, Dave H. "Standard for the Format of ARPA Internet Text + Messages", RFC-822, August 1982. + + [10] Orth, Charles and Bill Arms; Handle Resolution Protocol + Specification, http://www.handle.net/docs/client_spec.html + + [11] Williamson, S., M. Kosters, D. Blacka, J. Singh, K. Zeilstra, + "Referral Whois Protocol (RWhois)", RFC-2167, June 1997. + + [12] Information Retrieval (Z39.50): Application Service Definition + and Protocol Specification, ANSI/NISO Z39.50-1995, July 1995. + + [13] IEEE Standard for Information Technology - Portable Operating + System Interface (POSIX) - Part 2: Shell and Utilities (Vol. 1); + IEEE Std 1003.2-1992; The Institute of Electrical and + Electronics Engineers; New York; 1993. ISBN:1-55937-255-9 + + [14] Braden, R., "Requirements for Internet Hosts - Application and + and Support", RFC-1123, Oct. 1989. + + [15] Sollins, Karen, "Requirements and a Framework for URN Resolution + Systems", November 1996, Work in Progress. + + + + + + + + + + + + + +Daniel & Mealling Experimental [Page 19] + +RFC 2168 Resolution of URIs Using the DNS June 1997 + + +Security Considerations +======================= + + The use of "urn.net" as the registry for URN namespaces is subject to + denial of service attacks, as well as other DNS spoofing attacks. The + interactions with DNSSEC are currently being studied. It is expected + that NAPTR records will be signed with SIG records once the DNSSEC + work is deployed. + + The rewrite rules make identifiers from other namespaces subject to + the same attacks as normal domain names. Since they have not been + easily resolvable before, this may or may not be considered a + problem. + + Regular expressions should be checked for sanity, not blindly passed + to something like PERL. + + This document has discussed a way of locating a resolver, but has not + discussed any detail of how the communication with the resolver takes + place. There are significant security considerations attached to the + communication with a resolver. Those considerations are outside the + scope of this document, and must be addressed by the specifications + for particular resolver communication protocols. + +Author Contact Information: +=========================== + + Ron Daniel + Los Alamos National Laboratory + MS B287 + Los Alamos, NM, USA, 87545 + voice: +1 505 665 0597 + fax: +1 505 665 4939 + email: rdaniel@lanl.gov + + + Michael Mealling + Network Solutions + 505 Huntmar Park Drive + Herndon, VA 22070 + voice: (703) 742-0400 + fax: (703) 742-9552 + email: michaelm@internic.net + URL: http://www.netsol.com/ + + + + + + + +Daniel & Mealling Experimental [Page 20] +