#include "config.h"
#include "ldapdns.h"
#include "ip.h"
#include "env.h"

static int udp53 = -1;
#ifdef HAVE_IPV6
static int using_6 = 0;
#endif

void tp_close(dns_ctx *c)
{
	/* we NEVER close the UDP connections */
}
void inline tp_housekeeping(long *now)
{
	/* there is no housekeeping for UDP */
}
void tp_initialize(void)
{
	char *x;
	char ip[IP_LEN];
	int port;

	x = env_get("IP");
	if (!x)
		x = "0.0.0.0";
	if (!ipv4_scan(x, ip)) {
#ifdef HAVE_IPV6
		if (ipv6_scan(x, ip))
			using_6 = 1;
		else
#endif
		fatal("cannot parse IP: %s", x);
	}

#ifdef HAVE_IPV6
	if (using_6)
		udp53 = socket_udp6();
	else
#endif
	udp53 = socket_udp4();
	if (udp53 == -1)
		cfatal("socket_udp4: %s");
	x = env_get("PORT");
	if (!x)
		port = 53;
	else {
		port = atoi(x);
		if (port < 1)
			fatal("cannot parse PORT: %s", x);
		if (port != 53)
			warning("running on non-standard port: %d", port);
	}

#ifdef HAVE_IPV6
	if (using_6) {
		if (socket_bind6_reuse(udp53, ip, port) == -1)
			cfatal("socket_bind4_reuse: %s");
	} else
#endif
	if (socket_bind4_reuse(udp53, ip, port) == -1)
		cfatal("socket_bind4_reuse: %s");

	ndelay_off(udp53);
	socket_tryreservein(udp53, 65536);

	/* we NEVER allow axfr over udp... */
	ldapdns.axfr_base = 0;
	/* or allow updates... */
	ldapdns.update = 0;
}
int inline tp_write(dns_ctx *c)
{
	if (clen(c->response) > 512)
		response_tc(c);
	/* if this were to fail, it would be because the kernel buffers
	 * cannot support a single UDP packet... in which case it's a kernel
	 * problem.
	 */
#ifdef HAVE_IPV6
	if (using_6)
		socket_send6(c->sock,
			caddr(c->response),
			clen(c->response),
			c->ip,
			c->port);
	else
#endif
	socket_send4(c->sock,
		caddr(c->response),
		clen(c->response),
		c->ip,
		c->port);
	return 1;
}
int inline tp_read(dns_ctx *c)
{
	int len;

	do {
#ifdef HAVE_IPV6
		if (using_6)
			len = socket_recv6(udp53,
					c->request_buf,
					512,
					c->ip,
					&c->port);
		else
#endif
		len = socket_recv4(udp53,
				c->request_buf,
				512,
				c->ip,
				&c->port);
		/* infinite if 0 hangs up */
		if (len == -1) {
			if (errno == EBADF || errno == EINVAL || errno == EFAULT)
				cfatal("read failed(%d): %s", udp53);
		}
	} while (len <= 0);
	if (len >= 512)
		return 0;

	/* never allow axfr over UDP */
	c->axfr_base = 0;
	c->update = 0;

	c->sock = udp53;
	c->request_pos = 0;
	c->request_len = len;
	return 1;
}



syntax highlighted by Code2HTML, v. 0.9.1