예제 #1
0
void
ns_lwdclient_send(isc_task_t *task, isc_event_t *ev) {
    ns_lwdclient_t *client = ev->ev_arg;
    ns_lwdclientmgr_t *cm = client->clientmgr;
    isc_socketevent_t *dev = (isc_socketevent_t *)ev;

    UNUSED(task);
    UNUSED(dev);

    INSIST(NS_LWDCLIENT_ISSEND(client));
    INSIST(client->sendbuf == dev->region.base);

    ns_lwdclient_log(50, "task %p for client %p got send-done event",
                     task, client);

    if (client->sendbuf != client->buffer)
        lwres_context_freemem(cm->lwctx, client->sendbuf,
                              client->sendlength);
    client->sendbuf = NULL;
    client->sendlength = 0;

    ns_lwdclient_stateidle(client);

    isc_event_free(&ev);
}
예제 #2
0
void
ns_lwdclient_recv(isc_task_t *task, isc_event_t *ev) {
	isc_result_t result;
	ns_lwdclient_t *client = ev->ev_arg;
	ns_lwdclientmgr_t *cm = client->clientmgr;
	isc_socketevent_t *dev = (isc_socketevent_t *)ev;

	INSIST(dev->region.base == client->buffer);
	INSIST(NS_LWDCLIENT_ISRECV(client));

	NS_LWDCLIENT_SETRECVDONE(client);

	LOCK(&cm->lock);
	INSIST((cm->flags & NS_LWDCLIENTMGR_FLAGRECVPENDING) != 0);
	cm->flags &= ~NS_LWDCLIENTMGR_FLAGRECVPENDING;
	UNLOCK(&cm->lock);

	ns_lwdclient_log(50,
			 "event received: task %p, length %u, result %u (%s)",
			 task, dev->n, dev->result,
			 isc_result_totext(dev->result));

	if (dev->result != ISC_R_SUCCESS) {
		isc_event_free(&ev);
		dev = NULL;

		/*
		 * Go idle.
		 */
		ns_lwdclient_stateidle(client);

		return;
	}

	client->recvlength = dev->n;
	client->address = dev->address;
	if ((dev->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
		client->pktinfo = dev->pktinfo;
		client->pktinfo_valid = ISC_TRUE;
	} else
		client->pktinfo_valid = ISC_FALSE;
	isc_event_free(&ev);
	dev = NULL;

	result = ns_lwdclient_startrecv(cm);
	if (result != ISC_R_SUCCESS)
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_LWRESD, ISC_LOG_ERROR,
			      "could not start lwres "
			      "client handler: %s",
			      isc_result_totext(result));

	process_request(client);
}
/*%
 * Generate an error packet for the client, schedule a send, and put us in
 * the SEND state.
 *
 * The client->pkt structure will be modified to form an error return.
 * The receiver needs to verify that it is in fact an error, and do the
 * right thing with it.  The opcode will be unchanged.  The result needs
 * to be set before calling this function.
 *
 * The only change this code makes is to set the receive buffer size to the
 * size we use, set the reply bit, and recompute any security information.
 */
void
ns_lwdclient_errorpktsend(ns_lwdclient_t *client, isc_uint32_t _result) {
	isc_result_t result;
	int lwres;
	isc_region_t r;
	lwres_buffer_t b;

	REQUIRE(NS_LWDCLIENT_ISRUNNING(client));

	/*
	 * Since we are only sending the packet header, we can safely toss
	 * the receive buffer.  This means we won't need to allocate space
	 * for sending an error reply.  This is a Good Thing.
	 */
	client->pkt.length = LWRES_LWPACKET_LENGTH;
	client->pkt.pktflags |= LWRES_LWPACKETFLAG_RESPONSE;
	client->pkt.recvlength = LWRES_RECVLENGTH;
	client->pkt.authtype = 0; /* XXXMLG */
	client->pkt.authlength = 0;
	client->pkt.result = _result;

	lwres_buffer_init(&b, client->buffer, LWRES_RECVLENGTH);
	lwres = lwres_lwpacket_renderheader(&b, &client->pkt);
	if (lwres != LWRES_R_SUCCESS) {
		ns_lwdclient_stateidle(client);
		return;
	}

	r.base = client->buffer;
	r.length = b.used;
	client->sendbuf = client->buffer;
	result = ns_lwdclient_sendreply(client, &r);
	if (result != ISC_R_SUCCESS) {
		ns_lwdclient_stateidle(client);
		return;
	}

	NS_LWDCLIENT_SETSEND(client);
}
예제 #4
0
static void
process_request(ns_lwdclient_t *client) {
    lwres_buffer_t b;
    isc_result_t result;

    lwres_buffer_init(&b, client->buffer, client->recvlength);
    lwres_buffer_add(&b, client->recvlength);

    result = lwres_lwpacket_parseheader(&b, &client->pkt);
    if (result != ISC_R_SUCCESS) {
        ns_lwdclient_log(50, "invalid packet header received");
        goto restart;
    }

    ns_lwdclient_log(50, "opcode %08x", client->pkt.opcode);

    switch (client->pkt.opcode) {
    case LWRES_OPCODE_GETADDRSBYNAME:
        ns_lwdclient_processgabn(client, &b);
        return;
    case LWRES_OPCODE_GETNAMEBYADDR:
        ns_lwdclient_processgnba(client, &b);
        return;
    case LWRES_OPCODE_GETRDATABYNAME:
        ns_lwdclient_processgrbn(client, &b);
        return;
    case LWRES_OPCODE_NOOP:
        ns_lwdclient_processnoop(client, &b);
        return;
    default:
        ns_lwdclient_log(50, "unknown opcode %08x", client->pkt.opcode);
        goto restart;
    }

    /*
     * Drop the packet.
     */
restart:
    ns_lwdclient_log(50, "restarting client %p...", client);
    ns_lwdclient_stateidle(client);
}