diff options
Diffstat (limited to 'libc/inet/resolv.c')
-rw-r--r-- | libc/inet/resolv.c | 261 |
1 files changed, 230 insertions, 31 deletions
diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index 38aa9b272..d02d29fbc 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -49,6 +49,7 @@ #include <cfgfile.h> #include <resolv.h> #include <netdb.h> +#include <ctype.h> #include <arpa/nameser.h> #define MAX_RECURSE 5 @@ -59,16 +60,20 @@ #undef DEBUG #ifdef DEBUG -static inline void DPRINTF(const char *format, ...) -{ - va_list args; - va_start(args, format); - vfprintf(stderr, format, args); - va_end(args); -} +#define DPRINTF(X,args...) fprintf(stderr, X, ##args) #else -static inline void DPRINTF(const char *format, ...) { } -#endif +#define DPRINTF(X,args...) +#endif /* DEBUG */ + + +extern int nameservers; +extern const char * nameserver[MAX_SERVERS]; +extern int searchdomains; +extern const char * searchdomain[MAX_SEARCH]; +extern struct hostent * get_hosts_byname(const char * name); +extern struct hostent * get_hosts_byaddr(const char * addr, int len, int type); +extern struct hostent * read_etc_hosts(const char * name, int ip); + #ifdef L_encodeh int encode_header(struct resolv_header *h, unsigned char *dest, int maxlen) @@ -461,8 +466,6 @@ int dns_lookup(const char *name, int type, int nscount, const char **nsip, unsigned char * packet = malloc(PACKETSZ); unsigned char * lookup = malloc(MAXDNAME); int variant = 0; - extern int searchdomains; - extern const char * searchdomain[MAX_SEARCH]; fd = -1; @@ -753,10 +756,6 @@ int resolve_mailbox(const char *address, } #endif -extern int nameservers; -extern const char * nameserver[MAX_SERVERS]; -extern int searchdomains; -extern const char * searchdomain[MAX_SEARCH]; #ifdef L_opennameservers @@ -765,26 +764,57 @@ const char * nameserver[MAX_SERVERS]; int searchdomains; const char * searchdomain[MAX_SEARCH]; +/* + * we currently read formats not quite the same as that on normal + * unix systems, we can have a list of nameservers after the keyword. + */ + int open_nameservers() { FILE *fp; - char **arg; int i; +#define RESOLV_ARGS 5 + char szBuffer[128], *p, *argv[RESOLV_ARGS]; + int argc; if (nameservers > 0) return 0; - if ((fp = fopen("/etc/resolv.conf", "r"))) { - if (0 != (arg = cfgfind(fp, "nameserver"))) { - for (i=1; arg[i] && nameservers <= MAX_SERVERS; i++) { - nameserver[nameservers++] = strdup(arg[i]); - DPRINTF("adding nameserver %s\n",arg[i]); + if ((fp = fopen("/etc/resolv.conf", "r")) || + (fp = fopen("/etc/config/resolv.conf", "r"))) { + + while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) { + + for (p = szBuffer; *p && isspace(*p); p++) + /* skip white space */; + if (*p == '\0' || *p == '\n' || *p == '#') /* skip comments etc */ + continue; + argc = 0; + while (*p && argc < RESOLV_ARGS) { + argv[argc++] = p; + while (*p && !isspace(*p) && *p != '\n') + p++; + while (*p && (isspace(*p) || *p == '\n')) /* remove spaces */ + *p++ = '\0'; + } + + if (strcmp(argv[0], "nameserver") == 0) { + for (i = 1; i < argc && nameservers < MAX_SERVERS; i++) { + nameserver[nameservers++] = strdup(argv[i]); + DPRINTF("adding nameserver %s\n", argv[i]); + } } - } - if (0 != (arg = cfgfind(fp, "search"))) { - for (i=1; arg[i] && searchdomains <= MAX_SEARCH; i++) { - searchdomain[searchdomains++] = strdup(arg[i]); - DPRINTF("adding search %s\n",arg[i]); + + /* domain and search are mutually exclusive, the last one wins */ + if (strcmp(argv[0],"domain")==0 || strcmp(argv[0],"search")==0) { + while (searchdomains > 0) { + free(searchdomain[--searchdomains]); + searchdomain[searchdomains] = NULL; + } + for (i=1; i < argc && searchdomains < MAX_SEARCH; i++) { + searchdomain[searchdomains++] = strdup(argv[i]); + DPRINTF("adding search %s\n", argv[i]); + } } } fclose(fp); @@ -796,12 +826,19 @@ int open_nameservers() } #endif + #ifdef L_closenameservers + void close_nameservers(void) { - - while (nameservers > 0) - free((void*)nameserver[--nameservers]); + while (nameservers > 0) { + free(nameserver[--nameservers]); + nameserver[nameservers] = NULL; + } + while (searchdomains > 0) { + free(searchdomain[--searchdomains]); + searchdomain[searchdomains] = NULL; + } } #endif @@ -836,6 +873,7 @@ const char *resolve_name(const char *name, int mailbox) } #endif + #ifdef L_gethostbyname struct hostent *gethostbyname(const char *name) @@ -844,6 +882,7 @@ struct hostent *gethostbyname(const char *name) static char namebuf[256]; static struct in_addr in; static struct in_addr *addr_list[2]; + struct hostent *hp; unsigned char *packet; struct resolv_answer a; int i; @@ -853,13 +892,16 @@ struct hostent *gethostbyname(const char *name) if (!name) return 0; - + + if ((hp = get_hosts_byname(name))) /* do /etc/hosts first */ + return(hp); + memset(&h, 0, sizeof(h)); addr_list[0] = ∈ addr_list[1] = 0; - strcpy(namebuf, name); + strncpy(namebuf, name, sizeof(namebuf)); /* First check if this is already an address */ if (inet_aton(name, &in)) { @@ -909,6 +951,66 @@ struct hostent *gethostbyname(const char *name) } #endif + +#ifdef L_getnetbyname + +struct netent * getnetbyname(const char * name) +{ + return NULL; +} +#endif + + +#ifdef L_res_init + +int res_init() +{ + return(0); +} +#endif + + +#ifdef L_res_query + +#ifndef MIN +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#endif + +int res_query(const char *dname, int class, int type, + unsigned char *answer, int anslen) +{ + unsigned char * packet = 0; + struct resolv_answer a; + int i; + + open_nameservers(); + + if (!dname || class != 1 /* CLASS_IN */) + return(-1); + + memset((char *) &a, '\0', sizeof(a)); + + i = dns_lookup(dname, type, nameservers, nameserver, &packet, &a); + + if (i < 0) + return(-1); + + free(a.dotted); + + if (a.atype == type) { /* CNAME*/ + if (anslen && answer) + memcpy(answer, a.rdata, MIN(anslen, a.rdlength)); + if (packet) + free(packet); + return(MIN(anslen, a.rdlength)); + } + if (packet) + free(packet); + return 0; +} +#endif + + #ifdef L_gethostbyaddr struct hostent *gethostbyaddr(const char *addr, int len, int type) @@ -917,6 +1019,7 @@ struct hostent *gethostbyaddr(const char *addr, int len, int type) static char namebuf[256]; static struct in_addr in; static struct in_addr *addr_list[2]; + struct hostent *hp; unsigned char *packet; struct resolv_answer a; int i; @@ -925,6 +1028,9 @@ struct hostent *gethostbyaddr(const char *addr, int len, int type) if (!addr || (len != sizeof(in)) || (type != AF_INET)) return 0; + if ((hp = get_hosts_byaddr(addr, len, type))) /* do /etc/hosts first */ + return(hp); + memcpy(&in.s_addr, addr, len); open_nameservers(); @@ -978,3 +1084,96 @@ struct hostent *gethostbyaddr(const char *addr, int len, int type) return &h; } #endif + + +#ifdef L_read_etc_hosts + +struct hostent * read_etc_hosts(const char * name, int ip) +{ + static struct hostent h; + static struct in_addr in; + static struct in_addr *addr_list[2]; + static char line[80]; + FILE *fp; + char *cp; +#define MAX_ALIAS 5 + char *alias[MAX_ALIAS]; + int aliases, i; + + if ((fp = fopen("/etc/hosts", "r")) == NULL && + (fp = fopen("/etc/config/hosts", "r")) == NULL) + return((struct hostent *) NULL); + + while (fgets(line, sizeof(line), fp)) { + if ((cp = strchr(line, '#'))) + *cp = '\0'; + aliases = 0; + + cp = line; + while (*cp) { + while (*cp && isspace(*cp)) + *cp++ = '\0'; + if (!*cp) + continue; + if (aliases < MAX_ALIAS) + alias[aliases++] = cp; + while (*cp && !isspace(*cp)) + cp++; + } + + if (aliases < 2) + continue; /* syntax error really */ + + if (ip) { + if (strcmp(name, alias[0]) != 0) + continue; + } else { + for (i = 1; i < aliases; i++) + if (strcasecmp(name, alias[i]) == 0) + break; + if (i >= aliases) + continue; + } + + if (inet_aton(alias[0], &in) == 0) + break; /* bad ip address */ + + addr_list[0] = ∈ + addr_list[1] = 0; + h.h_name = alias[1]; + h.h_addrtype = AF_INET; + h.h_length = sizeof(in); + h.h_addr_list = (char**) addr_list; + fclose(fp); + return(&h); + } + fclose(fp); + return((struct hostent *) NULL); +} +#endif + + +#ifdef L_get_hosts_byname + +struct hostent * get_hosts_byname(const char * name) +{ + return(read_etc_hosts(name, 0)); +} +#endif + + +#ifdef L_get_hosts_byaddr + +struct hostent * get_hosts_byaddr(const char * addr, int len, int type) +{ + char ipaddr[20]; + + if (type != AF_INET || len != sizeof(struct in_addr)) + return((struct hostent *) NULL); + + strcpy(ipaddr, inet_ntoa(* (struct in_addr *) addr)); + return(read_etc_hosts(ipaddr, 1)); +} +#endif + + |