diff options
author | Eric Andersen <andersen@codepoet.org> | 2001-07-09 21:20:20 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2001-07-09 21:20:20 +0000 |
commit | 8f6ad301913dc5ddfda7823510c17b8ce61df51c (patch) | |
tree | 5aa3f54536fdc7b42c9ae15836fb5c2a01f31cd2 /libc/inet/resolv.c | |
parent | 8df26e4f7bba3fb0f4c84df7c166fd5d5e09cf7b (diff) |
A patch from Michal Moskal <malekith@pld.org.pl> to include
partial IPV6 support. This adds things like gethostbyname2().
Off by defaut, of course,
Diffstat (limited to 'libc/inet/resolv.c')
-rw-r--r-- | libc/inet/resolv.c | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index 00b7a7634..034bb80db 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -32,6 +32,10 @@ * * General cleanup * + * 20-Jun-2001 Michal Moskal <malekith@pld.org.pl> + * partial IPv6 support (i.e. gethostbyname2() and resolve_address2() + * functions added), IPv6 nameservers are also supported. + * */ #define __FORCE_GLIBC__ @@ -59,6 +63,8 @@ #define MAX_SEARCH 4 #undef DEBUG +/*#define DEBUG*/ + #ifdef DEBUG #define DPRINTF(X,args...) fprintf(stderr, X, ##args) #else @@ -465,6 +471,9 @@ int dns_lookup(const char *name, int type, int nscount, char **nsip, int i, j, len, fd, pos; static int ns = 0; struct sockaddr_in sa; +#ifdef __UCLIBC_HAS_IPV6__ + struct sockaddr_in6 sa6; +#endif /* __UCLIBC_HAS_IPV6__ */ int oldalarm; __sighandler_t oldhandler; struct resolv_header h; @@ -473,6 +482,9 @@ int dns_lookup(const char *name, int type, int nscount, char **nsip, unsigned char * packet = malloc(PACKETSZ); unsigned char * lookup = malloc(MAXDNAME); int variant = 0; +#ifdef __UCLIBC_HAS_IPV6__ + int v6; +#endif /* __UCLIBC_HAS_IPV6__ */ fd = -1; @@ -484,11 +496,18 @@ int dns_lookup(const char *name, int type, int nscount, char **nsip, ns %= nscount; while (retries++ < MAX_RETRIES) { +#ifdef __UCLIBC_HAS_IPV6__ + v6 = (inet_pton(AF_INET6, nsip[ns], &sa6.sin6_addr) > 0); +#endif /* __UCLIBC_HAS_IPV6__ */ if (fd != -1) close(fd); +#ifndef __UCLIBC_HAS_IPV6__ fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); +#else /* __UCLIBC_HAS_IPV6__ */ + fd = socket(v6 ? AF_INET6 : AF_INET, SOCK_DGRAM, IPPROTO_UDP); +#endif /* __UCLIBC_HAS_IPV6__ */ if (fd == -1) goto fail; @@ -526,11 +545,28 @@ int dns_lookup(const char *name, int type, int nscount, char **nsip, DPRINTF("On try %d, sending query to port %d of machine %s\n", retries, NAMESERVER_PORT, nsip[ns]); +#ifndef __UCLIBC_HAS_IPV6__ sa.sin_family = AF_INET; sa.sin_port = htons(NAMESERVER_PORT); sa.sin_addr.s_addr = inet_addr(nsip[ns]); +#else /* __UCLIBC_HAS_IPV6__ */ + if (v6) { + sa6.sin6_family = AF_INET6; + sa6.sin6_port = htons(NAMESERVER_PORT); + /* sa6.sin6_addr is already here */ + } else { + sa.sin_family = AF_INET; + sa.sin_port = htons(NAMESERVER_PORT); + sa.sin_addr.s_addr = inet_addr(nsip[ns]); + } +#endif /* __UCLIBC_HAS_IPV6__ */ +#ifndef __UCLIBC_HAS_IPV6__ if (connect(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) { +#else /* __UCLIBC_HAS_IPV6__ */ + if (connect(fd, (struct sockaddr *) (v6 ? &sa6 : &sa), + v6 ? sizeof(sa6) : sizeof(sa)) == -1) { +#endif /* __UCLIBC_HAS_IPV6__ */ if (errno == ENETUNREACH) { /* routing error, presume not transient */ goto tryall; @@ -958,6 +994,92 @@ struct hostent *gethostbyname(const char *name) } #endif +#ifdef L_gethostbyname2 + +struct hostent *gethostbyname2(const char *name, int family) +{ +#ifndef __UCLIBC_HAS_IPV6__ + return family == AF_INET ? gethostbyname(name) : (struct hostent*)0; +#else /* __UCLIBC_HAS_IPV6__ */ + static struct hostent h; + static char namebuf[256]; + static struct in6_addr in; + static struct in6_addr *addr_list[2]; + struct hostent *hp; + unsigned char *packet; + struct resolv_answer a; + int i; + int nest = 0; + + if (family == AF_INET) + return gethostbyname(name); + + if (family != AF_INET6) + return NULL; + + open_nameservers(); + + 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; + + strncpy(namebuf, name, sizeof(namebuf)); + + /* First check if this is already an address */ + if (inet_pton(AF_INET6, name, &in)) { + h.h_name = namebuf; + h.h_addrtype = AF_INET6; + h.h_length = sizeof(in); + h.h_addr_list = (char **) addr_list; + return &h; + } + + for (;;) { + + i = dns_lookup(namebuf, T_AAAA, nameservers, nameserver, &packet, &a); + + if (i < 0) + return 0; + + strncpy(namebuf, a.dotted, sizeof(namebuf)); + free(a.dotted); + + + if (a.atype == T_CNAME) { /* CNAME */ + DPRINTF("Got a CNAME in gethostbyname()\n"); + i = decode_dotted(packet, a.rdoffset, namebuf, sizeof(namebuf)); + free(packet); + + if (i < 0) + return 0; + if (++nest > MAX_RECURSE) + return 0; + continue; + } else if (a.atype == T_AAAA) { /* ADDRESS */ + memcpy(&in, a.rdata, sizeof(in)); + h.h_name = namebuf; + h.h_addrtype = AF_INET6; + h.h_length = sizeof(in); + h.h_addr_list = (char **) addr_list; + free(packet); + break; + } else { + free(packet); + return 0; + } + } + + return &h; +#endif /* __UCLIBC_HAS_IPV6__ */ +} +#endif #ifdef L_getnetbyname @@ -1100,6 +1222,10 @@ 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]; +#ifdef __UCLIBC_HAS_IPV6__ + static struct in6_addr in6; + static struct in6_addr *addr_list6[2]; +#endif /* __UCLIBC_HAS_IPV6__ */ static char line[80]; FILE *fp; char *cp; @@ -1142,8 +1268,24 @@ struct hostent * read_etc_hosts(const char * name, int ip) continue; } +#ifndef __UCLIBC_HAS_IPV6__ if (inet_aton(alias[0], &in) == 0) break; /* bad ip address */ +#else /* __UCLIBC_HAS_IPV6__ */ + if (inet_aton(alias[0], &in) == 0) { + if (inet_pton(AF_INET6, alias[0], &in6) == 0) { + addr_list6[0] = &in6; + addr_list6[1] = 0; + h.h_name = alias[1]; + h.h_addrtype = AF_INET6; + h.h_length = sizeof(in6); + h.h_addr_list = (char**) addr_list6; + fclose(fp); + return(&h); + } else + break; /* bad ip address */ + } +#endif /* __UCLIBC_HAS_IPV6__ */ addr_list[0] = ∈ addr_list[1] = 0; |