summaryrefslogtreecommitdiffstats
path: root/isys
diff options
context:
space:
mode:
authorDavid Cantrell <dcantrell@redhat.com>2006-11-02 02:20:24 +0000
committerDavid Cantrell <dcantrell@redhat.com>2006-11-02 02:20:24 +0000
commitc89579246f19348d5921e6148b235bf840b24f88 (patch)
treeae6e06ac2a1b98d7e911e5c8ed4a7013fcbaf245 /isys
parentbf05f4da7b9d4e83095a633eef2ef759ded9499b (diff)
downloadanaconda-c89579246f19348d5921e6148b235bf840b24f88.tar.gz
anaconda-c89579246f19348d5921e6148b235bf840b24f88.tar.xz
anaconda-c89579246f19348d5921e6148b235bf840b24f88.zip
Added IPv6 DNS lookup support to libisys.
Diffstat (limited to 'isys')
-rw-r--r--isys/dns.c171
-rw-r--r--isys/dns.h4
-rw-r--r--isys/nfsmount.c4
3 files changed, 136 insertions, 43 deletions
diff --git a/isys/dns.c b/isys/dns.c
index 1a24069f0..7ccaf5321 100644
--- a/isys/dns.c
+++ b/isys/dns.c
@@ -7,15 +7,22 @@
#include <stdlib.h>
#include <string.h>
+#include "dns.h"
+
/* This is dumb, but glibc doesn't like to do hostname lookups w/o libc.so */
+/*
+ * IPv6 DNS extensions documented here:
+ * http://tools.ietf.org/html/rfc3596
+ */
+
union dns_response{
HEADER hdr;
u_char buf[PACKETSZ];
};
static int doQuery(char * query, int queryType,
- char ** domainName, struct in_addr * ipNum) {
+ char ** domainName, void * ipNum, int family) {
int len, ancount, type;
u_char * data, * end;
char name[MAXDNAME];
@@ -94,14 +101,22 @@ static int doQuery(char * query, int queryType,
return 0;
}
} else if (type == T_A) {
- /* we got an address */
+ /* we have an IPv4 address */
if (queryType == T_A && ipNum) {
- /* we wanted an address */
- memcpy(ipNum, data, sizeof(*ipNum));
- if (response != &static_response) free(response);
+ memcpy(ipNum, data, sizeof(struct in_addr));
+ if (response != &static_response)
+ free(response);
return 0;
}
- }
+ } else if (type == T_AAAA) {
+ /* we have an IPv6 address */
+ if (queryType == T_AAAA && ipNum) {
+ memcpy(ipNum, data, sizeof(struct in6_addr));
+ if (response != &static_response)
+ free(response);
+ return 0;
+ }
+ }
/* move ahead to next RR */
data += len;
@@ -111,58 +126,136 @@ static int doQuery(char * query, int queryType,
return -1;
}
-char * mygethostbyaddr(char * ipnum) {
- int rc;
- char * result;
- char * strbuf;
- char * chptr;
- char * splits[4];
- int i;
+char * mygethostbyaddr(char * ipnum, int family) {
+ int i, j, ret;
+ char *buf = NULL;
+ char sbuf[5];
+ char *result = NULL;
+ char *octets[4];
+ char *octet = NULL;
+ char *parts[8];
+ char *partptr = NULL;
+ struct in6_addr addr6;
_res.retry = 1;
- strbuf = alloca(strlen(ipnum) + 1);
- strcpy(strbuf, ipnum);
+ if (ipnum == NULL || (family != AF_INET && family != AF_INET6))
+ return NULL;
- ipnum = alloca(strlen(strbuf) + 20);
+ if (family == AF_INET) {
+ buf = strdup(ipnum);
+ octet = strtok(buf, ".");
- for (i = 0; i < 4; i++) {
- chptr = strbuf;
- while (*chptr && *chptr != '.') chptr++;
- *chptr = '\0';
+ i = 0;
+ while (octet != NULL) {
+ octets[i] = octet;
+ i++;
+ octet = strtok(NULL, ".");
+ }
- if (chptr - strbuf > 3) return NULL;
- splits[i] = strbuf;
- strbuf = chptr + 1;
- }
+ if (i == 4) {
+ if (asprintf(&ipnum, "%s.%s.%s.%s.in-addr.arpa", octets[3],
+ octets[2], octets[1], octets[0]) == -1)
+ return NULL;
+ } else {
+ return NULL;
+ }
+
+ free(buf);
+ buf = NULL;
+ } else if (family == AF_INET6) {
+ if (!inet_pton(AF_INET6, ipnum, &addr6))
+ return NULL;
+
+ i = 7;
+ while (i >= 0) {
+ sprintf(sbuf, "%4x", ntohs(addr6.s6_addr16[i]));
+ sbuf[4] = '\0';
+
+ if ((parts[i] = malloc(8)) == NULL)
+ return NULL;
- sprintf(ipnum, "%s.%s.%s.%s.in-addr.arpa", splits[3], splits[2],
- splits[1], splits[0]);
+ partptr = parts[i];
- rc = doQuery(ipnum, T_PTR, &result, NULL);
- if (rc)
- rc = doQuery(ipnum, T_PTR, &result, NULL);
+ for (j = 3; j >= 0; j--) {
+ if (sbuf[j] == ' ')
+ *partptr = '0';
+ else
+ *partptr = sbuf[j];
+
+ partptr++;
+
+ if (j != 0) {
+ *partptr = '.';
+ partptr++;
+ }
+ }
- if (rc)
+ i--;
+ }
+
+ if (asprintf(&ipnum, "%s.%s.%s.%s.%s.%s.%s.%s.ip6.arpa", parts[7],
+ parts[6], parts[5], parts[4], parts[3], parts[2],
+ parts[1], parts[0]) == -1)
+ return NULL;
+
+ for (j = 0; j < 8; j++) {
+ free(parts[j]);
+ parts[j] = NULL;
+ }
+ }
+
+ ret = doQuery(ipnum, T_PTR, &result, NULL, family);
+ if (ret)
+ ret = doQuery(ipnum, T_PTR, &result, NULL, family);
+
+ if (ret)
return NULL;
else
return result;
}
-int mygethostbyname(char * name, struct in_addr * addr) {
- return doQuery(name, T_A, NULL, addr);
+int mygethostbyname(char * name, void * addr, int family) {
+ int type;
+
+ if (family == AF_INET)
+ type = T_A;
+ else if (family == AF_INET6)
+ type = T_AAAA;
+ else
+ type = -1;
+
+ return doQuery(name, type, NULL, addr, family);
}
#if 0
int main(int argc, char **argv) {
- struct in_addr address;
- fprintf(stderr, "hostname for %s is %s\n", "152.1.2.22",
- mygethostbyaddr("152.1.2.22"));
- if (mygethostbyname("www.redhat.com", &address) == 0) {
- fprintf(stderr, "ip for www.redhat.com is %d.%d.%d.%d\n",
- (address.s_addr >> 0) & 0xff, (address.s_addr >> 8) & 0xff,
- (address.s_addr >> 16) & 0xff, (address.s_addr >> 24) & 0xff);
+ struct in_addr addr;
+ struct in6_addr addr6;
+ char *ret = NULL;
+
+ /* IPv4 tests */
+ printf("hostname for %s is %s\n", "152.1.2.22",
+ mygethostbyaddr("152.1.2.22", AF_INET));
+ if (mygethostbyname("www.redhat.com", &addr, AF_INET) == 0) {
+ ret = malloc(48);
+ inet_ntop(AF_INET, &addr, ret, INET_ADDRSTRLEN);
+ printf("ip for www.redhat.com is %s\n", ret);
+ free(ret);
+ ret = NULL;
}
+
+ /* IPv6 tests */
+ printf("hostname for %s is %s\n", "fec0:acdc:1::1",
+ mygethostbyaddr("fec0:acdc:1::1", AF_INET6));
+ if (mygethostbyname("cutlet.ipv6.install.boston.redhat.com", &addr6, AF_INET6) == 0) {
+ ret = malloc(48);
+ inet_ntop(AF_INET6, &addr6, ret, INET6_ADDRSTRLEN);
+ printf("ip for cutlet.ipv6.install.boston.redhat.com is %s\n", ret);
+ free(ret);
+ ret = NULL;
+ }
+
return 0;
}
#endif
diff --git a/isys/dns.h b/isys/dns.h
index 45bcb38bf..71321c276 100644
--- a/isys/dns.h
+++ b/isys/dns.h
@@ -3,7 +3,7 @@
#include <netinet/in.h>
-int mygethostbyname(char * name, struct in_addr * addr);
-char * mygethostbyaddr(char * ipnum);
+int mygethostbyname(char * name, void * addr, int family);
+char * mygethostbyaddr(char * ipnum, int family);
#endif
diff --git a/isys/nfsmount.c b/isys/nfsmount.c
index 53353434a..21ad20d7c 100644
--- a/isys/nfsmount.c
+++ b/isys/nfsmount.c
@@ -310,7 +310,7 @@ int nfsmount(const char *spec, const char *node, int *flags,
if (!inet_aton(hostname, &server_addr.sin_addr))
#endif
{
- if (mygethostbyname(hostname, &server_addr.sin_addr)) {
+ if (mygethostbyname(hostname, &server_addr.sin_addr, AF_INET)) {
myerror = ERROR_HOSTNAME;
goto fail;
} else {
@@ -548,7 +548,7 @@ int nfsmount(const char *spec, const char *node, int *flags,
mount_server_addr.sin_family = AF_INET;
mount_server_addr.sin_addr.s_addr = inet_addr(hostname);
} else {
- if (mygethostbyname(hostname, &mount_server_addr.sin_addr)) {
+ if (mygethostbyname(hostname, &mount_server_addr.sin_addr, AF_INET)) {
myerror = ERROR_HOSTNAME;
goto fail;
} else {