[xinetd] IPv6 redirect patch

Cougar cougar at random.ee
Sun Mar 16 01:25:27 PST 2003


Hi,

I found one logical error in redirect.c. I my case I tried to make
IPv6->IPv4 proxy. In config file I had such lines:

service proxy
{
        port            = 8000
        bind            = 2001:ad0::
        socket_type     = stream
        protocol        = tcp
        redirect        = 10.0.0.1 8000
[----]

Now when I connect to 2001:ad0:: port 8000, xinetd should connect to IPv4
address. Here is what it actually does:

accept(6, {sin_family=AF_INET6, sin6_port=htons(38638), inet_pton(AF_INET6, "2001:ad0:ff:6::2", &sin6_addr), sin6_flowinfo=htonl(0)}}, [28]) = 8
[----]
[pid  6809] socket(PF_INET6, SOCK_STREAM, 0) = 9
[pid  6809] connect(9, {sin_family=AF_INET, sin_port=htons(8000), sin_addr=inet_addr("10.0.0.1")}}, 28) = -1 EAFNOSUPPORT (Address family not supported by protocol)

In redirect.c, xinetd creates socket with the same protocol which it
listened:

      if( SC_IPV4(scp) ) {
         sin_len = sizeof( struct sockaddr_in );
         RedirServerFd = socket(AF_INET, SOCK_STREAM, 0);
      } else if( SC_IPV6(scp) ) {
         sin_len = sizeof( struct sockaddr_in6 );
         RedirServerFd = socket(AF_INET6, SOCK_STREAM, 0);

The right proto is what getaddrinfo() gives for destination address. So,
the right code should be:

      if( serveraddr.sa_in.sin_family == AF_INET ) {
         sin_len = sizeof( struct sockaddr_in );
         RedirServerFd = socket(AF_INET, SOCK_STREAM, 0);
      } else if( serveraddr.sa_in.sin_family == AF_INET6 ) {
         sin_len = sizeof( struct sockaddr_in6 );
         RedirServerFd = socket(AF_INET6, SOCK_STREAM, 0);

This way it can redirect IPv6 sockets to both IPv4 and IPv6 addresses. t
works also with IPv4 sockets without any problem. I tested all four
situations.

I attached path to this mail. There are two places in redirect.c which
should be changed.

---
Cougar
-------------- next part --------------
--- xinetd-2.3.10.orig/xinetd/redirect.c	Mon Sep  9 22:40:52 2002
+++ xinetd-2.3.10/xinetd/redirect.c	Sun Mar 16 10:57:35 2003
@@ -72,10 +72,11 @@
    if( scp->sc_protocol.value == IPPROTO_TCP )
    {
       char *foo = NULL;
+      memcpy(&serveraddr, scp->sc_redir_addr, sizeof(serveraddr));
-      if( SC_IPV4(scp) ) {
+      if( serveraddr.sa_in.sin_family == AF_INET ) {
          sin_len = sizeof( struct sockaddr_in );
          RedirServerFd = socket(AF_INET, SOCK_STREAM, 0);
-      } else if( SC_IPV6(scp) ) {
+      } else if( serveraddr.sa_in.sin_family == AF_INET6 ) {
          sin_len = sizeof( struct sockaddr_in6 );
          RedirServerFd = socket(AF_INET6, SOCK_STREAM, 0);
       } else {
@@ -95,10 +96,9 @@
             msg(LOG_ERR, func, 
                 "setsockopt SO_KEEPALIVE RedirServerFd failed: %m");
       
-      memcpy(&serveraddr, scp->sc_redir_addr, sizeof(serveraddr));
-      if( SC_IPV4(scp) )
+      if( serveraddr.sa_in.sin_family == AF_INET )
          serveraddr.sa_in.sin_port = htons(serveraddr.sa_in.sin_port);
-      if( SC_IPV6(scp) )
+      if( serveraddr.sa_in.sin_family == AF_INET6 )
          serveraddr.sa_in6.sin6_port = htons(serveraddr.sa_in6.sin6_port);
 
       if( connect(RedirServerFd, &serveraddr.sa, sin_len) < 0 )


More information about the Xinetd mailing list