diff --git a/ChangeLog b/ChangeLog
index af7429b..cbd3db2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2010-08-19 Mats Erik Andersson
+ * src/tftpd.c: Implement full support for IPv6.
+
+2010-08-19 Mats Erik Andersson
+
* libinetutils/sockaddr_aux.h: New file.
* libinetutils/sockaddr_aux.c: New file.
* libinetutils/Makefile.am: Add sockaddr_aux.h and sockaddr_aux.c.
diff --git a/src/tftpd.c b/src/tftpd.c
index f343f8a..892c709 100644
--- a/src/tftpd.c
+++ b/src/tftpd.c
@@ -83,6 +83,7 @@
#include
#include "tftpsubs.h"
+#include "sockaddr_aux.h"
#include
#include
@@ -103,8 +104,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[INET6_ADDRSTRLEN];
void tftp (struct tftphdr *, int);
@@ -126,7 +128,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 *);
@@ -174,7 +176,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,24 +272,28 @@ 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;
- if (bind (peer, (struct sockaddr *) &sin, sizeof (sin)) < 0)
+ sin.ss_family = from.ss_family;
+ if (bind (peer, (struct sockaddr *) &sin,
+ get_socklen ((struct sockaddr *) &sin)) < 0)
{
syslog (LOG_ERR, "bind: %m\n");
exit (1);
}
- if (connect (peer, (struct sockaddr *) &from, sizeof (from)) < 0)
+ if (connect (peer, (struct sockaddr *) &from,
+ get_socklen ((struct sockaddr *) &from)) < 0)
{
syslog (LOG_ERR, "connect: %m\n");
exit (1);
@@ -739,16 +745,20 @@ 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;
+ rc = getnameinfo ((struct sockaddr *) fromp,
+ get_socklen ((struct sockaddr *) fromp),
+ host, sizeof (host), NULL, 0, NI_NUMERICHOST);
+ if (rc == 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[] =