Exemple #1
0
static void
my_http_get(isc_task_t *task, isc_event_t *event) {
	isc_socket_t *sock;
	isc_socketevent_t *dev;

	sock = event->ev_sender;
	dev = (isc_socketevent_t *)event;

	printf("my_http_get: %s task %p\n\t(sock %p, base %p, length %d, "
	       "n %d, result %d)\n",
	       (char *)(event->ev_arg), task, sock,
	       dev->region.base, dev->region.length,
	       dev->n, dev->result);

	if (dev->result != ISC_R_SUCCESS) {
		isc_socket_detach(&sock);
		isc_task_shutdown(task);
		isc_event_free(&event);
		return;
	}

	isc_socket_recv(sock, &dev->region, 1, task, my_recv, event->ev_arg);

	isc_event_free(&event);
}
Exemple #2
0
static void
my_recv(isc_task_t *task, isc_event_t *event) {
	isc_socket_t *sock;
	isc_socketevent_t *dev;
	isc_region_t region;
	char buf[1024];
	char host[256];

	sock = event->ev_sender;
	dev = (isc_socketevent_t *)event;

	printf("Socket %s (sock %p, base %p, length %d, n %d, result %d)\n",
	       (char *)(event->ev_arg), sock,
	       dev->region.base, dev->region.length,
	       dev->n, dev->result);
	if (dev->address.type.sa.sa_family == AF_INET6) {
		inet_ntop(AF_INET6, &dev->address.type.sin6.sin6_addr,
			  host, sizeof(host));
		printf("\tFrom: %s port %d\n", host,
		       ntohs(dev->address.type.sin6.sin6_port));
	} else {
		inet_ntop(AF_INET, &dev->address.type.sin.sin_addr,
			  host, sizeof(host));
		printf("\tFrom: %s port %d\n", host,
		       ntohs(dev->address.type.sin.sin_port));
	}

	if (dev->result != ISC_R_SUCCESS) {
		isc_socket_detach(&sock);

		isc_mem_put(mctx, dev->region.base,
			    dev->region.length);
		isc_event_free(&event);

		isc_task_shutdown(task);
		return;
	}

	/*
	 * Echo the data back.
	 */
	if (strcmp(event->ev_arg, "so2") != 0) {
		region = dev->region;
		sprintf(buf, "\r\nReceived: %.*s\r\n\r\n",
			(int)dev->n, (char *)region.base);
		region.base = isc_mem_get(mctx, strlen(buf) + 1);
		region.length = strlen(buf) + 1;
		strcpy((char *)region.base, buf);  /* strcpy is safe */
		isc_socket_send(sock, &region, task, my_send, event->ev_arg);
	} else {
		region = dev->region;
		printf("\r\nReceived: %.*s\r\n\r\n",
		       (int)dev->n, (char *)region.base);
	}

	isc_socket_recv(sock, &dev->region, 1, task, my_recv, event->ev_arg);

	isc_event_free(&event);
}
static void
recv_length(isc_task_t *task, isc_event_t *ev_in) {
	isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
	isc_event_t *dev;
	dns_tcpmsg_t *tcpmsg = ev_in->ev_arg;
	isc_region_t region;
	isc_result_t result;

	INSIST(VALID_TCPMSG(tcpmsg));

	dev = &tcpmsg->event;
	tcpmsg->address = ev->address;

	if (ev->result != ISC_R_SUCCESS) {
		tcpmsg->result = ev->result;
		goto send_and_free;
	}

	/*
	 * Success.
	 */
	tcpmsg->size = ntohs(tcpmsg->size);
	if (tcpmsg->size == 0) {
		tcpmsg->result = ISC_R_UNEXPECTEDEND;
		goto send_and_free;
	}
	if (tcpmsg->size > tcpmsg->maxsize) {
		tcpmsg->result = ISC_R_RANGE;
		goto send_and_free;
	}

	region.base = isc_mem_get(tcpmsg->mctx, tcpmsg->size);
	region.length = tcpmsg->size;
	if (region.base == NULL) {
		tcpmsg->result = ISC_R_NOMEMORY;
		goto send_and_free;
	}
	XDEBUG(("Allocated %d bytes\n", tcpmsg->size));

	isc_buffer_init(&tcpmsg->buffer, region.base, region.length);
	result = isc_socket_recv(tcpmsg->sock, &region, 0,
				 task, recv_message, tcpmsg);
	if (result != ISC_R_SUCCESS) {
		tcpmsg->result = result;
		goto send_and_free;
	}

	isc_event_free(&ev_in);
	return;

 send_and_free:
	isc_task_send(tcpmsg->task, &dev);
	tcpmsg->task = NULL;
	isc_event_free(&ev_in);
	return;
}
Exemple #4
0
static void
recv_length(isc_task_t *task, isc_event_t *ev_in) {
	isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
	isc_event_t *dev;
	isccc_ccmsg_t *ccmsg = ev_in->ev_arg;
	isc_region_t region;
	isc_result_t result;

	INSIST(VALID_CCMSG(ccmsg));

	dev = &ccmsg->event;

	if (ev->result != ISC_R_SUCCESS) {
		ccmsg->result = ev->result;
		goto send_and_free;
	}

	/*
	 * Success.
	 */
	ccmsg->size = ntohl(ccmsg->size);
	if (ccmsg->size == 0) {
		ccmsg->result = ISC_R_UNEXPECTEDEND;
		goto send_and_free;
	}
	if (ccmsg->size > ccmsg->maxsize) {
		ccmsg->result = ISC_R_RANGE;
		goto send_and_free;
	}

	region.base = isc_mem_get(ccmsg->mctx, ccmsg->size);
	region.length = ccmsg->size;
	if (region.base == NULL) {
		ccmsg->result = ISC_R_NOMEMORY;
		goto send_and_free;
	}

	isc_buffer_init(&ccmsg->buffer, region.base, region.length);
	result = isc_socket_recv(ccmsg->sock, &region, 0,
				 task, recv_message, ccmsg);
	if (result != ISC_R_SUCCESS) {
		ccmsg->result = result;
		goto send_and_free;
	}

	isc_event_free(&ev_in);
	return;

 send_and_free:
	isc_task_send(ccmsg->task, &dev);
	ccmsg->task = NULL;
	isc_event_free(&ev_in);
	return;
}
Exemple #5
0
/*
 * This function will start a new recv() on a socket for this client manager.
 */
isc_result_t
ns_lwdclient_startrecv(ns_lwdclientmgr_t *cm) {
    ns_lwdclient_t *client;
    isc_result_t result;
    isc_region_t r;

    if (SHUTTINGDOWN(cm)) {
        lwdclientmgr_destroy(cm);
        return (ISC_R_SUCCESS);
    }

    /*
     * If a recv is already running, don't bother.
     */
    if ((cm->flags & NS_LWDCLIENTMGR_FLAGRECVPENDING) != 0)
        return (ISC_R_SUCCESS);

    /*
     * If we have no idle slots, just return success.
     */
    client = ISC_LIST_HEAD(cm->idle);
    if (client == NULL)
        return (ISC_R_SUCCESS);
    INSIST(NS_LWDCLIENT_ISIDLE(client));

    /*
     * Issue the recv.  If it fails, return that it did.
     */
    r.base = client->buffer;
    r.length = LWRES_RECVLENGTH;
    result = isc_socket_recv(cm->sock, &r, 0, cm->task, ns_lwdclient_recv,
                             client);
    if (result != ISC_R_SUCCESS)
        return (result);

    /*
     * Set the flag to say we've issued a recv() call.
     */
    cm->flags |= NS_LWDCLIENTMGR_FLAGRECVPENDING;

    /*
     * Remove the client from the idle list, and put it on the running
     * list.
     */
    NS_LWDCLIENT_SETRECV(client);
    ISC_LIST_UNLINK(cm->idle, client, link);
    ISC_LIST_APPEND(cm->running, client, link);

    return (ISC_R_SUCCESS);
}
Exemple #6
0
static void
my_listen(isc_task_t *task, isc_event_t *event) {
	char *name = event->ev_arg;
	isc_socket_newconnev_t *dev;
	isc_region_t region;
	isc_socket_t *oldsock;
	isc_task_t *newtask;

	dev = (isc_socket_newconnev_t *)event;

	printf("newcon %s (task %p, oldsock %p, newsock %p, result %d)\n",
	       name, task, event->ev_sender, dev->newsocket, dev->result);
	fflush(stdout);

	if (dev->result == ISC_R_SUCCESS) {
		/*
		 * Queue another listen on this socket.
		 */
		RUNTIME_CHECK(isc_socket_accept(event->ev_sender, task,
						my_listen, event->ev_arg)
			      == ISC_R_SUCCESS);

		region.base = isc_mem_get(mctx, 20);
		region.length = 20;

		/*
		 * Create a new task for this socket, and queue up a
		 * recv on it.
		 */
		newtask = NULL;
		RUNTIME_CHECK(isc_task_create(manager, 0, &newtask)
			      == ISC_R_SUCCESS);
		isc_socket_recv(dev->newsocket, &region, 1,
				newtask, my_recv, event->ev_arg);
		isc_task_detach(&newtask);
	} else {
		printf("detaching from socket %p\n", event->ev_sender);
		oldsock = event->ev_sender;

		isc_socket_detach(&oldsock);

		isc_event_free(&event);
		isc_task_shutdown(task);
		return;
	}

	isc_event_free(&event);
}
isc_result_t
dns_tcpmsg_readmessage(dns_tcpmsg_t *tcpmsg,
		       isc_task_t *task, isc_taskaction_t action, void *arg)
{
	isc_result_t result;
	isc_region_t region;

	REQUIRE(VALID_TCPMSG(tcpmsg));
	REQUIRE(task != NULL);
	REQUIRE(tcpmsg->task == NULL);  /* not currently in use */

	if (tcpmsg->buffer.base != NULL) {
		isc_mem_put(tcpmsg->mctx, tcpmsg->buffer.base,
			    tcpmsg->buffer.length);
		tcpmsg->buffer.base = NULL;
		tcpmsg->buffer.length = 0;
	}

	tcpmsg->task = task;
	tcpmsg->action = action;
	tcpmsg->arg = arg;
	tcpmsg->result = ISC_R_UNEXPECTED;  /* unknown right now */

	ISC_EVENT_INIT(&tcpmsg->event, sizeof(isc_event_t), 0, 0,
		       DNS_EVENT_TCPMSG, action, arg, tcpmsg,
		       NULL, NULL);

	region.base = (unsigned char *)&tcpmsg->size;
	region.length = 2;  /* isc_uint16_t */
	result = isc_socket_recv(tcpmsg->sock, &region, 0,
				 tcpmsg->task, recv_length, tcpmsg);

	if (result != ISC_R_SUCCESS)
		tcpmsg->task = NULL;

	return (result);
}
Exemple #8
0
isc_result_t
isccc_ccmsg_readmessage(isccc_ccmsg_t *ccmsg,
		       isc_task_t *task, isc_taskaction_t action, void *arg)
{
	isc_result_t result;
	isc_region_t region;

	REQUIRE(VALID_CCMSG(ccmsg));
	REQUIRE(task != NULL);
	REQUIRE(ccmsg->task == NULL);  /* not currently in use */

	if (ccmsg->buffer.base != NULL) {
		isc_mem_put(ccmsg->mctx, ccmsg->buffer.base,
			    ccmsg->buffer.length);
		ccmsg->buffer.base = NULL;
		ccmsg->buffer.length = 0;
	}

	ccmsg->task = task;
	ccmsg->action = action;
	ccmsg->arg = arg;
	ccmsg->result = ISC_R_UNEXPECTED;  /* unknown right now */

	ISC_EVENT_INIT(&ccmsg->event, sizeof(isc_event_t), 0, 0,
		       ISCCC_EVENT_CCMSG, action, arg, ccmsg,
		       NULL, NULL);

	region.base = (unsigned char *)&ccmsg->size;
	region.length = 4;  /* isc_uint32_t */
	result = isc_socket_recv(ccmsg->sock, &region, 0,
				 ccmsg->task, recv_length, ccmsg);

	if (result != ISC_R_SUCCESS)
		ccmsg->task = NULL;

	return (result);
}
Exemple #9
0
static void
isc_httpd_senddone(isc_task_t *task, isc_event_t *ev) {
	isc_httpd_t *httpd = ev->ev_arg;
	isc_region_t r;
	isc_socketevent_t *sev = (isc_socketevent_t *)ev;

	ENTER("senddone");
	INSIST(ISC_HTTPD_ISSEND(httpd));

	/*
	 * First, unlink our header buffer from the socket's bufflist.  This
	 * is sort of an evil hack, since we know our buffer will be there,
	 * and we know it's address, so we can just remove it directly.
	 */
	NOTICE("senddone unlinked header");
	ISC_LIST_UNLINK(sev->bufferlist, &httpd->headerbuffer, link);

	/*
	 * We will always want to clean up our receive buffer, even if we
	 * got an error on send or we are shutting down.
	 *
	 * We will pass in the buffer only if there is data in it.  If
	 * there is no data, we will pass in a NULL.
	 */
	if (httpd->freecb != NULL) {
		isc_buffer_t *b = NULL;
		if (isc_buffer_length(&httpd->bodybuffer) > 0)
			b = &httpd->bodybuffer;
		httpd->freecb(b, httpd->freecb_arg);
		NOTICE("senddone free callback performed");
	}
	if (ISC_LINK_LINKED(&httpd->bodybuffer, link)) {
		ISC_LIST_UNLINK(sev->bufferlist, &httpd->bodybuffer, link);
		NOTICE("senddone body buffer unlinked");
	}

	if (sev->result != ISC_R_SUCCESS) {
		destroy_client(&httpd);
		goto out;
	}

	if ((httpd->flags & HTTPD_CLOSE) != 0) {
		destroy_client(&httpd);
		goto out;
	}

	ISC_HTTPD_SETRECV(httpd);

	NOTICE("senddone restarting recv on socket");

	reset_client(httpd);

	r.base = (unsigned char *)httpd->recvbuf;
	r.length = HTTP_RECVLEN - 1;
	/* check return code? */
	(void)isc_socket_recv(httpd->sock, &r, 1, task,
			      isc_httpd_recvdone, httpd);

out:
	isc_event_free(&ev);
	EXIT("senddone");
}
Exemple #10
0
static void
isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) {
	isc_region_t r;
	isc_result_t result;
	isc_httpd_t *httpd = ev->ev_arg;
	isc_socketevent_t *sev = (isc_socketevent_t *)ev;
	isc_httpdurl_t *url;
	isc_time_t now;
	char datebuf[32];  /* Only need 30, but safety first */

	ENTER("recv");

	INSIST(ISC_HTTPD_ISRECV(httpd));

	if (sev->result != ISC_R_SUCCESS) {
		NOTICE("recv destroying client");
		destroy_client(&httpd);
		goto out;
	}

	result = process_request(httpd, sev->n);
	if (result == ISC_R_NOTFOUND) {
		if (httpd->recvlen >= HTTP_RECVLEN - 1) {
			destroy_client(&httpd);
			goto out;
		}
		r.base = (unsigned char *)httpd->recvbuf + httpd->recvlen;
		r.length = HTTP_RECVLEN - httpd->recvlen - 1;
		/* check return code? */
		(void)isc_socket_recv(httpd->sock, &r, 1, task,
				      isc_httpd_recvdone, httpd);
		goto out;
	} else if (result != ISC_R_SUCCESS) {
		destroy_client(&httpd);
		goto out;
	}

	ISC_HTTPD_SETSEND(httpd);

	/*
	 * XXXMLG Call function here.  Provide an add-header function
	 * which will append the common headers to a response we generate.
	 */
	isc_buffer_initnull(&httpd->bodybuffer);
	isc_time_now(&now);
	isc_time_formathttptimestamp(&now, datebuf, sizeof(datebuf));
	url = ISC_LIST_HEAD(httpd->mgr->urls);
	while (url != NULL) {
		if (strcmp(httpd->url, url->url) == 0)
			break;
		url = ISC_LIST_NEXT(url, link);
	}
	if (url == NULL)
		result = httpd->mgr->render_404(httpd->url, NULL,
						httpd->querystring,
						NULL, NULL,
						&httpd->retcode,
						&httpd->retmsg,
						&httpd->mimetype,
						&httpd->bodybuffer,
						&httpd->freecb,
						&httpd->freecb_arg);
	else
		result = url->action(httpd->url, url,
				     httpd->querystring,
				     httpd->headers,
				     url->action_arg,
				     &httpd->retcode, &httpd->retmsg,
				     &httpd->mimetype, &httpd->bodybuffer,
				     &httpd->freecb, &httpd->freecb_arg);
	if (result != ISC_R_SUCCESS) {
		result = httpd->mgr->render_500(httpd->url, url,
						httpd->querystring,
						NULL, NULL,
						&httpd->retcode,
						&httpd->retmsg,
						&httpd->mimetype,
						&httpd->bodybuffer,
						&httpd->freecb,
						&httpd->freecb_arg);
		RUNTIME_CHECK(result == ISC_R_SUCCESS);
	}

	isc_httpd_response(httpd);
	isc_httpd_addheader(httpd, "Content-Type", httpd->mimetype);
	isc_httpd_addheader(httpd, "Date", datebuf);
	isc_httpd_addheader(httpd, "Expires", datebuf);

	if (url != NULL && url->isstatic) {
		char loadbuf[32];
		isc_time_formathttptimestamp(&url->loadtime,
					     loadbuf, sizeof(loadbuf));
		isc_httpd_addheader(httpd, "Last-Modified", loadbuf);
		isc_httpd_addheader(httpd, "Cache-Control: public", NULL);
	} else {
	isc_httpd_addheader(httpd, "Last-Modified", datebuf);
	isc_httpd_addheader(httpd, "Pragma: no-cache", NULL);
	isc_httpd_addheader(httpd, "Cache-Control: no-cache", NULL);
	}

	isc_httpd_addheader(httpd, "Server: libisc", NULL);
	isc_httpd_addheaderuint(httpd, "Content-Length",
				isc_buffer_usedlength(&httpd->bodybuffer));
	isc_httpd_endheaders(httpd);  /* done */

	ISC_LIST_APPEND(httpd->bufflist, &httpd->headerbuffer, link);
	/*
	 * Link the data buffer into our send queue, should we have any data
	 * rendered into it.  If no data is present, we won't do anything
	 * with the buffer.
	 */
	if (isc_buffer_length(&httpd->bodybuffer) > 0)
		ISC_LIST_APPEND(httpd->bufflist, &httpd->bodybuffer, link);

	/* check return code? */
	(void)isc_socket_sendv(httpd->sock, &httpd->bufflist, task,
			       isc_httpd_senddone, httpd);

 out:
	isc_event_free(&ev);
	EXIT("recv");
}
Exemple #11
0
static void
isc_httpd_accept(isc_task_t *task, isc_event_t *ev) {
	isc_result_t result;
	isc_httpdmgr_t *httpdmgr = ev->ev_arg;
	isc_httpd_t *httpd;
	isc_region_t r;
	isc_socket_newconnev_t *nev = (isc_socket_newconnev_t *)ev;
	isc_sockaddr_t peeraddr;

	ENTER("accept");

	LOCK(&httpdmgr->lock);
	if (MSHUTTINGDOWN(httpdmgr)) {
		NOTICE("accept shutting down, goto out");
		goto out;
	}

	if (nev->result == ISC_R_CANCELED) {
		NOTICE("accept canceled, goto out");
		goto out;
	}

	if (nev->result != ISC_R_SUCCESS) {
		/* XXXMLG log failure */
		NOTICE("accept returned failure, goto requeue");
		goto requeue;
	}

	(void)isc_socket_getpeername(nev->newsocket, &peeraddr);
	if (httpdmgr->client_ok != NULL &&
	    !(httpdmgr->client_ok)(&peeraddr, httpdmgr->cb_arg)) {
		isc_socket_detach(&nev->newsocket);
		goto requeue;
	}

	httpd = isc_mem_get(httpdmgr->mctx, sizeof(isc_httpd_t));
	if (httpd == NULL) {
		/* XXXMLG log failure */
		NOTICE("accept failed to allocate memory, goto requeue");
		isc_socket_detach(&nev->newsocket);
		goto requeue;
	}

	httpd->mgr = httpdmgr;
	ISC_LINK_INIT(httpd, link);
	ISC_LIST_APPEND(httpdmgr->running, httpd, link);
	ISC_HTTPD_SETRECV(httpd);
	httpd->sock = nev->newsocket;
	isc_socket_setname(httpd->sock, "httpd", NULL);
	httpd->flags = 0;

	/*
	 * Initialize the buffer for our headers.
	 */
	httpd->headerdata = isc_mem_get(httpdmgr->mctx, HTTP_SENDGROW);
	if (httpd->headerdata == NULL) {
		isc_mem_put(httpdmgr->mctx, httpd, sizeof(isc_httpd_t));
		isc_socket_detach(&nev->newsocket);
		goto requeue;
	}
	httpd->headerlen = HTTP_SENDGROW;
	isc_buffer_init(&httpd->headerbuffer, httpd->headerdata,
			httpd->headerlen);

	ISC_LIST_INIT(httpd->bufflist);

	isc_buffer_initnull(&httpd->bodybuffer);
	reset_client(httpd);

	r.base = (unsigned char *)httpd->recvbuf;
	r.length = HTTP_RECVLEN - 1;
	result = isc_socket_recv(httpd->sock, &r, 1, task, isc_httpd_recvdone,
				 httpd);
	/* FIXME!!! */
	POST(result);
	NOTICE("accept queued recv on socket");

 requeue:
	result = isc_socket_accept(httpdmgr->sock, task, isc_httpd_accept,
				   httpdmgr);
	if (result != ISC_R_SUCCESS) {
		/* XXXMLG what to do?  Log failure... */
		NOTICE("accept could not reaccept due to failure");
	}

 out:
	UNLOCK(&httpdmgr->lock);

	httpdmgr_destroy(httpdmgr);

	isc_event_free(&ev);

	EXIT("accept");
}
Exemple #12
0
isc_result_t
ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
		       isc_socketmgr_t *socketmgr,
		       dns_dispatchmgr_t *dispatchmgr,
		       isc_task_t *task, ns_interfacemgr_t **mgrp)
{
	isc_result_t result;
	ns_interfacemgr_t *mgr;

#ifndef USE_ROUTE_SOCKET
	UNUSED(task);
#endif

	REQUIRE(mctx != NULL);
	REQUIRE(mgrp != NULL);
	REQUIRE(*mgrp == NULL);

	mgr = isc_mem_get(mctx, sizeof(*mgr));
	if (mgr == NULL)
		return (ISC_R_NOMEMORY);

	mgr->mctx = NULL;
	isc_mem_attach(mctx, &mgr->mctx);

	result = isc_mutex_init(&mgr->lock);
	if (result != ISC_R_SUCCESS)
		goto cleanup_mem;

	mgr->taskmgr = taskmgr;
	mgr->socketmgr = socketmgr;
	mgr->dispatchmgr = dispatchmgr;
	mgr->generation = 1;
	mgr->listenon4 = NULL;
	mgr->listenon6 = NULL;

	ISC_LIST_INIT(mgr->interfaces);
	ISC_LIST_INIT(mgr->listenon);

	/*
	 * The listen-on lists are initially empty.
	 */
	result = ns_listenlist_create(mctx, &mgr->listenon4);
	if (result != ISC_R_SUCCESS)
		goto cleanup_mem;
	ns_listenlist_attach(mgr->listenon4, &mgr->listenon6);

	result = dns_aclenv_init(mctx, &mgr->aclenv);
	if (result != ISC_R_SUCCESS)
		goto cleanup_listenon;
#ifdef HAVE_GEOIP
	mgr->aclenv.geoip = ns_g_geoip;
#endif

#ifdef USE_ROUTE_SOCKET
	mgr->route = NULL;
	result = isc_socket_create(mgr->socketmgr, ROUTE_SOCKET_PROTOCOL,
				   isc_sockettype_raw, &mgr->route);
	switch (result) {
	case ISC_R_NOPERM:
	case ISC_R_SUCCESS:
	case ISC_R_NOTIMPLEMENTED:
	case ISC_R_FAMILYNOSUPPORT:
	    break;
	default:
		goto cleanup_aclenv;
	}

	mgr->task = NULL;
	if (mgr->route != NULL)
		isc_task_attach(task, &mgr->task);
	mgr->references = (mgr->route != NULL) ? 2 : 1;
#else
	mgr->references = 1;
#endif
	mgr->magic = IFMGR_MAGIC;
	*mgrp = mgr;

#ifdef USE_ROUTE_SOCKET
	if (mgr->route != NULL) {
		isc_region_t r = { mgr->buf, sizeof(mgr->buf) };

		result = isc_socket_recv(mgr->route, &r, 1, mgr->task,
					 route_event, mgr);
		if (result != ISC_R_SUCCESS) {
			isc_task_detach(&mgr->task);
			isc_socket_detach(&mgr->route);
			ns_interfacemgr_detach(&mgr);
		}
	}
#endif
	return (ISC_R_SUCCESS);

#ifdef USE_ROUTE_SOCKET
 cleanup_aclenv:
	dns_aclenv_destroy(&mgr->aclenv);
#endif
 cleanup_listenon:
	ns_listenlist_detach(&mgr->listenon4);
	ns_listenlist_detach(&mgr->listenon6);
 cleanup_mem:
	isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
	return (result);
}
Exemple #13
0
static void
route_event(isc_task_t *task, isc_event_t *event) {
	isc_socketevent_t *sevent = NULL;
	ns_interfacemgr_t *mgr = NULL;
	isc_region_t r;
	isc_result_t result;
	struct MSGHDR *rtm;
	isc_boolean_t done = ISC_TRUE;

	UNUSED(task);

	REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
	mgr = event->ev_arg;
	sevent = (isc_socketevent_t *)event;

	if (sevent->result != ISC_R_SUCCESS) {
		if (sevent->result != ISC_R_CANCELED)
			isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
				      "automatic interface scanning "
				      "terminated: %s",
				      isc_result_totext(sevent->result));
		ns_interfacemgr_detach(&mgr);
		isc_event_free(&event);
		return;
	}

	rtm = (struct MSGHDR *)mgr->buf;
#ifdef RTM_VERSION
	if (rtm->rtm_version != RTM_VERSION) {
		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
			      "automatic interface rescanning disabled: "
			      "rtm->rtm_version mismatch (%u != %u) "
			      "recompile required", rtm->rtm_version,
			      RTM_VERSION);
		ns_interfacemgr_detach(&mgr);
		isc_event_free(&event);
		return;
	}
#endif

	switch (rtm->MSGTYPE) {
	case RTM_NEWADDR:
	case RTM_DELADDR:
		if (mgr->route != NULL && ns_g_server->interface_auto)
			ns_server_scan_interfaces(ns_g_server);
		break;
	default:
		break;
	}

	LOCK(&mgr->lock);
	if (mgr->route != NULL) {
		/*
		 * Look for next route event.
		 */
		r.base = mgr->buf;
		r.length = sizeof(mgr->buf);
		result = isc_socket_recv(mgr->route, &r, 1, mgr->task,
					 route_event, mgr);
		if (result == ISC_R_SUCCESS)
			done = ISC_FALSE;
	}
	UNLOCK(&mgr->lock);

	if (done)
		ns_interfacemgr_detach(&mgr);
	isc_event_free(&event);
	return;
}
Exemple #14
0
static void
buildquery(void) {
	isc_result_t result;
	dns_rdataset_t *question = NULL;
	dns_name_t *qname = NULL;
	isc_region_t r, inr;
	dns_message_t *query;
	char nametext[] = "host.example";
	isc_buffer_t namesrc, namedst;
	unsigned char namedata[256];
	isc_sockaddr_t sa;
	dns_compress_t cctx;

	query = NULL;
	result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
	CHECK("dns_message_create", result);
	result = dns_message_setsig0key(query, key);
	CHECK("dns_message_setsig0key", result);

	result = dns_message_gettemprdataset(query, &question);
	CHECK("dns_message_gettemprdataset", result);
	dns_rdataset_init(question);
	dns_rdataset_makequestion(question, dns_rdataclass_in,
				  dns_rdatatype_a);
	result = dns_message_gettempname(query, &qname);
	CHECK("dns_message_gettempname", result);
	isc_buffer_init(&namesrc, nametext, strlen(nametext));
	isc_buffer_add(&namesrc, strlen(nametext));
	isc_buffer_init(&namedst, namedata, sizeof(namedata));
	dns_name_init(qname, NULL);
	result = dns_name_fromtext(qname, &namesrc, dns_rootname, ISC_FALSE,
				   &namedst);
	CHECK("dns_name_fromtext", result);
	ISC_LIST_APPEND(qname->list, question, link);
	dns_message_addname(query, qname, DNS_SECTION_QUESTION);

	isc_buffer_init(&qbuffer, qdata, sizeof(qdata));

	result = dns_compress_init(&cctx, -1, mctx);
	CHECK("dns_compress_init", result);
	result = dns_message_renderbegin(query, &cctx, &qbuffer);
	CHECK("dns_message_renderbegin", result);
	result = dns_message_rendersection(query, DNS_SECTION_QUESTION, 0);
	CHECK("dns_message_rendersection(question)", result);
	result = dns_message_rendersection(query, DNS_SECTION_ANSWER, 0);
	CHECK("dns_message_rendersection(answer)", result);
	result = dns_message_rendersection(query, DNS_SECTION_AUTHORITY, 0);
	CHECK("dns_message_rendersection(auth)", result);
	result = dns_message_rendersection(query, DNS_SECTION_ADDITIONAL, 0);
	CHECK("dns_message_rendersection(add)", result);
	result = dns_message_renderend(query);
	CHECK("dns_message_renderend", result);
	dns_compress_invalidate(&cctx);

	isc_buffer_init(&outbuf, output, sizeof(output));
	result = dns_message_totext(query, style, 0, &outbuf);
	CHECK("dns_message_totext", result);
	printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
	       (char *)isc_buffer_base(&outbuf));

	isc_buffer_usedregion(&qbuffer, &r);
	isc_sockaddr_any(&sa);
	result = isc_socket_bind(s, &sa);
	CHECK("isc_socket_bind", result);
	result = isc_socket_sendto(s, &r, task1, senddone, NULL, &address,
				   NULL);
	CHECK("isc_socket_sendto", result);

	inr.base = rdata;
	inr.length = sizeof(rdata);
	result = isc_socket_recv(s, &inr, 1, task1, recvdone, NULL);
	CHECK("isc_socket_recv", result);
	dns_message_destroy(&query);
}
ATF_TC_BODY(udp_sendto, tc) {
	isc_result_t result;
	isc_sockaddr_t addr1, addr2;
	struct in_addr in;
	isc_socket_t *s1 = NULL, *s2 = NULL;
	isc_task_t *task = NULL;
	char sendbuf[BUFSIZ], recvbuf[BUFSIZ];
	completion_t completion;
	isc_region_t r;

	UNUSED(tc);

	result = isc_test_begin(NULL, ISC_TRUE);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	/*
	 * Create two sockets: 127.0.0.1/5444 and 127.0.0.1/5445, talking to
	 * each other.
	 */
	in.s_addr = inet_addr("127.0.0.1");
	isc_sockaddr_fromin(&addr1, &in, 5444);
	isc_sockaddr_fromin(&addr2, &in, 5445);

	result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s1);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
	result = isc_socket_bind(s1, &addr1, ISC_SOCKET_REUSEADDRESS);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s2);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
	result = isc_socket_bind(s2, &addr2, ISC_SOCKET_REUSEADDRESS);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	result = isc_task_create(taskmgr, 0, &task);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	strcpy(sendbuf, "Hello");
	r.base = (void *) sendbuf;
	r.length = strlen(sendbuf) + 1;

	completion_init(&completion);
	result = isc_socket_sendto(s1, &r, task, event_done, &completion,
				   &addr2, NULL);
	ATF_CHECK_EQ(result, ISC_R_SUCCESS);
	waitfor(&completion);
	ATF_CHECK(completion.done);
	ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);

	r.base = (void *) recvbuf;
	r.length = BUFSIZ;
	completion_init(&completion);
	result = isc_socket_recv(s2, &r, 1, task, event_done, &completion);
	ATF_CHECK_EQ(result, ISC_R_SUCCESS);
	waitfor(&completion);
	ATF_CHECK(completion.done);
	ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
	ATF_CHECK_STREQ(recvbuf, "Hello");

	isc_task_detach(&task);

	isc_socket_detach(&s1);
	isc_socket_detach(&s2);

	isc_test_end();
}
Exemple #16
0
/*
 * This function will start a new recv() on a socket for this client manager.
 */
isc_result_t
ns_lwdclient_startrecv(ns_lwdclientmgr_t *cm) {
	ns_lwdclient_t *client;
	isc_result_t result;
	isc_region_t r;
	isc_boolean_t destroy = ISC_FALSE;


	LOCK(&cm->lock);
	if (SHUTTINGDOWN(cm)) {
		destroy = ISC_TRUE;
		result = ISC_R_SUCCESS;
		goto unlock;
	}

	/*
	 * If a recv is already running, don't bother.
	 */
	if ((cm->flags & NS_LWDCLIENTMGR_FLAGRECVPENDING) != 0) {
		result = ISC_R_SUCCESS;
		goto unlock;
	}

	/*
	 * If we have no idle slots, just return success.
	 */
	client = ISC_LIST_HEAD(cm->idle);
	if (client == NULL) {
		result = ISC_R_SUCCESS;
		goto unlock;
	}

	INSIST(NS_LWDCLIENT_ISIDLE(client));

	/*
	 * Set the flag to say there is a recv pending.  If isc_socket_recv
	 * fails we will clear the flag otherwise it will be cleared by
	 * ns_lwdclient_recv.
	 */
	cm->flags |= NS_LWDCLIENTMGR_FLAGRECVPENDING;

	/*
	 * Issue the recv.  If it fails, return that it did.
	 */
	r.base = client->buffer;
	r.length = LWRES_RECVLENGTH;
	result = isc_socket_recv(cm->sock, &r, 0, cm->task, ns_lwdclient_recv,
				 client);
	if (result != ISC_R_SUCCESS) {
		cm->flags &= ~NS_LWDCLIENTMGR_FLAGRECVPENDING;
		goto unlock;
	}

	/*
	 * Remove the client from the idle list, and put it on the running
	 * list.
	 */
	NS_LWDCLIENT_SETRECV(client);
	ISC_LIST_UNLINK(cm->idle, client, link);
	ISC_LIST_APPEND(cm->running, client, link);

 unlock:
	UNLOCK(&cm->lock);

	if (destroy)
		lwdclientmgr_destroy(cm);

	return (result);
}