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 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[] =