예제 #1
0
int tcp_response_recursive_process (Context *cont) {
	const char *fn = "tcp_response_recursive_process()";

	syslog (LOG_DEBUG, "%s: start", fn);

	switch (recursive_process (cont)) {
	case 0:
		syslog (LOG_DEBUG, "%s: return, continue", fn);

		/* SUCCESS */
		return 0;
	case 1:
		assemble_response (cont);

		if (cont->mesg_len < 0 || cont->mesg_len > MAX_STREAM) {
			syslog (LOG_WARNING, "response message too big");
			return (response_abort (cont, 1));
		}

		if (cont->tout)
			cont->tout->handler = NULL;

		if (context_timeout_register (cont, cont->timeout))
			return (response_abort (cont, -1));

		/* register output */
		if (ev_tcp_out_register (cont->conn_sock, cont))
			return (response_abort (cont, -1));

		/* change the state */
		cont->process = tcp_response_writing_process;
		cont->retry = tcp_response_writing_retry;
		cont->wp = NULL;

		syslog (LOG_DEBUG, "%s: return, finish", fn);

		/* SUCCESS */
		return 0;
	default:
		return (response_abort (cont, -1));
	}
}
int udp_response_finish (Context *cont) {
        const char *fn = "udp_response_finish()";
	int len;

	syslog (LOG_DEBUG, "%s: start", fn);

	/*
	 * We trim the response down if it doesn't fit in a default UDP
	 * data in a somewhat crude way. Could be smarter, like trim
	 * A records from response for pure IPv6 queries and so. See, if
	 * it is needed often. Maybe better to support EDNS0 option instead.
	 *
	 * RFC1035 says we should truncate the message to 512 bytes and set the
	 * tr bit in the header, but it is really vague on when a response does
	 * not fit. RFC2181 clarifies the use of the tr bit in section 9.
	 *
	 * Note that similar logic is still present in mesg_assemble() in
	 * ne_mesg.c (may disappear if we add the logic to assemble_response()
	 * instead).
	 */
	assemble_response (cont);
	if (cont->mesg_len < 0 || cont->mesg_len > MAX_PACKET) {
		/* put the message on a diet */
		list_destroy (cont->ar_list, rrset_freev);
		cont->ar_list = NULL;
		syslog (LOG_DEBUG, "Overweight, dropping additional section");
		assemble_response (cont);
	}
	if (cont->mesg_len < 0 || cont->mesg_len > MAX_PACKET) {
		/*
		 * ok, water adn bread then then. shuold check
		 * RFCs, it may be better to return error msg
		 * instead of slimmed answer.
		 */
		list_destroy (cont->ns_list, rrset_freev);
		cont->ns_list = NULL;
		syslog (LOG_DEBUG, "Overweight, dropping authority section");
		assemble_response (cont);
	}
	if (cont->mesg_len < 0 || cont->mesg_len > MAX_PACKET) {
		/* ok, nothing viable left, so die */
		list_destroy (cont->an_list, rrset_freev);
		cont->an_list = NULL;
		assemble_response (cont);
		cont->mesg.hdr->tc = 1;
		syslog (LOG_WARNING, "Obese, answers too big for UDP");
	}
	if (cont->mesg_len < 0 || cont->mesg_len > MAX_PACKET) {
		syslog (LOG_ERR, "Even error msg is too big for UDP");
		return (response_abort (cont, 1));
	}

	/* send the answer */
	len = net_mesg_send (cont->netifaddr, cont->mesg.p, cont->mesg_len,
			     cont->peer);

	if (len < cont->mesg_len) {
		syslog (LOG_NOTICE, "failed to send message.");
		return (response_abort (cont, -1));
	}

        context_destroy (cont);
	return 0;
}
예제 #3
0
int tcp_response_reading_process (Context *cont) {
	const char *fn = "tcp_response_reading_process()";
	int len;

	syslog (LOG_DEBUG, "%s: start", fn);

	if (cont->tout)
		cont->tout->handler = NULL;

	if (context_timeout_register (cont, cont->timeout))
		return(response_abort (cont, -1));

	len = read (cont->conn_sock, cont->wp,
		    cont->mesg_len - (cont->wp - cont->mesg.p));

	if (len <= 0)
		return(response_abort (cont, -1));

	cont->wp += len;
	if (cont->wp < (cont->mesg.p + cont->mesg_len)) {
		syslog (LOG_DEBUG, "%s: left %zd bytes -- continue.", fn,
			(cont->mesg.p + cont->mesg_len) - cont->wp);

		/* SUCCESS */
		return 0;	/* the processing continues ... */
	}

	/* all data has been read now */
	ev_tcp_conn_in_remove (cont->conn_sock);

	if (cont->mesg.hdr->opcode == OP_QUERY) {
		if (cont->tout)
			cont->tout->handler = NULL;

		/*
		 * don't register input list,
		 * child context takes input
		 */

		switch (request_start (cont, QUERY_TCP)) {
		case 0:
			/*
			 * We forwarded the request without problems,
			 * asycnhronously awaiting a response.
			 * goto recursive_processing state
			 * clear events, child will call me then
			 */
			if (cont->tout)
				cont->tout->handler = NULL;

			cont->process = tcp_response_recursive_process;
			cont->retry = tcp_response_recursive_retry;

			/* SUCCESS */
			return 0;
		case 1:
			/* Something wrong with the query */
			syslog (LOG_NOTICE, "%s: Request failed", fn);
			cont->mesg.hdr->rcode = RC_FMTERR;
		default:
			/* totd failed itself somehow */
			syslog (LOG_NOTICE, "%s: Totd failed", fn);
			cont->mesg.hdr->rcode = RC_SERVERERR;
		}
	} else
		cont->mesg.hdr->rcode = RC_NIMP;

	/* 
	 * Not OP_QUERY or Request failed brings us here
	 *
	 * Go to writing state. Timeout already done in this function
	 * Register new output event 
	 */

	if (!ev_tcp_out_register (cont->conn_sock, cont)) {
		assemble_response (cont);

		/* state change */
		cont->process = tcp_response_writing_process;
		cont->retry = tcp_response_writing_retry;
		cont->wp = NULL;

		syslog (LOG_DEBUG, "%s: end (writing:)", fn);
		/* SUCCESS */
		return 0;
	}

	/* FAILURE */
	return (response_abort (cont, -1));
}