00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "ares_private.h"
00024
00025 #define htons HTONS
00026 #define htonl HTONL
00027
00028 extern int sprintf(char *str, const char *format, ...);
00029
00030 struct addr_query {
00031
00032 ares_channel channel;
00033 struct in_addr addr;
00034 ares_host_callback callback;
00035 void *arg;
00036
00037 const char *remaining_lookups;
00038 };
00039
00040 static void next_lookup(struct addr_query *aquery);
00041 static void addr_callback(void *arg, int status, unsigned char *abuf,
00042 int alen);
00043 static void end_aquery(struct addr_query *aquery, int status,
00044 struct hostent *host);
00045
00046 void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen,
00047 int family, ares_host_callback callback, void *arg)
00048 {
00049 struct addr_query *aquery;
00050
00051 if (family != AF_INET || addrlen != sizeof(struct in_addr))
00052 {
00053 callback(arg, ARES_ENOTIMP, NULL);
00054 return;
00055 }
00056
00057 aquery = malloc(sizeof(struct addr_query));
00058 if (!aquery)
00059 {
00060 callback(arg, ARES_ENOMEM, NULL);
00061 return;
00062 }
00063 aquery->channel = channel;
00064 memcpy(&aquery->addr, addr, sizeof(aquery->addr));
00065 aquery->callback = callback;
00066 aquery->arg = arg;
00067 aquery->remaining_lookups = channel->lookups;
00068
00069 next_lookup(aquery);
00070 }
00071
00072 static void next_lookup(struct addr_query *aquery)
00073 {
00074 const char *p;
00075 char name[64];
00076 int a1, a2, a3, a4;
00077 unsigned long addr;
00078
00079 for (p = aquery->remaining_lookups; *p; p++)
00080 {
00081 switch (*p)
00082 {
00083 case 'b':
00084 addr = ntohl(aquery->addr.s_addr);
00085 a1 = addr >> 24;
00086 a2 = (addr >> 16) & 0xff;
00087 a3 = (addr >> 8) & 0xff;
00088 a4 = addr & 0xff;
00089 sprintf(name, "%d.%d.%d.%d.in-addr.arpa", a4, a3, a2, a1);
00090 aquery->remaining_lookups = p + 1;
00091 ares_query(aquery->channel, name, C_IN, T_PTR, addr_callback,
00092 aquery);
00093 return;
00094 case 'f':
00095 break;
00096 }
00097 }
00098 end_aquery(aquery, ARES_ENOTFOUND, NULL);
00099 }
00100
00101 static void addr_callback(void *arg, int status, unsigned char *abuf, int alen)
00102 {
00103 struct addr_query *aquery = (struct addr_query *) arg;
00104 struct hostent *host;
00105
00106 if (status == ARES_SUCCESS)
00107 {
00108 status = ares_parse_ptr_reply(abuf, alen, &aquery->addr,
00109 sizeof(struct in_addr), AF_INET, &host);
00110 end_aquery(aquery, status, host);
00111 }
00112 else if (status == ARES_EDESTRUCTION)
00113 end_aquery(aquery, status, NULL);
00114 else
00115 next_lookup(aquery);
00116 }
00117
00118 static void end_aquery(struct addr_query *aquery, int status,
00119 struct hostent *host)
00120 {
00121 aquery->callback(aquery->arg, status, host);
00122 if (host)
00123 ares_free_hostent(host);
00124 free(aquery);
00125 }
00126