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