Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

netdb.c

Go to the documentation of this file.
00001 /* Copyright 1998 by the Massachusetts Institute of Technology.
00002  *
00003  * Permission to use, copy, modify, and distribute this
00004  * software and its documentation for any purpose and without
00005  * fee is hereby granted, provided that the above copyright
00006  * notice appear in all copies and that both that copyright
00007  * notice and this permission notice appear in supporting
00008  * documentation, and that the name of M.I.T. not be used in
00009  * advertising or publicity pertaining to distribution of the
00010  * software without specific, written prior permission.
00011  * M.I.T. makes no representations about the suitability of
00012  * this software for any purpose.  It is provided "as is"
00013  * without express or implied warranty.
00014  *
00015  * CHANGELOG: this file has been modified by Sergio Perez Alcañiz <serpeal@disca.upv.es> 
00016  *            Departamento de Informática de Sistemas y Computadores          
00017  *            Universidad Politécnica de Valencia                             
00018  *            Valencia (Spain)    
00019  *            Date: April 2003                                          
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     //abort (); /* prevents warning */
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 /* copy the host entry */
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)       /* we got back a cname, so retry the query with the 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 /* clear any old cname */
00106         if (r->cname) {
00107             free (r->cname);
00108             r->cname = 0;
00109         }
00110 
00111 /* copy alias list */
00112         array_dup (r->host.h_aliases, host->h_aliases, strlen (__p) + 1);
00113 
00114 /* copy address list */
00115         array_dup (r->host.h_addr_list, host->h_addr_list, host->h_length);
00116 
00117 /* copy tidbits */
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 /* get status */
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     /* Wait for all queries to complete. */
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 

Generated on Wed Jan 14 12:58:56 2004 for RTL-lwIP-0.4 by doxygen 1.3.4