X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=lib%2Finet6.c;h=9a484a01fd394b47f6d4de1906c06fbe7fe07d38;hb=d114ba0f293ba448ead9682d0fe25e37d395702b;hp=c5e058fddcce3bc0bebbd6069295d89681506609;hpb=8e304247055c6ca2e5b2b30ce09ded3644dc89c7;p=platform%2Fupstream%2Fnet-tools.git diff --git a/lib/inet6.c b/lib/inet6.c index c5e058f..9a484a0 100644 --- a/lib/inet6.c +++ b/lib/inet6.c @@ -3,7 +3,7 @@ * support functions for the net-tools. * (most of it copied from lib/inet.c 1.26). * - * Version: $Id: inet6.c,v 1.5 1998/11/17 15:16:49 freitag Exp $ + * Version: $Id: inet6.c,v 1.12 2002/12/10 01:03:09 ecki Exp $ * * Author: Fred N. van Kempen, * Copyright 1993 MicroWalt Corporation @@ -11,6 +11,7 @@ * Modified: *960808 {0.01} Frank Strauss : adapted for IPv6 support *980701 {0.02} Arnaldo C. Melo: GNU gettext instead of catgets + *990824 Bernd Eckenfels: clear members for selecting v6 address * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General @@ -39,17 +40,34 @@ #include "net-support.h" #include "pathnames.h" #include "intl.h" +#include "util.h" extern int h_errno; /* some netdb.h versions don't export this */ +char * fix_v4_address(char *buf, struct in6_addr *in6) +{ + if (IN6_IS_ADDR_V4MAPPED(in6->s6_addr)) { + char *s =strchr(buf, '.'); + if (s) { + while (s > buf && *s != ':') + --s; + if (*s == ':') ++s; + else s = NULL; + } + if (s) return s; + } + return buf; +} + static int INET6_resolve(char *name, struct sockaddr_in6 *sin6) { struct addrinfo req, *ai; int s; + memset (&req, '\0', sizeof req); req.ai_family = AF_INET6; if ((s = getaddrinfo(name, NULL, &req, &ai))) { - fprintf(stderr, "getaddrinfo: %s: %s\n", name, gai_strerror(s)); + fprintf(stderr, "getaddrinfo: %s: %d\n", name, s); return -1; } memcpy(sin6, ai->ai_addr, sizeof(struct sockaddr_in6)); @@ -59,6 +77,12 @@ static int INET6_resolve(char *name, struct sockaddr_in6 *sin6) return (0); } +#ifndef IN6_IS_ADDR_UNSPECIFIED +#define IN6_IS_ADDR_UNSPECIFIED(a) \ + (((__u32 *) (a))[0] == 0 && ((__u32 *) (a))[1] == 0 && \ + ((__u32 *) (a))[2] == 0 && ((__u32 *) (a))[3] == 0) +#endif + static int INET6_rresolve(char *name, struct sockaddr_in6 *sin6, int numeric) { @@ -74,12 +98,20 @@ static int INET6_rresolve(char *name, struct sockaddr_in6 *sin6, int numeric) return (-1); } if (numeric & 0x7FFF) { - inet_ntop(AF_INET6, &sin6->sin6_addr, name, 80); + inet_ntop( AF_INET6, &sin6->sin6_addr, name, 80); + return (0); + } + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { + if (numeric & 0x8000) + strcpy(name, "default"); + else + strcpy(name, "[::]"); return (0); } + if ((s = getnameinfo((struct sockaddr *) sin6, sizeof(struct sockaddr_in6), name, 255 /* !! */ , NULL, 0, 0))) { - fprintf(stderr, "getnameinfo: %s\n", gai_strerror(s)); + fputs("getnameinfo failed\n", stderr); return -1; } return (0); @@ -92,13 +124,14 @@ static void INET6_reserror(char *text) } + /* Display an Internet socket address. */ static char *INET6_print(unsigned char *ptr) { static char name[80]; inet_ntop(AF_INET6, (struct in6_addr *) ptr, name, 80); - return name; + return fix_v4_address(name, (struct in6_addr *)ptr); } @@ -111,14 +144,15 @@ static char *INET6_sprint(struct sockaddr *sap, int numeric) if (sap->sa_family == 0xFFFF || sap->sa_family == 0) return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff)); if (INET6_rresolve(buff, (struct sockaddr_in6 *) sap, numeric) != 0) - return (NULL); - return (buff); + return safe_strncpy(buff, _("[UNKNOWN]"), sizeof(buff)); + return (fix_v4_address(buff, &((struct sockaddr_in6 *)sap)->sin6_addr)); } static int INET6_getsock(char *bufp, struct sockaddr *sap) { struct sockaddr_in6 *sin6; + char *p; sin6 = (struct sockaddr_in6 *) sap; sin6->sin6_family = AF_INET6; @@ -126,7 +160,9 @@ static int INET6_getsock(char *bufp, struct sockaddr *sap) if (inet_pton(AF_INET6, bufp, sin6->sin6_addr.s6_addr) <= 0) return (-1); - + p = fix_v4_address(bufp, &sin6->sin6_addr); + if (p != bufp) + memcpy(bufp, p, strlen(p)+1); return 16; /* ?;) */ }