Hello all,

a quick look reveals that 'tftpd' is hard coded for IPv4.
The following patch amends this and provides full IPv6
capability for the server 'tftpd'. The client side will
follow in a few days time.


Best regards,

Mats Erik Andersson, fil. dr

2459 41E9 C420 3F6D F68B  2E88 F768 4541 F25B 5D41
Description: Incorporate IPv6 support in 'tftpd'.
 Migrating to 'struct sockaddr_storage' and replacement
 of gethostbyaddr(3) by getnameinfo(3) accomplish full
 support for IPv6, granted that 'inetd' can handle IPv6
 on its own.
Author: Mats Erik Andersson <[email protected]>
X-Signed-off-by: Mats Erik Andersson
Last-Update: 2010-07-29
diff --git a/libinetutils/tftpsubs.c b/libinetutils/tftpsubs.c
index 6eb0a09..371764b 100644
--- a/libinetutils/tftpsubs.c
+++ b/libinetutils/tftpsubs.c
@@ -287,7 +287,7 @@ synchnet (int f)
 {
   int i, j = 0;
   char rbuf[PKTSIZE];
-  struct sockaddr_in from;
+  struct sockaddr_storage from;
   socklen_t fromlen;
 
   while (1)
diff --git a/src/tftpd.c b/src/tftpd.c
index f343f8a..a086131 100644
--- a/src/tftpd.c
+++ b/src/tftpd.c
@@ -103,8 +103,9 @@ static int maxtimeout = 5 * TIMEOUT;
 #define PKTSIZE	SEGSIZE+4
 static char buf[PKTSIZE];
 static char ackbuf[PKTSIZE];
-static struct sockaddr_in from;
+static struct sockaddr_storage from;
 static socklen_t fromlen;
+static char host[NI_MAXHOST];
 
 void tftp (struct tftphdr *, int);
 
@@ -126,9 +127,7 @@ static int logging;
 
 static const char *errtomsg (int);
 static void nak (int);
-static const char *verifyhost (struct sockaddr_in *);
-
-
+static const char *verifyhost (struct sockaddr_storage *);
 
 static struct argp_option options[] = {
   { "logging", 'l', NULL, 0,
@@ -174,7 +173,7 @@ main (int argc, char *argv[])
   int index;
   register struct tftphdr *tp;
   int on, n;
-  struct sockaddr_in sin;
+  struct sockaddr_storage sin;
 
   set_program_name (argv[0]);
   iu_argp_init ("tftpd", default_program_authors);
@@ -270,18 +269,20 @@ main (int argc, char *argv[])
 	exit (0);
       }
   }
-  from.sin_family = AF_INET;
+  /* The peer's address 'from' is valid at this point,
+   * and 'from.ss_family' contains the correct address
+   * family for any callback connection. */
   alarm (0);
   close (0);
   close (1);
-  peer = socket (AF_INET, SOCK_DGRAM, 0);
+  peer = socket (from.ss_family, SOCK_DGRAM, 0);
   if (peer < 0)
     {
       syslog (LOG_ERR, "socket: %m\n");
       exit (1);
     }
   memset (&sin, 0, sizeof (sin));
-  sin.sin_family = AF_INET;
+  sin.ss_family = from.ss_family;
   if (bind (peer, (struct sockaddr *) &sin, sizeof (sin)) < 0)
     {
       syslog (LOG_ERR, "bind: %m\n");
@@ -739,16 +740,18 @@ nak (int error)
 }
 
 static const char *
-verifyhost (struct sockaddr_in *fromp)
+verifyhost (struct sockaddr_storage *fromp)
 {
-  struct hostent *hp;
+  int rc;
 
-  hp = gethostbyaddr ((char *) &fromp->sin_addr, sizeof (fromp->sin_addr),
-		      fromp->sin_family);
-  if (hp)
-    return hp->h_name;
+  if ( (rc = getnameinfo ((struct sockaddr *) fromp, sizeof (*fromp),
+			  host, sizeof (host), NULL, 0, 0)) == 0)
+    return host;
   else
-    return inet_ntoa (fromp->sin_addr);
+    {
+      syslog (LOG_ERR, "getnameinfo: %s\n", gai_strerror(rc));
+      return "0.0.0.0";
+    }
 }
 
 static const char usage_str[] =

Attachment: signature.asc
Description: Digital signature

Reply via email to