summaryrefslogtreecommitdiffstats
path: root/rfc1035/rfc1035qptr.c
diff options
context:
space:
mode:
Diffstat (limited to 'rfc1035/rfc1035qptr.c')
-rw-r--r--rfc1035/rfc1035qptr.c149
1 files changed, 149 insertions, 0 deletions
diff --git a/rfc1035/rfc1035qptr.c b/rfc1035/rfc1035qptr.c
new file mode 100644
index 0000000..704d849
--- /dev/null
+++ b/rfc1035/rfc1035qptr.c
@@ -0,0 +1,149 @@
+/*
+** Copyright 1998 - 2011 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#include "rfc1035.h"
+#include <string.h>
+#include <errno.h>
+
+
+static int ptr(struct rfc1035_res *, const void *, int,
+ void (*)(const char *, void *),
+ void *);
+
+static void save_name(const char *name, void *void_arg)
+{
+ strcpy((char *)void_arg, name);
+}
+
+int rfc1035_ptr(struct rfc1035_res *res, const RFC1035_ADDR *addr,
+ char *name)
+{
+ return rfc1035_ptr_x(res, addr, save_name, name);
+}
+
+/* Convenient function to do reverse IP lookup */
+#if RFC1035_IPV6
+
+int rfc1035_ptr_x(struct rfc1035_res *res, const RFC1035_ADDR *addr,
+ void (*cb_func)(const char *, void *),
+ void *cb_arg)
+{
+struct in_addr in4;
+
+ if (IN6_IS_ADDR_V4MAPPED(addr))
+ {
+ rfc1035_ipv6to4(&in4, addr);
+ if (ptr(res, &in4, AF_INET, cb_func, cb_arg) == 0) return (0);
+ return (-1);
+ }
+ return (ptr(res, addr, AF_INET6, cb_func,cb_arg));
+}
+
+#else
+int rfc1035_ptr_x(struct rfc1035_res *res, const RFC1035_ADDR *a,
+ void (*cb_func)(const char *, void *),
+ void *cb_arg)
+{
+ return (ptr(res, a, AF_INET, cb_func, cb_arg));
+}
+#endif
+
+static int ptr(struct rfc1035_res *res, const void *addr, int af,
+ void (*cb_func)(const char *, void *),
+ void *cb_arg)
+{
+struct rfc1035_reply *reply;
+int n;
+char name[256], ptrbuf[256];
+
+#if RFC1035_IPV6
+
+ if (af == AF_INET6)
+ {
+ const char *sin6=(const char *)addr;
+ unsigned i;
+
+ *name=0;
+ for (i=sizeof(struct in6_addr); i; )
+ {
+ char buf[10];
+
+ --i;
+ sprintf(buf, "%x.%x.",
+ (int)(unsigned char)(sin6[i] & 0x0F),
+ (int)(unsigned char)((sin6[i] >> 4) & 0x0F));
+ strcat(name, buf);
+ }
+ strcat(name, "ip6.arpa");
+ }
+ else
+#endif
+ if (af != AF_INET)
+ {
+ errno=ENOENT;
+ return (-1); /* hard error */
+ }
+ else
+ {
+ const char *p;
+ unsigned char a=0,b=0,c=0,d=0;
+ struct in_addr ia;
+
+ memcpy(&ia, addr, sizeof(ia));
+ rfc1035_ntoa_ipv4(&ia, name);
+ p=name;
+
+ while (*p >= '0' && *p <= '9')
+ a= (int)a * 10 + (*p++ - '0');
+ if (*p) p++;
+ while (*p >= '0' && *p <= '9')
+ b= (int)b * 10 + (*p++ - '0');
+ if (*p) p++;
+ while (*p >= '0' && *p <= '9')
+ c= (int)c * 10 + (*p++ - '0');
+ if (*p) p++;
+ while (*p >= '0' && *p <= '9')
+ d= (int)d * 10 + (*p++ - '0');
+
+ sprintf(name, "%d.%d.%d.%d.in-addr.arpa",
+ (int)d, (int)c, (int)b, (int)a);
+ }
+
+ if (rfc1035_resolve_cname(res, name,
+ RFC1035_TYPE_PTR, RFC1035_CLASS_IN, &reply, 0) < 0 ||
+ reply == 0 ||
+ (n=rfc1035_replysearch_an( res, reply, name, RFC1035_TYPE_PTR,
+ RFC1035_CLASS_IN, 0)) < 0 ||
+ rfc1035_replyhostname(reply, reply->allrrs[n]->rr.domainname,
+ ptrbuf) == 0)
+ {
+ if (reply && reply->rcode != RFC1035_RCODE_NXDOMAIN &&
+ reply->rcode != RFC1035_RCODE_NOERROR)
+ {
+ rfc1035_replyfree(reply);
+ errno=EAGAIN;
+ return (-1);
+ }
+
+ if (reply) rfc1035_replyfree(reply);
+ errno=ENOENT;
+ return (-1); /* hard error */
+ }
+
+ (*cb_func)(ptrbuf, cb_arg);
+
+ while ((n=rfc1035_replysearch_an(res, reply, name,
+ RFC1035_TYPE_PTR,
+ RFC1035_CLASS_IN, n+1)) >= 0)
+ {
+ if (rfc1035_replyhostname(reply,
+ reply->allrrs[n]->rr.domainname,
+ ptrbuf))
+ (*cb_func)(ptrbuf, cb_arg);
+ }
+
+ rfc1035_replyfree(reply);
+ return (0);
+}