summaryrefslogtreecommitdiff
path: root/libc/inet/resolv.c
diff options
context:
space:
mode:
authorDavid McCullough <davidm@snapgear.com>2001-02-26 03:48:52 +0000
committerDavid McCullough <davidm@snapgear.com>2001-02-26 03:48:52 +0000
commite173fa9173faff66b26e348f6e2571b139d0eab3 (patch)
tree7b7cf89e5b166f29414b261756ff1c7d1b07e136 /libc/inet/resolv.c
parent62b59bd5ed8ff393c5f129dbd538966a2cfc0702 (diff)
Added /etc/hosts processing (parses everytime like a real one :-)
Added support for multiple nameserver lines, still supports multiple servers on a on single line. Added "domain" entry. domain and search are mutually exclusive and override each other (the last one wins, see the resolver(5) man page). Added dummy "getnetbyname" that returns fail. Added "res_init" and "res_query".
Diffstat (limited to 'libc/inet/resolv.c')
-rw-r--r--libc/inet/resolv.c261
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] = &in;
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] = &in;
+ 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
+
+