Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[vdr] Re: Feature request: AF independence for vdr.



On Mon, 5 Apr 2004 18:52:18 +0200
DOm <angelus.dei@tiscalinet.it> wrote:

> Hallo,
> 
> i'm studying a little IPv6 and i'll try to port vdr to IPv6 adopting
> an AF (Address family) independent approach as suggested in
> http://www.kame.net/newsletter/19980604/
> any chance to have some help ? I'm not a great programmer :)
> 
> Have a good time,
>    Angelus.
> 

Well, i tried to code a patch to have AF independence and here we are.
I think such an independence could be always a good idea... even if you
hate IPv6 :) I stealed the code from:
http://jungla.dit.upm.es/~ecastro/IPv6-web/ipv6.html and
http://www.ietf.org/internet-drafts/draft-shin-v6ops-application-transition-02.txt

By the way, the patch is highly EXPERIMENTAL, it can break something,
but since i have a dual stack IPv6-IPv4 machine i would like to have
comments _and_ critics by someone with IPv4 only machine (most of you).

The Acceptable Addresses feature (svdrphosts.conf) is disabled in this
patch because i don't know how to parse IPv6 addresses in the correct
way, yet. That is: connections will be accepted from ANY host, sorry.

Many thanks for you tests,
   Angelus.
diff -pruN vdr-1.3.6-vanilla/runvdr vdr-1.3.6-AFind/runvdr
--- vdr-1.3.6-vanilla/runvdr	2004-01-09 17:19:26.000000000 +0100
+++ vdr-1.3.6-AFind/runvdr	2004-04-06 17:20:05.000000000 +0200
@@ -24,7 +24,7 @@ DVBDIR="../DVB/driver"
 VDRPRG="./vdr"
 VDRCMD="$VDRPRG -w 60 $*"
 
-LSMOD="`/sbin/lsmod | grep -w '^dvb' | wc -l`"
+LSMOD="`/sbin/lsmod | grep ^dvb | wc -l`"
 KILL="/usr/bin/killall -q -TERM"
 
 # Load driver if it hasn't been loaded already:
diff -pruN vdr-1.3.6-vanilla/svdrp.c vdr-1.3.6-AFind/svdrp.c
--- vdr-1.3.6-vanilla/svdrp.c	2004-02-24 13:24:43.000000000 +0100
+++ vdr-1.3.6-AFind/svdrp.c	2004-04-06 18:12:57.000000000 +0200
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
+#include <netdb.h>
 #include <sys/time.h>
 #include <unistd.h>
 #include "channels.h"
@@ -61,42 +62,78 @@ void cSocket::Close(void)
 bool cSocket::Open(void)
 {
   if (sock < 0) {
-     // create socket:
-     sock = socket(PF_INET, SOCK_STREAM, 0);
+     struct addrinfo hints, *res, *ressave;
+     int error;
+
+     memset(&hints, 0, sizeof(hints));
+
+     /*
+       AI_PASSIVE flag: the resulting address is used to bind
+       to a socket for accepting incoming connections.
+       So, when the hostname==NULL, getaddrinfo function will
+       return one entry per allowed protocol family containing
+       the unspecified address for that family.
+     */
+     hints.ai_flags = AI_PASSIVE;
+     hints.ai_family = AF_UNSPEC;
+     hints.ai_socktype = SOCK_STREAM;
+ 
+     // 5 = strlen("65535") the highest possible port number
+     char service[5];
+     snprintf(service, 5, "%d", port);
+     error = getaddrinfo(NULL, service, &hints, &res);
+     if (error != 0) {
+       // handle getaddrinfo error
+       esyslog("Error in getaddrinfo.");
+        return false;
+     }
+
+     ressave=res;
+
+    /*
+       Try open socket with each address getaddrinfo returned,
+       until getting a valid listening socket.
+    */
+     while (res) {
+           // create socket:
+           sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+           if (!(sock < 0)) {
+              // allow it to always reuse the same port:
+              int ReUseAddr = 1;
+              setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &ReUseAddr, sizeof(ReUseAddr));
+              // make it non-blocking:
+              int oldflags = fcntl(sock, F_GETFL, 0);
+              if (oldflags < 0) {
+                LOG_ERROR;
+                return false;
+                }
+              oldflags |= O_NONBLOCK;
+              if (fcntl(sock, F_SETFL, oldflags) < 0) {
+                LOG_ERROR;
+                return false;
+                }
+              if (bind(sock, res->ai_addr, res->ai_addrlen) == 0)
+                break;
+
+              LOG_ERROR;
+              close(sock);
+              sock=-1;
+            }
+        res = res->ai_next;
+      }
      if (sock < 0) {
         LOG_ERROR;
         port = 0;
+        freeaddrinfo(ressave);
         return false;
-        }
-     // allow it to always reuse the same port:
-     int ReUseAddr = 1;
-     setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &ReUseAddr, sizeof(ReUseAddr));
-     //
-     struct sockaddr_in name;
-     name.sin_family = AF_INET;
-     name.sin_port = htons(port);
-     name.sin_addr.s_addr = htonl(INADDR_ANY);
-     if (bind(sock, (struct sockaddr *)&name, sizeof(name)) < 0) {
-        LOG_ERROR;
-        Close();
-        return false;
-        }
-     // make it non-blocking:
-     int oldflags = fcntl(sock, F_GETFL, 0);
-     if (oldflags < 0) {
-        LOG_ERROR;
-        return false;
-        }
-     oldflags |= O_NONBLOCK;
-     if (fcntl(sock, F_SETFL, oldflags) < 0) {
-        LOG_ERROR;
-        return false;
-        }
+      }
+     
      // listen to the socket:
      if (listen(sock, queue) < 0) {
         LOG_ERROR;
         return false;
         }
+     freeaddrinfo(ressave);
      }
   return true;
 }
@@ -104,18 +141,28 @@ bool cSocket::Open(void)
 int cSocket::Accept(void)
 {
   if (Open()) {
-     struct sockaddr_in clientname;
-     uint size = sizeof(clientname);
-     int newsock = accept(sock, (struct sockaddr *)&clientname, &size);
+     struct sockaddr_storage clientname;
+     socklen_t addrlen = sizeof(clientname);
+     int newsock = accept(sock, (struct sockaddr *)&clientname, &addrlen);
      if (newsock > 0) {
-        bool accepted = SVDRPhosts.Acceptable(clientname.sin_addr.s_addr);
+        //bool accepted = SVDRPhosts.Acceptable(clientname.sin_addr.s_addr);
+        bool accepted = true;
         if (!accepted) {
            const char *s = "Access denied!\n";
            write(newsock, s, strlen(s));
            close(newsock);
            newsock = -1;
            }
-        isyslog("connect from %s, port %hd - %s", inet_ntoa(clientname.sin_addr), ntohs(clientname.sin_port), accepted ? "accepted" : "DENIED");
+        
+        char clienthost[NI_MAXHOST];
+        char clientservice[NI_MAXSERV];
+        memset(clienthost, 0, sizeof(clienthost));
+        memset(clientservice, 0, sizeof(clientservice));
+        getnameinfo((struct sockaddr *)&clientname, addrlen,
+                    clienthost, sizeof(clienthost),
+                    clientservice, sizeof(clientservice),
+                    NI_NUMERICHOST);
+        isyslog("connect from %s, port %s - %s", clienthost, clientservice, accepted ? "accepted" : "DENIED");
         }
      else if (errno != EINTR && errno != EAGAIN)
         LOG_ERROR;

Home | Main Index | Thread Index