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 #include "lwip/arch.h"
00025 #define ENSROK 0
00026
00027 static struct {
00028 unsigned short errno2, ares_errno;
00029 } ares_errno_trans[] = {
00030 {
00031 ENSROK, ARES_SUCCESS}, {
00032 ENSRNODATA, ARES_ENODATA}, {
00033 ENSRFORMERR, ARES_EFORMERR}, {
00034 ENSRSERVFAIL, ARES_ESERVFAIL}, {
00035 ENSRNOTFOUND, ARES_ENOTFOUND}, {
00036 ENSRNOTIMP, ARES_ENOTIMP}, {
00037 ENSRREFUSED, ARES_EREFUSED}, {
00038 ENSRBADQUERY, ARES_EBADQUERY}, {
00039 ENSRBADNAME, ARES_EBADNAME}, {
00040 ENSRBADFAMILY, ARES_EBADFAMILY}, {
00041 ENSRBADRESP, ARES_EBADRESP}, {
00042 ENSRCONNREFUSED, ARES_ECONNREFUSED}, {
00043 ENSRTIMEOUT, ARES_ETIMEOUT}, {
00044 ENSROF, ARES_EOF}, {
00045 ENSRFILE, ARES_EFILE}, {
00046 ENSRNOMEM, ARES_ENOMEM}, {
00047 ENSRDESTRUCTION, ARES_EDESTRUCTION}
00048 };
00049
00050 static int ares_error_to_errno (int e)
00051 {
00052 int i;
00053 for (i = 0; i < (sizeof(ares_errno_trans) / sizeof(ares_errno_trans[0])); i++)
00054 if (ares_errno_trans[i].ares_errno == e)
00055 return ares_errno_trans[i].errno2;
00056 rtl_printf ("no such ares error");
00057
00058 return -1;
00059 }
00060
00061 struct gethost_result {
00062 struct hostent host;
00063 int status;
00064 char *cname;
00065 };
00066
00067 #define array_dup(r,a,len_func) \
00068 do { \
00069 int __i; \
00070 for (__i = 0; (a)[__i]; __i++); \
00071 (r) = malloc ((__i + 1) * sizeof (char *)); \
00072 (r)[__i] = 0; \
00073 while (__i--) { \
00074 char *__p; \
00075 int __l; \
00076 __p = (a)[__i]; \
00077 __l = len_func; \
00078 (r)[__i] = memcpy ((char *) malloc (__l), __p, (__l)); \
00079 } \
00080 } while (0)
00081
00082 #define array_free(a) \
00083 do { \
00084 int __i; \
00085 for (__i = 0; (a)[__i]; __i++) \
00086 free ((a)[__i]); \
00087 free (a); \
00088 } while (0)
00089
00090
00091 static void callback (void *arg, int status, struct hostent *host)
00092 {
00093 struct gethost_result *r = (struct gethost_result *) arg;
00094
00095 if (host) {
00096 if (status == ARES_SUCCESS)
00097 if (r->cname)
00098 if (strcasecmp (r->cname, host->h_name)) {
00099 free (r->cname);
00100 r->cname = strdup (host->h_name);
00101 r->status = ARES_SUCCESS;
00102 return;
00103 }
00104
00105
00106 if (r->cname) {
00107 free (r->cname);
00108 r->cname = 0;
00109 }
00110
00111
00112 array_dup (r->host.h_aliases, host->h_aliases, strlen (__p) + 1);
00113
00114
00115 array_dup (r->host.h_addr_list, host->h_addr_list, host->h_length);
00116
00117
00118 r->host.h_name = (char *) strdup (host->h_name);
00119 r->host.h_addrtype = host->h_addrtype;
00120 r->host.h_length = host->h_length;
00121 }
00122
00123
00124 r->status = status;
00125 }
00126
00127 static struct in_addr __nameservers[2];
00128
00129 void setnameservers (const struct in_addr *ns1, const struct in_addr *ns2)
00130 {
00131 __nameservers[0].s_addr = ns1->s_addr;
00132 __nameservers[1].s_addr = ns2->s_addr;
00133 }
00134
00135 void getnameservers (struct in_addr *ns1, struct in_addr *ns2)
00136 {
00137 ns1->s_addr = __nameservers[0].s_addr;
00138 ns2->s_addr = __nameservers[1].s_addr;
00139 }
00140
00141 #ifndef DNS_MAXDOMAIN
00142 #define DNS_MAXDOMAIN 255
00143 #endif
00144
00145 static struct hostent *gethostbynameaddr (const char *name, struct in_addr addr, struct gethost_result *r)
00146 {
00147 char cname[DNS_MAXDOMAIN + 1];
00148 ares_channel channel;
00149 int status, nfds, cname_loops = 0;
00150 fd_set read_fds, write_fds;
00151 struct timeval *tvp, tv;
00152 struct ares_options o;
00153
00154 if (!__nameservers[0].s_addr) {
00155 rtl_printf ("The nameservers have not been set - use the setnameservers() function\n");
00156 errno = EINVAL;
00157 return NULL;
00158 }
00159
00160 o.servers = __nameservers;
00161 o.nservers = 1;
00162 if (__nameservers[1].s_addr)
00163 o.nservers++;
00164
00165 status = ares_init_options (&channel, &o, ARES_OPT_SERVERS);
00166 if (status != ARES_SUCCESS) {
00167 errno = ares_error_to_errno (status);
00168 return NULL;
00169 }
00170
00171 r->status = -1;
00172 if (r->cname)
00173 free (r->cname);
00174 r->cname = strdup (name);
00175 if (name) {
00176 if (strlen (name) > DNS_MAXDOMAIN) {
00177 ares_destroy (channel);
00178 errno = ENSRQUERYDOMAINTOOLONG;
00179 return NULL;
00180 }
00181 ares_gethostbyname (channel, name, AF_INET, callback, (void *) r);
00182 } else {
00183 ares_gethostbyaddr (channel, &addr, sizeof (addr), AF_INET, callback, (void *) r);
00184 }
00185
00186
00187 while (1) {
00188 FD_ZERO (&read_fds);
00189 FD_ZERO (&write_fds);
00190 nfds = ares_fds (channel, &read_fds, &write_fds);
00191 if (nfds == 0) {
00192 if (name && r->cname && r->status == ARES_SUCCESS) {
00193 if (++cname_loops > 10) {
00194 errno = ENSRCNAMELOOP;
00195 ares_destroy (channel);
00196 return NULL;
00197 }
00198 strncpy (cname, r->cname, DNS_MAXDOMAIN);
00199 cname[DNS_MAXDOMAIN] = '\0';
00200 name = cname;
00201 ares_gethostbyname (channel, name, AF_INET, callback, (void *) r);
00202 continue;
00203 }
00204 break;
00205 }
00206 tvp = ares_timeout (channel, NULL, &tv);
00207 select (nfds, &read_fds, &write_fds, NULL, tvp);
00208 ares_process (channel, &read_fds, &write_fds);
00209 }
00210
00211 ares_destroy (channel);
00212 if (r->status != ARES_SUCCESS || r->status == -1) {
00213 errno = r->status == -1 ? ARES_ENOTFOUND : ares_error_to_errno (r->status);
00214 return NULL;
00215 }
00216 return &r->host;
00217 }
00218
00219 struct hostent *gethostbyname (const char *name)
00220 {
00221 struct in_addr addr;
00222 static struct gethost_result r;
00223 static int init = 0;
00224 if (!init) {
00225 init = 1;
00226 memset (&r, 0, sizeof (r));
00227 }
00228 addr.s_addr = 0;
00229 if (r.host.h_aliases)
00230 array_free (r.host.h_aliases);
00231 if (r.host.h_addr_list)
00232 array_free (r.host.h_addr_list);
00233 if (r.host.h_name)
00234 free (r.host.h_name);
00235 return gethostbynameaddr (name, addr, &r);
00236 }
00237
00238 struct hostent *gethostbyaddr (const char *addr, int len, int type)
00239 {
00240 static struct gethost_result r;
00241 static int init = 0;
00242 if (!init) {
00243 init = 1;
00244 memset (&r, 0, sizeof (r));
00245 }
00246 if (len != sizeof (struct in_addr) || type != AF_INET) {
00247 errno = EINVAL;
00248 return 0;
00249 }
00250 if (r.host.h_aliases)
00251 array_free (r.host.h_aliases);
00252 if (r.host.h_addr_list)
00253 array_free (r.host.h_addr_list);
00254 if (r.host.h_name)
00255 free (r.host.h_name);
00256 return gethostbynameaddr (0, *((struct in_addr *) addr), &r);
00257 }
00258