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); }
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); }
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); }