1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
/*
** Copyright 1998 - 2002 Double Precision, Inc.
** See COPYING for distribution information.
*/
#include "rfc1035.h"
#include <string.h>
#include <errno.h>
#include "rfc1035_res.h"
static const char rcsid[]="$Id: rfc1035qptr.c,v 1.10 2005/06/24 17:47:33 mrsam Exp $";
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, RFC1035_RESOLVE_RECURSIVE, 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);
}
|