diff options
Diffstat (limited to 'rfc1035/rfc1035qptr.c')
| -rw-r--r-- | rfc1035/rfc1035qptr.c | 149 |
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); +} |
