summaryrefslogtreecommitdiff
path: root/os/access.c
diff options
context:
space:
mode:
Diffstat (limited to 'os/access.c')
-rw-r--r--os/access.c325
1 files changed, 284 insertions, 41 deletions
diff --git a/os/access.c b/os/access.c
index f12c5c081..77dcebe20 100644
--- a/os/access.c
+++ b/os/access.c
@@ -45,13 +45,14 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
******************************************************************/
-/* $XFree86: xc/programs/Xserver/os/access.c,v 3.42 2002/07/07 20:11:52 herrb Exp $ */
+/* $XFree86: xc/programs/Xserver/os/access.c,v 3.50 2003/11/03 05:12:00 tsi Exp $ */
#ifdef WIN32
#include <X11/Xwinsock.h>
#endif
#include <stdio.h>
+#include <stdlib.h>
#include <X11/Xtrans.h>
#include <X11/Xauth.h>
#include <X.h>
@@ -142,6 +143,19 @@ SOFTWARE.
#include <ifaddrs.h>
#endif
+/* Solaris provides an extended interface SIOCGLIFCONF. Other systems
+ * may have this as well, but the code has only been tested on Solaris
+ * so far, so we only enable it there. Other platforms may be added as
+ * needed.
+ *
+ * Test for Solaris commented out -- TSI @ UQV 2003.06.13
+ */
+#ifdef SIOCGLIFCONF
+/* #if defined(sun) */
+#define USE_SIOCGLIFCONF
+/* #endif */
+#endif
+
#endif /* WIN32 */
#ifndef PATH_MAX
@@ -170,6 +184,14 @@ SOFTWARE.
#include "extensions/security.h"
#endif
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+
Bool defeatAccessControl = FALSE;
#define acmp(a1, a2, len) memcmp((char *)(a1), (char *)(a2), len)
@@ -189,23 +211,35 @@ static int CheckAddr(int /*family*/,
static Bool NewHost(int /*family*/,
pointer /*addr*/,
- int /*len*/);
+ int /*len*/,
+ int /* addingLocalHosts */);
+
+/* XFree86 bug #156: To keep track of which hosts were explicitly requested in
+ /etc/X<display>.hosts, we've added a requested field to the HOST struct,
+ and a LocalHostRequested variable. These default to FALSE, but are set
+ to TRUE in ResetHosts when reading in /etc/X<display>.hosts. They are
+ checked in DisableLocalHost(), which is called to disable the default
+ local host entries when stronger authentication is turned on. */
typedef struct _host {
short family;
short len;
unsigned char *addr;
struct _host *next;
+ int requested;
} HOST;
#define MakeHost(h,l) (h)=(HOST *) xalloc(sizeof *(h)+(l));\
- if((h))\
- (h)->addr=(unsigned char *) ((h) + 1);
+ if (h) { \
+ (h)->addr=(unsigned char *) ((h) + 1);\
+ (h)->requested = FALSE; \
+ }
#define FreeHost(h) xfree(h)
static HOST *selfhosts = NULL;
static HOST *validhosts = NULL;
static int AccessEnabled = DEFAULT_ACCESS_CONTROL;
static int LocalHostEnabled = FALSE;
+static int LocalHostRequested = FALSE;
static int UsingXdmcp = FALSE;
@@ -232,9 +266,12 @@ DisableLocalHost (void)
{
HOST *self;
- LocalHostEnabled = FALSE;
- for (self = selfhosts; self; self = self->next)
+ if (!LocalHostRequested) /* Fix for XFree86 bug #156 */
+ LocalHostEnabled = FALSE;
+ for (self = selfhosts; self; self = self->next) {
+ if (!self->requested) /* Fix for XFree86 bug #156 */
(void) RemoveHost ((ClientPtr)NULL, self->family, self->len, (pointer)self->addr);
+ }
}
/*
@@ -250,7 +287,7 @@ AccessUsingXdmcp (void)
}
-#if ((defined(SVR4) && !defined(DGUX) && !defined(SCO325) && !defined(sun) && !defined(NCR)) || defined(ISC)) && defined(SIOCGIFCONF)
+#if ((defined(SVR4) && !defined(DGUX) && !defined(SCO325) && !defined(sun) && !defined(NCR)) || defined(ISC)) && defined(SIOCGIFCONF) && !defined(USE_SIOCGLIFCONF)
/* Deal with different SIOCGIFCONF ioctl semantics on these OSs */
@@ -465,9 +502,13 @@ DefineSelf (int fd)
union {
struct sockaddr sa;
struct sockaddr_in in;
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_in6 in6;
+#endif
} saddr;
struct sockaddr_in *inetaddr;
+ struct sockaddr_in6 *inet6addr;
struct sockaddr_in broad_addr;
#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
_Xgethostbynameparams hparams;
@@ -492,9 +533,22 @@ DefineSelf (int fd)
if (hp != NULL)
{
saddr.sa.sa_family = hp->h_addrtype;
- inetaddr = (struct sockaddr_in *) (&(saddr.sa));
- acopy ( hp->h_addr, &(inetaddr->sin_addr), hp->h_length);
- len = sizeof(saddr.sa);
+ switch (hp->h_addrtype) {
+ case AF_INET:
+ inetaddr = (struct sockaddr_in *) (&(saddr.sa));
+ acopy ( hp->h_addr, &(inetaddr->sin_addr), hp->h_length);
+ len = sizeof(saddr.sa);
+ break;
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6:
+ inet6addr = (struct sockaddr_in6 *) (&(saddr.sa));
+ acopy ( hp->h_addr, &(inet6addr->sin6_addr), hp->h_length);
+ len = sizeof(saddr.in6);
+ break;
+#endif
+ default:
+ goto DefineLocalHost;
+ }
family = ConvertAddr ( &(saddr.sa), &len, (pointer *)&addr);
if ( family != -1 && family != FamilyLocal )
{
@@ -530,6 +584,14 @@ DefineSelf (int fd)
XdmcpRegisterBroadcastAddress ((struct sockaddr_in *)
&broad_addr);
}
+#if defined(IPv6) && defined(AF_INET6)
+ else if (family == FamilyInternet6 &&
+ !(IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr)))
+ {
+ XdmcpRegisterConnection (family, (char *)addr, len);
+ }
+#endif
+
#endif /* XDMCP */
}
}
@@ -537,6 +599,7 @@ DefineSelf (int fd)
/*
* now add a host of family FamilyLocalHost...
*/
+DefineLocalHost:
for (host = selfhosts;
host && !addrEqual(FamilyLocalHost, "", 0, host);
host = host->next);
@@ -557,6 +620,12 @@ DefineSelf (int fd)
#else
+#ifdef USE_SIOCGLIFCONF
+#define ifr_type struct lifreq
+#else
+#define ifr_type struct ifreq
+#endif
+
#ifdef VARIABLE_IFREQ
#define ifr_size(p) (sizeof (struct ifreq) + \
(p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \
@@ -567,7 +636,7 @@ DefineSelf (int fd)
#define ifr_size(p) (p->ifr_addr.sa_len + IFNAMSIZ)
#define ifraddr_size(a) (a.sa_len)
#else
-#define ifr_size(p) (sizeof (struct ifreq))
+#define ifr_size(p) (sizeof (ifr_type))
#define ifraddr_size(a) (sizeof (a))
#endif
#endif
@@ -581,8 +650,17 @@ DefineSelf (int fd)
{
#ifndef HAS_GETIFADDRS
char buf[2048], *cp, *cplim;
+ void * bufptr = buf;
+#ifdef USE_SIOCGLIFCONF
+ struct lifconf ifc;
+ register struct lifreq *ifr;
+#ifdef SIOCGLIFNUM
+ struct lifnum ifn;
+#endif
+#else
struct ifconf ifc;
register struct ifreq *ifr;
+#endif
#else
struct ifaddrs * ifap, *ifr;
#endif
@@ -621,37 +699,80 @@ DefineSelf (int fd)
}
#endif /* DNETCONN */
#ifndef HAS_GETIFADDRS
- ifc.ifc_len = sizeof (buf);
- ifc.ifc_buf = buf;
- if (ifioctl (fd, SIOCGIFCONF, (pointer) &ifc) < 0)
- Error ("Getting interface configuration (4)");
+ len = sizeof(buf);
+
+#ifdef USE_SIOCGLIFCONF
+
+#ifdef SIOCGLIFNUM
+ ifn.lifn_family = AF_UNSPEC;
+ ifn.lifn_flags = 0;
+ if (ioctl (fd, SIOCGLIFNUM, (char *) &ifn) < 0)
+ Error ("Getting interface count");
+ if (len < (ifn.lifn_count * sizeof(struct lifreq))) {
+ len = ifn.lifn_count * sizeof(struct lifreq);
+ bufptr = xalloc(len);
+ }
+#endif
+
+ ifc.lifc_family = AF_UNSPEC;
+ ifc.lifc_flags = 0;
+ ifc.lifc_len = len;
+ ifc.lifc_buf = bufptr;
+
+#define IFC_IOCTL_REQ SIOCGLIFCONF
+#define IFC_IFC_REQ ifc.lifc_req
+#define IFC_IFC_LEN ifc.lifc_len
+#define IFR_IFR_ADDR ifr->lifr_addr
+#define IFR_IFR_NAME ifr->lifr_name
+
+#else /* Use SIOCGIFCONF */
+ ifc.ifc_len = len;
+ ifc.ifc_buf = bufptr;
+
+#define IFC_IOCTL_REQ SIOCGIFCONF
#ifdef ISC
#define IFC_IFC_REQ (struct ifreq *) ifc.ifc_buf
#else
#define IFC_IFC_REQ ifc.ifc_req
#endif /* ISC */
+#define IFC_IFC_LEN ifc.ifc_len
+#define IFR_IFR_ADDR ifr->ifr_addr
+#define IFR_IFR_NAME ifr->ifr_name
+#endif
+
+ if (ifioctl (fd, IFC_IOCTL_REQ, (pointer) &ifc) < 0)
+ Error ("Getting interface configuration (4)");
- cplim = (char *) IFC_IFC_REQ + ifc.ifc_len;
+ cplim = (char *) IFC_IFC_REQ + IFC_IFC_LEN;
for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size (ifr))
{
- ifr = (struct ifreq *) cp;
- len = ifraddr_size (ifr->ifr_addr);
+ ifr = (ifr_type *) cp;
+ len = ifraddr_size (IFR_IFR_ADDR);
+ family = ConvertAddr ((struct sockaddr *) &IFR_IFR_ADDR,
+ &len, (pointer *)&addr);
#ifdef DNETCONN
/*
* DECnet was handled up above.
*/
- if (ifr->ifr_addr.sa_family == AF_DECnet)
+ if (family == AF_DECnet)
continue;
#endif /* DNETCONN */
- family = ConvertAddr (&ifr->ifr_addr, &len, (pointer *)&addr);
if (family == -1 || family == FamilyLocal)
continue;
#ifdef DEF_SELF_DEBUG
if (family == FamilyInternet)
ErrorF("Xserver: DefineSelf(): ifname = %s, addr = %d.%d.%d.%d\n",
- ifr->ifr_name, addr[0], addr[1], addr[2], addr[3]);
+ IFR_IFR_NAME, addr[0], addr[1], addr[2], addr[3]);
+#if defined(IPv6) && defined(AF_INET6)
+ else if (family == FamilyInternet6) {
+ char cp[INET6_ADDRSTRLEN] = "";
+ inet_ntop(AF_INET6, addr, cp, sizeof(cp));
+ ErrorF("Xserver: DefineSelf(): ifname = %s, addr = %s\n",
+ IFR_IFR_NAME, cp);
+ }
+#endif
#endif /* DEF_SELF_DEBUG */
for (host = selfhosts;
host && !addrEqual (family, addr, len, host);
@@ -670,39 +791,80 @@ DefineSelf (int fd)
}
#ifdef XDMCP
{
+#ifdef USE_SIOCGLIFCONF
+ struct sockaddr_storage broad_addr;
+#else
struct sockaddr broad_addr;
+#endif
/*
* If this isn't an Internet Address, don't register it.
*/
- if (family != FamilyInternet)
+ if (family != FamilyInternet
+#if defined(IPv6) && defined(AF_INET6)
+ && family != FamilyInternet6
+#endif
+ )
continue;
/*
* ignore 'localhost' entries as they're not useful
* on the other end of the wire
*/
- if (len == 4 &&
+ if (family == FamilyInternet &&
addr[0] == 127 && addr[1] == 0 &&
addr[2] == 0 && addr[3] == 1)
continue;
+#if defined(IPv6) && defined(AF_INET6)
+ else if (family == FamilyInternet6 &&
+ IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))
+ continue;
+#endif
XdmcpRegisterConnection (family, (char *)addr, len);
- broad_addr = ifr->ifr_addr;
+
+#if defined(IPv6) && defined(AF_INET6)
+ /* IPv6 doesn't support broadcasting, so we drop out here */
+ if (family == FamilyInternet6)
+ continue;
+#endif
+
+ broad_addr = IFR_IFR_ADDR;
+
((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
htonl (INADDR_BROADCAST);
-#ifdef SIOCGIFBRDADDR
+#if defined(USE_SIOCGLIFCONF) && defined(SIOCGLIFBRDADDR)
+ {
+ struct lifreq broad_req;
+
+ broad_req = *ifr;
+ if (ioctl (fd, SIOCGLIFFLAGS, (char *) &broad_req) != -1 &&
+ (broad_req.lifr_flags & IFF_BROADCAST) &&
+ (broad_req.lifr_flags & IFF_UP)
+ )
+ {
+ broad_req = *ifr;
+ if (ioctl (fd, SIOCGLIFBRDADDR, &broad_req) != -1)
+ broad_addr = broad_req.lifr_broadaddr;
+ else
+ continue;
+ }
+ else
+ continue;
+ }
+
+#elif defined(SIOCGIFBRDADDR)
{
struct ifreq broad_req;
broad_req = *ifr;
- if (ifioctl (fd, SIOCGIFFLAGS, (char *) &broad_req) != -1 &&
+ if (ifioctl (fd, SIOCGIFFLAGS, (pointer) &broad_req) != -1 &&
(broad_req.ifr_flags & IFF_BROADCAST) &&
(broad_req.ifr_flags & IFF_UP)
)
{
broad_req = *ifr;
- if (ifioctl (fd, SIOCGIFBRDADDR, &broad_req) != -1)
+ if (ifioctl (fd, SIOCGIFBRDADDR, (pointer) &broad_req) != -1)
broad_addr = broad_req.ifr_addr;
else
continue;
@@ -713,13 +875,15 @@ DefineSelf (int fd)
#endif /* SIOCGIFBRDADDR */
#ifdef DEF_SELF_DEBUG
ErrorF("Xserver: DefineSelf(): ifname = %s, baddr = %s\n",
- ifr->ifr_name,
+ IFR_IFR_NAME,
inet_ntoa(((struct sockaddr_in *) &broad_addr)->sin_addr));
#endif /* DEF_SELF_DEBUG */
XdmcpRegisterBroadcastAddress ((struct sockaddr_in *) &broad_addr);
}
#endif /* XDMCP */
}
+ if (bufptr != buf)
+ free(bufptr);
#else /* HAS_GETIFADDRS */
if (getifaddrs(&ifap) < 0) {
ErrorF("Warning: getifaddrs returns %s\n", strerror(errno));
@@ -730,6 +894,7 @@ DefineSelf (int fd)
if (ifr->ifa_addr.sa_family == AF_DECnet)
continue;
#endif /* DNETCONN */
+ len = sizeof(*(ifr->ifa_addr));
family = ConvertAddr(ifr->ifa_addr, &len, (pointer *)&addr);
if (family == -1 || family == FamilyLocal)
continue;
@@ -843,7 +1008,11 @@ AddLocalHosts (void)
HOST *self;
for (self = selfhosts; self; self = self->next)
- (void) NewHost (self->family, self->addr, self->len);
+ /* Fix for XFree86 bug #156: pass addingLocal = TRUE to
+ * NewHost to tell that we are adding the default local
+ * host entries and not to flag the entries as being
+ * explicitely requested */
+ (void) NewHost (self->family, self->addr, self->len, TRUE);
}
/* Reset access control list to initial hosts */
@@ -858,15 +1027,18 @@ ResetHosts (char *display)
FILE *fd;
char *ptr;
int i, hostlen;
+#if ((defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)) && \
+ (!defined(IPv6) || !defined(AF_INET6))) || defined(DNETCONN)
union {
struct sockaddr sa;
#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
- struct sockaddr_in in;
+ struct sockaddr_in in;
#endif /* TCPCONN || STREAMSCONN */
#ifdef DNETCONN
- struct sockaddr_dn dn;
+ struct sockaddr_dn dn;
+#endif
+ } saddr;
#endif
- } saddr;
#ifdef DNETCONN
struct nodeent *np;
struct dn_naddr dnaddr, *dnaddrp, *dnet_addr();
@@ -878,7 +1050,6 @@ ResetHosts (char *display)
int family = 0;
pointer addr;
int len;
- register struct hostent *hp;
AccessEnabled = defeatAccessControl ? FALSE : DEFAULT_ACCESS_CONTROL;
LocalHostEnabled = FALSE;
@@ -902,6 +1073,7 @@ ResetHosts (char *display)
{
while (fgets (ohostname, sizeof (ohostname), fd))
{
+ family = FamilyWild;
if (*ohostname == '#')
continue;
if ((ptr = strchr(ohostname, '\n')) != 0)
@@ -917,7 +1089,8 @@ ResetHosts (char *display)
if (!strncmp("local:", lhostname, 6))
{
family = FamilyLocalHost;
- NewHost(family, "", 0);
+ NewHost(family, "", 0, FALSE);
+ LocalHostRequested = TRUE; /* Fix for XFree86 bug #156 */
}
#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
else if (!strncmp("inet:", lhostname, 5))
@@ -925,6 +1098,13 @@ ResetHosts (char *display)
family = FamilyInternet;
hostname = ohostname + 5;
}
+#if defined(IPv6) && defined(AF_INET6)
+ else if (!strncmp("inet6:", lhostname, 6))
+ {
+ family = FamilyInternet6;
+ hostname = ohostname + 6;
+ }
+#endif
#endif
#ifdef DNETCONN
else if (!strncmp("dnet:", lhostname, 5))
@@ -969,7 +1149,7 @@ ResetHosts (char *display)
}
if (dnaddrp)
(void) NewHost(FamilyDECnet, (pointer)dnaddrp,
- (int)(dnaddrp->a_len + sizeof(dnaddrp->a_len)));
+ (int)(dnaddrp->a_len + sizeof(dnaddrp->a_len)), FALSE);
}
else
#endif /* DNETCONN */
@@ -978,7 +1158,7 @@ ResetHosts (char *display)
{
krb5_parse_name(hostname, &princ);
XauKrb5Encode(princ, &kbuf);
- (void) NewHost(FamilyKrb5Principal, kbuf.data, kbuf.length);
+ (void) NewHost(FamilyKrb5Principal, kbuf.data, kbuf.length, FALSE);
krb5_free_principal(princ);
}
else
@@ -987,15 +1167,37 @@ ResetHosts (char *display)
if ((family == FamilyNetname) || (strchr(hostname, '@')))
{
SecureRPCInit ();
- (void) NewHost (FamilyNetname, hostname, strlen (hostname));
+ (void) NewHost (FamilyNetname, hostname, strlen (hostname), FALSE);
}
else
#endif /* SECURE_RPC */
#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
{
+#if defined(IPv6) && defined(AF_INET6)
+ if ( (family == FamilyInternet) || (family == FamilyInternet6) ||
+ (family == FamilyWild) )
+ {
+ struct addrinfo *addresses;
+ struct addrinfo *a;
+ int f;
+
+ if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
+ for (a = addresses ; a != NULL ; a = a->ai_next) {
+ len = a->ai_addrlen;
+ f = ConvertAddr(a->ai_addr,&len,(pointer *)&addr);
+ if ( (family == f) ||
+ ((family == FamilyWild) && (f != -1)) ) {
+ NewHost(f, addr, len, FALSE);
+ }
+ }
+ freeaddrinfo(addresses);
+ }
+ }
+#else
#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
_Xgethostbynameparams hparams;
#endif
+ register struct hostent *hp;
/* host name */
if ((family == FamilyInternet &&
@@ -1011,12 +1213,13 @@ ResetHosts (char *display)
/* iterate over the addresses */
for (list = hp->h_addr_list; *list; list++)
- (void) NewHost (family, (pointer)*list, len);
+ (void) NewHost (family, (pointer)*list, len, FALSE);
#else
- (void) NewHost (family, (pointer)hp->h_addr, len);
+ (void) NewHost (family, (pointer)hp->h_addr, len, FALSE);
#endif
}
}
+#endif /* IPv6 */
}
#endif /* TCPCONN || STREAMSCONN */
family = FamilyWild;
@@ -1080,6 +1283,7 @@ Bool LocalClient(ClientPtr client)
int
LocalClientCred(ClientPtr client, int *pUid, int *pGid)
{
+#if defined(HAS_GETPEEREID) || defined(SO_PEERCRED)
int fd;
XtransConnInfo ci;
#ifdef HAS_GETPEEREID
@@ -1114,6 +1318,7 @@ LocalClientCred(ClientPtr client, int *pUid, int *pGid)
if (pGid != NULL)
*pGid = peercred.gid;
return 0;
+#endif
#else
/* No system call available to get the credentials of the peer */
return -1;
@@ -1158,6 +1363,9 @@ AddHost (ClientPtr client,
break;
#endif
case FamilyInternet:
+#if defined(IPv6) && defined(AF_INET6)
+ case FamilyInternet6:
+#endif
case FamilyDECnet:
case FamilyChaos:
if ((len = CheckAddr (family, pAddr, length)) < 0)
@@ -1171,7 +1379,7 @@ AddHost (ClientPtr client,
client->errorValue = family;
return (BadValue);
}
- if (NewHost (family, pAddr, len))
+ if (NewHost (family, pAddr, len, FALSE))
return Success;
return BadAlloc;
}
@@ -1197,7 +1405,8 @@ ForEachHostInFamily (int family,
static Bool
NewHost (int family,
pointer addr,
- int len)
+ int len,
+ int addingLocalHosts)
{
register HOST *host;
@@ -1206,6 +1415,14 @@ NewHost (int family,
if (addrEqual (family, addr, len, host))
return TRUE;
}
+ if (!addingLocalHosts) { /* Fix for XFree86 bug #156 */
+ for (host = selfhosts; host; host = host->next) {
+ if (addrEqual (family, addr, len, host)) {
+ host->requested = TRUE;
+ break;
+ }
+ }
+ }
MakeHost(host,len)
if (!host)
return FALSE;
@@ -1247,6 +1464,9 @@ RemoveHost (
break;
#endif
case FamilyInternet:
+#if defined(IPv6) && defined(AF_INET6)
+ case FamilyInternet6:
+#endif
case FamilyDECnet:
case FamilyChaos:
if ((len = CheckAddr (family, pAddr, length)) < 0)
@@ -1336,6 +1556,14 @@ CheckAddr (
else
len = -1;
break;
+#if defined(IPv6) && defined(AF_INET6)
+ case FamilyInternet6:
+ if (length == sizeof (struct in6_addr))
+ len = length;
+ else
+ len = -1;
+ break;
+#endif
#endif
#ifdef DNETCONN
case FamilyDECnet:
@@ -1424,6 +1652,21 @@ ConvertAddr (
*len = sizeof (struct in_addr);
*addr = (pointer) &(((struct sockaddr_in *) saddr)->sin_addr);
return FamilyInternet;
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) saddr;
+ if (IN6_IS_ADDR_V4MAPPED(&(saddr6->sin6_addr))) {
+ *len = sizeof (struct in_addr);
+ *addr = (pointer) &(saddr6->sin6_addr.s6_addr[12]);
+ return FamilyInternet;
+ } else {
+ *len = sizeof (struct in6_addr);
+ *addr = (pointer) &(saddr6->sin6_addr);
+ return FamilyInternet6;
+ }
+ }
+#endif
#endif
#ifdef DNETCONN
case AF_DECnet: