summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Bartoschek <bartoschek@or.uni-bonn.de>2009-11-30 13:34:30 +0100
committerAdam Jackson <ajax@redhat.com>2009-11-30 11:59:27 -0500
commit989d892443b9d6e52313bf6f4a8606f8749e218d (patch)
tree11a5e0e9db4124b25815258c3b1bd0c8c197844e
parentbad944beb34a988a12a9e18a2f4c42dc59a916a5 (diff)
XDM: Add support for clients that sent ipv4 addresses to a dual-stacked host
If a client sends an ipv4 address to a dual-stacked xdm that is bound to a ipv6 socket in a forward request, then the packet was silently discarded. Now the address is encapsulated as a ipv4-mapped address and a response is send back. Signed-off-by: Adam Jackson <ajax@redhat.com>
-rw-r--r--xdmcp.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/xdmcp.c b/xdmcp.c
index 7c91d1e..66a5e0f 100644
--- a/xdmcp.c
+++ b/xdmcp.c
@@ -791,8 +791,8 @@ forward_respond (
{
struct sockaddr_in6 in6_addr;
- if (clientAddress.length != 16 ||
- clientPort.length != 2)
+ if ((clientAddress.length != 16 && clientAddress.length != 4) ||
+ (clientPort.length != 2))
{
goto badAddress;
}
@@ -801,7 +801,24 @@ forward_respond (
in6_addr.sin6_len = sizeof(in6_addr);
# endif
in6_addr.sin6_family = AF_INET6;
- memmove(&in6_addr.sin6_addr,clientAddress.data,clientAddress.length);
+ if (clientAddress.length == 16) {
+ memmove(in6_addr.sin6_addr.s6_addr, clientAddress.data, 16);
+ } else {
+ /* If the client wants to forward the xdm server to an
+ ipv4 hosts it sends an ipv4 address in the forward
+ packet. On dual-stack hosts the packet arrives as a
+ ipv6 packet. To respond to the ipv4 host one has
+ to create an ipv4-mapped address of the form
+
+ ::ffff::xxx.xxx.xxx.xxx
+
+ One example where this is necessary is an ipv4-only
+ thin client that connects to a dual-stacked xdm.
+ */
+ in6_addr.sin6_addr.s6_addr[10] = 0xff;
+ in6_addr.sin6_addr.s6_addr[11] = 0xff;
+ memmove(in6_addr.sin6_addr.s6_addr + 12, clientAddress.data, 4);
+ }
memmove((char *) &in6_addr.sin6_port, clientPort.data, 2);
client = (struct sockaddr *) &in6_addr;
clientlen = sizeof (in6_addr);