client.c revision 260b413740a3f1eeef333862c70767df40678404
/*
* 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 <config.h>
#include <isc/assertions.h>
#include <dns/dispatch.h>
#define NS_CLIENT_TRACE
#ifdef NS_CLIENT_TRACE
#include <stdio.h>
#else
#define CTRACE(m)
#define MTRACE(m)
#endif
#define SEND_BUFFER_SIZE 512
struct ns_clientmgr {
/* Unlocked. */
unsigned int magic;
/* Locked by lock. */
unsigned int nclients;
};
#define VALID_MANAGER(m) ((m) != NULL && \
(m)->magic == MANAGER_MAGIC)
/***
*** 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
CTRACE("free");
}
else
deventp);
}
}
void
CTRACE("destroy");
}
static void
CTRACE("shutdown");
}
void
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;
/*
* Reset any changes made by answering a query. XXXRTH Should this
* be in query.c? We'll free all but one namebuf.
*/
}
}
}
}
static void
CTRACE("senddone");
/*
* If all of its sendbufs buffers were busy, the client might be
* waiting for one to become available.
*/
return;
}
/* XXXRTH need to add exit draining mode. */
}
void
unsigned char *data;
isc_region_t r;
CTRACE("send");
CTRACE("no buffers available");
/*
* We couldn't get memory, but there is at least one
* send outstanding. We arrange to be restarted when a
* send completes.
*/
CTRACE("waiting");
} else
return;
}
/*
* XXXRTH The following doesn't deal with truncation, TSIGs,
* or ENDS1 more data packets.
*/
if (result != ISC_R_SUCCESS)
goto done;
DNS_SECTION_QUESTION, 0, 0);
if (result != ISC_R_SUCCESS)
goto done;
DNS_SECTION_ANSWER, 0, 0);
if (result != ISC_R_SUCCESS)
goto done;
DNS_SECTION_AUTHORITY, 0, 0);
if (result != ISC_R_SUCCESS)
goto done;
DNS_SECTION_ADDITIONAL, 0, 0);
goto done;
if (result != ISC_R_SUCCESS)
goto done;
isc_buffer_used(&buffer, &r);
/*
* XXXRTH this only works for UDP clients.
*/
CTRACE("sendto");
if (result == ISC_R_SUCCESS)
done:
if (result != ISC_R_SUCCESS)
}
void
CTRACE("error");
/*
* client->message may be an in-progress reply that we had trouble
* with, in which case QR will be set. We need to clear QR before
* calling dns_message_reply() to avoid triggering an assertion.
*/
if (result != ISC_R_SUCCESS) {
return;
}
}
static void
CTRACE("recv");
return;
}
if (result != ISC_R_SUCCESS) {
return;
}
/* XXXRTH Find view here. */
/*
* Dispatch the request.
*/
case dns_opcode_query:
CTRACE("query");
break;
case dns_opcode_iquery:
CTRACE("iquery");
default:
CTRACE("unknown opcode");
}
}
static void
CTRACE("timeout");
}
if (result != ISC_R_SUCCESS)
return (result);
return (ISC_R_SUCCESS);
}
static isc_result_t
{
/*
* 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.
*/
return (ISC_R_NOMEMORY);
if (result != ISC_R_SUCCESS)
goto cleanup_client;
if (result != ISC_R_SUCCESS)
goto cleanup_task;
if (result != ISC_R_SUCCESS)
goto cleanup_task;
if (result != ISC_R_SUCCESS)
goto cleanup_timer;
/* XXXRTH Hardwired constants */
if (result != ISC_R_SUCCESS)
goto cleanup_message;
/*
* We do the rest of the initialization here because the
* ns_client_newnamebuf() call below REQUIREs a valid client.
*/
client->attributes = 0;
if (result != ISC_R_SUCCESS)
goto cleanup_sendbufs;
CTRACE("create");
return (ISC_R_SUCCESS);
return (result);
}
/***
*** Client Manager
***/
static void
MTRACE("clientmgr_destroy");
}
{
return (ISC_R_NOMEMORY);
if (result != ISC_R_SUCCESS)
goto cleanup_manager;
MTRACE("create");
return (ISC_R_SUCCESS);
return (result);
}
void
MTRACE("destroy");
if (need_destroy)
}
unsigned int n,
{
unsigned int i;
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.
*/
for (i = 0; i < n; i++) {
if (result != ISC_R_SUCCESS)
break;
if (result != ISC_R_SUCCESS) {
break;
}
}
if (i != 0) {
/*
* We managed to create at least one client, so we
* declare victory.
*/
}
return (result);
}