1 /*
2 ** Copyright 1998 - 2011 Double Precision, Inc.
3 ** See COPYING for distribution information.
4 */
5
6 #include "rfc1035.h"
7 #include <string.h>
8 #include <errno.h>
9
10
11 static int ptr(struct rfc1035_res *, const void *, int,
12 void (*)(const char *, void *),
13 void *);
14
save_name(const char * name,void * void_arg)15 static void save_name(const char *name, void *void_arg)
16 {
17 strcpy((char *)void_arg, name);
18 }
19
rfc1035_ptr(struct rfc1035_res * res,const RFC1035_ADDR * addr,char * name)20 int rfc1035_ptr(struct rfc1035_res *res, const RFC1035_ADDR *addr,
21 char *name)
22 {
23 return rfc1035_ptr_x(res, addr, save_name, name);
24 }
25
26 /* Convenient function to do reverse IP lookup */
27 #if RFC1035_IPV6
28
rfc1035_ptr_x(struct rfc1035_res * res,const RFC1035_ADDR * addr,void (* cb_func)(const char *,void *),void * cb_arg)29 int rfc1035_ptr_x(struct rfc1035_res *res, const RFC1035_ADDR *addr,
30 void (*cb_func)(const char *, void *),
31 void *cb_arg)
32 {
33 struct in_addr in4;
34
35 if (IN6_IS_ADDR_V4MAPPED(addr))
36 {
37 rfc1035_ipv6to4(&in4, addr);
38 if (ptr(res, &in4, AF_INET, cb_func, cb_arg) == 0) return (0);
39 return (-1);
40 }
41 return (ptr(res, addr, AF_INET6, cb_func,cb_arg));
42 }
43
44 #else
rfc1035_ptr_x(struct rfc1035_res * res,const RFC1035_ADDR * a,void (* cb_func)(const char *,void *),void * cb_arg)45 int rfc1035_ptr_x(struct rfc1035_res *res, const RFC1035_ADDR *a,
46 void (*cb_func)(const char *, void *),
47 void *cb_arg)
48 {
49 return (ptr(res, a, AF_INET, cb_func, cb_arg));
50 }
51 #endif
52
ptr(struct rfc1035_res * res,const void * addr,int af,void (* cb_func)(const char *,void *),void * cb_arg)53 static int ptr(struct rfc1035_res *res, const void *addr, int af,
54 void (*cb_func)(const char *, void *),
55 void *cb_arg)
56 {
57 struct rfc1035_reply *reply;
58 int n;
59 char name[256], ptrbuf[256];
60
61 #if RFC1035_IPV6
62
63 if (af == AF_INET6)
64 {
65 const char *sin6=(const char *)addr;
66 unsigned i;
67
68 *name=0;
69 for (i=sizeof(struct in6_addr); i; )
70 {
71 char buf[10];
72
73 --i;
74 sprintf(buf, "%x.%x.",
75 (int)(unsigned char)(sin6[i] & 0x0F),
76 (int)(unsigned char)((sin6[i] >> 4) & 0x0F));
77 strcat(name, buf);
78 }
79 strcat(name, "ip6.arpa");
80 }
81 else
82 #endif
83 if (af != AF_INET)
84 {
85 errno=ENOENT;
86 return (-1); /* hard error */
87 }
88 else
89 {
90 const char *p;
91 unsigned char a=0,b=0,c=0,d=0;
92 struct in_addr ia;
93
94 memcpy(&ia, addr, sizeof(ia));
95 rfc1035_ntoa_ipv4(&ia, name);
96 p=name;
97
98 while (*p >= '0' && *p <= '9')
99 a= (int)a * 10 + (*p++ - '0');
100 if (*p) p++;
101 while (*p >= '0' && *p <= '9')
102 b= (int)b * 10 + (*p++ - '0');
103 if (*p) p++;
104 while (*p >= '0' && *p <= '9')
105 c= (int)c * 10 + (*p++ - '0');
106 if (*p) p++;
107 while (*p >= '0' && *p <= '9')
108 d= (int)d * 10 + (*p++ - '0');
109
110 sprintf(name, "%d.%d.%d.%d.in-addr.arpa",
111 (int)d, (int)c, (int)b, (int)a);
112 }
113
114 if (rfc1035_resolve_cname(res, name,
115 RFC1035_TYPE_PTR, RFC1035_CLASS_IN, &reply, 0) < 0 ||
116 reply == 0 ||
117 (n=rfc1035_replysearch_an( res, reply, name, RFC1035_TYPE_PTR,
118 RFC1035_CLASS_IN, 0)) < 0 ||
119 rfc1035_replyhostname(reply, reply->allrrs[n]->rr.domainname,
120 ptrbuf) == 0)
121 {
122 if (reply && reply->rcode != RFC1035_RCODE_NXDOMAIN &&
123 reply->rcode != RFC1035_RCODE_NOERROR)
124 {
125 rfc1035_replyfree(reply);
126 errno=EAGAIN;
127 return (-1);
128 }
129
130 if (reply) rfc1035_replyfree(reply);
131 errno=ENOENT;
132 return (-1); /* hard error */
133 }
134
135 (*cb_func)(ptrbuf, cb_arg);
136
137 while ((n=rfc1035_replysearch_an(res, reply, name,
138 RFC1035_TYPE_PTR,
139 RFC1035_CLASS_IN, n+1)) >= 0)
140 {
141 if (rfc1035_replyhostname(reply,
142 reply->allrrs[n]->rr.domainname,
143 ptrbuf))
144 (*cb_func)(ptrbuf, cb_arg);
145 }
146
147 rfc1035_replyfree(reply);
148 return (0);
149 }
150