From 8f6ad301913dc5ddfda7823510c17b8ce61df51c Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Mon, 9 Jul 2001 21:20:20 +0000 Subject: A patch from Michal Moskal to include partial IPV6 support. This adds things like gethostbyname2(). Off by defaut, of course, --- Makefile | 5 ++ extra/Configs/Config.arm | 4 + extra/Configs/Config.cross.arm.uclinux | 4 + extra/Configs/Config.i386 | 4 + extra/Configs/Config.m68k | 4 + extra/Configs/Config.m68k.coff | 4 + extra/Configs/Config.mips | 4 + extra/Configs/Config.mipsel | 4 + extra/Configs/Config.powerpc | 4 + extra/Configs/Config.sh | 4 + include/netdb.h | 1 + libc/inet/Makefile | 4 +- libc/inet/ntop.c | 8 ++ libc/inet/resolv.c | 142 +++++++++++++++++++++++++++++++++ 14 files changed, 194 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 96f1d88a1..98ab12ede 100644 --- a/Makefile +++ b/Makefile @@ -98,6 +98,11 @@ uClibc_config.h: Makefile Config @echo "#endif" >> uClibc_config.h @echo "#define linux 1" >> uClibc_config.h @echo "#define __linux__ 1" >> uClibc_config.h + @if [ "$(INCLUDE_IPV6)" = "true" ] ; then \ + echo "#define __UCLIBC_HAS_IPV6__ 1" >> uClibc_config.h ; \ + else \ + echo "#undef __UCLIBC_HAS_IPV6__" >> uClibc_config.h ; \ + fi @if [ "$(HAS_MMU)" = "true" ] ; then \ echo "#define __UCLIBC_HAS_MMU__ 1" >> uClibc_config.h ; \ else \ diff --git a/extra/Configs/Config.arm b/extra/Configs/Config.arm index 21c66bcb6..408a23f60 100644 --- a/extra/Configs/Config.arm +++ b/extra/Configs/Config.arm @@ -132,6 +132,10 @@ DOLFS = false # disabled. This is off by default. INCLUDE_RPC = false +# If you want to include support for the next version of the Internet +# Protocol: IP version 6, enable this. This is off by default. +INCLUDE_IPV6 = false + # If you want to compile the library as PIC code, turn this on. DOPIC = false diff --git a/extra/Configs/Config.cross.arm.uclinux b/extra/Configs/Config.cross.arm.uclinux index 9f34e83af..f61a8d2dd 100644 --- a/extra/Configs/Config.cross.arm.uclinux +++ b/extra/Configs/Config.cross.arm.uclinux @@ -132,6 +132,10 @@ DOLFS = false # disabled. This is off by default. INCLUDE_RPC = false +# If you want to include support for the next version of the Internet +# Protocol: IP version 6, enable this. This is off by default. +INCLUDE_IPV6 = false + # If you want to compile the library as PIC code, turn this on. DOPIC = false diff --git a/extra/Configs/Config.i386 b/extra/Configs/Config.i386 index 1876d05a0..b383ebda8 100644 --- a/extra/Configs/Config.i386 +++ b/extra/Configs/Config.i386 @@ -132,6 +132,10 @@ DOLFS = false # disabled. This is off by default. INCLUDE_RPC = false +# If you want to include support for the next version of the Internet +# Protocol: IP version 6, enable this. This is off by default. +INCLUDE_IPV6 = false + # If you want to compile the library as PIC code, turn this on. DOPIC = false diff --git a/extra/Configs/Config.m68k b/extra/Configs/Config.m68k index becad56f4..dc6e107dc 100644 --- a/extra/Configs/Config.m68k +++ b/extra/Configs/Config.m68k @@ -132,6 +132,10 @@ DOLFS = false # disabled. This is off by default. INCLUDE_RPC = true +# If you want to include support for the next version of the Internet +# Protocol: IP version 6, enable this. This is off by default. +INCLUDE_IPV6 = false + # If you want to compile the library as PIC code, turn this on. DOPIC = false diff --git a/extra/Configs/Config.m68k.coff b/extra/Configs/Config.m68k.coff index e70220a98..c0bbd3f77 100644 --- a/extra/Configs/Config.m68k.coff +++ b/extra/Configs/Config.m68k.coff @@ -132,6 +132,10 @@ DOLFS = false # disabled. This is off by default. INCLUDE_RPC = true +# If you want to include support for the next version of the Internet +# Protocol: IP version 6, enable this. This is off by default. +INCLUDE_IPV6 = false + # If you want to compile the library as PIC code, turn this on. DOPIC = false diff --git a/extra/Configs/Config.mips b/extra/Configs/Config.mips index 30778e848..163a9aa4e 100644 --- a/extra/Configs/Config.mips +++ b/extra/Configs/Config.mips @@ -132,6 +132,10 @@ DOLFS = false # disabled. This is off by default. INCLUDE_RPC = false +# If you want to include support for the next version of the Internet +# Protocol: IP version 6, enable this. This is off by default. +INCLUDE_IPV6 = false + # If you want to compile the library as PIC code, turn this on. DOPIC = false diff --git a/extra/Configs/Config.mipsel b/extra/Configs/Config.mipsel index 30778e848..163a9aa4e 100644 --- a/extra/Configs/Config.mipsel +++ b/extra/Configs/Config.mipsel @@ -132,6 +132,10 @@ DOLFS = false # disabled. This is off by default. INCLUDE_RPC = false +# If you want to include support for the next version of the Internet +# Protocol: IP version 6, enable this. This is off by default. +INCLUDE_IPV6 = false + # If you want to compile the library as PIC code, turn this on. DOPIC = false diff --git a/extra/Configs/Config.powerpc b/extra/Configs/Config.powerpc index 836b1dfcf..659231db9 100644 --- a/extra/Configs/Config.powerpc +++ b/extra/Configs/Config.powerpc @@ -132,6 +132,10 @@ DOLFS = false # disabled. This is off by default. INCLUDE_RPC = false +# If you want to include support for the next version of the Internet +# Protocol: IP version 6, enable this. This is off by default. +INCLUDE_IPV6 = false + # If you want to compile the library as PIC code, turn this on. DOPIC = false diff --git a/extra/Configs/Config.sh b/extra/Configs/Config.sh index 39736b4cf..9012530c2 100644 --- a/extra/Configs/Config.sh +++ b/extra/Configs/Config.sh @@ -153,6 +153,10 @@ DOLFS = false # disabled. This is off by default. INCLUDE_RPC = false +# If you want to include support for the next version of the Internet +# Protocol: IP version 6, enable this. This is off by default. +INCLUDE_IPV6 = false + # If you want to compile the library as PIC code, turn this on. DOPIC = false diff --git a/include/netdb.h b/include/netdb.h index 888b87ded..96358bd85 100644 --- a/include/netdb.h +++ b/include/netdb.h @@ -153,6 +153,7 @@ void endservent __P((void)); void endrpcent __P ((void)); struct hostent *gethostbyaddr __P((__const char *, int, int)); struct hostent *gethostbyname __P((__const char *)); +struct hostent *gethostbyname2 __P((__const char *, int)); struct hostent *gethostent __P((void)); struct netent *getnetbyaddr __P((long, int)); /* u_long? */ struct netent *getnetbyname __P((__const char *)); diff --git a/libc/inet/Makefile b/libc/inet/Makefile index e6ffff694..6fd75010d 100644 --- a/libc/inet/Makefile +++ b/libc/inet/Makefile @@ -39,8 +39,8 @@ MOBJ2=encodeh.o decodeh.o encoded.o decoded.o lengthd.o encodeq.o \ formquery.o dnslookup.o resolveaddress.o resolvemailbox.o \ opennameservers.o closenameservers.o resolvename.o gethostbyname.o\ res_init.o res_query.o gethostbyaddr.o \ - get_hosts_byname.o get_hosts_byaddr.o read_etc_hosts.o - + get_hosts_byname.o get_hosts_byaddr.o read_etc_hosts.o \ + gethostbyname2.o MSRC3=socketcalls.c MOBJ3= accept.o bind.o connect.o getpeername.o getsockname.o getsockopt.o \ diff --git a/libc/inet/ntop.c b/libc/inet/ntop.c index 6d7e691cc..521c1de63 100644 --- a/libc/inet/ntop.c +++ b/libc/inet/ntop.c @@ -29,6 +29,13 @@ #include #include +#ifdef __UCLIBC_HAS_IPV6__ +#define INET_IPV6 +#define SPRINTF(a) sprintf a +#include +#endif + + /* * WARNING: Don't even consider trying to compile this on a system where * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. @@ -259,6 +266,7 @@ inet_pton6(src, dst) int ch, saw_xdigit; u_int val; + tp = memset(tmp, '\0', 16); endp = tp + 16; colonp = NULL; 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 + * 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; -- cgit v1.2.3