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