Hello, I am suggesting to split off the IPv6-patch for "src/tftpd.c", as it now is self-contained, apart from the elementary change to "libinetutils/tftpsubs.c".
The previous thread "[patches 1,2,3] Making tftp/tftpd IPv6-capable." is hereby declared closed, and its code is declared dead. Well, it does return in a refined form! The present patch for "src/tftpd.c" has been verified on Debian Squeeze and OpenBSD 4.6. For the testing I have used the IPv6-capable netkit-ftp client in Debian, for which I am myself responsible for the implementation. I am not at all certain that my formulation of the changelog entry fulfill all your requirements, so do regard also that as a valid reason for patch rejection, besides any further nit picking in the C-code itself. The corresponding changes to "src/tftp.c" will have to avait a few days more until I finalize the details. A client is always more delicate than an inetd-supported server code. Best regards as always, Mats E A ------------------------------------------------------- From cd51b27c2638581d8d790c38c7d82044ee265bb1 Mon Sep 17 00:00:00 2001 From: Mats Erik Andersson <g...@gisladisker.se> Date: Sun, 12 Sep 2010 02:13:21 +0200 Subject: [PATCH] Implement IPv6 capability for the TFTP server. --- ChangeLog | 9 +++++++++ libinetutils/tftpsubs.c | 2 +- src/tftpd.c | 45 ++++++++++++++++++++++++++++----------------- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7f3efb3..9cdbaaa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-09-12 Mats Erik Andersson <g...@gisladisker.se> + + * libinetutils/tftpsubs.c (synchnet): Upgrade the variable "from" + to be "struct sockaddr_storage". + * src/tftpd.c: Upgrade all "sockaddr_in" to "sockaddr_storage". + Accurate use of "fromlen" to track length of address structure. + (tftp): Let logging display "IPv4", "IPv6, or "?". + (verifyhost): New signature. Uses getnameinfo() as resolver. + 2010-09-09 Mats Erik Andersson <g...@gisladisker.se> * src/tftp.c (peeraddr, f, trace, verbose, rexmtval) diff --git a/libinetutils/tftpsubs.c b/libinetutils/tftpsubs.c index bc1f84a..6fa78bc 100644 --- a/libinetutils/tftpsubs.c +++ b/libinetutils/tftpsubs.c @@ -285,7 +285,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 70602fa..355fc0e 100644 --- a/src/tftpd.c +++ b/src/tftpd.c @@ -101,7 +101,7 @@ 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; void tftp (struct tftphdr *, int); @@ -124,7 +124,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 *, socklen_t); @@ -172,7 +172,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); @@ -268,24 +268,29 @@ main (int argc, char *argv[]) exit (EXIT_SUCCESS); } } - from.sin_family = AF_INET; + alarm (0); close (0); close (1); - peer = socket (AF_INET, SOCK_DGRAM, 0); + + /* The peer's address 'from' is valid at this point. + * 'from.ss_family' contains the correct address + * family for any callback connection, and 'fromlen' + * is the length of the corresponding address structure. */ + peer = socket (from.ss_family, SOCK_DGRAM, 0); if (peer < 0) { syslog (LOG_ERR, "socket: %m\n"); exit (EXIT_FAILURE); } 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, fromlen) < 0) { syslog (LOG_ERR, "bind: %m\n"); exit (EXIT_FAILURE); } - if (connect (peer, (struct sockaddr *) &from, sizeof (from)) < 0) + if (connect (peer, (struct sockaddr *) &from, fromlen) < 0) { syslog (LOG_ERR, "connect: %m\n"); exit (EXIT_FAILURE); @@ -360,8 +365,10 @@ again: ecode = (*pf->f_validate) (&filename, tp->th_opcode); if (logging) { - syslog (LOG_INFO, "%s: %s request for %s: %s", - verifyhost (&from), + syslog (LOG_INFO, "%s (%s): %s request for %s: %s", + verifyhost (&from, fromlen), + from.ss_family == AF_INET ? "IPv4" + : (from.ss_family == AF_INET6 ? "IPv6" : "?"), tp->th_opcode == WRQ ? "write" : "read", filename, errtomsg (ecode)); } @@ -737,16 +744,20 @@ nak (int error) } static const char * -verifyhost (struct sockaddr_in *fromp) +verifyhost (struct sockaddr_storage *fromp, socklen_t frlen) { - struct hostent *hp; + int rc; + static char host[NI_MAXHOST]; - hp = gethostbyaddr ((char *) &fromp->sin_addr, sizeof (fromp->sin_addr), - fromp->sin_family); - if (hp) - return hp->h_name; + rc = getnameinfo ((struct sockaddr *) fromp, frlen, + host, sizeof (host), NULL, 0, 0); + 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[] = -- 1.7.0
signature.asc
Description: Digital signature