* support functions for the net-tools.
* (most of it copied from lib/inet.c 1.26).
*
- * Version: $Id: inet6.c,v 1.4 1998/11/15 20:10:37 freitag Exp $
+ * Version: $Id: inet6.c,v 1.12 2002/12/10 01:03:09 ecki Exp $
*
* Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
* Copyright 1993 MicroWalt Corporation
* 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
#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));
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)
{
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);
}
+
/* 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);
}
static char buff[128];
if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
- return strncpy(buff, _("[NONE SET]"), sizeof(buff));
+ 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;
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; /* ?;) */
}